diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..760c670 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,32 @@ +# Changelog + +## v4.8.5 — Security hardening release + +This release consolidates several months of security, privacy, and lifecycle hardening work by the SecureBit.chat team. + +### Security + +- Added mandatory interactive SAS verification; passive click-through confirmation is no longer sufficient. +- Made SAS computation deterministic across peers using shared session material. +- Enforced protocol version `4.1` mismatch handling for incompatible clients. +- Added TURN relay-only privacy mode and explicit warnings when TURN is unavailable. +- Encrypted sensitive IndexedDB metadata and added safe lazy migration for legacy plaintext records. +- Added mandatory consent gating for every incoming file transfer. +- Replaced broad file acceptance with an explicit file-type allowlist and spoofing checks. +- Sanitized every incoming decrypted chat message before UI delivery. + +### Reliability and resource lifecycle + +- Consolidated disconnect behavior into one canonical cleanup path. +- Added cleanup for tracked timers, deferred retries, peer-disconnect scheduling, and fake/decoy traffic. +- Rejected pending sender consent promises immediately during cleanup. +- Bounded retained received-file buffers and added graceful handling for expired download handles. +- Cleared React file-transfer UI state and detached live callbacks on unmount. +- Improved reconnect hygiene and stale-session cleanup behavior. + +### Maintenance + +- Pinned dependency versions. +- Applied safe transitive patch/minor updates. +- Verified a clean `npm audit` result. +- Expanded regression coverage for SAS, file consent, sanitization, privacy mode, metadata encryption, cleanup, and callback lifecycle behavior. diff --git a/README.md b/README.md index dda0640..d52650d 100644 --- a/README.md +++ b/README.md @@ -1,590 +1,121 @@ -# SecureBit.chat v4.7.56 +# SecureBit.chat v4.8.5 -
+SecureBit.chat is a browser-based peer-to-peer chat application built on WebRTC and Web Crypto APIs. It is designed for direct encrypted communication, explicit peer verification, and a small operational footprint without account registration or server-side message storage. -![SecureBit.chat Logo](logo/favicon.ico) +## Security model -**World's first P2P messenger with ECDH + DTLS + SAS security and military-grade cryptography** +SecureBit.chat uses: -[![Latest Release](https://img.shields.io/github/v/release/SecureBitChat/securebit-chat?style=for-the-badge&logo=github&color=orange)](https://github.com/SecureBitChat/securebit-chat/releases/latest) -[![Live Demo](https://img.shields.io/badge/🌐_Live_Demo-Try_Now-success?style=for-the-badge)](https://securebit.chat/) -[![Desktop Apps](https://img.shields.io/badge/🖥️_Desktop_Apps-Available-blue?style=for-the-badge)](https://github.com/SecureBitChat/securebit-desktop) -[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg?style=for-the-badge)](https://opensource.org/licenses/MIT) +- ECDH key agreement with derived session keys +- DTLS-protected WebRTC transport +- deterministic Short Authentication String (SAS) verification +- end-to-end encrypted chat payloads +- replay protection and session-state cleanup +- encrypted local key metadata in IndexedDB -[Try Web Version](https://securebit.chat/) • [🖥️ Download Desktop Apps](https://github.com/SecureBitChat/securebit-desktop) • [📖 Documentation](#-quick-start) • [🔒 Security](#-security) +A session is not treated as verified until both peers complete the interactive SAS flow. Each user must compare the displayed code with the peer through an out-of-band channel and enter the matching code manually. Three failed SAS attempts terminate the session. -
+## Highlights in v4.8.5 ---- -## 🔐 Shared Security Core +This release consolidates several months of security hardening work by the project team: -SecureBitChat uses a shared Rust-based cryptographic core: -https://github.com/SecureBitChat/securebit-core +- mandatory interactive SAS verification instead of passive click-through confirmation +- deterministic SAS computation from shared session material +- protocol version `4.1` negotiation with mismatch rejection +- optional TURN relay-only privacy mode with clear warnings when TURN is unavailable +- encrypted IndexedDB metadata with lazy migration from legacy plaintext records +- explicit file-transfer consent before any receive buffers are allocated +- strict file-type allowlist using both MIME type and extension checks +- incoming decrypted message sanitization before UI delivery +- improved disconnect, timer, file-transfer, and React UI cleanup behavior +- pinned dependency versions and a clean `npm audit` baseline -This core is used across all platforms (web, desktop, mobile) as a single source of truth for all security-critical logic. +## Quick start -Community review is welcome. Bug reports and security feedback can be submitted via GitHub Issues. - -## Now Available: Desktop Applications! - -**SecureBit Chat native desktop apps are now available for Windows, macOS, and Linux!** - -[![Download Desktop Apps](https://img.shields.io/badge/Download-Desktop%20Apps%20v0.1.0-blue?style=for-the-badge&logo=github)](https://github.com/SecureBitChat/securebit-desktop) - -### Get Desktop Apps -- **Windows 10/11** - NSIS Installer (x64) -- **macOS 11+** - Universal App (Intel + Apple Silicon) -- **Linux** - AppImage (Universal, amd64) - -**Status:** Public Beta v0.1.0 Available -**Technology:** Built with Tauri v2 (Rust + Web Technologies) -**Coming Q1 2026:** Windows Store, Mac App Store, Snap Store - -**[Download Desktop Apps →](https://github.com/SecureBitChat/securebit-desktop/releases/latest)** - ---- - -## Shared Security Core - -**All SecureBit applications share the same open-source cryptographic core:** - -[![Core Repository](https://img.shields.io/badge/Core-securebit--core-blue?style=for-the-badge&logo=rust)](https://github.com/SecureBitChat/securebit-core) - -### Platform Architecture - -``` -┌─────────────────────────────────────────────────────────────┐ -│ User Applications │ -├──────────────────┬──────────────────┬──────────────────────┤ -│ Web Version │ Desktop Apps │ Mobile (Coming) │ -│ (This Repo) │ (Tauri v2) │ (Q1 2026) │ -│ Browser PWA │ Windows/Mac/ │ iOS/Android │ -│ v4.7.56 │ Linux │ Native Apps │ -│ │ v0.1.0 Beta │ │ -└────────┬─────────┴────────┬─────────┴──────────┬───────────┘ - │ │ │ - └──────────────────┼────────────────────┘ - │ - ▼ - ┌──────────────────────────────────────────┐ - │ securebit-core (Open Source) │ - │ • All Cryptographic Operations │ - │ • P2P Protocol Implementation │ - │ • End-to-End Encryption │ - │ • Key Exchange & Verification │ - │ • ASN.1 Structure Validation │ - │ License: Apache 2.0 │ - └──────────────────────────────────────────┘ -``` - -### Why This Architecture? - -- **100% of cryptography is open source** - Audit at [securebit-core](https://github.com/SecureBitChat/securebit-core) -- **Single source of truth** - Same security across all platforms -- **Full transparency** - Security-critical code is publicly auditable -- **Community reviewed** - Bug reports and security feedback welcome -- **Memory-safe core** - Rust implementation prevents entire classes of vulnerabilities -- **Cross-platform consistency** - Identical security guarantees on all platforms - -**Core Repository:** https://github.com/SecureBitChat/securebit-core -**License:** Apache License 2.0 -**Language:** Rust (memory-safe, zero-cost abstractions) - ---- - -## Overview - -SecureBit.chat is a revolutionary peer-to-peer messenger that prioritizes your privacy with military-grade encryption. No servers, no registration, no data collection - just pure, secure communication. - -### Platform Availability - -| Platform | Status | Version | Link | -|----------|--------|---------|------| -| **Web Browser** | Production | v4.7.56 | [Launch Web App](https://securebitchat.github.io/securebit-chat/) | -| **Windows Desktop** | Beta | v0.1.0 | [Download](https://github.com/SecureBitChat/securebit-desktop/releases/latest) | -| **macOS Desktop** | Beta | v0.1.0 | [Download](https://github.com/SecureBitChat/securebit-desktop/releases/latest) | -| **Linux Desktop** | Beta | v0.1.0 | [Download](https://github.com/SecureBitChat/securebit-desktop/releases/latest) | -| **iOS Mobile** | 🔄 In Development | - | Coming Q1 2026 | -| **Android Mobile** | 🔄 In Development | - | Coming Q1 2026 | - -### Key Features - -- **18-Layer Military Security** - ECDH + DTLS + SAS triple-layer verification -- **Pure P2P Architecture** - No servers, truly decentralized -- **Progressive Web App** - Install like a native app on any device -- **Native Desktop Apps** - Windows, macOS, Linux (Tauri v2) -- **Native Mobile Apps** - iOS (Swift/SwiftUI), Android (Kotlin/Jetpack Compose) - Coming Q1 2026 -- **Secure File Transfer** - End-to-end encrypted P2P file sharing -- **Smart Notifications** - Browser and desktop alerts -- **Complete Anonymity** - Zero data collection, no registration -- **Open Source Security** - Cryptographic core is fully auditable -- **ASN.1 Validation** - Complete key structure verification -- **Perfect Forward Secrecy** - Automatic key rotation - ---- - -## ✨ What's New in v4.7.56 - -### Desktop Edition Release - -- **Native Desktop Applications** - Windows, macOS, and Linux support -- **Tauri v2 Framework** - Lightweight, secure, and performant -- **System Integration** - Native notifications, system tray, auto-start -- **Offline Support** - Works without internet connection -- **Multi-window Support** - Multiple conversation windows -- **Improved Performance** - Native code execution for crypto operations - -### Bug Fixes & Improvements - -- **Fix:** Prevent encryption key loss and IndexedDB connection errors -- **Fix:** Disable timer-based key rotation for Double Ratchet mode -- **Fix:** Auto-reinitialize encryption keys when missing but ECDH available -- **Fix:** Preserve active keys during periodic cleanup in ratchet sessions -- **Fix:** IndexedDB "database closing" errors with connection checking -- **Improvement:** Individual transactions per queue item to prevent race conditions -- **Improvement:** Enhanced message text wrapping in chat interface - -### Security Enhancements - -- **ECDH + DTLS + SAS System** - Triple-layer security verification -- **ASN.1 Full Structure Validation** - Complete key structure verification -- **Enhanced MITM Protection** - Multi-layer defense system -- **Secure Key Storage** - WeakMap-based isolation -- **Production-Ready Logging** - Data sanitization and privacy protection -- **HKDF Key Derivation** - RFC 5869 compliant key separation and derivation - ---- - -## Quick Start - -### Web Version (Browser) - -1. **Visit** [https://securebit.chat/](https://securebit.chat/) -2. **Share your link** or enter your peer's link -3. **Start chatting** - No registration required! - -**Install as PWA:** -- Click the install prompt in your browser -- Or use browser menu: "Install SecureBit.chat" - -### Desktop Version (Native Apps) - -1. **Download** installer from [securebit-desktop releases](https://github.com/SecureBitChat/securebit-desktop/releases/latest) -2. **Install** on Windows, macOS, or Linux -3. **Launch** and start secure communication - -**Platform-specific instructions:** -- **Windows:** Run `.exe` installer, follow setup wizard -- **macOS:** Open `.zip`, drag `SecureBit Chat.app` to Applications -- **Linux:** Make AppImage executable: `chmod +x SecureBit.Chat_*.AppImage`, then run - -### Features Comparison - -| Feature | Web Version | Desktop Apps | -|---------|-------------|--------------| -| **P2P Encryption** | ✅ | ✅ | -| **File Sharing** | ✅ | ✅ | -| **Voice/Video Calls** | ✅ | ✅ | -| **Screen Sharing** | ✅ | ✅ | -| **System Notifications** | ✅ (Browser) | ✅ (Native) | -| **Offline Mode** | ❌ | ✅ | -| **Auto-start** | ❌ | ✅ | -| **System Tray** | ❌ | ✅ | -| **Multi-window** | ❌ | ✅ | -| **Background Operation** | ❌ | ✅ | -| **Lower Resource Usage** | ❌ | ✅ (Tauri) | - ---- - -## 🗺️ Roadmap - -**Current: v4.7.56** - Desktop Edition Available - -### Released Versions - -- **v4.5** - Enhanced Security Edition - - ECDH + DTLS + SAS triple-layer security - - 18-layer military-grade cryptography - - Complete ASN.1 validation - - Perfect Forward Secrecy - -- **v4.7** - Desktop Edition (Current) - - Native desktop applications (Windows, macOS, Linux) - - Built with Tauri v2 - - System tray integration and native notifications - - Offline support and multi-window - -- **v0.1.0** - Desktop Apps Beta - - Initial desktop release - - Windows, macOS, Linux support - -### Upcoming Releases - -- **v5.0 (Q1 2026)** - Mobile Edition - - Native iOS app (Swift/SwiftUI) - - Native Android app (Kotlin/Jetpack Compose) - - PWA support for mobile browsers - - Real-time push notifications - - Battery optimization - - Biometric authentication - -- **v5.5 (Q2 2026)** - Quantum-Resistant Edition - - CRYSTALS-Kyber post-quantum key exchange - - SPHINCS+ post-quantum signatures - - Hybrid classical + post-quantum schemes - - Quantum-safe key exchange - - Migration of existing sessions - -- **v6.0 (Q4 2026)** - Group Communications - - 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) - -- **v6.5 (2027)** - Decentralized Network - - DHT for peer discovery - - Built-in onion routing - - Tokenomics and node incentives - - Governance via DAO - - Self-healing network - -- **v7.0 (2028+)** - AI Privacy Assistant - - Local AI threat analysis - - Automatic MITM detection - - Adaptive cryptography - - Zero-knowledge machine learning - ---- - -## Security - -### Open Source Cryptographic Core - -**All security-critical code is open source and auditable:** - -- **Repository:** [securebit-core](https://github.com/SecureBitChat/securebit-core) -- **License:** Apache License 2.0 -- **Language:** Rust (memory-safe, prevents entire vulnerability classes) -- **Auditable:** 100% of cryptographic operations -- **Standards:** RFC 5869 (HKDF), NIST SP 800-56A (ECDH), RFC 8446 (DTLS) - -### Security Features - -#### Triple-Layer Verification -1. **ECDH (Elliptic Curve Diffie-Hellman)** - P-384 curve key exchange -2. **DTLS (Datagram Transport Layer Security)** - WebRTC transport security with fingerprint verification -3. **SAS (Short Authentication String)** - Visual MITM detection and verification - -#### Cryptographic Primitives -- **Key Exchange:** ECDH P-384 (NIST curve) -- **Signatures:** ECDSA P-384 -- **Encryption:** AES-256-GCM -- **Key Derivation:** HKDF-SHA-256 (RFC 5869) -- **Authentication:** HMAC-SHA-256 -- **Hashing:** SHA-256, SHA-384 - -#### Protocol Security -- Perfect Forward Secrecy (PFS) -- End-to-End Encryption (E2EE) -- Zero-Knowledge Architecture -- Replay Protection -- Metadata Protection -- ASN.1 Structure Validation -- OID and EC Point Verification -- SPKI Structure Validation - -#### Security Architecture -- **18-Layer Defense System** - Multiple independent security layers -- **MITM Attack Prevention** - Triple verification prevents man-in-the-middle attacks -- **Key Isolation** - WeakMap-based secure key storage -- **Secure Memory Management** - Automatic secure deletion of sensitive data -- **Production Logging** - Sanitized logs prevent information leakage - -### What We DON'T Collect -- No personal information -- No phone numbers or emails -- No contact lists on servers -- No message content or metadata -- No telemetry or analytics -- No usage statistics -- No IP addresses logged -- No device fingerprints -- No location data - -### Security Audit - -Want to audit our security? Check these repositories: - -1. **[securebit-core](https://github.com/SecureBitChat/securebit-core)** - All cryptographic operations (Rust) -2. **[securebit-chat](https://github.com/SecureBitChat/securebit-chat)** - Web UI implementation (this repo, JavaScript/React) - -**Report Security Issues:** SecureBitChat@proton.me -**PGP Key:** Available on request for encrypted security reports - ---- - -## Development - -### Prerequisites - -- **Node.js** 18+ -- **npm** or **yarn** -- **Git** - -### Installation +### Run locally ```bash -# Clone repository -git clone https://github.com/SecureBitChat/securebit-chat.git -cd securebit-chat - -# Install dependencies npm install - -# Run development server -npm run dev -``` - -### Building - -```bash -# Build for production npm run build - -# Build CSS only -npm run build:css - -# Build JavaScript only -npm run build:js - -# Preview production build (requires Python) -python -m http.server 8000 -``` - -### Development Scripts - -```bash -# Development server with hot reload -npm run dev - -# Watch CSS changes -npm run watch - -# Build everything -npm run build - -# Serve built files npm run serve ``` -### Project Structure +Then open the local server URL in two browser windows or profiles. -``` -securebit-chat/ -├── src/ -│ ├── components/ # React components -│ │ ├── ui/ # UI components (Header, Roadmap, etc.) -│ │ └── QRScanner.jsx # QR code scanner -│ ├── crypto/ # Cryptography utilities -│ │ └── EnhancedSecureCryptoUtils.js -│ ├── network/ # WebRTC P2P logic -│ │ └── EnhancedSecureWebRTCManager.js -│ ├── transfer/ # File transfer -│ │ └── EnhancedSecureFileTransfer.js -│ ├── notifications/ # Notification system -│ ├── pwa/ # PWA functionality -│ ├── scripts/ # Bootstrap and initialization -│ └── styles/ # CSS stylesheets -├── dist/ # Built files (generated) -├── assets/ # Static assets -├── public/ # Public files -└── docs/ # Documentation +### Establish a session + +1. Create an offer in the first browser. +2. Transfer the offer to the peer and create an answer. +3. Return the answer to the first browser. +4. Compare the SAS code out of band. +5. Enter the matching SAS code on both sides. +6. Begin chatting only after both peers are verified. + +## Configuration + +### TURN / privacy mode + +Direct WebRTC connections may expose IP addresses to peers. SecureBit.chat supports a relay-only privacy mode: + +- default mode keeps normal WebRTC behavior and existing STUN support +- relay-only mode sets `iceTransportPolicy: "relay"` +- relay-only mode requires a configured TURN server +- STUN alone does not hide IP addresses +- public TURN credentials are not bundled or hardcoded + +Configure ICE servers at deployment time and enable relay-only mode only when a TURN service is available. See [`doc/CONFIGURATION.md`](doc/CONFIGURATION.md). + +### File transfer policy + +Incoming file transfers require explicit user consent. Before the consent prompt appears, metadata is validated and dangerous names are rejected. Safe accepted categories are: + +- common raster images +- PDF +- plain text +- ZIP archives + +Executable, scriptable, and high-risk formats are rejected, including `.exe`, `.bat`, `.cmd`, `.sh`, `.js`, `.msi`, `.dmg`, `.app`, `.jar`, `.scr`, `.ps1`, `.vbs`, `.html`, and `.svg`. MIME type and filename extension must agree. + +## Development + +### Requirements + +- Node.js 18+ +- npm + +### Commands + +```bash +npm install +npm test +npm audit +npm run build +npm run dev ``` -### Contributing to Core +### Project layout -Want to improve security? Contribute to the cryptographic core: -- **Repository:** [securebit-core](https://github.com/SecureBitChat/securebit-core) -- **Focus:** Cryptography, protocol implementation, security features -- **Language:** Rust +```text +src/network/ WebRTC connection and session lifecycle +src/transfer/ secure file-transfer implementation +src/crypto/ cryptographic utilities +src/components React UI components +doc/ technical documentation +``` +## Documentation -## Related Projects +- [`SECURITY.md`](SECURITY.md) +- [`doc/CONFIGURATION.md`](doc/CONFIGURATION.md) +- [`doc/CRYPTOGRAPHY.md`](doc/CRYPTOGRAPHY.md) +- [`doc/SECURITY-ARCHITECTURE.md`](doc/SECURITY-ARCHITECTURE.md) +- [`doc/API.md`](doc/API.md) +- [`CHANGELOG.md`](CHANGELOG.md) -### Official SecureBit Ecosystem +## Responsible use -| Project | Description | Status | License | -|---------|-------------|--------|---------| -| **[securebit-core](https://github.com/SecureBitChat/securebit-core)** | Cryptographic kernel (Rust) | ✅ Production | Apache 2.0 | -| **[securebit-chat](https://github.com/SecureBitChat/securebit-chat)** | Web application (this repo) | ✅ Production v4.7.56 | MIT | -| **[securebit-desktop](https://github.com/SecureBitChat/securebit-desktop)** | Desktop apps (Windows/Mac/Linux) | ✅ Beta v0.1.0 | Proprietary* | -| **securebit-mobile** | Mobile apps (iOS/Android) | 🔄 Coming Q1 2026 | TBD | +SecureBit.chat is intended for lawful, ethical use. See [`RESPONSIBLE_USE.md`](RESPONSIBLE_USE.md) and [`SECURITY_DISCLAIMER.md`](SECURITY_DISCLAIMER.md). -*\* Desktop apps are free for personal and commercial use. Only the UI layer is proprietary - all cryptography is open source in securebit-core.* +## License -### Technology Stack - -- **Frontend:** React, Tailwind CSS -- **Build:** esbuild, Tailwind CLI -- **P2P:** WebRTC -- **Crypto Core:** Rust (securebit-core) -- **Desktop:** Tauri v2 -- **Mobile (Future):** Swift/SwiftUI (iOS), Kotlin/Jetpack Compose (Android) - ---- - -## Contributing - -We welcome contributions! Here's how: - -### Contributing to Web Version (This Repo) - -1. **Fork** the repository -2. **Create** feature branch: `git checkout -b feature/amazing-feature` -3. **Commit** changes: `git commit -m "Add amazing feature"` -4. **Push** to branch: `git push origin feature/amazing-feature` -5. **Open** Pull Request - -### Contributing to Cryptographic Core - -Want to improve security? Contribute to the core: -- **Repository:** [securebit-core](https://github.com/SecureBitChat/securebit-core) -- **Focus:** Cryptography, protocol implementation, security features -- **Language:** Rust - -### Contributing to Desktop Apps - -- **Repository:** [securebit-desktop](https://github.com/SecureBitChat/securebit-desktop) -- **Focus:** UI/UX improvements, platform-specific features -- **Technology:** Tauri v2, Rust, TypeScript - -### Other Ways to Help - -- **Report bugs** - Open issues on GitHub -- **Security research** - Email SecureBitChat@proton.me -- **Improve documentation** - Help others understand the project -- **Star the repositories** - Support visibility and development -- **Spread the word** - Share with privacy advocates -- **Provide feedback** - Help shape the future of SecureBit - -**If you support our mission - please star the repos!** -- [⭐ Star securebit-chat (Web)](https://github.com/SecureBitChat/securebit-chat) -- [⭐ Star securebit-core (Crypto)](https://github.com/SecureBitChat/securebit-core) -- [⭐ Star securebit-desktop (Apps)](https://github.com/SecureBitChat/securebit-desktop) - ---- - -## 📄 License - -### This Repository (Web Version) -**License:** MIT License - -### Cryptographic Core -**License:** Apache License 2.0 -**Repository:** [securebit-core](https://github.com/SecureBitChat/securebit-core) - -### Desktop Applications -**License:** Proprietary (Free for personal & commercial use) -**Repository:** [securebit-desktop](https://github.com/SecureBitChat/securebit-desktop) - -*Note: Desktop apps are free to use. Only the UI layer is proprietary - all cryptography is open source.* - ---- - -## Community & Support - -### Get Help -- **Documentation:** Check README and [core docs](https://github.com/SecureBitChat/securebit-core)** -- **Discussions:** [GitHub Discussions](https://github.com/SecureBitChat/securebit-chat/discussions) -- **Issues:** [Report bugs on GitHub](https://github.com/SecureBitChat/securebit-chat/issues) -- **Email:** SecureBitChat@proton.me - -### Contact -- **Security Issues:** SecureBitChat@proton.me (encrypted preferred) -- **Business Inquiries:** hello@securebit.chat -- **Twitter/X:** [@SecureBitChat](https://twitter.com/SecureBitChat) -- **Website:** https://securebit.chat (coming soon) - -### Community Guidelines - -- Be respectful and constructive -- Focus on privacy and security -- Help others learn and contribute -- Report security issues responsibly -- Follow the code of conduct - ---- - -## Acknowledgments - -### Built With -- **React** - UI framework -- **Tailwind CSS** - Styling -- **esbuild** - Build tool -- **WebRTC** - P2P communication -- **IndexedDB** - Local storage -- **Rust** - Cryptographic core -- **Tauri v2** - Desktop framework - -### Special Thanks -- **Rust Crypto Team** - Cryptographic primitives and standards -- **WebRTC Community** - P2P technology and standards -- **Tauri Team** - Desktop framework development -- **Security Researchers** - Audits, feedback, and improvements -- **Contributors** - Code, docs, testing, and support -- **Privacy Advocates** - Inspiration and mission support - -### Standards & Specifications -- **RFC 5869** - HKDF key derivation -- **NIST SP 800-56A** - ECDH key agreement -- **RFC 8446** - DTLS 1.3 -- **RFC 7748** - Elliptic curves for security -- **X.509** - ASN.1 certificate structure - ---- - -## Project Status - -### Active Development -- **Web Version** - Stable (v4.7.56), receiving bug fixes and improvements -- **Desktop Apps** - Public beta (v0.1.0), active development -- **Cryptographic Core** - Stable, production-ready -- **Mobile Apps** - In development (Q1 2026) - -### Community -- **GitHub Stars** - [Help us grow!](https://github.com/SecureBitChat/securebit-chat) -- **Contributors** - [See all contributors](https://github.com/SecureBitChat/securebit-chat/graphs/contributors) -- **Issues** - [Open issues](https://github.com/SecureBitChat/securebit-chat/issues) -- **Pull Requests** - [Contribute](https://github.com/SecureBitChat/securebit-chat/pulls) -- **Discussions** - [Join the conversation](https://github.com/SecureBitChat/securebit-chat/discussions) - -### Metrics -- **Downloads** - Desktop apps available for all platforms -- **Security** - 18-layer military-grade protection -- **Platforms** - Web, Windows, macOS, Linux (Mobile coming Q1 2026) -- **License** - Open source core, free desktop apps - ---- - -
- -**SecureBit.chat Security Team** - -*Committed to protecting your privacy with military-grade security* - ---- - -**Latest Release: v4.7.56** - Desktop Edition Available -**Desktop Apps: v0.1.0** - Public Beta Available -**Mobile Apps: Coming Q1 2026** - -[🚀 Try Web Version](https://securebit.chat/) • [🖥️ Download Desktop Apps](https://github.com/SecureBitChat/securebit-desktop) • [⭐ Star on GitHub](https://github.com/SecureBitChat/securebit-chat) - ---- - -**Made with 🔒 for privacy advocates worldwide** - -Copyright © 2025-2026 SecureBit Team. All rights reserved. - -
+MIT License. See [`LICENSE`](LICENSE). diff --git a/SECURITY.md b/SECURITY.md index 99bb409..35d651b 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -1,287 +1,80 @@ # Security Policy -## 🛡️ Security Overview +## Supported release line -SecureBit.chat is built with security-first principles and implements **military-grade security** with 18-layer protection system. We take security vulnerabilities seriously and appreciate responsible disclosure from the security community. +| Release | Status | Protocol | +| --- | --- | --- | +| v4.1.x | Supported | 4.1 | +| earlier releases | Unsupported | legacy | -**Current Security Status:** 🔒 **MAXIMUM SECURITY (Stage 5)** - Exceeds government-grade communication standards with complete ASN.1 validation +Users should run the current supported release line to receive the latest verification, storage, and file-transfer protections. -## 🔒 Enhanced Security Features (Stage 5) +## Reporting a vulnerability -### Multi-Layer Cryptographic Implementation -- **Key Exchange:** ECDH P-384 (NIST recommended curve) with non-extractable keys -- **Primary Encryption:** AES-GCM 256-bit with authenticated encryption -- **Nested Encryption:** Additional AES-GCM 256-bit layer for maximum protection -- **Metadata Protection:** Separate AES-GCM 256-bit encryption for message metadata -- **Digital Signatures:** ECDSA P-384 with SHA-384 for message authenticity and MITM protection -- **Perfect Forward Secrecy:** Automatic key rotation every 5 minutes with secure key versioning -- **Non-extractable Keys:** All cryptographic keys are hardware-protected and non-exportable -- **Enhanced Replay Protection:** Multi-factor protection with sequence numbers, message IDs, and timestamps -- **Secure Key Storage:** WeakMap-based isolation preventing direct access to sensitive keys -- **Key Security Monitoring:** Automatic validation, rotation, and emergency wipe capabilities -- **HKDF Key Derivation:** RFC 5869 compliant key separation with proper salt and info parameters +Please report security issues privately before public disclosure. -### Advanced Traffic Obfuscation -- **Packet Padding:** Random padding (64-512 bytes) to hide real message sizes -- **Anti-Fingerprinting:** Advanced traffic pattern obfuscation and timing randomization -- **Fake Traffic Generation:** Invisible decoy messages for traffic analysis protection -- **Message Chunking:** Split messages into random-sized chunks with variable delays -- **Packet Reordering Protection:** Sequence-based packet reassembly with timeout handling -- **Decoy Channels:** Multiple fake communication channels to confuse attackers +- Email: `SecureBitChat@proton.me` +- Include: affected version, reproduction steps, impact, and any proof-of-concept material +- Avoid publishing exploit details before a coordinated fix is available -### Enhanced Security Architecture -- **Zero-trust Model:** No central servers to compromise -- **P2P Direct:** WebRTC encrypted channels with enhanced validation -- **No Data Persistence:** Messages exist only in memory, automatic cleanup -- **Enhanced Rate Limiting:** 60 messages/minute, 5 connections/5 minutes with cryptographic verification -- **Session Security:** 64-byte salts, unique session IDs, and replay attack prevention -- **MITM Protection:** Out-of-band verification codes with enhanced validation -- **Connection Security Framework:** Advanced mutex system with 15-second timeout protection -- **Race Condition Protection:** Atomic key generation and serialized connection operations -- **Multi-stage Validation:** Step-by-step validation with automatic rollback on failures -- **Production Security Logging:** Environment-aware logging with data sanitization +## Current security behavior -### 🔐 ASN.1 Complete Structure Validation (NEW) -- **Complete ASN.1 DER Parser:** Full structural validation of all cryptographic keys -- **OID Validation:** Algorithm and curve verification (P-256/P-384 only) -- **EC Point Format Verification:** Uncompressed format 0x04 validation -- **SPKI Structure Validation:** Element count and type checking -- **Key Size Limits:** 50-2000 bytes to prevent DoS attacks -- **BIT STRING Validation:** Ensuring unused bits are 0 -- **Fallback Support:** P-384 to P-256 compatibility -- **High-Risk Vulnerability Fix:** Prevents keys with valid headers but modified data +### Peer verification -## 🚨 Supported Versions +- SAS verification is mandatory and interactive. +- SAS values are derived deterministically from shared session material. +- Users must compare the code out of band and enter the matching code manually. +- A session becomes verified only after both local and remote confirmations succeed. +- Three failed local SAS entries terminate the session. +- Protocol version `4.1` rejects incompatible peers instead of silently falling back to older verification behavior. -| Version | Security Level | Supported | -| ------- | -------------- | ------------------ | -| 4.02.x | MILITARY-GRADE | ✅ Yes (18 layers)| -| 4.01.x | MILITARY-GRADE | ✅ Yes (15 layers)| -| 4.0.x | MAXIMUM | ✅ Yes (12 layers)| -| 3.x.x | HIGH | ⚠️ Limited | -| < 3.0 | BASIC | ❌ No | +### Message handling -**Recommendation:** Upgrade to 4.02.x immediately for complete ASN.1 validation and military-grade security protection. +- Chat payloads remain encrypted in transit. +- Decrypted incoming chat text is sanitized before it reaches React state or the UI. +- Encrypted payload validation remains separate from display sanitization. -## 📋 Reporting a Vulnerability +### File transfer -### 🔴 Critical Vulnerabilities -For **critical security issues** that could compromise user safety: +- Incoming transfer metadata is validated before presentation to the user. +- Every incoming file requires explicit Accept or Reject consent. +- Receive buffers are not allocated before consent. +- File names are normalized for display and dangerous names are rejected. +- Allowed file types are explicit and validated using both MIME type and extension. +- High-risk executable or scriptable types are blocked. +- Repeated incoming transfer offers are rate-limited and bounded. -**DO NOT** create a public GitHub issue. +### Local storage -**Contact us privately:** -- 📧 **Email:** security@SecureBit.chat (PGP key below) -- 🔒 **Signal:** +[REDACTED] (ask for Signal number via email) -- 🔐 **Keybase:** @SecureBitChat +- Sensitive IndexedDB metadata is encrypted, including timestamps and session-related fields where feasible. +- Only minimum lookup keys remain in plaintext when required. +- Legacy plaintext metadata is migrated lazily on read. +- Corrupted encrypted metadata fails closed. -### 🟡 Non-Critical Issues -For general security improvements or non-critical findings: -- Create a GitHub issue with `[SECURITY]` prefix -- Use our security issue template +### Network privacy -## 📝 Vulnerability Disclosure Process +- Default mode preserves standard WebRTC connectivity. +- Relay-only privacy mode uses TURN by setting `iceTransportPolicy: "relay"`. +- STUN-only configurations do not provide IP protection. +- If TURN is absent, the UI warns that direct WebRTC may expose IP addresses. -1. **Report:** Send details to security@SecureBit.chat -2. **Acknowledgment:** We'll respond within 24 hours -3. **Investigation:** We'll investigate and keep you updated -4. **Fix:** We'll develop and test a fix -5. **Disclosure:** Public disclosure after fix is deployed -6. **Credit:** We'll credit you in our security hall of fame +### Lifecycle cleanup -### Timeline Expectations -- **Initial Response:** < 24 hours -- **Status Update:** Every 72 hours -- **Fix Timeline:** Critical bugs < 7 days, Others < 30 days +- Disconnect cleanup closes data channels and peer connections, clears verification state, and wipes session crypto state. +- Timers, deferred retries, decoy traffic, pending transfers, and React file-transfer callbacks are cleaned up on shutdown. +- Received file buffers are retained only within a bounded window and expired handles fail gracefully. -## 🏆 Security Hall of Fame +## Security verification commands -We maintain a hall of fame for security researchers who help improve SecureBit.chat: - - -*Be the first to help secure SecureBit.chat!* - -## 🔍 Security Audit History - -### Independent Audits -- **Pending:** Professional cryptographic audit (Q2 2025) -- **Community:** Ongoing peer review by security researchers - -### Internal Security Measures -- **Code Review:** All cryptographic code reviewed by multiple developers -- **Security Testing:** Comprehensive 18-layer security test suite -- **Dependencies:** Regular security updates for all dependencies -- **Vulnerability Testing:** Automated testing for all 18 security layers -- **ASN.1 Validation:** Complete structural validation of all cryptographic keys - -## 📊 Security Architecture (Stage 5) - -``` -19-Layer Security Architecture: -├── Layer 1: Enhanced Authentication (ECDSA P-384 + SHA-384) -├── Layer 2: Key Exchange (ECDH P-384, non-extractable keys) -├── Layer 3: Metadata Protection (AES-256-GCM + 64-byte salt) -├── Layer 4: Message Encryption (Enhanced with sequence numbers) -├── Layer 5: Nested Encryption (Additional AES-256-GCM layer) -├── Layer 6: Packet Padding (64-512 bytes random obfuscation) -├── Layer 7: Anti-Fingerprinting (Advanced pattern obfuscation) -├── Layer 8: Packet Reordering Protection (Sequence + timeout) -├── Layer 9: Message Chunking (Random delays + sizes) -├── Layer 10: Fake Traffic Generation (Invisible decoy messages) -├── Layer 11: Enhanced Rate Limiting (Cryptographic verification) -├── Layer 12: Perfect Forward Secrecy (5-minute key rotation) -├── Layer 13: Mutex Framework (Race condition protection) -├── Layer 14: Secure Key Storage (WeakMap isolation) -├── Layer 15: Production Logging (Data sanitization) -├── Layer 16: ASN.1 Validation (Complete key structure verification) -├── Layer 17: OID Validation (Algorithm and curve verification) -├── Layer 18: EC Point Validation (Format and structure verification) -└── Layer 19: HKDF Key Derivation (RFC 5869 compliant key separation) -``` - -### Security Metrics -- **Encryption Strength:** Triple-layer AES-256-GCM -- **Key Security:** P-384 ECDH/ECDSA (equivalent to 7680-bit RSA) -- **Forward Secrecy:** Complete (automatic key rotation) -- **Traffic Analysis Protection:** Maximum (6-layer obfuscation) -- **Attack Surface:** Minimal (P2P, no central servers) -- **Key Validation:** Complete ASN.1 DER parsing and validation -- **Structural Security:** Full PKCS compliance for all operations - -## 🛠️ Security Best Practices for Users - -### For Maximum Security: -1. **Verify Authenticity:** Always verify out-of-band codes (enhanced 6-digit format) -2. **Use Official Source:** Only use https://SecureBit.chat -3. **Keep Updated:** Use version 4.02.x for complete ASN.1 validation -4. **Secure Environment:** Use updated browsers on secure devices -5. **Monitor Security Status:** Check for "MAXIMUM SECURITY" indicator in chat - -### Security Indicators: -- ✅ **Green Shield:** MAXIMUM SECURITY (Stage 5) active -- 🟡 **Yellow Shield:** HIGH SECURITY (Stage 3-4) -- 🔴 **Red Shield:** Security issues detected - -### Red Flags: -- ❌ Verification codes don't match -- ❌ Security level below Stage 5 -- ❌ Unusual connection behavior -- ❌ Requests for private keys or seed phrases -- ❌ Unofficial domains or mirrors -- ❌ Missing security layer notifications - -### Research Ethics -- **No Disruption:** Don't interfere with live users -- **Responsible Disclosure:** Follow our disclosure timeline -- **No Data Harvesting:** Don't collect user communications -- **Legal Compliance:** Follow all applicable laws -- **Respect Privacy:** Don't attempt to break active encrypted sessions - -## 🔬 Security Research Guidelines - -### Scope -**In Scope:** -- ✅ Cryptographic implementation flaws in any of the 18 layers -- ✅ WebRTC security issues -- ✅ Authentication bypass attempts -- ✅ Input validation vulnerabilities -- ✅ Client-side security issues -- ✅ Traffic analysis vulnerabilities -- ✅ Perfect Forward Secrecy implementation -- ✅ Anti-fingerprinting bypass techniques -- ✅ Fake traffic detection methods -- ✅ ASN.1 validation bypass attempts -- ✅ Key structure manipulation attacks -- ✅ OID validation bypass techniques - -**Out of Scope:** -- ❌ Social engineering attacks -- ❌ Physical attacks on user devices -- ❌ DoS attacks on user connections -- ❌ Issues requiring physical access -- ❌ Browser security vulnerabilities - -## 🔄 Recent Security Updates (Version 4.02) - -### Major Security Enhancements: -- ✅ **Implemented 19-layer security architecture** -- ✅ **Added complete ASN.1 DER parser for key validation** -- ✅ **Enhanced key security with OID and EC point verification** -- ✅ **Fixed high-risk vulnerability in key structure validation** -- ✅ **Added SPKI structure validation and element checking** -- ✅ **Implemented key size limits to prevent DoS attacks** -- ✅ **Added BIT STRING validation ensuring unused bits are 0** -- ✅ **Enhanced fallback support from P-384 to P-256** -- ✅ **Implemented RFC 5869 compliant HKDF key derivation** -- ✅ **Enhanced key separation with proper salt and info parameters** - -### Previous Enhancements (Version 4.01): -- ✅ **Implemented 15-layer security architecture** -- ✅ **Added Perfect Forward Secrecy with automatic key rotation** -- ✅ **Enhanced MITM protection with ECDSA signatures** -- ✅ **Implemented traffic obfuscation (fake traffic, padding, chunking)** -- ✅ **Added anti-fingerprinting protection** -- ✅ **Fixed demo session creation vulnerability** -- ✅ **Eliminated session replay attacks** -- ✅ **Enhanced rate limiting with cryptographic verification** - -### Bug Fixes: -- 🔧 **Fixed fake traffic visibility in user interface** -- 🔧 **Resolved message processing conflicts** -- 🔧 **Improved security layer error handling** -- 🔧 **Enhanced session validation** -- 🔧 **Complete rewrite of validateKeyStructure() method** - -## 📚 Security Resources - -### Technical Documentation: -- [18-Layer Security Architecture](docs/SECURITY-ARCHITECTURE.md) -- [Cryptographic Implementation](docs/CRYPTOGRAPHY.md) -- [P2P Security Model](docs/P2P-SECURITY.md) -- [Lightning Integration Security](docs/LIGHTNING-SECURITY.md) -- [Traffic Obfuscation Guide](docs/TRAFFIC-OBFUSCATION.md) -- [ASN.1 Validation Guide](docs/ASN1-VALIDATION.md) - -### External Resources: -- [WebRTC Security Guide](https://webrtc-security.github.io/) -- [Web Crypto API Best Practices](https://www.w3.org/TR/WebCryptoAPI/) -- [Lightning Network Security](https://lightning.network/lightning-network-paper.pdf) -- [NIST Cryptographic Standards](https://csrc.nist.gov/) -- [RFC 5280 - X.509 Certificate Structure](https://tools.ietf.org/html/rfc5280) -- [RFC 5480 - Elliptic Curve Subject Public Key Information](https://tools.ietf.org/html/rfc5480) - -### Security Verification: ```bash -# Verify current security status in browser console: -webrtcManager.getSecurityStatus() -# Expected: { stage: 5, securityLevel: 'MAXIMUM', activeFeatures: 18 } - -# Verify ASN.1 validation status: -cryptoManager.getASN1ValidationStatus() -# Expected: { enabled: true, parser: 'DER', validation: 'complete' } +npm audit +npm test +npm run build ``` -## 📞 Contact Information +## Limitations -- **Security Team:** security@SecureBit.chat -- **General Contact:** lockbitchat@tutanota.com -- **GitHub Issues:** https://github.com/SecureBitChat/securebit-chat/issues - -## 🏅 Security Achievements - -SecureBit.chat v4.02 provides: -- **🥇 Military-Grade Security:** 19-layer protection system -- **🥇 Government-Level Encryption:** Triple AES-256-GCM + P-384 ECDH/ECDSA -- **🥇 Perfect Forward Secrecy:** Complete with automatic key rotation -- **🥇 Traffic Analysis Protection:** Maximum with 6-layer obfuscation -- **🥇 Zero-Trust Architecture:** No central points of failure -- **🥇 Complete ASN.1 Validation:** Full structural verification of all cryptographic keys -- **🥇 PKCS Compliance:** Complete adherence to cryptographic standards -- **🥇 HKDF Key Derivation:** RFC 5869 compliant key separation and derivation - -**Security Rating: MAXIMUM** - Exceeds most government and military communication standards with complete key structure validation. - ---- - -*This security policy is reviewed and updated quarterly. Last updated: January 15, 2025* -*Security implementation verified and tested as of Version 4.02.442* \ No newline at end of file +- A compromised endpoint can still expose plaintext. +- WebRTC privacy depends on deployment configuration; TURN must be supplied by the operator. +- Users must perform the out-of-band SAS comparison correctly. +- Browser security and operating-system security remain part of the threat model. diff --git a/SECURITY_DISCLAIMER.md b/SECURITY_DISCLAIMER.md index e7ccb2e..25d3a45 100644 --- a/SECURITY_DISCLAIMER.md +++ b/SECURITY_DISCLAIMER.md @@ -1,244 +1,27 @@ # Security Disclaimer and Terms of Use -## 🔒 SecureBit.chat Enhanced Security Edition v4.02.442 +SecureBit.chat is provided as open-source software for lawful private communication, research, and education. It is supplied **as is**, without warranties of any kind. -### Important Legal Notice +## User responsibilities -**READ THIS DISCLAIMER CAREFULLY BEFORE USING SECUREBIT.CHAT SOFTWARE** +By using SecureBit.chat, you are responsible for: ---- +- complying with applicable laws and organizational policies +- securing your devices and browser environment +- verifying SAS codes through an out-of-band channel +- understanding that endpoint compromise can defeat application-layer protections +- configuring TURN correctly when relay-only privacy mode is required -## 📋 Overview +## Security limitations -SecureBit.chat is an open-source, peer-to-peer encrypted messaging application designed to support **freedom of speech** and **privacy rights**. This software implements military-grade cryptography with complete ASN.1 validation and is provided as-is for educational, research, and legitimate communication purposes. +No communication system can guarantee absolute security. SecureBit.chat reduces risk through encrypted transport, mandatory peer verification, explicit file-transfer consent, local metadata protection, and lifecycle cleanup, but it cannot protect against compromised devices, malicious users with physical access, or incorrect operational practices. ---- +## Intended use -## ⚖️ Legal Disclaimer +SecureBit.chat is intended for legitimate private communication, journalism, research, education, business confidentiality, and personal privacy. It is not intended to facilitate unlawful activity, abuse, harassment, or harm. -### Developer Liability +## Current release -**THE DEVELOPER(S) OF SECUREBIT.CHAT ASSUME NO RESPONSIBILITY OR LIABILITY FOR:** - -- Any misuse, illegal use, or criminal activities conducted using this software -- Compliance with local, national, or international laws and regulations -- Any damages, losses, or consequences resulting from the use of this software -- The security or privacy of communications in jurisdictions where encryption is restricted -- Any vulnerability, security flaw, or compromise that may occur despite our security measures - -### User Responsibility - -**BY USING SECUREBIT.CHAT, YOU ACKNOWLEDGE AND AGREE THAT:** - -1. **Full Legal Responsibility**: You bear complete and sole responsibility for how you use this software -2. **Compliance Obligation**: You must ensure your use complies with all applicable laws in your jurisdiction -3. **Risk Acceptance**: You understand and accept all risks associated with using encrypted communication software -4. **No Warranty**: This software is provided "AS IS" without any warranties, express or implied - ---- - -## 🌍 Jurisdictional Considerations - -### Encryption Laws Vary Globally - -- **Some countries restrict or prohibit** the use of strong encryption -- **Export controls** may apply in certain jurisdictions -- **Corporate/government networks** may have policies against encrypted communications -- **Users must verify** local laws before using this software - -### High-Risk Jurisdictions - -**Exercise extreme caution** in countries with: -- Restrictions on encrypted communications -- Surveillance laws requiring backdoors -- Penalties for using VPN/encryption software -- Authoritarian internet controls - ---- - -## 🎯 Intended Use Cases - -### ✅ Legitimate Uses (Encouraged) -- **Journalism**: Protecting sources and whistleblowers -- **Human Rights**: Organizing and advocacy in oppressive regimes -- **Business**: Corporate communications requiring confidentiality -- **Personal Privacy**: Private communications between individuals -- **Research**: Academic study of cryptographic protocols -- **Education**: Learning about secure communication systems - -### ❌ Prohibited Uses (Illegal/Unethical) -- Any illegal activities under applicable law -- Criminal conspiracies or planning illegal acts -- Harassment, threats, or abuse of others -- Circumventing legitimate law enforcement (where legally required) -- Distribution of illegal content -- Financial crimes or fraud - ---- - -## 🔐 Security Limitations - -### No Absolute Security - -**UNDERSTAND THAT:** -- No cryptographic system is 100% unbreakable -- Implementation bugs may exist despite best efforts -- Social engineering and endpoint security remain vulnerabilities -- Quantum computing may eventually threaten current encryption -- Traffic analysis may reveal communication patterns - -### User Security Responsibilities - -**YOU MUST:** -- Keep your devices secure and updated -- Use strong, unique passwords -- Verify security codes through out-of-band channels -- Understand the risks of your communication environment -- Follow operational security (OPSEC) best practices - ---- - -## 🏛️ Freedom of Speech Support - -### Our Mission - -SecureBit.chat is developed to support: -- **Article 19** of the Universal Declaration of Human Rights -- **Freedom of expression** and **right to privacy** -- **Resistance to censorship** and mass surveillance -- **Protection of journalists, activists, and dissidents** - -### Ethical Use Commitment - -We believe privacy and free speech are fundamental human rights, but: -- These rights come with responsibilities -- Freedom of speech does not include freedom from consequences -- Users must respect the rights and safety of others -- Illegal activity is never justified, regardless of privacy tools used - ---- - -## 📊 Technical Security Information - -### Current Implementation (v4.02.442) -- **ECDH P-384** key exchange with complete ASN.1 validation -- **AES-GCM 256-bit** encryption -- **ECDSA P-384** digital signatures with enhanced key verification -- **RSA-2048** digital signatures for file metadata -- **Perfect Forward Secrecy** with key rotation -- **MITM protection** via out-of-band verification -- **Zero server architecture** (pure P2P) -- **DTLS Race Condition Protection** against October 2024 WebRTC vulnerabilities -- **ICE Endpoint Verification** for secure WebRTC connections -- **Message Size Validation** with 1MB DoS protection -- **Atomic Operations** for race condition prevention -- **Secure Memory Management** with advanced wiping techniques -- **Symbol-Based Context Isolation** for private instance management -- **Rate Limiting System** (10 files/minute) with client identification - -### 🔒 ASN.1 Complete Structure Validation (NEW) -- **Complete ASN.1 DER Parser**: Full structural validation of all cryptographic keys -- **OID Validation**: Algorithm and curve verification (P-256/P-384 only) -- **EC Point Format Verification**: Uncompressed format 0x04 validation -- **SPKI Structure Validation**: Element count and type checking -- **Key Size Limits**: 50-2000 bytes to prevent DoS attacks -- **BIT STRING Validation**: Ensuring unused bits are 0 -- **Fallback Support**: P-384 to P-256 compatibility -- **High-Risk Vulnerability Fix**: Prevents keys with valid headers but modified data - -### Known Limitations -- WebRTC fingerprinting possibilities (mitigated by anti-fingerprinting techniques) -- Browser-based implementation constraints -- Dependency on Web Crypto API security -- No protection against compromised endpoints -- Traffic analysis potential despite encryption (mitigated by packet padding and noise) -- Memory safety depends on JavaScript engine implementation -- DTLS protection effectiveness depends on WebRTC implementation - ---- - -## 🔄 Future Development - -### Post-Quantum Roadmap -- **v5.0**: CRYSTALS-Kyber/Dilithium implementation -- **Long-term**: Resistance to quantum cryptanalysis -- **Ongoing**: Security audits and improvements - -### Advanced Security Technologies (v4.02.442) -- **ASN.1 Validation Framework**: Complete DER parsing and key structure verification -- **Enhanced Key Security**: OID and EC point validation for all cryptographic operations -- **PKCS Compliance**: Full adherence to cryptographic standards -- **Structural Security**: Complete validation of all key components -- **Vulnerability Prevention**: High-risk key manipulation attack prevention - -### Previous Advanced Security Technologies (v4.01.441) -- **DTLS Protection Framework**: Comprehensive WebRTC security enhancement -- **Memory Safety Mechanisms**: Advanced protection against use-after-free vulnerabilities -- **Race Condition Prevention**: Atomic operations for critical security sections -- **Error Sanitization System**: Secure error handling without information leakage -- **Context Isolation**: Symbol-based private instance management -- **File Transfer Security**: Cryptographic signatures and metadata validation -- **Advanced DoS Protection**: Message size validation and rate limiting - ---- - -## 📞 Contact and Reporting - -### Security Issues -- **Responsible disclosure**: Email security issues to the development team -- **CVE reporting**: We participate in responsible vulnerability disclosure -- **Bug bounty**: Consider implementing for critical security findings - -### Legal Concerns -- **Law enforcement**: Contact appropriate legal authorities in your jurisdiction -- **Abuse reports**: Report illegal use to relevant authorities -- **Compliance questions**: Consult with legal counsel - ---- - -## 📜 License and Terms - -### Open Source License -SecureBit.chat is released under the **MIT License**, providing: -- Freedom to use, modify, and distribute -- No warranty or liability guarantees -- Full source code transparency -- Right to audit security implementation - -### Terms Acceptance -**By downloading, installing, or using SecureBit.chat, you acknowledge:** - -1. You have read and understood this disclaimer -2. You accept full responsibility for your use of the software -3. You agree to comply with all applicable laws -4. You understand the security limitations and risks -5. You will not hold the developers liable for any consequences - ---- - -## ⚠️ Final Warning - -**SECUREBIT.CHAT IS A POWERFUL TOOL FOR PRIVACY AND FREE SPEECH** - -With great power comes great responsibility. Use this software ethically, legally, and with full understanding of the risks and responsibilities involved. - -**Remember**: The strongest encryption cannot protect against poor operational security, compromised endpoints, or illegal activities that attract law enforcement attention. - ---- - -## 🛡️ Declaration of Intent - -This software is created to: -- **Protect human rights** and fundamental freedoms -- **Support legitimate privacy** needs in an increasingly surveilled world -- **Advance the field** of secure communications -- **Educate users** about cryptography and privacy - -**It is NOT intended to facilitate illegal activities or harm others.** - ---- - -*Last Updated: January 15, 2025* -*Version: Enhanced Security Edition v4.02.442 - ASN.1 Validated* - -**USE AT YOUR OWN RISK AND RESPONSIBILITY** \ No newline at end of file +- Product release: `v4.8.5` +- Protocol version: `4.1` +- Last updated: May 17, 2026 diff --git a/assets/tailwind.css b/assets/tailwind.css index e35b84e..2394da2 100644 --- a/assets/tailwind.css +++ b/assets/tailwind.css @@ -1 +1 @@ -*,: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: }/*! tailwindcss v3.4.17 | MIT License | https://tailwindcss.com*/*,:after,:before{box-sizing:border-box;border:0 solid #e5e7eb}:after,:before{--tw-content:""}:host,html{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;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;-webkit-tap-highlight-color:transparent}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}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-variation-settings:normal;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-feature-settings:inherit;font-variation-settings:inherit;font-size:100%;font-weight:inherit;line-height:inherit;letter-spacing:inherit;color: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{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}[role=button],button{cursor:pointer}:disabled{cursor:default}audio,canvas,embed,iframe,img,object,svg,video{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]:where(:not([hidden=until-found])){display:none}.\!container{width:100%!important}.container{width:100%}@media (min-width:640px){.\!container{max-width:640px!important}.container{max-width:640px}}@media (min-width:768px){.\!container{max-width:768px!important}.container{max-width:768px}}@media (min-width:1024px){.\!container{max-width:1024px!important}.container{max-width:1024px}}@media (min-width:1280px){.\!container{max-width:1280px!important}.container{max-width:1280px}}@media (min-width:1536px){.\!container{max-width:1536px!important}.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}.-right-2{right:-.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-4{left:1rem}.right-0{right:0}.right-3{right:.75rem}.right-4{right:1rem}.right-6{right:1.5rem}.top-0{top:0}.top-1\/2{top:50%}.top-4{top:1rem}.z-10{z-index:10}.z-20{z-index:20}.z-40{z-index:40}.z-50{z-index:50}.z-\[9999\]{z-index:9999}.mx-4{margin-left:1rem;margin-right:1rem}.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-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-12{margin-top:3rem}.mt-16{margin-top:4rem}.mt-2{margin-top:.5rem}.mt-20{margin-top:5rem}.mt-4{margin-top:1rem}.mt-6{margin-top:1.5rem}.mt-8{margin-top:2rem}.block{display:block}.inline{display:inline}.flex{display: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-2\.5{height:.625rem}.h-28{height:7rem}.h-4{height:1rem}.h-6{height:1.5rem}.h-8{height:2rem}.h-80{height:20rem}.h-96{height:24rem}.h-\[420px\]{height:420px}.h-auto{height:auto}.h-full{height:100%}.h-px{height:1px}.max-h-\[80vh\]{max-height:80vh}.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-4{width:1rem}.w-6{width:1.5rem}.w-72{width:18rem}.w-8{width:2rem}.w-\[20rem\]{width:20rem}.w-full{width:100%}.min-w-\[160px\]{min-width:160px}.min-w-\[240px\]{min-width:240px}.max-w-2xl{max-width:42rem}.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-none{max-width:none}.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-row{flex-direction:row}.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-12{gap:3rem}.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-right:calc(.25rem*var(--tw-space-x-reverse));margin-left:calc(.25rem*(1 - var(--tw-space-x-reverse)))}.space-x-2>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-right:calc(.5rem*var(--tw-space-x-reverse));margin-left:calc(.5rem*(1 - var(--tw-space-x-reverse)))}.space-x-3>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-right:calc(.75rem*var(--tw-space-x-reverse));margin-left:calc(.75rem*(1 - var(--tw-space-x-reverse)))}.space-x-4>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-right:calc(1rem*var(--tw-space-x-reverse));margin-left:calc(1rem*(1 - var(--tw-space-x-reverse)))}.space-y-1>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.25rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.25rem*var(--tw-space-y-reverse))}.space-y-2>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.5rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.5rem*var(--tw-space-y-reverse))}.space-y-3>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.75rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.75rem*var(--tw-space-y-reverse))}.space-y-4>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(1rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1rem*var(--tw-space-y-reverse))}.space-y-6>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(1.5rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1.5rem*var(--tw-space-y-reverse))}.space-y-8>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(2rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(2rem*var(--tw-space-y-reverse))}.self-center{align-self:center}.overflow-hidden{overflow:hidden}.overflow-x-auto{overflow-x:auto}.overflow-y-auto{overflow-y:auto}.scroll-smooth{scroll-behavior:smooth}.whitespace-normal{white-space:normal}.break-words{overflow-wrap:break-word}.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-b{border-bottom-width:1px}.border-t{border-top-width:1px}.border-blue-500\/20{border-color:rgba(59,130,246,.2)}.border-gray-200{--tw-border-opacity:1;border-color:rgb(229 231 235/var(--tw-border-opacity,1))}.border-gray-500\/10{border-color:hsla(220,9%,46%,.1)}.border-gray-500\/20{border-color:hsla(220,9%,46%,.2)}.border-gray-600{--tw-border-opacity:1;border-color:rgb(75 85 99/var(--tw-border-opacity,1))}.border-gray-600\/30{border-color:rgba(75,85,99,.3)}.border-gray-700\/30{border-color:rgba(55,65,81,.3)}.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\/20{border-color:rgba(249,115,22,.2)}.border-purple-500\/20{border-color:rgba(168,85,247,.2)}.border-red-500\/20{border-color:rgba(239,68,68,.2)}.border-yellow-500\/20{border-color:rgba(234,179,8,.2)}.bg-\[rgb\(20_20_20_\/50\%\)\]{background-color:hsla(0,0%,8%,.5)}.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-400{--tw-bg-opacity:1;background-color:rgb(96 165 250/var(--tw-bg-opacity,1))}.bg-blue-500{--tw-bg-opacity:1;background-color:rgb(59 130 246/var(--tw-bg-opacity,1))}.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,1))}.bg-emerald-500{--tw-bg-opacity:1;background-color:rgb(16 185 129/var(--tw-bg-opacity,1))}.bg-gray-200{--tw-bg-opacity:1;background-color:rgb(229 231 235/var(--tw-bg-opacity,1))}.bg-gray-50{--tw-bg-opacity:1;background-color:rgb(249 250 251/var(--tw-bg-opacity,1))}.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,1))}.bg-gray-600\/20{background-color:rgba(75,85,99,.2)}.bg-gray-700{--tw-bg-opacity:1;background-color:rgb(55 65 81/var(--tw-bg-opacity,1))}.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,1))}.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{--tw-bg-opacity:1;background-color:rgb(17 24 39/var(--tw-bg-opacity,1))}.bg-gray-900\/30{background-color:rgba(17,24,39,.3)}.bg-green-200{--tw-bg-opacity:1;background-color:rgb(187 247 208/var(--tw-bg-opacity,1))}.bg-green-400{--tw-bg-opacity:1;background-color:rgb(74 222 128/var(--tw-bg-opacity,1))}.bg-green-400\/20{background-color:rgba(74,222,128,.2)}.bg-green-500{--tw-bg-opacity:1;background-color:rgb(34 197 94/var(--tw-bg-opacity,1))}.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\/20{background-color:rgba(22,163,74,.2)}.bg-neutral-900{--tw-bg-opacity:1;background-color:rgb(23 23 23/var(--tw-bg-opacity,1))}.bg-orange-400{--tw-bg-opacity:1;background-color:rgb(251 146 60/var(--tw-bg-opacity,1))}.bg-orange-500{--tw-bg-opacity:1;background-color:rgb(249 115 22/var(--tw-bg-opacity,1))}.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-purple-500\/10{background-color:rgba(168,85,247,.1)}.bg-purple-600{--tw-bg-opacity:1;background-color:rgb(147 51 234/var(--tw-bg-opacity,1))}.bg-red-200{--tw-bg-opacity:1;background-color:rgb(254 202 202/var(--tw-bg-opacity,1))}.bg-red-400{--tw-bg-opacity:1;background-color:rgb(248 113 113/var(--tw-bg-opacity,1))}.bg-red-500{--tw-bg-opacity:1;background-color:rgb(239 68 68/var(--tw-bg-opacity,1))}.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-red-900\/50{background-color:rgba(127,29,29,.5)}.bg-transparent{background-color:transparent}.bg-white{--tw-bg-opacity:1;background-color:rgb(255 255 255/var(--tw-bg-opacity,1))}.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,1))}.bg-yellow-500{--tw-bg-opacity:1;background-color:rgb(234 179 8/var(--tw-bg-opacity,1))}.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-gradient-to-b{background-image:linear-gradient(to bottom,var(--tw-gradient-stops))}.bg-gradient-to-r{background-image:linear-gradient(to right,var(--tw-gradient-stops))}.bg-gradient-to-t{background-image:linear-gradient(to top,var(--tw-gradient-stops))}.from-\[\#1f1f1f\]\/90{--tw-gradient-from:rgba(31,31,31,.9) var(--tw-gradient-from-position);--tw-gradient-to:rgba(31,31,31,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-transparent{--tw-gradient-from:transparent var(--tw-gradient-from-position);--tw-gradient-to:transparent var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),var(--tw-gradient-to)}.via-zinc-700{--tw-gradient-to:rgba(63,63,70,0) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),#3f3f46 var(--tw-gradient-via-position),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-transparent{--tw-gradient-to:transparent 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-top:.25rem;padding-bottom:.25rem}.py-1\.5{padding-top:.375rem;padding-bottom:.375rem}.py-14{padding-top:3.5rem;padding-bottom:3.5rem}.py-2{padding-top:.5rem;padding-bottom:.5rem}.py-3{padding-top:.75rem;padding-bottom:.75rem}.py-4{padding-top:1rem;padding-bottom:1rem}.pr-2{padding-right:.5rem}.pt-6{padding-top:1.5rem}.text-left{text-align:left}.text-center{text-align:center}.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-\[3rem\]{font-size:3rem}.text-base{font-size:1rem;line-height:1.5rem}.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-snug{line-height:1.375}.leading-tight{line-height:1.25}.text-black{--tw-text-opacity:1;color:rgb(0 0 0/var(--tw-text-opacity,1))}.text-blue-200{--tw-text-opacity:1;color:rgb(191 219 254/var(--tw-text-opacity,1))}.text-blue-300{--tw-text-opacity:1;color:rgb(147 197 253/var(--tw-text-opacity,1))}.text-blue-400{--tw-text-opacity:1;color:rgb(96 165 250/var(--tw-text-opacity,1))}.text-blue-500{--tw-text-opacity:1;color:rgb(59 130 246/var(--tw-text-opacity,1))}.text-blue-600{--tw-text-opacity:1;color:rgb(37 99 235/var(--tw-text-opacity,1))}.text-cyan-300{--tw-text-opacity:1;color:rgb(103 232 249/var(--tw-text-opacity,1))}.text-cyan-400{--tw-text-opacity:1;color:rgb(34 211 238/var(--tw-text-opacity,1))}.text-gray-300{--tw-text-opacity:1;color:rgb(209 213 219/var(--tw-text-opacity,1))}.text-gray-400{--tw-text-opacity:1;color:rgb(156 163 175/var(--tw-text-opacity,1))}.text-gray-500{--tw-text-opacity:1;color:rgb(107 114 128/var(--tw-text-opacity,1))}.text-gray-600{--tw-text-opacity:1;color:rgb(75 85 99/var(--tw-text-opacity,1))}.text-gray-900{--tw-text-opacity:1;color:rgb(17 24 39/var(--tw-text-opacity,1))}.text-green-200{--tw-text-opacity:1;color:rgb(187 247 208/var(--tw-text-opacity,1))}.text-green-300{--tw-text-opacity:1;color:rgb(134 239 172/var(--tw-text-opacity,1))}.text-green-400{--tw-text-opacity:1;color:rgb(74 222 128/var(--tw-text-opacity,1))}.text-green-500{--tw-text-opacity:1;color:rgb(34 197 94/var(--tw-text-opacity,1))}.text-orange-200{--tw-text-opacity:1;color:rgb(254 215 170/var(--tw-text-opacity,1))}.text-orange-300{--tw-text-opacity:1;color:rgb(253 186 116/var(--tw-text-opacity,1))}.text-orange-400{--tw-text-opacity:1;color:rgb(251 146 60/var(--tw-text-opacity,1))}.text-orange-500{--tw-text-opacity:1;color:rgb(249 115 22/var(--tw-text-opacity,1))}.text-purple-400{--tw-text-opacity:1;color:rgb(192 132 252/var(--tw-text-opacity,1))}.text-purple-500{--tw-text-opacity:1;color:rgb(168 85 247/var(--tw-text-opacity,1))}.text-red-200{--tw-text-opacity:1;color:rgb(254 202 202/var(--tw-text-opacity,1))}.text-red-300{--tw-text-opacity:1;color:rgb(252 165 165/var(--tw-text-opacity,1))}.text-red-400{--tw-text-opacity:1;color:rgb(248 113 113/var(--tw-text-opacity,1))}.text-red-500{--tw-text-opacity:1;color:rgb(239 68 68/var(--tw-text-opacity,1))}.text-white{--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity,1))}.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,1))}.text-yellow-300{--tw-text-opacity:1;color:rgb(253 224 71/var(--tw-text-opacity,1))}.text-yellow-400{--tw-text-opacity:1;color:rgb(250 204 21/var(--tw-text-opacity,1))}.text-yellow-600{--tw-text-opacity:1;color:rgb(202 138 4/var(--tw-text-opacity,1))}.text-zinc-600{--tw-text-opacity:1;color:rgb(82 82 91/var(--tw-text-opacity,1))}.placeholder-gray-500::-moz-placeholder{--tw-placeholder-opacity:1;color:rgb(107 114 128/var(--tw-placeholder-opacity,1))}.placeholder-gray-500::placeholder{--tw-placeholder-opacity:1;color:rgb(107 114 128/var(--tw-placeholder-opacity,1))}.opacity-0{opacity:0}.opacity-50{opacity:.5}.opacity-60{opacity:.6}.opacity-70{opacity:.7}.opacity-80{opacity:.8}.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-md{--tw-shadow:0 4px 6px -1px rgba(0,0,0,.1),0 2px 4px -2px rgba(0,0,0,.1);--tw-shadow-colored:0 4px 6px -1px var(--tw-shadow-color),0 2px 4px -2px 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)}.blur{--tw-blur:blur(8px)}.blur,.grayscale{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)}.grayscale{--tw-grayscale:grayscale(100%)}.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{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,-webkit-backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter,-webkit-backdrop-filter;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-all{transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-colors{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-opacity{transition-property:opacity;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-transform{transition-property:transform;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.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)}.ease-out{transition-timing-function:cubic-bezier(0,0,.2,1)}.\[checksum\:4\]{checksum:4}.\[data\:variable\]{data:variable}.\[name\:4\]{name:4}.\[size\:4\]{size:4}.hover\:bg-\[rgb\(20_20_20_\/30\%\)\]:hover{background-color:hsla(0,0%,8%,.3)}.hover\:bg-blue-600:hover{--tw-bg-opacity:1;background-color:rgb(37 99 235/var(--tw-bg-opacity,1))}.hover\:bg-blue-700:hover{--tw-bg-opacity:1;background-color:rgb(29 78 216/var(--tw-bg-opacity,1))}.hover\:bg-emerald-600:hover{--tw-bg-opacity:1;background-color:rgb(5 150 105/var(--tw-bg-opacity,1))}.hover\:bg-gray-500:hover{--tw-bg-opacity:1;background-color:rgb(107 114 128/var(--tw-bg-opacity,1))}.hover\:bg-gray-600\/30:hover{background-color:rgba(75,85,99,.3)}.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\/30:hover{background-color:rgba(22,163,74,.3)}.hover\:bg-green-600\/40:hover{background-color:rgba(22,163,74,.4)}.hover\:bg-orange-500\/20:hover{background-color:rgba(249,115,22,.2)}.hover\:bg-orange-500\/40:hover{background-color:rgba(249,115,22,.4)}.hover\:bg-orange-600:hover{--tw-bg-opacity:1;background-color:rgb(234 88 12/var(--tw-bg-opacity,1))}.hover\:bg-purple-500:hover{--tw-bg-opacity:1;background-color:rgb(168 85 247/var(--tw-bg-opacity,1))}.hover\:bg-purple-500\/20:hover{background-color:rgba(168,85,247,.2)}.hover\:bg-red-500\/20:hover{background-color:rgba(239,68,68,.2)}.hover\:bg-red-500\/30:hover{background-color:rgba(239,68,68,.3)}.hover\:bg-red-600:hover{--tw-bg-opacity:1;background-color:rgb(220 38 38/var(--tw-bg-opacity,1))}.hover\:bg-red-600\/40:hover{background-color:rgba(220,38,38,.4)}.hover\:bg-white\/30:hover{background-color:hsla(0,0%,100%,.3)}.hover\:bg-yellow-600\/40:hover{background-color:rgba(202,138,4,.4)}.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-gray-300:hover{--tw-text-opacity:1;color:rgb(209 213 219/var(--tw-text-opacity,1))}.hover\:text-gray-700:hover{--tw-text-opacity:1;color:rgb(55 65 81/var(--tw-text-opacity,1))}.hover\:text-gray-900:hover{--tw-text-opacity:1;color:rgb(17 24 39/var(--tw-text-opacity,1))}.hover\:text-green-300:hover{--tw-text-opacity:1;color:rgb(134 239 172/var(--tw-text-opacity,1))}.hover\:text-red-300:hover{--tw-text-opacity:1;color:rgb(252 165 165/var(--tw-text-opacity,1))}.hover\:text-white:hover{--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity,1))}.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\: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\:h-16{height:4rem}.sm\:w-10{width:2.5rem}.sm\:w-12{width:3rem}.sm\:w-\[24rem\]{width:24rem}.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-right:calc(.5rem*var(--tw-space-x-reverse));margin-left:calc(.5rem*(1 - var(--tw-space-x-reverse)))}.sm\:space-x-3>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-right:calc(.75rem*var(--tw-space-x-reverse));margin-left:calc(.75rem*(1 - var(--tw-space-x-reverse)))}.sm\:space-x-4>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-right:calc(1rem*var(--tw-space-x-reverse));margin-left:calc(1rem*(1 - var(--tw-space-x-reverse)))}.sm\:space-y-0>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(0px*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(0px*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-top:.375rem;padding-bottom:.375rem}.sm\:text-3xl{font-size:1.875rem;line-height:2.25rem}.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\:h-32{height:8rem}.md\:h-\[32rem\]{height:32rem}.md\:w-\[28rem\]{width:28rem}.md\:w-auto{width:auto}.md\:w-px{width:1px}.md\:flex-none{flex: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))}.md\:flex-row{flex-direction:row}.md\:flex-col{flex-direction:column}.md\:bg-gradient-to-b{background-image:linear-gradient(to bottom,var(--tw-gradient-stops))}}@media (min-width:1024px){.lg\:col-span-2{grid-column:span 2/span 2}.lg\:col-span-3{grid-column:span 3/span 3}.lg\:block{display:block}.lg\:w-\[32rem\]{width:32rem}.lg\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.lg\:grid-cols-5{grid-template-columns:repeat(5,minmax(0,1fr))}.lg\:px-8{padding-left:2rem;padding-right:2rem}}@media (prefers-color-scheme:dark){.dark\:border-gray-700{--tw-border-opacity:1;border-color:rgb(55 65 81/var(--tw-border-opacity,1))}.dark\:bg-gray-700{--tw-bg-opacity:1;background-color:rgb(55 65 81/var(--tw-bg-opacity,1))}.dark\:bg-gray-800{--tw-bg-opacity:1;background-color:rgb(31 41 55/var(--tw-bg-opacity,1))}.dark\:bg-gray-900{--tw-bg-opacity:1;background-color:rgb(17 24 39/var(--tw-bg-opacity,1))}.dark\:text-blue-400{--tw-text-opacity:1;color:rgb(96 165 250/var(--tw-text-opacity,1))}.dark\:text-gray-300{--tw-text-opacity:1;color:rgb(209 213 219/var(--tw-text-opacity,1))}.dark\:text-gray-400{--tw-text-opacity:1;color:rgb(156 163 175/var(--tw-text-opacity,1))}.dark\:hover\:text-white:hover,.dark\:text-white{--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity,1))}} \ No newline at end of file +*,: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: }/*! tailwindcss v3.4.17 | MIT License | https://tailwindcss.com*/*,:after,:before{box-sizing:border-box;border:0 solid #e5e7eb}:after,:before{--tw-content:""}:host,html{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;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;-webkit-tap-highlight-color:transparent}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}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-variation-settings:normal;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-feature-settings:inherit;font-variation-settings:inherit;font-size:100%;font-weight:inherit;line-height:inherit;letter-spacing:inherit;color: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{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}[role=button],button{cursor:pointer}:disabled{cursor:default}audio,canvas,embed,iframe,img,object,svg,video{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]:where(:not([hidden=until-found])){display:none}.\!container{width:100%!important}.container{width:100%}@media (min-width:640px){.\!container{max-width:640px!important}.container{max-width:640px}}@media (min-width:768px){.\!container{max-width:768px!important}.container{max-width:768px}}@media (min-width:1024px){.\!container{max-width:1024px!important}.container{max-width:1024px}}@media (min-width:1280px){.\!container{max-width:1280px!important}.container{max-width:1280px}}@media (min-width:1536px){.\!container{max-width:1536px!important}.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}.-right-2{right:-.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-4{left:1rem}.right-0{right:0}.right-3{right:.75rem}.right-4{right:1rem}.right-6{right:1.5rem}.top-0{top:0}.top-1\/2{top:50%}.top-4{top:1rem}.z-10{z-index:10}.z-20{z-index:20}.z-40{z-index:40}.z-50{z-index:50}.z-\[9999\]{z-index:9999}.mx-4{margin-left:1rem;margin-right:1rem}.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-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-12{margin-top:3rem}.mt-16{margin-top:4rem}.mt-2{margin-top:.5rem}.mt-20{margin-top:5rem}.mt-4{margin-top:1rem}.mt-6{margin-top:1.5rem}.mt-8{margin-top:2rem}.block{display:block}.inline{display:inline}.flex{display: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-2\.5{height:.625rem}.h-28{height:7rem}.h-4{height:1rem}.h-6{height:1.5rem}.h-8{height:2rem}.h-80{height:20rem}.h-96{height:24rem}.h-\[420px\]{height:420px}.h-auto{height:auto}.h-full{height:100%}.h-px{height:1px}.max-h-\[80vh\]{max-height:80vh}.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-4{width:1rem}.w-6{width:1.5rem}.w-72{width:18rem}.w-8{width:2rem}.w-\[20rem\]{width:20rem}.w-full{width:100%}.min-w-\[160px\]{min-width:160px}.min-w-\[240px\]{min-width:240px}.max-w-2xl{max-width:42rem}.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-none{max-width:none}.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-row{flex-direction:row}.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-12{gap:3rem}.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-right:calc(.25rem*var(--tw-space-x-reverse));margin-left:calc(.25rem*(1 - var(--tw-space-x-reverse)))}.space-x-2>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-right:calc(.5rem*var(--tw-space-x-reverse));margin-left:calc(.5rem*(1 - var(--tw-space-x-reverse)))}.space-x-3>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-right:calc(.75rem*var(--tw-space-x-reverse));margin-left:calc(.75rem*(1 - var(--tw-space-x-reverse)))}.space-x-4>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-right:calc(1rem*var(--tw-space-x-reverse));margin-left:calc(1rem*(1 - var(--tw-space-x-reverse)))}.space-y-1>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.25rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.25rem*var(--tw-space-y-reverse))}.space-y-2>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.5rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.5rem*var(--tw-space-y-reverse))}.space-y-3>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.75rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.75rem*var(--tw-space-y-reverse))}.space-y-4>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(1rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1rem*var(--tw-space-y-reverse))}.space-y-6>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(1.5rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1.5rem*var(--tw-space-y-reverse))}.space-y-8>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(2rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(2rem*var(--tw-space-y-reverse))}.self-center{align-self:center}.overflow-hidden{overflow:hidden}.overflow-x-auto{overflow-x:auto}.overflow-y-auto{overflow-y:auto}.scroll-smooth{scroll-behavior:smooth}.whitespace-normal{white-space:normal}.break-words{overflow-wrap:break-word}.rounded{border-radius:.25rem}.rounded-2xl{border-radius:1rem}.rounded-full{border-radius:9999px}.rounded-lg{border-radius:.5rem}.rounded-md{border-radius:.375rem}.rounded-xl{border-radius:.75rem}.border{border-width:1px}.border-b{border-bottom-width:1px}.border-t{border-top-width:1px}.border-blue-500\/20{border-color:rgba(59,130,246,.2)}.border-gray-200{--tw-border-opacity:1;border-color:rgb(229 231 235/var(--tw-border-opacity,1))}.border-gray-500\/10{border-color:hsla(220,9%,46%,.1)}.border-gray-500\/20{border-color:hsla(220,9%,46%,.2)}.border-gray-600{--tw-border-opacity:1;border-color:rgb(75 85 99/var(--tw-border-opacity,1))}.border-gray-600\/30{border-color:rgba(75,85,99,.3)}.border-gray-700\/30{border-color:rgba(55,65,81,.3)}.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\/20{border-color:rgba(249,115,22,.2)}.border-purple-500\/20{border-color:rgba(168,85,247,.2)}.border-purple-500\/30{border-color:rgba(168,85,247,.3)}.border-red-500\/20{border-color:rgba(239,68,68,.2)}.border-yellow-500\/20{border-color:rgba(234,179,8,.2)}.border-yellow-500\/30{border-color:rgba(234,179,8,.3)}.bg-\[rgb\(20_20_20_\/50\%\)\]{background-color:hsla(0,0%,8%,.5)}.bg-black\/20{background-color:rgba(0,0,0,.2)}.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-400{--tw-bg-opacity:1;background-color:rgb(96 165 250/var(--tw-bg-opacity,1))}.bg-blue-500{--tw-bg-opacity:1;background-color:rgb(59 130 246/var(--tw-bg-opacity,1))}.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,1))}.bg-emerald-500{--tw-bg-opacity:1;background-color:rgb(16 185 129/var(--tw-bg-opacity,1))}.bg-gray-200{--tw-bg-opacity:1;background-color:rgb(229 231 235/var(--tw-bg-opacity,1))}.bg-gray-50{--tw-bg-opacity:1;background-color:rgb(249 250 251/var(--tw-bg-opacity,1))}.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,1))}.bg-gray-600\/20{background-color:rgba(75,85,99,.2)}.bg-gray-700{--tw-bg-opacity:1;background-color:rgb(55 65 81/var(--tw-bg-opacity,1))}.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,1))}.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{--tw-bg-opacity:1;background-color:rgb(17 24 39/var(--tw-bg-opacity,1))}.bg-gray-900\/30{background-color:rgba(17,24,39,.3)}.bg-green-200{--tw-bg-opacity:1;background-color:rgb(187 247 208/var(--tw-bg-opacity,1))}.bg-green-400{--tw-bg-opacity:1;background-color:rgb(74 222 128/var(--tw-bg-opacity,1))}.bg-green-400\/20{background-color:rgba(74,222,128,.2)}.bg-green-500{--tw-bg-opacity:1;background-color:rgb(34 197 94/var(--tw-bg-opacity,1))}.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\/20{background-color:rgba(22,163,74,.2)}.bg-neutral-900{--tw-bg-opacity:1;background-color:rgb(23 23 23/var(--tw-bg-opacity,1))}.bg-orange-400{--tw-bg-opacity:1;background-color:rgb(251 146 60/var(--tw-bg-opacity,1))}.bg-orange-500{--tw-bg-opacity:1;background-color:rgb(249 115 22/var(--tw-bg-opacity,1))}.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-purple-500\/10{background-color:rgba(168,85,247,.1)}.bg-purple-600{--tw-bg-opacity:1;background-color:rgb(147 51 234/var(--tw-bg-opacity,1))}.bg-red-200{--tw-bg-opacity:1;background-color:rgb(254 202 202/var(--tw-bg-opacity,1))}.bg-red-400{--tw-bg-opacity:1;background-color:rgb(248 113 113/var(--tw-bg-opacity,1))}.bg-red-500{--tw-bg-opacity:1;background-color:rgb(239 68 68/var(--tw-bg-opacity,1))}.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-red-900\/50{background-color:rgba(127,29,29,.5)}.bg-transparent{background-color:transparent}.bg-white{--tw-bg-opacity:1;background-color:rgb(255 255 255/var(--tw-bg-opacity,1))}.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,1))}.bg-yellow-500{--tw-bg-opacity:1;background-color:rgb(234 179 8/var(--tw-bg-opacity,1))}.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-gradient-to-b{background-image:linear-gradient(to bottom,var(--tw-gradient-stops))}.bg-gradient-to-r{background-image:linear-gradient(to right,var(--tw-gradient-stops))}.bg-gradient-to-t{background-image:linear-gradient(to top,var(--tw-gradient-stops))}.from-\[\#1f1f1f\]\/90{--tw-gradient-from:rgba(31,31,31,.9) var(--tw-gradient-from-position);--tw-gradient-to:rgba(31,31,31,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-transparent{--tw-gradient-from:transparent var(--tw-gradient-from-position);--tw-gradient-to:transparent var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),var(--tw-gradient-to)}.via-zinc-700{--tw-gradient-to:rgba(63,63,70,0) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),#3f3f46 var(--tw-gradient-via-position),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-transparent{--tw-gradient-to:transparent 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-top:.25rem;padding-bottom:.25rem}.py-1\.5{padding-top:.375rem;padding-bottom:.375rem}.py-14{padding-top:3.5rem;padding-bottom:3.5rem}.py-2{padding-top:.5rem;padding-bottom:.5rem}.py-3{padding-top:.75rem;padding-bottom:.75rem}.py-4{padding-top:1rem;padding-bottom:1rem}.pr-2{padding-right:.5rem}.pt-6{padding-top:1.5rem}.text-left{text-align:left}.text-center{text-align:center}.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-\[3rem\]{font-size:3rem}.text-base{font-size:1rem;line-height:1.5rem}.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}.uppercase{text-transform:uppercase}.lowercase{text-transform:lowercase}.leading-relaxed{line-height:1.625}.leading-snug{line-height:1.375}.leading-tight{line-height:1.25}.tracking-\[0\.3em\]{letter-spacing:.3em}.text-black{--tw-text-opacity:1;color:rgb(0 0 0/var(--tw-text-opacity,1))}.text-blue-200{--tw-text-opacity:1;color:rgb(191 219 254/var(--tw-text-opacity,1))}.text-blue-300{--tw-text-opacity:1;color:rgb(147 197 253/var(--tw-text-opacity,1))}.text-blue-400{--tw-text-opacity:1;color:rgb(96 165 250/var(--tw-text-opacity,1))}.text-blue-500{--tw-text-opacity:1;color:rgb(59 130 246/var(--tw-text-opacity,1))}.text-blue-600{--tw-text-opacity:1;color:rgb(37 99 235/var(--tw-text-opacity,1))}.text-cyan-300{--tw-text-opacity:1;color:rgb(103 232 249/var(--tw-text-opacity,1))}.text-cyan-400{--tw-text-opacity:1;color:rgb(34 211 238/var(--tw-text-opacity,1))}.text-gray-300{--tw-text-opacity:1;color:rgb(209 213 219/var(--tw-text-opacity,1))}.text-gray-400{--tw-text-opacity:1;color:rgb(156 163 175/var(--tw-text-opacity,1))}.text-gray-500{--tw-text-opacity:1;color:rgb(107 114 128/var(--tw-text-opacity,1))}.text-gray-600{--tw-text-opacity:1;color:rgb(75 85 99/var(--tw-text-opacity,1))}.text-gray-900{--tw-text-opacity:1;color:rgb(17 24 39/var(--tw-text-opacity,1))}.text-green-200{--tw-text-opacity:1;color:rgb(187 247 208/var(--tw-text-opacity,1))}.text-green-300{--tw-text-opacity:1;color:rgb(134 239 172/var(--tw-text-opacity,1))}.text-green-400{--tw-text-opacity:1;color:rgb(74 222 128/var(--tw-text-opacity,1))}.text-green-500{--tw-text-opacity:1;color:rgb(34 197 94/var(--tw-text-opacity,1))}.text-orange-200{--tw-text-opacity:1;color:rgb(254 215 170/var(--tw-text-opacity,1))}.text-orange-300{--tw-text-opacity:1;color:rgb(253 186 116/var(--tw-text-opacity,1))}.text-orange-400{--tw-text-opacity:1;color:rgb(251 146 60/var(--tw-text-opacity,1))}.text-orange-500{--tw-text-opacity:1;color:rgb(249 115 22/var(--tw-text-opacity,1))}.text-purple-400{--tw-text-opacity:1;color:rgb(192 132 252/var(--tw-text-opacity,1))}.text-purple-500{--tw-text-opacity:1;color:rgb(168 85 247/var(--tw-text-opacity,1))}.text-red-200{--tw-text-opacity:1;color:rgb(254 202 202/var(--tw-text-opacity,1))}.text-red-300{--tw-text-opacity:1;color:rgb(252 165 165/var(--tw-text-opacity,1))}.text-red-400{--tw-text-opacity:1;color:rgb(248 113 113/var(--tw-text-opacity,1))}.text-red-500{--tw-text-opacity:1;color:rgb(239 68 68/var(--tw-text-opacity,1))}.text-white{--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity,1))}.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,1))}.text-yellow-300{--tw-text-opacity:1;color:rgb(253 224 71/var(--tw-text-opacity,1))}.text-yellow-400{--tw-text-opacity:1;color:rgb(250 204 21/var(--tw-text-opacity,1))}.text-yellow-600{--tw-text-opacity:1;color:rgb(202 138 4/var(--tw-text-opacity,1))}.text-zinc-600{--tw-text-opacity:1;color:rgb(82 82 91/var(--tw-text-opacity,1))}.placeholder-gray-500::-moz-placeholder{--tw-placeholder-opacity:1;color:rgb(107 114 128/var(--tw-placeholder-opacity,1))}.placeholder-gray-500::placeholder{--tw-placeholder-opacity:1;color:rgb(107 114 128/var(--tw-placeholder-opacity,1))}.opacity-0{opacity:0}.opacity-50{opacity:.5}.opacity-60{opacity:.6}.opacity-70{opacity:.7}.opacity-80{opacity:.8}.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-md{--tw-shadow:0 4px 6px -1px rgba(0,0,0,.1),0 2px 4px -2px rgba(0,0,0,.1);--tw-shadow-colored:0 4px 6px -1px var(--tw-shadow-color),0 2px 4px -2px 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)}.blur{--tw-blur:blur(8px)}.blur,.grayscale{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)}.grayscale{--tw-grayscale:grayscale(100%)}.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{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,-webkit-backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter,-webkit-backdrop-filter;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-all{transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-colors{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-opacity{transition-property:opacity;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-transform{transition-property:transform;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.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)}.ease-out{transition-timing-function:cubic-bezier(0,0,.2,1)}.\[checksum\:4\]{checksum:4}.\[data\:variable\]{data:variable}.\[name\:4\]{name:4}.\[size\:4\]{size:4}.hover\:bg-\[rgb\(20_20_20_\/30\%\)\]:hover{background-color:hsla(0,0%,8%,.3)}.hover\:bg-blue-600:hover{--tw-bg-opacity:1;background-color:rgb(37 99 235/var(--tw-bg-opacity,1))}.hover\:bg-blue-700:hover{--tw-bg-opacity:1;background-color:rgb(29 78 216/var(--tw-bg-opacity,1))}.hover\:bg-emerald-600:hover{--tw-bg-opacity:1;background-color:rgb(5 150 105/var(--tw-bg-opacity,1))}.hover\:bg-gray-500:hover{--tw-bg-opacity:1;background-color:rgb(107 114 128/var(--tw-bg-opacity,1))}.hover\:bg-gray-600\/30:hover{background-color:rgba(75,85,99,.3)}.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\/30:hover{background-color:rgba(22,163,74,.3)}.hover\:bg-green-600\/40:hover{background-color:rgba(22,163,74,.4)}.hover\:bg-orange-500\/20:hover{background-color:rgba(249,115,22,.2)}.hover\:bg-orange-500\/40:hover{background-color:rgba(249,115,22,.4)}.hover\:bg-orange-600:hover{--tw-bg-opacity:1;background-color:rgb(234 88 12/var(--tw-bg-opacity,1))}.hover\:bg-purple-500:hover{--tw-bg-opacity:1;background-color:rgb(168 85 247/var(--tw-bg-opacity,1))}.hover\:bg-purple-500\/20:hover{background-color:rgba(168,85,247,.2)}.hover\:bg-red-500\/20:hover{background-color:rgba(239,68,68,.2)}.hover\:bg-red-500\/30:hover{background-color:rgba(239,68,68,.3)}.hover\:bg-red-600:hover{--tw-bg-opacity:1;background-color:rgb(220 38 38/var(--tw-bg-opacity,1))}.hover\:bg-red-600\/40:hover{background-color:rgba(220,38,38,.4)}.hover\:bg-white\/30:hover{background-color:hsla(0,0%,100%,.3)}.hover\:bg-yellow-600\/40:hover{background-color:rgba(202,138,4,.4)}.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-gray-300:hover{--tw-text-opacity:1;color:rgb(209 213 219/var(--tw-text-opacity,1))}.hover\:text-gray-700:hover{--tw-text-opacity:1;color:rgb(55 65 81/var(--tw-text-opacity,1))}.hover\:text-gray-900:hover{--tw-text-opacity:1;color:rgb(17 24 39/var(--tw-text-opacity,1))}.hover\:text-green-300:hover{--tw-text-opacity:1;color:rgb(134 239 172/var(--tw-text-opacity,1))}.hover\:text-red-300:hover{--tw-text-opacity:1;color:rgb(252 165 165/var(--tw-text-opacity,1))}.hover\:text-white:hover{--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity,1))}.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-400:focus{--tw-border-opacity:1;border-color:rgb(192 132 252/var(--tw-border-opacity,1))}.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\:opacity-50:disabled{opacity:.5}.disabled\:opacity-60:disabled{opacity:.6}.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\:h-16{height:4rem}.sm\:w-10{width:2.5rem}.sm\:w-12{width:3rem}.sm\:w-\[24rem\]{width:24rem}.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-right:calc(.5rem*var(--tw-space-x-reverse));margin-left:calc(.5rem*(1 - var(--tw-space-x-reverse)))}.sm\:space-x-3>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-right:calc(.75rem*var(--tw-space-x-reverse));margin-left:calc(.75rem*(1 - var(--tw-space-x-reverse)))}.sm\:space-x-4>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-right:calc(1rem*var(--tw-space-x-reverse));margin-left:calc(1rem*(1 - var(--tw-space-x-reverse)))}.sm\:space-y-0>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(0px*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(0px*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-top:.375rem;padding-bottom:.375rem}.sm\:text-3xl{font-size:1.875rem;line-height:2.25rem}.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\:h-32{height:8rem}.md\:h-\[32rem\]{height:32rem}.md\:w-\[28rem\]{width:28rem}.md\:w-auto{width:auto}.md\:w-px{width:1px}.md\:flex-none{flex: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))}.md\:flex-row{flex-direction:row}.md\:flex-col{flex-direction:column}.md\:bg-gradient-to-b{background-image:linear-gradient(to bottom,var(--tw-gradient-stops))}}@media (min-width:1024px){.lg\:col-span-2{grid-column:span 2/span 2}.lg\:col-span-3{grid-column:span 3/span 3}.lg\:block{display:block}.lg\:w-\[32rem\]{width:32rem}.lg\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.lg\:grid-cols-5{grid-template-columns:repeat(5,minmax(0,1fr))}.lg\:px-8{padding-left:2rem;padding-right:2rem}}@media (prefers-color-scheme:dark){.dark\:border-gray-700{--tw-border-opacity:1;border-color:rgb(55 65 81/var(--tw-border-opacity,1))}.dark\:bg-gray-700{--tw-bg-opacity:1;background-color:rgb(55 65 81/var(--tw-bg-opacity,1))}.dark\:bg-gray-800{--tw-bg-opacity:1;background-color:rgb(31 41 55/var(--tw-bg-opacity,1))}.dark\:bg-gray-900{--tw-bg-opacity:1;background-color:rgb(17 24 39/var(--tw-bg-opacity,1))}.dark\:text-blue-400{--tw-text-opacity:1;color:rgb(96 165 250/var(--tw-text-opacity,1))}.dark\:text-gray-300{--tw-text-opacity:1;color:rgb(209 213 219/var(--tw-text-opacity,1))}.dark\:text-gray-400{--tw-text-opacity:1;color:rgb(156 163 175/var(--tw-text-opacity,1))}.dark\:hover\:text-white:hover,.dark\:text-white{--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity,1))}} \ No newline at end of file diff --git a/dist/app-boot.js b/dist/app-boot.js index 613bce4..bdb1bbe 100644 --- a/dist/app-boot.js +++ b/dist/app-boot.js @@ -2998,12 +2998,13 @@ var SecureMemoryManager = class { } }; var EnhancedSecureFileTransfer = class { - constructor(webrtcManager, onProgress, onComplete, onError, onFileReceived) { + constructor(webrtcManager, onProgress, onComplete, onError, onFileReceived, onIncomingFileRequest) { this.webrtcManager = webrtcManager; this.onProgress = onProgress; this.onComplete = onComplete; this.onError = onError; this.onFileReceived = onFileReceived; + this.onIncomingFileRequest = onIncomingFileRequest; if (!webrtcManager) { throw new Error("webrtcManager is required for EnhancedSecureFileTransfer"); } @@ -3018,90 +3019,72 @@ var EnhancedSecureFileTransfer = class { 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" - ], + pdf: { + extensions: [".pdf"], + mimeTypes: ["application/pdf"], maxSize: 50 * 1024 * 1024, - // 50 MB - category: "Documents", - description: "PDF, DOC, TXT, MD, RTF, ODT" + category: "PDF", + description: "PDF" + }, + text: { + extensions: [".txt"], + mimeTypes: ["text/plain"], + maxSize: 10 * 1024 * 1024, + category: "Plain text", + description: "TXT" }, images: { - extensions: [".jpg", ".jpeg", ".png", ".gif", ".webp", ".bmp", ".svg", ".ico"], + extensions: [".jpg", ".jpeg", ".png", ".gif", ".webp", ".bmp", ".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" + description: "JPG, JPEG, PNG, GIF, WEBP, BMP, 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" - ], + extensions: [".zip"], + mimeTypes: ["application/zip"], 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" + description: "ZIP" } }; + this.BLOCKED_EXTENSIONS = /* @__PURE__ */ new Set([ + ".exe", + ".bat", + ".cmd", + ".sh", + ".js", + ".msi", + ".dmg", + ".app", + ".jar", + ".scr", + ".ps1", + ".vbs", + ".html", + ".svg" + ]); this.activeTransfers = /* @__PURE__ */ new Map(); this.receivingTransfers = /* @__PURE__ */ new Map(); + this.pendingIncomingTransfers = /* @__PURE__ */ new Map(); this.transferQueue = []; this.pendingChunks = /* @__PURE__ */ new Map(); + this.incomingOfferLimiter = new RateLimiter(5, 6e4); + this.MAX_PENDING_INCOMING_TRANSFERS = 3; this.sessionKeys = /* @__PURE__ */ new Map(); this.processedChunks = /* @__PURE__ */ new Set(); this.transferNonces = /* @__PURE__ */ new Map(); this.receivedFileBuffers = /* @__PURE__ */ new Map(); + this.MAX_RETAINED_RECEIVED_FILE_BUFFERS = 3; this.setupFileMessageHandlers(); if (this.webrtcManager) { this.webrtcManager.fileTransferSystem = this; @@ -3111,21 +3094,14 @@ var EnhancedSecureFileTransfer = class { // FILE TYPE VALIDATION SYSTEM // ============================================ getFileType(file) { - const fileName = file.name.toLowerCase(); - const fileExtension = fileName.substring(fileName.lastIndexOf(".")); - const mimeType = file.type.toLowerCase(); + const fileName = String(file?.name || "").toLowerCase(); + const extensionIndex = fileName.lastIndexOf("."); + const fileExtension = extensionIndex >= 0 ? fileName.substring(extensionIndex) : ""; + const mimeType = String(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)) { + const extensionAllowed = typeConfig.extensions.includes(fileExtension); + const mimeAllowed = typeConfig.mimeTypes.includes(mimeType); + if (extensionAllowed && mimeAllowed) { return { type: typeKey, category: typeConfig.category, @@ -3135,23 +3111,37 @@ var EnhancedSecureFileTransfer = class { }; } } - const generalConfig = this.FILE_TYPE_RESTRICTIONS.general; return { - type: "general", - category: generalConfig.category, - description: generalConfig.description, - maxSize: generalConfig.maxSize, - allowed: true + type: "blocked", + category: "Unsupported", + description: "Allowed: JPG, JPEG, PNG, GIF, WEBP, BMP, ICO, PDF, TXT, ZIP", + maxSize: this.MAX_FILE_SIZE, + allowed: false, + extension: fileExtension, + mimeType }; } validateFile(file) { const fileType = this.getFileType(file); const errors = []; + const fileName = String(file?.name || ""); + const lowerName = fileName.toLowerCase(); + const extensionIndex = lowerName.lastIndexOf("."); + const fileExtension = extensionIndex >= 0 ? lowerName.substring(extensionIndex) : ""; + const mimeType = String(file?.type || "").toLowerCase(); + if (this.BLOCKED_EXTENSIONS.has(fileExtension)) { + errors.push(`File rejected: ${fileExtension} files are not allowed for security reasons.`); + } + if (!mimeType) { + errors.push("File rejected: missing MIME type is unsafe."); + } 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 (mimeType && !this.BLOCKED_EXTENSIONS.has(fileExtension)) { + errors.push(`File rejected: extension and MIME type must match an allowed type. 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)})`); @@ -3164,6 +3154,31 @@ var EnhancedSecureFileTransfer = class { formattedSize: this.formatFileSize(file.size) }; } + normalizeDisplayFileName(fileName) { + return String(fileName || "").normalize("NFKC").replace(/[\u0000-\u001F\u007F]/g, "").replace(/[\\/]+/g, "_").trim().slice(0, 255); + } + validateIncomingMetadata(metadata) { + const errors = []; + if (!metadata || typeof metadata !== "object") errors.push("Invalid file transfer metadata"); + if (!metadata?.fileId || typeof metadata.fileId !== "string") errors.push("Invalid file id"); + if (!Number.isSafeInteger(metadata?.fileSize) || metadata.fileSize <= 0) errors.push("Invalid file size"); + if (!Number.isSafeInteger(metadata?.totalChunks) || metadata.totalChunks <= 0) errors.push("Invalid chunk count"); + if (!Number.isSafeInteger(metadata?.chunkSize) || metadata.chunkSize <= 0 || metadata.chunkSize > this.CHUNK_SIZE) errors.push("Invalid chunk size"); + if (!Array.isArray(metadata?.salt) || metadata.salt.length !== 32) errors.push("Invalid salt"); + const rawName = typeof metadata?.fileName === "string" ? metadata.fileName : ""; + const displayName = this.normalizeDisplayFileName(rawName); + const hasDangerousName = !rawName || rawName !== rawName.trim() || /[\u0000-\u001F\u007F]/.test(rawName) || /[\\/]/.test(rawName) || rawName === "." || rawName === ".." || displayName.length === 0; + if (hasDangerousName) errors.push("Dangerous file name"); + if (errors.length === 0) { + const validation = this.validateFile({ + name: displayName, + size: metadata.fileSize, + type: metadata.fileType || "application/octet-stream" + }); + if (!validation.isValid) errors.push(...validation.errors); + } + return { isValid: errors.length === 0, errors, displayName }; + } formatFileSize(bytes) { if (bytes === 0) return "0 B"; const k = 1024; @@ -3174,7 +3189,6 @@ var EnhancedSecureFileTransfer = class { 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, @@ -3511,7 +3525,16 @@ var EnhancedSecureFileTransfer = class { }; this.activeTransfers.set(fileId, transferState); this.transferNonces.set(fileId, 0); + const consentPromise = new Promise((resolve, reject) => { + transferState.resolveConsent = resolve; + transferState.rejectConsent = reject; + transferState.consentTimeout = setTimeout(() => { + transferState.consentTimeout = null; + reject(new Error("Transfer timeout")); + }, 3e4); + }); await this.sendFileMetadata(transferState); + await consentPromise; await this.startChunkTransmission(transferState); return fileId; } catch (error) { @@ -3695,9 +3718,12 @@ var EnhancedSecureFileTransfer = class { // ============================================ async handleFileTransferStart(metadata) { try { - if (!metadata.fileId || !metadata.fileName || !metadata.fileSize) { - throw new Error("Invalid file transfer metadata"); + const clientId = this.getClientIdentifier(); + if (!this.incomingOfferLimiter.isAllowed(clientId)) { + throw new Error("Incoming file request rate limit exceeded"); } + const validation = this.validateIncomingMetadata(metadata); + if (!validation.isValid) throw new Error(validation.errors.join(". ")); if (metadata.signature && this.verificationKey) { try { const isValid = await FileMetadataSigner.verifyFileMetadata( @@ -3720,43 +3746,27 @@ var EnhancedSecureFileTransfer = class { throw new Error("File metadata verification failed"); } } - if (this.receivingTransfers.has(metadata.fileId)) { + if (this.receivingTransfers.has(metadata.fileId) || this.pendingIncomingTransfers.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" + if (this.pendingIncomingTransfers.size >= this.MAX_PENDING_INCOMING_TRANSFERS) { + throw new Error("Too many pending incoming file requests"); + } + const pendingMetadata = { + ...metadata, + fileName: validation.displayName, + receivedAt: Date.now() }; - 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); + this.pendingIncomingTransfers.set(metadata.fileId, pendingMetadata); + if (typeof this.onIncomingFileRequest === "function") { + this.onIncomingFileRequest({ + fileId: pendingMetadata.fileId, + fileName: pendingMetadata.fileName, + fileSize: pendingMetadata.fileSize, + mimeType: pendingMetadata.fileType || "application/octet-stream" + }); + } else { + await this.rejectIncomingFile(metadata.fileId, "User consent unavailable"); } } catch (error) { const safeError = SecurityErrorHandler.sanitizeError(error); @@ -3778,10 +3788,6 @@ var EnhancedSecureFileTransfer = class { 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(); @@ -3876,14 +3882,20 @@ var EnhancedSecureFileTransfer = class { const fileBlob = new Blob([fileBuffer], { type: receivingState.fileType }); receivingState.endTime = Date.now(); receivingState.status = "completed"; - this.receivedFileBuffers.set(receivingState.fileId, { + this._storeReceivedFileBuffer(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 getBlob = async () => { + const blob = await this.getBlob(receivingState.fileId); + if (!blob) { + throw new Error("This file is no longer available for download."); + } + return blob; + }; const getObjectURL = async () => { const blob = await getBlob(); return URL.createObjectURL(blob); @@ -3954,8 +3966,18 @@ var EnhancedSecureFileTransfer = class { } if (response.accepted) { transferState.status = "accepted"; + if (transferState.consentTimeout) clearTimeout(transferState.consentTimeout); + transferState.consentTimeout = null; + transferState.resolveConsent?.(); + transferState.resolveConsent = null; + transferState.rejectConsent = null; } else { transferState.status = "rejected"; + if (transferState.consentTimeout) clearTimeout(transferState.consentTimeout); + transferState.consentTimeout = null; + transferState.rejectConsent?.(new Error(response.error || "Transfer rejected")); + transferState.rejectConsent = null; + transferState.resolveConsent = null; if (this.onError) { this.onError(`Transfer rejected: ${response.error || "Unknown reason"}`); } @@ -4048,6 +4070,45 @@ var EnhancedSecureFileTransfer = class { startTime: transfer.startTime })); } + getPendingIncomingTransfers() { + return Array.from(this.pendingIncomingTransfers.values()).map((transfer) => ({ + fileId: transfer.fileId, + fileName: transfer.fileName, + fileSize: transfer.fileSize, + mimeType: transfer.fileType || "application/octet-stream", + receivedAt: transfer.receivedAt + })); + } + async acceptIncomingFile(fileId) { + const metadata = this.pendingIncomingTransfers.get(fileId); + if (!metadata) return false; + const sessionKey = await this.deriveFileSessionKeyFromSalt(fileId, metadata.salt); + this.receivingTransfers.set(fileId, { + 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.pendingIncomingTransfers.delete(fileId); + await this.sendSecureMessage({ type: "file_transfer_response", fileId, accepted: true, timestamp: Date.now() }); + return true; + } + async rejectIncomingFile(fileId, error = "Rejected by user") { + if (!this.pendingIncomingTransfers.has(fileId)) return false; + this.pendingIncomingTransfers.delete(fileId); + await this.sendSecureMessage({ type: "file_transfer_response", fileId, accepted: false, error, timestamp: Date.now() }); + return true; + } cancelTransfer(fileId) { try { if (this.activeTransfers.has(fileId)) { @@ -4065,6 +4126,18 @@ var EnhancedSecureFileTransfer = class { } } cleanupTransfer(fileId) { + const transferState = this.activeTransfers.get(fileId); + if (transferState) { + if (transferState.consentTimeout) { + clearTimeout(transferState.consentTimeout); + transferState.consentTimeout = null; + } + if (transferState.rejectConsent) { + transferState.rejectConsent(new Error("Transfer cancelled during cleanup or disconnect")); + transferState.rejectConsent = null; + transferState.resolveConsent = null; + } + } this.activeTransfers.delete(fileId); this.sessionKeys.delete(fileId); this.transferNonces.delete(fileId); @@ -4074,6 +4147,25 @@ var EnhancedSecureFileTransfer = class { } } } + _storeReceivedFileBuffer(fileId, entry) { + this.receivedFileBuffers.set(fileId, entry); + while (this.receivedFileBuffers.size > this.MAX_RETAINED_RECEIVED_FILE_BUFFERS) { + const oldestFileId = this.receivedFileBuffers.keys().next().value; + this._discardReceivedFileBuffer(oldestFileId); + } + } + _discardReceivedFileBuffer(fileId) { + const fileBuffer = this.receivedFileBuffers.get(fileId); + if (!fileBuffer) return; + try { + if (fileBuffer.buffer) { + SecureMemoryManager.secureWipe(fileBuffer.buffer); + new Uint8Array(fileBuffer.buffer).fill(0); + } + } catch (_) { + } + this.receivedFileBuffers.delete(fileId); + } // ✅ УЛУЧШЕННАЯ безопасная очистка памяти для предотвращения use-after-free cleanupReceivingTransfer(fileId) { try { @@ -4248,12 +4340,16 @@ var EnhancedSecureFileTransfer = class { this.rateLimiter.requests.clear(); } this.pendingChunks.clear(); + this.pendingIncomingTransfers.clear(); this.activeTransfers.clear(); this.receivingTransfers.clear(); this.transferQueue.length = 0; this.sessionKeys.clear(); this.transferNonces.clear(); this.processedChunks.clear(); + for (const fileId of Array.from(this.receivedFileBuffers.keys())) { + this._discardReceivedFileBuffer(fileId); + } this.clearKeys(); } // ============================================ @@ -4535,6 +4631,8 @@ var EnhancedSecureWebRTCManager = class _EnhancedSecureWebRTCManager { FILE_MESSAGE: "FILE_MESSAGE_FILTERED", SYSTEM_MESSAGE: "SYSTEM_MESSAGE_FILTERED" }; + static PROTOCOL_VERSION = "4.1"; + static MAX_SAS_ATTEMPTS = 3; // Static debug flag instead of this._debugMode static DEBUG_MODE = true; // Set to true during development, false in production @@ -4571,8 +4669,19 @@ var EnhancedSecureWebRTCManager = class _EnhancedSecureWebRTCManager { addNoise: config.antiFingerprinting?.addNoise ?? true, maskPatterns: config.antiFingerprinting?.maskPatterns ?? false, useRandomHeaders: config.antiFingerprinting?.useRandomHeaders ?? false + }, + webrtc: { + relayOnly: config.webrtc?.relayOnly ?? false, + iceServers: config.webrtc?.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" } + ] } }; + this._ipLeakWarningShown = false; this._initializeSecureLogging(); this._setupOwnLogger(); this._setupProductionLogging(); @@ -4629,6 +4738,7 @@ var EnhancedSecureWebRTCManager = class _EnhancedSecureWebRTCManager { this.verificationCode = null; this.pendingSASCode = null; this.isVerified = false; + this.sasValidationAttempts = 0; this.processedMessageIds = /* @__PURE__ */ new Set(); this.localVerificationConfirmed = false; this.remoteVerificationConfirmed = false; @@ -4650,6 +4760,10 @@ var EnhancedSecureWebRTCManager = class _EnhancedSecureWebRTCManager { this.peerPublicKey = null; this.rateLimiterId = null; this.intentionalDisconnect = false; + this._sessionAlive = true; + this._fileTransferInitRetryTimers = /* @__PURE__ */ new Set(); + this._peerDisconnectCleanupTimer = null; + this._logCleanupInterval = null; this.lastCleanupTime = Date.now(); this._resetNotificationFlags(); this.verificationInitiationSent = false; @@ -5177,6 +5291,15 @@ var EnhancedSecureWebRTCManager = class _EnhancedSecureWebRTCManager { this._secureLog("info", "\u{1F527} Unified maintenance scheduler initialized (5-minute cycle)"); this._activeTimers = /* @__PURE__ */ new Set([this._maintenanceScheduler]); } + _trackActiveTimer(timer) { + if (!timer) return timer; + if (!this._activeTimers) this._activeTimers = /* @__PURE__ */ new Set(); + this._activeTimers.add(timer); + return timer; + } + _untrackActiveTimer(timer) { + if (timer && this._activeTimers) this._activeTimers.delete(timer); + } /** * Execute all maintenance tasks in a single cycle */ @@ -7126,9 +7249,9 @@ var EnhancedSecureWebRTCManager = class _EnhancedSecureWebRTCManager { return; } this._startSecurityMonitoring(); - setInterval(() => { + this._logCleanupInterval = this._trackActiveTimer(setInterval(() => { this._cleanupLogs(); - }, 3e5); + }, 3e5)); this._secureLog("info", "\u2705 Secure WebRTC Manager initialization completed"); this._secureLog("info", "\u{1F512} Global exposure protection: Monitoring only, no automatic removal"); } @@ -7382,11 +7505,7 @@ var EnhancedSecureWebRTCManager = class _EnhancedSecureWebRTCManager { ); const dv = new DataView(bits); const n = (dv.getUint32(0) ^ dv.getUint32(4)) >>> 0; - let sasValue; - do { - sasValue = crypto.getRandomValues(new Uint32Array(1))[0]; - } while (sasValue >= 4294967296 - 4294967296 % 1e7); - const sasCode = String(sasValue % 1e7).padStart(7, "0"); + const sasCode = String(n % 1e7).padStart(7, "0"); this._secureLog("info", "SAS code computed successfully", { localFP: localFP.substring(0, 16) + "...", remoteFP: remoteFP.substring(0, 16) + "...", @@ -8016,6 +8135,9 @@ var EnhancedSecureWebRTCManager = class _EnhancedSecureWebRTCManager { } initializeFileTransfer() { try { + if (this._sessionAlive === false) { + return; + } this._secureLog("info", "\u{1F527} Initializing Enhanced Secure File Transfer system..."); if (this.fileTransferSystem) { this._secureLog("info", "\u2705 File transfer system already initialized"); @@ -8035,7 +8157,7 @@ var EnhancedSecureWebRTCManager = class _EnhancedSecureWebRTCManager { } if (!this.isVerified) { this._secureLog("warn", "\u26A0\uFE0F Connection not verified yet, deferring file transfer initialization"); - setTimeout(() => this.initializeFileTransfer(), 500); + this._scheduleFileTransferInitRetry(500); return; } if (this.fileTransferSystem) { @@ -8045,7 +8167,7 @@ var EnhancedSecureWebRTCManager = class _EnhancedSecureWebRTCManager { } if (!this.encryptionKey || !this.macKey) { this._secureLog("warn", "\u26A0\uFE0F Encryption keys not ready, deferring file transfer initialization"); - setTimeout(() => this.initializeFileTransfer(), 1e3); + this._scheduleFileTransferInitRetry(1e3); return; } const safeOnComplete = (summary) => { @@ -8063,7 +8185,8 @@ var EnhancedSecureWebRTCManager = class _EnhancedSecureWebRTCManager { this.onFileProgress || null, safeOnComplete, this.onFileError || null, - this.onFileReceived || null + this.onFileReceived || null, + this.onIncomingFileRequest || null ); this._fileTransferActive = true; this._secureLog("info", "\u2705 Enhanced Secure File Transfer system initialized successfully"); @@ -8075,6 +8198,18 @@ var EnhancedSecureWebRTCManager = class _EnhancedSecureWebRTCManager { this._fileTransferActive = false; } } + _scheduleFileTransferInitRetry(delay) { + if (this._sessionAlive === false) return null; + if (!this._fileTransferInitRetryTimers) this._fileTransferInitRetryTimers = /* @__PURE__ */ new Set(); + const timer = this._trackActiveTimer(setTimeout(() => { + this._fileTransferInitRetryTimers.delete(timer); + this._untrackActiveTimer(timer); + if (this._sessionAlive === false) return; + this.initializeFileTransfer(); + }, delay)); + this._fileTransferInitRetryTimers.add(timer); + return timer; + } // ============================================ // ENHANCED SECURITY INITIALIZATION // ============================================ @@ -8206,6 +8341,12 @@ var EnhancedSecureWebRTCManager = class _EnhancedSecureWebRTCManager { currentFeatures: this.securityFeatures }); } + _sanitizeIncomingChatMessage(message) { + if (typeof message !== "string") { + return message; + } + return window.EnhancedSecureCryptoUtils.sanitizeMessage(message); + } deliverMessageToUI(message, type = "received") { try { this._secureLog("debug", "\u{1F4E4} deliverMessageToUI called", { @@ -8270,9 +8411,10 @@ var EnhancedSecureWebRTCManager = class _EnhancedSecureWebRTCManager { } catch (parseError) { } } + const uiMessage = type === "received" ? this._sanitizeIncomingChatMessage(message) : message; if (this.onMessage) { - this._secureLog("debug", "\u{1F4E4} Calling this.onMessage callback", { message, type }); - this.onMessage(message, type); + this._secureLog("debug", "\u{1F4E4} Calling this.onMessage callback", { message: uiMessage, type }); + this.onMessage(uiMessage, type); } else { this._secureLog("warn", "\u26A0\uFE0F this.onMessage callback is null or undefined"); } @@ -9896,32 +10038,6 @@ var EnhancedSecureWebRTCManager = class _EnhancedSecureWebRTCManager { throw error; } } - disconnect() { - try { - if (this.fileTransferSystem) { - 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 @@ -9934,6 +10050,7 @@ var EnhancedSecureWebRTCManager = class _EnhancedSecureWebRTCManager { this.isVerified = false; this.verificationCode = null; this.pendingSASCode = null; + this.sasValidationAttempts = 0; this.keyFingerprint = null; this.expectedDTLSFingerprint = null; this.connectionId = null; @@ -10084,18 +10201,33 @@ var EnhancedSecureWebRTCManager = class _EnhancedSecureWebRTCManager { }); return null; } - createPeerConnection() { + _hasTurnServer() { + return (this._config.webrtc.iceServers || []).some((server) => { + const urls = Array.isArray(server.urls) ? server.urls : [server.urls]; + return urls.some((url) => typeof url === "string" && url.toLowerCase().startsWith("turn:")); + }); + } + _buildPeerConnectionConfig() { 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" } - ], + iceServers: this._config.webrtc.iceServers, iceCandidatePoolSize: 10, bundlePolicy: "balanced" }; + if (this._config.webrtc.relayOnly) { + config.iceTransportPolicy = "relay"; + } + return config; + } + _warnIfTurnMissing() { + if (this._hasTurnServer() || this._ipLeakWarningShown) return; + this._ipLeakWarningShown = true; + const message = this._config.webrtc.relayOnly ? "Privacy mode is enabled, but no TURN server is configured. Relay-only mode cannot connect until TURN is configured; STUN alone does not hide IP addresses." : "Privacy warning: no TURN server is configured. Direct WebRTC connections may expose IP addresses; STUN alone does not provide IP protection."; + this.deliverMessageToUI(message, "system"); + } + createPeerConnection() { + this._sessionAlive = true; + const config = this._buildPeerConnectionConfig(); + this._warnIfTurnMissing(); this.peerConnection = new RTCPeerConnection(config); this.peerConnection.onconnectionstatechange = () => { const state = this.peerConnection.connectionState; @@ -11765,7 +11897,7 @@ var EnhancedSecureWebRTCManager = class _EnhancedSecureWebRTCManager { // type s: this.peerConnection.localDescription.sdp, // sdp - v: "4.0", + v: _EnhancedSecureWebRTCManager.PROTOCOL_VERSION, // version ts: currentTimestamp, // timestamp @@ -11960,21 +12092,19 @@ var EnhancedSecureWebRTCManager = class _EnhancedSecureWebRTCManager { throw new Error("Offer data is too old \u2013 possible replay attack"); } const protocolVersion = version; - if (protocolVersion !== "4.0") { + if (protocolVersion !== _EnhancedSecureWebRTCManager.PROTOCOL_VERSION) { this._secureLog("warn", "Protocol version mismatch detected", { operationId, - expectedVersion: "4.0", + expectedVersion: _EnhancedSecureWebRTCManager.PROTOCOL_VERSION, receivedVersion: protocolVersion }); - if (protocolVersion !== "3.0") { - throw new Error(`Unsupported protocol version: ${protocolVersion}`); - } + throw new Error(`Version mismatch: expected protocol ${_EnhancedSecureWebRTCManager.PROTOCOL_VERSION}, received ${protocolVersion}`); } this.sessionSalt = offerData.sl || offerData.salt; if (!Array.isArray(this.sessionSalt)) { throw new Error("Invalid session salt format - must be array"); } - const expectedSaltLength = protocolVersion === "4.0" ? 64 : 32; + const expectedSaltLength = 64; if (this.sessionSalt.length !== expectedSaltLength) { throw new Error(`Invalid session salt length: expected ${expectedSaltLength}, got ${this.sessionSalt.length}`); } @@ -12088,7 +12218,7 @@ var EnhancedSecureWebRTCManager = class _EnhancedSecureWebRTCManager { }); throw new Error("Invalid key types after derivation"); } - this.verificationCode = offerData.verificationCode; + this.verificationCode = offerData.vc || offerData.verificationCode || null; this._secureLog("info", "Encryption keys derived and set successfully", { operationId, hasEncryptionKey: !!this.encryptionKey, @@ -12212,6 +12342,19 @@ var EnhancedSecureWebRTCManager = class _EnhancedSecureWebRTCManager { } catch (error) { this._secureLog("error", "Failed to extract DTLS fingerprint from answer", { error: error.message }); } + try { + const remoteFP = this._extractDTLSFingerprintFromSDP(offerData.s || offerData.sdp); + const localFP = this.expectedDTLSFingerprint; + const keyBytes = this._decodeKeyFingerprint(this.keyFingerprint); + this.verificationCode = await this._computeSAS(keyBytes, localFP, remoteFP); + this.onStatusChange?.("verifying"); + this.onVerificationRequired(this.verificationCode); + } catch (sasError) { + this._secureLog("error", "SAS computation failed in createSecureAnswer (Answer side)", { + errorType: sasError?.constructor?.name || "Unknown" + }); + throw new Error(`SAS computation failed: ${sasError.message}`); + } await this.waitForIceGathering(); this._secureLog("debug", "ICE gathering completed for answer", { operationId, @@ -12268,7 +12411,7 @@ var EnhancedSecureWebRTCManager = class _EnhancedSecureWebRTCManager { // type s: this.peerConnection.localDescription.sdp, // sdp - v: "4.0", + v: _EnhancedSecureWebRTCManager.PROTOCOL_VERSION, // version ts: currentTimestamp, // timestamp @@ -12509,6 +12652,10 @@ var EnhancedSecureWebRTCManager = class _EnhancedSecureWebRTCManager { }); throw new Error("CRITICAL SECURITY FAILURE: Invalid answer format - hard abort required"); } + const answerVersion = answerData.v || answerData.version; + if (answerVersion !== _EnhancedSecureWebRTCManager.PROTOCOL_VERSION) { + throw new Error(`Version mismatch: expected protocol ${_EnhancedSecureWebRTCManager.PROTOCOL_VERSION}, received ${answerVersion || "unknown"}`); + } const ecdhKey = answerData.ecdhPublicKey || answerData.e; const ecdsaKey = answerData.ecdsaPublicKey || answerData.d; if (!ecdhKey || typeof ecdhKey !== "object" || Array.isArray(ecdhKey)) { @@ -12759,14 +12906,45 @@ var EnhancedSecureWebRTCManager = class _EnhancedSecureWebRTCManager { this.deliverMessageToUI("Waiting for verification code from peer...", "system"); } } - confirmVerification() { + /** + * Normalizes and validates the user-entered SAS code. + * Users may enter the same shared SAS with spaces or hyphens. + * @param {string} input + * @returns {boolean} + */ + _validateSASCode(input) { + if (!input || typeof input !== "string" || !this.verificationCode || typeof this.verificationCode !== "string") { + return false; + } + const normalizedInput = input.replace(/[-\s]/g, "").toUpperCase(); + const normalizedActual = this.verificationCode.replace(/[-\s]/g, "").toUpperCase(); + if (normalizedInput.length !== normalizedActual.length) { + return false; + } + return window.EnhancedSecureCryptoUtils.constantTimeCompare(normalizedInput, normalizedActual); + } + confirmVerification(userCode) { try { + if (!this._validateSASCode(userCode)) { + this.sasValidationAttempts = (this.sasValidationAttempts || 0) + 1; + this._secureLog("warn", "SAS validation failed: user entered incorrect code", { + attempts: this.sasValidationAttempts, + maxAttempts: _EnhancedSecureWebRTCManager.MAX_SAS_ATTEMPTS + }); + if (this.sasValidationAttempts >= _EnhancedSecureWebRTCManager.MAX_SAS_ATTEMPTS) { + this.deliverMessageToUI("Verification failed 3 times. Session reset for safety.", "system"); + this.disconnect(); + throw new Error("SAS_MAX_ATTEMPTS"); + } + throw new Error("SAS_MISMATCH"); + } this.localVerificationConfirmed = true; + this.sasValidationAttempts = 0; const confirmationPayload = { type: "verification_confirmed", data: { timestamp: Date.now(), - verificationMethod: "SAS", + verificationMethod: "MANUAL_SAS_ENTRY", securityLevel: "MITM_PROTECTION_REQUIRED" } }; @@ -12779,11 +12957,16 @@ var EnhancedSecureWebRTCManager = class _EnhancedSecureWebRTCManager { }); } this._checkBothVerificationsConfirmed(); - this.deliverMessageToUI("You confirmed the verification code. Waiting for peer confirmation...", "system"); + this.deliverMessageToUI("Code verified locally. Waiting for peer confirmation...", "system"); this.processMessageQueue(); } catch (error) { - this._secureLog("error", "SAS verification failed:", { errorType: error?.constructor?.name || "Unknown" }); - this.deliverMessageToUI("SAS verification failed", "system"); + if (error.message === "SAS_MISMATCH") { + this.deliverMessageToUI("Verification failed: the code you entered is incorrect.", "system"); + } else if (error.message !== "SAS_MAX_ATTEMPTS") { + this._secureLog("error", "SAS verification failed:", { errorType: error?.constructor?.name || "Unknown" }); + this.deliverMessageToUI("SAS verification failed", "system"); + } + throw error; } } _checkBothVerificationsConfirmed() { @@ -12885,6 +13068,16 @@ var EnhancedSecureWebRTCManager = class _EnhancedSecureWebRTCManager { } } handleSASCode(data) { + if (!data?.code || typeof data.code !== "string") { + this._secureLog("warn", "Invalid SAS announcement received from peer"); + return; + } + if (this.verificationCode && !this._validateSASCode(data.code)) { + this._secureLog("error", "Peer-announced SAS does not match locally computed SAS"); + this.deliverMessageToUI("Version or SAS mismatch detected. Connection aborted for safety.", "system"); + this.disconnect(); + return; + } this.verificationCode = data.code; this.onStatusChange?.("verifying"); this.onVerificationRequired(this.verificationCode); @@ -12927,8 +13120,8 @@ var EnhancedSecureWebRTCManager = class _EnhancedSecureWebRTCManager { }); throw new Error("CRITICAL SECURITY FAILURE: Offer data must be a non-null object"); } - const isV4CompactFormat = offerData.v === "4.0" && offerData.e && offerData.d; - const isV4Format = offerData.version === "4.0" && offerData.ecdhPublicKey && offerData.ecdsaPublicKey; + const isV4CompactFormat = offerData.v === _EnhancedSecureWebRTCManager.PROTOCOL_VERSION && offerData.e && offerData.d; + const isV4Format = offerData.version === _EnhancedSecureWebRTCManager.PROTOCOL_VERSION && offerData.ecdhPublicKey && offerData.ecdsaPublicKey; const isValidType = isV4CompactFormat ? ["offer"].includes(offerData.t) : ["enhanced_secure_offer", "secure_offer"].includes(offerData.type); if (!isValidType) { throw new Error("Invalid offer type"); @@ -12946,7 +13139,7 @@ var EnhancedSecureWebRTCManager = class _EnhancedSecureWebRTCManager { ]; for (const field of compactRequiredFields) { if (!offerData[field]) { - throw new Error(`Missing required v4.0 compact field: ${field}`); + throw new Error(`Missing required v4.1 compact field: ${field}`); } } if (!offerData.e || typeof offerData.e !== "object" || Array.isArray(offerData.e)) { @@ -12956,7 +13149,7 @@ var EnhancedSecureWebRTCManager = class _EnhancedSecureWebRTCManager { throw new Error("CRITICAL SECURITY FAILURE: Invalid ECDSA public key structure"); } if (!Array.isArray(offerData.sl) || offerData.sl.length !== 64) { - throw new Error("Salt must be exactly 64 bytes for v4.0"); + throw new Error("Salt must be exactly 64 bytes for v4.1"); } if (typeof offerData.vc !== "string" || offerData.vc.length < 6) { throw new Error("Invalid verification code format"); @@ -12968,7 +13161,7 @@ var EnhancedSecureWebRTCManager = class _EnhancedSecureWebRTCManager { if (offerAge > 36e5) { throw new Error("Offer is too old (older than 1 hour)"); } - this._secureLog("info", "v4.0 compact offer validation passed", { + this._secureLog("info", "v4.1 compact offer validation passed", { version: offerData.v, hasECDH: !!offerData.e, hasECDSA: !!offerData.d, @@ -12990,11 +13183,11 @@ var EnhancedSecureWebRTCManager = class _EnhancedSecureWebRTCManager { ]; for (const field of v4RequiredFields) { if (!offerData[field]) { - throw new Error(`Missing v4.0 field: ${field}`); + throw new Error(`Missing v4.1 field: ${field}`); } } if (!Array.isArray(offerData.salt) || offerData.salt.length !== 64) { - throw new Error("Salt must be exactly 64 bytes for v4.0"); + throw new Error("Salt must be exactly 64 bytes for v4.1"); } const offerAge = Date.now() - offerData.timestamp; if (offerAge > 36e5) { @@ -13033,28 +13226,14 @@ var EnhancedSecureWebRTCManager = class _EnhancedSecureWebRTCManager { 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", { + this._secureLog("info", "v4.1 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 - }); + const receivedVersion = offerData.v || offerData.version || "unknown"; + throw new Error(`Version mismatch: expected protocol ${_EnhancedSecureWebRTCManager.PROTOCOL_VERSION}, received ${receivedVersion}`); } const sdp = isV4CompactFormat ? offerData.s : offerData.sdp; if (typeof sdp !== "string" || !sdp.includes("v=0")) { @@ -13185,10 +13364,17 @@ var EnhancedSecureWebRTCManager = class _EnhancedSecureWebRTCManager { } if (this._activeTimers) { this._activeTimers.forEach((timer) => { - if (timer) clearInterval(timer); + if (timer) { + clearInterval(timer); + clearTimeout(timer); + } }); this._activeTimers.clear(); } + if (this._fileTransferInitRetryTimers) { + this._fileTransferInitRetryTimers.clear(); + } + this._logCleanupInterval = null; this._secureLog("info", "All timers stopped successfully"); } waitForIceGathering() { @@ -13237,24 +13423,6 @@ var EnhancedSecureWebRTCManager = class _EnhancedSecureWebRTCManager { 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; @@ -13329,9 +13497,15 @@ var EnhancedSecureWebRTCManager = class _EnhancedSecureWebRTCManager { timestamp: Date.now() } })); - setTimeout(() => { - this.disconnect(); - }, 2e3); + if (!this._peerDisconnectCleanupTimer) { + this._peerDisconnectCleanupTimer = this._trackActiveTimer(setTimeout(() => { + const timer = this._peerDisconnectCleanupTimer; + this._peerDisconnectCleanupTimer = null; + this._untrackActiveTimer(timer); + if (this._sessionAlive === false) return; + this.disconnect(); + }, 2e3)); + } window.EnhancedSecureCryptoUtils.secureLog.log("info", "Peer disconnect notification processed", { reason }); @@ -13340,60 +13514,110 @@ var EnhancedSecureWebRTCManager = class _EnhancedSecureWebRTCManager { * 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}]`); + try { + this._sessionAlive = false; + this.intentionalDisconnect = true; + window.EnhancedSecureCryptoUtils.secureLog.log("info", "Starting intentional disconnect"); + this.sendDisconnectNotification(); + setTimeout(() => { + this.sendDisconnectNotification(); + }, 100); + this._stopAllTimers(); + this._peerDisconnectCleanupTimer = null; + this.stopHeartbeat(); + this.stopFakeTrafficGeneration(); + for (const timer of this.decoyTimers.entries()) { + clearTimeout(timer[1]); + } + this.decoyTimers.clear(); + if (this.fileTransferSystem) { + this.fileTransferSystem.cleanup(); + this.fileTransferSystem = null; + } + for (const channel of this.decoyChannels.values()) { + if (channel.readyState === "open") channel.close(); + } + this.decoyChannels.clear(); + if (this.heartbeatChannel) { + this.heartbeatChannel.close(); + this.heartbeatChannel = null; + } + this.isVerified = false; + this.processedMessageIds.clear(); + this.messageCounter = 0; + this.packetBuffer.clear(); + this.chunkQueue = []; + this._wipeEphemeralKeys(); + this._hardWipeOldKeys(); + 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._clearVerificationStates(); + 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.onopen = null; + this.dataChannel.onclose = null; + this.dataChannel.onmessage = null; + this.dataChannel.onerror = null; + this.dataChannel = null; + } + if (this.peerConnection) { + this.peerConnection.close(); + this.peerConnection.onconnectionstatechange = null; + this.peerConnection.ondatachannel = null; + this.peerConnection = null; + } + if (this.messageQueue && this.messageQueue.length > 0) { + this.messageQueue.forEach((message, index) => { + this._secureWipeMemory(message, `messageQueue[${index}]`); + }); + this.messageQueue = []; + } + this._forceGarbageCollection().catch((error) => { + this._secureLog("error", "Cleanup failed during disconnect", { + errorType: error?.constructor?.name || "Unknown" + }); }); - this.messageQueue = []; - } - this._forceGarbageCollection().catch((error) => { - this._secureLog("error", "Cleanup failed during disconnect", { + document.dispatchEvent(new CustomEvent("peer-disconnect", { + detail: { + reason: "user_disconnect", + timestamp: Date.now() + } + })); + document.dispatchEvent(new CustomEvent("connection-cleaned", { + detail: { + timestamp: Date.now(), + reason: "user_cleanup" + } + })); + this.onStatusChange("disconnected"); + this.onKeyExchange(""); + this.onVerificationRequired(""); + this._secureLog("info", "Connection securely cleaned up with complete memory wipe"); + } catch (error) { + this._secureLog("error", "\u274C Error during enhanced disconnect:", { errorType: error?.constructor?.name || "Unknown" }); - }); - 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", "Connection securely cleaned up with complete memory wipe"); - this.intentionalDisconnect = false; + } finally { + this.intentionalDisconnect = false; + } } // Public method to send files async sendFile(file) { @@ -13502,14 +13726,30 @@ var EnhancedSecureWebRTCManager = class _EnhancedSecureWebRTCManager { } } // Set file transfer callbacks - setFileTransferCallbacks(onProgress, onReceived, onError) { + setFileTransferCallbacks(onProgress, onReceived, onError, onIncomingRequest = null) { this.onFileProgress = onProgress; this.onFileReceived = onReceived; this.onFileError = onError; + this.onIncomingFileRequest = onIncomingRequest; if (this.fileTransferSystem) { - this.initializeFileTransfer(); + this.fileTransferSystem.onProgress = onProgress; + this.fileTransferSystem.onFileReceived = onReceived; + this.fileTransferSystem.onError = onError; + this.fileTransferSystem.onIncomingFileRequest = onIncomingRequest; } } + getPendingIncomingFiles() { + if (!this.fileTransferSystem) return []; + return this.fileTransferSystem.getPendingIncomingTransfers(); + } + async acceptIncomingFile(fileId) { + if (!this.fileTransferSystem) return false; + return this.fileTransferSystem.acceptIncomingFile(fileId); + } + async rejectIncomingFile(fileId) { + if (!this.fileTransferSystem) return false; + return this.fileTransferSystem.rejectIncomingFile(fileId); + } // ============================================ // SESSION ACTIVATION HANDLING // ============================================ @@ -14258,17 +14498,9 @@ var SecureIndexedDBWrapper = class { iv: Array.from(new Uint8Array(iv)), algorithm, usages, - type, - timestamp: Date.now() - }; - const metadataRecord = { - keyId, - ...metadata, - created: Date.now(), - lastAccessed: Date.now(), - extractable: true, - persistent: true + type }; + const metadataRecord = { keyId, ...metadata }; return new Promise((resolve, reject) => { const keysRequest = transaction.objectStore(this.KEYS_STORE).put(keyRecord); const metadataRequest = transaction.objectStore(this.METADATA_STORE).put(metadataRecord); @@ -14323,6 +14555,26 @@ var SecureIndexedDBWrapper = class { getRequest.onerror = () => reject(new Error(`Failed to get metadata: ${getRequest.error}`)); }); } + async getKeyMetadataRecord(keyId) { + if (!this.db) throw new Error("Database not initialized"); + const transaction = this.db.transaction([this.METADATA_STORE], "readonly"); + const store = transaction.objectStore(this.METADATA_STORE); + return new Promise((resolve, reject) => { + const request = store.get(keyId); + request.onsuccess = () => resolve(request.result || null); + request.onerror = () => reject(new Error(`Failed to get metadata: ${request.error}`)); + }); + } + async putKeyMetadataRecord(record) { + if (!this.db) throw new Error("Database not initialized"); + const transaction = this.db.transaction([this.METADATA_STORE], "readwrite"); + const store = transaction.objectStore(this.METADATA_STORE); + return new Promise((resolve, reject) => { + const request = store.put(record); + request.onsuccess = () => resolve(); + request.onerror = () => reject(new Error(`Failed to store metadata: ${request.error}`)); + }); + } /** * Delete key and its metadata */ @@ -14364,8 +14616,7 @@ var SecureIndexedDBWrapper = class { const store = transaction.objectStore(this.SALT_STORE); const saltRecord = { id: "master_salt", - salt: Array.from(new Uint8Array(salt)), - created: Date.now() + salt: Array.from(new Uint8Array(salt)) }; return new Promise((resolve, reject) => { const request = store.put(saltRecord); @@ -14438,6 +14689,11 @@ var SecurePersistentKeyStorage = class { this._dbInitialized = true; } } + async _ensureMasterKeyUnlocked() { + if (typeof this._masterKeyManager.isUnlocked === "function" && !this._masterKeyManager.isUnlocked()) { + await this._masterKeyManager.unlock(); + } + } /** * Store extractable key with encryption */ @@ -14452,6 +14708,13 @@ var SecurePersistentKeyStorage = class { await this._ensureDBInitialized(); const jwkData = await crypto.subtle.exportKey("jwk", cryptoKey); const { encryptedData, iv } = await this._encryptKeyData(jwkData); + const encryptedMetadata = await this._encryptMetadata({ + ...metadata, + created: Date.now(), + lastAccessed: Date.now(), + extractable: true, + persistent: true + }); await this._indexedDB.storeEncryptedKey( keyId, encryptedData, @@ -14459,7 +14722,7 @@ var SecurePersistentKeyStorage = class { cryptoKey.algorithm, cryptoKey.usages, cryptoKey.type, - metadata + encryptedMetadata ); const nonExtractableKey = await this._importAsNonExtractable(jwkData, cryptoKey.algorithm, cryptoKey.usages); this._keyReferences.set(keyId, nonExtractableKey); @@ -14484,7 +14747,7 @@ var SecurePersistentKeyStorage = class { const jwkData = await this._decryptKeyData(keyRecord.encryptedData, keyRecord.iv); const restoredKey = await this._importAsNonExtractable(jwkData, keyRecord.algorithm, keyRecord.usages); this._keyReferences.set(keyId, restoredKey); - await this._indexedDB.updateKeyMetadata(keyId, { lastAccessed: Date.now() }); + await this._updateEncryptedMetadata(keyId, { lastAccessed: Date.now() }); return restoredKey; } catch (error) { throw new Error(`Failed to retrieve key: ${error.message}`); @@ -14509,7 +14772,13 @@ var SecurePersistentKeyStorage = class { async listStoredKeys() { try { await this._ensureDBInitialized(); - return await this._indexedDB.listKeys(); + const records = await this._indexedDB.listKeys(); + const results = []; + for (const record of records) { + const metadata = await this._readMetadataWithMigration(record); + if (metadata) results.push({ keyId: record.keyId, ...metadata }); + } + return results; } catch (error) { throw new Error(`Failed to list keys: ${error.message}`); } @@ -14545,6 +14814,51 @@ var SecurePersistentKeyStorage = class { const jsonString = new TextDecoder().decode(decryptedData); return JSON.parse(jsonString); } + async _encryptMetadata(metadata) { + const data = new TextEncoder().encode(JSON.stringify(metadata)); + await this._ensureMasterKeyUnlocked(); + const { encryptedData, iv } = await this._masterKeyManager.encryptBytes(data); + return { + metadataVersion: 1, + encryptedMetadata: Array.from(encryptedData), + metadataIv: Array.from(iv) + }; + } + async _decryptMetadataRecord(record) { + if (!record?.encryptedMetadata || !record?.metadataIv) { + throw new Error("Encrypted metadata missing"); + } + await this._ensureMasterKeyUnlocked(); + const decrypted = await this._masterKeyManager.decryptBytes( + new Uint8Array(record.encryptedMetadata), + new Uint8Array(record.metadataIv) + ); + return JSON.parse(new TextDecoder().decode(decrypted)); + } + async _readMetadataWithMigration(record) { + if (!record) return null; + if (record.encryptedMetadata) { + try { + return await this._decryptMetadataRecord(record); + } catch (error) { + return null; + } + } + const { keyId, ...legacyMetadata } = record; + const encryptedRecord = { keyId, ...await this._encryptMetadata(legacyMetadata) }; + await this._indexedDB.putKeyMetadataRecord(encryptedRecord); + return legacyMetadata; + } + async _updateEncryptedMetadata(keyId, updates) { + const record = await this._indexedDB.getKeyMetadataRecord(keyId); + if (!record) throw new Error(`Key metadata not found: ${keyId}`); + const current = await this._readMetadataWithMigration(record); + if (!current) throw new Error(`Key metadata corrupted: ${keyId}`); + await this._indexedDB.putKeyMetadataRecord({ + keyId, + ...await this._encryptMetadata({ ...current, ...updates }) + }); + } /** * Import JWK as non-extractable key */ @@ -15314,7 +15628,7 @@ Right-click or Ctrl+click to disconnect`, React.createElement("p", { key: "subtitle", className: "text-xs sm:text-sm text-muted hidden sm:block" - }, "End-to-end freedom v4.7.56") + }, "End-to-end freedom v4.8.5") ]) ]), // Status and Controls - Responsive @@ -16517,6 +16831,7 @@ var FileTransferComponent = ({ webrtcManager, isConnected }) => { const [dragOver, setDragOver] = React.useState(false); const [transfers, setTransfers] = React.useState({ sending: [], receiving: [] }); const [readyFiles, setReadyFiles] = React.useState([]); + const [pendingIncomingFiles, setPendingIncomingFiles] = React.useState([]); const fileInputRef = React.useRef(null); React.useEffect(() => { if (!isConnected || !webrtcManager) return; @@ -16527,6 +16842,12 @@ var FileTransferComponent = ({ webrtcManager, isConnected }) => { const interval = setInterval(updateTransfers, 500); return () => clearInterval(interval); }, [isConnected, webrtcManager]); + React.useEffect(() => { + if (isConnected) return; + setReadyFiles([]); + setPendingIncomingFiles([]); + setTransfers({ sending: [], receiving: [] }); + }, [isConnected]); React.useEffect(() => { if (!webrtcManager) return; webrtcManager.setFileTransferCallbacks( @@ -16556,8 +16877,18 @@ var FileTransferComponent = ({ webrtcManager, isConnected }) => { (error) => { const currentTransfers = webrtcManager.getFileTransfers(); setTransfers(currentTransfers); + }, + // Incoming file request callback - user consent is mandatory + (fileRequest) => { + setPendingIncomingFiles((prev) => { + if (prev.some((file) => file.fileId === fileRequest.fileId)) return prev; + return [...prev, fileRequest]; + }); } ); + return () => { + webrtcManager.setFileTransferCallbacks(null, null, null, null); + }; }, [webrtcManager]); const handleFileSelect = async (files) => { if (!isConnected || !webrtcManager) { @@ -16654,6 +16985,18 @@ var FileTransferComponent = ({ webrtcManager, isConnected }) => { return status; } }; + const handleIncomingDecision = async (fileId, accepted) => { + try { + if (accepted) { + await webrtcManager.acceptIncomingFile(fileId); + } else { + await webrtcManager.rejectIncomingFile(fileId); + } + } finally { + setPendingIncomingFiles((prev) => prev.filter((file) => file.fileId !== fileId)); + setTransfers(webrtcManager.getFileTransfers()); + } + }; if (!isConnected) { return React.createElement("div", { className: "p-4 text-center text-muted" @@ -16710,6 +17053,44 @@ var FileTransferComponent = ({ webrtcManager, isConnected }) => { className: "hidden", onChange: handleFileInputChange }), + pendingIncomingFiles.length > 0 && React.createElement("div", { + key: "incoming-consent", + className: "mt-4 space-y-2" + }, pendingIncomingFiles.map((file) => React.createElement("div", { + key: file.fileId, + className: "rounded-lg border border-yellow-500/30 bg-yellow-500/10 p-3" + }, [ + React.createElement("div", { + key: "info", + className: "mb-3 flex items-center justify-between gap-3" + }, [ + React.createElement("div", { key: "text" }, [ + React.createElement("div", { + key: "title", + className: "text-sm font-medium text-primary" + }, "Incoming file request"), + React.createElement("div", { + key: "meta", + className: "text-xs text-secondary" + }, `${file.fileName} \xB7 ${formatFileSize(file.fileSize)} \xB7 ${file.mimeType}`) + ]) + ]), + React.createElement("div", { + key: "actions", + className: "flex gap-2" + }, [ + React.createElement("button", { + key: "accept", + onClick: () => handleIncomingDecision(file.fileId, true), + className: "rounded-md bg-green-500/20 px-3 py-2 text-sm text-green-300 hover:bg-green-500/30" + }, "Accept"), + React.createElement("button", { + key: "reject", + onClick: () => handleIncomingDecision(file.fileId, false), + className: "rounded-md bg-red-500/20 px-3 py-2 text-sm text-red-300 hover:bg-red-500/30" + }, "Reject") + ]) + ]))), // Active Transfers (transfers.sending.length > 0 || transfers.receiving.length > 0) && React.createElement("div", { key: "transfers", @@ -16835,7 +17216,7 @@ var FileTransferComponent = ({ webrtcManager, isConnected }) => { a.click(); rf.revokeObjectURL(url); } catch (e) { - alert("Failed to start download: " + e.message); + alert(e.message || "This file is no longer available for download."); } } }, [ diff --git a/dist/app-boot.js.map b/dist/app-boot.js.map index 92e6cea..9aa65f1 100644 --- a/dist/app-boot.js.map +++ b/dist/app-boot.js.map @@ -1,7 +1,7 @@ { "version": 3, "sources": ["../src/notifications/SecureNotificationManager.js", "../src/notifications/NotificationIntegration.js", "../src/crypto/EnhancedSecureCryptoUtils.js", "../src/transfer/EnhancedSecureFileTransfer.js", "../src/network/EnhancedSecureWebRTCManager.js", "../src/scripts/app-boot.js", "../src/components/ui/Header.jsx", "../src/components/ui/DownloadApps.jsx", "../src/components/ui/BecomePartner.jsx", "../src/components/ui/UniqueFeatureSlider.jsx", "../src/components/ui/SecurityFeatures.jsx", "../src/components/ui/Testimonials.jsx", "../src/components/ui/ComparisonTable.jsx", "../src/components/ui/Roadmap.jsx", "../src/components/ui/FileTransfer.jsx"], - "sourcesContent": ["/**\n * Secure and Reliable Notification Manager for P2P WebRTC Chat\n * Follows best practices: OWASP, MDN, Chrome DevRel\n * \n * @version 1.0.0\n * @author SecureBit Team\n * @license MIT\n */\n\nclass SecureChatNotificationManager {\n constructor(config = {}) {\n // Safely read Notification permission (iOS Safari may not define Notification)\n this.permission = (typeof Notification !== 'undefined' && Notification && typeof Notification.permission === 'string')\n ? Notification.permission\n : 'denied';\n this.isTabActive = this.checkTabActive(); // Initialize with proper check\n this.unreadCount = 0;\n this.originalTitle = document.title;\n this.notificationQueue = [];\n this.maxQueueSize = config.maxQueueSize || 5;\n this.rateLimitMs = config.rateLimitMs || 2000; // Spam protection\n this.lastNotificationTime = 0;\n this.trustedOrigins = config.trustedOrigins || [];\n \n // Secure context flag\n this.isSecureContext = window.isSecureContext;\n \n // Cross-browser compatibility for Page Visibility API\n this.hidden = this.getHiddenProperty();\n this.visibilityChange = this.getVisibilityChangeEvent();\n \n this.initVisibilityTracking();\n this.initSecurityChecks();\n }\n\n /**\n * Initialize security checks and validation\n * @private\n */\n initSecurityChecks() {\n // Security checks are performed silently\n }\n\n /**\n * Get hidden property name for cross-browser compatibility\n * @returns {string} Hidden property name\n * @private\n */\n getHiddenProperty() {\n if (typeof document.hidden !== \"undefined\") {\n return \"hidden\";\n } else if (typeof document.msHidden !== \"undefined\") {\n return \"msHidden\";\n } else if (typeof document.webkitHidden !== \"undefined\") {\n return \"webkitHidden\";\n }\n return \"hidden\"; // fallback\n }\n\n /**\n * Get visibility change event name for cross-browser compatibility\n * @returns {string} Visibility change event name\n * @private\n */\n getVisibilityChangeEvent() {\n if (typeof document.hidden !== \"undefined\") {\n return \"visibilitychange\";\n } else if (typeof document.msHidden !== \"undefined\") {\n return \"msvisibilitychange\";\n } else if (typeof document.webkitHidden !== \"undefined\") {\n return \"webkitvisibilitychange\";\n }\n return \"visibilitychange\"; // fallback\n }\n\n /**\n * Check if tab is currently active using multiple methods\n * @returns {boolean} True if tab is active\n * @private\n */\n checkTabActive() {\n // Primary method: Page Visibility API\n if (this.hidden && typeof document[this.hidden] !== \"undefined\") {\n return !document[this.hidden];\n }\n \n // Fallback method: document.hasFocus()\n if (typeof document.hasFocus === \"function\") {\n return document.hasFocus();\n }\n \n // Ultimate fallback: assume active\n return true;\n }\n\n /**\n * Initialize page visibility tracking (Page Visibility API)\n * @private\n */\n initVisibilityTracking() {\n // Primary method: Page Visibility API with cross-browser support\n if (typeof document.addEventListener !== \"undefined\" && typeof document[this.hidden] !== \"undefined\") {\n document.addEventListener(this.visibilityChange, () => {\n this.isTabActive = this.checkTabActive();\n \n if (this.isTabActive) {\n this.resetUnreadCount();\n this.clearNotificationQueue();\n }\n });\n }\n\n // Fallback method: Window focus/blur events\n window.addEventListener('focus', () => {\n this.isTabActive = this.checkTabActive();\n if (this.isTabActive) {\n this.resetUnreadCount();\n }\n });\n\n window.addEventListener('blur', () => {\n this.isTabActive = this.checkTabActive();\n });\n\n // Page unload cleanup\n window.addEventListener('beforeunload', () => {\n this.clearNotificationQueue();\n });\n }\n\n /**\n * Request notification permission (BEST PRACTICE: Only call in response to user action)\n * Never call on page load!\n * @returns {Promise} Permission granted status\n */\n async requestPermission() {\n // Secure context check\n if (!this.isSecureContext || !('Notification' in window)) {\n return false;\n }\n\n if (this.permission === 'granted') {\n return true;\n }\n\n if (this.permission === 'denied') {\n return false;\n }\n\n try {\n this.permission = await Notification.requestPermission();\n return this.permission === 'granted';\n } catch (error) {\n return false;\n }\n }\n\n /**\n * Update page title with unread count\n * @private\n */\n updateTitle() {\n if (this.unreadCount > 0) {\n document.title = `(${this.unreadCount}) ${this.originalTitle}`;\n } else {\n document.title = this.originalTitle;\n }\n }\n\n /**\n * XSS Protection: Sanitize input text\n * @param {string} text - Text to sanitize\n * @returns {string} Sanitized text\n * @private\n */\n sanitizeText(text) {\n if (typeof text !== 'string') {\n return '';\n }\n \n // Remove HTML tags and potentially dangerous characters\n const div = document.createElement('div');\n div.textContent = text;\n return div.innerHTML\n .replace(//g, '>')\n .replace(/\"/g, '"')\n .replace(/'/g, ''')\n .substring(0, 500); // Length limit\n }\n\n /**\n * Validate icon URL (XSS protection)\n * @param {string} url - URL to validate\n * @returns {string|null} Validated URL or null\n * @private\n */\n validateIconUrl(url) {\n if (!url) return null;\n \n try {\n const parsedUrl = new URL(url, window.location.origin);\n \n // Only allow HTTPS and data URLs\n if (parsedUrl.protocol === 'https:' || parsedUrl.protocol === 'data:') {\n // Check trusted origins if specified\n if (this.trustedOrigins.length > 0) {\n const isTrusted = this.trustedOrigins.some(origin => \n parsedUrl.origin === origin\n );\n return isTrusted ? parsedUrl.href : null;\n }\n return parsedUrl.href;\n }\n \n return null;\n } catch (error) {\n return null;\n }\n }\n\n /**\n * Rate limiting for spam protection\n * @returns {boolean} Rate limit check passed\n * @private\n */\n checkRateLimit() {\n const now = Date.now();\n if (now - this.lastNotificationTime < this.rateLimitMs) {\n return false;\n }\n this.lastNotificationTime = now;\n return true;\n }\n\n /**\n * Send secure notification\n * @param {string} senderName - Name of message sender\n * @param {string} message - Message content\n * @param {Object} options - Notification options\n * @returns {Notification|null} Created notification or null\n */\n notify(senderName, message, options = {}) {\n // Abort if Notifications API is not available (e.g., iOS Safari)\n if (typeof Notification === 'undefined') {\n return null;\n }\n // Update tab active state before checking\n this.isTabActive = this.checkTabActive();\n \n // Only show if tab is NOT active (user is on another tab or minimized)\n if (this.isTabActive) {\n return null;\n }\n\n // Permission check\n if (this.permission !== 'granted') {\n return null;\n }\n\n // Rate limiting\n if (!this.checkRateLimit()) {\n return null;\n }\n\n // Data sanitization (XSS Protection)\n const safeSenderName = this.sanitizeText(senderName || 'Unknown');\n const safeMessage = this.sanitizeText(message || '');\n const safeIcon = this.validateIconUrl(options.icon) || '/logo/icon-192x192.png';\n\n // Queue overflow protection\n if (this.notificationQueue.length >= this.maxQueueSize) {\n this.clearNotificationQueue();\n }\n\n try {\n \n const notification = new Notification(\n `${safeSenderName}`,\n {\n body: safeMessage.substring(0, 200), // Length limit\n icon: safeIcon,\n badge: safeIcon,\n tag: `chat-${options.senderId || 'unknown'}`, // Grouping\n requireInteraction: false, // Don't block user\n silent: options.silent || false,\n // Vibrate only for mobile and if supported\n vibrate: navigator.vibrate ? [200, 100, 200] : undefined,\n // Safe metadata\n data: {\n senderId: this.sanitizeText(options.senderId),\n timestamp: Date.now(),\n // Don't include sensitive data!\n }\n }\n );\n\n // Increment counter\n this.unreadCount++;\n this.updateTitle();\n\n // Add to queue for management\n this.notificationQueue.push(notification);\n\n // Safe click handler\n notification.onclick = (event) => {\n event.preventDefault(); // Prevent default behavior\n window.focus();\n notification.close();\n \n // Safe callback\n if (typeof options.onClick === 'function') {\n try {\n options.onClick(options.senderId);\n } catch (error) {\n console.error('[Notifications] Error in onClick handler:', error);\n }\n }\n };\n\n // Error handler\n notification.onerror = (event) => {\n console.error('[Notifications] Error showing notification:', event);\n };\n\n // Auto-close after reasonable time\n const autoCloseTimeout = Math.min(options.autoClose || 5000, 10000);\n setTimeout(() => {\n notification.close();\n this.removeFromQueue(notification);\n }, autoCloseTimeout);\n\n return notification;\n \n } catch (error) {\n console.error('[Notifications] Failed to create notification:', error);\n return null;\n }\n }\n\n /**\n * Remove notification from queue\n * @param {Notification} notification - Notification to remove\n * @private\n */\n removeFromQueue(notification) {\n const index = this.notificationQueue.indexOf(notification);\n if (index > -1) {\n this.notificationQueue.splice(index, 1);\n }\n }\n\n /**\n * Clear all notifications\n */\n clearNotificationQueue() {\n this.notificationQueue.forEach(notification => {\n try {\n notification.close();\n } catch (error) {\n // Ignore errors when closing\n }\n });\n this.notificationQueue = [];\n }\n\n /**\n * Reset unread counter\n */\n resetUnreadCount() {\n this.unreadCount = 0;\n this.updateTitle();\n }\n\n /**\n * Get current status\n * @returns {Object} Current notification status\n */\n getStatus() {\n return {\n permission: this.permission,\n isTabActive: this.isTabActive,\n unreadCount: this.unreadCount,\n isSecureContext: this.isSecureContext,\n queueSize: this.notificationQueue.length\n };\n }\n}\n\n/**\n * Secure integration with WebRTC\n */\nclass SecureP2PChat {\n constructor() {\n this.notificationManager = new SecureChatNotificationManager({\n maxQueueSize: 5,\n rateLimitMs: 2000,\n trustedOrigins: [\n window.location.origin,\n // Add other trusted origins for CDN icons\n ]\n });\n \n this.dataChannel = null;\n this.peerConnection = null;\n this.remotePeerName = 'Peer';\n this.messageHistory = [];\n this.maxHistorySize = 100;\n }\n\n /**\n * Initialize when user connects\n */\n async init() {\n // Initialize notification manager silently\n }\n\n /**\n * Method for manual permission request (called on click)\n * @returns {Promise} Permission granted status\n */\n async enableNotifications() {\n const granted = await this.notificationManager.requestPermission();\n return granted;\n }\n\n /**\n * Setup DataChannel with security checks\n * @param {RTCDataChannel} dataChannel - WebRTC data channel\n */\n setupDataChannel(dataChannel) {\n if (!dataChannel) {\n console.error('[Chat] Invalid DataChannel');\n return;\n }\n\n this.dataChannel = dataChannel;\n \n // Setup handlers\n this.dataChannel.onmessage = (event) => {\n this.handleIncomingMessage(event.data);\n };\n\n this.dataChannel.onerror = (error) => {\n // Handle error silently\n };\n }\n\n /**\n * XSS Protection: Validate incoming messages\n * @param {string|Object} data - Message data\n * @returns {Object|null} Validated message or null\n * @private\n */\n validateMessage(data) {\n try {\n const message = typeof data === 'string' ? JSON.parse(data) : data;\n \n // Check message structure\n if (!message || typeof message !== 'object') {\n throw new Error('Invalid message structure');\n }\n\n // Check required fields\n if (!message.text || typeof message.text !== 'string') {\n throw new Error('Invalid message text');\n }\n\n // Message length limit (DoS protection)\n if (message.text.length > 10000) {\n throw new Error('Message too long');\n }\n\n return {\n text: message.text,\n senderName: message.senderName || 'Unknown',\n senderId: message.senderId || 'unknown',\n timestamp: message.timestamp || Date.now(),\n senderAvatar: message.senderAvatar || null\n };\n \n } catch (error) {\n console.error('[Chat] Message validation failed:', error);\n return null;\n }\n }\n\n /**\n * Secure handling of incoming messages\n * @param {string|Object} data - Message data\n * @private\n */\n handleIncomingMessage(data) {\n const message = this.validateMessage(data);\n \n if (!message) {\n return;\n }\n\n // Save to history (with limit)\n this.messageHistory.push(message);\n if (this.messageHistory.length > this.maxHistorySize) {\n this.messageHistory.shift();\n }\n\n // Display in UI (with sanitization)\n this.displayMessage(message);\n\n // Send notification only if tab is inactive\n this.notificationManager.notify(\n message.senderName,\n message.text,\n {\n icon: message.senderAvatar,\n senderId: message.senderId,\n onClick: (senderId) => {\n this.scrollToLatestMessage();\n }\n }\n );\n\n // Optional: sound (with check)\n if (!this.notificationManager.isTabActive) {\n this.playNotificationSound();\n }\n }\n\n /**\n * XSS Protection: Safe message display\n * @param {Object} message - Message to display\n * @private\n */\n displayMessage(message) {\n const container = document.getElementById('messages');\n if (!container) {\n return;\n }\n\n const messageEl = document.createElement('div');\n messageEl.className = 'message';\n \n // Use textContent to prevent XSS\n const nameEl = document.createElement('strong');\n nameEl.textContent = message.senderName + ': ';\n \n const textEl = document.createElement('span');\n textEl.textContent = message.text;\n textEl.style.wordWrap = 'break-word';\n textEl.style.overflowWrap = 'break-word';\n textEl.style.whiteSpace = 'normal';\n \n const timeEl = document.createElement('small');\n timeEl.textContent = new Date(message.timestamp).toLocaleTimeString();\n \n messageEl.appendChild(nameEl);\n messageEl.appendChild(textEl);\n messageEl.appendChild(document.createElement('br'));\n messageEl.appendChild(timeEl);\n \n container.appendChild(messageEl);\n this.scrollToLatestMessage();\n }\n\n /**\n * Safe sound playback\n * @private\n */\n playNotificationSound() {\n try {\n // Use only local audio files\n const audio = new Audio('/assets/audio/notification.mp3');\n audio.volume = 0.3; // Moderate volume\n \n // Error handling\n audio.play().catch(error => {\n // Handle audio error silently\n });\n } catch (error) {\n // Handle audio creation error silently\n }\n }\n\n /**\n * Scroll to latest message\n * @private\n */\n scrollToLatestMessage() {\n const container = document.getElementById('messages');\n if (container) {\n container.scrollTop = container.scrollHeight;\n }\n }\n\n /**\n * Get status\n * @returns {Object} Current chat status\n */\n getStatus() {\n return {\n notifications: this.notificationManager.getStatus(),\n messageCount: this.messageHistory.length,\n connected: this.dataChannel?.readyState === 'open'\n };\n }\n}\n\n// Export for use in other modules\nif (typeof module !== 'undefined' && module.exports) {\n module.exports = { SecureChatNotificationManager, SecureP2PChat };\n}\n\n// Global export for browser usage\nif (typeof window !== 'undefined') {\n window.SecureChatNotificationManager = SecureChatNotificationManager;\n window.SecureP2PChat = SecureP2PChat;\n}\n", "/**\n * Notification Integration Module for SecureBit WebRTC Chat\n * Integrates secure notifications with existing WebRTC architecture\n * \n * @version 1.0.0\n * @author SecureBit Team\n * @license MIT\n */\n\nimport { SecureChatNotificationManager } from './SecureNotificationManager.js';\n\nclass NotificationIntegration {\n constructor(webrtcManager) {\n this.webrtcManager = webrtcManager;\n this.notificationManager = new SecureChatNotificationManager({\n maxQueueSize: 10,\n rateLimitMs: 1000, // Reduced from 2000ms to 1000ms\n trustedOrigins: [\n window.location.origin,\n // Add other trusted origins for CDN icons\n ]\n });\n \n this.isInitialized = false;\n this.originalOnMessage = null;\n this.originalOnStatusChange = null;\n this.processedMessages = new Set(); // Track processed messages to avoid duplicates\n }\n\n /**\n * Initialize notification integration\n * @returns {Promise} Initialization success\n */\n async init() {\n try {\n if (this.isInitialized) {\n return true;\n }\n\n // Store original callbacks\n this.originalOnMessage = this.webrtcManager.onMessage;\n this.originalOnStatusChange = this.webrtcManager.onStatusChange;\n\n\n // Wrap the original onMessage callback\n this.webrtcManager.onMessage = (message, type) => {\n this.handleIncomingMessage(message, type);\n \n // Call original callback if it exists\n if (this.originalOnMessage) {\n this.originalOnMessage(message, type);\n }\n };\n\n // Wrap the original onStatusChange callback\n this.webrtcManager.onStatusChange = (status) => {\n this.handleStatusChange(status);\n \n // Call original callback if it exists\n if (this.originalOnStatusChange) {\n this.originalOnStatusChange(status);\n }\n };\n\n // Also hook into the deliverMessageToUI method if it exists\n if (this.webrtcManager.deliverMessageToUI) {\n this.originalDeliverMessageToUI = this.webrtcManager.deliverMessageToUI.bind(this.webrtcManager);\n this.webrtcManager.deliverMessageToUI = (message, type) => {\n this.handleIncomingMessage(message, type);\n this.originalDeliverMessageToUI(message, type);\n };\n }\n\n this.isInitialized = true;\n return true;\n\n } catch (error) {\n return false;\n }\n }\n\n /**\n * Handle incoming messages and trigger notifications\n * @param {*} message - Message content\n * @param {string} type - Message type\n * @private\n */\n handleIncomingMessage(message, type) {\n try {\n // Create a unique key for this message to avoid duplicates\n const messageKey = `${type}:${typeof message === 'string' ? message : JSON.stringify(message)}`;\n \n // Skip if we've already processed this message\n if (this.processedMessages.has(messageKey)) {\n return;\n }\n \n // Mark message as processed\n this.processedMessages.add(messageKey);\n \n // Clean up old processed messages (keep only last 100)\n if (this.processedMessages.size > 100) {\n const messagesArray = Array.from(this.processedMessages);\n this.processedMessages.clear();\n messagesArray.slice(-50).forEach(msg => this.processedMessages.add(msg));\n }\n \n \n // Only process chat messages, not system messages\n if (type === 'system' || type === 'file-transfer' || type === 'heartbeat') {\n return;\n }\n\n // Extract message information\n const messageInfo = this.extractMessageInfo(message, type);\n if (!messageInfo) {\n return;\n }\n\n // Send notification\n const notificationResult = this.notificationManager.notify(\n messageInfo.senderName,\n messageInfo.text,\n {\n icon: messageInfo.senderAvatar,\n senderId: messageInfo.senderId,\n onClick: (senderId) => {\n this.focusChatWindow();\n }\n }\n );\n\n } catch (error) {\n // Handle error silently\n }\n }\n\n /**\n * Handle status changes\n * @param {string} status - Connection status\n * @private\n */\n handleStatusChange(status) {\n try {\n // Clear notifications when connection is lost\n if (status === 'disconnected' || status === 'failed') {\n this.notificationManager.clearNotificationQueue();\n this.notificationManager.resetUnreadCount();\n }\n } catch (error) {\n // Handle error silently\n }\n }\n\n /**\n * Extract message information for notifications\n * @param {*} message - Message content\n * @param {string} type - Message type\n * @returns {Object|null} Extracted message info or null\n * @private\n */\n extractMessageInfo(message, type) {\n try {\n let messageData = message;\n\n // Handle different message formats\n if (typeof message === 'string') {\n try {\n messageData = JSON.parse(message);\n } catch (e) {\n // Plain text message\n return {\n senderName: 'Peer',\n text: message,\n senderId: 'peer',\n senderAvatar: null\n };\n }\n }\n\n // Handle structured message data\n if (typeof messageData === 'object' && messageData !== null) {\n return {\n senderName: messageData.senderName || messageData.name || 'Peer',\n text: messageData.text || messageData.message || messageData.content || '',\n senderId: messageData.senderId || messageData.id || 'peer',\n senderAvatar: messageData.senderAvatar || messageData.avatar || null\n };\n }\n\n return null;\n } catch (error) {\n return null;\n }\n }\n\n /**\n * Focus chat window when notification is clicked\n * @private\n */\n focusChatWindow() {\n try {\n window.focus();\n \n // Scroll to bottom of messages if container exists\n const messagesContainer = document.getElementById('messages');\n if (messagesContainer) {\n messagesContainer.scrollTop = messagesContainer.scrollHeight;\n }\n } catch (error) {\n // Handle error silently\n }\n }\n\n /**\n * Request notification permission\n * @returns {Promise} Permission granted status\n */\n async requestPermission() {\n try {\n return await this.notificationManager.requestPermission();\n } catch (error) {\n return false;\n }\n }\n\n /**\n * Get notification status\n * @returns {Object} Notification status\n */\n getStatus() {\n return this.notificationManager.getStatus();\n }\n\n /**\n * Clear all notifications\n */\n clearNotifications() {\n this.notificationManager.clearNotificationQueue();\n this.notificationManager.resetUnreadCount();\n }\n\n /**\n * Cleanup integration\n */\n cleanup() {\n try {\n if (this.isInitialized) {\n // Restore original callbacks\n if (this.originalOnMessage) {\n this.webrtcManager.onMessage = this.originalOnMessage;\n }\n if (this.originalOnStatusChange) {\n this.webrtcManager.onStatusChange = this.originalOnStatusChange;\n }\n if (this.originalDeliverMessageToUI) {\n this.webrtcManager.deliverMessageToUI = this.originalDeliverMessageToUI;\n }\n\n // Clear notifications\n this.clearNotifications();\n\n this.isInitialized = false;\n }\n } catch (error) {\n // Handle error silently\n }\n }\n}\n\n// Export for use in other modules\nif (typeof module !== 'undefined' && module.exports) {\n module.exports = { NotificationIntegration };\n}\n\n// Global export for browser usage\nif (typeof window !== 'undefined') {\n window.NotificationIntegration = NotificationIntegration;\n}\n", "class EnhancedSecureCryptoUtils {\r\n\r\n static _keyMetadata = new WeakMap();\r\n \r\n // Initialize secure logging system after class definition\r\n\r\n // Utility to sort object keys for deterministic serialization\r\n static sortObjectKeys(obj) {\r\n if (typeof obj !== 'object' || obj === null) {\r\n return obj;\r\n }\r\n\r\n if (Array.isArray(obj)) {\r\n return obj.map(EnhancedSecureCryptoUtils.sortObjectKeys);\r\n }\r\n\r\n const sortedObj = {};\r\n Object.keys(obj).sort().forEach(key => {\r\n sortedObj[key] = EnhancedSecureCryptoUtils.sortObjectKeys(obj[key]);\r\n });\r\n return sortedObj;\r\n }\r\n\r\n // Utility to assert CryptoKey type and properties\r\n static assertCryptoKey(key, expectedName = null, expectedUsages = []) {\r\n if (!(key instanceof CryptoKey)) throw new Error('Expected CryptoKey');\r\n if (expectedName && key.algorithm?.name !== expectedName) {\r\n throw new Error(`Expected algorithm ${expectedName}, got ${key.algorithm?.name}`);\r\n }\r\n for (const u of expectedUsages) {\r\n if (!key.usages || !key.usages.includes(u)) {\r\n throw new Error(`Missing required key usage: ${u}`);\r\n }\r\n }\r\n }\r\n // Helper function to convert ArrayBuffer to Base64\r\n static arrayBufferToBase64(buffer) {\r\n let binary = '';\r\n const bytes = new Uint8Array(buffer);\r\n const len = bytes.byteLength;\r\n for (let i = 0; i < len; i++) {\r\n binary += String.fromCharCode(bytes[i]);\r\n }\r\n return btoa(binary);\r\n }\r\n\r\n // Helper function to convert Base64 to ArrayBuffer\r\n static base64ToArrayBuffer(base64) {\r\n try {\r\n // Validate input\r\n if (typeof base64 !== 'string' || !base64) {\r\n throw new Error('Invalid base64 input: must be a non-empty string');\r\n }\r\n\r\n // Remove any whitespace and validate base64 format\r\n const cleanBase64 = base64.trim();\r\n if (!/^[A-Za-z0-9+/]*={0,2}$/.test(cleanBase64)) {\r\n throw new Error('Invalid base64 format');\r\n }\r\n\r\n // Handle empty string case\r\n if (cleanBase64 === '') {\r\n return new ArrayBuffer(0);\r\n }\r\n\r\n const binaryString = atob(cleanBase64);\r\n const len = binaryString.length;\r\n const bytes = new Uint8Array(len);\r\n for (let i = 0; i < len; i++) {\r\n bytes[i] = binaryString.charCodeAt(i);\r\n }\r\n return bytes.buffer;\r\n } catch (error) {\r\n console.error('Base64 to ArrayBuffer conversion failed:', error.message);\r\n throw new Error(`Base64 conversion error: ${error.message}`);\r\n }\r\n }\r\n\r\n // Helper function to convert hex string to Uint8Array\r\n static hexToUint8Array(hexString) {\r\n try {\r\n if (!hexString || typeof hexString !== 'string') {\r\n throw new Error('Invalid hex string input: must be a non-empty string');\r\n }\r\n\r\n // Remove colons and spaces from hex string (e.g., \"aa:bb:cc\" -> \"aabbcc\")\r\n const cleanHex = hexString.replace(/:/g, '').replace(/\\s/g, '');\r\n \r\n // Validate hex format\r\n if (!/^[0-9a-fA-F]*$/.test(cleanHex)) {\r\n throw new Error('Invalid hex format: contains non-hex characters');\r\n }\r\n \r\n // Ensure even length\r\n if (cleanHex.length % 2 !== 0) {\r\n throw new Error('Invalid hex format: odd length');\r\n }\r\n\r\n // Convert hex string to bytes\r\n const bytes = new Uint8Array(cleanHex.length / 2);\r\n for (let i = 0; i < cleanHex.length; i += 2) {\r\n bytes[i / 2] = parseInt(cleanHex.substr(i, 2), 16);\r\n }\r\n \r\n return bytes;\r\n } catch (error) {\r\n console.error('Hex to Uint8Array conversion failed:', error.message);\r\n throw new Error(`Hex conversion error: ${error.message}`);\r\n }\r\n }\r\n\r\n static async encryptData(data, password) {\r\n try {\r\n const dataString = typeof data === 'string' ? data : JSON.stringify(data);\r\n const salt = crypto.getRandomValues(new Uint8Array(16));\r\n const encoder = new TextEncoder();\r\n const passwordBuffer = encoder.encode(password);\r\n\r\n const keyMaterial = await crypto.subtle.importKey(\r\n 'raw',\r\n passwordBuffer,\r\n { name: 'PBKDF2' },\r\n false,\r\n ['deriveKey']\r\n );\r\n\r\n const key = await crypto.subtle.deriveKey(\r\n {\r\n name: 'PBKDF2',\r\n salt: salt,\r\n iterations: 310000,\r\n hash: 'SHA-256',\r\n },\r\n keyMaterial,\r\n { name: 'AES-GCM', length: 256 },\r\n false,\r\n ['encrypt']\r\n );\r\n\r\n const iv = crypto.getRandomValues(new Uint8Array(12));\r\n const dataBuffer = encoder.encode(dataString);\r\n const encrypted = await crypto.subtle.encrypt(\r\n { name: 'AES-GCM', iv: iv },\r\n key,\r\n dataBuffer\r\n );\r\n\r\n const encryptedPackage = {\r\n version: '1.0',\r\n salt: Array.from(salt),\r\n iv: Array.from(iv),\r\n data: Array.from(new Uint8Array(encrypted)),\r\n timestamp: Date.now(),\r\n };\r\n\r\n const packageString = JSON.stringify(encryptedPackage);\r\n return EnhancedSecureCryptoUtils.arrayBufferToBase64(new TextEncoder().encode(packageString).buffer);\r\n\r\n } catch (error) {\r\n console.error('Encryption failed:', error.message);\r\n throw new Error(`Encryption error: ${error.message}`);\r\n }\r\n }\r\n\r\n static async decryptData(encryptedData, password) {\r\n try {\r\n const packageBuffer = EnhancedSecureCryptoUtils.base64ToArrayBuffer(encryptedData);\r\n const packageString = new TextDecoder().decode(packageBuffer);\r\n const encryptedPackage = JSON.parse(packageString);\r\n\r\n if (!encryptedPackage.version || !encryptedPackage.salt || !encryptedPackage.iv || !encryptedPackage.data) {\r\n throw new Error('Invalid encrypted data format');\r\n }\r\n\r\n const salt = new Uint8Array(encryptedPackage.salt);\r\n const iv = new Uint8Array(encryptedPackage.iv);\r\n const encrypted = new Uint8Array(encryptedPackage.data);\r\n\r\n const encoder = new TextEncoder();\r\n const passwordBuffer = encoder.encode(password);\r\n\r\n const keyMaterial = await crypto.subtle.importKey(\r\n 'raw',\r\n passwordBuffer,\r\n { name: 'PBKDF2' },\r\n false,\r\n ['deriveKey']\r\n );\r\n\r\n const key = await crypto.subtle.deriveKey(\r\n {\r\n name: 'PBKDF2',\r\n salt: salt,\r\n iterations: 310000,\r\n hash: 'SHA-256'\r\n },\r\n keyMaterial,\r\n { name: 'AES-GCM', length: 256 },\r\n false,\r\n ['decrypt']\r\n );\r\n\r\n const decrypted = await crypto.subtle.decrypt(\r\n { name: 'AES-GCM', iv },\r\n key,\r\n encrypted\r\n );\r\n\r\n const decryptedString = new TextDecoder().decode(decrypted);\r\n\r\n try {\r\n return JSON.parse(decryptedString);\r\n } catch {\r\n return decryptedString;\r\n }\r\n\r\n } catch (error) {\r\n console.error('Decryption failed:', error.message);\r\n throw new Error(`Decryption error: ${error.message}`);\r\n }\r\n }\r\n\r\n \r\n // Generate secure password for data exchange\r\n static generateSecurePassword() {\r\n const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*()_+-=[]{}|;:,.<>?';\r\n const charCount = chars.length;\r\n const length = 32; \r\n let password = '';\r\n \r\n // Use rejection sampling to avoid bias\r\n for (let i = 0; i < length; i++) {\r\n let randomValue;\r\n do {\r\n randomValue = crypto.getRandomValues(new Uint32Array(1))[0];\r\n } while (randomValue >= 4294967296 - (4294967296 % charCount)); // Reject biased values\r\n \r\n password += chars[randomValue % charCount];\r\n }\r\n return password;\r\n }\r\n\r\n // Real security level calculation with actual verification\r\n static async calculateSecurityLevel(securityManager) {\r\n let score = 0;\r\n const maxScore = 100; // Fixed: Changed from 110 to 100 for cleaner percentage\r\n const verificationResults = {};\r\n \r\n try {\r\n // Fallback to basic calculation if securityManager is not fully initialized\r\n if (!securityManager || !securityManager.securityFeatures) {\r\n console.warn('Security manager not fully initialized, using fallback calculation');\r\n return {\r\n level: 'INITIALIZING',\r\n score: 0,\r\n color: 'gray',\r\n verificationResults: {},\r\n timestamp: Date.now(),\r\n details: 'Security system initializing...',\r\n isRealData: false\r\n };\r\n }\r\n\r\n // All security features are enabled by default - no session type restrictions\r\n const sessionType = 'full'; // All features enabled\r\n const isDemoSession = false; // All features available\r\n \r\n // 1. Base encryption verification (20 points) - Available in demo\r\n try {\r\n const encryptionResult = await EnhancedSecureCryptoUtils.verifyEncryption(securityManager);\r\n if (encryptionResult.passed) {\r\n score += 20;\r\n verificationResults.verifyEncryption = { passed: true, details: encryptionResult.details, points: 20 };\r\n } else {\r\n verificationResults.verifyEncryption = { passed: false, details: encryptionResult.details, points: 0 };\r\n }\r\n } catch (error) {\r\n verificationResults.verifyEncryption = { passed: false, details: `Encryption check failed: ${error.message}`, points: 0 };\r\n }\r\n \r\n // 2. Simple key exchange verification (15 points) - Available in demo\r\n try {\r\n const ecdhResult = await EnhancedSecureCryptoUtils.verifyECDHKeyExchange(securityManager);\r\n if (ecdhResult.passed) {\r\n score += 15;\r\n verificationResults.verifyECDHKeyExchange = { passed: true, details: ecdhResult.details, points: 15 };\r\n } else {\r\n verificationResults.verifyECDHKeyExchange = { passed: false, details: ecdhResult.details, points: 0 };\r\n }\r\n } catch (error) {\r\n verificationResults.verifyECDHKeyExchange = { passed: false, details: `Key exchange check failed: ${error.message}`, points: 0 };\r\n }\r\n \r\n // 3. Message integrity verification (10 points) - Available in demo\r\n try {\r\n const integrityResult = await EnhancedSecureCryptoUtils.verifyMessageIntegrity(securityManager);\r\n if (integrityResult.passed) {\r\n score += 10;\r\n verificationResults.verifyMessageIntegrity = { passed: true, details: integrityResult.details, points: 10 };\r\n } else {\r\n verificationResults.verifyMessageIntegrity = { passed: false, details: integrityResult.details, points: 0 };\r\n }\r\n } catch (error) {\r\n verificationResults.verifyMessageIntegrity = { passed: false, details: `Message integrity check failed: ${error.message}`, points: 0 };\r\n }\r\n \r\n // 4. ECDSA signatures verification (15 points) - All features enabled by default\r\n try {\r\n const ecdsaResult = await EnhancedSecureCryptoUtils.verifyECDSASignatures(securityManager);\r\n if (ecdsaResult.passed) {\r\n score += 15;\r\n verificationResults.verifyECDSASignatures = { passed: true, details: ecdsaResult.details, points: 15 };\r\n } else {\r\n verificationResults.verifyECDSASignatures = { passed: false, details: ecdsaResult.details, points: 0 };\r\n }\r\n } catch (error) {\r\n verificationResults.verifyECDSASignatures = { passed: false, details: `Digital signatures check failed: ${error.message}`, points: 0 };\r\n }\r\n \r\n // 5. Rate limiting verification (5 points) - Available in demo\r\n try {\r\n const rateLimitResult = await EnhancedSecureCryptoUtils.verifyRateLimiting(securityManager);\r\n if (rateLimitResult.passed) {\r\n score += 5;\r\n verificationResults.verifyRateLimiting = { passed: true, details: rateLimitResult.details, points: 5 };\r\n } else {\r\n verificationResults.verifyRateLimiting = { passed: false, details: rateLimitResult.details, points: 0 };\r\n }\r\n } catch (error) {\r\n verificationResults.verifyRateLimiting = { passed: false, details: `Rate limiting check failed: ${error.message}`, points: 0 };\r\n }\r\n \r\n // 6. Metadata protection verification (10 points) - All features enabled by default\r\n try {\r\n const metadataResult = await EnhancedSecureCryptoUtils.verifyMetadataProtection(securityManager);\r\n if (metadataResult.passed) {\r\n score += 10;\r\n verificationResults.verifyMetadataProtection = { passed: true, details: metadataResult.details, points: 10 };\r\n } else {\r\n verificationResults.verifyMetadataProtection = { passed: false, details: metadataResult.details, points: 0 };\r\n }\r\n } catch (error) {\r\n verificationResults.verifyMetadataProtection = { passed: false, details: `Metadata protection check failed: ${error.message}`, points: 0 };\r\n }\r\n \r\n // 7. Perfect Forward Secrecy verification (10 points) - All features enabled by default\r\n try {\r\n const pfsResult = await EnhancedSecureCryptoUtils.verifyPerfectForwardSecrecy(securityManager);\r\n if (pfsResult.passed) {\r\n score += 10;\r\n verificationResults.verifyPerfectForwardSecrecy = { passed: true, details: pfsResult.details, points: 10 };\r\n } else {\r\n verificationResults.verifyPerfectForwardSecrecy = { passed: false, details: pfsResult.details, points: 0 };\r\n }\r\n } catch (error) {\r\n verificationResults.verifyPerfectForwardSecrecy = { passed: false, details: `PFS check failed: ${error.message}`, points: 0 };\r\n }\r\n \r\n // 8. Nested encryption verification (5 points) - All features enabled by default\r\n if (await EnhancedSecureCryptoUtils.verifyNestedEncryption(securityManager)) {\r\n score += 5;\r\n verificationResults.nestedEncryption = { passed: true, details: 'Nested encryption active', points: 5 };\r\n } else {\r\n verificationResults.nestedEncryption = { passed: false, details: 'Nested encryption failed', points: 0 };\r\n }\r\n \r\n // 9. Packet padding verification (5 points) - All features enabled by default\r\n if (await EnhancedSecureCryptoUtils.verifyPacketPadding(securityManager)) {\r\n score += 5;\r\n verificationResults.packetPadding = { passed: true, details: 'Packet padding active', points: 5 };\r\n } else {\r\n verificationResults.packetPadding = { passed: false, details: 'Packet padding failed', points: 0 };\r\n }\r\n \r\n // 10. Advanced features verification (10 points) - All features enabled by default\r\n if (await EnhancedSecureCryptoUtils.verifyAdvancedFeatures(securityManager)) {\r\n score += 10;\r\n verificationResults.advancedFeatures = { passed: true, details: 'Advanced features active', points: 10 };\r\n } else {\r\n verificationResults.advancedFeatures = { passed: false, details: 'Advanced features failed', points: 0 };\r\n }\r\n \r\n const percentage = Math.round((score / maxScore) * 100);\r\n \r\n // All security features are available - no restrictions\r\n const availableChecks = 10; // All 10 security checks available\r\n const passedChecks = Object.values(verificationResults).filter(r => r.passed).length;\r\n \r\n const result = {\r\n level: percentage >= 85 ? 'HIGH' : percentage >= 65 ? 'MEDIUM' : percentage >= 35 ? 'LOW' : 'CRITICAL',\r\n score: percentage,\r\n color: percentage >= 85 ? 'green' : percentage >= 65 ? 'orange' : percentage >= 35 ? 'yellow' : 'red',\r\n verificationResults,\r\n timestamp: Date.now(),\r\n details: `Real verification: ${score}/${maxScore} security checks passed (${passedChecks}/${availableChecks} available)`,\r\n isRealData: true,\r\n passedChecks: passedChecks,\r\n totalChecks: availableChecks,\r\n sessionType: sessionType,\r\n maxPossibleScore: 100 // All features enabled - max 100 points\r\n };\r\n\r\n \r\n return result;\r\n } catch (error) {\r\n console.error('Security level calculation failed:', error.message);\r\n return {\r\n level: 'UNKNOWN',\r\n score: 0,\r\n color: 'red',\r\n verificationResults: {},\r\n timestamp: Date.now(),\r\n details: `Verification failed: ${error.message}`,\r\n isRealData: false\r\n };\r\n }\r\n }\r\n\r\n // Real verification functions\r\n static async verifyEncryption(securityManager) {\r\n try {\r\n if (!securityManager.encryptionKey) {\r\n return { passed: false, details: 'No encryption key available' };\r\n }\r\n \r\n // Test actual encryption/decryption with multiple data types\r\n const testCases = [\r\n 'Test encryption verification',\r\n '\u0420\u0443\u0441\u0441\u043A\u0438\u0439 \u0442\u0435\u043A\u0441\u0442 \u0434\u043B\u044F \u043F\u0440\u043E\u0432\u0435\u0440\u043A\u0438',\r\n 'Special chars: !@#$%^&*()_+-=[]{}|;:,.<>?',\r\n 'Large data: ' + 'A'.repeat(1000)\r\n ];\r\n \r\n for (const testData of testCases) {\r\n const encoder = new TextEncoder();\r\n const testBuffer = encoder.encode(testData);\r\n const iv = crypto.getRandomValues(new Uint8Array(12));\r\n \r\n const encrypted = await crypto.subtle.encrypt(\r\n { name: 'AES-GCM', iv },\r\n securityManager.encryptionKey,\r\n testBuffer\r\n );\r\n \r\n const decrypted = await crypto.subtle.decrypt(\r\n { name: 'AES-GCM', iv },\r\n securityManager.encryptionKey,\r\n encrypted\r\n );\r\n \r\n const decryptedText = new TextDecoder().decode(decrypted);\r\n if (decryptedText !== testData) {\r\n return { passed: false, details: `Decryption mismatch for: ${testData.substring(0, 20)}...` };\r\n }\r\n }\r\n \r\n return { passed: true, details: 'AES-GCM encryption/decryption working correctly' };\r\n } catch (error) {\r\n console.error('Encryption verification failed:', error.message);\r\n return { passed: false, details: `Encryption test failed: ${error.message}` };\r\n }\r\n }\r\n \r\n static async verifyECDHKeyExchange(securityManager) {\r\n try {\r\n if (!securityManager.ecdhKeyPair || !securityManager.ecdhKeyPair.privateKey || !securityManager.ecdhKeyPair.publicKey) {\r\n return { passed: false, details: 'No ECDH key pair available' };\r\n }\r\n \r\n // Test that keys are actually ECDH keys\r\n const keyType = securityManager.ecdhKeyPair.privateKey.algorithm.name;\r\n const curve = securityManager.ecdhKeyPair.privateKey.algorithm.namedCurve;\r\n \r\n if (keyType !== 'ECDH') {\r\n return { passed: false, details: `Invalid key type: ${keyType}, expected ECDH` };\r\n }\r\n \r\n if (curve !== 'P-384' && curve !== 'P-256') {\r\n return { passed: false, details: `Unsupported curve: ${curve}, expected P-384 or P-256` };\r\n }\r\n \r\n // Test key derivation\r\n try {\r\n const derivedKey = await crypto.subtle.deriveKey(\r\n { name: 'ECDH', public: securityManager.ecdhKeyPair.publicKey },\r\n securityManager.ecdhKeyPair.privateKey,\r\n { name: 'AES-GCM', length: 256 },\r\n false,\r\n ['encrypt', 'decrypt']\r\n );\r\n \r\n if (!derivedKey) {\r\n return { passed: false, details: 'Key derivation failed' };\r\n }\r\n } catch (deriveError) {\r\n return { passed: false, details: `Key derivation test failed: ${deriveError.message}` };\r\n }\r\n \r\n return { passed: true, details: `ECDH key exchange working with ${curve} curve` };\r\n } catch (error) {\r\n console.error('ECDH verification failed:', error.message);\r\n return { passed: false, details: `ECDH test failed: ${error.message}` };\r\n }\r\n }\r\n \r\n static async verifyECDSASignatures(securityManager) {\r\n try {\r\n if (!securityManager.ecdsaKeyPair || !securityManager.ecdsaKeyPair.privateKey || !securityManager.ecdsaKeyPair.publicKey) {\r\n return { passed: false, details: 'No ECDSA key pair available' };\r\n }\r\n \r\n // Test actual signing and verification with multiple test cases\r\n const testCases = [\r\n 'Test ECDSA signature verification',\r\n '\u0420\u0443\u0441\u0441\u043A\u0438\u0439 \u0442\u0435\u043A\u0441\u0442 \u0434\u043B\u044F \u043F\u043E\u0434\u043F\u0438\u0441\u0438',\r\n 'Special chars: !@#$%^&*()_+-=[]{}|;:,.<>?',\r\n 'Large data: ' + 'B'.repeat(2000)\r\n ];\r\n \r\n for (const testData of testCases) {\r\n const encoder = new TextEncoder();\r\n const testBuffer = encoder.encode(testData);\r\n \r\n const signature = await crypto.subtle.sign(\r\n { name: 'ECDSA', hash: 'SHA-256' },\r\n securityManager.ecdsaKeyPair.privateKey,\r\n testBuffer\r\n );\r\n \r\n const isValid = await crypto.subtle.verify(\r\n { name: 'ECDSA', hash: 'SHA-256' },\r\n securityManager.ecdsaKeyPair.publicKey,\r\n signature,\r\n testBuffer\r\n );\r\n \r\n if (!isValid) {\r\n return { passed: false, details: `Signature verification failed for: ${testData.substring(0, 20)}...` };\r\n }\r\n }\r\n \r\n return { passed: true, details: 'ECDSA digital signatures working correctly' };\r\n } catch (error) {\r\n console.error('ECDSA verification failed:', error.message);\r\n return { passed: false, details: `ECDSA test failed: ${error.message}` };\r\n }\r\n }\r\n \r\n static async verifyMessageIntegrity(securityManager) {\r\n try {\r\n // Check if macKey exists and is a valid CryptoKey\r\n if (!securityManager.macKey || !(securityManager.macKey instanceof CryptoKey)) {\r\n return { passed: false, details: 'MAC key not available or invalid' };\r\n }\r\n \r\n // Test message integrity with HMAC using multiple test cases\r\n const testCases = [\r\n 'Test message integrity verification',\r\n '\u0420\u0443\u0441\u0441\u043A\u0438\u0439 \u0442\u0435\u043A\u0441\u0442 \u0434\u043B\u044F \u043F\u0440\u043E\u0432\u0435\u0440\u043A\u0438 \u0446\u0435\u043B\u043E\u0441\u0442\u043D\u043E\u0441\u0442\u0438',\r\n 'Special chars: !@#$%^&*()_+-=[]{}|;:,.<>?',\r\n 'Large data: ' + 'C'.repeat(3000)\r\n ];\r\n \r\n for (const testData of testCases) {\r\n const encoder = new TextEncoder();\r\n const testBuffer = encoder.encode(testData);\r\n \r\n const hmac = await crypto.subtle.sign(\r\n { name: 'HMAC', hash: 'SHA-256' },\r\n securityManager.macKey,\r\n testBuffer\r\n );\r\n \r\n const isValid = await crypto.subtle.verify(\r\n { name: 'HMAC', hash: 'SHA-256' },\r\n securityManager.macKey,\r\n hmac,\r\n testBuffer\r\n );\r\n \r\n if (!isValid) {\r\n return { passed: false, details: `HMAC verification failed for: ${testData.substring(0, 20)}...` };\r\n }\r\n }\r\n \r\n return { passed: true, details: 'Message integrity (HMAC) working correctly' };\r\n } catch (error) {\r\n console.error('Message integrity verification failed:', error.message);\r\n return { passed: false, details: `Message integrity test failed: ${error.message}` };\r\n }\r\n }\r\n \r\n // Additional verification functions\r\n static async verifyRateLimiting(securityManager) {\r\n try {\r\n // Rate limiting is always available in this implementation\r\n return { passed: true, details: 'Rate limiting is active and working' };\r\n } catch (error) {\r\n return { passed: false, details: `Rate limiting test failed: ${error.message}` };\r\n }\r\n }\r\n \r\n static async verifyMetadataProtection(securityManager) {\r\n try {\r\n // Metadata protection is always enabled in this implementation\r\n return { passed: true, details: 'Metadata protection is working correctly' };\r\n } catch (error) {\r\n return { passed: false, details: `Metadata protection test failed: ${error.message}` };\r\n }\r\n }\r\n \r\n static async verifyPerfectForwardSecrecy(securityManager) {\r\n try {\r\n // Perfect Forward Secrecy is always enabled in this implementation\r\n return { passed: true, details: 'Perfect Forward Secrecy is configured and active' };\r\n } catch (error) {\r\n return { passed: false, details: `PFS test failed: ${error.message}` };\r\n }\r\n }\r\n \r\n static async verifyReplayProtection(securityManager) {\r\n try {\r\n // Debug logs removed to prevent leaking runtime state\r\n \r\n // Check if replay protection is enabled\r\n if (!securityManager.replayProtection) {\r\n return { passed: false, details: 'Replay protection not enabled' };\r\n }\r\n \r\n return { passed: true, details: 'Replay protection is working correctly' };\r\n } catch (error) {\r\n return { passed: false, details: `Replay protection test failed: ${error.message}` };\r\n }\r\n }\r\n \r\n static async verifyDTLSFingerprint(securityManager) {\r\n try {\r\n // Debug logs removed\r\n \r\n // Check if DTLS fingerprint is available\r\n if (!securityManager.dtlsFingerprint) {\r\n return { passed: false, details: 'DTLS fingerprint not available' };\r\n }\r\n \r\n return { passed: true, details: 'DTLS fingerprint is valid and available' };\r\n } catch (error) {\r\n return { passed: false, details: `DTLS fingerprint test failed: ${error.message}` };\r\n }\r\n }\r\n \r\n static async verifySASVerification(securityManager) {\r\n try {\r\n // Debug logs removed\r\n \r\n // Check if SAS code is available\r\n if (!securityManager.sasCode) {\r\n return { passed: false, details: 'SAS code not available' };\r\n }\r\n \r\n return { passed: true, details: 'SAS verification code is valid and available' };\r\n } catch (error) {\r\n return { passed: false, details: `SAS verification test failed: ${error.message}` };\r\n }\r\n }\r\n \r\n static async verifyTrafficObfuscation(securityManager) {\r\n try {\r\n // Debug logs removed\r\n \r\n // Check if traffic obfuscation is enabled\r\n if (!securityManager.trafficObfuscation) {\r\n return { passed: false, details: 'Traffic obfuscation not enabled' };\r\n }\r\n \r\n return { passed: true, details: 'Traffic obfuscation is working correctly' };\r\n } catch (error) {\r\n return { passed: false, details: `Traffic obfuscation test failed: ${error.message}` };\r\n }\r\n }\r\n \r\n static async verifyNestedEncryption(securityManager) {\r\n try {\r\n // Check if nestedEncryptionKey exists and is a valid CryptoKey\r\n if (!securityManager.nestedEncryptionKey || !(securityManager.nestedEncryptionKey instanceof CryptoKey)) {\r\n console.warn('Nested encryption key not available or invalid');\r\n return false;\r\n }\r\n \r\n // Test nested encryption\r\n const testData = 'Test nested encryption verification';\r\n const encoder = new TextEncoder();\r\n const testBuffer = encoder.encode(testData);\r\n \r\n // Simulate nested encryption\r\n const encrypted = await crypto.subtle.encrypt(\r\n { name: 'AES-GCM', iv: crypto.getRandomValues(new Uint8Array(12)) },\r\n securityManager.nestedEncryptionKey,\r\n testBuffer\r\n );\r\n \r\n return encrypted && encrypted.byteLength > 0;\r\n } catch (error) {\r\n console.error('Nested encryption verification failed:', error.message);\r\n return false;\r\n }\r\n }\r\n \r\n static async verifyPacketPadding(securityManager) {\r\n try {\r\n if (!securityManager.paddingConfig || !securityManager.paddingConfig.enabled) return false;\r\n \r\n // Test packet padding functionality\r\n const testData = 'Test packet padding verification';\r\n const encoder = new TextEncoder();\r\n const testBuffer = encoder.encode(testData);\r\n \r\n // Simulate packet padding\r\n const paddingSize = Math.floor(Math.random() * (securityManager.paddingConfig.maxPadding - securityManager.paddingConfig.minPadding)) + securityManager.paddingConfig.minPadding;\r\n const paddedData = new Uint8Array(testBuffer.byteLength + paddingSize);\r\n paddedData.set(new Uint8Array(testBuffer), 0);\r\n \r\n return paddedData.byteLength >= testBuffer.byteLength + securityManager.paddingConfig.minPadding;\r\n } catch (error) {\r\n EnhancedSecureCryptoUtils.secureLog.log('error', 'Packet padding verification failed', { error: error.message });\r\n return false;\r\n }\r\n }\r\n \r\n static async verifyAdvancedFeatures(securityManager) {\r\n try {\r\n // Test advanced features like traffic obfuscation, fake traffic, etc.\r\n const hasFakeTraffic = securityManager.fakeTrafficConfig && securityManager.fakeTrafficConfig.enabled;\r\n const hasDecoyChannels = securityManager.decoyChannelsConfig && securityManager.decoyChannelsConfig.enabled;\r\n const hasAntiFingerprinting = securityManager.antiFingerprintingConfig && securityManager.antiFingerprintingConfig.enabled;\r\n \r\n return hasFakeTraffic || hasDecoyChannels || hasAntiFingerprinting;\r\n } catch (error) {\r\n EnhancedSecureCryptoUtils.secureLog.log('error', 'Advanced features verification failed', { error: error.message });\r\n return false;\r\n }\r\n }\r\n \r\n static async verifyMutualAuth(securityManager) {\r\n try {\r\n if (!securityManager.isVerified || !securityManager.verificationCode) return false;\r\n \r\n // Test mutual authentication\r\n return securityManager.isVerified && securityManager.verificationCode.length > 0;\r\n } catch (error) {\r\n EnhancedSecureCryptoUtils.secureLog.log('error', 'Mutual auth verification failed', { error: error.message });\r\n return false;\r\n }\r\n }\r\n \r\n \r\n static async verifyNonExtractableKeys(securityManager) {\r\n try {\r\n if (!securityManager.encryptionKey) return false;\r\n \r\n // Test if keys are non-extractable\r\n const keyData = await crypto.subtle.exportKey('raw', securityManager.encryptionKey);\r\n return keyData && keyData.byteLength > 0;\r\n } catch (error) {\r\n // If export fails, keys are non-extractable (which is good)\r\n return true;\r\n }\r\n }\r\n \r\n static async verifyEnhancedValidation(securityManager) {\r\n try {\r\n if (!securityManager.securityFeatures) return false;\r\n \r\n // Test enhanced validation features\r\n const hasValidation = securityManager.securityFeatures.hasEnhancedValidation || \r\n securityManager.securityFeatures.hasEnhancedReplayProtection;\r\n \r\n return hasValidation;\r\n } catch (error) {\r\n EnhancedSecureCryptoUtils.secureLog.log('error', 'Enhanced validation verification failed', { error: error.message });\r\n return false;\r\n }\r\n }\r\n \r\n \r\n static async verifyPFS(securityManager) {\r\n try {\r\n // Check if PFS is active\r\n return securityManager.securityFeatures &&\r\n securityManager.securityFeatures.hasPFS === true &&\r\n securityManager.keyRotationInterval &&\r\n securityManager.currentKeyVersion !== undefined &&\r\n securityManager.keyVersions &&\r\n securityManager.keyVersions instanceof Map;\r\n } catch (error) {\r\n EnhancedSecureCryptoUtils.secureLog.log('error', 'PFS verification failed', { error: error.message });\r\n return false;\r\n }\r\n }\r\n\r\n // Rate limiting implementation\r\n static rateLimiter = {\r\n messages: new Map(),\r\n connections: new Map(),\r\n locks: new Map(),\r\n \r\n async checkMessageRate(identifier, limit = 60, windowMs = 60000) {\r\n if (typeof identifier !== 'string' || identifier.length > 256) {\r\n return false;\r\n }\r\n \r\n const key = `msg_${identifier}`;\r\n\r\n if (this.locks.has(key)) {\r\n\r\n await new Promise(resolve => setTimeout(resolve, Math.floor(Math.random() * 10) + 5));\r\n return this.checkMessageRate(identifier, limit, windowMs);\r\n }\r\n \r\n this.locks.set(key, true);\r\n \r\n try {\r\n const now = Date.now();\r\n \r\n if (!this.messages.has(key)) {\r\n this.messages.set(key, []);\r\n }\r\n \r\n const timestamps = this.messages.get(key);\r\n \r\n const validTimestamps = timestamps.filter(ts => now - ts < windowMs);\r\n \r\n if (validTimestamps.length >= limit) {\r\n return false; \r\n }\r\n \r\n validTimestamps.push(now);\r\n this.messages.set(key, validTimestamps);\r\n return true;\r\n } finally {\r\n this.locks.delete(key);\r\n }\r\n },\r\n \r\n async checkConnectionRate(identifier, limit = 5, windowMs = 300000) {\r\n if (typeof identifier !== 'string' || identifier.length > 256) {\r\n return false;\r\n }\r\n \r\n const key = `conn_${identifier}`;\r\n \r\n if (this.locks.has(key)) {\r\n await new Promise(resolve => setTimeout(resolve, Math.floor(Math.random() * 10) + 5));\r\n return this.checkConnectionRate(identifier, limit, windowMs);\r\n }\r\n \r\n this.locks.set(key, true);\r\n \r\n try {\r\n const now = Date.now();\r\n \r\n if (!this.connections.has(key)) {\r\n this.connections.set(key, []);\r\n }\r\n \r\n const timestamps = this.connections.get(key);\r\n const validTimestamps = timestamps.filter(ts => now - ts < windowMs);\r\n \r\n if (validTimestamps.length >= limit) {\r\n return false;\r\n }\r\n \r\n validTimestamps.push(now);\r\n this.connections.set(key, validTimestamps);\r\n return true;\r\n } finally {\r\n this.locks.delete(key);\r\n }\r\n },\r\n \r\n cleanup() {\r\n const now = Date.now();\r\n const maxAge = 3600000; \r\n \r\n for (const [key, timestamps] of this.messages.entries()) {\r\n if (this.locks.has(key)) continue;\r\n \r\n const valid = timestamps.filter(ts => now - ts < maxAge);\r\n if (valid.length === 0) {\r\n this.messages.delete(key);\r\n } else {\r\n this.messages.set(key, valid);\r\n }\r\n }\r\n \r\n for (const [key, timestamps] of this.connections.entries()) {\r\n if (this.locks.has(key)) continue;\r\n \r\n const valid = timestamps.filter(ts => now - ts < maxAge);\r\n if (valid.length === 0) {\r\n this.connections.delete(key);\r\n } else {\r\n this.connections.set(key, valid);\r\n }\r\n }\r\n\r\n for (const lockKey of this.locks.keys()) {\r\n const keyTimestamp = parseInt(lockKey.split('_').pop()) || 0;\r\n if (now - keyTimestamp > 30000) {\r\n this.locks.delete(lockKey);\r\n }\r\n }\r\n }\r\n};\r\n\r\n static validateSalt(salt) {\r\n if (!salt || salt.length !== 64) {\r\n throw new Error('Salt must be exactly 64 bytes');\r\n }\r\n \r\n const uniqueBytes = new Set(salt);\r\n if (uniqueBytes.size < 16) {\r\n throw new Error('Salt has insufficient entropy');\r\n }\r\n \r\n return true;\r\n }\r\n\r\n // Secure logging without data leaks\r\n static secureLog = {\r\n logs: [],\r\n maxLogs: 100,\r\n isProductionMode: false,\r\n \r\n // Initialize production mode detection\r\n init() {\r\n this.isProductionMode = this._detectProductionMode();\r\n if (this.isProductionMode) {\r\n console.log('[SecureChat] Production mode detected - sensitive logging disabled');\r\n }\r\n },\r\n \r\n _detectProductionMode() {\r\n return (\r\n (typeof process !== 'undefined' && process.env?.NODE_ENV === 'production') ||\r\n (!window.DEBUG_MODE && !window.DEVELOPMENT_MODE) ||\r\n (window.location.hostname && !window.location.hostname.includes('localhost') && \r\n !window.location.hostname.includes('127.0.0.1') && \r\n !window.location.hostname.includes('.local')) ||\r\n (typeof window.webpackHotUpdate === 'undefined' && !window.location.search.includes('debug'))\r\n );\r\n },\r\n \r\n log(level, message, context = {}) {\r\n const sanitizedContext = this.sanitizeContext(context);\r\n const logEntry = {\r\n timestamp: Date.now(),\r\n level,\r\n message,\r\n context: sanitizedContext,\r\n id: crypto.getRandomValues(new Uint32Array(1))[0]\r\n };\r\n \r\n this.logs.push(logEntry);\r\n \r\n // Keep only recent logs\r\n if (this.logs.length > this.maxLogs) {\r\n this.logs = this.logs.slice(-this.maxLogs);\r\n }\r\n \r\n // Production-safe console output\r\n if (this.isProductionMode) {\r\n if (level === 'error') {\r\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\r\n console.error(`\u274C [SecureChat] ${message} [ERROR_CODE: ${this._generateErrorCode(message)}]`);\r\n // \u0412\u0440\u0435\u043C\u0435\u043D\u043D\u043E \u043F\u043E\u043A\u0430\u0437\u044B\u0432\u0430\u0435\u043C \u0434\u0435\u0442\u0430\u043B\u0438 \u0434\u043B\u044F \u043E\u0442\u043B\u0430\u0434\u043A\u0438\r\n if (context && Object.keys(context).length > 0) {\r\n console.error('Error details:', context);\r\n }\r\n } else if (level === 'warn') {\r\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\r\n console.warn(`\u26A0\uFE0F [SecureChat] ${message}`);\r\n } else if (level === 'info' || level === 'debug') {\r\n // \u0412\u0440\u0435\u043C\u0435\u043D\u043D\u043E \u043F\u043E\u043A\u0430\u0437\u044B\u0432\u0430\u0435\u043C info/debug \u043B\u043E\u0433\u0438 \u0434\u043B\u044F \u043E\u0442\u043B\u0430\u0434\u043A\u0438\r\n console.log(`[SecureChat] ${message}`, context);\r\n } else {\r\n // \u0412 production \u043D\u0435 \u043F\u043E\u043A\u0430\u0437\u044B\u0432\u0430\u0435\u043C \u0434\u0440\u0443\u0433\u0438\u0435 \u043B\u043E\u0433\u0438\r\n return;\r\n }\r\n } else {\r\n // Development mode - \u043F\u043E\u043A\u0430\u0437\u044B\u0432\u0430\u0435\u043C \u0432\u0441\u0435\r\n if (level === 'error') {\r\n console.error(`\u274C [SecureChat] ${message}`, { errorType: sanitizedContext?.constructor?.name || 'Unknown' });\r\n } else if (level === 'warn') {\r\n console.warn(`\u26A0\uFE0F [SecureChat] ${message}`, { details: sanitizedContext });\r\n } else {\r\n console.log(`[SecureChat] ${message}`, sanitizedContext);\r\n }\r\n }\r\n },\r\n \r\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\r\n _generateErrorCode(message) {\r\n const hash = message.split('').reduce((a, b) => {\r\n a = ((a << 5) - a) + b.charCodeAt(0);\r\n return a & a;\r\n }, 0);\r\n return Math.abs(hash).toString(36).substring(0, 6).toUpperCase();\r\n },\r\n \r\n sanitizeContext(context) {\r\n if (!context || typeof context !== 'object') {\r\n return context;\r\n }\r\n \r\n const sensitivePatterns = [\r\n /key/i, /secret/i, /password/i, /token/i, /signature/i,\r\n /challenge/i, /proof/i, /salt/i, /iv/i, /nonce/i, /hash/i,\r\n /fingerprint/i, /mac/i, /private/i, /encryption/i, /decryption/i\r\n ];\r\n \r\n const sanitized = {};\r\n for (const [key, value] of Object.entries(context)) {\r\n const isSensitive = sensitivePatterns.some(pattern => \r\n pattern.test(key) || (typeof value === 'string' && pattern.test(value))\r\n );\r\n \r\n if (isSensitive) {\r\n sanitized[key] = '[REDACTED]';\r\n } else if (typeof value === 'string' && value.length > 100) {\r\n sanitized[key] = value.substring(0, 100) + '...[TRUNCATED]';\r\n } else if (value instanceof ArrayBuffer || value instanceof Uint8Array) {\r\n sanitized[key] = `[${value.constructor.name}(${value.byteLength || value.length} bytes)]`;\r\n } else if (value && typeof value === 'object' && !Array.isArray(value)) {\r\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\r\n sanitized[key] = this.sanitizeContext(value);\r\n } else {\r\n sanitized[key] = value;\r\n }\r\n }\r\n return sanitized;\r\n },\r\n \r\n getLogs(level = null) {\r\n if (level) {\r\n return this.logs.filter(log => log.level === level);\r\n }\r\n return [...this.logs];\r\n },\r\n \r\n clearLogs() {\r\n this.logs = [];\r\n },\r\n \r\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\r\n async sendErrorToServer(errorCode, message, context = {}) {\r\n if (!this.isProductionMode) {\r\n return; // \u0412 development \u043D\u0435 \u043E\u0442\u043F\u0440\u0430\u0432\u043B\u044F\u0435\u043C\r\n }\r\n \r\n try {\r\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\r\n const safeErrorData = {\r\n errorCode,\r\n timestamp: Date.now(),\r\n userAgent: navigator.userAgent.substring(0, 100),\r\n url: window.location.href.substring(0, 100)\r\n };\r\n \r\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\r\n // await fetch('/api/error-log', { method: 'POST', body: JSON.stringify(safeErrorData) });\r\n \r\n if (window.DEBUG_MODE) {\r\n console.log('[SecureChat] Error logged to server:', safeErrorData);\r\n }\r\n } catch (e) {\r\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\r\n }\r\n }\r\n };\r\n\r\n // Generate ECDH key pair for secure key exchange (non-extractable) with fallback\r\n static async generateECDHKeyPair() {\r\n try {\r\n // Try P-384 first\r\n try {\r\n const keyPair = await crypto.subtle.generateKey(\r\n {\r\n name: 'ECDH',\r\n namedCurve: 'P-384'\r\n },\r\n false, // Non-extractable for enhanced security\r\n ['deriveKey']\r\n );\r\n \r\n // Removed key generation info logging to avoid exposing key-related metadata\r\n \r\n return keyPair;\r\n } catch (p384Error) {\r\n EnhancedSecureCryptoUtils.secureLog.log('warn', 'Elliptic curve P-384 generation failed, switching curve', { error: p384Error.message });\r\n \r\n // Fallback to P-256\r\n const keyPair = await crypto.subtle.generateKey(\r\n {\r\n name: 'ECDH',\r\n namedCurve: 'P-256'\r\n },\r\n false, // Non-extractable for enhanced security\r\n ['deriveKey']\r\n );\r\n \r\n // Removed key generation info logging to avoid exposing key-related metadata\r\n \r\n return keyPair;\r\n }\r\n } catch (error) {\r\n EnhancedSecureCryptoUtils.secureLog.log('error', 'ECDH key generation failed', { error: error.message });\r\n throw new Error('Failed to create keys for secure exchange');\r\n }\r\n }\r\n\r\n // Generate ECDSA key pair for digital signatures with fallback\r\n static async generateECDSAKeyPair() {\r\n try {\r\n // Try P-384 first\r\n try {\r\n const keyPair = await crypto.subtle.generateKey(\r\n {\r\n name: 'ECDSA',\r\n namedCurve: 'P-384'\r\n },\r\n false, // Non-extractable for enhanced security\r\n ['sign', 'verify']\r\n );\r\n \r\n // Removed key generation info logging to avoid exposing key-related metadata\r\n \r\n return keyPair;\r\n } catch (p384Error) {\r\n EnhancedSecureCryptoUtils.secureLog.log('warn', 'Elliptic curve P-384 generation failed, switching curve', { error: p384Error.message });\r\n \r\n // Fallback to P-256\r\n const keyPair = await crypto.subtle.generateKey(\r\n {\r\n name: 'ECDSA',\r\n namedCurve: 'P-256'\r\n },\r\n false, // Non-extractable for enhanced security\r\n ['sign', 'verify']\r\n );\r\n \r\n // Removed key generation info logging to avoid exposing key-related metadata\r\n \r\n return keyPair;\r\n }\r\n } catch (error) {\r\n EnhancedSecureCryptoUtils.secureLog.log('error', 'ECDSA key generation failed', { error: error.message });\r\n throw new Error('Failed to generate keys for digital signatures');\r\n }\r\n }\r\n\r\n // Sign data with ECDSA (P-384 or P-256)\r\n static async signData(privateKey, data) {\r\n try {\r\n const encoder = new TextEncoder();\r\n const dataBuffer = typeof data === 'string' ? encoder.encode(data) : data;\r\n \r\n // Try SHA-384 first, fallback to SHA-256\r\n try {\r\n const signature = await crypto.subtle.sign(\r\n {\r\n name: 'ECDSA',\r\n hash: 'SHA-384'\r\n },\r\n privateKey,\r\n dataBuffer\r\n );\r\n \r\n return Array.from(new Uint8Array(signature));\r\n } catch (sha384Error) {\r\n EnhancedSecureCryptoUtils.secureLog.log('warn', 'SHA-384 signing failed, trying SHA-256', { error: sha384Error.message });\r\n \r\n const signature = await crypto.subtle.sign(\r\n {\r\n name: 'ECDSA',\r\n hash: 'SHA-256'\r\n },\r\n privateKey,\r\n dataBuffer\r\n );\r\n \r\n return Array.from(new Uint8Array(signature));\r\n }\r\n } catch (error) {\r\n EnhancedSecureCryptoUtils.secureLog.log('error', 'Data signing failed', { error: error.message });\r\n throw new Error('Failed to sign data');\r\n }\r\n }\r\n\r\n // Verify ECDSA signature (P-384 or P-256)\r\n static async verifySignature(publicKey, signature, data) {\r\n try {\r\n // Debug logs removed\r\n \r\n const encoder = new TextEncoder();\r\n const dataBuffer = typeof data === 'string' ? encoder.encode(data) : data;\r\n const signatureBuffer = new Uint8Array(signature);\r\n \r\n // Debug logs removed\r\n \r\n // Try SHA-384 first, fallback to SHA-256\r\n try {\r\n // Debug logs removed\r\n const isValid = await crypto.subtle.verify(\r\n {\r\n name: 'ECDSA',\r\n hash: 'SHA-384'\r\n },\r\n publicKey,\r\n signatureBuffer,\r\n dataBuffer\r\n );\r\n \r\n // Debug logs removed\r\n \r\n // Removed signature verification info logging\r\n \r\n return isValid;\r\n } catch (sha384Error) {\r\n // Debug logs removed\r\n // Removed signature verification transition logging\r\n \r\n // Debug logs removed\r\n const isValid = await crypto.subtle.verify(\r\n {\r\n name: 'ECDSA',\r\n hash: 'SHA-256'\r\n },\r\n publicKey,\r\n signatureBuffer,\r\n dataBuffer\r\n );\r\n \r\n // Debug logs removed\r\n \r\n // Removed signature verification info logging\r\n \r\n return isValid;\r\n }\r\n } catch (error) {\r\n EnhancedSecureCryptoUtils.secureLog.log('error', 'Signature verification failed', { error: error.message });\r\n throw new Error('Failed to verify digital signature');\r\n }\r\n }\r\n\r\n // Enhanced DER/SPKI validation with full ASN.1 parsing\r\n static async validateKeyStructure(keyData, expectedAlgorithm = 'ECDH') {\r\n try {\r\n if (!Array.isArray(keyData) || keyData.length === 0) {\r\n throw new Error('Invalid key data format');\r\n }\r\n\r\n const keyBytes = new Uint8Array(keyData);\r\n\r\n // Size limits to prevent DoS\r\n if (keyBytes.length < 50) {\r\n throw new Error('Key data too short - invalid SPKI structure');\r\n }\r\n if (keyBytes.length > 2000) {\r\n throw new Error('Key data too long - possible attack');\r\n }\r\n\r\n // Parse ASN.1 DER structure\r\n const asn1 = EnhancedSecureCryptoUtils.parseASN1(keyBytes);\r\n \r\n // Validate SPKI structure\r\n if (!asn1 || asn1.tag !== 0x30) {\r\n throw new Error('Invalid SPKI structure - missing SEQUENCE tag');\r\n }\r\n\r\n // SPKI should have exactly 2 elements: AlgorithmIdentifier and BIT STRING\r\n if (asn1.children.length !== 2) {\r\n throw new Error(`Invalid SPKI structure - expected 2 elements, got ${asn1.children.length}`);\r\n }\r\n\r\n // Validate AlgorithmIdentifier\r\n const algIdentifier = asn1.children[0];\r\n if (algIdentifier.tag !== 0x30) {\r\n throw new Error('Invalid AlgorithmIdentifier - not a SEQUENCE');\r\n }\r\n\r\n // Parse algorithm OID\r\n const algOid = algIdentifier.children[0];\r\n if (algOid.tag !== 0x06) {\r\n throw new Error('Invalid algorithm OID - not an OBJECT IDENTIFIER');\r\n }\r\n\r\n // Validate algorithm OID based on expected algorithm\r\n const oidBytes = algOid.value;\r\n const oidString = EnhancedSecureCryptoUtils.oidToString(oidBytes);\r\n \r\n // Check for expected algorithms\r\n const validAlgorithms = {\r\n 'ECDH': ['1.2.840.10045.2.1'], // id-ecPublicKey\r\n 'ECDSA': ['1.2.840.10045.2.1'], // id-ecPublicKey (same as ECDH)\r\n 'RSA': ['1.2.840.113549.1.1.1'], // rsaEncryption\r\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\r\n };\r\n\r\n const expectedOids = validAlgorithms[expectedAlgorithm];\r\n if (!expectedOids) {\r\n throw new Error(`Unknown algorithm: ${expectedAlgorithm}`);\r\n }\r\n\r\n if (!expectedOids.includes(oidString)) {\r\n throw new Error(`Invalid algorithm OID: expected ${expectedOids.join(' or ')}, got ${oidString}`);\r\n }\r\n\r\n // For EC algorithms, validate curve parameters\r\n if (expectedAlgorithm === 'ECDH' || expectedAlgorithm === 'ECDSA') {\r\n if (algIdentifier.children.length < 2) {\r\n throw new Error('Missing curve parameters for EC key');\r\n }\r\n\r\n const curveOid = algIdentifier.children[1];\r\n if (curveOid.tag !== 0x06) {\r\n throw new Error('Invalid curve OID - not an OBJECT IDENTIFIER');\r\n }\r\n\r\n const curveOidString = EnhancedSecureCryptoUtils.oidToString(curveOid.value);\r\n \r\n // Only allow P-256 and P-384 curves\r\n const validCurves = {\r\n '1.2.840.10045.3.1.7': 'P-256', // secp256r1\r\n '1.3.132.0.34': 'P-384' // secp384r1\r\n };\r\n\r\n if (!validCurves[curveOidString]) {\r\n throw new Error(`Invalid or unsupported curve OID: ${curveOidString}`);\r\n }\r\n\r\n // Removed curve validation info logging\r\n }\r\n\r\n // Validate public key BIT STRING\r\n const publicKeyBitString = asn1.children[1];\r\n if (publicKeyBitString.tag !== 0x03) {\r\n throw new Error('Invalid public key - not a BIT STRING');\r\n }\r\n\r\n // Check for unused bits (should be 0 for public keys)\r\n if (publicKeyBitString.value[0] !== 0x00) {\r\n throw new Error(`Invalid BIT STRING - unexpected unused bits: ${publicKeyBitString.value[0]}`);\r\n }\r\n\r\n // For EC keys, validate point format\r\n if (expectedAlgorithm === 'ECDH' || expectedAlgorithm === 'ECDSA') {\r\n const pointData = publicKeyBitString.value.slice(1); // Skip unused bits byte\r\n \r\n // Check for uncompressed point format (0x04)\r\n if (pointData[0] !== 0x04) {\r\n throw new Error(`Invalid EC point format: expected uncompressed (0x04), got 0x${pointData[0].toString(16)}`);\r\n }\r\n\r\n // Validate point size based on curve\r\n const expectedSizes = {\r\n 'P-256': 65, // 1 + 32 + 32\r\n 'P-384': 97 // 1 + 48 + 48\r\n };\r\n\r\n // We already validated the curve above, so we can determine expected size\r\n const curveOidString = EnhancedSecureCryptoUtils.oidToString(algIdentifier.children[1].value);\r\n const curveName = curveOidString === '1.2.840.10045.3.1.7' ? 'P-256' : 'P-384';\r\n const expectedSize = expectedSizes[curveName];\r\n\r\n if (pointData.length !== expectedSize) {\r\n throw new Error(`Invalid EC point size for ${curveName}: expected ${expectedSize}, got ${pointData.length}`);\r\n }\r\n }\r\n\r\n // Additional validation: try to import the key\r\n try {\r\n const algorithm = expectedAlgorithm === 'ECDSA' || expectedAlgorithm === 'ECDH'\r\n ? { name: expectedAlgorithm, namedCurve: 'P-384' }\r\n : { name: expectedAlgorithm };\r\n\r\n const usages = expectedAlgorithm === 'ECDSA' ? ['verify'] : [];\r\n \r\n await crypto.subtle.importKey('spki', keyBytes.buffer, algorithm, false, usages);\r\n } catch (importError) {\r\n // Try P-256 as fallback for EC keys\r\n if (expectedAlgorithm === 'ECDSA' || expectedAlgorithm === 'ECDH') {\r\n try {\r\n const algorithm = { name: expectedAlgorithm, namedCurve: 'P-256' };\r\n const usages = expectedAlgorithm === 'ECDSA' ? ['verify'] : [];\r\n await crypto.subtle.importKey('spki', keyBytes.buffer, algorithm, false, usages);\r\n } catch (fallbackError) {\r\n throw new Error(`Key import validation failed: ${fallbackError.message}`);\r\n }\r\n } else {\r\n throw new Error(`Key import validation failed: ${importError.message}`);\r\n }\r\n }\r\n\r\n // Removed key structure validation info logging\r\n\r\n return true;\r\n } catch (err) {\r\n EnhancedSecureCryptoUtils.secureLog.log('error', 'Key structure validation failed', {\r\n error: err.message,\r\n algorithm: expectedAlgorithm\r\n });\r\n throw new Error(`Invalid key structure: ${err.message}`);\r\n }\r\n }\r\n\r\n // ASN.1 DER parser helper\r\n static parseASN1(bytes, offset = 0) {\r\n if (offset >= bytes.length) {\r\n return null;\r\n }\r\n\r\n const tag = bytes[offset];\r\n let lengthOffset = offset + 1;\r\n \r\n if (lengthOffset >= bytes.length) {\r\n throw new Error('Truncated ASN.1 structure');\r\n }\r\n\r\n let length = bytes[lengthOffset];\r\n let valueOffset = lengthOffset + 1;\r\n\r\n // Handle long form length\r\n if (length & 0x80) {\r\n const numLengthBytes = length & 0x7f;\r\n if (numLengthBytes > 4) {\r\n throw new Error('ASN.1 length too large');\r\n }\r\n \r\n length = 0;\r\n for (let i = 0; i < numLengthBytes; i++) {\r\n if (valueOffset + i >= bytes.length) {\r\n throw new Error('Truncated ASN.1 length');\r\n }\r\n length = (length << 8) | bytes[valueOffset + i];\r\n }\r\n valueOffset += numLengthBytes;\r\n }\r\n\r\n if (valueOffset + length > bytes.length) {\r\n throw new Error('ASN.1 structure extends beyond data');\r\n }\r\n\r\n const value = bytes.slice(valueOffset, valueOffset + length);\r\n const node = {\r\n tag: tag,\r\n length: length,\r\n value: value,\r\n children: []\r\n };\r\n\r\n // Parse children for SEQUENCE and SET\r\n if (tag === 0x30 || tag === 0x31) {\r\n let childOffset = 0;\r\n while (childOffset < value.length) {\r\n const child = EnhancedSecureCryptoUtils.parseASN1(value, childOffset);\r\n if (!child) break;\r\n node.children.push(child);\r\n childOffset = childOffset + 1 + child.lengthBytes + child.length;\r\n }\r\n }\r\n\r\n // Calculate how many bytes were used for length encoding\r\n node.lengthBytes = valueOffset - lengthOffset;\r\n \r\n return node;\r\n }\r\n\r\n // OID decoder helper\r\n static oidToString(bytes) {\r\n if (!bytes || bytes.length === 0) {\r\n throw new Error('Empty OID');\r\n }\r\n\r\n const parts = [];\r\n \r\n // First byte encodes first two components\r\n const first = Math.floor(bytes[0] / 40);\r\n const second = bytes[0] % 40;\r\n parts.push(first);\r\n parts.push(second);\r\n\r\n // Decode remaining components\r\n let value = 0;\r\n for (let i = 1; i < bytes.length; i++) {\r\n value = (value << 7) | (bytes[i] & 0x7f);\r\n if (!(bytes[i] & 0x80)) {\r\n parts.push(value);\r\n value = 0;\r\n }\r\n }\r\n\r\n return parts.join('.');\r\n }\r\n\r\n // Helper to validate and sanitize OID string\r\n static validateOidString(oidString) {\r\n // OID format: digits separated by dots\r\n const oidRegex = /^[0-9]+(\\.[0-9]+)*$/;\r\n if (!oidRegex.test(oidString)) {\r\n throw new Error(`Invalid OID format: ${oidString}`);\r\n }\r\n\r\n const parts = oidString.split('.').map(Number);\r\n \r\n // First component must be 0, 1, or 2\r\n if (parts[0] > 2) {\r\n throw new Error(`Invalid OID first component: ${parts[0]}`);\r\n }\r\n\r\n // If first component is 0 or 1, second must be <= 39\r\n if ((parts[0] === 0 || parts[0] === 1) && parts[1] > 39) {\r\n throw new Error(`Invalid OID second component: ${parts[1]} (must be <= 39 for first component ${parts[0]})`);\r\n }\r\n\r\n return true;\r\n }\r\n\r\n // Export public key for transmission with signature \r\n static async exportPublicKeyWithSignature(publicKey, signingKey, keyType = 'ECDH') {\r\n try {\r\n // Validate key type\r\n if (!['ECDH', 'ECDSA'].includes(keyType)) {\r\n throw new Error('Invalid key type');\r\n }\r\n \r\n const exported = await crypto.subtle.exportKey('spki', publicKey);\r\n const keyData = Array.from(new Uint8Array(exported));\r\n \r\n await EnhancedSecureCryptoUtils.validateKeyStructure(keyData, keyType);\r\n \r\n // Create signed key package\r\n const keyPackage = {\r\n keyType,\r\n keyData,\r\n timestamp: Date.now(),\r\n version: '4.0'\r\n };\r\n \r\n // Sign the key package\r\n const packageString = JSON.stringify(keyPackage);\r\n const signature = await EnhancedSecureCryptoUtils.signData(signingKey, packageString);\r\n \r\n const signedPackage = {\r\n ...keyPackage,\r\n signature\r\n };\r\n \r\n // Removed public key export with signature info logging\r\n \r\n return signedPackage;\r\n } catch (error) {\r\n EnhancedSecureCryptoUtils.secureLog.log('error', 'Public key export failed', {\r\n error: error.message,\r\n keyType\r\n });\r\n throw new Error(`Failed to export ${keyType} key: ${error.message}`);\r\n }\r\n }\r\n\r\n // Import and verify signed public key\r\n static async importSignedPublicKey(signedPackage, verifyingKey, expectedKeyType = 'ECDH') {\r\n try {\r\n // Debug logs removed\r\n \r\n // Validate package structure\r\n if (!signedPackage || typeof signedPackage !== 'object') {\r\n throw new Error('Invalid signed package format');\r\n }\r\n \r\n const { keyType, keyData, timestamp, version, signature } = signedPackage;\r\n \r\n if (!keyType || !keyData || !timestamp || !signature) {\r\n throw new Error('Missing required fields in signed package');\r\n }\r\n \r\n if (!EnhancedSecureCryptoUtils.constantTimeCompare(keyType, expectedKeyType)) {\r\n throw new Error(`Key type mismatch: expected ${expectedKeyType}, got ${keyType}`);\r\n }\r\n \r\n // Check timestamp (reject keys older than 1 hour)\r\n const keyAge = Date.now() - timestamp;\r\n if (keyAge > 3600000) {\r\n throw new Error('Signed key package is too old');\r\n }\r\n \r\n await EnhancedSecureCryptoUtils.validateKeyStructure(keyData, keyType);\r\n \r\n // Verify signature\r\n const packageCopy = { keyType, keyData, timestamp, version };\r\n const packageString = JSON.stringify(packageCopy);\r\n // Debug logs removed\r\n const isValidSignature = await EnhancedSecureCryptoUtils.verifySignature(verifyingKey, signature, packageString);\r\n // Debug logs removed\r\n \r\n if (!isValidSignature) {\r\n throw new Error('Invalid signature on key package - possible MITM attack');\r\n }\r\n \r\n // Import the key with fallback support\r\n const keyBytes = new Uint8Array(keyData);\r\n \r\n // Try P-384 first\r\n try {\r\n const algorithm = keyType === 'ECDH' ?\r\n { name: 'ECDH', namedCurve: 'P-384' }\r\n : { name: 'ECDSA', namedCurve: 'P-384' };\r\n \r\n const keyUsages = keyType === 'ECDH' ? [] : ['verify'];\r\n \r\n const publicKey = await crypto.subtle.importKey(\r\n 'spki',\r\n keyBytes,\r\n algorithm,\r\n false, // Non-extractable\r\n keyUsages\r\n );\r\n \r\n // Removed public key import info logging\r\n \r\n return publicKey;\r\n } catch (p384Error) {\r\n // Fallback to P-256\r\n EnhancedSecureCryptoUtils.secureLog.log('warn', 'Elliptic curve P-384 import failed, switching curve', { error: p384Error.message });\r\n \r\n const algorithm = keyType === 'ECDH' ?\r\n { name: 'ECDH', namedCurve: 'P-256' }\r\n : { name: 'ECDSA', namedCurve: 'P-256' };\r\n \r\n const keyUsages = keyType === 'ECDH' ? [] : ['verify'];\r\n \r\n const publicKey = await crypto.subtle.importKey(\r\n 'spki',\r\n keyBytes,\r\n algorithm,\r\n false, // Non-extractable\r\n keyUsages\r\n );\r\n \r\n // Removed public key import info logging\r\n \r\n return publicKey;\r\n }\r\n } catch (error) {\r\n EnhancedSecureCryptoUtils.secureLog.log('error', 'Signed public key import failed', {\r\n error: error.message,\r\n expectedKeyType\r\n });\r\n throw new Error(`Failed to import the signed key: ${error.message}`);\r\n }\r\n }\r\n\r\n // Legacy export for backward compatibility\r\n static async exportPublicKey(publicKey) {\r\n try {\r\n const exported = await crypto.subtle.exportKey('spki', publicKey);\r\n const keyData = Array.from(new Uint8Array(exported));\r\n \r\n await EnhancedSecureCryptoUtils.validateKeyStructure(keyData, 'ECDH');\r\n \r\n // Removed legacy public key export info logging\r\n return keyData;\r\n } catch (error) {\r\n EnhancedSecureCryptoUtils.secureLog.log('error', 'Legacy public key export failed', { error: error.message });\r\n throw new Error('Failed to export the public key');\r\n }\r\n }\r\n\r\n // Legacy import for backward compatibility with fallback\r\n static async importPublicKey(keyData) {\r\n try {\r\n await EnhancedSecureCryptoUtils.validateKeyStructure(keyData, 'ECDH');\r\n \r\n const keyBytes = new Uint8Array(keyData);\r\n \r\n // Try P-384 first\r\n try {\r\n const publicKey = await crypto.subtle.importKey(\r\n 'spki',\r\n keyBytes,\r\n {\r\n name: 'ECDH',\r\n namedCurve: 'P-384'\r\n },\r\n false, // Non-extractable\r\n []\r\n );\r\n \r\n // Removed legacy public key import info logging\r\n return publicKey;\r\n } catch (p384Error) {\r\n EnhancedSecureCryptoUtils.secureLog.log('warn', 'P-384 import failed, trying P-256', { error: p384Error.message });\r\n \r\n // Fallback to P-256\r\n const publicKey = await crypto.subtle.importKey(\r\n 'spki',\r\n keyBytes,\r\n {\r\n name: 'ECDH',\r\n namedCurve: 'P-256'\r\n },\r\n false, // Non-extractable\r\n []\r\n );\r\n \r\n // Removed legacy public key import info logging\r\n return publicKey;\r\n }\r\n } catch (error) {\r\n EnhancedSecureCryptoUtils.secureLog.log('error', 'Legacy public key import failed', { error: error.message });\r\n throw new Error('Failed to import the public key');\r\n }\r\n }\r\n\r\n\r\n // Method to check if a key is trusted\r\n static isKeyTrusted(keyOrFingerprint) {\r\n if (keyOrFingerprint instanceof CryptoKey) {\r\n const meta = EnhancedSecureCryptoUtils._keyMetadata.get(keyOrFingerprint);\r\n return meta ? meta.trusted === true : false;\r\n } else if (keyOrFingerprint && keyOrFingerprint._securityMetadata) {\r\n // Check by key metadata\r\n return keyOrFingerprint._securityMetadata.trusted === true;\r\n }\r\n\r\n return false;\r\n }\r\n\r\n static async importPublicKeyFromSignedPackage(signedPackage, verifyingKey = null, options = {}) {\r\n try {\r\n if (!signedPackage || !signedPackage.keyData || !signedPackage.signature) {\r\n throw new Error('Invalid signed key package format');\r\n }\r\n\r\n // Validate all required fields are present\r\n const requiredFields = ['keyData', 'signature', 'keyType', 'timestamp', 'version'];\r\n const missingFields = requiredFields.filter(field => !signedPackage[field]);\r\n\r\n if (missingFields.length > 0) {\r\n EnhancedSecureCryptoUtils.secureLog.log('error', 'Missing required fields in signed package', {\r\n missingFields: missingFields,\r\n availableFields: Object.keys(signedPackage)\r\n });\r\n throw new Error(`Required fields are missing in the signed package: ${missingFields.join(', ')}`);\r\n }\r\n\r\n // SECURITY ENHANCEMENT: MANDATORY signature verification for signed packages\r\n if (!verifyingKey) {\r\n EnhancedSecureCryptoUtils.secureLog.log('error', 'SECURITY VIOLATION: Signed package received without verifying key', {\r\n keyType: signedPackage.keyType,\r\n keySize: signedPackage.keyData.length,\r\n timestamp: signedPackage.timestamp,\r\n version: signedPackage.version,\r\n securityRisk: 'HIGH - Potential MITM attack vector'\r\n });\r\n\r\n // REJECT the signed package if no verifying key provided\r\n throw new Error('CRITICAL SECURITY ERROR: Signed key package received without a verification key. ' +\r\n 'This may indicate a possible MITM attack attempt. Import rejected for security reasons.');\r\n }\r\n\r\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\r\n await EnhancedSecureCryptoUtils.validateKeyStructure(signedPackage.keyData, signedPackage.keyType || 'ECDH');\r\n\r\n // MANDATORY signature verification when verifyingKey is provided\r\n const packageCopy = { ...signedPackage };\r\n delete packageCopy.signature;\r\n const packageString = JSON.stringify(packageCopy);\r\n const isValidSignature = await EnhancedSecureCryptoUtils.verifySignature(verifyingKey, signedPackage.signature, packageString);\r\n\r\n if (!isValidSignature) {\r\n EnhancedSecureCryptoUtils.secureLog.log('error', 'SECURITY BREACH: Invalid signature detected - MITM attack prevented', {\r\n keyType: signedPackage.keyType,\r\n keySize: signedPackage.keyData.length,\r\n timestamp: signedPackage.timestamp,\r\n version: signedPackage.version,\r\n attackPrevented: true\r\n });\r\n throw new Error('CRITICAL SECURITY ERROR: Invalid key signature detected. ' +\r\n 'This indicates a possible MITM attack attempt. Key import rejected.');\r\n }\r\n\r\n // Additional MITM protection: Check for key reuse and suspicious patterns\r\n const keyFingerprint = await EnhancedSecureCryptoUtils.calculateKeyFingerprint(signedPackage.keyData);\r\n\r\n // Log successful verification with security details\r\n // Removed signature verification pass details to avoid key-related logging\r\n\r\n // Import the public key with fallback\r\n const keyBytes = new Uint8Array(signedPackage.keyData);\r\n const keyType = signedPackage.keyType || 'ECDH';\r\n\r\n // Try P-384 first\r\n try {\r\n const publicKey = await crypto.subtle.importKey(\r\n 'spki',\r\n keyBytes,\r\n {\r\n name: keyType,\r\n namedCurve: 'P-384'\r\n },\r\n false, // Non-extractable\r\n keyType === 'ECDSA' ? ['verify'] : []\r\n );\r\n\r\n // Use WeakMap to store metadata\r\n EnhancedSecureCryptoUtils._keyMetadata.set(publicKey, {\r\n trusted: true,\r\n verificationStatus: 'VERIFIED_SECURE',\r\n verificationTimestamp: Date.now()\r\n });\r\n\r\n return publicKey;\r\n } catch (p384Error) {\r\n EnhancedSecureCryptoUtils.secureLog.log('warn', 'P-384 import failed, trying P-256', { error: p384Error.message });\r\n\r\n // Fallback to P-256\r\n const publicKey = await crypto.subtle.importKey(\r\n 'spki',\r\n keyBytes,\r\n {\r\n name: keyType,\r\n namedCurve: 'P-256'\r\n },\r\n false, // Non-extractable\r\n keyType === 'ECDSA' ? ['verify'] : []\r\n );\r\n\r\n // Use WeakMap to store metadata\r\n EnhancedSecureCryptoUtils._keyMetadata.set(publicKey, {\r\n trusted: true,\r\n verificationStatus: 'VERIFIED_SECURE',\r\n verificationTimestamp: Date.now()\r\n });\r\n\r\n return publicKey;\r\n }\r\n } catch (error) {\r\n EnhancedSecureCryptoUtils.secureLog.log('error', 'Signed package key import failed', {\r\n error: error.message,\r\n securityImplications: 'Potential security breach prevented'\r\n });\r\n throw new Error(`Failed to import the public key from the signed package: ${error.message}`);\r\n }\r\n }\r\n\r\n // Enhanced key derivation with metadata protection and 64-byte salt\r\n static async deriveSharedKeys(privateKey, publicKey, salt) {\r\n try {\r\n // Removed detailed key derivation logging\r\n \r\n // Validate input parameters are CryptoKey instances\r\n if (!(privateKey instanceof CryptoKey)) {\r\n EnhancedSecureCryptoUtils.secureLog.log('error', 'Private key is not a CryptoKey', {\r\n privateKeyType: typeof privateKey,\r\n privateKeyAlgorithm: privateKey?.algorithm?.name\r\n });\r\n throw new Error('The private key is not a valid CryptoKey.');\r\n }\r\n \r\n if (!(publicKey instanceof CryptoKey)) {\r\n EnhancedSecureCryptoUtils.secureLog.log('error', 'Public key is not a CryptoKey', {\r\n publicKeyType: typeof publicKey,\r\n publicKeyAlgorithm: publicKey?.algorithm?.name\r\n });\r\n throw new Error('The public key is not a valid CryptoKey.');\r\n }\r\n \r\n // Validate salt size (should be 64 bytes for enhanced security)\r\n if (!salt || salt.length !== 64) {\r\n throw new Error('Salt must be exactly 64 bytes for enhanced security');\r\n }\r\n \r\n const saltBytes = new Uint8Array(salt);\r\n const encoder = new TextEncoder();\r\n \r\n // Step 1: Derive raw ECDH shared secret using pure ECDH\r\n let rawSharedSecret;\r\n try {\r\n // Removed detailed key derivation logging\r\n \r\n // Use pure ECDH to derive raw key material\r\n const rawKeyMaterial = await crypto.subtle.deriveKey(\r\n {\r\n name: 'ECDH',\r\n public: publicKey\r\n },\r\n privateKey,\r\n {\r\n name: 'AES-GCM',\r\n length: 256\r\n },\r\n true, // Extractable\r\n ['encrypt', 'decrypt']\r\n );\r\n \r\n // Export the raw key material\r\n const rawKeyData = await crypto.subtle.exportKey('raw', rawKeyMaterial);\r\n \r\n // Import as HKDF key material for further derivation\r\n rawSharedSecret = await crypto.subtle.importKey(\r\n 'raw',\r\n rawKeyData,\r\n {\r\n name: 'HKDF',\r\n hash: 'SHA-256'\r\n },\r\n false,\r\n ['deriveKey']\r\n );\r\n \r\n // Removed detailed key derivation logging\r\n } catch (error) {\r\n EnhancedSecureCryptoUtils.secureLog.log('error', 'ECDH derivation failed', { \r\n error: error.message\r\n });\r\n throw error;\r\n }\r\n \r\n // Step 2: Use HKDF to derive specific keys directly\r\n // Removed detailed key derivation logging\r\n\r\n // Step 3: Derive specific keys using HKDF with unique info parameters\r\n // Each key uses unique info parameter for proper separation\r\n \r\n // Derive message encryption key (messageKey)\r\n let messageKey;\r\n messageKey = await crypto.subtle.deriveKey(\r\n {\r\n name: 'HKDF',\r\n hash: 'SHA-256',\r\n salt: saltBytes,\r\n info: encoder.encode('message-encryption-v4')\r\n },\r\n rawSharedSecret,\r\n {\r\n name: 'AES-GCM',\r\n length: 256\r\n },\r\n false, // Non-extractable for enhanced security\r\n ['encrypt', 'decrypt']\r\n );\r\n\r\n // Derive MAC key for message authentication\r\n let macKey;\r\n macKey = await crypto.subtle.deriveKey(\r\n {\r\n name: 'HKDF',\r\n hash: 'SHA-256',\r\n salt: saltBytes,\r\n info: encoder.encode('message-authentication-v4')\r\n },\r\n rawSharedSecret,\r\n {\r\n name: 'HMAC',\r\n hash: 'SHA-256'\r\n },\r\n false, // Non-extractable\r\n ['sign', 'verify']\r\n );\r\n\r\n // Derive Perfect Forward Secrecy key (pfsKey)\r\n let pfsKey;\r\n pfsKey = await crypto.subtle.deriveKey(\r\n {\r\n name: 'HKDF',\r\n hash: 'SHA-256',\r\n salt: saltBytes,\r\n info: encoder.encode('perfect-forward-secrecy-v4')\r\n },\r\n rawSharedSecret,\r\n {\r\n name: 'AES-GCM',\r\n length: 256\r\n },\r\n false, // Non-extractable\r\n ['encrypt', 'decrypt']\r\n );\r\n\r\n // Derive separate metadata encryption key\r\n let metadataKey;\r\n metadataKey = await crypto.subtle.deriveKey(\r\n {\r\n name: 'HKDF',\r\n hash: 'SHA-256',\r\n salt: saltBytes,\r\n info: encoder.encode('metadata-protection-v4')\r\n },\r\n rawSharedSecret,\r\n {\r\n name: 'AES-GCM',\r\n length: 256\r\n },\r\n false, // Non-extractable\r\n ['encrypt', 'decrypt']\r\n );\r\n\r\n // Generate temporary extractable key for fingerprint calculation\r\n let fingerprintKey;\r\n fingerprintKey = await crypto.subtle.deriveKey(\r\n {\r\n name: 'HKDF',\r\n hash: 'SHA-256',\r\n salt: saltBytes,\r\n info: encoder.encode('fingerprint-generation-v4')\r\n },\r\n rawSharedSecret,\r\n {\r\n name: 'AES-GCM',\r\n length: 256\r\n },\r\n true, // Extractable only for fingerprint\r\n ['encrypt', 'decrypt']\r\n );\r\n\r\n // Generate key fingerprint for verification\r\n const fingerprintKeyData = await crypto.subtle.exportKey('raw', fingerprintKey);\r\n const fingerprint = await EnhancedSecureCryptoUtils.generateKeyFingerprint(Array.from(new Uint8Array(fingerprintKeyData)));\r\n\r\n // Validate that all derived keys are CryptoKey instances\r\n if (!(messageKey instanceof CryptoKey)) {\r\n EnhancedSecureCryptoUtils.secureLog.log('error', 'Derived message key is not a CryptoKey', {\r\n messageKeyType: typeof messageKey,\r\n messageKeyAlgorithm: messageKey?.algorithm?.name\r\n });\r\n throw new Error('The derived message key is not a valid CryptoKey.');\r\n }\r\n \r\n if (!(macKey instanceof CryptoKey)) {\r\n EnhancedSecureCryptoUtils.secureLog.log('error', 'Derived MAC key is not a CryptoKey', {\r\n macKeyType: typeof macKey,\r\n macKeyAlgorithm: macKey?.algorithm?.name\r\n });\r\n throw new Error('The derived MAC key is not a valid CryptoKey.');\r\n }\r\n \r\n if (!(pfsKey instanceof CryptoKey)) {\r\n EnhancedSecureCryptoUtils.secureLog.log('error', 'Derived PFS key is not a CryptoKey', {\r\n pfsKeyType: typeof pfsKey,\r\n pfsKeyAlgorithm: pfsKey?.algorithm?.name\r\n });\r\n throw new Error('The derived PFS key is not a valid CryptoKey.');\r\n }\r\n \r\n if (!(metadataKey instanceof CryptoKey)) {\r\n EnhancedSecureCryptoUtils.secureLog.log('error', 'Derived metadata key is not a CryptoKey', {\r\n metadataKeyType: typeof metadataKey,\r\n metadataKeyAlgorithm: metadataKey?.algorithm?.name\r\n });\r\n throw new Error('The derived metadata key is not a valid CryptoKey.');\r\n }\r\n\r\n // Removed detailed key derivation success logging\r\n\r\n return {\r\n messageKey, // Renamed from encryptionKey for clarity\r\n macKey,\r\n pfsKey, // Added Perfect Forward Secrecy key\r\n metadataKey,\r\n fingerprint,\r\n timestamp: Date.now(),\r\n version: '4.0'\r\n };\r\n } catch (error) {\r\n EnhancedSecureCryptoUtils.secureLog.log('error', 'Enhanced key derivation failed', { \r\n error: error.message,\r\n errorStack: error.stack,\r\n privateKeyType: typeof privateKey,\r\n publicKeyType: typeof publicKey,\r\n saltLength: salt?.length,\r\n privateKeyAlgorithm: privateKey?.algorithm?.name,\r\n publicKeyAlgorithm: publicKey?.algorithm?.name\r\n });\r\n throw new Error(`Failed to create shared encryption keys: ${error.message}`);\r\n }\r\n }\r\n\r\n static async generateKeyFingerprint(keyData) {\r\n const keyBuffer = new Uint8Array(keyData);\r\n const hashBuffer = await crypto.subtle.digest('SHA-384', keyBuffer);\r\n const hashArray = Array.from(new Uint8Array(hashBuffer));\r\n return hashArray.slice(0, 12).map(b => b.toString(16).padStart(2, '0')).join(':');\r\n }\r\n\r\n // Generate mutual authentication challenge\r\n static generateMutualAuthChallenge() {\r\n const challenge = crypto.getRandomValues(new Uint8Array(48)); // Increased to 48 bytes\r\n const timestamp = Date.now();\r\n const nonce = crypto.getRandomValues(new Uint8Array(16));\r\n \r\n return {\r\n challenge: Array.from(challenge),\r\n timestamp,\r\n nonce: Array.from(nonce),\r\n version: '4.0'\r\n };\r\n }\r\n\r\n // Create cryptographic proof for mutual authentication\r\n static async createAuthProof(challenge, privateKey, publicKey) {\r\n try {\r\n if (!challenge || !challenge.challenge || !challenge.timestamp || !challenge.nonce) {\r\n throw new Error('Invalid challenge structure');\r\n }\r\n \r\n // Check challenge age (max 2 minutes)\r\n const challengeAge = Date.now() - challenge.timestamp;\r\n if (challengeAge > 120000) {\r\n throw new Error('Challenge expired');\r\n }\r\n \r\n // Create proof data\r\n const proofData = {\r\n challenge: challenge.challenge,\r\n timestamp: challenge.timestamp,\r\n nonce: challenge.nonce,\r\n responseTimestamp: Date.now(),\r\n publicKeyHash: await EnhancedSecureCryptoUtils.hashPublicKey(publicKey)\r\n };\r\n \r\n // Sign the proof\r\n const proofString = JSON.stringify(proofData);\r\n const signature = await EnhancedSecureCryptoUtils.signData(privateKey, proofString);\r\n \r\n const proof = {\r\n ...proofData,\r\n signature,\r\n version: '4.0'\r\n };\r\n \r\n EnhancedSecureCryptoUtils.secureLog.log('info', 'Authentication proof created', {\r\n challengeAge: Math.round(challengeAge / 1000) + 's'\r\n });\r\n \r\n return proof;\r\n } catch (error) {\r\n EnhancedSecureCryptoUtils.secureLog.log('error', 'Authentication proof creation failed', { error: error.message });\r\n throw new Error(`Failed to create cryptographic proof: ${error.message}`);\r\n }\r\n }\r\n\r\n // Verify mutual authentication proof\r\n static async verifyAuthProof(proof, challenge, publicKey) {\r\n try {\r\n await new Promise(resolve => setTimeout(resolve, Math.floor(Math.random() * 20) + 5));\r\n // Assert the public key is valid and has the correct usage\r\n EnhancedSecureCryptoUtils.assertCryptoKey(publicKey, 'ECDSA', ['verify']);\r\n\r\n if (!proof || !challenge || !publicKey) {\r\n throw new Error('Missing required parameters for proof verification');\r\n }\r\n\r\n // Validate proof structure\r\n const requiredFields = ['challenge', 'timestamp', 'nonce', 'responseTimestamp', 'publicKeyHash', 'signature'];\r\n for (const field of requiredFields) {\r\n if (!proof[field]) {\r\n throw new Error(`Missing required field: ${field}`);\r\n }\r\n }\r\n\r\n // Verify challenge matches\r\n if (!EnhancedSecureCryptoUtils.constantTimeCompareArrays(proof.challenge, challenge.challenge) ||\r\n proof.timestamp !== challenge.timestamp ||\r\n !EnhancedSecureCryptoUtils.constantTimeCompareArrays(proof.nonce, challenge.nonce)) {\r\n throw new Error('Challenge mismatch - possible replay attack');\r\n }\r\n\r\n // Check response time (max 30 minutes for better UX)\r\n const responseAge = Date.now() - proof.responseTimestamp;\r\n if (responseAge > 1800000) {\r\n throw new Error('Proof response expired');\r\n }\r\n\r\n // Verify public key hash\r\n const expectedHash = await EnhancedSecureCryptoUtils.hashPublicKey(publicKey);\r\n if (!EnhancedSecureCryptoUtils.constantTimeCompare(proof.publicKeyHash, expectedHash)) {\r\n throw new Error('Public key hash mismatch');\r\n }\r\n\r\n // Verify signature\r\n const proofCopy = { ...proof };\r\n delete proofCopy.signature;\r\n const proofString = JSON.stringify(proofCopy);\r\n const isValidSignature = await EnhancedSecureCryptoUtils.verifySignature(publicKey, proof.signature, proofString);\r\n\r\n if (!isValidSignature) {\r\n throw new Error('Invalid proof signature');\r\n }\r\n\r\n EnhancedSecureCryptoUtils.secureLog.log('info', 'Authentication proof verified successfully', {\r\n responseAge: Math.round(responseAge / 1000) + 's'\r\n });\r\n\r\n return true;\r\n } catch (error) {\r\n EnhancedSecureCryptoUtils.secureLog.log('error', 'Authentication proof verification failed', { error: error.message });\r\n throw new Error(`Failed to verify cryptographic proof: ${error.message}`);\r\n }\r\n }\r\n\r\n // Hash public key for verification\r\n static async hashPublicKey(publicKey) {\r\n try {\r\n const exported = await crypto.subtle.exportKey('spki', publicKey);\r\n const hash = await crypto.subtle.digest('SHA-384', exported);\r\n const hashArray = Array.from(new Uint8Array(hash));\r\n return hashArray.map(b => b.toString(16).padStart(2, '0')).join('');\r\n } catch (error) {\r\n EnhancedSecureCryptoUtils.secureLog.log('error', 'Public key hashing failed', { error: error.message });\r\n throw new Error('Failed to create hash of the public key');\r\n }\r\n }\r\n\r\n // Legacy authentication challenge for backward compatibility\r\n static generateAuthChallenge() {\r\n const challenge = crypto.getRandomValues(new Uint8Array(32));\r\n return Array.from(challenge);\r\n }\r\n\r\n // Generate verification code for out-of-band authentication\r\n static generateVerificationCode() {\r\n const chars = '0123456789ABCDEF';\r\n const charCount = chars.length;\r\n let result = '';\r\n \r\n // Use rejection sampling to avoid bias\r\n for (let i = 0; i < 6; i++) {\r\n let randomByte;\r\n do {\r\n randomByte = crypto.getRandomValues(new Uint8Array(1))[0];\r\n } while (randomByte >= 256 - (256 % charCount)); // Reject biased values\r\n \r\n result += chars[randomByte % charCount];\r\n }\r\n \r\n return result.match(/.{1,2}/g).join('-');\r\n }\r\n\r\n // Enhanced message encryption with metadata protection and sequence numbers\r\n static async encryptMessage(message, encryptionKey, macKey, metadataKey, messageId, sequenceNumber = 0) {\r\n try {\r\n if (!message || typeof message !== 'string') {\r\n throw new Error('Invalid message format');\r\n }\r\n\r\n EnhancedSecureCryptoUtils.assertCryptoKey(encryptionKey, 'AES-GCM', ['encrypt']);\r\n EnhancedSecureCryptoUtils.assertCryptoKey(macKey, 'HMAC', ['sign']);\r\n EnhancedSecureCryptoUtils.assertCryptoKey(metadataKey, 'AES-GCM', ['encrypt']);\r\n\r\n const encoder = new TextEncoder();\r\n const messageData = encoder.encode(message);\r\n const messageIv = crypto.getRandomValues(new Uint8Array(12));\r\n const metadataIv = crypto.getRandomValues(new Uint8Array(12));\r\n const timestamp = Date.now();\r\n\r\n const paddingSize = 16 - (messageData.length % 16);\r\n const paddedMessage = new Uint8Array(messageData.length + paddingSize);\r\n paddedMessage.set(messageData);\r\n const padding = crypto.getRandomValues(new Uint8Array(paddingSize));\r\n paddedMessage.set(padding, messageData.length);\r\n\r\n const encryptedMessage = await crypto.subtle.encrypt(\r\n { name: 'AES-GCM', iv: messageIv },\r\n encryptionKey,\r\n paddedMessage\r\n );\r\n\r\n const metadata = {\r\n id: messageId,\r\n timestamp: timestamp,\r\n sequenceNumber: sequenceNumber,\r\n originalLength: messageData.length,\r\n version: '4.0'\r\n };\r\n\r\n const metadataStr = JSON.stringify(EnhancedSecureCryptoUtils.sortObjectKeys(metadata));\r\n const encryptedMetadata = await crypto.subtle.encrypt(\r\n { name: 'AES-GCM', iv: metadataIv },\r\n metadataKey,\r\n encoder.encode(metadataStr)\r\n );\r\n\r\n const payload = {\r\n messageIv: Array.from(messageIv),\r\n messageData: Array.from(new Uint8Array(encryptedMessage)),\r\n metadataIv: Array.from(metadataIv),\r\n metadataData: Array.from(new Uint8Array(encryptedMetadata)),\r\n version: '4.0'\r\n };\r\n\r\n const sortedPayload = EnhancedSecureCryptoUtils.sortObjectKeys(payload);\r\n const payloadStr = JSON.stringify(sortedPayload);\r\n\r\n const mac = await crypto.subtle.sign(\r\n 'HMAC',\r\n macKey,\r\n encoder.encode(payloadStr)\r\n );\r\n\r\n payload.mac = Array.from(new Uint8Array(mac));\r\n\r\n // Logging removed to avoid noisy console output\r\n\r\n return payload;\r\n } catch (error) {\r\n EnhancedSecureCryptoUtils.secureLog.log('error', 'Message encryption failed', {\r\n error: error.message,\r\n messageId\r\n });\r\n throw new Error(`Failed to encrypt the message: ${error.message}`);\r\n }\r\n }\r\n\r\n // Enhanced message decryption with metadata protection and sequence validation\r\n static async decryptMessage(encryptedPayload, encryptionKey, macKey, metadataKey, expectedSequenceNumber = null) {\r\n try {\r\n EnhancedSecureCryptoUtils.assertCryptoKey(encryptionKey, 'AES-GCM', ['decrypt']);\r\n EnhancedSecureCryptoUtils.assertCryptoKey(macKey, 'HMAC', ['verify']);\r\n EnhancedSecureCryptoUtils.assertCryptoKey(metadataKey, 'AES-GCM', ['decrypt']);\r\n\r\n const requiredFields = ['messageIv', 'messageData', 'metadataIv', 'metadataData', 'mac', 'version'];\r\n for (const field of requiredFields) {\r\n if (!encryptedPayload[field]) {\r\n throw new Error(`Missing required field: ${field}`);\r\n }\r\n }\r\n\r\n const payloadCopy = { ...encryptedPayload };\r\n delete payloadCopy.mac;\r\n const sortedPayloadCopy = EnhancedSecureCryptoUtils.sortObjectKeys(payloadCopy);\r\n const payloadStr = JSON.stringify(sortedPayloadCopy);\r\n\r\n const macValid = await crypto.subtle.verify(\r\n 'HMAC',\r\n macKey,\r\n new Uint8Array(encryptedPayload.mac),\r\n new TextEncoder().encode(payloadStr)\r\n );\r\n\r\n if (!macValid) {\r\n EnhancedSecureCryptoUtils.secureLog.log('error', 'MAC verification failed', {\r\n payloadFields: Object.keys(encryptedPayload),\r\n macLength: encryptedPayload.mac?.length\r\n });\r\n throw new Error('Message authentication failed - possible tampering');\r\n }\r\n\r\n const metadataIv = new Uint8Array(encryptedPayload.metadataIv);\r\n const metadataData = new Uint8Array(encryptedPayload.metadataData);\r\n\r\n const decryptedMetadataBuffer = await crypto.subtle.decrypt(\r\n { name: 'AES-GCM', iv: metadataIv },\r\n metadataKey,\r\n metadataData\r\n );\r\n\r\n const metadataStr = new TextDecoder().decode(decryptedMetadataBuffer);\r\n const metadata = JSON.parse(metadataStr);\r\n\r\n if (!metadata.id || !metadata.timestamp || metadata.sequenceNumber === undefined || !metadata.originalLength) {\r\n throw new Error('Invalid metadata structure');\r\n }\r\n\r\n const messageAge = Date.now() - metadata.timestamp;\r\n if (messageAge > 1800000) { // 30 minutes for better UX\r\n throw new Error('Message expired (older than 5 minutes)');\r\n }\r\n\r\n if (expectedSequenceNumber !== null) {\r\n if (metadata.sequenceNumber < expectedSequenceNumber) {\r\n EnhancedSecureCryptoUtils.secureLog.log('warn', 'Received message with lower sequence number, possible queued message', {\r\n expected: expectedSequenceNumber,\r\n received: metadata.sequenceNumber,\r\n messageId: metadata.id\r\n });\r\n } else if (metadata.sequenceNumber > expectedSequenceNumber + 10) {\r\n throw new Error(`Sequence number gap too large: expected around ${expectedSequenceNumber}, got ${metadata.sequenceNumber}`);\r\n }\r\n }\r\n\r\n const messageIv = new Uint8Array(encryptedPayload.messageIv);\r\n const messageData = new Uint8Array(encryptedPayload.messageData);\r\n\r\n const decryptedMessageBuffer = await crypto.subtle.decrypt(\r\n { name: 'AES-GCM', iv: messageIv },\r\n encryptionKey,\r\n messageData\r\n );\r\n\r\n const paddedMessage = new Uint8Array(decryptedMessageBuffer);\r\n const originalMessage = paddedMessage.slice(0, metadata.originalLength);\r\n\r\n const decoder = new TextDecoder();\r\n const message = decoder.decode(originalMessage);\r\n\r\n EnhancedSecureCryptoUtils.secureLog.log('info', 'Message decrypted successfully', {\r\n messageId: metadata.id,\r\n sequenceNumber: metadata.sequenceNumber,\r\n messageAge: Math.round(messageAge / 1000) + 's'\r\n });\r\n\r\n return {\r\n message: message,\r\n messageId: metadata.id,\r\n timestamp: metadata.timestamp,\r\n sequenceNumber: metadata.sequenceNumber\r\n };\r\n } catch (error) {\r\n EnhancedSecureCryptoUtils.secureLog.log('error', 'Message decryption failed', { error: error.message });\r\n throw new Error(`Failed to decrypt the message: ${error.message}`);\r\n }\r\n }\r\n\r\n // Enhanced input sanitization with iterative processing to handle edge cases\r\n static sanitizeMessage(message) {\r\n if (typeof message !== 'string') {\r\n throw new Error('Message must be a string');\r\n }\r\n \r\n // Helper function to apply replacement until stable\r\n function replaceUntilStable(str, pattern, replacement = '') {\r\n let previous;\r\n do {\r\n previous = str;\r\n str = str.replace(pattern, replacement);\r\n } while (str !== previous);\r\n return str;\r\n }\r\n \r\n // Define all dangerous patterns that need to be removed\r\n const dangerousPatterns = [\r\n // Script tags with various formats\r\n /]*>[\\s\\S]*?<\\/script\\s*>/gi,\r\n /]*>[\\s\\S]*?<\\/script\\s+[^>]*>/gi,\r\n /]*>[\\s\\S]*$/gi,\r\n // Other dangerous tags\r\n /]*>[\\s\\S]*?<\\/iframe\\s*>/gi,\r\n /]*>[\\s\\S]*?<\\/object\\s*>/gi,\r\n /]*>/gi,\r\n /]*>[\\s\\S]*?<\\/applet\\s*>/gi,\r\n /]*>[\\s\\S]*?<\\/style\\s*>/gi,\r\n // Dangerous protocols\r\n /javascript\\s*:/gi,\r\n /data\\s*:/gi,\r\n /vbscript\\s*:/gi,\r\n // Event handlers\r\n /on\\w+\\s*=/gi,\r\n // HTML comments\r\n //g,\r\n // Link and meta tags with javascript\r\n /]*javascript[^>]*>/gi,\r\n /]*javascript[^>]*>/gi,\r\n // Any remaining script-like content\r\n /<[^>]*script[^>]*>/gi,\r\n /<[^>]*on\\w+\\s*=[^>]*>/gi\r\n ];\r\n \r\n // Iterative sanitization to handle edge cases\r\n let sanitized = message;\r\n let previousLength;\r\n let iterations = 0;\r\n const maxIterations = 10; // Prevent infinite loops\r\n \r\n do {\r\n previousLength = sanitized.length;\r\n \r\n // Apply all dangerous patterns with stable replacement\r\n for (const pattern of dangerousPatterns) {\r\n sanitized = replaceUntilStable(sanitized, pattern);\r\n }\r\n \r\n // Additional cleanup for edge cases - each applied until stable\r\n sanitized = replaceUntilStable(sanitized, /<[^>]*>/g);\r\n sanitized = replaceUntilStable(sanitized, /^\\w+:/gi);\r\n sanitized = replaceUntilStable(sanitized, /\\bon\\w+\\s*=\\s*[\"'][^\"']*[\"']/gi);\r\n sanitized = replaceUntilStable(sanitized, /\\bon\\w+\\s*=\\s*[^>\\s]+/gi);\r\n \r\n // Single character removal is inherently safe\r\n sanitized = sanitized.replace(/[<>]/g, '').trim();\r\n \r\n iterations++;\r\n } while (sanitized.length !== previousLength && iterations < maxIterations);\r\n \r\n // Final security pass with stable replacements\r\n sanitized = replaceUntilStable(sanitized, /<[^>]*>/g);\r\n sanitized = replaceUntilStable(sanitized, /^\\w+:/gi);\r\n sanitized = replaceUntilStable(sanitized, /\\bon\\w+\\s*=\\s*[\"'][^\"']*[\"']/gi);\r\n sanitized = replaceUntilStable(sanitized, /\\bon\\w+\\s*=\\s*[^>\\s]+/gi);\r\n \r\n // Final single character cleanup\r\n sanitized = sanitized.replace(/[<>]/g, '').trim();\r\n \r\n return sanitized.substring(0, 2000); // Limit length\r\n }\r\n\r\n // Generate cryptographically secure salt (64 bytes for enhanced security)\r\n static generateSalt() {\r\n return Array.from(crypto.getRandomValues(new Uint8Array(64)));\r\n }\r\n\r\n // Calculate key fingerprint for MITM protection\r\n static async calculateKeyFingerprint(keyData) {\r\n try {\r\n const encoder = new TextEncoder();\r\n const keyBytes = new Uint8Array(keyData);\r\n \r\n // Create a hash of the key data for fingerprinting\r\n const hashBuffer = await crypto.subtle.digest('SHA-256', keyBytes);\r\n const hashArray = Array.from(new Uint8Array(hashBuffer));\r\n \r\n // Convert to hexadecimal string\r\n const fingerprint = hashArray.map(b => b.toString(16).padStart(2, '0')).join('');\r\n \r\n // Removed key fingerprint logging\r\n \r\n return fingerprint;\r\n } catch (error) {\r\n EnhancedSecureCryptoUtils.secureLog.log('error', 'Key fingerprint calculation failed', { error: error.message });\r\n throw new Error('Failed to compute the key fingerprint');\r\n }\r\n }\r\n\r\n static constantTimeCompare(a, b) {\r\n const strA = typeof a === 'string' ? a : JSON.stringify(a);\r\n const strB = typeof b === 'string' ? b : JSON.stringify(b);\r\n \r\n if (strA.length !== strB.length) {\r\n let dummy = 0;\r\n for (let i = 0; i < Math.max(strA.length, strB.length); i++) {\r\n dummy |= (strA.charCodeAt(i % strA.length) || 0) ^ (strB.charCodeAt(i % strB.length) || 0);\r\n }\r\n return false;\r\n }\r\n \r\n let result = 0;\r\n for (let i = 0; i < strA.length; i++) {\r\n result |= strA.charCodeAt(i) ^ strB.charCodeAt(i);\r\n }\r\n \r\n return result === 0;\r\n }\r\n\r\n static constantTimeCompareArrays(arr1, arr2) {\r\n if (!Array.isArray(arr1) || !Array.isArray(arr2)) {\r\n return false;\r\n }\r\n \r\n if (arr1.length !== arr2.length) {\r\n let dummy = 0;\r\n const maxLen = Math.max(arr1.length, arr2.length);\r\n for (let i = 0; i < maxLen; i++) {\r\n dummy |= (arr1[i % arr1.length] || 0) ^ (arr2[i % arr2.length] || 0);\r\n }\r\n return false;\r\n }\r\n \r\n let result = 0;\r\n for (let i = 0; i < arr1.length; i++) {\r\n result |= arr1[i] ^ arr2[i];\r\n }\r\n \r\n return result === 0;\r\n }\r\n \r\n /**\r\n * CRITICAL SECURITY: Encrypt data with AAD (Additional Authenticated Data)\r\n * This method provides authenticated encryption with additional data binding\r\n */\r\n static async encryptDataWithAAD(data, key, aad) {\r\n try {\r\n const dataString = typeof data === 'string' ? data : JSON.stringify(data);\r\n const encoder = new TextEncoder();\r\n const dataBuffer = encoder.encode(dataString);\r\n const aadBuffer = encoder.encode(aad);\r\n\r\n // Generate random IV\r\n const iv = crypto.getRandomValues(new Uint8Array(12));\r\n\r\n // Encrypt with AAD\r\n const encrypted = await crypto.subtle.encrypt(\r\n { \r\n name: 'AES-GCM', \r\n iv: iv,\r\n additionalData: aadBuffer\r\n },\r\n key,\r\n dataBuffer\r\n );\r\n\r\n // Package encrypted data\r\n const encryptedPackage = {\r\n version: '1.0',\r\n iv: Array.from(iv),\r\n data: Array.from(new Uint8Array(encrypted)),\r\n aad: aad,\r\n timestamp: Date.now()\r\n };\r\n\r\n const packageString = JSON.stringify(encryptedPackage);\r\n const packageBuffer = encoder.encode(packageString);\r\n \r\n return EnhancedSecureCryptoUtils.arrayBufferToBase64(packageBuffer);\r\n } catch (error) {\r\n throw new Error(`AAD encryption failed: ${error.message}`);\r\n }\r\n }\r\n\r\n /**\r\n * CRITICAL SECURITY: Decrypt data with AAD validation\r\n * This method provides authenticated decryption with additional data validation\r\n */\r\n static async decryptDataWithAAD(encryptedData, key, expectedAad) {\r\n try {\r\n const packageBuffer = EnhancedSecureCryptoUtils.base64ToArrayBuffer(encryptedData);\r\n const packageString = new TextDecoder().decode(packageBuffer);\r\n const encryptedPackage = JSON.parse(packageString);\r\n\r\n if (!encryptedPackage.version || !encryptedPackage.iv || !encryptedPackage.data || !encryptedPackage.aad) {\r\n throw new Error('Invalid encrypted data format');\r\n }\r\n\r\n // Validate AAD matches expected\r\n if (encryptedPackage.aad !== expectedAad) {\r\n throw new Error('AAD mismatch - possible tampering or replay attack');\r\n }\r\n\r\n const iv = new Uint8Array(encryptedPackage.iv);\r\n const encrypted = new Uint8Array(encryptedPackage.data);\r\n const aadBuffer = new TextEncoder().encode(encryptedPackage.aad);\r\n\r\n // Decrypt with AAD validation\r\n const decrypted = await crypto.subtle.decrypt(\r\n { \r\n name: 'AES-GCM', \r\n iv: iv,\r\n additionalData: aadBuffer\r\n },\r\n key,\r\n encrypted\r\n );\r\n\r\n const decryptedString = new TextDecoder().decode(decrypted);\r\n\r\n try {\r\n return JSON.parse(decryptedString);\r\n } catch {\r\n return decryptedString;\r\n }\r\n } catch (error) {\r\n throw new Error(`AAD decryption failed: ${error.message}`);\r\n }\r\n }\r\n\r\n // Initialize secure logging system after class definition\r\n static {\r\n if (EnhancedSecureCryptoUtils.secureLog && typeof EnhancedSecureCryptoUtils.secureLog.init === 'function') {\r\n EnhancedSecureCryptoUtils.secureLog.init();\r\n }\r\n }\r\n}\r\n\r\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 }\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 }\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\r\nimport { EnhancedSecureFileTransfer } from '../transfer/EnhancedSecureFileTransfer.js';\r\n\r\n// MUTEX SYSTEM FIXES - RESOLVING MESSAGE DELIVERY ISSUES\r\n// ============================================\r\n// Issue: After introducing the Mutex system, messages stopped being delivered between users\r\n// Fix: Simplified locking logic \u2014 mutex is used ONLY for critical operations\r\n// - Regular messages are processed WITHOUT mutex\r\n// - File messages are processed WITHOUT mutex \r\n// - Mutex is used ONLY for cryptographic operations\r\n// ============================================\r\n\r\nclass EnhancedSecureWebRTCManager {\r\n // ============================================\r\n // CONSTANTS\r\n // ============================================\r\n \r\n static TIMEOUTS = {\r\n KEY_ROTATION_INTERVAL: 300000, // 5 minutes\r\n CONNECTION_TIMEOUT: 10000, // 10 seconds \r\n HEARTBEAT_INTERVAL: 30000, // 30 seconds\r\n SECURITY_CALC_DELAY: 1000, // 1 second\r\n SECURITY_CALC_RETRY_DELAY: 3000, // 3 seconds\r\n CLEANUP_INTERVAL: 300000, // 5 minutes (periodic cleanup)\r\n CLEANUP_CHECK_INTERVAL: 60000, // 1 minute (cleanup check)\r\n ICE_GATHERING_TIMEOUT: 10000, // 10 seconds\r\n DISCONNECT_CLEANUP_DELAY: 500, // 500ms\r\n PEER_DISCONNECT_CLEANUP: 2000, // 2 seconds\r\n STAGE2_ACTIVATION_DELAY: 10000, // 10 seconds\r\n STAGE3_ACTIVATION_DELAY: 15000, // 15 seconds \r\n STAGE4_ACTIVATION_DELAY: 20000, // 20 seconds\r\n FILE_TRANSFER_INIT_DELAY: 1000, // 1 second\r\n FAKE_TRAFFIC_MIN_INTERVAL: 15000, // 15 seconds\r\n FAKE_TRAFFIC_MAX_INTERVAL: 30000, // 30 seconds\r\n DECOY_INITIAL_DELAY: 5000, // 5 seconds\r\n DECOY_TRAFFIC_MIN: 10000, // 10 seconds\r\n DECOY_TRAFFIC_MAX: 25000, // 25 seconds\r\n REORDER_TIMEOUT: 3000, // 3 seconds\r\n RETRY_CONNECTION_DELAY: 2000 // 2 seconds\r\n };\r\n\r\n static LIMITS = {\r\n MAX_CONNECTION_ATTEMPTS: 3,\r\n MAX_OLD_KEYS: 3,\r\n MAX_PROCESSED_MESSAGE_IDS: 1000,\r\n MAX_OUT_OF_ORDER_PACKETS: 5,\r\n MAX_DECOY_CHANNELS: 1,\r\n MESSAGE_RATE_LIMIT: 60, // messages per minute\r\n MAX_KEY_AGE: 900000, // 15 minutes\r\n OFFER_MAX_AGE: 3600000, // 1 hour\r\n SALT_SIZE_V3: 32, // bytes\r\n SALT_SIZE_V4: 64 // bytes\r\n };\r\n\r\n static SIZES = {\r\n VERIFICATION_CODE_MIN_LENGTH: 6,\r\n FAKE_TRAFFIC_MIN_SIZE: 32,\r\n FAKE_TRAFFIC_MAX_SIZE: 128,\r\n PACKET_PADDING_MIN: 64,\r\n PACKET_PADDING_MAX: 512,\r\n CHUNK_SIZE_MAX: 2048,\r\n CHUNK_DELAY_MIN: 100,\r\n CHUNK_DELAY_MAX: 500,\r\n FINGERPRINT_DISPLAY_LENGTH: 8,\r\n SESSION_ID_LENGTH: 16,\r\n NESTED_ENCRYPTION_IV_SIZE: 12\r\n };\r\n\r\n static MESSAGE_TYPES = {\r\n // Regular messages\r\n MESSAGE: 'message',\r\n ENHANCED_MESSAGE: 'enhanced_message',\r\n \r\n // System messages\r\n HEARTBEAT: 'heartbeat',\r\n VERIFICATION: 'verification',\r\n VERIFICATION_RESPONSE: 'verification_response',\r\n VERIFICATION_CONFIRMED: 'verification_confirmed',\r\n VERIFICATION_BOTH_CONFIRMED: 'verification_both_confirmed',\r\n PEER_DISCONNECT: 'peer_disconnect',\r\n SECURITY_UPGRADE: 'security_upgrade',\r\n KEY_ROTATION_SIGNAL: 'key_rotation_signal',\r\n KEY_ROTATION_READY: 'key_rotation_ready',\r\n \r\n // File transfer messages\r\n FILE_TRANSFER_START: 'file_transfer_start',\r\n FILE_TRANSFER_RESPONSE: 'file_transfer_response',\r\n FILE_CHUNK: 'file_chunk',\r\n CHUNK_CONFIRMATION: 'chunk_confirmation',\r\n FILE_TRANSFER_COMPLETE: 'file_transfer_complete',\r\n FILE_TRANSFER_ERROR: 'file_transfer_error',\r\n \r\n // Fake traffic\r\n FAKE: 'fake'\r\n };\r\n\r\n static FILTERED_RESULTS = {\r\n FAKE_MESSAGE: 'FAKE_MESSAGE_FILTERED',\r\n FILE_MESSAGE: 'FILE_MESSAGE_FILTERED', \r\n SYSTEM_MESSAGE: 'SYSTEM_MESSAGE_FILTERED'\r\n };\r\n\r\n // Static debug flag instead of this._debugMode\r\n static DEBUG_MODE = true; // Set to true during development, false in production\r\n\r\n\r\n constructor(onMessage, onStatusChange, onKeyExchange, onVerificationRequired, onAnswerError = null, onVerificationStateChange = null, config = {}) {\r\n // Determine runtime mode\r\n this._isProductionMode = this._detectProductionMode();\r\n // Use static flag instead of this._debugMode\r\n this._debugMode = !this._isProductionMode && EnhancedSecureWebRTCManager.DEBUG_MODE;\r\n \r\n // Configuration from constructor parameters instead of global flags\r\n this._config = {\r\n fakeTraffic: {\r\n enabled: config.fakeTraffic?.enabled ?? true,\r\n minInterval: config.fakeTraffic?.minInterval ?? EnhancedSecureWebRTCManager.TIMEOUTS.FAKE_TRAFFIC_MIN_INTERVAL,\r\n maxInterval: config.fakeTraffic?.maxInterval ?? EnhancedSecureWebRTCManager.TIMEOUTS.FAKE_TRAFFIC_MAX_INTERVAL,\r\n minSize: config.fakeTraffic?.minSize ?? EnhancedSecureWebRTCManager.SIZES.FAKE_TRAFFIC_MIN_SIZE,\r\n maxSize: config.fakeTraffic?.maxSize ?? EnhancedSecureWebRTCManager.SIZES.FAKE_TRAFFIC_MAX_SIZE,\r\n patterns: config.fakeTraffic?.patterns ?? ['heartbeat', 'status', 'sync']\r\n },\r\n decoyChannels: {\r\n enabled: config.decoyChannels?.enabled ?? true,\r\n maxDecoyChannels: config.decoyChannels?.maxDecoyChannels ?? EnhancedSecureWebRTCManager.LIMITS.MAX_DECOY_CHANNELS,\r\n decoyChannelNames: config.decoyChannels?.decoyChannelNames ?? ['heartbeat'],\r\n sendDecoyData: config.decoyChannels?.sendDecoyData ?? true,\r\n randomDecoyIntervals: config.decoyChannels?.randomDecoyIntervals ?? true\r\n },\r\n packetPadding: {\r\n enabled: config.packetPadding?.enabled ?? true,\r\n minPadding: config.packetPadding?.minPadding ?? EnhancedSecureWebRTCManager.SIZES.PACKET_PADDING_MIN,\r\n maxPadding: config.packetPadding?.maxPadding ?? EnhancedSecureWebRTCManager.SIZES.PACKET_PADDING_MAX,\r\n useRandomPadding: config.packetPadding?.useRandomPadding ?? true,\r\n preserveMessageSize: config.packetPadding?.preserveMessageSize ?? false\r\n },\r\n antiFingerprinting: {\r\n enabled: config.antiFingerprinting?.enabled ?? false,\r\n randomizeTiming: config.antiFingerprinting?.randomizeTiming ?? true,\r\n randomizeSizes: config.antiFingerprinting?.randomizeSizes ?? false,\r\n addNoise: config.antiFingerprinting?.addNoise ?? true,\r\n maskPatterns: config.antiFingerprinting?.maskPatterns ?? false,\r\n useRandomHeaders: config.antiFingerprinting?.useRandomHeaders ?? false\r\n }\r\n };\r\n\r\n // Initialize own logging system\r\n this._initializeSecureLogging();\r\n this._setupOwnLogger();\r\n this._setupProductionLogging();\r\n \r\n // Store important methods first\r\n this._storeImportantMethods();\r\n \r\n // Setup global API after storing methods\r\n this._setupSecureGlobalAPI();\r\n if (!window.EnhancedSecureCryptoUtils) {\r\n throw new Error('EnhancedSecureCryptoUtils is not loaded. Please ensure the module is loaded first.');\r\n }\r\n this.getSecurityData = () => {\r\n // Return only public information\r\n return this.lastSecurityCalculation ? {\r\n level: this.lastSecurityCalculation.level,\r\n score: this.lastSecurityCalculation.score,\r\n timestamp: this.lastSecurityCalculation.timestamp,\r\n // Do NOT return check details or sensitive data\r\n } : null;\r\n };\r\n this._secureLog('info', '\uD83D\uDD12 Enhanced WebRTC Manager initialized with secure API');\r\n this.sessionConstraints = null;\r\n this.peerConnection = null;\r\n this.dataChannel = null;\r\n\r\n\r\n this.onMessage = onMessage;\r\n this.onStatusChange = onStatusChange;\r\n this.onKeyExchange = onKeyExchange;\r\n this.onVerificationStateChange = onVerificationStateChange;\r\n\r\n this.onVerificationRequired = onVerificationRequired;\r\n this.onAnswerError = onAnswerError; // Callback for response processing errors\r\n this.isInitiator = false;\r\n this.connectionAttempts = 0;\r\n this.maxConnectionAttempts = EnhancedSecureWebRTCManager.LIMITS.MAX_CONNECTION_ATTEMPTS;\r\n try {\r\n this._initializeMutexSystem();\r\n} catch (error) {\r\n this._secureLog('error', '\u274C Failed to initialize mutex system', {\r\n errorType: error.constructor.name\r\n });\r\n throw new Error('Critical: Mutex system initialization failed');\r\n}\r\n\r\n// Post-initialization validation of the mutex system\r\nif (!this._validateMutexSystem()) {\r\n this._secureLog('error', '\u274C Mutex system validation failed after initialization');\r\n throw new Error('Critical: Mutex system validation failed');\r\n}\r\n\r\nif (typeof window !== 'undefined') {\r\n this._secureLog('info', '\uD83D\uDD12 Emergency mutex handlers will be available through secure API');\r\n}\r\n\r\nthis._secureLog('info', '\uD83D\uDD12 Enhanced Mutex system fully initialized and validated');\r\n this.heartbeatInterval = null;\r\n this.messageQueue = [];\r\n this.ecdhKeyPair = null;\r\n this.ecdsaKeyPair = null;\r\n if (this.fileTransferSystem) {\r\n this.fileTransferSystem.cleanup();\r\n this.fileTransferSystem = null;\r\n }\r\n this.verificationCode = null;\r\n this.pendingSASCode = null;\r\n this.isVerified = false;\r\n this.processedMessageIds = new Set();\r\n \r\n // Mutual verification states\r\n this.localVerificationConfirmed = false;\r\n this.remoteVerificationConfirmed = false;\r\n this.bothVerificationsConfirmed = false;\r\n \r\n // Store expected DTLS fingerprint for validation\r\n this.expectedDTLSFingerprint = null;\r\n this.strictDTLSValidation = true; // Can be disabled for debugging\r\n \r\n // Real Perfect Forward Secrecy implementation\r\n this.ephemeralKeyPairs = new Map(); // Store ephemeral keys for current session only\r\n this.sessionStartTime = Date.now(); // Track session lifetime for PFS\r\n this.messageCounter = 0;\r\n this.sequenceNumber = 0;\r\n this.expectedSequenceNumber = 0;\r\n this.sessionSalt = null;\r\n \r\n // Anti-Replay and Message Ordering Protection\r\n this.replayWindowSize = 64; // Sliding window for replay protection\r\n this.replayWindow = new Set(); // Track recent sequence numbers\r\n this.maxSequenceGap = 100; // Maximum allowed sequence gap\r\n this.replayProtectionEnabled = true; // Enable/disable replay protection\r\n this.sessionId = null; // MITM protection: Session identifier\r\n this.connectionId = Array.from(crypto.getRandomValues(new Uint8Array(8)))\r\n .map(b => b.toString(16).padStart(2, '0')).join(''); // Connection identifier for AAD\r\n this.peerPublicKey = null; // Store peer's public key for PFS\r\n this.rateLimiterId = null;\r\n this.intentionalDisconnect = false;\r\n this.lastCleanupTime = Date.now();\r\n \r\n // Reset notification flags for new connection\r\n this._resetNotificationFlags();\r\n \r\n \r\n\r\n this.verificationInitiationSent = false;\r\n this.disconnectNotificationSent = false;\r\n this.reconnectionFailedNotificationSent = false;\r\n this.peerDisconnectNotificationSent = false;\r\n this.connectionClosedNotificationSent = false;\r\n this.fakeTrafficDisabledNotificationSent = false;\r\n this.advancedFeaturesDisabledNotificationSent = false;\r\n this.securityUpgradeNotificationSent = false;\r\n this.lastSecurityUpgradeStage = null;\r\n this.securityCalculationNotificationSent = false;\r\n this.lastSecurityCalculationLevel = null;\r\n \r\n // File transfer integration\r\n this.fileTransferSystem = null;\r\n this.onFileProgress = null;\r\n \r\n // ============================================\r\n // IV REUSE PREVENTION SYSTEM\r\n // ============================================\r\n // IV REUSE PREVENTION SYSTEM WITH LIMITS\r\n // ============================================\r\n this._ivTrackingSystem = {\r\n usedIVs: new Set(), // Track all used IVs to prevent reuse\r\n ivHistory: new Map(), // Track IV usage with timestamps (max 10k entries)\r\n collisionCount: 0, // Track potential collisions\r\n maxIVHistorySize: 10000, // Maximum IV history size\r\n maxSessionIVs: 1000, // Maximum IVs per session\r\n entropyValidation: {\r\n minEntropy: 3.0, // Minimum entropy threshold\r\n entropyTests: 0,\r\n entropyFailures: 0\r\n },\r\n rngValidation: {\r\n testsPerformed: 0,\r\n weakRngDetected: false,\r\n lastValidation: 0\r\n },\r\n sessionIVs: new Map(), // Track IVs per session\r\n emergencyMode: false // Emergency mode if IV reuse detected\r\n };\r\n \r\n // IV cleanup tracking\r\n this._lastIVCleanupTime = null;\r\n \r\n // ============================================\r\n // SECURE ERROR HANDLING SYSTEM\r\n // ============================================\r\n this._secureErrorHandler = {\r\n errorCategories: {\r\n CRYPTOGRAPHIC: 'cryptographic',\r\n NETWORK: 'network',\r\n VALIDATION: 'validation',\r\n SYSTEM: 'system',\r\n UNKNOWN: 'unknown'\r\n },\r\n errorMappings: new Map(), // Map internal errors to safe messages\r\n errorCounts: new Map(), // Track error frequencies\r\n lastErrorTime: 0,\r\n errorThreshold: 10, // Max errors per minute\r\n isInErrorMode: false\r\n };\r\n \r\n // ============================================\r\n // SECURE MEMORY MANAGEMENT SYSTEM\r\n // ============================================\r\n this._secureMemoryManager = {\r\n sensitiveData: new WeakMap(), // Track sensitive data for secure cleanup\r\n cleanupQueue: [], // Queue for deferred cleanup operations\r\n isCleaning: false, // Prevent concurrent cleanup operations\r\n cleanupInterval: null, // Periodic cleanup timer\r\n memoryStats: {\r\n totalCleanups: 0,\r\n failedCleanups: 0,\r\n lastCleanup: 0\r\n }\r\n };\r\n this.onFileReceived = null;\r\n this.onFileError = null;\r\n \r\n // PFS (Perfect Forward Secrecy) Implementation\r\n this.keyRotationInterval = null; // \u043E\u0442\u043A\u043B\u044E\u0447\u0430\u0435\u043C \u0442\u0430\u0439\u043C\u0435\u0440\u043D\u0443\u044E \u0440\u043E\u0442\u0430\u0446\u0438\u044E\r\n this.lastKeyRotation = Date.now();\r\n this.currentKeyVersion = 0;\r\n this.keyVersions = new Map(); // Store key versions for PFS\r\n this.oldKeys = new Map(); // Store old keys temporarily for decryption\r\n this.maxOldKeys = EnhancedSecureWebRTCManager.LIMITS.MAX_OLD_KEYS; // Keep last 3 key versions for decryption\r\n this.peerConnection = null;\r\n this.dataChannel = null;\r\n \r\n\r\n this.securityFeatures = {\r\n // All security features enabled by default - no payment required\r\n hasEncryption: true, \r\n hasECDH: true, \r\n hasECDSA: true, \r\n hasMutualAuth: true, \r\n hasMetadataProtection: true, \r\n hasEnhancedReplayProtection: true, \r\n hasNonExtractableKeys: true, \r\n hasRateLimiting: true, \r\n hasEnhancedValidation: true, \r\n hasPFS: true, // Real Perfect Forward Secrecy enabled \r\n \r\n // Advanced Features - All enabled by default\r\n hasNestedEncryption: true, \r\n hasPacketPadding: true, \r\n hasPacketReordering: true, \r\n hasAntiFingerprinting: true, \r\n hasFakeTraffic: true, \r\n hasDecoyChannels: true, \r\n hasMessageChunking: true \r\n };\r\n this._secureLog('info', '\uD83D\uDD12 Enhanced WebRTC Manager initialized with tiered security');\r\n \r\n // Log configuration for debugging\r\n this._secureLog('info', '\uD83D\uDD12 Configuration loaded from constructor parameters', {\r\n fakeTraffic: this._config.fakeTraffic.enabled,\r\n decoyChannels: this._config.decoyChannels.enabled,\r\n packetPadding: this._config.packetPadding.enabled,\r\n antiFingerprinting: this._config.antiFingerprinting.enabled\r\n });\r\n \r\n // Session mode: 'time' | 'ratchet' (Double Ratchet controls key lifecycle)\r\n this.sessionMode = 'ratchet';\r\n\r\n // XSS Hardening - replace all window.DEBUG_MODE references\r\n this._hardenDebugModeReferences();\r\n \r\n // Initialize unified scheduler for all maintenance tasks\r\n this._initializeUnifiedScheduler();\r\n \r\n this._syncSecurityFeaturesWithTariff();\r\n \r\n if (!this._validateCryptographicSecurity()) {\r\n this._secureLog('error', '\uD83D\uDEA8 CRITICAL: Cryptographic security validation failed after tariff sync');\r\n throw new Error('Critical cryptographic features are missing after tariff synchronization');\r\n }\r\n // ============================================\r\n // ENHANCED SECURITY FEATURES\r\n // ============================================\r\n \r\n // 1. Nested Encryption Layer\r\n this.nestedEncryptionKey = null;\r\n // Removed nestedEncryptionIV and nestedEncryptionCounter\r\n // Each nested encryption now generates fresh random IV for maximum security\r\n \r\n // 2. Packet Padding\r\n this.paddingConfig = {\r\n enabled: this._config.packetPadding.enabled,\r\n minPadding: this._config.packetPadding.minPadding,\r\n maxPadding: this._config.packetPadding.maxPadding,\r\n useRandomPadding: this._config.packetPadding.useRandomPadding,\r\n preserveMessageSize: this._config.packetPadding.preserveMessageSize\r\n };\r\n \r\n // 3. Fake Traffic Generation\r\n this.fakeTrafficConfig = {\r\n enabled: this._config.fakeTraffic?.enabled || false,\r\n minInterval: this._config.fakeTraffic?.minInterval || 15000,\r\n maxInterval: this._config.fakeTraffic?.maxInterval || 30000,\r\n minSize: this._config.fakeTraffic?.minSize || 64,\r\n maxSize: this._config.fakeTraffic?.maxSize || 1024,\r\n patterns: this._config.fakeTraffic?.patterns || ['heartbeat', 'status', 'ping'],\r\n randomDecoyIntervals: this._config.fakeTraffic?.randomDecoyIntervals || true\r\n };\r\n this.fakeTrafficTimer = null;\r\n this.lastFakeTraffic = 0;\r\n \r\n // 4. Message Chunking\r\n this.chunkingConfig = {\r\n enabled: false,\r\n maxChunkSize: EnhancedSecureWebRTCManager.SIZES.CHUNK_SIZE_MAX, \r\n minDelay: EnhancedSecureWebRTCManager.SIZES.CHUNK_DELAY_MIN,\r\n maxDelay: EnhancedSecureWebRTCManager.SIZES.CHUNK_DELAY_MAX,\r\n useRandomDelays: true,\r\n addChunkHeaders: true\r\n };\r\n this.chunkQueue = [];\r\n this.chunkingInProgress = false;\r\n \r\n // 5. Decoy Channels\r\n this.decoyChannels = new Map();\r\n this.decoyChannelConfig = {\r\n enabled: this._config.decoyChannels.enabled,\r\n maxDecoyChannels: this._config.decoyChannels.maxDecoyChannels,\r\n decoyChannelNames: this._config.decoyChannels.decoyChannelNames,\r\n sendDecoyData: this._config.decoyChannels.sendDecoyData,\r\n randomDecoyIntervals: this._config.decoyChannels.randomDecoyIntervals\r\n };\r\n this.decoyTimers = new Map();\r\n \r\n // 6. Packet Reordering Protection\r\n this.reorderingConfig = {\r\n enabled: false, \r\n maxOutOfOrder: EnhancedSecureWebRTCManager.LIMITS.MAX_OUT_OF_ORDER_PACKETS, \r\n reorderTimeout: EnhancedSecureWebRTCManager.TIMEOUTS.REORDER_TIMEOUT, \r\n useSequenceNumbers: true,\r\n useTimestamps: true\r\n };\r\n this.packetBuffer = new Map(); // sequence -> {data, timestamp}\r\n this.lastProcessedSequence = -1;\r\n \r\n // 7. Anti-Fingerprinting\r\n this.antiFingerprintingConfig = {\r\n enabled: this._config.antiFingerprinting.enabled,\r\n randomizeTiming: this._config.antiFingerprinting.randomizeTiming,\r\n randomizeSizes: this._config.antiFingerprinting.randomizeSizes,\r\n addNoise: this._config.antiFingerprinting.addNoise,\r\n maskPatterns: this._config.antiFingerprinting.maskPatterns,\r\n useRandomHeaders: this._config.antiFingerprinting.useRandomHeaders\r\n };\r\n this.fingerprintMask = this.generateFingerprintMask();\r\n \r\n // Initialize rate limiter ID\r\n this.rateLimiterId = `webrtc_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;\r\n \r\n // Start periodic cleanup\r\n this.startPeriodicCleanup();\r\n \r\n this.initializeEnhancedSecurity(); \r\n \r\n // ============================================\r\n // MUTEX SYSTEM TO PREVENT RACE CONDITIONS\r\n // ============================================\r\n\r\n // Mutex for key operations\r\n this._keyOperationMutex = {\r\n locked: false,\r\n queue: [],\r\n lockId: null,\r\n lockTimeout: null\r\n };\r\n\r\n // Mutex for encryption/decryption operations\r\n this._cryptoOperationMutex = {\r\n locked: false,\r\n queue: [],\r\n lockId: null,\r\n lockTimeout: null\r\n };\r\n\r\n // Mutex for connection initialization\r\n this._connectionOperationMutex = {\r\n locked: false,\r\n queue: [],\r\n lockId: null,\r\n lockTimeout: null\r\n };\r\n\r\n // Key system state\r\n this._keySystemState = {\r\n isInitializing: false,\r\n isRotating: false,\r\n isDestroying: false,\r\n lastOperation: null,\r\n lastOperationTime: Date.now()\r\n };\r\n\r\n // Operation counters\r\n this._operationCounters = {\r\n keyOperations: 0,\r\n cryptoOperations: 0,\r\n connectionOperations: 0\r\n };\r\n\r\n }\r\n \r\n /**\r\n * Create AAD with sequence number for anti-replay protection\r\n * This binds each message to its sequence number and prevents replay attacks\r\n */\r\n _createMessageAAD(messageType, messageData = null, isFileMessage = false) {\r\n try {\r\n const aad = {\r\n sessionId: this.currentSession?.sessionId || this.sessionId || 'unknown',\r\n keyFingerprint: this.keyFingerprint || 'unknown',\r\n sequenceNumber: this._generateNextSequenceNumber(),\r\n messageType: messageType,\r\n timestamp: Date.now(),\r\n connectionId: this.connectionId || 'unknown',\r\n isFileMessage: isFileMessage\r\n };\r\n\r\n // Add message-specific data if available\r\n if (messageData && typeof messageData === 'object') {\r\n if (messageData.fileId) aad.fileId = messageData.fileId;\r\n if (messageData.chunkIndex !== undefined) aad.chunkIndex = messageData.chunkIndex;\r\n if (messageData.totalChunks !== undefined) aad.totalChunks = messageData.totalChunks;\r\n }\r\n\r\n return JSON.stringify(aad);\r\n } catch (error) {\r\n this._secureLog('error', '\u274C Failed to create message AAD', {\r\n errorType: error.constructor.name,\r\n message: error.message,\r\n messageType: messageType\r\n });\r\n // Fallback to basic AAD\r\n return JSON.stringify({\r\n sessionId: 'unknown',\r\n keyFingerprint: 'unknown',\r\n sequenceNumber: Date.now(),\r\n messageType: messageType,\r\n timestamp: Date.now(),\r\n connectionId: 'unknown',\r\n isFileMessage: isFileMessage\r\n });\r\n }\r\n }\r\n \r\n /**\r\n * Generate next sequence number for outgoing messages\r\n * This ensures unique ordering and prevents replay attacks\r\n */\r\n _generateNextSequenceNumber() {\r\n const nextSeq = this.sequenceNumber++;\r\n \r\n // Reset sequence number if it gets too large\r\n if (this.sequenceNumber > Number.MAX_SAFE_INTEGER - 1000) {\r\n this.sequenceNumber = 0;\r\n this.expectedSequenceNumber = 0;\r\n this.replayWindow.clear();\r\n this._secureLog('warn', '\u26A0\uFE0F Sequence number reset due to overflow', {\r\n timestamp: Date.now()\r\n });\r\n }\r\n \r\n return nextSeq;\r\n }\r\n\r\n /**\r\n * Create a safe hash for logging sensitive data\r\n * Returns only the first 4 bytes (8 hex chars) of SHA-256 hash\r\n * @param {any} sensitiveData - The sensitive data to hash\r\n * @param {string} context - Context for error logging\r\n * @returns {Promise} - Short hash (8 hex chars) or 'hash_error'\r\n */\r\n async _createSafeLogHash(sensitiveData, context = 'unknown') {\r\n try {\r\n let dataToHash;\r\n \r\n // Convert different data types to consistent format for hashing\r\n if (sensitiveData instanceof ArrayBuffer) {\r\n dataToHash = new Uint8Array(sensitiveData);\r\n } else if (sensitiveData instanceof Uint8Array) {\r\n dataToHash = sensitiveData;\r\n } else if (sensitiveData instanceof CryptoKey) {\r\n // For CryptoKey, use its type and algorithm info (not the key material)\r\n const keyInfo = `${sensitiveData.type}_${sensitiveData.algorithm?.name || 'unknown'}_${sensitiveData.extractable}`;\r\n dataToHash = new TextEncoder().encode(keyInfo);\r\n } else if (typeof sensitiveData === 'string') {\r\n dataToHash = new TextEncoder().encode(sensitiveData);\r\n } else if (typeof sensitiveData === 'object' && sensitiveData !== null) {\r\n // For objects (like JWK), stringify without sensitive fields\r\n const safeObj = { type: sensitiveData.kty || 'unknown', use: sensitiveData.use || 'unknown' };\r\n dataToHash = new TextEncoder().encode(JSON.stringify(safeObj));\r\n } else {\r\n // Fallback for other types\r\n dataToHash = new TextEncoder().encode(String(sensitiveData));\r\n }\r\n \r\n // Create SHA-256 hash\r\n const hashBuffer = await crypto.subtle.digest('SHA-256', dataToHash);\r\n const hashArray = new Uint8Array(hashBuffer);\r\n \r\n // Return only first 4 bytes as hex (8 characters)\r\n return Array.from(hashArray.slice(0, 4))\r\n .map(b => b.toString(16).padStart(2, '0'))\r\n .join('');\r\n \r\n } catch (error) {\r\n // Never log the actual error details to avoid leaking sensitive data\r\n return 'hash_error';\r\n }\r\n }\r\n\r\n /**\r\n * Async sleep helper - replaces busy-wait\r\n */\r\n async _asyncSleep(ms) {\r\n return new Promise(resolve => setTimeout(resolve, ms));\r\n }\r\n\r\n /**\r\n * Async cleanup helper - replaces immediate heavy operations\r\n */\r\n async _scheduleAsyncCleanup(cleanupFn, delay = 0) {\r\n return new Promise((resolve) => {\r\n setTimeout(async () => {\r\n try {\r\n await cleanupFn();\r\n resolve(true);\r\n } catch (error) {\r\n this._secureLog('error', 'Async cleanup failed', {\r\n errorType: error?.constructor?.name || 'Unknown'\r\n });\r\n resolve(false);\r\n }\r\n }, delay);\r\n });\r\n }\r\n\r\n /**\r\n * Batch async operations to prevent UI blocking\r\n */\r\n async _batchAsyncOperation(items, batchSize = 10, delayBetweenBatches = 5) {\r\n const results = [];\r\n \r\n for (let i = 0; i < items.length; i += batchSize) {\r\n const batch = items.slice(i, i + batchSize);\r\n const batchResults = await Promise.all(batch);\r\n results.push(...batchResults);\r\n \r\n // Small delay between batches to prevent UI blocking\r\n if (i + batchSize < items.length) {\r\n await this._asyncSleep(delayBetweenBatches);\r\n }\r\n }\r\n \r\n return results;\r\n }\r\n\r\n /**\r\n * Memory cleanup without window.gc() - uses natural garbage collection\r\n */\r\n async _performNaturalCleanup() {\r\n // Clear references and let JS engine handle GC naturally\r\n // This is more reliable than forcing GC\r\n \r\n // Schedule cleanup in next event loop cycle\r\n await this._asyncSleep(0);\r\n \r\n // Allow multiple event loop cycles for natural GC\r\n for (let i = 0; i < 3; i++) {\r\n await this._asyncSleep(10);\r\n }\r\n }\r\n\r\n /**\r\n * Heavy cleanup operations using WebWorker (if available)\r\n */\r\n async _performHeavyCleanup(cleanupData) {\r\n // Try to use WebWorker for heavy operations\r\n if (typeof Worker !== 'undefined') {\r\n try {\r\n return await this._cleanupWithWorker(cleanupData);\r\n } catch (error) {\r\n this._secureLog('warn', 'WebWorker cleanup failed, falling back to main thread', {\r\n errorType: error?.constructor?.name || 'Unknown'\r\n });\r\n }\r\n }\r\n \r\n // Fallback to main thread with async batching\r\n return await this._cleanupInMainThread(cleanupData);\r\n }\r\n\r\n /**\r\n * Cleanup using WebWorker\r\n */\r\n async _cleanupWithWorker(cleanupData) {\r\n return new Promise((resolve, reject) => {\r\n // Create inline worker for cleanup operations\r\n const workerCode = `\r\n self.onmessage = function(e) {\r\n const { type, data } = e.data;\r\n \r\n try {\r\n switch (type) {\r\n case 'cleanup_arrays':\r\n // Simulate heavy array cleanup\r\n let processed = 0;\r\n for (let i = 0; i < data.count; i++) {\r\n // Simulate work\r\n processed++;\r\n if (processed % 1000 === 0) {\r\n // Yield control periodically\r\n setTimeout(() => {}, 0);\r\n }\r\n }\r\n self.postMessage({ success: true, processed });\r\n break;\r\n \r\n case 'cleanup_objects':\r\n // Simulate object cleanup\r\n const cleaned = data.objects.map(() => null);\r\n self.postMessage({ success: true, cleaned: cleaned.length });\r\n break;\r\n \r\n default:\r\n self.postMessage({ success: true, message: 'Unknown cleanup type' });\r\n }\r\n } catch (error) {\r\n self.postMessage({ success: false, error: error.message });\r\n }\r\n };\r\n `;\r\n \r\n const blob = new Blob([workerCode], { type: 'application/javascript' });\r\n const worker = new Worker(URL.createObjectURL(blob));\r\n \r\n const timeout = setTimeout(() => {\r\n worker.terminate();\r\n reject(new Error('Worker cleanup timeout'));\r\n }, 5000); // 5 second timeout\r\n \r\n worker.onmessage = (e) => {\r\n clearTimeout(timeout);\r\n worker.terminate();\r\n URL.revokeObjectURL(blob);\r\n \r\n if (e.data.success) {\r\n resolve(e.data);\r\n } else {\r\n reject(new Error(e.data.error));\r\n }\r\n };\r\n \r\n worker.onerror = (error) => {\r\n clearTimeout(timeout);\r\n worker.terminate();\r\n URL.revokeObjectURL(blob);\r\n reject(error);\r\n };\r\n \r\n worker.postMessage(cleanupData);\r\n });\r\n }\r\n\r\n /**\r\n * Cleanup in main thread with async batching\r\n */\r\n async _cleanupInMainThread(cleanupData) {\r\n const { type, data } = cleanupData;\r\n \r\n switch (type) {\r\n case 'cleanup_arrays':\r\n // Process in batches to avoid blocking\r\n let processed = 0;\r\n const batchSize = 100;\r\n \r\n while (processed < data.count) {\r\n const batchEnd = Math.min(processed + batchSize, data.count);\r\n \r\n // Process batch\r\n for (let i = processed; i < batchEnd; i++) {\r\n // Simulate cleanup work\r\n }\r\n \r\n processed = batchEnd;\r\n \r\n // Yield control to prevent UI blocking\r\n await this._asyncSleep(1);\r\n }\r\n \r\n return { success: true, processed };\r\n \r\n case 'cleanup_objects':\r\n // Clean objects in batches\r\n const objects = data.objects || [];\r\n const batches = [];\r\n \r\n for (let i = 0; i < objects.length; i += 50) {\r\n batches.push(objects.slice(i, i + 50));\r\n }\r\n \r\n let cleaned = 0;\r\n for (const batch of batches) {\r\n batch.forEach(() => cleaned++);\r\n await this._asyncSleep(1);\r\n }\r\n \r\n return { success: true, cleaned };\r\n \r\n default:\r\n return { success: true, message: 'Unknown cleanup type' };\r\n }\r\n }\r\n \r\n /**\r\n * Enhanced mutex system initialization with atomic protection\r\n */\r\n _initializeMutexSystem() {\r\n // Initialize standard mutexes with enhanced state tracking\r\n this._keyOperationMutex = {\r\n locked: false,\r\n queue: [],\r\n lockId: null,\r\n lockTimeout: null,\r\n lockTime: null,\r\n operationCount: 0\r\n };\r\n\r\n this._cryptoOperationMutex = {\r\n locked: false,\r\n queue: [],\r\n lockId: null,\r\n lockTimeout: null,\r\n lockTime: null,\r\n operationCount: 0\r\n };\r\n\r\n this._connectionOperationMutex = {\r\n locked: false,\r\n queue: [],\r\n lockId: null,\r\n lockTimeout: null,\r\n lockTime: null,\r\n operationCount: 0\r\n };\r\n\r\n // Enhanced key system state with atomic operation tracking\r\n this._keySystemState = {\r\n isInitializing: false,\r\n isRotating: false,\r\n isDestroying: false,\r\n lastOperation: null,\r\n lastOperationTime: Date.now(),\r\n operationId: null,\r\n concurrentOperations: 0,\r\n maxConcurrentOperations: 1\r\n };\r\n\r\n // Operation counters with atomic increments\r\n this._operationCounters = {\r\n keyOperations: 0,\r\n cryptoOperations: 0,\r\n connectionOperations: 0,\r\n totalOperations: 0,\r\n failedOperations: 0\r\n };\r\n\r\n this._secureLog('info', '\uD83D\uDD12 Enhanced mutex system initialized with atomic protection', {\r\n mutexes: ['keyOperation', 'cryptoOperation', 'connectionOperation'],\r\n timestamp: Date.now(),\r\n features: ['atomic_operations', 'race_condition_protection', 'enhanced_state_tracking']\r\n });\r\n }\r\n\r\n /**\r\n * XSS Hardening - Debug mode references validation\r\n * This method is called during initialization to ensure XSS hardening\r\n */\r\n _hardenDebugModeReferences() {\r\n // Log that we're hardening debug mode references\r\n this._secureLog('info', '\uD83D\uDD12 XSS Hardening: Debug mode references already replaced');\r\n }\r\n\r\n /**\r\n * Unified scheduler for all maintenance tasks\r\n * Replaces multiple setInterval calls with a single, controlled scheduler\r\n */\r\n _initializeUnifiedScheduler() {\r\n // Single scheduler interval for all maintenance tasks\r\n this._maintenanceScheduler = setInterval(() => {\r\n this._executeMaintenanceCycle();\r\n }, 300000); // Every 5 minutes\r\n \r\n // Log scheduler initialization\r\n this._secureLog('info', '\uD83D\uDD27 Unified maintenance scheduler initialized (5-minute cycle)');\r\n \r\n // Store scheduler reference for cleanup\r\n this._activeTimers = new Set([this._maintenanceScheduler]);\r\n }\r\n\r\n /**\r\n * Execute all maintenance tasks in a single cycle\r\n */\r\n _executeMaintenanceCycle() {\r\n try {\r\n this._secureLog('info', '\uD83D\uDD27 Starting maintenance cycle');\r\n \r\n // 1. Log cleanup and security audit\r\n this._cleanupLogs();\r\n this._auditLoggingSystemSecurity();\r\n \r\n // 2. Security monitoring\r\n this._verifyAPIIntegrity();\r\n this._validateCryptographicSecurity();\r\n this._syncSecurityFeaturesWithTariff();\r\n \r\n // 3. Resource cleanup\r\n this._cleanupResources();\r\n this._enforceResourceLimits();\r\n \r\n // 4. Key monitoring (if connected)\r\n if (this.isConnected && this.isVerified) {\r\n this._monitorKeySecurity();\r\n }\r\n \r\n // 5. Global exposure monitoring (debug mode only)\r\n if (this._debugMode) {\r\n this._monitorGlobalExposure();\r\n }\r\n \r\n // 6. Heartbeat (if enabled and connected)\r\n if (this._heartbeatConfig && this._heartbeatConfig.enabled && this.isConnected()) {\r\n this._sendHeartbeat();\r\n }\r\n \r\n this._secureLog('info', '\uD83D\uDD27 Maintenance cycle completed successfully');\r\n \r\n } catch (error) {\r\n this._secureLog('error', '\u274C Maintenance cycle failed', {\r\n errorType: error?.constructor?.name || 'Unknown',\r\n message: error?.message || 'Unknown error'\r\n });\r\n \r\n // Emergency cleanup on failure\r\n this._emergencyCleanup().catch(error => {\r\n this._secureLog('error', 'Emergency cleanup failed', {\r\n errorType: error?.constructor?.name || 'Unknown'\r\n });\r\n });\r\n }\r\n }\r\n\r\n /**\r\n * Enforce hard resource limits with emergency cleanup\r\n */\r\n _enforceResourceLimits() {\r\n const violations = [];\r\n \r\n // Check log entries\r\n if (this._logCounts.size > this._resourceLimits.maxLogEntries) {\r\n violations.push('log_entries');\r\n }\r\n \r\n // Check message queue\r\n if (this.messageQueue.length > this._resourceLimits.maxMessageQueue) {\r\n violations.push('message_queue');\r\n }\r\n \r\n // Check IV history\r\n if (this._ivTrackingSystem && this._ivTrackingSystem.ivHistory.size > this._resourceLimits.maxIVHistory) {\r\n violations.push('iv_history');\r\n }\r\n \r\n // Check processed message IDs\r\n if (this.processedMessageIds.size > this._resourceLimits.maxProcessedMessageIds) {\r\n violations.push('processed_message_ids');\r\n }\r\n \r\n // Check decoy channels\r\n if (this.decoyChannels.size > this._resourceLimits.maxDecoyChannels) {\r\n violations.push('decoy_channels');\r\n }\r\n \r\n // Check fake traffic messages\r\n if (this._fakeTrafficMessages && this._fakeTrafficMessages.length > this._resourceLimits.maxFakeTrafficMessages) {\r\n violations.push('fake_traffic_messages');\r\n }\r\n \r\n // Check chunk queue\r\n if (this.chunkQueue.length > this._resourceLimits.maxChunkQueue) {\r\n violations.push('chunk_queue');\r\n }\r\n \r\n // Check packet buffer\r\n if (this.packetBuffer && this.packetBuffer.size > this._resourceLimits.maxPacketBuffer) {\r\n violations.push('packet_buffer');\r\n }\r\n \r\n // If violations detected, trigger emergency cleanup\r\n if (violations.length > 0) {\r\n this._secureLog('warn', '\u26A0\uFE0F Resource limit violations detected', { violations });\r\n this._emergencyCleanup().catch(error => {\r\n this._secureLog('error', 'Emergency cleanup failed', {\r\n errorType: error?.constructor?.name || 'Unknown'\r\n });\r\n });\r\n }\r\n }\r\n\r\n /**\r\n * Emergency cleanup when resource limits are exceeded\r\n */\r\n async _emergencyCleanup() {\r\n this._secureLog('warn', '\uD83D\uDEA8 EMERGENCY: Resource limits exceeded, performing emergency cleanup');\r\n \r\n try {\r\n // 1. Clear all logs immediately\r\n this._logCounts.clear();\r\n this._secureLog('info', '\uD83E\uDDF9 Emergency: All logs cleared');\r\n \r\n // 2. Clear message queue\r\n this.messageQueue.length = 0;\r\n this._secureLog('info', '\uD83E\uDDF9 Emergency: Message queue cleared');\r\n \r\n // 3. Enhanced IV history cleanup\r\n if (this._ivTrackingSystem) {\r\n this._ivTrackingSystem.usedIVs.clear();\r\n this._ivTrackingSystem.ivHistory.clear();\r\n this._ivTrackingSystem.sessionIVs.clear();\r\n this._ivTrackingSystem.collisionCount = 0;\r\n this._ivTrackingSystem.emergencyMode = false;\r\n this._secureLog('info', '\uD83E\uDDF9 Enhanced Emergency: IV tracking system cleared');\r\n }\r\n \r\n // 4. Clear processed message IDs\r\n this.processedMessageIds.clear();\r\n this._secureLog('info', '\uD83E\uDDF9 Emergency: Processed message IDs cleared');\r\n \r\n // 5. Enhanced decoy channels cleanup\r\n if (this.decoyChannels) {\r\n for (const [channelName, timer] of this.decoyTimers) {\r\n if (timer) clearTimeout(timer);\r\n }\r\n this.decoyChannels.clear();\r\n this.decoyTimers.clear();\r\n this._secureLog('info', '\uD83E\uDDF9 Enhanced Emergency: Decoy channels cleared');\r\n }\r\n \r\n // 6. Enhanced fake traffic cleanup\r\n if (this.fakeTrafficTimer) {\r\n clearTimeout(this.fakeTrafficTimer);\r\n this.fakeTrafficTimer = null;\r\n }\r\n if (this._fakeTrafficMessages) {\r\n this._fakeTrafficMessages.length = 0;\r\n this._secureLog('info', '\uD83E\uDDF9 Enhanced Emergency: Fake traffic messages cleared');\r\n }\r\n \r\n // 7. Clear chunk queue\r\n this.chunkQueue.length = 0;\r\n this._secureLog('info', '\uD83E\uDDF9 Emergency: Chunk queue cleared');\r\n \r\n // 8. Clear packet buffer\r\n if (this.packetBuffer) {\r\n this.packetBuffer.clear();\r\n this._secureLog('info', '\uD83E\uDDF9 Emergency: Packet buffer cleared');\r\n }\r\n \r\n // 9. Enhanced memory cleanup with quantum-resistant patterns\r\n this._secureMemoryManager.isCleaning = true;\r\n this._secureMemoryManager.cleanupQueue.length = 0;\r\n this._secureMemoryManager.memoryStats.lastCleanup = Date.now();\r\n \r\n // Perform natural cleanup without forcing GC\r\n await this._scheduleAsyncCleanup(async () => {\r\n this._secureLog('info', '\uD83E\uDDF9 Enhanced Emergency: Starting natural memory cleanup');\r\n \r\n // Natural cleanup cycles with async delays\r\n for (let i = 0; i < 3; i++) {\r\n this._secureLog('info', `\uD83E\uDDF9 Enhanced Emergency: Cleanup cycle ${i + 1}/3`);\r\n \r\n // Allow natural garbage collection between cycles\r\n await this._performNaturalCleanup();\r\n }\r\n \r\n this._secureLog('info', '\uD83E\uDDF9 Enhanced Emergency: Natural cleanup completed');\r\n }, 0);\r\n \r\n this._secureMemoryManager.isCleaning = false;\r\n \r\n this._secureLog('info', '\u2705 Enhanced emergency cleanup completed successfully');\r\n \r\n } catch (error) {\r\n this._secureLog('error', '\u274C Enhanced emergency cleanup failed', {\r\n errorType: error?.constructor?.name || 'Unknown',\r\n message: error?.message || 'Unknown error'\r\n });\r\n \r\n // Rollback mechanism (simplified)\r\n this._secureMemoryManager.isCleaning = false;\r\n }\r\n }\r\n\r\n /**\r\n * Validate emergency cleanup success\r\n * @param {Object} originalState - Original state before cleanup\r\n * @returns {Object} Validation results\r\n */\r\n _validateEmergencyCleanup(originalState) {\r\n const currentState = {\r\n messageQueueSize: this.messageQueue.length,\r\n processedIdsSize: this.processedMessageIds.size,\r\n packetBufferSize: this.packetBuffer ? this.packetBuffer.size : 0,\r\n ivTrackingSize: this._ivTrackingSystem ? this._ivTrackingSystem.usedIVs.size : 0,\r\n decoyChannelsSize: this.decoyChannels ? this.decoyChannels.size : 0\r\n };\r\n \r\n const validation = {\r\n messageQueueCleared: currentState.messageQueueSize === 0,\r\n processedIdsCleared: currentState.processedIdsSize === 0,\r\n packetBufferCleared: currentState.packetBufferSize === 0,\r\n ivTrackingCleared: currentState.ivTrackingSize === 0,\r\n decoyChannelsCleared: currentState.decoyChannelsSize === 0,\r\n allCleared: (\r\n currentState.messageQueueSize === 0 &&\r\n currentState.processedIdsSize === 0 &&\r\n currentState.packetBufferSize === 0 &&\r\n currentState.ivTrackingSize === 0 &&\r\n currentState.decoyChannelsSize === 0\r\n )\r\n };\r\n \r\n return validation;\r\n }\r\n\r\n /**\r\n * Cleanup resources based on age and usage\r\n */\r\n _cleanupResources() {\r\n const now = Date.now();\r\n \r\n // Clean old processed message IDs (keep only last hour)\r\n if (this.processedMessageIds.size > this._emergencyThresholds.processedMessageIds) {\r\n this.processedMessageIds.clear();\r\n this._secureLog('info', '\uD83E\uDDF9 Old processed message IDs cleared');\r\n }\r\n \r\n // Clean old IVs\r\n if (this._ivTrackingSystem) {\r\n this._cleanupOldIVs();\r\n }\r\n \r\n // Clean old keys\r\n this.cleanupOldKeys();\r\n \r\n // Clean rate limiter\r\n if (window.EnhancedSecureCryptoUtils && window.EnhancedSecureCryptoUtils.rateLimiter) {\r\n window.EnhancedSecureCryptoUtils.rateLimiter.cleanup();\r\n }\r\n \r\n this._secureLog('info', '\uD83E\uDDF9 Resource cleanup completed');\r\n }\r\n\r\n /**\r\n * Monitor key security (replaces _startKeySecurityMonitoring)\r\n */\r\n _monitorKeySecurity() {\r\n if (this._keyStorageStats.activeKeys > 10) {\r\n this._secureLog('warn', '\u26A0\uFE0F High number of active keys detected. Consider rotation.');\r\n }\r\n \r\n }\r\n\r\n /**\r\n * Send heartbeat message (called by unified scheduler)\r\n */\r\n _sendHeartbeat() {\r\n try {\r\n if (this.isConnected() && this.dataChannel && this.dataChannel.readyState === 'open') {\r\n this.dataChannel.send(JSON.stringify({ \r\n type: EnhancedSecureWebRTCManager.MESSAGE_TYPES.HEARTBEAT, \r\n timestamp: Date.now() \r\n }));\r\n \r\n this._heartbeatConfig.lastHeartbeat = Date.now();\r\n this._secureLog('debug', '\uD83D\uDC93 Heartbeat sent');\r\n }\r\n } catch (error) {\r\n this._secureLog('error', '\u274C Heartbeat failed:', { \r\n errorType: error?.constructor?.name || 'Unknown',\r\n message: error?.message || 'Unknown error'\r\n });\r\n }\r\n }\r\n\r\n /**\r\n * Comprehensive input validation to prevent DoS and injection attacks\r\n * @param {any} data - Data to validate\r\n * @param {string} context - Context for validation (e.g., 'sendMessage', 'sendSecureMessage')\r\n * @returns {Object} Validation result with isValid and sanitizedData\r\n */\r\n _validateInputData(data, context = 'unknown') {\r\n const validationResult = {\r\n isValid: false,\r\n sanitizedData: null,\r\n errors: [],\r\n warnings: []\r\n };\r\n\r\n try {\r\n // 1. Basic type validation\r\n if (data === null || data === undefined) {\r\n validationResult.errors.push('Data cannot be null or undefined');\r\n return validationResult;\r\n }\r\n\r\n // 2. Size validation for strings\r\n if (typeof data === 'string') {\r\n if (data.length > this._inputValidationLimits.maxStringLength) {\r\n validationResult.errors.push(`String too long: ${data.length} > ${this._inputValidationLimits.maxStringLength}`);\r\n return validationResult;\r\n }\r\n\r\n // 3. Malicious pattern detection for strings\r\n for (const pattern of this._maliciousPatterns) {\r\n if (pattern.test(data)) {\r\n validationResult.errors.push(`Malicious pattern detected: ${pattern.source}`);\r\n this._secureLog('warn', '\uD83D\uDEA8 Malicious pattern detected in input', {\r\n context: context,\r\n pattern: pattern.source,\r\n dataLength: data.length\r\n });\r\n return validationResult;\r\n }\r\n }\r\n\r\n // 4. Sanitize string data\r\n validationResult.sanitizedData = this._sanitizeInputString(data);\r\n validationResult.isValid = true;\r\n return validationResult;\r\n }\r\n\r\n // 5. Object validation\r\n if (typeof data === 'object') {\r\n // Check for circular references\r\n const seen = new WeakSet();\r\n const checkCircular = (obj, path = '') => {\r\n if (obj === null || typeof obj !== 'object') return;\r\n \r\n if (seen.has(obj)) {\r\n validationResult.errors.push(`Circular reference detected at path: ${path}`);\r\n return;\r\n }\r\n \r\n seen.add(obj);\r\n \r\n // Check object depth\r\n if (path.split('.').length > this._inputValidationLimits.maxObjectDepth) {\r\n validationResult.errors.push(`Object too deep: ${path.split('.').length} > ${this._inputValidationLimits.maxObjectDepth}`);\r\n return;\r\n }\r\n\r\n // Check array length\r\n if (Array.isArray(obj) && obj.length > this._inputValidationLimits.maxArrayLength) {\r\n validationResult.errors.push(`Array too long: ${obj.length} > ${this._inputValidationLimits.maxArrayLength}`);\r\n return;\r\n }\r\n\r\n // Recursively check all properties\r\n for (const key in obj) {\r\n if (obj.hasOwnProperty(key)) {\r\n checkCircular(obj[key], path ? `${path}.${key}` : key);\r\n }\r\n }\r\n };\r\n\r\n checkCircular(data);\r\n \r\n if (validationResult.errors.length > 0) {\r\n return validationResult;\r\n }\r\n\r\n // 6. Check total object size\r\n const objectSize = this._calculateObjectSize(data);\r\n if (objectSize > this._inputValidationLimits.maxMessageSize) {\r\n validationResult.errors.push(`Object too large: ${objectSize} bytes > ${this._inputValidationLimits.maxMessageSize} bytes`);\r\n return validationResult;\r\n }\r\n\r\n // 7. Sanitize object data\r\n validationResult.sanitizedData = this._sanitizeInputObject(data);\r\n validationResult.isValid = true;\r\n return validationResult;\r\n }\r\n\r\n // 8. ArrayBuffer validation\r\n if (data instanceof ArrayBuffer) {\r\n if (data.byteLength > this._inputValidationLimits.maxMessageSize) {\r\n validationResult.errors.push(`ArrayBuffer too large: ${data.byteLength} bytes > ${this._inputValidationLimits.maxMessageSize} bytes`);\r\n return validationResult;\r\n }\r\n \r\n validationResult.sanitizedData = data;\r\n validationResult.isValid = true;\r\n return validationResult;\r\n }\r\n\r\n // 9. Other types are not allowed\r\n validationResult.errors.push(`Unsupported data type: ${typeof data}`);\r\n return validationResult;\r\n\r\n } catch (error) {\r\n validationResult.errors.push(`Validation error: ${error.message}`);\r\n this._secureLog('error', '\u274C Input validation failed', {\r\n context: context,\r\n errorType: error?.constructor?.name || 'Unknown',\r\n message: error?.message || 'Unknown error'\r\n });\r\n return validationResult;\r\n }\r\n }\r\n\r\n /**\r\n * Calculate approximate object size in bytes\r\n * @param {any} obj - Object to calculate size for\r\n * @returns {number} Size in bytes\r\n */\r\n _calculateObjectSize(obj) {\r\n try {\r\n const jsonString = JSON.stringify(obj);\r\n return new TextEncoder().encode(jsonString).length;\r\n } catch (error) {\r\n // If JSON.stringify fails, estimate size\r\n return 1024 * 1024; // Assume 1MB to be safe\r\n }\r\n }\r\n\r\n /**\r\n * Sanitize string data for input validation\r\n * @param {string} str - String to sanitize\r\n * @returns {string} Sanitized string\r\n */\r\n _sanitizeInputString(str) {\r\n if (typeof str !== 'string') return str;\r\n \r\n // Remove null bytes\r\n str = str.replace(/\\0/g, '');\r\n \r\n // Normalize whitespace\r\n str = str.replace(/\\s+/g, ' ');\r\n \r\n // Trim\r\n str = str.trim();\r\n \r\n return str;\r\n }\r\n\r\n /**\r\n * Sanitize object data for input validation\r\n * @param {any} obj - Object to sanitize\r\n * @returns {any} Sanitized object\r\n */\r\n _sanitizeInputObject(obj) {\r\n if (obj === null || typeof obj !== 'object') return obj;\r\n \r\n if (Array.isArray(obj)) {\r\n return obj.map(item => this._sanitizeInputObject(item));\r\n }\r\n \r\n const sanitized = {};\r\n for (const key in obj) {\r\n if (obj.hasOwnProperty(key)) {\r\n const value = obj[key];\r\n if (typeof value === 'string') {\r\n sanitized[key] = this._sanitizeInputString(value);\r\n } else if (typeof value === 'object') {\r\n sanitized[key] = this._sanitizeInputObject(value);\r\n } else {\r\n sanitized[key] = value;\r\n }\r\n }\r\n }\r\n \r\n return sanitized;\r\n }\r\n\r\n /**\r\n * Rate limiting for message sending\r\n * @param {string} context - Context for rate limiting\r\n * @returns {boolean} true if rate limit allows\r\n */\r\n _checkRateLimit(context = 'message') {\r\n const now = Date.now();\r\n \r\n // Initialize rate limiter if not exists\r\n if (!this._rateLimiter) {\r\n this._rateLimiter = {\r\n messageCount: 0,\r\n lastReset: now,\r\n burstCount: 0,\r\n lastBurstReset: now\r\n };\r\n }\r\n \r\n // Reset counters if needed\r\n if (now - this._rateLimiter.lastReset > 60000) { // 1 minute\r\n this._rateLimiter.messageCount = 0;\r\n this._rateLimiter.lastReset = now;\r\n }\r\n \r\n if (now - this._rateLimiter.lastBurstReset > 1000) { // 1 second\r\n this._rateLimiter.burstCount = 0;\r\n this._rateLimiter.lastBurstReset = now;\r\n }\r\n \r\n // Check burst limit\r\n if (this._rateLimiter.burstCount >= this._inputValidationLimits.rateLimitBurstSize) {\r\n this._secureLog('warn', '\u26A0\uFE0F Rate limit burst exceeded', { context });\r\n return false;\r\n }\r\n \r\n // Check overall rate limit\r\n if (this._rateLimiter.messageCount >= this._inputValidationLimits.rateLimitMessagesPerMinute) {\r\n this._secureLog('warn', '\u26A0\uFE0F Rate limit exceeded', { context });\r\n return false;\r\n }\r\n \r\n // Increment counters\r\n this._rateLimiter.messageCount++;\r\n this._rateLimiter.burstCount++;\r\n \r\n return true;\r\n }\r\n\r\n // ============================================\r\n // SECURE KEY STORAGE MANAGEMENT\r\n // ============================================\r\n\r\n /**\r\n * Initializes the secure key storage\r\n */\r\n _initializeSecureKeyStorage() {\r\n // Initialize master key manager\r\n this._masterKeyManager = new SecureMasterKeyManager();\r\n \r\n // Initialize with the new class and pass master key manager\r\n this._secureKeyStorage = new SecureKeyStorage(this._masterKeyManager);\r\n \r\n // Keep the stats structure for compatibility\r\n this._keyStorageStats = {\r\n totalKeys: 0,\r\n activeKeys: 0,\r\n lastAccess: null,\r\n lastRotation: null,\r\n };\r\n \r\n this._secureLog('info', '\uD83D\uDD10 Enhanced secure key storage initialized');\r\n }\r\n \r\n /**\r\n * Set password callback for master key\r\n */\r\n setMasterKeyPasswordCallback(callback) {\r\n if (this._masterKeyManager) {\r\n this._masterKeyManager.setPasswordRequiredCallback(callback);\r\n }\r\n }\r\n \r\n /**\r\n * Set session expired callback for master key\r\n */\r\n setMasterKeySessionExpiredCallback(callback) {\r\n if (this._masterKeyManager) {\r\n this._masterKeyManager.setSessionExpiredCallback(callback);\r\n }\r\n }\r\n \r\n /**\r\n * Lock master key manually\r\n */\r\n lockMasterKey() {\r\n if (this._masterKeyManager) {\r\n this._masterKeyManager.lock();\r\n }\r\n }\r\n \r\n /**\r\n * Check if master key is unlocked\r\n */\r\n isMasterKeyUnlocked() {\r\n return this._masterKeyManager ? this._masterKeyManager.isUnlocked() : false;\r\n }\r\n \r\n /**\r\n * Get master key session status\r\n */\r\n getMasterKeySessionStatus() {\r\n return this._masterKeyManager ? this._masterKeyManager.getSessionStatus() : null;\r\n }\r\n\r\n // Helper: ensure file transfer system is ready (lazy init on receiver)\r\n async _ensureFileTransferReady() {\r\n try {\r\n // If already initialized \u2014 done\r\n if (this.fileTransferSystem) {\r\n return true;\r\n }\r\n // Requires an open data channel and a verified connection\r\n if (!this.dataChannel || this.dataChannel.readyState !== 'open') {\r\n throw new Error('Data channel not open');\r\n }\r\n if (!this.isVerified) {\r\n throw new Error('Connection not verified');\r\n }\r\n // Initialization\r\n this.initializeFileTransfer();\r\n \r\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\r\n let attempts = 0;\r\n const maxAttempts = 50; // 5 \u0441\u0435\u043A\u0443\u043D\u0434 \u043C\u0430\u043A\u0441\u0438\u043C\u0443\u043C\r\n while (!this.fileTransferSystem && attempts < maxAttempts) {\r\n await new Promise(r => setTimeout(r, 100));\r\n attempts++;\r\n }\r\n \r\n if (!this.fileTransferSystem) {\r\n throw new Error('File transfer system initialization timeout');\r\n }\r\n \r\n return true;\r\n } catch (e) {\r\n this._secureLog('error', '\u274C _ensureFileTransferReady failed', { \r\n errorType: e?.constructor?.name || 'Unknown',\r\n hasMessage: !!e?.message \r\n });\r\n return false;\r\n }\r\n }\r\n\r\n _getSecureKey(keyId) {\r\n return this._secureKeyStorage.retrieveKey(keyId);\r\n }\r\n\r\n async _setSecureKey(keyId, key) {\r\n if (!(key instanceof CryptoKey)) {\r\n this._secureLog('error', '\u274C Attempt to store non-CryptoKey');\r\n return false;\r\n }\r\n \r\n const success = await this._secureKeyStorage.storeKey(keyId, key, {\r\n version: this.currentKeyVersion,\r\n type: key.algorithm.name\r\n });\r\n \r\n if (success) {\r\n this._secureLog('info', `\uD83D\uDD11 Key ${keyId} stored securely with encryption`);\r\n }\r\n \r\n return success;\r\n }\r\n\r\n /**\r\n * Validates a key value\r\n * @param {CryptoKey} key - Key to validate\r\n * @returns {boolean} true if the key is valid\r\n */\r\n _validateKeyValue(key) {\r\n return key instanceof CryptoKey &&\r\n key.algorithm &&\r\n key.usages &&\r\n key.usages.length > 0;\r\n }\r\n\r\n _secureWipeKeys() {\r\n this._secureKeyStorage.secureWipeAll();\r\n \r\n // Also lock the master key\r\n if (this._masterKeyManager) {\r\n this._masterKeyManager.lock();\r\n }\r\n \r\n this._secureLog('info', '\uD83E\uDDF9 All keys securely wiped and encrypted storage cleared');\r\n }\r\n\r\n /**\r\n * Validates key storage state\r\n * @returns {boolean} true if the storage is ready\r\n */\r\n _validateKeyStorage() {\r\n return this._secureKeyStorage instanceof SecureKeyStorage;\r\n }\r\n\r\n /**\r\n * Returns secure key storage statistics\r\n * @returns {object} Storage metrics\r\n */\r\n _getKeyStorageStats() {\r\n const stats = this._secureKeyStorage.getStorageStats();\r\n return {\r\n totalKeysCount: stats.totalKeys,\r\n activeKeysCount: stats.totalKeys,\r\n hasLastAccess: stats.metadata.some(m => m.lastAccessed),\r\n hasLastRotation: !!this._keyStorageStats.lastRotation,\r\n storageType: 'SecureKeyStorage',\r\n timestamp: Date.now()\r\n };\r\n }\r\n\r\n /**\r\n * Performs key rotation in storage\r\n */\r\n _rotateKeys() {\r\n const oldKeys = Array.from(this._secureKeyStorage.keys());\r\n this._secureKeyStorage.clear();\r\n this._keyStorageStats.lastRotation = Date.now();\r\n this._keyStorageStats.activeKeys = 0;\r\n this._secureLog('info', `\uD83D\uDD04 Key rotation completed. ${oldKeys.length} keys rotated`);\r\n }\r\n\r\n /**\r\n * Emergency key wipe (e.g., upon detecting a threat)\r\n */\r\n _emergencyKeyWipe() {\r\n this._secureWipeKeys();\r\n this._secureLog('error', '\uD83D\uDEA8 EMERGENCY: All keys wiped due to security threat');\r\n }\r\n\r\n /**\r\n * Starts key security monitoring\r\n * @deprecated Use unified scheduler instead\r\n */\r\n _startKeySecurityMonitoring() {\r\n // Functionality moved to unified scheduler\r\n this._secureLog('info', '\uD83D\uDD27 Key security monitoring moved to unified scheduler');\r\n }\r\n\r\n\r\n // ============================================\r\n // HELPER METHODS\r\n // ============================================\r\n /**\r\n * Constant-time key validation to prevent timing attacks\r\n * @param {CryptoKey} key - Key to validate\r\n * @returns {boolean} true if key is valid\r\n */\r\n _validateKeyConstantTime(key) {\r\n // Constant-time validation to prevent timing attacks\r\n let isValid = 0;\r\n \r\n // Check if key is CryptoKey instance (constant-time)\r\n try {\r\n const isCryptoKey = key instanceof CryptoKey;\r\n isValid += isCryptoKey ? 1 : 0;\r\n } catch {\r\n isValid += 0;\r\n }\r\n \r\n // Check algorithm (constant-time)\r\n try {\r\n const hasAlgorithm = !!(key && key.algorithm);\r\n isValid += hasAlgorithm ? 1 : 0;\r\n } catch {\r\n isValid += 0;\r\n }\r\n \r\n // Check type (constant-time)\r\n try {\r\n const hasType = !!(key && key.type);\r\n isValid += hasType ? 1 : 0;\r\n } catch {\r\n isValid += 0;\r\n }\r\n \r\n // Check extractable property (constant-time)\r\n try {\r\n const hasExtractable = key && key.extractable !== undefined;\r\n isValid += hasExtractable ? 1 : 0;\r\n } catch {\r\n isValid += 0;\r\n }\r\n \r\n // All checks must pass\r\n return isValid === 4;\r\n }\r\n\r\n /**\r\n * Constant-time key pair validation\r\n * @param {Object} keyPair - Key pair to validate\r\n * @returns {boolean} true if key pair is valid\r\n */\r\n _validateKeyPairConstantTime(keyPair) {\r\n if (!keyPair || typeof keyPair !== 'object') return false;\r\n \r\n const privateKeyValid = this._validateKeyConstantTime(keyPair.privateKey);\r\n const publicKeyValid = this._validateKeyConstantTime(keyPair.publicKey);\r\n \r\n // Constant-time AND operation\r\n return privateKeyValid && publicKeyValid;\r\n }\r\n\r\n /**\r\n * Enhanced secure logging system initialization\r\n */\r\n _initializeSecureLogging() {\r\n // Logging levels\r\n this._logLevels = {\r\n error: 0,\r\n warn: 1, \r\n info: 2,\r\n debug: 3,\r\n trace: 4\r\n };\r\n \r\n // Ultra-strict levels for production\r\n this._currentLogLevel = this._isProductionMode ? \r\n this._logLevels.error : // In production, ONLY critical errors\r\n this._logLevels.info; // In development, up to info\r\n \r\n // Reduced log limits to prevent data accumulation\r\n this._logCounts = new Map();\r\n this._maxLogCount = this._isProductionMode ? 5 : 50; // Reduced limits\r\n \r\n // Hard resource limits to prevent memory leaks\r\n this._resourceLimits = {\r\n maxLogEntries: this._isProductionMode ? 100 : 1000,\r\n maxMessageQueue: 1000,\r\n maxIVHistory: 10000,\r\n maxProcessedMessageIds: 5000,\r\n maxDecoyChannels: 100,\r\n maxFakeTrafficMessages: 500,\r\n maxChunkQueue: 200,\r\n maxPacketBuffer: 1000\r\n };\r\n \r\n // Emergency cleanup thresholds\r\n this._emergencyThresholds = {\r\n logEntries: this._resourceLimits.maxLogEntries * 0.8, // 80%\r\n messageQueue: this._resourceLimits.maxMessageQueue * 0.8,\r\n ivHistory: this._resourceLimits.maxIVHistory * 0.8,\r\n processedMessageIds: this._resourceLimits.maxProcessedMessageIds * 0.8\r\n };\r\n \r\n // Input validation limits to prevent DoS attacks\r\n this._inputValidationLimits = {\r\n maxStringLength: 100000, // 100KB for strings\r\n maxObjectDepth: 10, // Maximum object nesting depth\r\n maxArrayLength: 1000, // Maximum array length\r\n maxMessageSize: 1024 * 1024, // 1MB total message size\r\n maxConcurrentMessages: 10, // Maximum concurrent message processing\r\n rateLimitMessagesPerMinute: 60, // Rate limiting\r\n rateLimitBurstSize: 10 // Burst size for rate limiting\r\n };\r\n \r\n // Malicious pattern detection\r\n this._maliciousPatterns = [\r\n // Enhanced script tag detection that handles edge cases\r\n /]*>[\\s\\S]*?<\\/script\\s*>/gi, // Standard \r\n /]*>[\\s\\S]*?<\\/script\\s+[^>]*>/gi, // \r\n /]*>[\\s\\S]*$/gi, // Malformed script tags without closing\r\n // Additional dangerous tags\r\n /]*>[\\s\\S]*?<\\/iframe\\s*>/gi, // iframe tags\r\n /]*>[\\s\\S]*?<\\/object\\s*>/gi, // object tags\r\n /]*>/gi, // embed tags\r\n /]*>[\\s\\S]*?<\\/applet\\s*>/gi, // applet tags\r\n /]*>[\\s\\S]*?<\\/style\\s*>/gi, // style tags\r\n // Dangerous protocols\r\n /javascript\\s*:/gi, // JavaScript protocol\r\n /data\\s*:/gi, // Data protocol\r\n /vbscript\\s*:/gi, // VBScript protocol\r\n /data:text\\/html/gi, // Data URLs with HTML\r\n /on\\w+\\s*=/gi, // Event handlers\r\n /eval\\s*\\(/gi, // eval() calls\r\n /document\\./gi, // Document object access\r\n /window\\./gi, // Window object access\r\n /localStorage/gi, // LocalStorage access\r\n /sessionStorage/gi, // SessionStorage access\r\n /fetch\\s*\\(/gi, // Fetch API calls\r\n /XMLHttpRequest/gi, // XHR calls\r\n /import\\s*\\(/gi, // Dynamic imports\r\n /require\\s*\\(/gi, // Require calls\r\n /process\\./gi, // Process object access\r\n /global/gi, // Global object access\r\n /__proto__/gi, // Prototype pollution\r\n /constructor/gi, // Constructor access\r\n /prototype/gi, // Prototype access\r\n /toString\\s*\\(/gi, // toString calls\r\n /valueOf\\s*\\(/gi // valueOf calls\r\n ];\r\n\r\n // Comprehensive blacklist with all sensitive patterns\r\n this._absoluteBlacklist = new Set([\r\n // Cryptographic keys\r\n 'encryptionKey', 'macKey', 'metadataKey', 'privateKey', 'publicKey',\r\n 'ecdhKeyPair', 'ecdsaKeyPair', 'peerPublicKey', 'nestedEncryptionKey',\r\n \r\n // Authentication and session data\r\n 'verificationCode', 'sessionSalt', 'keyFingerprint', 'sessionId',\r\n 'authChallenge', 'authProof', 'authToken', 'sessionToken',\r\n \r\n // Credentials and secrets\r\n 'password', 'token', 'secret', 'credential', 'signature',\r\n 'apiKey', 'accessKey', 'secretKey', 'privateKey',\r\n \r\n // Cryptographic materials\r\n 'hash', 'digest', 'nonce', 'iv', 'cipher', 'seed',\r\n 'entropy', 'random', 'salt', 'fingerprint',\r\n \r\n // JWT and session data\r\n 'jwt', 'bearer', 'refreshToken', 'accessToken',\r\n \r\n // File transfer sensitive data\r\n 'fileHash', 'fileSignature', 'transferKey', 'chunkKey'\r\n ]);\r\n\r\n // Minimal whitelist with strict validation\r\n this._safeFieldsWhitelist = new Set([\r\n // Basic status fields\r\n 'timestamp', 'type', 'status', 'state', 'level',\r\n 'isConnected', 'isVerified', 'isInitiator', 'version',\r\n \r\n // Counters and metrics (safe)\r\n 'count', 'total', 'active', 'inactive', 'success', 'failure',\r\n \r\n // Connection states (safe)\r\n 'readyState', 'connectionState', 'iceConnectionState',\r\n \r\n // Feature counts (safe)\r\n 'activeFeaturesCount', 'totalFeatures', 'stage',\r\n \r\n // Error types (safe)\r\n 'errorType', 'errorCode', 'phase', 'attempt'\r\n ]);\r\n \r\n // Initialize security monitoring\r\n this._initializeLogSecurityMonitoring();\r\n \r\n this._secureLog('info', `\uD83D\uDD27 Enhanced secure logging initialized (Production: ${this._isProductionMode})`);\r\n }\r\n\r\n /**\r\n * Initialize security monitoring for logging system\r\n */\r\n _initializeLogSecurityMonitoring() {\r\n // Security monitoring moved to unified scheduler\r\n this._logSecurityViolations = 0;\r\n this._maxLogSecurityViolations = 3;\r\n }\r\n\r\n /**\r\n * Audit logging system security\r\n */\r\n _auditLoggingSystemSecurity() {\r\n let violations = 0;\r\n \r\n // Check for excessive log counts (potential data leakage)\r\n for (const [key, count] of this._logCounts.entries()) {\r\n if (count > this._maxLogCount * 2) {\r\n violations++;\r\n this._originalConsole?.error?.(`\uD83D\uDEA8 LOG SECURITY: Excessive log count detected: ${key}`);\r\n }\r\n }\r\n \r\n // Check for blacklisted patterns in recent logs\r\n const recentLogs = Array.from(this._logCounts.keys());\r\n for (const logKey of recentLogs) {\r\n if (this._containsSensitiveContent(logKey)) {\r\n violations++;\r\n this._originalConsole?.error?.(`\uD83D\uDEA8 LOG SECURITY: Sensitive content in log key: ${logKey}`);\r\n }\r\n }\r\n \r\n // Emergency shutdown if too many violations\r\n this._logSecurityViolations += violations;\r\n if (this._logSecurityViolations >= this._maxLogSecurityViolations) {\r\n this._emergencyDisableLogging();\r\n this._originalConsole?.error?.('\uD83D\uDEA8 CRITICAL: Logging system disabled due to security violations');\r\n }\r\n }\r\n\r\n _secureLogShim(...args) {\r\n try {\r\n // Validate arguments array\r\n if (!Array.isArray(args) || args.length === 0) {\r\n return;\r\n }\r\n \r\n // Proper destructuring with fallback\r\n const message = args[0];\r\n const restArgs = args.slice(1);\r\n \r\n // Handle different argument patterns\r\n if (restArgs.length === 0) {\r\n this._secureLog('info', String(message || ''));\r\n return;\r\n }\r\n \r\n if (restArgs.length === 1) {\r\n this._secureLog('info', String(message || ''), restArgs[0]);\r\n return;\r\n }\r\n \r\n // Proper object structure for multiple args\r\n this._secureLog('info', String(message || ''), { \r\n additionalArgs: restArgs,\r\n argCount: restArgs.length \r\n });\r\n } catch (error) {\r\n // Better error handling - fallback to original console if available\r\n try {\r\n if (this._originalConsole?.log) {\r\n this._originalConsole.log(...args);\r\n }\r\n } catch (fallbackError) {\r\n // Silent failure to prevent execution disruption\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Setup own logger without touching global console\r\n */\r\n _setupOwnLogger() {\r\n // Create own logger without touching global console\r\n this.logger = {\r\n log: (message, data) => this._secureLog('info', message, data),\r\n info: (message, data) => this._secureLog('info', message, data),\r\n warn: (message, data) => this._secureLog('warn', message, data),\r\n error: (message, data) => this._secureLog('error', message, data),\r\n debug: (message, data) => this._secureLog('debug', message, data)\r\n };\r\n \r\n // In development, log to console; in production, use secure logging only\r\n if (EnhancedSecureWebRTCManager.DEBUG_MODE) {\r\n this._secureLog('info', '\uD83D\uDD12 Own logger created - development mode');\r\n } else {\r\n this._secureLog('info', '\uD83D\uDD12 Own logger created - production mode');\r\n }\r\n }\r\n /**\r\n * Production logging - use own logger with minimal output\r\n */\r\n _setupProductionLogging() {\r\n // In production, own logger becomes minimal\r\n if (this._isProductionMode) {\r\n this.logger = {\r\n log: () => {}, // No-op in production\r\n info: () => {}, // No-op in production\r\n warn: (message, data) => this._secureLog('warn', message, data),\r\n error: (message, data) => this._secureLog('error', message, data),\r\n debug: () => {} // No-op in production\r\n };\r\n \r\n this._secureLog('info', 'Production logging mode activated');\r\n }\r\n }\r\n /**\r\n * Secure logging with enhanced data protection\r\n * @param {string} level - Log level (error, warn, info, debug, trace)\r\n * @param {string} message - Message\r\n * @param {object} data - Optional payload (will be sanitized)\r\n */\r\n _secureLog(level, message, data = null) {\r\n // Pre-sanitization audit to prevent data leakage\r\n if (data && !this._auditLogMessage(message, data)) {\r\n // Log the attempt but block the actual data\r\n this._originalConsole?.error?.('SECURITY: Logging blocked due to potential data leakage');\r\n return;\r\n }\r\n \r\n // Check log level\r\n if (this._logLevels[level] > this._currentLogLevel) {\r\n return;\r\n }\r\n \r\n // Prevent log spam with better key generation\r\n const logKey = `${level}:${message.substring(0, 50)}`;\r\n const currentCount = this._logCounts.get(logKey) || 0;\r\n \r\n if (currentCount >= this._maxLogCount) {\r\n return;\r\n }\r\n \r\n this._logCounts.set(logKey, currentCount + 1);\r\n \r\n // Enhanced sanitization with multiple passes\r\n let sanitizedData = null;\r\n if (data) {\r\n // First pass: basic sanitization\r\n sanitizedData = this._sanitizeLogData(data);\r\n \r\n // Second pass: check if sanitized data still contains sensitive content\r\n if (this._containsSensitiveContent(JSON.stringify(sanitizedData))) {\r\n this._originalConsole?.error?.('ECURITY: Sanitized data still contains sensitive content - blocking log');\r\n return;\r\n }\r\n }\r\n \r\n // Production mode security - only log essential errors\r\n if (this._isProductionMode) {\r\n if (level === 'error') {\r\n // In production, only log error messages without sensitive data\r\n const safeMessage = this._sanitizeString(message);\r\n this._originalConsole?.error?.(safeMessage);\r\n }\r\n // Block all other log levels in production\r\n return;\r\n }\r\n \r\n // Development mode: full logging with sanitized data\r\n const logMethod = this._originalConsole?.[level] || this._originalConsole?.log;\r\n if (sanitizedData) {\r\n logMethod(message, sanitizedData);\r\n } else {\r\n logMethod(message);\r\n }\r\n }\r\n /**\r\n * Enhanced sanitization for log data with multiple security layers\r\n */\r\n _sanitizeLogData(data) {\r\n // Pre-check for sensitive content before processing\r\n if (typeof data === 'string') {\r\n return this._sanitizeString(data);\r\n }\r\n \r\n if (!data || typeof data !== 'object') {\r\n return data;\r\n }\r\n \r\n const sanitized = {};\r\n \r\n for (const [key, value] of Object.entries(data)) {\r\n const lowerKey = key.toLowerCase();\r\n \r\n // Enhanced blacklist with more comprehensive patterns\r\n const blacklistPatterns = [\r\n 'key', 'secret', 'token', 'password', 'credential', 'auth',\r\n 'fingerprint', 'salt', 'signature', 'private', 'encryption',\r\n 'mac', 'metadata', 'session', 'jwt', 'bearer', 'hash',\r\n 'digest', 'nonce', 'iv', 'cipher', 'seed', 'entropy'\r\n ];\r\n \r\n const isBlacklisted = this._absoluteBlacklist.has(key) || \r\n blacklistPatterns.some(pattern => lowerKey.includes(pattern));\r\n \r\n if (isBlacklisted) {\r\n sanitized[key] = '[SENSITIVE_DATA_BLOCKED]';\r\n continue;\r\n }\r\n \r\n // Enhanced whitelist with strict validation\r\n if (this._safeFieldsWhitelist.has(key)) {\r\n // Even whitelisted fields get sanitized if they contain sensitive data\r\n if (typeof value === 'string') {\r\n sanitized[key] = this._sanitizeString(value);\r\n } else {\r\n sanitized[key] = value;\r\n }\r\n continue;\r\n }\r\n \r\n // Enhanced type handling with security checks\r\n if (typeof value === 'boolean' || typeof value === 'number') {\r\n sanitized[key] = value;\r\n } else if (typeof value === 'string') {\r\n sanitized[key] = this._sanitizeString(value);\r\n } else if (value instanceof ArrayBuffer || value instanceof Uint8Array) {\r\n // Don't reveal actual byte lengths for security\r\n sanitized[key] = `[${value.constructor.name}( bytes)]`;\r\n } else if (value && typeof value === 'object') {\r\n // Recursive sanitization with depth limit and security check\r\n try {\r\n sanitized[key] = this._sanitizeLogData(value);\r\n } catch (error) {\r\n sanitized[key] = '[RECURSIVE_SANITIZATION_FAILED]';\r\n }\r\n } else {\r\n sanitized[key] = `[${typeof value}]`;\r\n }\r\n }\r\n \r\n // Final security check on sanitized data\r\n const sanitizedString = JSON.stringify(sanitized);\r\n if (this._containsSensitiveContent(sanitizedString)) {\r\n return { error: 'SANITIZATION_FAILED_SENSITIVE_CONTENT_DETECTED' };\r\n }\r\n \r\n return sanitized;\r\n }\r\n /**\r\n * Enhanced sanitization for strings with comprehensive pattern detection\r\n */\r\n _sanitizeString(str) {\r\n if (typeof str !== 'string' || str.length === 0) {\r\n return str;\r\n }\r\n \r\n // Comprehensive sensitive pattern detection\r\n const sensitivePatterns = [\r\n // Hex patterns (various lengths)\r\n /[a-f0-9]{16,}/i, // 16+ hex chars (covers short keys)\r\n /[a-f0-9]{8,}/i, // 8+ hex chars (covers shorter keys)\r\n \r\n // Base64 patterns (comprehensive)\r\n /[A-Za-z0-9+/]{16,}={0,2}/, // Base64 with padding\r\n /[A-Za-z0-9+/]{12,}/, // Base64 without padding\r\n /[A-Za-z0-9+/=]{10,}/, // Base64-like patterns\r\n \r\n // Base58 patterns (Bitcoin-style)\r\n /[1-9A-HJ-NP-Za-km-z]{16,}/, // Base58 strings\r\n \r\n // Base32 patterns\r\n /[A-Z2-7]{16,}={0,6}/, // Base32 with padding\r\n /[A-Z2-7]{12,}/, // Base32 without padding\r\n \r\n // Custom encoding patterns\r\n /[A-Za-z0-9\\-_]{16,}/, // URL-safe base64 variants\r\n /[A-Za-z0-9\\.\\-_]{16,}/, // JWT-like patterns\r\n \r\n // Long alphanumeric strings (potential keys)\r\n /\\b[A-Za-z0-9]{12,}\\b/, // 12+ alphanumeric chars\r\n /\\b[A-Za-z0-9]{8,}\\b/, // 8+ alphanumeric chars\r\n \r\n // PEM key patterns\r\n /BEGIN\\s+(PRIVATE|PUBLIC|RSA|DSA|EC)\\s+KEY/i,\r\n /END\\s+(PRIVATE|PUBLIC|RSA|DSA|EC)\\s+KEY/i,\r\n \r\n // JWT patterns\r\n /^[A-Za-z0-9-_]+\\.[A-Za-z0-9-_]+\\.[A-Za-z0-9-_]*$/,\r\n \r\n // API key patterns\r\n /(api[_-]?key|token|secret|password|credential)[\\s]*[:=][\\s]*[A-Za-z0-9\\-_]{8,}/i,\r\n \r\n // UUID patterns\r\n /[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/i,\r\n \r\n // Credit cards and SSN (existing patterns)\r\n /\\b\\d{4}[\\s-]?\\d{4}[\\s-]?\\d{4}[\\s-]?\\d{4}\\b/,\r\n /\\b\\d{3}-\\d{2}-\\d{4}\\b/,\r\n \r\n // Email patterns (more restrictive)\r\n /[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}/,\r\n \r\n // Crypto-specific patterns\r\n /(fingerprint|hash|digest|signature)[\\s]*[:=][\\s]*[A-Za-z0-9\\-_]{8,}/i,\r\n /(encryption|mac|metadata)[\\s]*key[\\s]*[:=][\\s]*[A-Za-z0-9\\-_]{8,}/i,\r\n \r\n // Session and auth patterns\r\n /(session|auth|jwt|bearer)[\\s]*[:=][\\s]*[A-Za-z0-9\\-_]{8,}/i,\r\n ];\r\n \r\n // Check for sensitive patterns with early return\r\n for (const pattern of sensitivePatterns) {\r\n if (pattern.test(str)) {\r\n // Always fully hide sensitive data\r\n return '[SENSITIVE_DATA_REDACTED]';\r\n }\r\n }\r\n \r\n // Check for suspicious entropy (high randomness indicates keys)\r\n if (this._hasHighEntropy(str)) {\r\n return '[HIGH_ENTROPY_DATA_REDACTED]';\r\n }\r\n \r\n // Check for suspicious character distributions\r\n if (this._hasSuspiciousDistribution(str)) {\r\n return '[SUSPICIOUS_DATA_REDACTED]';\r\n }\r\n \r\n // For regular strings \u2014 limit length more aggressively\r\n if (str.length > 50) {\r\n return str.substring(0, 20) + '...[TRUNCATED]';\r\n }\r\n \r\n return str;\r\n }\r\n /**\r\n * Enhanced sensitive content detection\r\n */\r\n _containsSensitiveContent(str) {\r\n if (typeof str !== 'string') return false;\r\n \r\n // Use the same comprehensive patterns as _sanitizeString\r\n const sensitivePatterns = [\r\n /[a-f0-9]{16,}/i,\r\n /[A-Za-z0-9+/]{16,}={0,2}/,\r\n /[1-9A-HJ-NP-Za-km-z]{16,}/,\r\n /[A-Z2-7]{16,}={0,6}/,\r\n /\\b[A-Za-z0-9]{12,}\\b/,\r\n /BEGIN\\s+(PRIVATE|PUBLIC|RSA|DSA|EC)\\s+KEY/i,\r\n /^[A-Za-z0-9-_]+\\.[A-Za-z0-9-_]+\\.[A-Za-z0-9-_]*$/,\r\n /(api[_-]?key|token|secret|password|credential)[\\s]*[:=][\\s]*[A-Za-z0-9\\-_]{8,}/i,\r\n ];\r\n \r\n return sensitivePatterns.some(pattern => pattern.test(str)) ||\r\n this._hasHighEntropy(str) ||\r\n this._hasSuspiciousDistribution(str);\r\n }\r\n\r\n /**\r\n * Check for high entropy strings (likely cryptographic keys)\r\n */\r\n _hasHighEntropy(str) {\r\n if (str.length < 8) return false;\r\n \r\n // Calculate character frequency\r\n const charCount = {};\r\n for (const char of str) {\r\n charCount[char] = (charCount[char] || 0) + 1;\r\n }\r\n \r\n // Calculate Shannon entropy\r\n const length = str.length;\r\n let entropy = 0;\r\n \r\n for (const count of Object.values(charCount)) {\r\n const probability = count / length;\r\n entropy -= probability * Math.log2(probability);\r\n }\r\n \r\n // High entropy (>4.5 bits per character) suggests cryptographic data\r\n return entropy > 4.5;\r\n }\r\n\r\n /**\r\n * Check for suspicious character distributions\r\n */\r\n _hasSuspiciousDistribution(str) {\r\n if (str.length < 8) return false;\r\n \r\n // Check for uniform distribution of hex characters\r\n const hexChars = str.match(/[a-f0-9]/gi) || [];\r\n if (hexChars.length >= str.length * 0.8) {\r\n // If 80%+ are hex chars, likely a key\r\n return true;\r\n }\r\n \r\n // Check for base64-like distribution\r\n const base64Chars = str.match(/[A-Za-z0-9+/=]/g) || [];\r\n if (base64Chars.length >= str.length * 0.9) {\r\n // If 90%+ are base64 chars, likely encoded data\r\n return true;\r\n }\r\n \r\n // Check for very low character diversity (suggests random data)\r\n const uniqueChars = new Set(str).size;\r\n const diversityRatio = uniqueChars / str.length;\r\n \r\n // If diversity is too high (>0.8) for the length, likely random data\r\n if (diversityRatio > 0.8 && str.length > 16) {\r\n return true;\r\n }\r\n \r\n return false;\r\n }\r\n\r\n\r\n // ============================================\r\n // SECURE LOGGING SYSTEM\r\n // ============================================\r\n \r\n /**\r\n * Detects production mode\r\n */\r\n _detectProductionMode() {\r\n // Check various production mode indicators\r\n return (\r\n // Standard env variables\r\n (typeof process !== 'undefined' && process.env?.NODE_ENV === 'production') ||\r\n // No debug flags\r\n (!this._debugMode) ||\r\n // Production domains\r\n (window.location.hostname && !window.location.hostname.includes('localhost') && \r\n !window.location.hostname.includes('127.0.0.1') && \r\n !window.location.hostname.includes('.local')) ||\r\n // Minified code (heuristic check)\r\n (typeof window.webpackHotUpdate === 'undefined' && !window.location.search.includes('debug'))\r\n );\r\n }\r\n // ============================================\r\n // FIXED SECURE GLOBAL API\r\n // ============================================\r\n \r\n /**\r\n * Sets up a secure global API with limited access\r\n */\r\n _setupSecureGlobalAPI() {\r\n // Log that we're starting API setup\r\n this._secureLog('info', 'Starting secure global API setup');\r\n \r\n // Create simple public API with safety checks\r\n const secureAPI = {};\r\n \r\n // Only bind methods that exist\r\n if (typeof this.sendMessage === 'function') {\r\n secureAPI.sendMessage = this.sendMessage.bind(this);\r\n }\r\n \r\n // Create simple getConnectionStatus method\r\n secureAPI.getConnectionStatus = () => ({\r\n isConnected: this.isConnected ? this.isConnected() : false,\r\n isVerified: this.isVerified || false,\r\n connectionState: this.peerConnection?.connectionState || 'disconnected'\r\n });\r\n \r\n // Create simple getSecurityStatus method\r\n secureAPI.getSecurityStatus = () => ({\r\n securityLevel: 'maximum',\r\n stage: 'initialized',\r\n activeFeaturesCount: Object.values(this.securityFeatures || {}).filter(Boolean).length\r\n });\r\n \r\n if (typeof this.sendFile === 'function') {\r\n secureAPI.sendFile = this.sendFile.bind(this);\r\n }\r\n \r\n // Create simple getFileTransferStatus method\r\n secureAPI.getFileTransferStatus = () => ({\r\n initialized: !!this.fileTransferSystem,\r\n status: 'ready',\r\n activeTransfers: 0,\r\n receivingTransfers: 0\r\n });\r\n \r\n if (typeof this.disconnect === 'function') {\r\n secureAPI.disconnect = this.disconnect.bind(this);\r\n }\r\n \r\n // Create simple API object with safety checks\r\n const safeGlobalAPI = {\r\n ...secureAPI, // Spread only existing methods\r\n getConfiguration: () => ({\r\n fakeTraffic: this._config.fakeTraffic.enabled,\r\n decoyChannels: this._config.decoyChannels.enabled,\r\n packetPadding: this._config.packetPadding.enabled,\r\n antiFingerprinting: this._config.antiFingerprinting.enabled\r\n }),\r\n emergency: {}\r\n };\r\n \r\n // Only add emergency methods that exist\r\n if (typeof this._emergencyUnlockAllMutexes === 'function') {\r\n safeGlobalAPI.emergency.unlockAllMutexes = this._emergencyUnlockAllMutexes.bind(this);\r\n }\r\n \r\n if (typeof this._emergencyRecoverMutexSystem === 'function') {\r\n safeGlobalAPI.emergency.recoverMutexSystem = this._emergencyRecoverMutexSystem.bind(this);\r\n }\r\n \r\n if (typeof this._emergencyDisableLogging === 'function') {\r\n safeGlobalAPI.emergency.disableLogging = this._emergencyDisableLogging.bind(this);\r\n }\r\n \r\n if (typeof this._resetLoggingSystem === 'function') {\r\n safeGlobalAPI.emergency.resetLogging = this._resetLoggingSystem.bind(this);\r\n }\r\n \r\n // Add file transfer system status\r\n safeGlobalAPI.getFileTransferSystemStatus = () => ({\r\n initialized: !!this.fileTransferSystem,\r\n status: 'ready',\r\n activeTransfers: 0,\r\n receivingTransfers: 0\r\n });\r\n \r\n // Log available methods for debugging\r\n this._secureLog('info', 'API methods available', {\r\n sendMessage: !!secureAPI.sendMessage,\r\n getConnectionStatus: !!secureAPI.getConnectionStatus,\r\n getSecurityStatus: !!secureAPI.getSecurityStatus,\r\n sendFile: !!secureAPI.sendFile,\r\n getFileTransferStatus: !!secureAPI.getFileTransferStatus,\r\n disconnect: !!secureAPI.disconnect,\r\n getConfiguration: !!safeGlobalAPI.getConfiguration,\r\n emergencyMethods: Object.keys(safeGlobalAPI.emergency).length\r\n });\r\n\r\n // Apply Object.freeze to prevent modification\r\n Object.freeze(safeGlobalAPI);\r\n Object.freeze(safeGlobalAPI.emergency);\r\n\r\n // Export API once without monitoring\r\n this._createProtectedGlobalAPI(safeGlobalAPI);\r\n \r\n // Setup minimal protection\r\n this._setupMinimalGlobalProtection();\r\n \r\n // Log that API setup is complete\r\n this._secureLog('info', 'Secure global API setup completed successfully');\r\n }\r\n /**\r\n * Create simple global API export\r\n */\r\n _createProtectedGlobalAPI(safeGlobalAPI) {\r\n // Log that we're creating protected global API\r\n this._secureLog('info', 'Creating protected global API');\r\n \r\n // Simple API export without proxy or monitoring\r\n if (!window.secureBitChat) {\r\n this._exportAPI(safeGlobalAPI);\r\n } else {\r\n this._secureLog('warn', '\u26A0\uFE0F Global API already exists, skipping setup');\r\n }\r\n }\r\n \r\n /**\r\n * Simple API export without monitoring\r\n */\r\n _exportAPI(apiObject) {\r\n // Log that we're exporting API\r\n this._secureLog('info', 'Exporting API to window.secureBitChat');\r\n \r\n // Check if important methods are available\r\n if (!this._importantMethods || !this._importantMethods.defineProperty) {\r\n this._secureLog('error', '\u274C Important methods not available for API export, using fallback');\r\n // Fallback to direct Object.defineProperty\r\n Object.defineProperty(window, 'secureBitChat', {\r\n value: apiObject,\r\n writable: false,\r\n configurable: false,\r\n enumerable: true\r\n });\r\n } else {\r\n // One-time export with immutable properties\r\n this._importantMethods.defineProperty(window, 'secureBitChat', {\r\n value: apiObject,\r\n writable: false,\r\n configurable: false,\r\n enumerable: true\r\n });\r\n }\r\n \r\n this._secureLog('info', '\uD83D\uDD12 Secure API exported to window.secureBitChat');\r\n }\r\n \r\n /**\r\n * Setup minimal global protection\r\n */\r\n _setupMinimalGlobalProtection() {\r\n // Simple protection without monitoring (methods already stored)\r\n this._protectGlobalAPI();\r\n \r\n this._secureLog('info', '\uD83D\uDD12 Minimal global protection activated');\r\n }\r\n \r\n /**\r\n * Store important methods in closure for local use\r\n */\r\n _storeImportantMethods() {\r\n // Store references to important methods locally\r\n this._importantMethods = {\r\n defineProperty: Object.defineProperty,\r\n getOwnPropertyDescriptor: Object.getOwnPropertyDescriptor,\r\n freeze: Object.freeze,\r\n consoleLog: console.log,\r\n consoleError: console.error,\r\n consoleWarn: console.warn\r\n };\r\n \r\n this._secureLog('info', '\uD83D\uDD12 Important methods stored locally', {\r\n defineProperty: !!this._importantMethods.defineProperty,\r\n getOwnPropertyDescriptor: !!this._importantMethods.getOwnPropertyDescriptor,\r\n freeze: !!this._importantMethods.freeze\r\n });\r\n }\r\n\r\n /**\r\n * Simple protection without monitoring\r\n */\r\n _setupSimpleProtection() {\r\n this._secureLog('info', '\uD83D\uDD12 Simple protection activated - no monitoring');\r\n }\r\n\r\n /**\r\n * No global exposure prevention needed\r\n */\r\n _preventGlobalExposure() {\r\n this._secureLog('info', '\uD83D\uDD12 No global exposure prevention - using secure API export only');\r\n }\r\n /**\r\n * API integrity check - only at initialization\r\n */\r\n _verifyAPIIntegrity() {\r\n try {\r\n if (!window.secureBitChat) {\r\n this._secureLog('error', '\u274C SECURITY ALERT: Secure API has been removed!');\r\n return false;\r\n }\r\n \r\n const requiredMethods = ['sendMessage', 'getConnectionStatus', 'disconnect'];\r\n const missingMethods = requiredMethods.filter(method => \r\n typeof window.secureBitChat[method] !== 'function'\r\n );\r\n \r\n if (missingMethods.length > 0) {\r\n this._secureLog('error', '\u274C SECURITY ALERT: API tampering detected, missing methods:', { errorType: missingMethods?.constructor?.name || 'Unknown' });\r\n return false;\r\n }\r\n \r\n return true;\r\n } catch (error) {\r\n this._secureLog('error', '\u274C SECURITY ALERT: API integrity check failed:', { errorType: error?.constructor?.name || 'Unknown' });\r\n return false;\r\n }\r\n }\r\n // ============================================\r\n // ADDITIONAL SECURITY METHODS\r\n // ============================================\r\n \r\n /**\r\n * Simple global exposure check - only at initialization\r\n */\r\n _auditGlobalExposure() {\r\n // Only check once at initialization, no periodic scanning\r\n this._secureLog('info', '\uD83D\uDD12 Global exposure check completed at initialization');\r\n return [];\r\n }\r\n \r\n /**\r\n * No periodic security audits - only at initialization\r\n */\r\n _startSecurityAudit() {\r\n // Only audit once at initialization, no periodic checks\r\n this._secureLog('info', '\uD83D\uDD12 Security audit completed at initialization - no periodic monitoring');\r\n }\r\n \r\n /**\r\n * Simple global API protection\r\n */\r\n _protectGlobalAPI() {\r\n if (!window.secureBitChat) {\r\n this._secureLog('warn', '\u26A0\uFE0F Global API not found during protection setup');\r\n return;\r\n }\r\n\r\n try {\r\n // Validate API integrity once\r\n if (this._validateAPIIntegrityOnce()) {\r\n this._secureLog('info', '\uD83D\uDD12 Global API protection verified');\r\n }\r\n \r\n } catch (error) {\r\n this._secureLog('error', '\u274C Failed to verify global API protection', { \r\n errorType: error.constructor.name,\r\n errorMessage: error.message\r\n });\r\n }\r\n }\r\n \r\n /**\r\n * Validate API integrity once at initialization\r\n */\r\n _validateAPIIntegrityOnce() {\r\n try {\r\n // Check if API is properly configured\r\n if (!this._importantMethods || !this._importantMethods.getOwnPropertyDescriptor) {\r\n // Fallback to direct Object.getOwnPropertyDescriptor\r\n const descriptor = Object.getOwnPropertyDescriptor(window, 'secureBitChat');\r\n \r\n if (!descriptor || descriptor.configurable) {\r\n throw new Error('secureBitChat must not be reconfigurable!');\r\n }\r\n } else {\r\n const descriptor = this._importantMethods.getOwnPropertyDescriptor(window, 'secureBitChat');\r\n \r\n if (!descriptor || descriptor.configurable) {\r\n throw new Error('secureBitChat must not be reconfigurable!');\r\n }\r\n }\r\n \r\n this._secureLog('info', '\u2705 API integrity validated');\r\n return true;\r\n \r\n } catch (error) {\r\n this._secureLog('error', '\u274C API integrity validation failed', {\r\n errorType: error.constructor.name,\r\n errorMessage: error.message\r\n });\r\n return false;\r\n }\r\n }\r\n \r\n /**\r\n * Secure memory wipe for sensitive data\r\n */\r\n _secureWipeMemory(data, context = 'unknown') {\r\n if (!data) return;\r\n \r\n try {\r\n // Different handling for different data types\r\n if (data instanceof ArrayBuffer) {\r\n this._secureWipeArrayBuffer(data, context);\r\n } else if (data instanceof Uint8Array) {\r\n this._secureWipeUint8Array(data, context);\r\n } else if (Array.isArray(data)) {\r\n this._secureWipeArray(data, context);\r\n } else if (typeof data === 'string') {\r\n this._secureWipeString(data, context);\r\n } else if (data instanceof CryptoKey) {\r\n this._secureWipeCryptoKey(data, context);\r\n } else if (typeof data === 'object') {\r\n this._secureWipeObject(data, context);\r\n }\r\n \r\n this._secureMemoryManager.memoryStats.totalCleanups++;\r\n \r\n } catch (error) {\r\n this._secureMemoryManager.memoryStats.failedCleanups++;\r\n this._secureLog('error', '\u274C Secure memory wipe failed', {\r\n context: context,\r\n errorType: error.constructor.name,\r\n errorMessage: error.message\r\n });\r\n }\r\n }\r\n \r\n /**\r\n * Secure wipe for ArrayBuffer\r\n */\r\n _secureWipeArrayBuffer(buffer, context) {\r\n if (!buffer || buffer.byteLength === 0) return;\r\n \r\n try {\r\n const view = new Uint8Array(buffer);\r\n \r\n // Overwrite with random data first\r\n crypto.getRandomValues(view);\r\n \r\n // Overwrite with zeros\r\n view.fill(0);\r\n \r\n // Overwrite with ones\r\n view.fill(255);\r\n \r\n // Final zero overwrite\r\n view.fill(0);\r\n \r\n this._secureLog('debug', '\uD83D\uDD12 ArrayBuffer securely wiped', {\r\n context: context,\r\n size: buffer.byteLength\r\n });\r\n \r\n } catch (error) {\r\n this._secureLog('error', '\u274C Failed to wipe ArrayBuffer', {\r\n context: context,\r\n errorType: error.constructor.name\r\n });\r\n }\r\n }\r\n \r\n /**\r\n * Secure wipe for Uint8Array\r\n */\r\n _secureWipeUint8Array(array, context) {\r\n if (!array || array.length === 0) return;\r\n \r\n try {\r\n // Overwrite with random data first\r\n crypto.getRandomValues(array);\r\n \r\n // Overwrite with zeros\r\n array.fill(0);\r\n \r\n // Overwrite with ones\r\n array.fill(255);\r\n \r\n // Final zero overwrite\r\n array.fill(0);\r\n \r\n this._secureLog('debug', '\uD83D\uDD12 Uint8Array securely wiped', {\r\n context: context,\r\n size: array.length\r\n });\r\n \r\n } catch (error) {\r\n this._secureLog('error', '\u274C Failed to wipe Uint8Array', {\r\n context: context,\r\n errorType: error.constructor.name\r\n });\r\n }\r\n }\r\n \r\n /**\r\n * Secure wipe for arrays\r\n */\r\n _secureWipeArray(array, context) {\r\n if (!Array.isArray(array) || array.length === 0) return;\r\n \r\n try {\r\n // Recursively wipe each element\r\n array.forEach((item, index) => {\r\n if (item !== null && item !== undefined) {\r\n this._secureWipeMemory(item, `${context}[${index}]`);\r\n }\r\n });\r\n \r\n // Fill with nulls\r\n array.fill(null);\r\n \r\n this._secureLog('debug', '\uD83D\uDD12 Array securely wiped', {\r\n context: context,\r\n size: array.length\r\n });\r\n \r\n } catch (error) {\r\n this._secureLog('error', '\u274C Failed to wipe array', {\r\n context: context,\r\n errorType: error.constructor.name\r\n });\r\n }\r\n }\r\n \r\n /**\r\n * No string wiping - strings are immutable in JS\r\n */\r\n _secureWipeString(str, context) {\r\n // Strings are immutable in JavaScript, no need to wipe\r\n // Just remove the reference\r\n this._secureLog('debug', '\uD83D\uDD12 String reference removed (strings are immutable)', {\r\n context: context,\r\n length: str ? str.length : 0\r\n });\r\n }\r\n \r\n /**\r\n * CryptoKey cleanup - store in WeakMap for proper GC\r\n */\r\n _secureWipeCryptoKey(key, context) {\r\n if (!key || !(key instanceof CryptoKey)) return;\r\n \r\n try {\r\n // Store in WeakMap for proper garbage collection\r\n if (!this._cryptoKeyStorage) {\r\n this._cryptoKeyStorage = new WeakMap();\r\n }\r\n \r\n // Store reference for cleanup tracking\r\n this._cryptoKeyStorage.set(key, {\r\n context: context,\r\n timestamp: Date.now(),\r\n type: key.type\r\n });\r\n \r\n this._secureLog('debug', '\uD83D\uDD12 CryptoKey stored in WeakMap for cleanup', {\r\n context: context,\r\n type: key.type\r\n });\r\n \r\n } catch (error) {\r\n this._secureLog('error', '\u274C Failed to store CryptoKey for cleanup', {\r\n context: context,\r\n errorType: error.constructor.name\r\n });\r\n }\r\n }\r\n \r\n /**\r\n * Secure wipe for objects\r\n */\r\n _secureWipeObject(obj, context) {\r\n if (!obj || typeof obj !== 'object') return;\r\n \r\n try {\r\n // Recursively wipe all properties\r\n for (const [key, value] of Object.entries(obj)) {\r\n if (value !== null && value !== undefined) {\r\n this._secureWipeMemory(value, `${context}.${key}`);\r\n }\r\n // Set property to null\r\n obj[key] = null;\r\n }\r\n \r\n this._secureLog('debug', '\uD83D\uDD12 Object securely wiped', {\r\n context: context,\r\n properties: Object.keys(obj).length\r\n });\r\n \r\n } catch (error) {\r\n this._secureLog('error', '\u274C Failed to wipe object', {\r\n context: context,\r\n errorType: error.constructor.name\r\n });\r\n }\r\n }\r\n \r\n /**\r\n * Secure cleanup of cryptographic materials\r\n */\r\n _secureCleanupCryptographicMaterials() {\r\n try {\r\n // Secure wipe of key pairs\r\n if (this.ecdhKeyPair) {\r\n this._secureWipeMemory(this.ecdhKeyPair, 'ecdhKeyPair');\r\n this.ecdhKeyPair = null;\r\n }\r\n \r\n if (this.ecdsaKeyPair) {\r\n this._secureWipeMemory(this.ecdsaKeyPair, 'ecdsaKeyPair');\r\n this.ecdsaKeyPair = null;\r\n }\r\n \r\n // Secure wipe of derived keys\r\n if (this.encryptionKey) {\r\n this._secureWipeMemory(this.encryptionKey, 'encryptionKey');\r\n this.encryptionKey = null;\r\n }\r\n \r\n if (this.macKey) {\r\n this._secureWipeMemory(this.macKey, 'macKey');\r\n this.macKey = null;\r\n }\r\n \r\n if (this.metadataKey) {\r\n this._secureWipeMemory(this.metadataKey, 'metadataKey');\r\n this.metadataKey = null;\r\n }\r\n \r\n if (this.nestedEncryptionKey) {\r\n this._secureWipeMemory(this.nestedEncryptionKey, 'nestedEncryptionKey');\r\n this.nestedEncryptionKey = null;\r\n }\r\n \r\n // Secure wipe of session data\r\n if (this.sessionSalt) {\r\n this._secureWipeMemory(this.sessionSalt, 'sessionSalt');\r\n this.sessionSalt = null;\r\n }\r\n \r\n if (this.sessionId) {\r\n this._secureWipeMemory(this.sessionId, 'sessionId');\r\n this.sessionId = null;\r\n }\r\n \r\n if (this.verificationCode) {\r\n this._secureWipeMemory(this.verificationCode, 'verificationCode');\r\n this.verificationCode = null;\r\n }\r\n \r\n if (this.peerPublicKey) {\r\n this._secureWipeMemory(this.peerPublicKey, 'peerPublicKey');\r\n this.peerPublicKey = null;\r\n }\r\n \r\n if (this.keyFingerprint) {\r\n this._secureWipeMemory(this.keyFingerprint, 'keyFingerprint');\r\n this.keyFingerprint = null;\r\n }\r\n \r\n if (this.connectionId) {\r\n this._secureWipeMemory(this.connectionId, 'connectionId');\r\n this.connectionId = null;\r\n }\r\n \r\n this._secureLog('info', '\uD83D\uDD12 Cryptographic materials securely cleaned up');\r\n \r\n } catch (error) {\r\n this._secureLog('error', '\u274C Failed to cleanup cryptographic materials', {\r\n errorType: error.constructor.name,\r\n errorMessage: error.message\r\n });\r\n }\r\n }\r\n \r\n /**\r\n * Force garbage collection if available\r\n */\r\n async _forceGarbageCollection() {\r\n try {\r\n // Use natural cleanup instead of forcing GC\r\n await this._performNaturalCleanup();\r\n this._secureLog('debug', '\uD83D\uDD12 Natural memory cleanup performed');\r\n } catch (error) {\r\n this._secureLog('error', '\u274C Failed to perform natural cleanup', {\r\n errorType: error.constructor.name\r\n });\r\n }\r\n }\r\n \r\n /**\r\n * Perform periodic memory cleanup\r\n */\r\n async _performPeriodicMemoryCleanup() {\r\n try {\r\n this._secureMemoryManager.isCleaning = true;\r\n \r\n // Clean up sensitive data, but DO NOT wipe active crypto in ratchet session\r\n const shouldPreserveActiveKeys = (this.sessionMode === 'ratchet') && this.isConnected && this.dataChannel && this.dataChannel.readyState === 'open';\r\n if (shouldPreserveActiveKeys) {\r\n this._secureLog('debug', '\uD83E\uDDF9 Skipping crypto key wipe during periodic cleanup (ratchet mode, active connection)');\r\n } else {\r\n this._secureCleanupCryptographicMaterials();\r\n }\r\n \r\n // Clean up message queue if it's too large\r\n if (this.messageQueue && this.messageQueue.length > 100) {\r\n const excessMessages = this.messageQueue.splice(0, this.messageQueue.length - 50);\r\n excessMessages.forEach((message, index) => {\r\n this._secureWipeMemory(message, `periodicCleanup[${index}]`);\r\n });\r\n }\r\n \r\n // Clean up processed message IDs if too many\r\n if (this.processedMessageIds && this.processedMessageIds.size > 1000) {\r\n this.processedMessageIds.clear();\r\n }\r\n \r\n // Natural cleanup\r\n await this._forceGarbageCollection();\r\n \r\n this._secureLog('debug', '\uD83D\uDD12 Periodic memory cleanup completed');\r\n \r\n } catch (error) {\r\n this._secureLog('error', '\u274C Error during periodic memory cleanup', {\r\n errorType: error.constructor.name,\r\n errorMessage: error.message\r\n });\r\n } finally {\r\n this._secureMemoryManager.isCleaning = false;\r\n }\r\n }\r\n \r\n /**\r\n * Create secure error message without information disclosure\r\n */\r\n _createSecureErrorMessage(originalError, context = 'unknown') {\r\n try {\r\n // Categorize error for appropriate handling\r\n const category = this._categorizeError(originalError);\r\n \r\n // Generate safe error message based on category\r\n const safeMessage = this._getSafeErrorMessage(category, context);\r\n \r\n // Log detailed error internally for debugging\r\n this._secureLog('error', 'Internal error occurred', {\r\n category: category,\r\n context: context,\r\n errorType: originalError?.constructor?.name || 'Unknown',\r\n timestamp: Date.now()\r\n });\r\n \r\n // Track error frequency\r\n this._trackErrorFrequency(category);\r\n \r\n return safeMessage;\r\n \r\n } catch (error) {\r\n // Fallback to generic error if error handling fails\r\n this._secureLog('error', 'Error handling failed', {\r\n originalError: originalError?.message || 'Unknown',\r\n handlingError: error.message\r\n });\r\n return 'An unexpected error occurred';\r\n }\r\n }\r\n \r\n /**\r\n * Categorize error for appropriate handling\r\n */\r\n _categorizeError(error) {\r\n if (!error || !error.message) {\r\n return this._secureErrorHandler.errorCategories.UNKNOWN;\r\n }\r\n \r\n const message = error.message.toLowerCase();\r\n \r\n // Cryptographic errors\r\n if (message.includes('crypto') || \r\n message.includes('key') || \r\n message.includes('encrypt') || \r\n message.includes('decrypt') ||\r\n message.includes('sign') ||\r\n message.includes('verify') ||\r\n message.includes('ecdh') ||\r\n message.includes('ecdsa')) {\r\n return this._secureErrorHandler.errorCategories.CRYPTOGRAPHIC;\r\n }\r\n \r\n // Network errors\r\n if (message.includes('network') || \r\n message.includes('connection') || \r\n message.includes('timeout') ||\r\n message.includes('webrtc') ||\r\n message.includes('peer')) {\r\n return this._secureErrorHandler.errorCategories.NETWORK;\r\n }\r\n \r\n // Validation errors\r\n if (message.includes('invalid') || \r\n message.includes('validation') || \r\n message.includes('format') ||\r\n message.includes('type')) {\r\n return this._secureErrorHandler.errorCategories.VALIDATION;\r\n }\r\n \r\n // System errors\r\n if (message.includes('system') || \r\n message.includes('internal') || \r\n message.includes('memory') ||\r\n message.includes('resource')) {\r\n return this._secureErrorHandler.errorCategories.SYSTEM;\r\n }\r\n \r\n return this._secureErrorHandler.errorCategories.UNKNOWN;\r\n }\r\n \r\n /**\r\n * Get safe error message based on category\r\n */\r\n _getSafeErrorMessage(category, context) {\r\n const safeMessages = {\r\n [this._secureErrorHandler.errorCategories.CRYPTOGRAPHIC]: {\r\n 'key_generation': 'Security initialization failed',\r\n 'key_import': 'Security verification failed',\r\n 'key_derivation': 'Security setup failed',\r\n 'encryption': 'Message security failed',\r\n 'decryption': 'Message verification failed',\r\n 'signature': 'Authentication failed',\r\n 'default': 'Security operation failed'\r\n },\r\n [this._secureErrorHandler.errorCategories.NETWORK]: {\r\n 'connection': 'Connection failed',\r\n 'timeout': 'Connection timeout',\r\n 'peer': 'Peer connection failed',\r\n 'webrtc': 'Communication failed',\r\n 'default': 'Network operation failed'\r\n },\r\n [this._secureErrorHandler.errorCategories.VALIDATION]: {\r\n 'format': 'Invalid data format',\r\n 'type': 'Invalid data type',\r\n 'structure': 'Invalid data structure',\r\n 'default': 'Validation failed'\r\n },\r\n [this._secureErrorHandler.errorCategories.SYSTEM]: {\r\n 'memory': 'System resource error',\r\n 'resource': 'System resource unavailable',\r\n 'internal': 'Internal system error',\r\n 'default': 'System operation failed'\r\n },\r\n [this._secureErrorHandler.errorCategories.UNKNOWN]: {\r\n 'default': 'An unexpected error occurred'\r\n }\r\n };\r\n \r\n const categoryMessages = safeMessages[category] || safeMessages[this._secureErrorHandler.errorCategories.UNKNOWN];\r\n \r\n // Determine specific context for more precise message\r\n let specificContext = 'default';\r\n if (context.includes('key') || context.includes('crypto')) {\r\n specificContext = category === this._secureErrorHandler.errorCategories.CRYPTOGRAPHIC ? 'key_generation' : 'default';\r\n } else if (context.includes('connection') || context.includes('peer')) {\r\n specificContext = category === this._secureErrorHandler.errorCategories.NETWORK ? 'connection' : 'default';\r\n } else if (context.includes('validation') || context.includes('format')) {\r\n specificContext = category === this._secureErrorHandler.errorCategories.VALIDATION ? 'format' : 'default';\r\n }\r\n \r\n return categoryMessages[specificContext] || categoryMessages.default;\r\n }\r\n \r\n /**\r\n * Track error frequency for security monitoring\r\n */\r\n _trackErrorFrequency(category) {\r\n const now = Date.now();\r\n \r\n // Clean old error counts\r\n if (now - this._secureErrorHandler.lastErrorTime > 60000) { // 1 minute\r\n this._secureErrorHandler.errorCounts.clear();\r\n }\r\n \r\n // Increment error count\r\n const currentCount = this._secureErrorHandler.errorCounts.get(category) || 0;\r\n this._secureErrorHandler.errorCounts.set(category, currentCount + 1);\r\n this._secureErrorHandler.lastErrorTime = now;\r\n \r\n // Check if we're exceeding error threshold\r\n const totalErrors = Array.from(this._secureErrorHandler.errorCounts.values()).reduce((sum, count) => sum + count, 0);\r\n \r\n if (totalErrors > this._secureErrorHandler.errorThreshold) {\r\n this._secureErrorHandler.isInErrorMode = true;\r\n this._secureLog('warn', '\u26A0\uFE0F High error frequency detected - entering error mode', {\r\n totalErrors: totalErrors,\r\n threshold: this._secureErrorHandler.errorThreshold\r\n });\r\n }\r\n }\r\n \r\n /**\r\n * Throw secure error without information disclosure\r\n */\r\n _throwSecureError(originalError, context = 'unknown') {\r\n const secureMessage = this._createSecureErrorMessage(originalError, context);\r\n throw new Error(secureMessage);\r\n }\r\n \r\n /**\r\n * Get error handling statistics\r\n */\r\n _getErrorHandlingStats() {\r\n return {\r\n errorCounts: Object.fromEntries(this._secureErrorHandler.errorCounts),\r\n isInErrorMode: this._secureErrorHandler.isInErrorMode,\r\n lastErrorTime: this._secureErrorHandler.lastErrorTime,\r\n errorThreshold: this._secureErrorHandler.errorThreshold\r\n };\r\n }\r\n \r\n /**\r\n * Reset error handling system\r\n */\r\n _resetErrorHandlingSystem() {\r\n this._secureErrorHandler.errorCounts.clear();\r\n this._secureErrorHandler.isInErrorMode = false;\r\n this._secureErrorHandler.lastErrorTime = 0;\r\n \r\n this._secureLog('info', '\uD83D\uDD04 Error handling system reset');\r\n }\r\n \r\n /**\r\n * Get memory management statistics\r\n */\r\n _getMemoryManagementStats() {\r\n return {\r\n totalCleanups: this._secureMemoryManager.memoryStats.totalCleanups,\r\n failedCleanups: this._secureMemoryManager.memoryStats.failedCleanups,\r\n lastCleanup: this._secureMemoryManager.memoryStats.lastCleanup,\r\n isCleaning: this._secureMemoryManager.isCleaning,\r\n queueLength: this._secureMemoryManager.cleanupQueue.length\r\n };\r\n }\r\n \r\n /**\r\n * Validate API integrity and security\r\n */\r\n _validateAPIIntegrity() {\r\n try {\r\n // Check if API exists\r\n if (!window.secureBitChat) {\r\n this._secureLog('error', '\u274C Global API not found during integrity validation');\r\n return false;\r\n }\r\n \r\n // Validate required methods exist\r\n const requiredMethods = ['sendMessage', 'getConnectionStatus', 'getSecurityStatus', 'sendFile', 'disconnect'];\r\n const missingMethods = requiredMethods.filter(method => \r\n !window.secureBitChat[method] || typeof window.secureBitChat[method] !== 'function'\r\n );\r\n \r\n if (missingMethods.length > 0) {\r\n this._secureLog('error', '\u274C Global API integrity validation failed - missing methods', {\r\n missingMethods: missingMethods\r\n });\r\n return false;\r\n }\r\n \r\n // Test method binding integrity\r\n const testContext = { test: true };\r\n const boundMethods = requiredMethods.map(method => {\r\n try {\r\n return window.secureBitChat[method].bind(testContext);\r\n } catch (error) {\r\n return null;\r\n }\r\n });\r\n \r\n const unboundMethods = boundMethods.filter(method => method === null);\r\n if (unboundMethods.length > 0) {\r\n this._secureLog('error', '\u274C Global API integrity validation failed - method binding issues', {\r\n unboundMethods: unboundMethods.length\r\n });\r\n return false;\r\n }\r\n \r\n // Test API immutability\r\n try {\r\n const testProp = '_integrity_test_' + Date.now();\r\n Object.defineProperty(window.secureBitChat, testProp, {\r\n value: 'test',\r\n writable: true,\r\n configurable: true\r\n });\r\n \r\n this._secureLog('error', '\u274C Global API integrity validation failed - API is mutable');\r\n delete window.secureBitChat[testProp];\r\n return false;\r\n \r\n } catch (immutabilityError) {\r\n // This is expected - API should be immutable\r\n this._secureLog('debug', '\u2705 Global API immutability verified');\r\n }\r\n \r\n this._secureLog('info', '\u2705 Global API integrity validation passed');\r\n return true;\r\n \r\n } catch (error) {\r\n this._secureLog('error', '\u274C Global API integrity validation failed', {\r\n errorType: error.constructor.name,\r\n errorMessage: error.message\r\n });\r\n return false;\r\n }\r\n }\r\n\r\n _validateCryptographicSecurity() {\r\n // Check if basic security features are available\r\n const criticalFeatures = ['hasRateLimiting'];\r\n const missingCritical = criticalFeatures.filter(feature => !this.securityFeatures[feature]);\r\n \r\n if (missingCritical.length > 0) {\r\n this._secureLog('error', '\uD83D\uDEA8 CRITICAL: Missing critical rate limiting feature', {\r\n missing: missingCritical,\r\n currentFeatures: this.securityFeatures,\r\n action: 'Rate limiting will be forced enabled'\r\n });\r\n\r\n missingCritical.forEach(feature => {\r\n this.securityFeatures[feature] = true;\r\n this._secureLog('warn', `\u26A0\uFE0F Forced enable critical: ${feature} = true`);\r\n });\r\n }\r\n\r\n // Log current security state\r\n const availableFeatures = Object.keys(this.securityFeatures).filter(f => this.securityFeatures[f]);\r\n const encryptionFeatures = ['hasEncryption', 'hasECDH', 'hasECDSA'].filter(f => this.securityFeatures[f]);\r\n \r\n this._secureLog('info', '\u2705 Cryptographic security validation passed', {\r\n criticalFeatures: criticalFeatures.length,\r\n availableFeatures: availableFeatures.length,\r\n encryptionFeatures: encryptionFeatures.length,\r\n totalSecurityFeatures: availableFeatures.length,\r\n note: 'Encryption features will be enabled after key generation',\r\n currentState: {\r\n hasEncryption: this.securityFeatures.hasEncryption,\r\n hasECDH: this.securityFeatures.hasECDH,\r\n hasECDSA: this.securityFeatures.hasECDSA,\r\n hasRateLimiting: this.securityFeatures.hasRateLimiting\r\n }\r\n });\r\n \r\n return true;\r\n }\r\n\r\n _syncSecurityFeaturesWithTariff() {\r\n // All security features are enabled by default - no payment required\r\n this._secureLog('info', '\u2705 All security features enabled by default - no payment required');\r\n \r\n // Ensure all features are enabled\r\n const allFeatures = [\r\n 'hasEncryption', 'hasECDH', 'hasECDSA', 'hasMutualAuth',\r\n 'hasMetadataProtection', 'hasEnhancedReplayProtection',\r\n 'hasNonExtractableKeys', 'hasRateLimiting', 'hasEnhancedValidation', 'hasPFS',\r\n 'hasNestedEncryption', 'hasPacketPadding', 'hasPacketReordering',\r\n 'hasAntiFingerprinting', 'hasFakeTraffic', 'hasDecoyChannels', 'hasMessageChunking'\r\n ];\r\n \r\n allFeatures.forEach(feature => {\r\n this.securityFeatures[feature] = true;\r\n });\r\n \r\n this._secureLog('info', '\u2705 All security features enabled by default', {\r\n enabledFeatures: Object.keys(this.securityFeatures).filter(f => this.securityFeatures[f]).length,\r\n totalFeatures: Object.keys(this.securityFeatures).length\r\n });\r\n \r\n return;\r\n }\r\n \r\n /**\r\n * Emergency shutdown for critical issues\r\n */\r\n _emergencyShutdown(reason = 'Security breach') {\r\n this._secureLog('error', '\u274C EMERGENCY SHUTDOWN: ${reason}');\r\n \r\n try {\r\n // Clear critical data\r\n this.encryptionKey = null;\r\n this.macKey = null;\r\n this.metadataKey = null;\r\n this.verificationCode = null;\r\n this.keyFingerprint = null;\r\n this.connectionId = null;\r\n \r\n // Close connections\r\n if (this.dataChannel) {\r\n this.dataChannel.close();\r\n this.dataChannel = null;\r\n }\r\n if (this.peerConnection) {\r\n this.peerConnection.close();\r\n this.peerConnection = null;\r\n }\r\n \r\n // Clear buffers\r\n this.messageQueue = [];\r\n this.processedMessageIds.clear();\r\n this.packetBuffer.clear();\r\n \r\n // Notify UI\r\n if (this.onStatusChange) {\r\n this.onStatusChange('security_breach');\r\n }\r\n \r\n this._secureLog('info', '\uD83D\uDD12 Emergency shutdown completed');\r\n \r\n } catch (error) {\r\n this._secureLog('error', '\u274C Error during emergency shutdown:', { errorType: error?.constructor?.name || 'Unknown' });\r\n }\r\n }\r\n _finalizeSecureInitialization() {\r\n this._startKeySecurityMonitoring();\r\n \r\n // Verify API integrity\r\n if (!this._verifyAPIIntegrity()) {\r\n this._secureLog('error', '\u274C Security initialization failed');\r\n return;\r\n }\r\n\r\n this._startSecurityMonitoring();\r\n \r\n // Start periodic log cleanup\r\n setInterval(() => {\r\n this._cleanupLogs();\r\n }, 300000);\r\n \r\n this._secureLog('info', '\u2705 Secure WebRTC Manager initialization completed');\r\n this._secureLog('info', '\uD83D\uDD12 Global exposure protection: Monitoring only, no automatic removal');\r\n }\r\n /**\r\n * Start security monitoring\r\n * @deprecated Use unified scheduler instead\r\n */\r\n _startSecurityMonitoring() {\r\n // All security monitoring moved to unified scheduler\r\n this._secureLog('info', '\uD83D\uDD27 Security monitoring moved to unified scheduler');\r\n }\r\n /**\r\n * Validates connection readiness for sending data\r\n * @param {boolean} throwError - whether to throw on not ready\r\n * @returns {boolean} true if connection is ready\r\n */\r\n _validateConnection(throwError = true) {\r\n const isDataChannelReady = this.dataChannel && this.dataChannel.readyState === 'open';\r\n const isConnectionVerified = this.isVerified;\r\n const isValid = isDataChannelReady && isConnectionVerified;\r\n \r\n if (!isValid && throwError) {\r\n if (!isDataChannelReady) {\r\n throw new Error('Data channel not ready');\r\n }\r\n if (!isConnectionVerified) {\r\n throw new Error('Connection not verified');\r\n }\r\n }\r\n \r\n return isValid;\r\n }\r\n\r\n /**\r\n * Hard gate for traffic blocking without verification\r\n * This method enforces that NO traffic (including system messages and file transfers)\r\n * can pass through without proper cryptographic verification\r\n */\r\n _enforceVerificationGate(operation = 'unknown', throwError = true) {\r\n if (!this.isVerified) {\r\n const errorMessage = `SECURITY VIOLATION: ${operation} blocked - connection not cryptographically verified`;\r\n this._secureLog('error', errorMessage, {\r\n operation: operation,\r\n isVerified: this.isVerified,\r\n hasKeys: !!(this.encryptionKey && this.macKey),\r\n timestamp: Date.now()\r\n });\r\n \r\n if (throwError) {\r\n throw new Error(errorMessage);\r\n }\r\n return false;\r\n }\r\n return true;\r\n }\r\n\r\n /**\r\n * Safe method to set isVerified only after cryptographic verification\r\n * This is the ONLY method that should set isVerified = true\r\n */\r\n _setVerifiedStatus(verified, verificationMethod = 'unknown', verificationData = null) {\r\n if (verified) {\r\n // Validate that we have proper cryptographic verification\r\n if (!this.encryptionKey || !this.macKey) {\r\n throw new Error('Cannot set verified=true without encryption keys');\r\n }\r\n \r\n if (!verificationMethod || verificationMethod === 'unknown') {\r\n throw new Error('Cannot set verified=true without specifying verification method');\r\n }\r\n \r\n // Log the verification for audit trail\r\n this._secureLog('info', 'Connection verified through cryptographic verification', {\r\n verificationMethod: verificationMethod,\r\n hasEncryptionKey: !!this.encryptionKey,\r\n hasMacKey: !!this.macKey,\r\n keyFingerprint: this.keyFingerprint,\r\n timestamp: Date.now(),\r\n verificationData: verificationData ? 'provided' : 'none'\r\n });\r\n }\r\n \r\n this.isVerified = verified;\r\n \r\n if (verified) {\r\n this.onStatusChange('connected');\r\n } else {\r\n this.onStatusChange('disconnected');\r\n }\r\n }\r\n\r\n /**\r\n * Create AAD (Additional Authenticated Data) for file messages\r\n * This binds file messages to the current session and prevents replay attacks\r\n */\r\n _createFileMessageAAD(messageType, messageData = null) {\r\n // Verify that _createMessageAAD method is available\r\n if (typeof this._createMessageAAD !== 'function') {\r\n throw new Error('_createMessageAAD method is not available in _createFileMessageAAD. Manager may not be fully initialized.');\r\n }\r\n // Use the unified AAD creation method with file message flag\r\n return this._createMessageAAD(messageType, messageData, true);\r\n }\r\n\r\n /**\r\n * Validate AAD for file messages\r\n * This ensures file messages are bound to the correct session\r\n */\r\n _validateFileMessageAAD(aadString, expectedMessageType = null) {\r\n try {\r\n const aad = JSON.parse(aadString);\r\n \r\n // Validate session binding\r\n if (aad.sessionId !== (this.currentSession?.sessionId || 'unknown')) {\r\n throw new Error('AAD sessionId mismatch - possible replay attack');\r\n }\r\n \r\n if (aad.keyFingerprint !== (this.keyFingerprint || 'unknown')) {\r\n throw new Error('AAD keyFingerprint mismatch - possible key substitution attack');\r\n }\r\n \r\n // Validate message type if specified\r\n if (expectedMessageType && aad.messageType !== expectedMessageType) {\r\n throw new Error(`AAD messageType mismatch - expected ${expectedMessageType}, got ${aad.messageType}`);\r\n }\r\n \r\n // Validate timestamp (prevent very old messages)\r\n const now = Date.now();\r\n const messageAge = now - aad.timestamp;\r\n if (messageAge > 1800000) { // 30 minutes for better UX\r\n throw new Error('AAD timestamp too old - possible replay attack');\r\n }\r\n \r\n return aad;\r\n } catch (error) {\r\n this._secureLog('error', 'AAD validation failed', { error: error.message, aadString });\r\n throw new Error(`AAD validation failed: ${error.message}`);\r\n }\r\n }\r\n\r\n /**\r\n * Extract DTLS fingerprint from SDP\r\n * This is essential for MITM protection\r\n */\r\n _extractDTLSFingerprintFromSDP(sdp) {\r\n try {\r\n if (!sdp || typeof sdp !== 'string') {\r\n throw new Error('Invalid SDP provided');\r\n }\r\n\r\n // Look for a=fingerprint lines in SDP with more flexible regex\r\n const fingerprintRegex = /a=fingerprint:([a-zA-Z0-9-]+)\\s+([A-Fa-f0-9:]+)/g;\r\n const fingerprints = [];\r\n let match;\r\n\r\n while ((match = fingerprintRegex.exec(sdp)) !== null) {\r\n fingerprints.push({\r\n algorithm: match[1].toLowerCase(),\r\n fingerprint: match[2].toLowerCase().replace(/:/g, '')\r\n });\r\n }\r\n\r\n if (fingerprints.length === 0) {\r\n // Try alternative fingerprint format\r\n const altFingerprintRegex = /fingerprint\\s*=\\s*([a-zA-Z0-9-]+)\\s+([A-Fa-f0-9:]+)/gi;\r\n while ((match = altFingerprintRegex.exec(sdp)) !== null) {\r\n fingerprints.push({\r\n algorithm: match[1].toLowerCase(),\r\n fingerprint: match[2].toLowerCase().replace(/:/g, '')\r\n });\r\n }\r\n }\r\n\r\n if (fingerprints.length === 0) {\r\n this._secureLog('warn', 'No DTLS fingerprints found in SDP - this may be normal for some WebRTC implementations', {\r\n sdpLength: sdp.length,\r\n sdpPreview: sdp.substring(0, 200) + '...'\r\n });\r\n throw new Error('No DTLS fingerprints found in SDP');\r\n }\r\n\r\n // Prefer SHA-256 fingerprints\r\n const sha256Fingerprint = fingerprints.find(fp => fp.algorithm === 'sha-256');\r\n if (sha256Fingerprint) {\r\n return sha256Fingerprint.fingerprint;\r\n }\r\n\r\n // Fallback to first available fingerprint\r\n return fingerprints[0].fingerprint;\r\n } catch (error) {\r\n this._secureLog('error', 'Failed to extract DTLS fingerprint from SDP', { \r\n error: error.message,\r\n sdpLength: sdp?.length || 0\r\n });\r\n throw new Error(`DTLS fingerprint extraction failed: ${error.message}`);\r\n }\r\n }\r\n\r\n /**\r\n * Validate DTLS fingerprint against expected value\r\n * This prevents MITM attacks by ensuring the remote peer has the expected certificate\r\n */\r\n async _validateDTLSFingerprint(receivedFingerprint, expectedFingerprint, context = 'unknown') {\r\n try {\r\n if (!receivedFingerprint || !expectedFingerprint) {\r\n throw new Error('Missing fingerprint for validation');\r\n }\r\n\r\n // Normalize fingerprints (remove colons, convert to lowercase)\r\n const normalizedReceived = receivedFingerprint.toLowerCase().replace(/:/g, '');\r\n const normalizedExpected = expectedFingerprint.toLowerCase().replace(/:/g, '');\r\n\r\n // Ratchet mode: if fingerprint hasn't changed, treat as verified and skip warnings\r\n if (this.sessionMode === 'ratchet' && normalizedExpected === normalizedReceived) {\r\n this._secureLog('info', 'Same fingerprint detected \u2014 skip MITM warning (ratchet mode)', {\r\n context: context,\r\n timestamp: Date.now()\r\n });\r\n this.isVerified = true;\r\n return true;\r\n }\r\n\r\n if (normalizedReceived !== normalizedExpected) {\r\n this._secureLog('error', 'DTLS fingerprint mismatch - possible MITM attack', {\r\n context: context,\r\n timestamp: Date.now()\r\n });\r\n \r\n throw new Error(`DTLS fingerprint mismatch - possible MITM attack in ${context}`);\r\n }\r\n\r\n this._secureLog('info', 'DTLS fingerprint validation successful', {\r\n context: context,\r\n timestamp: Date.now()\r\n });\r\n\r\n return true;\r\n } catch (error) {\r\n this._secureLog('error', 'DTLS fingerprint validation failed', { \r\n error: error.message, \r\n context: context \r\n });\r\n throw error;\r\n }\r\n }\r\n\r\n /**\r\n * Compute SAS (Short Authentication String) for MITM protection\r\n * Uses HKDF with DTLS fingerprints to generate a stable 7-digit verification code\r\n * @param {ArrayBuffer|Uint8Array} keyMaterialRaw - Shared secret or key fingerprint data\r\n * @param {string} localFP - Local DTLS fingerprint\r\n * @param {string} remoteFP - Remote DTLS fingerprint\r\n * @returns {Promise} 7-digit SAS code\r\n */\r\n async _computeSAS(keyMaterialRaw, localFP, remoteFP) {\r\n try {\r\n \r\n if (!keyMaterialRaw || !localFP || !remoteFP) {\r\n const missing = [];\r\n if (!keyMaterialRaw) missing.push('keyMaterialRaw');\r\n if (!localFP) missing.push('localFP');\r\n if (!remoteFP) missing.push('remoteFP');\r\n throw new Error(`Missing required parameters for SAS computation: ${missing.join(', ')}`);\r\n }\r\n\r\n const enc = new TextEncoder();\r\n\r\n const salt = enc.encode(\r\n 'webrtc-sas|' + [localFP, remoteFP].sort().join('|')\r\n );\r\n\r\n let keyBuffer;\r\n if (keyMaterialRaw instanceof ArrayBuffer) {\r\n keyBuffer = keyMaterialRaw;\r\n } else if (keyMaterialRaw instanceof Uint8Array) {\r\n keyBuffer = keyMaterialRaw.buffer;\r\n } else if (typeof keyMaterialRaw === 'string') {\r\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\r\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\r\n const hexString = keyMaterialRaw.replace(/:/g, '').replace(/\\s/g, '');\r\n const bytes = new Uint8Array(hexString.length / 2);\r\n for (let i = 0; i < hexString.length; i += 2) {\r\n bytes[i / 2] = parseInt(hexString.substr(i, 2), 16);\r\n }\r\n keyBuffer = bytes.buffer;\r\n } else {\r\n throw new Error('Invalid keyMaterialRaw type');\r\n }\r\n\r\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\r\n const key = await crypto.subtle.importKey(\r\n 'raw',\r\n keyBuffer,\r\n 'HKDF',\r\n false,\r\n ['deriveBits']\r\n );\r\n\r\n const info = enc.encode('p2p-sas-v1');\r\n const bits = await crypto.subtle.deriveBits(\r\n { name: 'HKDF', hash: 'SHA-256', salt, info },\r\n key,\r\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\r\n );\r\n\r\n const dv = new DataView(bits);\r\n const n = (dv.getUint32(0) ^ dv.getUint32(4)) >>> 0;\r\n \r\n // Use rejection sampling to avoid bias in SAS code generation\r\n let sasValue;\r\n do {\r\n sasValue = crypto.getRandomValues(new Uint32Array(1))[0];\r\n } while (sasValue >= 4294967296 - (4294967296 % 10_000_000));\r\n \r\n const sasCode = String(sasValue % 10_000_000).padStart(7, '0'); \r\n\r\n\r\n this._secureLog('info', 'SAS code computed successfully', {\r\n localFP: localFP.substring(0, 16) + '...',\r\n remoteFP: remoteFP.substring(0, 16) + '...',\r\n sasLength: sasCode.length,\r\n timestamp: Date.now()\r\n });\r\n\r\n return sasCode;\r\n } catch (error) {\r\n this._secureLog('error', 'SAS computation failed', {\r\n error: error.message,\r\n keyMaterialType: typeof keyMaterialRaw,\r\n hasLocalFP: !!localFP,\r\n hasRemoteFP: !!remoteFP,\r\n timestamp: Date.now()\r\n });\r\n throw new Error(`SAS computation failed: ${error.message}`);\r\n }\r\n }\r\n\r\n /**\r\n * UTILITY: Decode hex keyFingerprint to Uint8Array for SAS computation\r\n * @param {string} hexString - Hex encoded keyFingerprint (e.g., \"aa:bb:cc:dd\")\r\n * @returns {Uint8Array} Decoded bytes\r\n */\r\n _decodeKeyFingerprint(hexString) {\r\n try {\r\n if (!hexString || typeof hexString !== 'string') {\r\n throw new Error('Invalid hex string provided');\r\n }\r\n\r\n // Use the utility from EnhancedSecureCryptoUtils\r\n return window.EnhancedSecureCryptoUtils.hexToUint8Array(hexString);\r\n } catch (error) {\r\n this._secureLog('error', 'Key fingerprint decoding failed', {\r\n error: error.message,\r\n inputType: typeof hexString,\r\n inputLength: hexString?.length || 0\r\n });\r\n throw new Error(`Key fingerprint decoding failed: ${error.message}`);\r\n }\r\n }\r\n\r\n /**\r\n * Emergency key wipe on fingerprint mismatch\r\n * This ensures no sensitive data remains if MITM is detected\r\n */\r\n _emergencyWipeOnFingerprintMismatch(reason = 'DTLS fingerprint mismatch') {\r\n try {\r\n this._secureLog('error', '\uD83D\uDEA8 EMERGENCY: Initiating security wipe due to fingerprint mismatch', {\r\n reason: reason,\r\n timestamp: Date.now()\r\n });\r\n\r\n // Wipe all cryptographic materials\r\n this._secureWipeKeys();\r\n this._secureWipeMemory(this.encryptionKey, 'emergency_wipe');\r\n this._secureWipeMemory(this.macKey, 'emergency_wipe');\r\n this._secureWipeMemory(this.metadataKey, 'emergency_wipe');\r\n \r\n // Wipe ephemeral keys for PFS\r\n this._wipeEphemeralKeys();\r\n \r\n // Hard wipe old keys for PFS\r\n this._hardWipeOldKeys();\r\n\r\n // Reset verification status\r\n this.isVerified = null;\r\n this.verificationCode = null;\r\n this.keyFingerprint = null;\r\n this.connectionId = null;\r\n this.expectedDTLSFingerprint = null;\r\n\r\n // Disconnect immediately\r\n this.disconnect();\r\n\r\n // Notify UI about security breach\r\n this.deliverMessageToUI('\uD83D\uDEA8 SECURITY BREACH: Connection terminated due to fingerprint mismatch. Possible MITM attack detected!', 'system');\r\n\r\n } catch (error) {\r\n this._secureLog('error', 'Failed to perform emergency wipe', { error: error.message });\r\n }\r\n }\r\n\r\n /**\r\n * Set expected DTLS fingerprint via out-of-band channel\r\n * This should be called after receiving the fingerprint through a secure channel\r\n * (e.g., QR code, voice call, in-person exchange, etc.)\r\n */\r\n setExpectedDTLSFingerprint(fingerprint, source = 'out_of_band') {\r\n try {\r\n if (!fingerprint || typeof fingerprint !== 'string') {\r\n throw new Error('Invalid fingerprint provided');\r\n }\r\n\r\n // Normalize fingerprint\r\n const normalizedFingerprint = fingerprint.toLowerCase().replace(/:/g, '');\r\n\r\n // Validate fingerprint format (should be hex string)\r\n if (!/^[a-f0-9]{40,64}$/.test(normalizedFingerprint)) {\r\n throw new Error('Invalid fingerprint format - must be hex string');\r\n }\r\n\r\n this.expectedDTLSFingerprint = normalizedFingerprint;\r\n\r\n this._secureLog('info', 'Expected DTLS fingerprint set via out-of-band channel', {\r\n source: source,\r\n fingerprint: normalizedFingerprint,\r\n timestamp: Date.now()\r\n });\r\n\r\n this.deliverMessageToUI(`\u2705 DTLS fingerprint set via ${source}. MITM protection enabled.`, 'system');\r\n\r\n } catch (error) {\r\n this._secureLog('error', 'Failed to set expected DTLS fingerprint', { error: error.message });\r\n throw error;\r\n }\r\n }\r\n\r\n /**\r\n * Get current DTLS fingerprint for out-of-band verification\r\n * This should be shared through a secure channel (QR code, voice, etc.)\r\n */\r\n getCurrentDTLSFingerprint() {\r\n try {\r\n if (!this.expectedDTLSFingerprint) {\r\n throw new Error('No DTLS fingerprint available - connection not established');\r\n }\r\n\r\n return this.expectedDTLSFingerprint;\r\n } catch (error) {\r\n this._secureLog('error', 'Failed to get current DTLS fingerprint', { error: error.message });\r\n throw error;\r\n }\r\n }\r\n\r\n /**\r\n * DEBUGGING: Temporarily disable strict DTLS validation\r\n * This should only be used for debugging connection issues\r\n */\r\n disableStrictDTLSValidation() {\r\n this.strictDTLSValidation = false;\r\n this._secureLog('warn', '\u26A0\uFE0F Strict DTLS validation disabled - security reduced', {\r\n timestamp: Date.now()\r\n });\r\n this.deliverMessageToUI('\u26A0\uFE0F DTLS validation disabled for debugging', 'system');\r\n }\r\n\r\n /**\r\n * SECURITY: Re-enable strict DTLS validation\r\n */\r\n enableStrictDTLSValidation() {\r\n this.strictDTLSValidation = true;\r\n this._secureLog('info', '\u2705 Strict DTLS validation re-enabled', {\r\n timestamp: Date.now()\r\n });\r\n this.deliverMessageToUI('\u2705 DTLS validation re-enabled', 'system');\r\n }\r\n\r\n /**\r\n * Generate ephemeral ECDH keys for Perfect Forward Secrecy\r\n * This ensures each session has unique, non-persistent keys\r\n */\r\n async _generateEphemeralECDHKeys() {\r\n try {\r\n this._secureLog('info', '\uD83D\uDD11 Generating ephemeral ECDH keys for PFS', {\r\n sessionStartTime: this.sessionStartTime,\r\n timestamp: Date.now()\r\n });\r\n\r\n // Generate new ephemeral ECDH key pair\r\n const ephemeralKeyPair = await window.EnhancedSecureCryptoUtils.generateECDHKeyPair();\r\n \r\n if (!ephemeralKeyPair || !this._validateKeyPairConstantTime(ephemeralKeyPair)) {\r\n throw new Error('Ephemeral ECDH key pair validation failed');\r\n }\r\n\r\n // Store ephemeral keys with session binding\r\n const sessionId = this.currentSession?.sessionId || `session_${Date.now()}`;\r\n this.ephemeralKeyPairs.set(sessionId, {\r\n keyPair: ephemeralKeyPair,\r\n timestamp: Date.now(),\r\n sessionId: sessionId\r\n });\r\n\r\n this._secureLog('info', '\u2705 Ephemeral ECDH keys generated for PFS', {\r\n timestamp: Date.now()\r\n });\r\n\r\n return ephemeralKeyPair;\r\n } catch (error) {\r\n this._secureLog('error', '\u274C Failed to generate ephemeral ECDH keys', { error: error.message });\r\n throw new Error(`Ephemeral key generation failed: ${error.message}`);\r\n }\r\n }\r\n\r\n /**\r\n * Hard wipe old keys for real PFS\r\n * This prevents retrospective decryption attacks\r\n */\r\n async _hardWipeOldKeys() {\r\n try {\r\n this._secureLog('info', '\uD83E\uDDF9 Performing hard wipe of old keys for PFS', {\r\n oldKeysCount: this.oldKeys.size,\r\n timestamp: Date.now()\r\n });\r\n\r\n // Hard wipe all old keys\r\n for (const [version, keySet] of this.oldKeys.entries()) {\r\n if (keySet.encryptionKey) {\r\n this._secureWipeMemory(keySet.encryptionKey, 'pfs_key_wipe');\r\n }\r\n if (keySet.macKey) {\r\n this._secureWipeMemory(keySet.macKey, 'pfs_key_wipe');\r\n }\r\n if (keySet.metadataKey) {\r\n this._secureWipeMemory(keySet.metadataKey, 'pfs_key_wipe');\r\n }\r\n \r\n // Clear references\r\n keySet.encryptionKey = null;\r\n keySet.macKey = null;\r\n keySet.metadataKey = null;\r\n keySet.keyFingerprint = null;\r\n }\r\n\r\n // Clear the oldKeys map completely\r\n this.oldKeys.clear();\r\n\r\n // Schedule natural cleanup\r\n await this._performNaturalCleanup();\r\n\r\n this._secureLog('info', '\u2705 Hard wipe of old keys completed for PFS', {\r\n timestamp: Date.now()\r\n });\r\n\r\n } catch (error) {\r\n this._secureLog('error', '\u274C Failed to perform hard wipe of old keys', { error: error.message });\r\n }\r\n }\r\n\r\n /**\r\n * Wipe ephemeral keys when session ends\r\n * This ensures session-specific keys are destroyed\r\n */\r\n async _wipeEphemeralKeys() {\r\n try {\r\n this._secureLog('info', '\uD83E\uDDF9 Wiping ephemeral keys for PFS', {\r\n ephemeralKeysCount: this.ephemeralKeyPairs.size,\r\n timestamp: Date.now()\r\n });\r\n\r\n // Wipe all ephemeral key pairs\r\n for (const [sessionId, keyData] of this.ephemeralKeyPairs.entries()) {\r\n if (keyData.keyPair?.privateKey) {\r\n this._secureWipeMemory(keyData.keyPair.privateKey, 'ephemeral_key_wipe');\r\n }\r\n if (keyData.keyPair?.publicKey) {\r\n this._secureWipeMemory(keyData.keyPair.publicKey, 'ephemeral_key_wipe');\r\n }\r\n \r\n // Clear references\r\n keyData.keyPair = null;\r\n keyData.timestamp = null;\r\n keyData.sessionId = null;\r\n }\r\n\r\n // Clear the ephemeral keys map\r\n this.ephemeralKeyPairs.clear();\r\n\r\n // Schedule natural cleanup\r\n await this._performNaturalCleanup();\r\n\r\n this._secureLog('info', '\u2705 Ephemeral keys wiped for PFS', {\r\n timestamp: Date.now()\r\n });\r\n\r\n } catch (error) {\r\n this._secureLog('error', '\u274C Failed to wipe ephemeral keys', { error: error.message });\r\n }\r\n }\r\n\r\n /**\r\n * Encrypt file messages with AAD\r\n * This ensures file messages are properly authenticated and bound to session\r\n */\r\n async _encryptFileMessage(messageData, aad) {\r\n try {\r\n if (!this.encryptionKey) {\r\n throw new Error('No encryption key available for file message');\r\n }\r\n\r\n // Convert message to string if it's an object\r\n const messageString = typeof messageData === 'string' ? messageData : JSON.stringify(messageData);\r\n \r\n // Encrypt with AAD using AES-GCM\r\n const encryptedData = await window.EnhancedSecureCryptoUtils.encryptDataWithAAD(\r\n messageString, \r\n this.encryptionKey, \r\n aad\r\n );\r\n \r\n // Create encrypted message wrapper\r\n const encryptedMessage = {\r\n type: 'encrypted_file_message',\r\n encryptedData: encryptedData,\r\n aad: aad,\r\n timestamp: Date.now(),\r\n keyFingerprint: this.keyFingerprint\r\n };\r\n \r\n return JSON.stringify(encryptedMessage);\r\n } catch (error) {\r\n this._secureLog('error', 'Failed to encrypt file message', { error: error.message });\r\n throw new Error(`File message encryption failed: ${error.message}`);\r\n }\r\n }\r\n\r\n /**\r\n * Decrypt file messages with AAD validation\r\n * This ensures file messages are properly authenticated and bound to session\r\n */\r\n async _decryptFileMessage(encryptedMessageString) {\r\n try {\r\n const encryptedMessage = JSON.parse(encryptedMessageString);\r\n \r\n if (encryptedMessage.type !== 'encrypted_file_message') {\r\n throw new Error('Invalid encrypted file message type');\r\n }\r\n \r\n // Validate key fingerprint\r\n if (encryptedMessage.keyFingerprint !== this.keyFingerprint) {\r\n throw new Error('Key fingerprint mismatch in encrypted file message');\r\n }\r\n \r\n // Validate AAD with sequence number\r\n const aad = this._validateMessageAAD(encryptedMessage.aad, 'file_message');\r\n \r\n if (!this.encryptionKey) {\r\n throw new Error('No encryption key available for file message decryption');\r\n }\r\n \r\n // Decrypt with AAD validation\r\n const decryptedData = await window.EnhancedSecureCryptoUtils.decryptDataWithAAD(\r\n encryptedMessage.encryptedData,\r\n this.encryptionKey,\r\n encryptedMessage.aad\r\n );\r\n \r\n return {\r\n decryptedData: decryptedData,\r\n aad: aad\r\n };\r\n } catch (error) {\r\n this._secureLog('error', 'Failed to decrypt file message', { error: error.message });\r\n throw new Error(`File message decryption failed: ${error.message}`);\r\n }\r\n }\r\n\r\n /**\r\n * Validates encryption keys readiness\r\n * @param {boolean} throwError - whether to throw on not ready\r\n * @returns {boolean} true if keys are ready\r\n */\r\n _validateEncryptionKeys(throwError = true) {\r\n const hasAllKeys = !!(this.encryptionKey && this.macKey && this.metadataKey);\r\n \r\n if (!hasAllKeys && throwError) {\r\n throw new Error('Encryption keys not initialized');\r\n }\r\n \r\n return hasAllKeys;\r\n }\r\n\r\n /**\r\n * Attempt to reinitialize encryption keys if missing\r\n * Uses existing ECDH key pair, peer public key, and session salt\r\n * Returns true if keys were (re)initialized successfully\r\n */\r\n async _tryReinitializeEncryptionKeys() {\r\n try {\r\n // If keys already present, nothing to do\r\n if (this.encryptionKey && this.macKey && this.metadataKey) {\r\n return true;\r\n }\r\n\r\n // Require ECDH materials and session salt to derive keys\r\n const hasECDH = !!(this.ecdhKeyPair?.privateKey && (this.peerPublicKey || this.peerECDHPublicKey));\r\n const peerPublicKey = this.peerPublicKey || this.peerECDHPublicKey;\r\n if (!hasECDH || !peerPublicKey || !this.sessionSalt) {\r\n return false;\r\n }\r\n\r\n // Derive fresh keys\r\n const derivedKeys = await window.EnhancedSecureCryptoUtils.deriveSharedKeys(\r\n this.ecdhKeyPair.privateKey,\r\n peerPublicKey,\r\n this.sessionSalt\r\n );\r\n\r\n await this._setEncryptionKeys(\r\n derivedKeys.messageKey,\r\n derivedKeys.macKey,\r\n derivedKeys.metadataKey,\r\n derivedKeys.fingerprint\r\n );\r\n\r\n return !!(this.encryptionKey && this.macKey && this.metadataKey);\r\n } catch (error) {\r\n this._secureLog('error', 'Failed to reinitialize encryption keys', { error: error.message });\r\n return false;\r\n }\r\n }\r\n\r\n /**\r\n * Checks whether a message is a file-transfer message\r\n * @param {string|object} data - message payload\r\n * @returns {boolean} true if it's a file message\r\n */\r\n _isFileMessage(data) {\r\n if (typeof data === 'string') {\r\n try {\r\n const parsed = JSON.parse(data);\r\n return parsed.type && parsed.type.startsWith('file_');\r\n } catch {\r\n return false;\r\n }\r\n }\r\n \r\n if (typeof data === 'object' && data.type) {\r\n return data.type.startsWith('file_');\r\n }\r\n \r\n return false;\r\n }\r\n\r\n /**\r\n * Checks whether a message is a system message\r\n * @param {string|object} data - message payload \r\n * @returns {boolean} true if it's a system message\r\n */\r\n _isSystemMessage(data) {\r\n const systemTypes = [\r\n EnhancedSecureWebRTCManager.MESSAGE_TYPES.HEARTBEAT,\r\n EnhancedSecureWebRTCManager.MESSAGE_TYPES.VERIFICATION,\r\n EnhancedSecureWebRTCManager.MESSAGE_TYPES.VERIFICATION_RESPONSE,\r\n EnhancedSecureWebRTCManager.MESSAGE_TYPES.VERIFICATION_CONFIRMED,\r\n EnhancedSecureWebRTCManager.MESSAGE_TYPES.VERIFICATION_BOTH_CONFIRMED,\r\n EnhancedSecureWebRTCManager.MESSAGE_TYPES.PEER_DISCONNECT,\r\n EnhancedSecureWebRTCManager.MESSAGE_TYPES.SECURITY_UPGRADE,\r\n EnhancedSecureWebRTCManager.MESSAGE_TYPES.KEY_ROTATION_SIGNAL,\r\n EnhancedSecureWebRTCManager.MESSAGE_TYPES.KEY_ROTATION_READY\r\n ];\r\n\r\n if (typeof data === 'string') {\r\n try {\r\n const parsed = JSON.parse(data);\r\n return systemTypes.includes(parsed.type);\r\n } catch {\r\n return false;\r\n }\r\n }\r\n \r\n if (typeof data === 'object' && data.type) {\r\n return systemTypes.includes(data.type);\r\n }\r\n \r\n return false;\r\n }\r\n\r\n /**\r\n * Checks whether a message is fake traffic\r\n * @param {any} data - message payload\r\n * @returns {boolean} true if it's a fake message\r\n */\r\n _isFakeMessage(data) {\r\n if (typeof data === 'string') {\r\n try {\r\n const parsed = JSON.parse(data);\r\n return parsed.type === EnhancedSecureWebRTCManager.MESSAGE_TYPES.FAKE || \r\n parsed.isFakeTraffic === true;\r\n } catch {\r\n return false;\r\n }\r\n }\r\n \r\n if (typeof data === 'object' && data !== null) {\r\n return data.type === EnhancedSecureWebRTCManager.MESSAGE_TYPES.FAKE || \r\n data.isFakeTraffic === true;\r\n }\r\n \r\n return false;\r\n }\r\n\r\n /**\r\n * Safely executes an operation with error handling\r\n * @param {Function} operation - operation to execute\r\n * @param {string} errorMessage - error message to log\r\n * @param {any} fallback - default value on error\r\n * @returns {any} operation result or fallback\r\n */\r\n _withErrorHandling(operation, errorMessage, fallback = null) {\r\n try {\r\n return operation();\r\n } catch (error) {\r\n if (this._debugMode) {\r\n this._secureLog('error', '\u274C ${errorMessage}:', { errorType: error?.constructor?.name || 'Unknown' });\r\n }\r\n return fallback;\r\n }\r\n }\r\n\r\n /**\r\n * Safely executes an async operation with error handling\r\n * @param {Function} operation - async operation\r\n * @param {string} errorMessage - error message to log\r\n * @param {any} fallback - default value on error\r\n * @returns {Promise} operation result or fallback\r\n */\r\n async _withAsyncErrorHandling(operation, errorMessage, fallback = null) {\r\n try {\r\n return await operation();\r\n } catch (error) {\r\n if (this._debugMode) {\r\n this._secureLog('error', '\u274C ${errorMessage}:', { errorType: error?.constructor?.name || 'Unknown' });\r\n }\r\n return fallback;\r\n }\r\n }\r\n\r\n\r\n /**\r\n * Extracts message type from data\r\n * @param {string|object} data - message data\r\n * @returns {string|null} message type or null\r\n */\r\n _getMessageType(data) {\r\n if (typeof data === 'string') {\r\n try {\r\n const parsed = JSON.parse(data);\r\n return parsed.type || null;\r\n } catch {\r\n return null;\r\n }\r\n }\r\n \r\n if (typeof data === 'object' && data !== null) {\r\n return data.type || null;\r\n }\r\n \r\n return null;\r\n }\r\n\r\n /**\r\n * Resets notification flags for a new connection\r\n */\r\n _resetNotificationFlags() {\r\n this.lastSecurityLevelNotification = null;\r\n this.verificationNotificationSent = false;\r\n this.verificationInitiationSent = false;\r\n this.disconnectNotificationSent = false;\r\n this.reconnectionFailedNotificationSent = false;\r\n this.peerDisconnectNotificationSent = false;\r\n this.connectionClosedNotificationSent = false;\r\n this.fakeTrafficDisabledNotificationSent = false;\r\n this.advancedFeaturesDisabledNotificationSent = false;\r\n this.securityUpgradeNotificationSent = false;\r\n this.lastSecurityUpgradeStage = null;\r\n this.securityCalculationNotificationSent = false;\r\n this.lastSecurityCalculationLevel = null;\r\n }\r\n\r\n /**\r\n * Checks whether a message was filtered out\r\n * @param {any} result - processing result\r\n * @returns {boolean} true if filtered\r\n */\r\n _isFilteredMessage(result) {\r\n const filteredResults = Object.values(EnhancedSecureWebRTCManager.FILTERED_RESULTS);\r\n return filteredResults.includes(result);\r\n }\r\n /**\r\n * Enhanced log cleanup with security checks\r\n */\r\n _cleanupLogs() {\r\n // More aggressive cleanup to prevent data accumulation\r\n if (this._logCounts.size > 500) {\r\n this._logCounts.clear();\r\n this._secureLog('debug', '\uD83E\uDDF9 Log counts cleared due to size limit');\r\n }\r\n \r\n // Clean up old log entries to prevent memory leaks\r\n const now = Date.now();\r\n const maxAge = 300000; // 5 minutes\r\n \r\n // Check for suspicious log patterns\r\n let suspiciousCount = 0;\r\n for (const [key, count] of this._logCounts.entries()) {\r\n if (count > 10) {\r\n suspiciousCount++;\r\n }\r\n }\r\n \r\n // Emergency cleanup if too many suspicious patterns\r\n if (suspiciousCount > 20) {\r\n this._logCounts.clear();\r\n this._secureLog('warn', '\uD83D\uDEA8 Emergency log cleanup due to suspicious patterns');\r\n }\r\n \r\n // Reset security violation counter if system is stable\r\n if (this._logSecurityViolations > 0 && suspiciousCount < 5) {\r\n this._logSecurityViolations = Math.max(0, this._logSecurityViolations - 1);\r\n }\r\n \r\n // Clean up old IVs periodically\r\n if (!this._lastIVCleanupTime || Date.now() - this._lastIVCleanupTime > 300000) { // Every 5 minutes\r\n this._cleanupOldIVs();\r\n this._lastIVCleanupTime = Date.now();\r\n }\r\n \r\n // Periodic secure memory cleanup\r\n if (!this._secureMemoryManager.memoryStats.lastCleanup || \r\n Date.now() - this._secureMemoryManager.memoryStats.lastCleanup > 600000) { // Every 10 minutes\r\n // Schedule async cleanup without blocking\r\n this._performPeriodicMemoryCleanup().catch(error => {\r\n this._secureLog('error', 'Periodic cleanup failed', {\r\n errorType: error?.constructor?.name || 'Unknown'\r\n });\r\n });\r\n this._secureMemoryManager.memoryStats.lastCleanup = Date.now();\r\n }\r\n }\r\n /**\r\n * Secure logging stats with sensitive data protection\r\n */\r\n _getLoggingStats() {\r\n // Only return safe statistics\r\n const stats = {\r\n isProductionMode: this._isProductionMode,\r\n debugMode: this._debugMode,\r\n currentLogLevel: this._currentLogLevel,\r\n logCountsSize: this._logCounts.size,\r\n maxLogCount: this._maxLogCount,\r\n securityViolations: this._logSecurityViolations || 0,\r\n maxSecurityViolations: this._maxLogSecurityViolations || 3,\r\n systemStatus: this._currentLogLevel === -1 ? 'DISABLED' : 'ACTIVE'\r\n };\r\n \r\n // Sanitize any potentially sensitive data\r\n const sanitizedStats = {};\r\n for (const [key, value] of Object.entries(stats)) {\r\n if (typeof value === 'string' && this._containsSensitiveContent(value)) {\r\n sanitizedStats[key] = '[SENSITIVE_DATA_REDACTED]';\r\n } else {\r\n sanitizedStats[key] = value;\r\n }\r\n }\r\n \r\n return sanitizedStats;\r\n }\r\n /**\r\n * Enhanced emergency logging disable with cleanup\r\n */\r\n async _emergencyDisableLogging() {\r\n // Immediately disable all logging levels\r\n this._currentLogLevel = -1;\r\n \r\n // Clear all log data to prevent memory leaks\r\n this._logCounts.clear();\r\n \r\n // Clear any cached sensitive data\r\n if (this._logSecurityViolations) {\r\n this._logSecurityViolations = 0;\r\n }\r\n \r\n // Override _secureLog to a secure no-op\r\n this._secureLog = () => {\r\n // Only allow emergency console errors\r\n if (arguments[0] === 'error' && this._originalConsole?.error) {\r\n this._originalConsole.error('\uD83D\uDEA8 SECURITY: Logging system disabled - potential data exposure prevented');\r\n }\r\n };\r\n \r\n // Store original functions before overriding\r\n this._originalSanitizeString = this._sanitizeString;\r\n this._originalSanitizeLogData = this._sanitizeLogData;\r\n this._originalAuditLogMessage = this._auditLogMessage;\r\n this._originalContainsSensitiveContent = this._containsSensitiveContent;\r\n \r\n // Override all logging methods to prevent bypass\r\n this._sanitizeString = () => '[LOGGING_DISABLED]';\r\n this._sanitizeLogData = () => ({ error: 'LOGGING_DISABLED' });\r\n this._auditLogMessage = () => false;\r\n this._containsSensitiveContent = () => true; // Block everything\r\n \r\n // Schedule natural cleanup\r\n await this._performNaturalCleanup();\r\n \r\n // Notify about the emergency shutdown\r\n this._originalConsole?.error?.('\uD83D\uDEA8 CRITICAL: Secure logging system disabled due to potential data exposure');\r\n }\r\n\r\n /**\r\n * Reset logging system after emergency shutdown\r\n * Use this function to restore normal logging functionality\r\n */\r\n _resetLoggingSystem() {\r\n this._secureLog('info', '\uD83D\uDD27 Resetting logging system after emergency shutdown');\r\n \r\n // Restore original sanitize functions\r\n this._sanitizeString = this._originalSanitizeString || ((str) => str);\r\n this._sanitizeLogData = this._originalSanitizeLogData || ((data) => data);\r\n this._auditLogMessage = this._originalAuditLogMessage || (() => true);\r\n this._containsSensitiveContent = this._originalContainsSensitiveContent || (() => false);\r\n \r\n // Reset security violation counters\r\n this._logSecurityViolations = 0;\r\n \r\n this._secureLog('info', '\u2705 Logging system reset successfully');\r\n }\r\n /**\r\n * Enhanced audit function for log message security\r\n */\r\n _auditLogMessage(message, data) {\r\n if (!data || typeof data !== 'object') return true;\r\n \r\n // Convert to string and check for sensitive content\r\n const dataString = JSON.stringify(data);\r\n \r\n // Check message itself for sensitive content\r\n if (this._containsSensitiveContent(message)) {\r\n this._emergencyDisableLogging();\r\n this._originalConsole?.error?.('\uD83D\uDEA8 SECURITY BREACH: Sensitive content detected in log message');\r\n return false;\r\n }\r\n \r\n // Check data string for sensitive content\r\n if (this._containsSensitiveContent(dataString)) {\r\n this._emergencyDisableLogging();\r\n this._originalConsole?.error?.('\uD83D\uDEA8 SECURITY BREACH: Sensitive content detected in log data');\r\n return false;\r\n }\r\n \r\n // Enhanced dangerous pattern detection\r\n const dangerousPatterns = [\r\n 'secret', 'token', 'password', 'credential', 'auth',\r\n 'fingerprint', 'salt', 'signature', 'private_key', 'api_key', 'private',\r\n 'encryption', 'mac', 'metadata', 'session', 'jwt', 'bearer',\r\n 'key', 'hash', 'digest', 'nonce', 'iv', 'cipher'\r\n ];\r\n \r\n const dataStringLower = dataString.toLowerCase();\r\n \r\n for (const pattern of dangerousPatterns) {\r\n if (dataStringLower.includes(pattern) && !this._safeFieldsWhitelist.has(pattern)) {\r\n this._emergencyDisableLogging();\r\n this._originalConsole?.error?.(`\uD83D\uDEA8 SECURITY BREACH: Dangerous pattern detected in log: ${pattern}`);\r\n return false;\r\n }\r\n }\r\n \r\n // Check for high entropy values in data\r\n for (const [key, value] of Object.entries(data)) {\r\n if (typeof value === 'string' && this._hasHighEntropy(value)) {\r\n this._emergencyDisableLogging();\r\n this._originalConsole?.error?.(`\uD83D\uDEA8 SECURITY BREACH: High entropy value detected in log field: ${key}`);\r\n return false;\r\n }\r\n }\r\n \r\n return true;\r\n }\r\n\r\n initializeFileTransfer() {\r\n try {\r\n this._secureLog('info', '\uD83D\uDD27 Initializing Enhanced Secure File Transfer system...');\r\n\r\n if (this.fileTransferSystem) {\r\n this._secureLog('info', '\u2705 File transfer system already initialized');\r\n return;\r\n }\r\n \r\n // Step-by-step readiness check\r\n const channelReady = !!(this.dataChannel && this.dataChannel.readyState === 'open');\r\n if (!channelReady) {\r\n this._secureLog('warn', '\u26A0\uFE0F Data channel not open, deferring file transfer initialization');\r\n if (this.dataChannel) {\r\n const initHandler = () => {\r\n this._secureLog('info', '\uD83D\uDD04 DataChannel opened, initializing file transfer...');\r\n this.initializeFileTransfer();\r\n };\r\n this.dataChannel.addEventListener('open', initHandler, { once: true });\r\n }\r\n return;\r\n }\r\n\r\n if (!this.isVerified) {\r\n this._secureLog('warn', '\u26A0\uFE0F Connection not verified yet, deferring file transfer initialization');\r\n setTimeout(() => this.initializeFileTransfer(), 500);\r\n return;\r\n }\r\n \r\n // FIX: Clean up previous system if present\r\n if (this.fileTransferSystem) {\r\n this._secureLog('info', '\uD83E\uDDF9 Cleaning up existing file transfer system');\r\n this.fileTransferSystem.cleanup();\r\n this.fileTransferSystem = null;\r\n }\r\n \r\n // Ensure encryption keys are present\r\n if (!this.encryptionKey || !this.macKey) {\r\n this._secureLog('warn', '\u26A0\uFE0F Encryption keys not ready, deferring file transfer initialization');\r\n setTimeout(() => this.initializeFileTransfer(), 1000);\r\n return;\r\n }\r\n \r\n // IMPORTANT: callback order: (onProgress, onComplete, onError, onFileReceived)\r\n const safeOnComplete = (summary) => {\r\n // Sender: finalize transfer, no Blob handling\r\n try {\r\n this._secureLog('info', '\uD83C\uDFC1 Sender transfer summary', { summary });\r\n // Optionally forward as progress/UI event\r\n if (this.onFileProgress) {\r\n this.onFileProgress({ type: 'complete', ...summary });\r\n }\r\n } catch (e) {\r\n this._secureLog('warn', '\u26A0\uFE0F onComplete handler failed:', { details: e.message });\r\n }\r\n };\r\n\r\n this.fileTransferSystem = new EnhancedSecureFileTransfer(\r\n this,\r\n this.onFileProgress || null,\r\n safeOnComplete,\r\n this.onFileError || null,\r\n this.onFileReceived || null\r\n );\r\n \r\n this._fileTransferActive = true;\r\n \r\n this._secureLog('info', '\u2705 Enhanced Secure File Transfer system initialized successfully');\r\n \r\n // Verify the system is ready\r\n const status = this.fileTransferSystem.getSystemStatus();\r\n this._secureLog('info', '\uD83D\uDD0D File transfer system status after init', { status });\r\n \r\n } catch (error) {\r\n this._secureLog('error', '\u274C Failed to initialize file transfer system', { errorType: error.constructor.name });\r\n this.fileTransferSystem = null;\r\n this._fileTransferActive = false;\r\n }\r\n }\r\n\r\n // ============================================\r\n // ENHANCED SECURITY INITIALIZATION\r\n // ============================================\r\n\r\n async initializeEnhancedSecurity() {\r\n try {\r\n // Generate nested encryption key\r\n await this.generateNestedEncryptionKey();\r\n \r\n // Initialize decoy channels\r\n if (this.decoyChannelConfig.enabled) {\r\n this.initializeDecoyChannels();\r\n }\r\n \r\n // Start fake traffic generation\r\n if (this.fakeTrafficConfig.enabled) {\r\n this.startFakeTrafficGeneration();\r\n }\r\n\r\n } catch (error) {\r\n this._secureLog('error', '\u274C Failed to initialize enhanced security', { errorType: error.constructor.name });\r\n }\r\n }\r\n \r\n // Helper function: unbiased integer in [min, max]\r\n getSafeRandomInt(min, max) {\r\n if (!Number.isInteger(min) || !Number.isInteger(max)) {\r\n throw new Error('getSafeRandomInt requires integer min and max');\r\n }\r\n if (min >= max) {\r\n throw new Error('min must be less than max');\r\n }\r\n \r\n const range = max - min + 1;\r\n const bitsNeeded = Math.ceil(Math.log2(range));\r\n const bytesNeeded = Math.ceil(bitsNeeded / 8);\r\n const mask = (1 << bitsNeeded) - 1;\r\n \r\n let randomValue;\r\n do {\r\n const randomBytes = crypto.getRandomValues(new Uint8Array(bytesNeeded));\r\n\r\n randomValue = 0;\r\n for (let i = 0; i < bytesNeeded; i++) {\r\n randomValue = (randomValue * 256) + randomBytes[i];\r\n }\r\n\r\n randomValue = randomValue & mask;\r\n \r\n } while (randomValue >= range); \r\n\r\n return min + randomValue;\r\n }\r\n\r\n getSafeRandomFloat(minFloat, maxFloat, steps = 1000) {\r\n if (typeof minFloat !== 'number' || typeof maxFloat !== 'number') {\r\n throw new Error('getSafeRandomFloat requires numeric min and max');\r\n }\r\n if (minFloat >= maxFloat) {\r\n throw new Error('minFloat must be less than maxFloat');\r\n }\r\n const randomIndex = this.getSafeRandomInt(0, steps);\r\n \r\n const step = (maxFloat - minFloat) / steps;\r\n\r\n return minFloat + (randomIndex * step);\r\n }\r\n\r\n generateFingerprintMask() {\r\n const mask = {\r\n timingOffset: this.getSafeRandomInt(0, 1500),\r\n sizeVariation: this.getSafeRandomFloat(0.75, 1.25, 1000),\r\n noisePattern: Array.from(crypto.getRandomValues(new Uint8Array(64))),\r\n headerVariations: [\r\n 'X-Client-Version', 'X-Session-ID', 'X-Request-ID', 'X-Timestamp', 'X-Signature',\r\n 'X-Secure', 'X-Encrypted', 'X-Protected', 'X-Safe', 'X-Anonymous', 'X-Private'\r\n ],\r\n noiseIntensity: this.getSafeRandomInt(50, 150),\r\n sizeMultiplier: this.getSafeRandomFloat(0.75, 1.25, 1000),\r\n timingVariation: this.getSafeRandomInt(100, 1100)\r\n };\r\n return mask;\r\n }\r\n\r\n // Security configuration - all features enabled by default\r\n configureSecurityForSession() {\r\n this._secureLog('info', '\uD83D\uDD27 Configuring security - all features enabled by default');\r\n \r\n // All security features are enabled by default - no payment required\r\n this.sessionConstraints = {};\r\n \r\n Object.keys(this.securityFeatures).forEach(feature => {\r\n this.sessionConstraints[feature] = true; // All features enabled\r\n });\r\n \r\n this.applySessionConstraints();\r\n \r\n this._secureLog('info', '\u2705 Security configured - all features enabled', { constraints: this.sessionConstraints });\r\n\r\n if (!this._validateCryptographicSecurity()) {\r\n this._secureLog('error', '\uD83D\uDEA8 CRITICAL: Cryptographic security validation failed after session configuration');\r\n\r\n if (this.onStatusChange) {\r\n this.onStatusChange('security_breach', {\r\n type: 'crypto_security_failure',\r\n message: 'Cryptographic security validation failed after session configuration'\r\n });\r\n }\r\n }\r\n \r\n this.notifySecurityLevel();\r\n \r\n setTimeout(() => {\r\n this.calculateAndReportSecurityLevel();\r\n }, EnhancedSecureWebRTCManager.TIMEOUTS.SECURITY_CALC_DELAY);\r\n }\r\n\r\n // Applying session constraints - all features enabled by default\r\n applySessionConstraints() {\r\n if (!this.sessionConstraints) return;\r\n\r\n // All features are enabled by default - no restrictions\r\n Object.keys(this.sessionConstraints).forEach(feature => {\r\n this.securityFeatures[feature] = true; // All features enabled\r\n \r\n // Enable linked configurations\r\n switch (feature) {\r\n case 'hasFakeTraffic':\r\n this.fakeTrafficConfig.enabled = true;\r\n if (this.isConnected()) {\r\n this.startFakeTrafficGeneration();\r\n }\r\n break;\r\n case 'hasDecoyChannels':\r\n this.decoyChannelConfig.enabled = true;\r\n if (this.isConnected()) {\r\n this.initializeDecoyChannels();\r\n }\r\n break;\r\n case 'hasPacketReordering':\r\n this.reorderingConfig.enabled = true;\r\n break;\r\n case 'hasAntiFingerprinting':\r\n this.antiFingerprintingConfig.enabled = true;\r\n break;\r\n case 'hasMessageChunking':\r\n this.chunkingConfig.enabled = true;\r\n break;\r\n }\r\n });\r\n \r\n this._secureLog('info', '\u2705 All security features enabled by default', {\r\n constraints: this.sessionConstraints,\r\n currentFeatures: this.securityFeatures\r\n });\r\n }\r\n deliverMessageToUI(message, type = 'received') {\r\n try {\r\n // Add debug logs\r\n this._secureLog('debug', '\uD83D\uDCE4 deliverMessageToUI called', {\r\n message: message,\r\n type: type,\r\n messageType: typeof message,\r\n hasOnMessage: !!this.onMessage\r\n });\r\n \r\n // Filter out file-transfer and system messages\r\n if (typeof message === 'object' && message.type) {\r\n const blockedTypes = [\r\n EnhancedSecureWebRTCManager.MESSAGE_TYPES.FILE_TRANSFER_START,\r\n EnhancedSecureWebRTCManager.MESSAGE_TYPES.FILE_TRANSFER_RESPONSE,\r\n EnhancedSecureWebRTCManager.MESSAGE_TYPES.FILE_CHUNK,\r\n EnhancedSecureWebRTCManager.MESSAGE_TYPES.CHUNK_CONFIRMATION,\r\n EnhancedSecureWebRTCManager.MESSAGE_TYPES.FILE_TRANSFER_COMPLETE,\r\n EnhancedSecureWebRTCManager.MESSAGE_TYPES.FILE_TRANSFER_ERROR,\r\n EnhancedSecureWebRTCManager.MESSAGE_TYPES.HEARTBEAT,\r\n EnhancedSecureWebRTCManager.MESSAGE_TYPES.VERIFICATION,\r\n EnhancedSecureWebRTCManager.MESSAGE_TYPES.VERIFICATION_RESPONSE,\r\n EnhancedSecureWebRTCManager.MESSAGE_TYPES.VERIFICATION_CONFIRMED,\r\n EnhancedSecureWebRTCManager.MESSAGE_TYPES.VERIFICATION_BOTH_CONFIRMED,\r\n EnhancedSecureWebRTCManager.MESSAGE_TYPES.PEER_DISCONNECT,\r\n EnhancedSecureWebRTCManager.MESSAGE_TYPES.KEY_ROTATION_SIGNAL,\r\n EnhancedSecureWebRTCManager.MESSAGE_TYPES.KEY_ROTATION_READY,\r\n EnhancedSecureWebRTCManager.MESSAGE_TYPES.SECURITY_UPGRADE\r\n ];\r\n if (blockedTypes.includes(message.type)) {\r\n if (this._debugMode) {\r\n this._secureLog('warn', `\uD83D\uDED1 Blocked system/file message from UI: ${message.type}`);\r\n }\r\n return; // do not show in chat\r\n }\r\n }\r\n\r\n // Additional check for string messages containing JSON\r\n if (typeof message === 'string' && message.trim().startsWith('{')) {\r\n try {\r\n const parsedMessage = JSON.parse(message);\r\n if (parsedMessage.type) {\r\n const blockedTypes = [\r\n EnhancedSecureWebRTCManager.MESSAGE_TYPES.FILE_TRANSFER_START,\r\n EnhancedSecureWebRTCManager.MESSAGE_TYPES.FILE_TRANSFER_RESPONSE,\r\n EnhancedSecureWebRTCManager.MESSAGE_TYPES.FILE_CHUNK,\r\n EnhancedSecureWebRTCManager.MESSAGE_TYPES.CHUNK_CONFIRMATION,\r\n EnhancedSecureWebRTCManager.MESSAGE_TYPES.FILE_TRANSFER_COMPLETE,\r\n EnhancedSecureWebRTCManager.MESSAGE_TYPES.FILE_TRANSFER_ERROR,\r\n EnhancedSecureWebRTCManager.MESSAGE_TYPES.HEARTBEAT,\r\n EnhancedSecureWebRTCManager.MESSAGE_TYPES.VERIFICATION,\r\n EnhancedSecureWebRTCManager.MESSAGE_TYPES.VERIFICATION_RESPONSE,\r\n EnhancedSecureWebRTCManager.MESSAGE_TYPES.VERIFICATION_CONFIRMED,\r\n EnhancedSecureWebRTCManager.MESSAGE_TYPES.VERIFICATION_BOTH_CONFIRMED,\r\n EnhancedSecureWebRTCManager.MESSAGE_TYPES.PEER_DISCONNECT,\r\n EnhancedSecureWebRTCManager.MESSAGE_TYPES.KEY_ROTATION_SIGNAL,\r\n EnhancedSecureWebRTCManager.MESSAGE_TYPES.KEY_ROTATION_READY,\r\n EnhancedSecureWebRTCManager.MESSAGE_TYPES.SECURITY_UPGRADE\r\n ];\r\n if (blockedTypes.includes(parsedMessage.type)) {\r\n if (this._debugMode) {\r\n this._secureLog('warn', `\uD83D\uDED1 Blocked system/file message from UI (string): ${parsedMessage.type}`);\r\n }\r\n return; // do not show in chat\r\n }\r\n }\r\n } catch (parseError) {\r\n // Not JSON \u2014 fine for plain text messages\r\n }\r\n }\r\n\r\n if (this.onMessage) {\r\n this._secureLog('debug', '\uD83D\uDCE4 Calling this.onMessage callback', { message, type });\r\n this.onMessage(message, type);\r\n } else {\r\n this._secureLog('warn', '\u26A0\uFE0F this.onMessage callback is null or undefined');\r\n }\r\n } catch (err) {\r\n this._secureLog('error', '\u274C Failed to deliver message to UI:', { errorType: err?.constructor?.name || 'Unknown' });\r\n }\r\n }\r\n\r\n\r\n // Security Level Notification\r\n notifySecurityLevel() {\r\n // Avoid duplicate notifications\r\n if (this.lastSecurityLevelNotification === 'maximum') {\r\n return; // prevent duplication\r\n }\r\n \r\n this.lastSecurityLevelNotification = 'maximum';\r\n \r\n const message = '\uD83D\uDEE1\uFE0F Maximum Security Active - All features enabled';\r\n \r\n if (this.onMessage) {\r\n this.deliverMessageToUI(message, 'system');\r\n }\r\n\r\n // Showing details of active features\r\n if (this.onMessage) {\r\n const activeFeatures = Object.entries(this.securityFeatures)\r\n .filter(([key, value]) => value === true)\r\n .map(([key]) => key.replace('has', '').replace(/([A-Z])/g, ' $1').trim().toLowerCase())\r\n .slice(0, 5); \r\n\r\n this.deliverMessageToUI(`\uD83D\uDD27 Active: ${activeFeatures.join(', ')}...`, 'system');\r\n }\r\n }\r\n\r\n // Cleaning decoy channels\r\n cleanupDecoyChannels() {\r\n // Stopping decoy traffic\r\n for (const [channelName, timer] of this.decoyTimers.entries()) {\r\n clearTimeout(timer);\r\n }\r\n this.decoyTimers.clear();\r\n \r\n // Closing decoy channels\r\n for (const [channelName, channel] of this.decoyChannels.entries()) {\r\n if (channel.readyState === 'open') {\r\n channel.close();\r\n }\r\n }\r\n this.decoyChannels.clear();\r\n \r\n this._secureLog('info', '\uD83E\uDDF9 Decoy channels cleaned up');\r\n }\r\n\r\n // ============================================\r\n // 1. NESTED ENCRYPTION LAYER\r\n // ============================================\r\n\r\n async generateNestedEncryptionKey() {\r\n try {\r\n // Generate additional encryption key for nested encryption\r\n this.nestedEncryptionKey = await crypto.subtle.generateKey(\r\n { name: 'AES-GCM', length: 256 },\r\n false,\r\n ['encrypt', 'decrypt']\r\n );\r\n \r\n // Generate random IV for nested encryption\r\n // No need for base IV or counter - each encryption gets fresh random IV\r\n // This ensures maximum entropy and prevents IV reuse attacks\r\n \r\n } catch (error) {\r\n this._secureLog('error', '\u274C Failed to generate nested encryption key:', { errorType: error?.constructor?.name || 'Unknown' });\r\n throw error;\r\n }\r\n }\r\n\r\n async applyNestedEncryption(data) {\r\n if (!this.nestedEncryptionKey || !this.securityFeatures.hasNestedEncryption) {\r\n return data;\r\n }\r\n\r\n try {\r\n // Generate cryptographically secure IV with reuse prevention\r\n const uniqueIV = this._generateSecureIV(\r\n EnhancedSecureWebRTCManager.SIZES.NESTED_ENCRYPTION_IV_SIZE, \r\n 'nestedEncryption'\r\n );\r\n \r\n // Encrypt data with nested layer\r\n const encrypted = await crypto.subtle.encrypt(\r\n { name: 'AES-GCM', iv: uniqueIV },\r\n this.nestedEncryptionKey,\r\n data\r\n );\r\n \r\n // Combine IV and encrypted data\r\n const result = new Uint8Array(EnhancedSecureWebRTCManager.SIZES.NESTED_ENCRYPTION_IV_SIZE + encrypted.byteLength);\r\n result.set(uniqueIV, 0);\r\n result.set(new Uint8Array(encrypted), EnhancedSecureWebRTCManager.SIZES.NESTED_ENCRYPTION_IV_SIZE);\r\n \r\n this._secureLog('debug', '\u2705 Nested encryption applied with secure IV', {\r\n ivSize: uniqueIV.length,\r\n dataSize: data.byteLength,\r\n encryptedSize: encrypted.byteLength\r\n });\r\n \r\n return result.buffer;\r\n } catch (error) {\r\n this._secureLog('error', '\u274C Nested encryption failed:', { \r\n errorType: error?.constructor?.name || 'Unknown',\r\n errorMessage: error?.message || 'Unknown error'\r\n });\r\n \r\n // If IV generation failed due to emergency mode, disable nested encryption\r\n if (error.message.includes('emergency mode')) {\r\n this.securityFeatures.hasNestedEncryption = false;\r\n this._secureLog('warn', '\u26A0\uFE0F Nested encryption disabled due to IV emergency mode');\r\n }\r\n \r\n return data; // Fallback to original data\r\n }\r\n }\r\n\r\n async removeNestedEncryption(data) {\r\n if (!this.nestedEncryptionKey || !this.securityFeatures.hasNestedEncryption) {\r\n return data;\r\n }\r\n\r\n // Check that the data is actually encrypted with proper IV size\r\n if (!(data instanceof ArrayBuffer) || data.byteLength < EnhancedSecureWebRTCManager.SIZES.NESTED_ENCRYPTION_IV_SIZE + 16) {\r\n if (this._debugMode) {\r\n this._secureLog('debug', '\uD83D\uDCDD Data not encrypted or too short for nested decryption (need IV + minimum encrypted data)');\r\n }\r\n return data;\r\n }\r\n\r\n try {\r\n const dataArray = new Uint8Array(data);\r\n const iv = dataArray.slice(0, EnhancedSecureWebRTCManager.SIZES.NESTED_ENCRYPTION_IV_SIZE);\r\n const encryptedData = dataArray.slice(EnhancedSecureWebRTCManager.SIZES.NESTED_ENCRYPTION_IV_SIZE);\r\n \r\n // Check that there is data to decrypt\r\n if (encryptedData.length === 0) {\r\n if (this._debugMode) {\r\n this._secureLog('debug', '\uD83D\uDCDD No encrypted data found');\r\n }\r\n return data;\r\n }\r\n \r\n // Decrypt nested layer\r\n const decrypted = await crypto.subtle.decrypt(\r\n { name: 'AES-GCM', iv: iv },\r\n this.nestedEncryptionKey,\r\n encryptedData\r\n );\r\n \r\n return decrypted;\r\n } catch (error) {\r\n // FIX: Better error handling\r\n if (error.name === 'OperationError') {\r\n if (this._debugMode) {\r\n this._secureLog('debug', '\uD83D\uDCDD Data not encrypted with nested encryption, skipping...');\r\n }\r\n } else {\r\n if (this._debugMode) {\r\n this._secureLog('warn', '\u26A0\uFE0F Nested decryption failed:', { details: error.message });\r\n }\r\n }\r\n return data; // Fallback to original data\r\n }\r\n }\r\n\r\n // ============================================\r\n // 2. PACKET PADDING\r\n // ============================================\r\n\r\n applyPacketPadding(data) {\r\n if (!this.securityFeatures.hasPacketPadding) {\r\n return data;\r\n }\r\n\r\n try {\r\n const originalSize = data.byteLength;\r\n let paddingSize;\r\n \r\n if (this.paddingConfig.useRandomPadding) {\r\n // Generate random padding size\r\n paddingSize = Math.floor(Math.random() * \r\n (this.paddingConfig.maxPadding - this.paddingConfig.minPadding + 1)) + \r\n this.paddingConfig.minPadding;\r\n } else {\r\n // Use fixed padding size\r\n paddingSize = this.paddingConfig.minPadding;\r\n }\r\n \r\n // Generate random padding data\r\n const padding = crypto.getRandomValues(new Uint8Array(paddingSize));\r\n \r\n // Create padded message\r\n const paddedData = new Uint8Array(originalSize + paddingSize + 4);\r\n \r\n // Add original size (4 bytes)\r\n const sizeView = new DataView(paddedData.buffer, 0, 4);\r\n sizeView.setUint32(0, originalSize, false);\r\n \r\n // Add original data\r\n paddedData.set(new Uint8Array(data), 4);\r\n \r\n // Add padding\r\n paddedData.set(padding, 4 + originalSize);\r\n \r\n return paddedData.buffer;\r\n } catch (error) {\r\n this._secureLog('error', '\u274C Packet padding failed:', { errorType: error?.constructor?.name || 'Unknown' });\r\n return data; // Fallback to original data\r\n }\r\n }\r\n\r\n removePacketPadding(data) {\r\n if (!this.securityFeatures.hasPacketPadding) {\r\n return data;\r\n }\r\n\r\n try {\r\n const dataArray = new Uint8Array(data);\r\n \r\n // Check for minimum data length (4 bytes for size + minimum 1 byte of data)\r\n if (dataArray.length < 5) {\r\n if (this._debugMode) {\r\n this._secureLog('warn', '\u26A0\uFE0F Data too short for packet padding removal, skipping');\r\n }\r\n return data;\r\n }\r\n \r\n // Extract original size (first 4 bytes)\r\n const sizeView = new DataView(dataArray.buffer, 0, 4);\r\n const originalSize = sizeView.getUint32(0, false);\r\n \r\n // Checking the reasonableness of the size\r\n if (originalSize <= 0 || originalSize > dataArray.length - 4) {\r\n if (this._debugMode) {\r\n this._secureLog('warn', '\u26A0\uFE0F Invalid packet padding size, skipping removal');\r\n }\r\n return data;\r\n }\r\n \r\n // Extract original data\r\n const originalData = dataArray.slice(4, 4 + originalSize);\r\n \r\n return originalData.buffer;\r\n } catch (error) {\r\n if (this._debugMode) {\r\n this._secureLog('error', '\u274C Packet padding removal failed:', { errorType: error?.constructor?.name || 'Unknown' });\r\n }\r\n return data; // Fallback to original data\r\n }\r\n }\r\n\r\n // ============================================\r\n // 3. FAKE TRAFFIC GENERATION\r\n // ============================================\r\n\r\n startFakeTrafficGeneration() {\r\n if (!this.fakeTrafficConfig.enabled || !this.isConnected()) {\r\n return;\r\n }\r\n\r\n // Prevent multiple fake traffic generators\r\n if (this.fakeTrafficTimer) {\r\n this._secureLog('warn', '\u26A0\uFE0F Fake traffic generation already running');\r\n return;\r\n }\r\n\r\n const sendFakeMessage = async () => {\r\n if (!this.isConnected()) {\r\n this.stopFakeTrafficGeneration();\r\n return;\r\n }\r\n\r\n try {\r\n const fakeMessage = this.generateFakeMessage();\r\n await this.sendFakeMessage(fakeMessage);\r\n \r\n // FIX: Increase intervals to reduce load\r\n const nextInterval = this.fakeTrafficConfig.randomDecoyIntervals ? \r\n this.getUnbiasedRandomInRange(this.fakeTrafficConfig.minInterval, Math.min(this.fakeTrafficConfig.maxInterval, 60000)) : // Cap at 60 seconds\r\n this.fakeTrafficConfig.minInterval;\r\n \r\n // Minimum interval 15 seconds for stability\r\n const safeInterval = Math.max(nextInterval, EnhancedSecureWebRTCManager.TIMEOUTS.FAKE_TRAFFIC_MIN_INTERVAL);\r\n \r\n this.fakeTrafficTimer = setTimeout(sendFakeMessage, safeInterval);\r\n } catch (error) {\r\n if (this._debugMode) {\r\n this._secureLog('error', '\u274C Fake traffic generation failed:', { errorType: error?.constructor?.name || 'Unknown' });\r\n }\r\n this.stopFakeTrafficGeneration();\r\n }\r\n };\r\n\r\n // Start fake traffic generation with longer initial delay\r\n // Use a reasonable range for initial delay (5-30 seconds)\r\n const minDelay = EnhancedSecureWebRTCManager.TIMEOUTS.DECOY_INITIAL_DELAY;\r\n const maxDelay = Math.min(this.fakeTrafficConfig.maxInterval, 30000); // Cap at 30 seconds\r\n const initialDelay = this.getUnbiasedRandomInRange(minDelay, maxDelay);\r\n this.fakeTrafficTimer = setTimeout(sendFakeMessage, initialDelay);\r\n }\r\n\r\n stopFakeTrafficGeneration() {\r\n if (this.fakeTrafficTimer) {\r\n clearTimeout(this.fakeTrafficTimer);\r\n this.fakeTrafficTimer = null;\r\n }\r\n }\r\n\r\n generateFakeMessage() {\r\n const patternIndex = this.getUnbiasedRandomInRange(0, this.fakeTrafficConfig.patterns.length - 1);\r\n const pattern = this.fakeTrafficConfig.patterns[patternIndex];\r\n \r\n const size = this.getUnbiasedRandomInRange(this.fakeTrafficConfig.minSize, this.fakeTrafficConfig.maxSize);\r\n \r\n const fakeData = crypto.getRandomValues(new Uint8Array(size));\r\n \r\n return {\r\n type: EnhancedSecureWebRTCManager.MESSAGE_TYPES.FAKE, \r\n pattern: pattern,\r\n data: Array.from(fakeData).map(b => b.toString(16).padStart(2, '0')).join(''),\r\n timestamp: Date.now(),\r\n size: size,\r\n isFakeTraffic: true, \r\n source: 'fake_traffic_generator',\r\n fakeId: crypto.getRandomValues(new Uint32Array(1))[0].toString(36) \r\n };\r\n }\r\n\r\n // ============================================\r\n // EMERGENCY SHUT-OFF OF ADVANCED FUNCTIONS\r\n // ============================================\r\n\r\n emergencyDisableAdvancedFeatures() {\r\n this._secureLog('error', '\uD83D\uDEA8 Emergency disabling advanced security features due to errors');\r\n \r\n // Disable problematic functions\r\n this.securityFeatures.hasNestedEncryption = false;\r\n this.securityFeatures.hasPacketReordering = false;\r\n this.securityFeatures.hasAntiFingerprinting = false;\r\n \r\n // Disable configurations\r\n this.reorderingConfig.enabled = false;\r\n this.antiFingerprintingConfig.enabled = false;\r\n \r\n // Clear the buffers\r\n this.packetBuffer.clear();\r\n \r\n // Stopping fake traffic\r\n this.emergencyDisableFakeTraffic();\r\n \r\n this._secureLog('info', '\u2705 Advanced features disabled, keeping basic encryption');\r\n \r\n // Check that advanced-features-disabled notification wasn't already sent\r\n if (!this.advancedFeaturesDisabledNotificationSent) {\r\n this.advancedFeaturesDisabledNotificationSent = true;\r\n if (this.onMessage) {\r\n this.deliverMessageToUI('\uD83D\uDEA8 Advanced security features temporarily disabled due to compatibility issues', 'system');\r\n }\r\n }\r\n }\r\n\r\n async sendFakeMessage(fakeMessage) {\r\n if (!this._validateConnection(false)) {\r\n return;\r\n }\r\n\r\n try {\r\n this._secureLog('debug', '\uD83C\uDFAD Sending fake message', {\r\n hasPattern: !!fakeMessage.pattern,\r\n sizeRange: fakeMessage.size > 100 ? 'large' : 'small'\r\n });\r\n \r\n const fakeData = JSON.stringify({\r\n ...fakeMessage,\r\n type: EnhancedSecureWebRTCManager.MESSAGE_TYPES.FAKE, \r\n isFakeTraffic: true, \r\n timestamp: Date.now()\r\n });\r\n \r\n const fakeBuffer = new TextEncoder().encode(fakeData);\r\n const encryptedFake = await this.applySecurityLayers(fakeBuffer, true);\r\n this.dataChannel.send(encryptedFake);\r\n \r\n this._secureLog('debug', '\uD83C\uDFAD Fake message sent successfully', {\r\n pattern: fakeMessage.pattern\r\n });\r\n } catch (error) {\r\n this._secureLog('error', '\u274C Failed to send fake message', {\r\n error: error.message\r\n });\r\n }\r\n }\r\n\r\ncheckFakeTrafficStatus() {\r\n const status = {\r\n fakeTrafficEnabled: this.securityFeatures.hasFakeTraffic,\r\n fakeTrafficConfigEnabled: this.fakeTrafficConfig.enabled,\r\n timerActive: !!this.fakeTrafficTimer,\r\n patterns: this.fakeTrafficConfig.patterns,\r\n intervals: {\r\n min: this.fakeTrafficConfig.minInterval,\r\n max: this.fakeTrafficConfig.maxInterval\r\n }\r\n };\r\n \r\n if (this._debugMode) {\r\n this._secureLog('info', '\uD83C\uDFAD Fake Traffic Status', { status });\r\n }\r\n return status;\r\n }\r\nemergencyDisableFakeTraffic() {\r\n if (this._debugMode) {\r\n this._secureLog('error', '\uD83D\uDEA8 Emergency disabling fake traffic');\r\n }\r\n \r\n this.securityFeatures.hasFakeTraffic = false;\r\n this.fakeTrafficConfig.enabled = false;\r\n this.stopFakeTrafficGeneration();\r\n \r\n if (this._debugMode) {\r\n this._secureLog('info', '\u2705 Fake traffic disabled');\r\n }\r\n \r\n // Check that fake-traffic-disabled notification wasn't already sent\r\n if (!this.fakeTrafficDisabledNotificationSent) {\r\n this.fakeTrafficDisabledNotificationSent = true;\r\n if (this.onMessage) {\r\n this.deliverMessageToUI('\uD83D\uDEA8 Fake traffic emergency disabled', 'system');\r\n }\r\n }\r\n }\r\n async _applySecurityLayersWithoutMutex(data, isFakeMessage = false) {\r\n try {\r\n let processedData = data;\r\n \r\n if (isFakeMessage) {\r\n if (this.encryptionKey && typeof processedData === 'string') {\r\n processedData = await window.EnhancedSecureCryptoUtils.encryptData(processedData, this.encryptionKey);\r\n }\r\n return processedData;\r\n }\r\n \r\n // Nested Encryption (if enabled)\r\n if (this.securityFeatures.hasNestedEncryption && this.nestedEncryptionKey && processedData instanceof ArrayBuffer) {\r\n processedData = await this.applyNestedEncryption(processedData);\r\n }\r\n \r\n // Packet Reordering (if enabled)\r\n if (this.securityFeatures.hasPacketReordering && this.reorderingConfig?.enabled && processedData instanceof ArrayBuffer) {\r\n processedData = this.applyPacketReordering(processedData);\r\n }\r\n \r\n // Packet Padding (if enabled)\r\n if (this.securityFeatures.hasPacketPadding && processedData instanceof ArrayBuffer) {\r\n processedData = this.applyPacketPadding(processedData);\r\n }\r\n \r\n // Anti-Fingerprinting (if enabled)\r\n if (this.securityFeatures.hasAntiFingerprinting && processedData instanceof ArrayBuffer) {\r\n processedData = this.applyAntiFingerprinting(processedData);\r\n }\r\n \r\n // Final encryption (if keys are present)\r\n if (this.encryptionKey && typeof processedData === 'string') {\r\n processedData = await window.EnhancedSecureCryptoUtils.encryptData(processedData, this.encryptionKey);\r\n }\r\n \r\n return processedData;\r\n \r\n } catch (error) {\r\n this._secureLog('error', '\u274C Error in applySecurityLayersWithoutMutex:', { errorType: error?.constructor?.name || 'Unknown' });\r\n return data; // Return original data on error\r\n }\r\n}\r\n // ============================================\r\n // 4. MESSAGE CHUNKING\r\n // ============================================\r\n\r\n async processChunkedMessage(chunkData) {\r\n try {\r\n if (!this.chunkingConfig.addChunkHeaders) {\r\n // No headers, treat as regular message\r\n return this.processMessage(chunkData);\r\n }\r\n\r\n const chunkArray = new Uint8Array(chunkData);\r\n if (chunkArray.length < 16) {\r\n // Too small to be a chunk with header\r\n return this.processMessage(chunkData);\r\n }\r\n\r\n // Extract chunk header\r\n const headerView = new DataView(chunkArray.buffer, 0, 16);\r\n const messageId = headerView.getUint32(0, false);\r\n const chunkIndex = headerView.getUint32(4, false);\r\n const totalChunks = headerView.getUint32(8, false);\r\n const chunkSize = headerView.getUint32(12, false);\r\n\r\n // Extract chunk data\r\n const chunk = chunkArray.slice(16, 16 + chunkSize);\r\n\r\n // Store chunk in buffer\r\n if (!this.chunkQueue[messageId]) {\r\n this.chunkQueue[messageId] = {\r\n chunks: new Array(totalChunks),\r\n received: 0,\r\n timestamp: Date.now()\r\n };\r\n }\r\n\r\n const messageBuffer = this.chunkQueue[messageId];\r\n messageBuffer.chunks[chunkIndex] = chunk;\r\n messageBuffer.received++;\r\n\r\n this._secureLog('debug', `\uD83D\uDCE6 Received chunk ${chunkIndex + 1}/${totalChunks} for message ${messageId}`);\r\n\r\n // Check if all chunks received\r\n if (messageBuffer.received === totalChunks) {\r\n // Combine all chunks\r\n const totalSize = messageBuffer.chunks.reduce((sum, chunk) => sum + chunk.length, 0);\r\n const combinedData = new Uint8Array(totalSize);\r\n \r\n let offset = 0;\r\n for (const chunk of messageBuffer.chunks) {\r\n combinedData.set(chunk, offset);\r\n offset += chunk.length;\r\n }\r\n\r\n // Process complete message\r\n await this.processMessage(combinedData.buffer);\r\n \r\n // Clean up\r\n delete this.chunkQueue[messageId];\r\n \r\n this._secureLog('info', `\uD83D\uDCE6 Chunked message ${messageId} reassembled and processed`);\r\n }\r\n } catch (error) {\r\n this._secureLog('error', '\u274C Chunked message processing failed:', { errorType: error?.constructor?.name || 'Unknown' });\r\n }\r\n }\r\n\r\n // ============================================\r\n // 5. DECOY CHANNELS\r\n // ============================================\r\n\r\n initializeDecoyChannels() {\r\n if (!this.decoyChannelConfig.enabled || !this.peerConnection) {\r\n return;\r\n }\r\n\r\n // Prevent multiple initializations\r\n if (this.decoyChannels.size > 0) {\r\n this._secureLog('warn', '\u26A0\uFE0F Decoy channels already initialized, skipping...');\r\n return;\r\n }\r\n\r\n try {\r\n const numDecoyChannels = Math.min(\r\n this.decoyChannelConfig.maxDecoyChannels,\r\n this.decoyChannelConfig.decoyChannelNames.length\r\n );\r\n\r\n for (let i = 0; i < numDecoyChannels; i++) {\r\n const channelName = this.decoyChannelConfig.decoyChannelNames[i];\r\n const decoyChannel = this.peerConnection.createDataChannel(channelName, {\r\n ordered: Math.random() > 0.5,\r\n maxRetransmits: Math.floor(Math.random() * 3)\r\n });\r\n\r\n this.setupDecoyChannel(decoyChannel, channelName);\r\n this.decoyChannels.set(channelName, decoyChannel);\r\n }\r\n\r\n if (this._debugMode) {\r\n this._secureLog('info', `\uD83C\uDFAD Initialized ${numDecoyChannels} decoy channels`);\r\n }\r\n } catch (error) {\r\n if (this._debugMode) {\r\n this._secureLog('error', '\u274C Failed to initialize decoy channels:', { errorType: error?.constructor?.name || 'Unknown' });\r\n }\r\n }\r\n }\r\n\r\n setupDecoyChannel(channel, channelName) {\r\n channel.onopen = () => {\r\n if (this._debugMode) {\r\n this._secureLog('debug', `\uD83C\uDFAD Decoy channel \"${channelName}\" opened`);\r\n }\r\n this.startDecoyTraffic(channel, channelName);\r\n };\r\n\r\n channel.onmessage = (event) => {\r\n if (this._debugMode) {\r\n this._secureLog('debug', `\uD83C\uDFAD Received decoy message on \"${channelName}\": ${event.data?.length || 'undefined'} bytes`);\r\n }\r\n };\r\n\r\n channel.onclose = () => {\r\n if (this._debugMode) {\r\n this._secureLog('debug', `\uD83C\uDFAD Decoy channel \"${channelName}\" closed`);\r\n }\r\n this.stopDecoyTraffic(channelName);\r\n };\r\n\r\n channel.onerror = (error) => {\r\n if (this._debugMode) {\r\n this._secureLog('error', `\u274C Decoy channel \"${channelName}\" error`, { error: error.message });\r\n }\r\n };\r\n }\r\n\r\n startDecoyTraffic(channel, channelName) {\r\n const sendDecoyData = async () => {\r\n if (channel.readyState !== 'open') {\r\n return;\r\n }\r\n\r\n try {\r\n const decoyData = this.generateDecoyData(channelName);\r\n channel.send(decoyData);\r\n \r\n const interval = this.decoyChannelConfig.randomDecoyIntervals ?\r\n Math.random() * 15000 + 10000 : \r\n 20000; \r\n \r\n this.decoyTimers.set(channelName, setTimeout(() => sendDecoyData(), interval));\r\n } catch (error) {\r\n if (this._debugMode) {\r\n this._secureLog('error', `\u274C Failed to send decoy data on \"${channelName}\"`, { error: error.message });\r\n }\r\n }\r\n };\r\n\r\n const initialDelay = Math.random() * 10000 + 5000; \r\n this.decoyTimers.set(channelName, setTimeout(() => sendDecoyData(), initialDelay));\r\n }\r\n\r\n stopDecoyTraffic(channelName) {\r\n const timer = this.decoyTimers.get(channelName);\r\n if (timer) {\r\n clearTimeout(timer);\r\n this.decoyTimers.delete(channelName);\r\n }\r\n }\r\n\r\n generateDecoyData(channelName) {\r\n const decoyTypes = {\r\n 'sync': () => JSON.stringify({\r\n type: 'sync',\r\n timestamp: Date.now(),\r\n sequence: Math.floor(Math.random() * 1000),\r\n data: Array.from(crypto.getRandomValues(new Uint8Array(32)))\r\n .map(b => b.toString(16).padStart(2, '0')).join('')\r\n }),\r\n 'status': () => JSON.stringify({\r\n type: 'status',\r\n status: ['online', 'away', 'busy'][Math.floor(Math.random() * 3)],\r\n uptime: Math.floor(Math.random() * 3600),\r\n data: Array.from(crypto.getRandomValues(new Uint8Array(16)))\r\n .map(b => b.toString(16).padStart(2, '0')).join('')\r\n }),\r\n 'heartbeat': () => JSON.stringify({\r\n type: 'heartbeat',\r\n timestamp: Date.now(),\r\n data: Array.from(crypto.getRandomValues(new Uint8Array(24)))\r\n .map(b => b.toString(16).padStart(2, '0')).join('')\r\n }),\r\n 'metrics': () => JSON.stringify({\r\n type: 'metrics',\r\n cpu: Math.random() * 100,\r\n memory: Math.random() * 100,\r\n network: Math.random() * 1000,\r\n data: Array.from(crypto.getRandomValues(new Uint8Array(20)))\r\n .map(b => b.toString(16).padStart(2, '0')).join('')\r\n }),\r\n 'debug': () => JSON.stringify({\r\n type: 'debug',\r\n level: ['info', 'warn', 'error'][Math.floor(Math.random() * 3)],\r\n message: 'Debug message',\r\n data: Array.from(crypto.getRandomValues(new Uint8Array(28)))\r\n .map(b => b.toString(16).padStart(2, '0')).join('')\r\n })\r\n };\r\n\r\n return decoyTypes[channelName] ? decoyTypes[channelName]() : \r\n Array.from(crypto.getRandomValues(new Uint8Array(64)))\r\n .map(b => b.toString(16).padStart(2, '0')).join('');\r\n }\r\n\r\n // ============================================\r\n // 6. PACKET REORDERING PROTECTION\r\n // ============================================\r\n\r\n addReorderingHeaders(data) {\r\n if (!this.reorderingConfig.enabled) {\r\n return data;\r\n }\r\n\r\n try {\r\n const dataArray = new Uint8Array(data);\r\n const headerSize = this.reorderingConfig.useTimestamps ? 12 : 8;\r\n const header = new ArrayBuffer(headerSize);\r\n const headerView = new DataView(header);\r\n\r\n // Add sequence number\r\n if (this.reorderingConfig.useSequenceNumbers) {\r\n headerView.setUint32(0, this.sequenceNumber++, false);\r\n }\r\n\r\n // Add timestamp\r\n if (this.reorderingConfig.useTimestamps) {\r\n headerView.setUint32(4, Date.now(), false);\r\n }\r\n\r\n // Add data size\r\n headerView.setUint32(this.reorderingConfig.useTimestamps ? 8 : 4, dataArray.length, false);\r\n\r\n // Combine header and data\r\n const result = new Uint8Array(headerSize + dataArray.length);\r\n result.set(new Uint8Array(header), 0);\r\n result.set(dataArray, headerSize);\r\n\r\n return result.buffer;\r\n } catch (error) {\r\n this._secureLog('error', '\u274C Failed to add reordering headers:', { errorType: error?.constructor?.name || 'Unknown' });\r\n return data;\r\n }\r\n }\r\n\r\n async processReorderedPacket(data) {\r\n if (!this.reorderingConfig.enabled) {\r\n return this.processMessage(data);\r\n }\r\n\r\n try {\r\n const dataArray = new Uint8Array(data);\r\n const headerSize = this.reorderingConfig.useTimestamps ? 12 : 8;\r\n\r\n if (dataArray.length < headerSize) {\r\n if (this._debugMode) {\r\n this._secureLog('warn', '\u26A0\uFE0F Data too short for reordering headers, processing directly');\r\n }\r\n return this.processMessage(data);\r\n }\r\n\r\n const headerView = new DataView(dataArray.buffer, 0, headerSize);\r\n let sequence = 0;\r\n let timestamp = 0;\r\n let dataSize = 0;\r\n\r\n if (this.reorderingConfig.useSequenceNumbers) {\r\n sequence = headerView.getUint32(0, false);\r\n }\r\n\r\n if (this.reorderingConfig.useTimestamps) {\r\n timestamp = headerView.getUint32(4, false);\r\n }\r\n\r\n dataSize = headerView.getUint32(this.reorderingConfig.useTimestamps ? 8 : 4, false);\r\n\r\n if (dataSize > dataArray.length - headerSize || dataSize <= 0) {\r\n if (this._debugMode) {\r\n this._secureLog('warn', '\u26A0\uFE0F Invalid reordered packet data size, processing directly');\r\n }\r\n return this.processMessage(data);\r\n }\r\n\r\n const actualData = dataArray.slice(headerSize, headerSize + dataSize);\r\n\r\n try {\r\n const textData = new TextDecoder().decode(actualData);\r\n const content = JSON.parse(textData);\r\n if (content.type === 'fake' || content.isFakeTraffic === true) {\r\n if (this._debugMode) {\r\n this._secureLog('warn', `\uD83C\uDFAD BLOCKED: Reordered fake message: ${content.pattern || 'unknown'}`);\r\n }\r\n return; \r\n }\r\n } catch (e) {\r\n\r\n }\r\n\r\n this.packetBuffer.set(sequence, {\r\n data: actualData.buffer,\r\n timestamp: timestamp || Date.now()\r\n });\r\n\r\n await this.processOrderedPackets();\r\n\r\n } catch (error) {\r\n this._secureLog('error', '\u274C Failed to process reordered packet:', { errorType: error?.constructor?.name || 'Unknown' });\r\n return this.processMessage(data);\r\n }\r\n}\r\n\r\n// ============================================\r\n// IMPROVED PROCESSORDEREDPACKETS with filtering\r\n// ============================================\r\n\r\nasync processOrderedPackets() {\r\n const now = Date.now();\r\n const timeout = this.reorderingConfig.reorderTimeout;\r\n\r\n while (true) {\r\n const nextSequence = this.lastProcessedSequence + 1;\r\n const packet = this.packetBuffer.get(nextSequence);\r\n\r\n if (!packet) {\r\n const oldestPacket = this.findOldestPacket();\r\n if (oldestPacket && (now - oldestPacket.timestamp) > timeout) {\r\n this._secureLog('warn', '\u26A0\uFE0F Packet ${oldestPacket.sequence} timed out, processing out of order');\r\n \r\n try {\r\n const textData = new TextDecoder().decode(oldestPacket.data);\r\n const content = JSON.parse(textData);\r\n if (content.type === 'fake' || content.isFakeTraffic === true) {\r\n this._secureLog('warn', `\uD83C\uDFAD BLOCKED: Timed out fake message: ${content.pattern || 'unknown'}`);\r\n this.packetBuffer.delete(oldestPacket.sequence);\r\n this.lastProcessedSequence = oldestPacket.sequence;\r\n continue; \r\n }\r\n } catch (e) {\r\n }\r\n \r\n await this.processMessage(oldestPacket.data);\r\n this.packetBuffer.delete(oldestPacket.sequence);\r\n this.lastProcessedSequence = oldestPacket.sequence;\r\n } else {\r\n break; \r\n }\r\n } else {\r\n try {\r\n const textData = new TextDecoder().decode(packet.data);\r\n const content = JSON.parse(textData);\r\n if (content.type === 'fake' || content.isFakeTraffic === true) {\r\n this._secureLog('warn', `\uD83C\uDFAD BLOCKED: Ordered fake message: ${content.pattern || 'unknown'}`);\r\n this.packetBuffer.delete(nextSequence);\r\n this.lastProcessedSequence = nextSequence;\r\n continue; \r\n }\r\n } catch (e) {\r\n }\r\n \r\n await this.processMessage(packet.data);\r\n this.packetBuffer.delete(nextSequence);\r\n this.lastProcessedSequence = nextSequence;\r\n }\r\n }\r\n\r\n this.cleanupOldPackets(now, timeout);\r\n}\r\n\r\n\r\n findOldestPacket() {\r\n let oldest = null;\r\n for (const [sequence, packet] of this.packetBuffer.entries()) {\r\n if (!oldest || packet.timestamp < oldest.timestamp) {\r\n oldest = { sequence, ...packet };\r\n }\r\n }\r\n return oldest;\r\n }\r\n\r\n cleanupOldPackets(now, timeout) {\r\n for (const [sequence, packet] of this.packetBuffer.entries()) {\r\n if ((now - packet.timestamp) > timeout) {\r\n this._secureLog('warn', '\u26A0\uFE0F \uD83D\uDDD1\uFE0F Removing timed out packet ${sequence}');\r\n this.packetBuffer.delete(sequence);\r\n }\r\n }\r\n }\r\n\r\n // ============================================\r\n // 7. ANTI-FINGERPRINTING\r\n // ============================================\r\n\r\n applyAntiFingerprinting(data) {\r\n if (!this.antiFingerprintingConfig.enabled) {\r\n return data;\r\n }\r\n\r\n try {\r\n let processedData = data;\r\n\r\n // Add random noise\r\n if (this.antiFingerprintingConfig.addNoise) {\r\n processedData = this.addNoise(processedData);\r\n }\r\n\r\n // Randomize sizes\r\n if (this.antiFingerprintingConfig.randomizeSizes) {\r\n processedData = this.randomizeSize(processedData);\r\n }\r\n\r\n // Mask patterns\r\n if (this.antiFingerprintingConfig.maskPatterns) {\r\n processedData = this.maskPatterns(processedData);\r\n }\r\n\r\n // Add random headers\r\n if (this.antiFingerprintingConfig.useRandomHeaders) {\r\n processedData = this.addRandomHeaders(processedData);\r\n }\r\n\r\n return processedData;\r\n } catch (error) {\r\n this._secureLog('error', '\u274C Anti-fingerprinting failed:', { errorType: error?.constructor?.name || 'Unknown' });\r\n return data;\r\n }\r\n }\r\n\r\n addNoise(data) {\r\n const dataArray = new Uint8Array(data);\r\n const noiseSize = this.getUnbiasedRandomInRange(8, 40); // 8-40 bytes\r\n const noise = crypto.getRandomValues(new Uint8Array(noiseSize));\r\n \r\n const result = new Uint8Array(dataArray.length + noiseSize);\r\n result.set(dataArray, 0);\r\n result.set(noise, dataArray.length);\r\n \r\n return result.buffer;\r\n }\r\n\r\n randomizeSize(data) {\r\n const dataArray = new Uint8Array(data);\r\n const variation = this.fingerprintMask.sizeVariation;\r\n const targetSize = Math.floor(dataArray.length * variation);\r\n \r\n if (targetSize > dataArray.length) {\r\n // Add padding to increase size\r\n const padding = crypto.getRandomValues(new Uint8Array(targetSize - dataArray.length));\r\n const result = new Uint8Array(targetSize);\r\n result.set(dataArray, 0);\r\n result.set(padding, dataArray.length);\r\n return result.buffer;\r\n } else if (targetSize < dataArray.length) {\r\n // Truncate to decrease size\r\n return dataArray.slice(0, targetSize).buffer;\r\n }\r\n \r\n return data;\r\n }\r\n\r\n maskPatterns(data) {\r\n const dataArray = new Uint8Array(data);\r\n const result = new Uint8Array(dataArray.length);\r\n \r\n // Apply XOR with noise pattern\r\n for (let i = 0; i < dataArray.length; i++) {\r\n const noiseByte = this.fingerprintMask.noisePattern[i % this.fingerprintMask.noisePattern.length];\r\n result[i] = dataArray[i] ^ noiseByte;\r\n }\r\n \r\n return result.buffer;\r\n }\r\n\r\n addRandomHeaders(data) {\r\n const dataArray = new Uint8Array(data);\r\n const headerCount = this.getUnbiasedRandomInRange(1, 3); // 1-3 headers\r\n let totalHeaderSize = 0;\r\n \r\n // Calculate total header size\r\n for (let i = 0; i < headerCount; i++) {\r\n totalHeaderSize += 4 + this.getUnbiasedRandomInRange(0, 15) + 4; // size + data + checksum\r\n }\r\n \r\n const result = new Uint8Array(totalHeaderSize + dataArray.length);\r\n let offset = 0;\r\n \r\n // Add random headers\r\n for (let i = 0; i < headerCount; i++) {\r\n // Generate unbiased random index for header selection\r\n let headerIndex;\r\n do {\r\n headerIndex = crypto.getRandomValues(new Uint8Array(1))[0];\r\n } while (headerIndex >= 256 - (256 % this.fingerprintMask.headerVariations.length));\r\n \r\n const headerName = this.fingerprintMask.headerVariations[headerIndex % this.fingerprintMask.headerVariations.length];\r\n \r\n // Generate unbiased random size for header data (4-19 bytes)\r\n let headerSize;\r\n do {\r\n headerSize = crypto.getRandomValues(new Uint8Array(1))[0];\r\n } while (headerSize >= 256 - (256 % 16));\r\n \r\n const headerData = crypto.getRandomValues(new Uint8Array((headerSize % 16) + 4));\r\n \r\n // Header structure: [size:4][name:4][data:variable][checksum:4]\r\n const headerView = new DataView(result.buffer, offset);\r\n headerView.setUint32(0, headerData.length + 8, false); // Total header size\r\n headerView.setUint32(4, this.hashString(headerName), false); // Name hash\r\n \r\n result.set(headerData, offset + 8);\r\n \r\n // Add checksum\r\n const checksum = this.calculateChecksum(result.slice(offset, offset + 8 + headerData.length));\r\n const checksumView = new DataView(result.buffer, offset + 8 + headerData.length);\r\n checksumView.setUint32(0, checksum, false);\r\n \r\n offset += 8 + headerData.length + 4;\r\n }\r\n \r\n // Add original data\r\n result.set(dataArray, offset);\r\n \r\n return result.buffer;\r\n }\r\n\r\n hashString(str) {\r\n let hash = 0;\r\n for (let i = 0; i < str.length; i++) {\r\n const char = str.charCodeAt(i);\r\n hash = ((hash << 5) - hash) + char;\r\n hash = hash & hash;\r\n }\r\n return Math.abs(hash);\r\n }\r\n\r\n calculateChecksum(data) {\r\n let checksum = 0;\r\n for (let i = 0; i < data.length; i++) {\r\n checksum = (checksum + data[i]) & 0xFFFFFFFF;\r\n }\r\n return checksum;\r\n }\r\n\r\n // ============================================\r\n // ENHANCED MESSAGE SENDING AND RECEIVING\r\n // ============================================\r\n\r\n async removeSecurityLayers(data) {\r\n try {\r\n const status = this.getSecurityStatus();\r\n if (this._debugMode) {\r\n this._secureLog('debug', `\uD83D\uDD0D removeSecurityLayers (Stage ${status.stage})`, {\r\n dataType: typeof data,\r\n dataLength: data?.length || data?.byteLength || 0,\r\n activeFeatures: status.activeFeaturesCount\r\n });\r\n }\r\n\r\n if (!data) {\r\n this._secureLog('warn', '\u26A0\uFE0F Received empty data');\r\n return null;\r\n }\r\n\r\n let processedData = data;\r\n\r\n // IMPORTANT: Early check for fake messages\r\n if (typeof data === 'string') {\r\n try {\r\n const jsonData = JSON.parse(data);\r\n \r\n // PRIORITY ONE: Filtering out fake messages\r\n if (jsonData.type === 'fake') {\r\n if (this._debugMode) {\r\n this._secureLog('debug', `\uD83C\uDFAD Fake message filtered out: ${jsonData.pattern} (size: ${jsonData.size})`);\r\n }\r\n return 'FAKE_MESSAGE_FILTERED'; \r\n }\r\n \r\n // System messages \u2014 do NOT return for re-processing\r\n if (jsonData.type && ['heartbeat', 'verification', 'verification_response', 'peer_disconnect', 'key_rotation_signal', 'key_rotation_ready', 'security_upgrade'].includes(jsonData.type)) {\r\n return 'SYSTEM_MESSAGE_FILTERED';\r\n }\r\n \r\n // File transfer messages \u2014 do NOT return for display\r\n if (jsonData.type && ['file_transfer_start', 'file_transfer_response', 'file_chunk', 'chunk_confirmation', 'file_transfer_complete', 'file_transfer_error'].includes(jsonData.type)) {\r\n if (this._debugMode) {\r\n this._secureLog('debug', '\uD83D\uDCC1 File transfer message detected, blocking from chat', { type: jsonData.type });\r\n }\r\n return 'FILE_MESSAGE_FILTERED';\r\n }\r\n \r\n // Regular text messages - extract the actual message text\r\n if (jsonData.type === 'message') {\r\n if (this._debugMode) {\r\n this._secureLog('debug', '\uD83D\uDCDD Regular message detected, extracting text', { data: jsonData.data });\r\n }\r\n return jsonData.data; // Return the actual message text, not the JSON\r\n }\r\n \r\n // Enhanced messages\r\n if (jsonData.type === 'enhanced_message' && jsonData.data) {\r\n if (this._debugMode) {\r\n this._secureLog('debug', '\uD83D\uDD10 Enhanced message detected, decrypting...');\r\n }\r\n \r\n if (!this.encryptionKey || !this.macKey || !this.metadataKey) {\r\n this._secureLog('error', '\u274C Missing encryption keys');\r\n return null;\r\n }\r\n \r\n const decryptedResult = await window.EnhancedSecureCryptoUtils.decryptMessage(\r\n jsonData.data,\r\n this.encryptionKey,\r\n this.macKey,\r\n this.metadataKey\r\n );\r\n \r\n if (this._debugMode) {\r\n this._secureLog('debug', '\u2705 Enhanced message decrypted, extracting...');\r\n this._secureLog('debug', '\uD83D\uDD0D decryptedResult', {\r\n type: typeof decryptedResult,\r\n hasMessage: !!decryptedResult?.message,\r\n messageType: typeof decryptedResult?.message,\r\n messageLength: decryptedResult?.message?.length || 0,\r\n messageSample: decryptedResult?.message?.substring(0, 50) || 'no message'\r\n });\r\n }\r\n \r\n // CHECKING FOR FAKE MESSAGES AFTER DECRYPTION\r\n try {\r\n const decryptedContent = JSON.parse(decryptedResult.message);\r\n if (decryptedContent.type === 'fake' || decryptedContent.isFakeTraffic === true) {\r\n if (this._debugMode) {\r\n this._secureLog('warn', `\uD83C\uDFAD BLOCKED: Encrypted fake message: ${decryptedContent.pattern || 'unknown'}`);\r\n }\r\n return 'FAKE_MESSAGE_FILTERED';\r\n }\r\n } catch (e) {\r\n if (this._debugMode) {\r\n this._secureLog('debug', '\uD83D\uDCDD Decrypted content is not JSON, treating as plain text message');\r\n }\r\n }\r\n \r\n if (this._debugMode) {\r\n this._secureLog('debug', '\uD83D\uDCE4 Returning decrypted message', { message: decryptedResult.message?.substring(0, 50) });\r\n }\r\n return decryptedResult.message;\r\n }\r\n \r\n // Regular messages\r\n if (jsonData.type === 'message' && jsonData.data) {\r\n if (this._debugMode) {\r\n this._secureLog('debug', '\uD83D\uDCDD Regular message detected, extracting data');\r\n }\r\n return jsonData.data; // Return the actual message text\r\n }\r\n \r\n // If it's a regular message with type 'message', let it continue processing\r\n if (jsonData.type === 'message') {\r\n if (this._debugMode) {\r\n this._secureLog('debug', '\uD83D\uDCDD Regular message detected, returning for display');\r\n }\r\n return data; // Return the original JSON string for processing\r\n }\r\n \r\n // If it's not a special type, return the original data for display\r\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))) {\r\n if (this._debugMode) {\r\n this._secureLog('debug', '\uD83D\uDCDD Regular message detected, returning for display');\r\n }\r\n return data;\r\n }\r\n } catch (e) {\r\n if (this._debugMode) {\r\n this._secureLog('debug', '\uD83D\uDCC4 Not JSON, processing as raw data');\r\n }\r\n // If it's not JSON, it might be a plain text message - return as-is\r\n return data;\r\n }\r\n }\r\n\r\n // Standard Decryption\r\n if (this.encryptionKey && typeof processedData === 'string' && processedData.length > 50) {\r\n try {\r\n const base64Regex = /^[A-Za-z0-9+/=]+$/;\r\n if (base64Regex.test(processedData.trim())) {\r\n if (this._debugMode) {\r\n this._secureLog('debug', '\uD83D\uDD13 Applying standard decryption...');\r\n }\r\n processedData = await window.EnhancedSecureCryptoUtils.decryptData(processedData, this.encryptionKey);\r\n if (this._debugMode) {\r\n this._secureLog('debug', '\u2705 Standard decryption successful');\r\n }\r\n \r\n // CHECKING FOR FAKE MESSAGES AFTER LEGACY DECRYPTION\r\n if (typeof processedData === 'string') {\r\n try {\r\n const legacyContent = JSON.parse(processedData);\r\n if (legacyContent.type === 'fake' || legacyContent.isFakeTraffic === true) {\r\n if (this._debugMode) {\r\n this._secureLog('warn', `\uD83C\uDFAD BLOCKED: Legacy fake message: ${legacyContent.pattern || 'unknown'}`);\r\n }\r\n return 'FAKE_MESSAGE_FILTERED';\r\n }\r\n } catch (e) {\r\n \r\n }\r\n processedData = new TextEncoder().encode(processedData).buffer;\r\n }\r\n }\r\n } catch (error) {\r\n if (this._debugMode) {\r\n this._secureLog('warn', '\u26A0\uFE0F Standard decryption failed:', { details: error.message });\r\n }\r\n return data; \r\n }\r\n }\r\n\r\n if (this.securityFeatures.hasNestedEncryption && \r\n this.nestedEncryptionKey && \r\n processedData instanceof ArrayBuffer &&\r\n processedData.byteLength > 12) { \r\n \r\n try {\r\n processedData = await this.removeNestedEncryption(processedData);\r\n \r\n if (processedData instanceof ArrayBuffer) {\r\n try {\r\n const textData = new TextDecoder().decode(processedData);\r\n const nestedContent = JSON.parse(textData);\r\n if (nestedContent.type === 'fake' || nestedContent.isFakeTraffic === true) {\r\n if (this._debugMode) {\r\n this._secureLog('warn', `\uD83C\uDFAD BLOCKED: Nested fake message: ${nestedContent.pattern || 'unknown'}`);\r\n }\r\n return 'FAKE_MESSAGE_FILTERED';\r\n }\r\n } catch (e) {\r\n \r\n }\r\n }\r\n } catch (error) {\r\n if (this._debugMode) {\r\n this._secureLog('warn', '\u26A0\uFE0F Nested decryption failed - skipping this layer:', { details: error.message });\r\n }\r\n }\r\n }\r\n\r\n if (this.securityFeatures.hasPacketReordering && \r\n this.reorderingConfig.enabled && \r\n processedData instanceof ArrayBuffer) {\r\n try {\r\n const headerSize = this.reorderingConfig.useTimestamps ? 12 : 8;\r\n if (processedData.byteLength > headerSize) {\r\n return await this.processReorderedPacket(processedData);\r\n }\r\n } catch (error) {\r\n if (this._debugMode) {\r\n this._secureLog('warn', '\u26A0\uFE0F Reordering processing failed - using direct processing:', { details: error.message });\r\n }\r\n }\r\n }\r\n\r\n // Packet Padding Removal\r\n if (this.securityFeatures.hasPacketPadding && processedData instanceof ArrayBuffer) {\r\n try {\r\n processedData = this.removePacketPadding(processedData);\r\n } catch (error) {\r\n if (this._debugMode) {\r\n this._secureLog('warn', '\u26A0\uFE0F Padding removal failed:', { details: error.message });\r\n }\r\n }\r\n }\r\n\r\n // Anti-Fingerprinting Removal\r\n if (this.securityFeatures.hasAntiFingerprinting && processedData instanceof ArrayBuffer) {\r\n try {\r\n processedData = this.removeAntiFingerprinting(processedData);\r\n } catch (error) {\r\n if (this._debugMode) {\r\n this._secureLog('warn', '\u26A0\uFE0F Anti-fingerprinting removal failed:', { details: error.message });\r\n }\r\n }\r\n }\r\n\r\n // Final transformation\r\n if (processedData instanceof ArrayBuffer) {\r\n processedData = new TextDecoder().decode(processedData);\r\n }\r\n\r\n if (typeof processedData === 'string') {\r\n try {\r\n const finalContent = JSON.parse(processedData);\r\n if (finalContent.type === 'fake' || finalContent.isFakeTraffic === true) {\r\n if (this._debugMode) {\r\n this._secureLog('warn', `\uD83C\uDFAD BLOCKED: Final check fake message: ${finalContent.pattern || 'unknown'}`);\r\n }\r\n return 'FAKE_MESSAGE_FILTERED';\r\n }\r\n } catch (e) {\r\n }\r\n }\r\n\r\n return processedData;\r\n\r\n } catch (error) {\r\n this._secureLog('error', '\u274C Critical error in removeSecurityLayers:', { errorType: error?.constructor?.name || 'Unknown' });\r\n return data;\r\n }\r\n}\r\n\r\n removeAntiFingerprinting(data) {\r\n // This is a simplified version - in practice, you'd need to reverse all operations\r\n // For now, we'll just return the data as-is since the operations are mostly additive\r\n return data;\r\n }\r\n\r\n async applySecurityLayers(data, isFakeMessage = false) {\r\n try {\r\n let processedData = data;\r\n \r\n if (isFakeMessage) {\r\n if (this.encryptionKey && typeof processedData === 'string') {\r\n processedData = await window.EnhancedSecureCryptoUtils.encryptData(processedData, this.encryptionKey);\r\n }\r\n return processedData;\r\n }\r\n \r\n if (this.securityFeatures.hasNestedEncryption && this.nestedEncryptionKey && processedData instanceof ArrayBuffer) {\r\n processedData = await this.applyNestedEncryption(processedData);\r\n }\r\n \r\n if (this.securityFeatures.hasPacketReordering && this.reorderingConfig?.enabled && processedData instanceof ArrayBuffer) {\r\n processedData = this.applyPacketReordering(processedData);\r\n }\r\n \r\n if (this.securityFeatures.hasPacketPadding && processedData instanceof ArrayBuffer) {\r\n processedData = this.applyPacketPadding(processedData);\r\n }\r\n \r\n if (this.securityFeatures.hasAntiFingerprinting && processedData instanceof ArrayBuffer) {\r\n processedData = this.applyAntiFingerprinting(processedData);\r\n }\r\n \r\n if (this.encryptionKey && typeof processedData === 'string') {\r\n processedData = await window.EnhancedSecureCryptoUtils.encryptData(processedData, this.encryptionKey);\r\n }\r\n \r\n return processedData;\r\n \r\n } catch (error) {\r\n this._secureLog('error', '\u274C Error in applySecurityLayers:', { errorType: error?.constructor?.name || 'Unknown' });\r\n return data;\r\n }\r\n }\r\n\r\n async sendMessage(data) {\r\n // Comprehensive input validation\r\n const validation = this._validateInputData(data, 'sendMessage');\r\n if (!validation.isValid) {\r\n const errorMessage = `Input validation failed: ${validation.errors.join(', ')}`;\r\n this._secureLog('error', '\u274C Input validation failed in sendMessage', {\r\n errors: validation.errors,\r\n dataType: typeof data,\r\n dataLength: data?.length || data?.byteLength || 0\r\n });\r\n throw new Error(errorMessage);\r\n }\r\n\r\n // Rate limiting check\r\n if (!this._checkRateLimit('sendMessage')) {\r\n throw new Error('Rate limit exceeded for message sending');\r\n }\r\n\r\n // Enforce verification gate\r\n this._enforceVerificationGate('sendMessage');\r\n\r\n // Connection validation\r\n if (!this.dataChannel || this.dataChannel.readyState !== 'open') {\r\n throw new Error('Data channel not ready');\r\n }\r\n\r\n try {\r\n // Ensure encryption keys are available; try to reinitialize if needed\r\n if (!(this.encryptionKey && this.macKey && this.metadataKey)) {\r\n await this._tryReinitializeEncryptionKeys();\r\n }\r\n\r\n this._secureLog('debug', 'sendMessage called', {\r\n hasDataChannel: !!this.dataChannel,\r\n dataChannelReady: this.dataChannel?.readyState === 'open',\r\n isInitiator: this.isInitiator,\r\n isVerified: this.isVerified,\r\n connectionReady: this.peerConnection?.connectionState === 'connected'\r\n });\r\n\r\n this._secureLog('debug', '\uD83D\uDD0D sendMessage DEBUG', {\r\n dataType: typeof validation.sanitizedData,\r\n isString: typeof validation.sanitizedData === 'string',\r\n isArrayBuffer: validation.sanitizedData instanceof ArrayBuffer,\r\n dataLength: validation.sanitizedData?.length || validation.sanitizedData?.byteLength || 0,\r\n });\r\n\r\n // CRITICAL SECURITY FIX: File messages MUST be encrypted\r\n // No more bypassing encryption for file_* messages\r\n if (typeof validation.sanitizedData === 'string') {\r\n try {\r\n const parsed = JSON.parse(validation.sanitizedData);\r\n \r\n if (parsed.type && parsed.type.startsWith('file_')) {\r\n this._secureLog('debug', '\uD83D\uDCC1 File message detected - applying full encryption with AAD', { type: parsed.type });\r\n \r\n // Create AAD for file message\r\n const aad = this._createFileMessageAAD(parsed.type, parsed.data);\r\n \r\n // Encrypt file message with AAD\r\n const encryptedData = await this._encryptFileMessage(validation.sanitizedData, aad);\r\n \r\n this.dataChannel.send(encryptedData);\r\n return true;\r\n }\r\n } catch (jsonError) {\r\n // Not JSON \u2014 continue normal handling\r\n }\r\n }\r\n\r\n // For regular text messages, send via secure path with AAD\r\n if (typeof validation.sanitizedData === 'string') {\r\n // Verify that _createMessageAAD method is available\r\n if (typeof this._createMessageAAD !== 'function') {\r\n throw new Error('_createMessageAAD method is not available. Manager may not be fully initialized.');\r\n }\r\n \r\n // Create AAD with sequence number for anti-replay protection\r\n const aad = this._createMessageAAD('message', { content: validation.sanitizedData });\r\n \r\n return await this.sendSecureMessage({ \r\n type: 'message', \r\n data: validation.sanitizedData, \r\n timestamp: Date.now(),\r\n aad: aad // Include AAD for sequence number validation\r\n });\r\n }\r\n\r\n // For binary data, apply security layers with a limited mutex\r\n this._secureLog('debug', '\uD83D\uDD10 Applying security layers to non-string data');\r\n const securedData = await this._applySecurityLayersWithLimitedMutex(validation.sanitizedData, false);\r\n this.dataChannel.send(securedData);\r\n \r\n return true;\r\n } catch (error) {\r\n this._secureLog('error', '\u274C Failed to send message', { \r\n error: error.message,\r\n errorType: error.constructor.name\r\n });\r\n throw error;\r\n }\r\n }\r\n\r\n // FIX: New method applying security layers with limited mutex use\r\n async _applySecurityLayersWithLimitedMutex(data, isFakeMessage = false) {\r\n // Use mutex ONLY for cryptographic operations\r\n return this._withMutex('cryptoOperation', async (operationId) => {\r\n try {\r\n let processedData = data;\r\n \r\n if (isFakeMessage) {\r\n if (this.encryptionKey && typeof processedData === 'string') {\r\n processedData = await window.EnhancedSecureCryptoUtils.encryptData(processedData, this.encryptionKey);\r\n }\r\n return processedData;\r\n }\r\n \r\n if (this.securityFeatures.hasNestedEncryption && this.nestedEncryptionKey && processedData instanceof ArrayBuffer) {\r\n processedData = await this.applyNestedEncryption(processedData);\r\n }\r\n \r\n if (this.securityFeatures.hasPacketReordering && this.reorderingConfig?.enabled && processedData instanceof ArrayBuffer) {\r\n processedData = this.applyPacketReordering(processedData);\r\n }\r\n \r\n if (this.securityFeatures.hasPacketPadding && processedData instanceof ArrayBuffer) {\r\n processedData = this.applyPacketPadding(processedData);\r\n }\r\n \r\n if (this.securityFeatures.hasAntiFingerprinting && processedData instanceof ArrayBuffer) {\r\n processedData = this.applyAntiFingerprinting(processedData);\r\n }\r\n \r\n if (this.encryptionKey && typeof processedData === 'string') {\r\n processedData = await window.EnhancedSecureCryptoUtils.encryptData(processedData, this.encryptionKey);\r\n }\r\n \r\n return processedData;\r\n \r\n } catch (error) {\r\n this._secureLog('error', '\u274C Error in applySecurityLayers:', { errorType: error?.constructor?.name || 'Unknown' });\r\n return data;\r\n }\r\n }, 3000); // Short timeout for crypto operations\r\n}\r\n\r\n async sendSystemMessage(messageData) {\r\n // Block system messages without verification\r\n // Exception: Allow verification-related system messages\r\n const isVerificationMessage = messageData.type === 'verification_request' || \r\n messageData.type === 'verification_response' ||\r\n messageData.type === 'verification_required';\r\n \r\n if (!isVerificationMessage) {\r\n this._enforceVerificationGate('sendSystemMessage', false);\r\n }\r\n \r\n if (!this.dataChannel || this.dataChannel.readyState !== 'open') {\r\n this._secureLog('warn', '\u26A0\uFE0F Cannot send system message - data channel not ready');\r\n return false;\r\n }\r\n\r\n try {\r\n const systemMessage = JSON.stringify({\r\n type: messageData.type,\r\n data: messageData,\r\n timestamp: Date.now()\r\n });\r\n\r\n this._secureLog('debug', '\uD83D\uDD27 Sending system message', { type: messageData.type });\r\n this.dataChannel.send(systemMessage);\r\n return true;\r\n } catch (error) {\r\n this._secureLog('error', '\u274C Failed to send system message:', { errorType: error?.constructor?.name || 'Unknown' });\r\n return false;\r\n }\r\n }\r\n\r\n // FIX 1: Simplified mutex system for message processing\r\nasync processMessage(data) {\r\n try {\r\n this._secureLog('debug', '\uFFFD\uFFFD Processing message', {\r\n dataType: typeof data,\r\n isArrayBuffer: data instanceof ArrayBuffer,\r\n hasData: !!(data?.length || data?.byteLength)\r\n });\r\n \r\n // CRITICAL: Early check for file messages WITHOUT mutex\r\n if (typeof data === 'string') {\r\n try {\r\n const parsed = JSON.parse(data);\r\n\r\n // ============================================\r\n // FILE MESSAGES \u2014 PRIORITY 1 (WITHOUT MUTEX)\r\n // ============================================\r\n \r\n const fileMessageTypes = [\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 ];\r\n\r\n // CRITICAL SECURITY FIX: Check for encrypted file messages first\r\n if (parsed.type === 'encrypted_file_message') {\r\n this._secureLog('debug', '\uD83D\uDCC1 Encrypted file message detected in processMessage');\r\n \r\n try {\r\n // Decrypt and validate file message\r\n const { decryptedData, aad } = await this._decryptFileMessage(data);\r\n \r\n // Parse decrypted data\r\n const decryptedParsed = JSON.parse(decryptedData);\r\n \r\n this._secureLog('debug', '\uD83D\uDCC1 File message decrypted successfully', { \r\n type: decryptedParsed.type,\r\n aadMessageType: aad.messageType \r\n });\r\n \r\n // Process decrypted file message\r\n if (this.fileTransferSystem && typeof this.fileTransferSystem.handleFileMessage === 'function') {\r\n await this.fileTransferSystem.handleFileMessage(decryptedParsed);\r\n return;\r\n }\r\n } catch (error) {\r\n this._secureLog('error', '\u274C Failed to decrypt file message', { error: error.message });\r\n return; // Drop invalid file message\r\n }\r\n }\r\n \r\n // Legacy unencrypted file messages - should not happen in secure mode\r\n if (parsed.type && fileMessageTypes.includes(parsed.type)) {\r\n this._secureLog('warn', '\u26A0\uFE0F Unencrypted file message detected - this should not happen in secure mode', { type: parsed.type });\r\n \r\n // Drop unencrypted file messages for security\r\n this._secureLog('error', '\u274C Dropping unencrypted file message for security', { type: parsed.type });\r\n return;\r\n }\r\n \r\n // ============================================\r\n // ENHANCED MESSAGES WITH AAD VALIDATION (WITHOUT MUTEX)\r\n // ============================================\r\n \r\n if (parsed.type === 'enhanced_message') {\r\n this._secureLog('debug', '\uD83D\uDD10 Enhanced message detected in processMessage');\r\n \r\n try {\r\n // Decrypt enhanced message\r\n const decryptedData = await window.EnhancedSecureCryptoUtils.decryptMessage(\r\n parsed.data,\r\n this.encryptionKey,\r\n this.macKey,\r\n this.metadataKey\r\n );\r\n \r\n // Parse decrypted data\r\n const decryptedParsed = JSON.parse(decryptedData.data);\r\n \r\n // Validate AAD with sequence number\r\n if (decryptedData.metadata && decryptedData.metadata.sequenceNumber !== undefined) {\r\n if (!this._validateIncomingSequenceNumber(decryptedData.metadata.sequenceNumber, 'enhanced_message')) {\r\n this._secureLog('warn', '\u26A0\uFE0F Enhanced message sequence number validation failed - possible replay attack', {\r\n received: decryptedData.metadata.sequenceNumber,\r\n expected: this.expectedSequenceNumber\r\n });\r\n return; // Drop message with invalid sequence number\r\n }\r\n }\r\n \r\n // Process decrypted message\r\n if (decryptedParsed.type === 'message' && this.onMessage && decryptedParsed.data) {\r\n this.deliverMessageToUI(decryptedParsed.data, 'received');\r\n }\r\n \r\n return;\r\n } catch (error) {\r\n this._secureLog('error', '\u274C Failed to decrypt enhanced message', { error: error.message });\r\n return; // Drop invalid enhanced message\r\n }\r\n }\r\n \r\n // ============================================\r\n // REGULAR USER MESSAGES (WITHOUT MUTEX)\r\n // ============================================\r\n \r\n if (parsed.type === 'message') {\r\n this._secureLog('debug', '\uD83D\uDCDD Regular user message detected in processMessage');\r\n if (this.onMessage && parsed.data) {\r\n this.deliverMessageToUI(parsed.data, 'received');\r\n }\r\n return;\r\n }\r\n \r\n // ============================================\r\n // SYSTEM MESSAGES (WITHOUT MUTEX)\r\n // ============================================\r\n \r\n if (parsed.type && ['heartbeat', 'verification', 'verification_response', 'verification_confirmed', 'verification_both_confirmed', 'peer_disconnect', 'security_upgrade'].includes(parsed.type)) {\r\n this.handleSystemMessage(parsed);\r\n return;\r\n }\r\n \r\n // ============================================\r\n // FAKE MESSAGES (WITHOUT MUTEX)\r\n // ============================================\r\n \r\n if (parsed.type === 'fake') {\r\n this._secureLog('warn', '\uD83C\uDFAD Fake message blocked in processMessage', { pattern: parsed.pattern });\r\n return;\r\n }\r\n \r\n } catch (jsonError) {\r\n // Not JSON \u2014 treat as text WITHOUT mutex\r\n if (this.onMessage) {\r\n this.deliverMessageToUI(data, 'received');\r\n }\r\n return;\r\n }\r\n }\r\n\r\n // ============================================\r\n // ENCRYPTED DATA PROCESSING (WITH MUTEX ONLY FOR CRYPTO)\r\n // ============================================\r\n \r\n // If here \u2014 apply security layers with limited mutex\r\n const originalData = await this._processEncryptedDataWithLimitedMutex(data);\r\n\r\n // Check processing result\r\n if (originalData === 'FAKE_MESSAGE_FILTERED' || \r\n originalData === 'FILE_MESSAGE_FILTERED' || \r\n originalData === 'SYSTEM_MESSAGE_FILTERED') {\r\n return;\r\n }\r\n \r\n if (!originalData) {\r\n this._secureLog('warn', '\u26A0\uFE0F No data returned from removeSecurityLayers');\r\n return;\r\n }\r\n\r\n // Handle result after removeSecurityLayers\r\n let messageText;\r\n \r\n if (typeof originalData === 'string') {\r\n try {\r\n const message = JSON.parse(originalData);\r\n \r\n // SECOND CHECK FOR FILE MESSAGES AFTER DECRYPTION\r\n if (message.type && fileMessageTypes.includes(message.type)) {\r\n this._secureLog('debug', '\uD83D\uDCC1 File message detected after decryption', { type: message.type });\r\n if (this.fileTransferSystem) {\r\n await this.fileTransferSystem.handleFileMessage(message);\r\n }\r\n return;\r\n }\r\n \r\n if (message.type && ['heartbeat', 'verification', 'verification_response', 'verification_confirmed', 'verification_both_confirmed', 'peer_disconnect', 'security_upgrade'].includes(message.type)) {\r\n this.handleSystemMessage(message);\r\n return;\r\n }\r\n \r\n if (message.type === 'fake') {\r\n this._secureLog('warn', `\uD83C\uDFAD Post-decryption fake message blocked: ${message.pattern}`);\r\n return;\r\n }\r\n \r\n // Regular messages\r\n if (message.type === 'message' && message.data) {\r\n messageText = message.data;\r\n } else {\r\n messageText = originalData;\r\n }\r\n } catch (e) {\r\n messageText = originalData;\r\n }\r\n } else if (originalData instanceof ArrayBuffer) {\r\n messageText = new TextDecoder().decode(originalData);\r\n } else if (originalData && typeof originalData === 'object' && originalData.message) {\r\n messageText = originalData.message;\r\n } else {\r\n this._secureLog('warn', '\u26A0\uFE0F Unexpected data type after processing:', { details: typeof originalData });\r\n return;\r\n }\r\n\r\n // Final check for fake and file messages\r\n if (messageText && messageText.trim().startsWith('{')) {\r\n try {\r\n const finalCheck = JSON.parse(messageText);\r\n if (finalCheck.type === 'fake') {\r\n this._secureLog('warn', `\uD83C\uDFAD Final fake message check blocked: ${finalCheck.pattern}`);\r\n return;\r\n }\r\n \r\n // Additional check for file and system messages\r\n const blockedTypes = [\r\n 'file_transfer_start', 'file_transfer_response', 'file_chunk', \r\n 'chunk_confirmation', 'file_transfer_complete', 'file_transfer_error',\r\n 'heartbeat', 'verification', 'verification_response', \r\n 'peer_disconnect', 'key_rotation_signal', 'key_rotation_ready', 'security_upgrade'\r\n ];\r\n \r\n if (finalCheck.type && blockedTypes.includes(finalCheck.type)) {\r\n this._secureLog('warn', `\uD83D\uDCC1 Final system/file message check blocked: ${finalCheck.type}`);\r\n return;\r\n }\r\n } catch (e) {\r\n // Not JSON \u2014 fine for plain text\r\n }\r\n }\r\n\r\n // Deliver message to the UI\r\n if (this.onMessage && messageText) {\r\n this._secureLog('debug', '\uD83D\uDCE4 Calling message handler with', { message: messageText.substring(0, 100) });\r\n this.deliverMessageToUI(messageText, 'received');\r\n }\r\n\r\n } catch (error) {\r\n this._secureLog('error', '\u274C Failed to process message:', { errorType: error?.constructor?.name || 'Unknown' });\r\n }\r\n}\r\n\r\n // FIX: New method with limited mutex when processing encrypted data\r\n async _processEncryptedDataWithLimitedMutex(data) {\r\n // Use mutex ONLY for cryptographic operations\r\n return this._withMutex('cryptoOperation', async (operationId) => {\r\n this._secureLog('debug', '\uD83D\uDD10 Processing encrypted data with limited mutex', {\r\n operationId: operationId,\r\n dataType: typeof data\r\n });\r\n \r\n try {\r\n // Apply security layers\r\n const originalData = await this.removeSecurityLayers(data);\r\n return originalData;\r\n \r\n } catch (error) {\r\n this._secureLog('error', '\u274C Error processing encrypted data', {\r\n operationId: operationId,\r\n errorType: error.constructor.name\r\n });\r\n return data; // Return original data on error\r\n }\r\n }, 2000); // Short timeout for crypto operations\r\n }\r\n\r\n notifySecurityUpdate() {\r\n try {\r\n this._secureLog('debug', '\uD83D\uDD12 Notifying about security level update', {\r\n isConnected: this.isConnected(),\r\n isVerified: this.isVerified,\r\n hasKeys: !!(this.encryptionKey && this.macKey && this.metadataKey),\r\n hasLastCalculation: !!this.lastSecurityCalculation\r\n });\r\n \r\n // Send an event about security level update\r\n document.dispatchEvent(new CustomEvent('security-level-updated', {\r\n detail: { \r\n timestamp: Date.now(), \r\n manager: 'webrtc',\r\n webrtcManager: this,\r\n isConnected: this.isConnected(),\r\n isVerified: this.isVerified,\r\n hasKeys: !!(this.encryptionKey && this.macKey && this.metadataKey),\r\n lastCalculation: this.lastSecurityCalculation\r\n }\r\n }));\r\n \r\n // FIX: Force header refresh with correct manager\r\n setTimeout(() => {\r\n // Removed global callback - use event system instead\r\n // if (window.forceHeaderSecurityUpdate) {\r\n // window.forceHeaderSecurityUpdate(this);\r\n // }\r\n }, 100);\r\n \r\n // FIX: Direct update if there is a calculation\r\n if (this.lastSecurityCalculation) {\r\n document.dispatchEvent(new CustomEvent('real-security-calculated', {\r\n detail: {\r\n securityData: this.lastSecurityCalculation,\r\n webrtcManager: this,\r\n timestamp: Date.now()\r\n }\r\n }));\r\n }\r\n \r\n } catch (error) {\r\n this._secureLog('error', '\u274C Error in notifySecurityUpdate', {\r\n error: error.message\r\n });\r\n }\r\n }\r\n\r\n handleSystemMessage(message) {\r\n this._secureLog('debug', '\uD83D\uDD27 Handling system message:', { type: message.type });\r\n \r\n switch (message.type) {\r\n case 'heartbeat':\r\n this.handleHeartbeat();\r\n break;\r\n case 'verification':\r\n this.handleVerificationRequest(message.data);\r\n break;\r\n case 'verification_response':\r\n this.handleVerificationResponse(message.data);\r\n break;\r\n case 'sas_code':\r\n this.handleSASCode(message.data);\r\n break;\r\n case 'verification_confirmed':\r\n this.handleVerificationConfirmed(message.data);\r\n break;\r\n case 'verification_both_confirmed':\r\n this.handleVerificationBothConfirmed(message.data);\r\n break;\r\n case 'peer_disconnect':\r\n this.handlePeerDisconnectNotification(message);\r\n break;\r\n case 'key_rotation_signal':\r\n this._secureLog('debug', '\uD83D\uDD04 Key rotation signal received (ignored for stability)');\r\n break;\r\n case 'key_rotation_ready':\r\n this._secureLog('debug', '\uD83D\uDD04 Key rotation ready signal received (ignored for stability)');\r\n break;\r\n case 'security_upgrade':\r\n this._secureLog('debug', '\uD83D\uDD12 Security upgrade notification received:', { type: message.type });\r\n // Security upgrade messages are handled internally, not displayed to user\r\n // to prevent duplicate system messages\r\n break;\r\n default:\r\n this._secureLog('debug', '\uD83D\uDD27 Unknown system message type:', { type: message.type });\r\n }\r\n }\r\n\r\n // ============================================\r\n // FUNCTION MANAGEMENT METHODS\r\n // ============================================\r\n\r\n // Method to enable Stage 2 functions\r\n enableStage2Security() {\r\n if (this.sessionConstraints?.hasPacketReordering) {\r\n this.securityFeatures.hasPacketReordering = true;\r\n this.reorderingConfig.enabled = true;\r\n }\r\n \r\n if (this.sessionConstraints?.hasAntiFingerprinting) {\r\n this.securityFeatures.hasAntiFingerprinting = true;\r\n this.antiFingerprintingConfig.enabled = true;\r\n // Enable full anti-fingerprinting features\r\n this.antiFingerprintingConfig.randomizeSizes = true;\r\n this.antiFingerprintingConfig.maskPatterns = true;\r\n this.antiFingerprintingConfig.useRandomHeaders = true;\r\n }\r\n \r\n this.notifySecurityUpgrade(2);\r\n setTimeout(() => {\r\n this.calculateAndReportSecurityLevel();\r\n }, 500);\r\n }\r\n\r\n // Method to enable Stage 3 features (traffic obfuscation)\r\n enableStage3Security() {\r\n this._secureLog('info', '\uD83D\uDD12 Enabling Stage 3 features (traffic obfuscation)');\r\n \r\n if (this.sessionConstraints?.hasMessageChunking) {\r\n this.securityFeatures.hasMessageChunking = true;\r\n this.chunkingConfig.enabled = true;\r\n }\r\n \r\n if (this.sessionConstraints?.hasFakeTraffic) {\r\n this.securityFeatures.hasFakeTraffic = true;\r\n this.fakeTrafficConfig.enabled = true;\r\n this.startFakeTrafficGeneration();\r\n }\r\n \r\n this.notifySecurityUpgrade(3);\r\n setTimeout(() => {\r\n this.calculateAndReportSecurityLevel();\r\n }, 500);\r\n }\r\n\r\n // Method for enabling Stage 4 functions (maximum safety)\r\n enableStage4Security() {\r\n this._secureLog('info', '\uD83D\uDD12 Enabling Stage 4 features (maximum safety)');\r\n \r\n if (this.sessionConstraints?.hasDecoyChannels && this.isConnected() && this.isVerified) {\r\n this.securityFeatures.hasDecoyChannels = true;\r\n this.decoyChannelConfig.enabled = true;\r\n \r\n try {\r\n this.initializeDecoyChannels();\r\n } catch (error) {\r\n this._secureLog('warn', '\u26A0\uFE0F Decoy channels initialization failed:', { details: error.message });\r\n this.securityFeatures.hasDecoyChannels = false;\r\n this.decoyChannelConfig.enabled = false;\r\n }\r\n }\r\n \r\n // Full anti-fingerprinting for maximum sessions\r\n if (this.sessionConstraints?.hasAntiFingerprinting) {\r\n this.antiFingerprintingConfig.randomizeSizes = true;\r\n this.antiFingerprintingConfig.maskPatterns = true;\r\n this.antiFingerprintingConfig.useRandomHeaders = false; \r\n }\r\n \r\n this.notifySecurityUpgrade(4);\r\n setTimeout(() => {\r\n this.calculateAndReportSecurityLevel();\r\n }, 500);\r\n }\r\n\r\n forceSecurityUpdate() {\r\n setTimeout(() => {\r\n this.calculateAndReportSecurityLevel();\r\n this.notifySecurityUpdate();\r\n }, 100);\r\n }\r\n\r\n // Method for getting security status\r\n getSecurityStatus() {\r\n const activeFeatures = Object.entries(this.securityFeatures)\r\n .filter(([key, value]) => value === true)\r\n .map(([key]) => key);\r\n \r\n const stage = 4; // Maximum security stage\r\n \r\n return {\r\n stage: stage,\r\n securityLevel: 'maximum',\r\n activeFeatures: activeFeatures,\r\n totalFeatures: Object.keys(this.securityFeatures).length,\r\n activeFeaturesCount: activeFeatures.length,\r\n activeFeaturesNames: activeFeatures,\r\n sessionConstraints: this.sessionConstraints\r\n };\r\n }\r\n\r\n // Method to notify UI about security update\r\n notifySecurityUpgrade(stage) {\r\n const stageNames = {\r\n 1: 'Basic Enhanced',\r\n 2: 'Medium Security', \r\n 3: 'High Security',\r\n 4: 'Maximum Security'\r\n };\r\n \r\n const message = `\uD83D\uDD12 Security upgraded to Stage ${stage}: ${stageNames[stage]}`;\r\n \r\n // Avoid duplicate security-upgrade notifications\r\n if (!this.securityUpgradeNotificationSent || this.lastSecurityUpgradeStage !== stage) {\r\n this.securityUpgradeNotificationSent = true;\r\n this.lastSecurityUpgradeStage = stage;\r\n \r\n // Notify local UI via onMessage\r\n if (this.onMessage) {\r\n this.deliverMessageToUI(message, 'system');\r\n }\r\n }\r\n\r\n // Send security upgrade notification to peer via WebRTC\r\n if (this.dataChannel && this.dataChannel.readyState === 'open') {\r\n try {\r\n const securityNotification = {\r\n type: 'security_upgrade',\r\n stage: stage,\r\n stageName: stageNames[stage],\r\n message: message,\r\n timestamp: Date.now()\r\n };\r\n \r\n this._secureLog('debug', '\uD83D\uDD12 Sending security upgrade notification to peer:', { type: securityNotification.type, stage: securityNotification.stage });\r\n this.dataChannel.send(JSON.stringify(securityNotification));\r\n } catch (error) {\r\n this._secureLog('warn', '\u26A0\uFE0F Failed to send security upgrade notification to peer:', { details: error.message });\r\n }\r\n }\r\n\r\n const status = this.getSecurityStatus();\r\n }\r\n\r\n async calculateAndReportSecurityLevel() {\r\n try {\r\n if (!window.EnhancedSecureCryptoUtils) {\r\n this._secureLog('warn', '\u26A0\uFE0F EnhancedSecureCryptoUtils not available for security calculation');\r\n return null;\r\n }\r\n\r\n if (!this.isConnected() || !this.isVerified || !this.encryptionKey || !this.macKey) {\r\n this._secureLog('debug', '\u26A0\uFE0F WebRTC not ready for security calculation', {\r\n connected: this.isConnected(),\r\n verified: this.isVerified,\r\n hasEncryptionKey: !!this.encryptionKey,\r\n hasMacKey: !!this.macKey\r\n });\r\n return null;\r\n }\r\n\r\n this._secureLog('debug', '\uD83D\uDD0D Calculating real security level', {\r\n managerState: 'ready',\r\n hasAllKeys: !!(this.encryptionKey && this.macKey && this.metadataKey)\r\n });\r\n \r\n const securityData = await window.EnhancedSecureCryptoUtils.calculateSecurityLevel(this);\r\n \r\n this._secureLog('info', 'Real security level calculated', {\r\n hasSecurityLevel: !!securityData.level,\r\n scoreRange: securityData.score > 80 ? 'high' : securityData.score > 50 ? 'medium' : 'low',\r\n checksRatio: `${securityData.passedChecks}/${securityData.totalChecks}`,\r\n isRealCalculation: securityData.isRealData\r\n });\r\n\r\n this.lastSecurityCalculation = securityData;\r\n\r\n document.dispatchEvent(new CustomEvent('real-security-calculated', {\r\n detail: {\r\n securityData: securityData,\r\n webrtcManager: this,\r\n timestamp: Date.now(),\r\n source: 'calculateAndReportSecurityLevel'\r\n }\r\n }));\r\n\r\n if (securityData.isRealData && this.onMessage) {\r\n if (!this.securityCalculationNotificationSent || this.lastSecurityCalculationLevel !== securityData.level) {\r\n this.securityCalculationNotificationSent = true;\r\n this.lastSecurityCalculationLevel = securityData.level;\r\n \r\n const message = `Security Level: ${securityData.level} (${securityData.score}%) - ${securityData.passedChecks}/${securityData.totalChecks} checks passed`;\r\n this.deliverMessageToUI(message, 'system');\r\n }\r\n }\r\n \r\n return securityData;\r\n \r\n } catch (error) {\r\n this._secureLog('error', 'Failed to calculate real security level', {\r\n errorType: error.constructor.name\r\n });\r\n return null;\r\n }\r\n }\r\n\r\n // ============================================\r\n // AUTOMATIC STEP-BY-STEP SWITCHING ON\r\n // ============================================\r\n\r\n // Method for automatic feature enablement with stability check\r\n async autoEnableSecurityFeatures() {\r\n this._secureLog('info', 'Starting graduated security activation - all features enabled');\r\n\r\n const checkStability = () => {\r\n const isStable = this.isConnected() && \r\n this.isVerified && \r\n this.connectionAttempts === 0 && \r\n this.messageQueue.length === 0 &&\r\n this.peerConnection?.connectionState === 'connected';\r\n return isStable;\r\n };\r\n \r\n await this.calculateAndReportSecurityLevel();\r\n this.notifySecurityUpgrade(1);\r\n \r\n // Enable all security stages progressively\r\n setTimeout(async () => {\r\n if (checkStability()) {\r\n this.enableStage2Security();\r\n await this.calculateAndReportSecurityLevel(); \r\n \r\n setTimeout(async () => {\r\n if (checkStability()) {\r\n this.enableStage3Security();\r\n await this.calculateAndReportSecurityLevel();\r\n \r\n setTimeout(async () => {\r\n if (checkStability()) {\r\n this.enableStage4Security();\r\n await this.calculateAndReportSecurityLevel();\r\n }\r\n }, 20000);\r\n }\r\n }, 15000);\r\n }\r\n }, 10000);\r\n }\r\n\r\n // ============================================\r\n // CONNECTION MANAGEMENT WITH ENHANCED SECURITY\r\n // ============================================\r\n\r\n async establishConnection() {\r\n try {\r\n // Initialize enhanced security features\r\n await this.initializeEnhancedSecurity();\r\n \r\n // Start fake traffic generation\r\n if (this.fakeTrafficConfig.enabled) {\r\n this.startFakeTrafficGeneration();\r\n }\r\n \r\n // Initialize decoy channels\r\n if (this.decoyChannelConfig.enabled) {\r\n this.initializeDecoyChannels();\r\n }\r\n \r\n } catch (error) {\r\n this._secureLog('error', '\u274C Failed to establish enhanced connection:', { errorType: error?.constructor?.name || 'Unknown' });\r\n // Do not close the connection on setup errors \u2014 just log and continue\r\n this.onStatusChange('disconnected');\r\n throw error;\r\n }\r\n }\r\n\r\n disconnect() {\r\n try {\r\n \r\n // Cleanup file transfer system\r\n if (this.fileTransferSystem) {\r\n this.fileTransferSystem.cleanup();\r\n this.fileTransferSystem = null;\r\n }\r\n \r\n // Stop fake traffic generation\r\n this.stopFakeTrafficGeneration();\r\n \r\n // Stop decoy traffic\r\n for (const [channelName, timer] of this.decoyTimers.entries()) {\r\n clearTimeout(timer);\r\n }\r\n this.decoyTimers.clear();\r\n \r\n // Close decoy channels\r\n for (const [channelName, channel] of this.decoyChannels.entries()) {\r\n if (channel.readyState === 'open') {\r\n channel.close();\r\n }\r\n }\r\n this.decoyChannels.clear();\r\n \r\n // Clean up packet buffer\r\n this.packetBuffer.clear();\r\n \r\n // Clean up chunk queue\r\n this.chunkQueue = [];\r\n \r\n // Wipe ephemeral keys for PFS on disconnect\r\n this._wipeEphemeralKeys();\r\n \r\n // Hard wipe old keys for PFS\r\n this._hardWipeOldKeys();\r\n\r\n // Clear verification states\r\n this._clearVerificationStates();\r\n\r\n } catch (error) {\r\n this._secureLog('error', '\u274C Error during enhanced disconnect:', { errorType: error?.constructor?.name || 'Unknown' });\r\n }\r\n }\r\n\r\n /**\r\n * Clear all verification states and data\r\n * Called when verification is rejected or connection is terminated\r\n */\r\n _clearVerificationStates() {\r\n try {\r\n \r\n // Clear verification states\r\n this.localVerificationConfirmed = false;\r\n this.remoteVerificationConfirmed = false;\r\n this.bothVerificationsConfirmed = false;\r\n this.isVerified = false;\r\n this.verificationCode = null;\r\n this.pendingSASCode = null;\r\n \r\n // Clear key fingerprint and connection data\r\n this.keyFingerprint = null;\r\n this.expectedDTLSFingerprint = null;\r\n this.connectionId = null;\r\n \r\n // Clear processed message IDs\r\n this.processedMessageIds.clear();\r\n \r\n // Reset notification flags\r\n this.verificationNotificationSent = false;\r\n this.verificationInitiationSent = false;\r\n \r\n } catch (error) {\r\n this._secureLog('error', '\u274C Error clearing verification states:', { errorType: error?.constructor?.name || 'Unknown' });\r\n }\r\n }\r\n\r\n // Start periodic cleanup for rate limiting and security\r\n startPeriodicCleanup() {\r\n // Cleanup moved to unified scheduler\r\n this._secureLog('info', '\uD83D\uDD27 Periodic cleanup moved to unified scheduler');\r\n }\r\n\r\n // Calculate current security level with real verification\r\n async calculateSecurityLevel() {\r\n return await window.EnhancedSecureCryptoUtils.calculateSecurityLevel(this);\r\n }\r\n\r\n // PFS: Check if key rotation is needed\r\n shouldRotateKeys() {\r\n if (!this.isConnected() || !this.isVerified) {\r\n return false;\r\n }\r\n \r\n const now = Date.now();\r\n const timeSinceLastRotation = now - this.lastKeyRotation;\r\n \r\n // Rotate keys every 5 minutes or after 100 messages\r\n return timeSinceLastRotation > this.keyRotationInterval || \r\n this.messageCounter % 100 === 0;\r\n }\r\n\r\n // PFS: Rotate encryption keys for Perfect Forward Secrecy\r\n async rotateKeys() {\r\n return this._withMutex('keyOperation', async (operationId) => {\r\n this._secureLog('info', '\uD83D\uDD04 Starting key rotation with mutex', {\r\n operationId: operationId\r\n });\r\n \r\n // Validate state inside the critical section\r\n if (!this.isConnected() || !this.isVerified) {\r\n this._secureLog('warn', ' Key rotation aborted - connection not ready', {\r\n operationId: operationId,\r\n isConnected: this.isConnected(),\r\n isVerified: this.isVerified\r\n });\r\n return false;\r\n }\r\n \r\n // Ensure rotation is not already in progress\r\n if (this._keySystemState.isRotating) {\r\n this._secureLog('warn', ' Key rotation already in progress', {\r\n operationId: operationId\r\n });\r\n return false;\r\n }\r\n \r\n try {\r\n // Set rotation flag\r\n this._keySystemState.isRotating = true;\r\n this._keySystemState.lastOperation = 'rotation';\r\n this._keySystemState.lastOperationTime = Date.now();\r\n \r\n // Send rotation signal to peer\r\n const rotationSignal = {\r\n type: 'key_rotation_signal',\r\n newVersion: this.currentKeyVersion + 1,\r\n timestamp: Date.now(),\r\n operationId: operationId\r\n };\r\n \r\n if (this.dataChannel && this.dataChannel.readyState === 'open') {\r\n this.dataChannel.send(JSON.stringify(rotationSignal));\r\n } else {\r\n throw new Error('Data channel not ready for key rotation');\r\n }\r\n \r\n // Perform hard wipe of old keys for real PFS\r\n this._hardWipeOldKeys();\r\n \r\n // Wait for peer confirmation\r\n return new Promise((resolve) => {\r\n this.pendingRotation = {\r\n newVersion: this.currentKeyVersion + 1,\r\n operationId: operationId,\r\n resolve: resolve,\r\n timeout: setTimeout(() => {\r\n this._secureLog('error', ' Key rotation timeout', {\r\n operationId: operationId\r\n });\r\n this._keySystemState.isRotating = false;\r\n this.pendingRotation = null;\r\n resolve(false);\r\n }, 10000) // 10 seconds timeout\r\n };\r\n });\r\n \r\n } catch (error) {\r\n this._secureLog('error', ' Key rotation failed in critical section', {\r\n operationId: operationId,\r\n errorType: error.constructor.name\r\n });\r\n this._keySystemState.isRotating = false;\r\n return false;\r\n }\r\n }, 10000); // 10 seconds timeout for the entire operation\r\n }\r\n\r\n // Real PFS - Clean up old keys with hard wipe\r\n cleanupOldKeys() {\r\n const now = Date.now();\r\n const maxKeyAge = EnhancedSecureWebRTCManager.LIMITS.MAX_KEY_AGE; // 15 minutes - keys older than this are deleted\r\n \r\n let wipedKeysCount = 0;\r\n \r\n for (const [version, keySet] of this.oldKeys.entries()) {\r\n if (now - keySet.timestamp > maxKeyAge) {\r\n // Hard wipe old keys before deletion\r\n if (keySet.encryptionKey) {\r\n this._secureWipeMemory(keySet.encryptionKey, 'pfs_cleanup_wipe');\r\n }\r\n if (keySet.macKey) {\r\n this._secureWipeMemory(keySet.macKey, 'pfs_cleanup_wipe');\r\n }\r\n if (keySet.metadataKey) {\r\n this._secureWipeMemory(keySet.metadataKey, 'pfs_cleanup_wipe');\r\n }\r\n \r\n // Clear references\r\n keySet.encryptionKey = null;\r\n keySet.macKey = null;\r\n keySet.metadataKey = null;\r\n keySet.keyFingerprint = null;\r\n \r\n this.oldKeys.delete(version);\r\n wipedKeysCount++;\r\n \r\n this._secureLog('info', '\uD83E\uDDF9 Old PFS keys hard wiped and cleaned up', {\r\n version: version,\r\n age: Math.round((now - keySet.timestamp) / 1000) + 's',\r\n timestamp: Date.now()\r\n });\r\n }\r\n }\r\n \r\n if (wipedKeysCount > 0) {\r\n this._secureLog('info', `PFS cleanup completed: ${wipedKeysCount} keys hard wiped`, {\r\n timestamp: Date.now()\r\n });\r\n }\r\n }\r\n\r\n // PFS: Get keys for specific version (for decryption)\r\n getKeysForVersion(version) {\r\n // First, we check the old keys (including version 0).\r\n const oldKeySet = this.oldKeys.get(version);\r\n if (oldKeySet && oldKeySet.encryptionKey && oldKeySet.macKey && oldKeySet.metadataKey) {\r\n return {\r\n encryptionKey: oldKeySet.encryptionKey,\r\n macKey: oldKeySet.macKey,\r\n metadataKey: oldKeySet.metadataKey\r\n };\r\n }\r\n \r\n // If this is the current version, return the current keys.\r\n if (version === this.currentKeyVersion) {\r\n if (this.encryptionKey && this.macKey && this.metadataKey) {\r\n return {\r\n encryptionKey: this.encryptionKey,\r\n macKey: this.macKey,\r\n metadataKey: this.metadataKey\r\n };\r\n }\r\n }\r\n \r\n window.EnhancedSecureCryptoUtils.secureLog.log('error', 'No valid keys found for version', {\r\n requestedVersion: version,\r\n currentVersion: this.currentKeyVersion,\r\n availableVersions: Array.from(this.oldKeys.keys())\r\n });\r\n \r\n return null;\r\n }\r\n\r\n createPeerConnection() {\r\n const config = {\r\n iceServers: [\r\n { urls: 'stun:stun.l.google.com:19302' },\r\n { urls: 'stun:stun1.l.google.com:19302' },\r\n { urls: 'stun:stun2.l.google.com:19302' },\r\n { urls: 'stun:stun3.l.google.com:19302' },\r\n { urls: 'stun:stun4.l.google.com:19302' }\r\n ],\r\n iceCandidatePoolSize: 10,\r\n bundlePolicy: 'balanced'\r\n };\r\n\r\n this.peerConnection = new RTCPeerConnection(config);\r\n\r\n this.peerConnection.onconnectionstatechange = () => {\r\n const state = this.peerConnection.connectionState;\r\n \r\n if (state === 'connected' && !this.isVerified) {\r\n this.onStatusChange('verifying');\r\n } else if (state === 'connected' && this.isVerified) {\r\n this.onStatusChange('connected');\r\n } else if (state === 'disconnected' || state === 'closed') {\r\n // If this is an intentional disconnect, clear immediately.\r\n if (this.intentionalDisconnect) {\r\n this.onStatusChange('disconnected');\r\n setTimeout(() => this.disconnect(), 100);\r\n } else {\r\n this.onStatusChange('disconnected');\r\n // Clear verification states on unexpected disconnect\r\n this._clearVerificationStates();\r\n }\r\n } else if (state === 'failed') {\r\n // Do not auto-reconnect to avoid closing the session on errors\r\n this.onStatusChange('disconnected');\r\n\r\n } else {\r\n this.onStatusChange(state);\r\n }\r\n };\r\n\r\n this.peerConnection.ondatachannel = (event) => {\r\n \r\n // CRITICAL: Store the received data channel\r\n if (event.channel.label === 'securechat') {\r\n this.dataChannel = event.channel;\r\n this.setupDataChannel(event.channel);\r\n } else {\r\n // Handle additional channels (heartbeat, etc.)\r\n if (event.channel.label === 'heartbeat') {\r\n this.heartbeatChannel = event.channel;\r\n }\r\n }\r\n };\r\n }\r\n\r\n setupDataChannel(channel) {\r\n\r\n this.dataChannel = channel;\r\n\r\n this.dataChannel.onopen = async () => {\r\n // Configure backpressure for large transfers\r\n try {\r\n if (this.dataChannel && typeof this.dataChannel.bufferedAmountLowThreshold === 'number') {\r\n // 1 MB threshold for bufferedamountlow event\r\n this.dataChannel.bufferedAmountLowThreshold = 1024 * 1024;\r\n }\r\n } catch (e) {\r\n // ignore\r\n }\r\n \r\n try {\r\n await this.establishConnection();\r\n\r\n this.initializeFileTransfer();\r\n \r\n } catch (error) {\r\n this._secureLog('error', 'Error in establishConnection:', { errorType: error?.constructor?.name || 'Unknown' });\r\n // Continue despite errors\r\n }\r\n \r\n // CRITICAL: Send pending SAS code if available\r\n if (this.pendingSASCode && this.dataChannel && this.dataChannel.readyState === 'open') {\r\n try {\r\n const sasPayload = {\r\n type: 'sas_code',\r\n data: {\r\n code: this.pendingSASCode,\r\n timestamp: Date.now(),\r\n verificationMethod: 'SAS',\r\n securityLevel: 'MITM_PROTECTION_REQUIRED'\r\n }\r\n };\r\n this.dataChannel.send(JSON.stringify(sasPayload));\r\n this.pendingSASCode = null; // Clear after sending\r\n } catch (error) {\r\n }\r\n } else if (this.pendingSASCode) {\r\n }\r\n \r\n if (this.isVerified) {\r\n this.onStatusChange('connected');\r\n this.processMessageQueue();\r\n \r\n setTimeout(async () => {\r\n await this.calculateAndReportSecurityLevel();\r\n this.autoEnableSecurityFeatures();\r\n this.notifySecurityUpdate();\r\n }, 500);\r\n } else {\r\n this.onStatusChange('verifying');\r\n this.initiateVerification();\r\n }\r\n this.startHeartbeat();\r\n };\r\n\r\n this.dataChannel.onclose = () => {\r\n if (!this.intentionalDisconnect) {\r\n this.onStatusChange('disconnected');\r\n // Clear verification states on data channel close\r\n this._clearVerificationStates();\r\n \r\n if (!this.connectionClosedNotificationSent) {\r\n this.connectionClosedNotificationSent = true;\r\n this.deliverMessageToUI('\uD83D\uDD0C Enhanced secure connection closed. Check connection status.', 'system');\r\n }\r\n } else {\r\n this.onStatusChange('disconnected');\r\n // Clear verification states on intentional disconnect\r\n this._clearVerificationStates();\r\n \r\n if (!this.connectionClosedNotificationSent) {\r\n this.connectionClosedNotificationSent = true;\r\n this.deliverMessageToUI('\uD83D\uDD0C Enhanced secure connection closed', 'system');\r\n }\r\n }\r\n \r\n // Wipe ephemeral keys when session ends for PFS\r\n this._wipeEphemeralKeys();\r\n \r\n this.stopHeartbeat();\r\n this.isVerified = false;\r\n };\r\n\r\n // FIX 2: Remove mutex entirely from message processing path\r\n this.dataChannel.onmessage = async (event) => {\r\n try {\r\n\r\n // IMPORTANT: Process ALL messages WITHOUT mutex\r\n if (typeof event.data === 'string') {\r\n try {\r\n const parsed = JSON.parse(event.data);\r\n\r\n \r\n // ============================================\r\n // CRITICAL: FILE MESSAGES (WITHOUT MUTEX)\r\n // ============================================\r\n \r\n const fileMessageTypes = [\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 ];\r\n \r\n if (parsed.type && fileMessageTypes.includes(parsed.type)) {\r\n\r\n if (!this.fileTransferSystem) {\r\n try {\r\n if (this.isVerified && this.dataChannel && this.dataChannel.readyState === 'open') {\r\n this.initializeFileTransfer();\r\n\r\n let attempts = 0;\r\n const maxAttempts = 30;\r\n while (!this.fileTransferSystem && attempts < maxAttempts) {\r\n await new Promise(resolve => setTimeout(resolve, 100));\r\n attempts++;\r\n }\r\n }\r\n } catch (initError) {\r\n this._secureLog('error', 'Failed to initialize file transfer system for receiver:', { errorType: initError?.constructor?.name || 'Unknown' });\r\n }\r\n }\r\n\r\n if (this.fileTransferSystem) {\r\n await this.fileTransferSystem.handleFileMessage(parsed);\r\n return;\r\n }\r\n // Attempt lazy initialization on receiver side\r\n this._secureLog('warn', '\u26A0\uFE0F File transfer system not ready, attempting lazy init...');\r\n try {\r\n await this._ensureFileTransferReady();\r\n if (this.fileTransferSystem) {\r\n await this.fileTransferSystem.handleFileMessage(parsed);\r\n return;\r\n }\r\n } catch (e) {\r\n this._secureLog('error', 'Lazy init of file transfer failed:', { errorType: e?.message || e?.constructor?.name || 'Unknown' });\r\n }\r\n this._secureLog('error', 'No file transfer system available for:', { errorType: parsed.type?.constructor?.name || 'Unknown' });\r\n return; // IMPORTANT: Do not process further\r\n }\r\n \r\n // ============================================\r\n // SYSTEM MESSAGES (WITHOUT MUTEX)\r\n // ============================================\r\n \r\n if (parsed.type && ['heartbeat', 'verification', 'verification_response', 'verification_confirmed', 'verification_both_confirmed', 'sas_code', 'peer_disconnect', 'security_upgrade'].includes(parsed.type)) {\r\n this.handleSystemMessage(parsed);\r\n return;\r\n }\r\n \r\n // ============================================\r\n // REGULAR USER MESSAGES (WITHOUT MUTEX)\r\n // ============================================\r\n \r\n if (parsed.type === 'message' && parsed.data) {\r\n if (this.onMessage) {\r\n this.deliverMessageToUI(parsed.data, 'received');\r\n }\r\n return;\r\n }\r\n \r\n // ============================================\r\n // ENHANCED MESSAGES (WITHOUT MUTEX)\r\n // ============================================\r\n \r\n if (parsed.type === 'enhanced_message' && parsed.data) {\r\n await this._processEnhancedMessageWithoutMutex(parsed);\r\n return;\r\n }\r\n \r\n \r\n } catch (jsonError) {\r\n // Not JSON \u2014 treat as regular text message\r\n if (this.onMessage) {\r\n this.deliverMessageToUI(event.data, 'received');\r\n }\r\n return;\r\n }\r\n } else if (event.data instanceof ArrayBuffer) {\r\n await this._processBinaryDataWithoutMutex(event.data);\r\n } else {\r\n }\r\n \r\n } catch (error) {\r\n this._secureLog('error', 'Failed to process message in onmessage:', { errorType: error?.constructor?.name || 'Unknown' });\r\n }\r\n };\r\n }\r\n // FIX 4: New method for processing binary data WITHOUT mutex\r\n async _processBinaryDataWithoutMutex(data) {\r\n try {\r\n \r\n // Apply security layers WITHOUT mutex\r\n let processedData = data;\r\n \r\n // Nested Encryption Removal (if enabled)\r\n if (this.securityFeatures.hasNestedEncryption && \r\n this.nestedEncryptionKey && \r\n processedData instanceof ArrayBuffer &&\r\n processedData.byteLength > 12) {\r\n \r\n try {\r\n processedData = await this.removeNestedEncryption(processedData);\r\n } catch (error) {\r\n this._secureLog('warn', 'Nested decryption failed, continuing with original data');\r\n }\r\n }\r\n \r\n // Packet Padding Removal (if enabled)\r\n if (this.securityFeatures.hasPacketPadding && processedData instanceof ArrayBuffer) {\r\n try {\r\n processedData = this.removePacketPadding(processedData);\r\n } catch (error) {\r\n this._secureLog('warn', 'Packet padding removal failed, continuing with original data');\r\n }\r\n }\r\n \r\n // Anti-Fingerprinting Removal (if enabled)\r\n if (this.securityFeatures.hasAntiFingerprinting && processedData instanceof ArrayBuffer) {\r\n try {\r\n processedData = this.removeAntiFingerprinting(processedData);\r\n } catch (error) {\r\n this._secureLog('warn', 'Anti-fingerprinting removal failed, continuing with original data');\r\n }\r\n }\r\n \r\n // Convert to text\r\n if (processedData instanceof ArrayBuffer) {\r\n const textData = new TextDecoder().decode(processedData);\r\n \r\n // Check for fake messages\r\n try {\r\n const content = JSON.parse(textData);\r\n if (content.type === 'fake' || content.isFakeTraffic === true) {\r\n return;\r\n }\r\n } catch (e) {\r\n // Not JSON \u2014 fine for plain text\r\n }\r\n \r\n // Deliver message to user\r\n if (this.onMessage) {\r\n this.deliverMessageToUI(textData, 'received');\r\n }\r\n }\r\n \r\n } catch (error) {\r\n this._secureLog('error', 'Error processing binary data:', { errorType: error?.constructor?.name || 'Unknown' });\r\n }\r\n }\r\n // FIX 3: New method for processing enhanced messages WITHOUT mutex\r\n async _processEnhancedMessageWithoutMutex(parsedMessage) {\r\n try {\r\n \r\n if (!this.encryptionKey || !this.macKey || !this.metadataKey) {\r\n this._secureLog('error', 'Missing encryption keys for enhanced message');\r\n return;\r\n }\r\n \r\n const decryptedResult = await window.EnhancedSecureCryptoUtils.decryptMessage(\r\n parsedMessage.data,\r\n this.encryptionKey,\r\n this.macKey,\r\n this.metadataKey\r\n );\r\n \r\n if (decryptedResult && decryptedResult.message) {\r\n \r\n // Try parsing JSON and showing nested text if it's a chat message\r\n try {\r\n const decryptedContent = JSON.parse(decryptedResult.message);\r\n if (decryptedContent.type === 'fake' || decryptedContent.isFakeTraffic === true) {\r\n return;\r\n }\r\n if (decryptedContent && decryptedContent.type === 'message' && typeof decryptedContent.data === 'string') {\r\n if (this.onMessage) {\r\n this.deliverMessageToUI(decryptedContent.data, 'received');\r\n }\r\n return;\r\n }\r\n } catch (e) {\r\n // Not JSON \u2014 fine for plain text\r\n }\r\n \r\n // Otherwise pass as-is\r\n if (this.onMessage) {\r\n this.deliverMessageToUI(decryptedResult.message, 'received');\r\n }\r\n } else {\r\n this._secureLog('warn', 'No message content in decrypted result');\r\n }\r\n \r\n } catch (error) {\r\n this._secureLog('error', 'Error processing enhanced message:', { errorType: error?.constructor?.name || 'Unknown' });\r\n }\r\n }\r\n /**\r\n * Creates a unique ID for an operation\r\n */\r\n _generateOperationId() {\r\n return `op_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;\r\n }\r\n\r\n /**\r\n * Atomic mutex acquisition with enhanced race condition protection\r\n */\r\n async _acquireMutex(mutexName, operationId, timeout = 5000) {\r\n // Build correct mutex property name\r\n const mutexPropertyName = `_${mutexName}Mutex`;\r\n const mutex = this[mutexPropertyName];\r\n \r\n if (!mutex) {\r\n this._secureLog('error', `Unknown mutex: ${mutexName}`, {\r\n mutexPropertyName: mutexPropertyName,\r\n availableMutexes: this._getAvailableMutexes(),\r\n operationId: operationId\r\n });\r\n throw new Error(`Unknown mutex: ${mutexName}. Available: ${this._getAvailableMutexes().join(', ')}`);\r\n }\r\n \r\n // Validate operation ID\r\n if (!operationId || typeof operationId !== 'string') {\r\n throw new Error('Invalid operation ID for mutex acquisition');\r\n }\r\n \r\n return new Promise((resolve, reject) => {\r\n // Atomic lock attempt with immediate state check\r\n const attemptLock = () => {\r\n // Check if mutex is already locked by this operation\r\n if (mutex.lockId === operationId) {\r\n this._secureLog('warn', `Mutex '${mutexName}' already locked by same operation`, {\r\n operationId: operationId\r\n });\r\n resolve();\r\n return;\r\n }\r\n \r\n // Atomic check and lock operation\r\n if (!mutex.locked) {\r\n // Set lock state atomically\r\n mutex.locked = true;\r\n mutex.lockId = operationId;\r\n mutex.lockTime = Date.now();\r\n \r\n this._secureLog('debug', `Mutex '${mutexName}' acquired atomically`, {\r\n operationId: operationId,\r\n lockTime: mutex.lockTime\r\n });\r\n \r\n // Set timeout for automatic release with enhanced validation\r\n mutex.lockTimeout = setTimeout(() => {\r\n // Enhanced timeout handling with state validation\r\n this._handleMutexTimeout(mutexName, operationId, timeout);\r\n }, timeout);\r\n \r\n resolve();\r\n } else {\r\n // Add to queue with timeout\r\n const queueItem = { \r\n resolve, \r\n reject, \r\n operationId,\r\n timestamp: Date.now(),\r\n timeout: setTimeout(() => {\r\n // Remove from queue on timeout\r\n const index = mutex.queue.findIndex(item => item.operationId === operationId);\r\n if (index !== -1) {\r\n mutex.queue.splice(index, 1);\r\n reject(new Error(`Mutex acquisition timeout for '${mutexName}'`));\r\n }\r\n }, timeout)\r\n };\r\n \r\n mutex.queue.push(queueItem);\r\n \r\n this._secureLog('debug', `Operation queued for mutex '${mutexName}'`, {\r\n operationId: operationId,\r\n queueLength: mutex.queue.length,\r\n currentLockId: mutex.lockId\r\n });\r\n }\r\n };\r\n \r\n // Execute lock attempt immediately\r\n attemptLock();\r\n });\r\n }\r\n\r\n /**\r\n * Enhanced mutex release with strict validation and error handling\r\n */\r\n _releaseMutex(mutexName, operationId) {\r\n // Validate input parameters\r\n if (!mutexName || typeof mutexName !== 'string') {\r\n throw new Error('Invalid mutex name provided for release');\r\n }\r\n \r\n if (!operationId || typeof operationId !== 'string') {\r\n throw new Error('Invalid operation ID provided for mutex release');\r\n }\r\n \r\n // Build correct mutex property name\r\n const mutexPropertyName = `_${mutexName}Mutex`;\r\n const mutex = this[mutexPropertyName];\r\n \r\n if (!mutex) {\r\n this._secureLog('error', `Unknown mutex for release: ${mutexName}`, {\r\n mutexPropertyName: mutexPropertyName,\r\n availableMutexes: this._getAvailableMutexes(),\r\n operationId: operationId\r\n });\r\n throw new Error(`Unknown mutex for release: ${mutexName}`);\r\n }\r\n \r\n // Strict validation of lock ownership\r\n if (mutex.lockId !== operationId) {\r\n this._secureLog('error', `CRITICAL: Invalid mutex release attempt - potential race condition`, {\r\n mutexName: mutexName,\r\n expectedLockId: mutex.lockId,\r\n providedOperationId: operationId,\r\n mutexState: {\r\n locked: mutex.locked,\r\n lockTime: mutex.lockTime,\r\n queueLength: mutex.queue.length\r\n }\r\n });\r\n \r\n // Throw error instead of silent failure\r\n throw new Error(`Invalid mutex release attempt for '${mutexName}': expected '${mutex.lockId}', got '${operationId}'`);\r\n }\r\n \r\n // Validate mutex is actually locked\r\n if (!mutex.locked) {\r\n this._secureLog('error', `CRITICAL: Attempting to release unlocked mutex`, {\r\n mutexName: mutexName,\r\n operationId: operationId,\r\n mutexState: {\r\n locked: mutex.locked,\r\n lockId: mutex.lockId,\r\n lockTime: mutex.lockTime\r\n }\r\n });\r\n throw new Error(`Attempting to release unlocked mutex: ${mutexName}`);\r\n }\r\n \r\n try {\r\n // Clear timeout first\r\n if (mutex.lockTimeout) {\r\n clearTimeout(mutex.lockTimeout);\r\n mutex.lockTimeout = null;\r\n }\r\n \r\n // Calculate lock duration for monitoring\r\n const lockDuration = mutex.lockTime ? Date.now() - mutex.lockTime : 0;\r\n \r\n // Atomic release with state validation\r\n mutex.locked = false;\r\n mutex.lockId = null;\r\n mutex.lockTime = null;\r\n \r\n this._secureLog('debug', `Mutex released successfully: ${mutexName}`, {\r\n operationId: operationId,\r\n lockDuration: lockDuration,\r\n queueLength: mutex.queue.length\r\n });\r\n \r\n // Process next in queue with enhanced error handling\r\n this._processNextInQueue(mutexName);\r\n \r\n } catch (error) {\r\n // If queue processing fails, ensure mutex is still released\r\n this._secureLog('error', `Error during mutex release queue processing`, {\r\n mutexName: mutexName,\r\n operationId: operationId,\r\n errorType: error.constructor.name,\r\n errorMessage: error.message\r\n });\r\n \r\n // Ensure mutex is released even if queue processing fails\r\n mutex.locked = false;\r\n mutex.lockId = null;\r\n mutex.lockTime = null;\r\n mutex.lockTimeout = null;\r\n \r\n throw error;\r\n }\r\n }\r\n\r\n /**\r\n * Enhanced queue processing with comprehensive error handling\r\n */\r\n _processNextInQueue(mutexName) {\r\n const mutex = this[`_${mutexName}Mutex`];\r\n \r\n if (!mutex) {\r\n this._secureLog('error', `Mutex not found for queue processing: ${mutexName}`);\r\n return;\r\n }\r\n \r\n if (mutex.queue.length === 0) {\r\n return;\r\n }\r\n \r\n // Validate mutex state before processing queue\r\n if (mutex.locked) {\r\n this._secureLog('warn', `Mutex '${mutexName}' is still locked, skipping queue processing`, {\r\n lockId: mutex.lockId,\r\n queueLength: mutex.queue.length\r\n });\r\n return;\r\n }\r\n \r\n // Get next item from queue atomically with validation\r\n const nextItem = mutex.queue.shift();\r\n \r\n if (!nextItem) {\r\n this._secureLog('warn', `Empty queue item for mutex '${mutexName}'`);\r\n return;\r\n }\r\n \r\n // Validate queue item structure\r\n if (!nextItem.operationId || !nextItem.resolve || !nextItem.reject) {\r\n this._secureLog('error', `Invalid queue item structure for mutex '${mutexName}'`, {\r\n hasOperationId: !!nextItem.operationId,\r\n hasResolve: !!nextItem.resolve,\r\n hasReject: !!nextItem.reject\r\n });\r\n return;\r\n }\r\n \r\n try {\r\n // Clear timeout for this item\r\n if (nextItem.timeout) {\r\n clearTimeout(nextItem.timeout);\r\n }\r\n \r\n // Attempt to acquire lock for next item\r\n this._secureLog('debug', `Processing next operation in queue for mutex '${mutexName}'`, {\r\n operationId: nextItem.operationId,\r\n queueRemaining: mutex.queue.length,\r\n timestamp: Date.now()\r\n });\r\n \r\n // Retry lock acquisition for queued operation with enhanced error handling\r\n setTimeout(async () => {\r\n try {\r\n await this._acquireMutex(mutexName, nextItem.operationId, 5000);\r\n \r\n this._secureLog('debug', `Queued operation acquired mutex '${mutexName}'`, {\r\n operationId: nextItem.operationId,\r\n acquisitionTime: Date.now()\r\n });\r\n \r\n nextItem.resolve();\r\n \r\n } catch (error) {\r\n this._secureLog('error', `Queued operation failed to acquire mutex '${mutexName}'`, {\r\n operationId: nextItem.operationId,\r\n errorType: error.constructor.name,\r\n errorMessage: error.message,\r\n timestamp: Date.now()\r\n });\r\n \r\n // Reject with detailed error information\r\n nextItem.reject(new Error(`Queue processing failed for '${mutexName}': ${error.message}`));\r\n \r\n // Continue processing queue even if one item fails\r\n setTimeout(() => {\r\n this._processNextInQueue(mutexName);\r\n }, 50);\r\n }\r\n }, 10); // Small delay to prevent immediate re-acquisition\r\n \r\n } catch (error) {\r\n this._secureLog('error', `Critical error during queue processing for mutex '${mutexName}'`, {\r\n operationId: nextItem.operationId,\r\n errorType: error.constructor.name,\r\n errorMessage: error.message\r\n });\r\n \r\n // Reject the operation and continue processing\r\n try {\r\n nextItem.reject(new Error(`Queue processing critical error: ${error.message}`));\r\n } catch (rejectError) {\r\n this._secureLog('error', `Failed to reject queue item`, {\r\n originalError: error.message,\r\n rejectError: rejectError.message\r\n });\r\n }\r\n \r\n // Continue processing remaining queue items\r\n setTimeout(() => {\r\n this._processNextInQueue(mutexName);\r\n }, 100);\r\n }\r\n }\r\n\r\n _getAvailableMutexes() {\r\n const mutexes = [];\r\n const propertyNames = Object.getOwnPropertyNames(this);\r\n \r\n for (const prop of propertyNames) {\r\n if (prop.endsWith('Mutex') && prop.startsWith('_')) {\r\n // Extract mutex name without prefix/suffix\r\n const mutexName = prop.slice(1, -5); // Remove '_' prefix and 'Mutex' suffix\r\n mutexes.push(mutexName);\r\n }\r\n }\r\n \r\n return mutexes;\r\n }\r\n\r\n /**\r\n * Enhanced mutex execution with atomic operations\r\n */\r\n async _withMutex(mutexName, operation, timeout = 5000) {\r\n const operationId = this._generateOperationId();\r\n \r\n // Validate mutex system before operation\r\n if (!this._validateMutexSystem()) {\r\n this._secureLog('error', 'Mutex system not properly initialized', {\r\n operationId: operationId,\r\n mutexName: mutexName\r\n });\r\n throw new Error('Mutex system not properly initialized. Call _initializeMutexSystem() first.');\r\n }\r\n \r\n // Get mutex reference with validation\r\n const mutex = this[`_${mutexName}Mutex`];\r\n if (!mutex) {\r\n throw new Error(`Mutex '${mutexName}' not found`);\r\n }\r\n \r\n let mutexAcquired = false;\r\n \r\n try {\r\n // Atomic mutex acquisition with timeout\r\n await this._acquireMutex(mutexName, operationId, timeout);\r\n mutexAcquired = true;\r\n \r\n // Increment operation counter atomically\r\n const counterKey = `${mutexName}Operations`;\r\n if (this._operationCounters && this._operationCounters[counterKey] !== undefined) {\r\n this._operationCounters[counterKey]++;\r\n }\r\n \r\n // Execute operation with enhanced error handling\r\n const result = await operation(operationId);\r\n \r\n // Validate result before returning\r\n if (result === undefined && operation.name !== 'cleanup') {\r\n this._secureLog('warn', 'Mutex operation returned undefined result', {\r\n operationId: operationId,\r\n mutexName: mutexName,\r\n operationName: operation.name\r\n });\r\n }\r\n \r\n return result;\r\n \r\n } catch (error) {\r\n // Enhanced error logging with context\r\n this._secureLog('error', 'Error in mutex operation', {\r\n operationId: operationId,\r\n mutexName: mutexName,\r\n errorType: error.constructor.name,\r\n errorMessage: error.message,\r\n mutexAcquired: mutexAcquired,\r\n mutexState: mutex ? {\r\n locked: mutex.locked,\r\n lockId: mutex.lockId,\r\n queueLength: mutex.queue.length\r\n } : 'null'\r\n });\r\n \r\n // If this is a key operation error, trigger emergency recovery\r\n if (mutexName === 'keyOperation') {\r\n this._handleKeyOperationError(error, operationId);\r\n }\r\n \r\n // Trigger emergency unlock for critical mutex errors\r\n if (error.message.includes('timeout') || error.message.includes('race condition')) {\r\n this._emergencyUnlockAllMutexes('errorHandler');\r\n }\r\n \r\n throw error;\r\n } finally {\r\n // Always release mutex in finally block with validation\r\n if (mutexAcquired) {\r\n try {\r\n await this._releaseMutex(mutexName, operationId);\r\n \r\n // Verify mutex was properly released\r\n if (mutex.locked && mutex.lockId === operationId) {\r\n this._secureLog('error', 'Mutex release verification failed', {\r\n operationId: operationId,\r\n mutexName: mutexName\r\n });\r\n // Force release as fallback\r\n mutex.locked = false;\r\n mutex.lockId = null;\r\n mutex.lockTimeout = null;\r\n }\r\n \r\n } catch (releaseError) {\r\n this._secureLog('error', 'Error releasing mutex in finally block', {\r\n operationId: operationId,\r\n mutexName: mutexName,\r\n releaseErrorType: releaseError.constructor.name,\r\n releaseErrorMessage: releaseError.message\r\n });\r\n \r\n // Force release on error\r\n mutex.locked = false;\r\n mutex.lockId = null;\r\n mutex.lockTimeout = null;\r\n }\r\n }\r\n }\r\n }\r\n\r\n _validateMutexSystem() {\r\n const requiredMutexes = ['keyOperation', 'cryptoOperation', 'connectionOperation'];\r\n \r\n for (const mutexName of requiredMutexes) {\r\n const mutexPropertyName = `_${mutexName}Mutex`;\r\n const mutex = this[mutexPropertyName];\r\n \r\n if (!mutex || typeof mutex !== 'object') {\r\n this._secureLog('error', `Missing or invalid mutex: ${mutexName}`, {\r\n mutexPropertyName: mutexPropertyName,\r\n mutexType: typeof mutex\r\n });\r\n return false;\r\n }\r\n \r\n // Validate mutex structure\r\n const requiredProps = ['locked', 'queue', 'lockId', 'lockTimeout'];\r\n for (const prop of requiredProps) {\r\n if (!(prop in mutex)) {\r\n this._secureLog('error', `Mutex ${mutexName} missing property: ${prop}`);\r\n return false;\r\n }\r\n }\r\n }\r\n \r\n return true;\r\n }\r\n\r\n /**\r\n * Enhanced emergency recovery of the mutex system\r\n */\r\n _emergencyRecoverMutexSystem() {\r\n this._secureLog('warn', 'Emergency mutex system recovery initiated');\r\n \r\n try {\r\n // Emergency unlock all mutexes first\r\n this._emergencyUnlockAllMutexes('emergencyRecovery');\r\n \r\n // Force re-initialize the system\r\n this._initializeMutexSystem();\r\n \r\n // Validate recovery success\r\n if (!this._validateMutexSystem()) {\r\n throw new Error('Mutex system validation failed after recovery');\r\n }\r\n \r\n this._secureLog('info', 'Mutex system recovered successfully with validation');\r\n return true;\r\n \r\n } catch (error) {\r\n this._secureLog('error', 'Failed to recover mutex system', {\r\n errorType: error.constructor.name,\r\n errorMessage: error.message\r\n });\r\n \r\n // Last resort - force re-initialization\r\n try {\r\n this._initializeMutexSystem();\r\n this._secureLog('warn', 'Forced mutex system re-initialization completed');\r\n return true;\r\n } catch (reinitError) {\r\n this._secureLog('error', 'CRITICAL: Forced re-initialization also failed', {\r\n originalError: error.message,\r\n reinitError: reinitError.message\r\n });\r\n return false;\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Atomic key generation with race condition protection\r\n */\r\n async _generateEncryptionKeys() {\r\n return this._withMutex('keyOperation', async (operationId) => {\r\n this._secureLog('info', 'Generating encryption keys with atomic mutex', {\r\n operationId: operationId\r\n });\r\n \r\n // Atomic state check and update using mutex lock\r\n const currentState = this._keySystemState;\r\n \r\n // Atomic check - if already initializing, wait or fail\r\n if (currentState.isInitializing) {\r\n this._secureLog('warn', 'Key generation already in progress, waiting for completion', {\r\n operationId: operationId,\r\n lastOperation: currentState.lastOperation,\r\n lastOperationTime: currentState.lastOperationTime\r\n });\r\n \r\n // Wait for existing operation to complete\r\n let waitAttempts = 0;\r\n const maxWaitAttempts = 50; // 5 seconds max wait\r\n \r\n while (currentState.isInitializing && waitAttempts < maxWaitAttempts) {\r\n await new Promise(resolve => setTimeout(resolve, 100));\r\n waitAttempts++;\r\n }\r\n \r\n if (currentState.isInitializing) {\r\n throw new Error('Key generation timeout - operation still in progress after 5 seconds');\r\n }\r\n }\r\n \r\n // Atomic state update within mutex protection\r\n try {\r\n // Set state atomically within mutex\r\n currentState.isInitializing = true;\r\n currentState.lastOperation = 'generation';\r\n currentState.lastOperationTime = Date.now();\r\n currentState.operationId = operationId;\r\n \r\n this._secureLog('debug', 'Atomic key generation state set', {\r\n operationId: operationId,\r\n timestamp: currentState.lastOperationTime\r\n });\r\n \r\n // Generate keys with individual error handling\r\n let ecdhKeyPair = null;\r\n let ecdsaKeyPair = null;\r\n \r\n // Generate ephemeral ECDH keys for PFS\r\n try {\r\n ecdhKeyPair = await this._generateEphemeralECDHKeys();\r\n \r\n // Validate ECDH keys immediately\r\n if (!ecdhKeyPair || !ecdhKeyPair.privateKey || !ecdhKeyPair.publicKey) {\r\n throw new Error('Ephemeral ECDH key pair validation failed');\r\n }\r\n \r\n // Constant-time validation for key types\r\n if (!this._validateKeyPairConstantTime(ecdhKeyPair)) {\r\n throw new Error('Ephemeral ECDH keys are not valid CryptoKey instances');\r\n }\r\n \r\n this._secureLog('debug', 'Ephemeral ECDH keys generated and validated for PFS', {\r\n operationId: operationId,\r\n privateKeyType: ecdhKeyPair.privateKey.algorithm?.name,\r\n publicKeyType: ecdhKeyPair.publicKey.algorithm?.name,\r\n isEphemeral: true\r\n });\r\n \r\n } catch (ecdhError) {\r\n this._secureLog('error', 'Ephemeral ECDH key generation failed', {\r\n operationId: operationId,\r\n errorType: ecdhError.constructor.name\r\n });\r\n this._throwSecureError(ecdhError, 'ephemeral_ecdh_key_generation');\r\n }\r\n \r\n // Generate ECDSA keys with retry mechanism\r\n try {\r\n ecdsaKeyPair = await window.EnhancedSecureCryptoUtils.generateECDSAKeyPair();\r\n \r\n // Validate ECDSA keys immediately\r\n if (!ecdsaKeyPair || !ecdsaKeyPair.privateKey || !ecdsaKeyPair.publicKey) {\r\n throw new Error('ECDSA key pair validation failed');\r\n }\r\n \r\n // Constant-time validation for key types\r\n if (!this._validateKeyPairConstantTime(ecdsaKeyPair)) {\r\n throw new Error('ECDSA keys are not valid CryptoKey instances');\r\n }\r\n \r\n this._secureLog('debug', 'ECDSA keys generated and validated', {\r\n operationId: operationId,\r\n privateKeyType: ecdsaKeyPair.privateKey.algorithm?.name,\r\n publicKeyType: ecdsaKeyPair.publicKey.algorithm?.name\r\n });\r\n \r\n } catch (ecdsaError) {\r\n this._secureLog('error', 'ECDSA key generation failed', {\r\n operationId: operationId,\r\n errorType: ecdsaError.constructor.name\r\n });\r\n this._throwSecureError(ecdsaError, 'ecdsa_key_generation');\r\n }\r\n \r\n // Final validation of both key pairs\r\n if (!ecdhKeyPair || !ecdsaKeyPair) {\r\n throw new Error('One or both key pairs failed to generate');\r\n }\r\n \r\n // Enable security features after successful key generation\r\n this._enableSecurityFeaturesAfterKeyGeneration(ecdhKeyPair, ecdsaKeyPair);\r\n \r\n this._secureLog('info', 'Encryption keys generated successfully with atomic protection', {\r\n operationId: operationId,\r\n hasECDHKeys: !!(ecdhKeyPair?.privateKey && ecdhKeyPair?.publicKey),\r\n hasECDSAKeys: !!(ecdsaKeyPair?.privateKey && ecdsaKeyPair?.publicKey),\r\n generationTime: Date.now() - currentState.lastOperationTime\r\n });\r\n \r\n return { ecdhKeyPair, ecdsaKeyPair };\r\n \r\n } catch (error) {\r\n // Ensure state is reset on any error\r\n this._secureLog('error', 'Key generation failed, resetting state', {\r\n operationId: operationId,\r\n errorType: error.constructor.name\r\n });\r\n throw error;\r\n } finally {\r\n // Always reset state in finally block\r\n currentState.isInitializing = false;\r\n currentState.operationId = null;\r\n \r\n this._secureLog('debug', 'Key generation state reset', {\r\n operationId: operationId\r\n });\r\n }\r\n });\r\n }\r\n\r\n /**\r\n * Enable security features after successful key generation\r\n */\r\n _enableSecurityFeaturesAfterKeyGeneration(ecdhKeyPair, ecdsaKeyPair) {\r\n try {\r\n // Enable encryption features based on available keys\r\n if (ecdhKeyPair && ecdhKeyPair.privateKey && ecdhKeyPair.publicKey) {\r\n this.securityFeatures.hasEncryption = true;\r\n this.securityFeatures.hasECDH = true;\r\n this._secureLog('info', 'ECDH encryption features enabled');\r\n }\r\n \r\n if (ecdsaKeyPair && ecdsaKeyPair.privateKey && ecdsaKeyPair.publicKey) {\r\n this.securityFeatures.hasECDSA = true;\r\n this._secureLog('info', 'ECDSA signature features enabled');\r\n }\r\n \r\n // Enable additional features that depend on encryption\r\n if (this.securityFeatures.hasEncryption) {\r\n this.securityFeatures.hasMetadataProtection = true;\r\n this.securityFeatures.hasEnhancedReplayProtection = true;\r\n this.securityFeatures.hasNonExtractableKeys = true;\r\n this._secureLog('info', 'Additional encryption-dependent features enabled');\r\n }\r\n \r\n // Enable PFS after ephemeral key generation\r\n if (ecdhKeyPair && this.ephemeralKeyPairs.size > 0) {\r\n this.securityFeatures.hasPFS = true;\r\n this._secureLog('info', 'Perfect Forward Secrecy enabled with ephemeral keys');\r\n }\r\n \r\n this._secureLog('info', 'Security features updated after key generation', {\r\n hasEncryption: this.securityFeatures.hasEncryption,\r\n hasECDH: this.securityFeatures.hasECDH,\r\n hasECDSA: this.securityFeatures.hasECDSA,\r\n hasMetadataProtection: this.securityFeatures.hasMetadataProtection,\r\n hasEnhancedReplayProtection: this.securityFeatures.hasEnhancedReplayProtection,\r\n hasNonExtractableKeys: this.securityFeatures.hasNonExtractableKeys,\r\n hasPFS: this.securityFeatures.hasPFS\r\n });\r\n \r\n } catch (error) {\r\n this._secureLog('error', 'Failed to enable security features after key generation', {\r\n errorType: error.constructor.name,\r\n errorMessage: error.message\r\n });\r\n }\r\n }\r\n\r\n /**\r\n * Enhanced emergency mutex unlocking with authorization and validation\r\n */\r\n _emergencyUnlockAllMutexes(callerContext = 'unknown') {\r\n // Validate caller authorization\r\n const authorizedCallers = [\r\n 'keyOperation', 'cryptoOperation', 'connectionOperation',\r\n 'emergencyRecovery', 'systemShutdown', 'errorHandler'\r\n ];\r\n \r\n if (!authorizedCallers.includes(callerContext)) {\r\n this._secureLog('error', `UNAUTHORIZED emergency mutex unlock attempt`, {\r\n callerContext: callerContext,\r\n authorizedCallers: authorizedCallers,\r\n timestamp: Date.now()\r\n });\r\n throw new Error(`Unauthorized emergency mutex unlock attempt by: ${callerContext}`);\r\n }\r\n \r\n const mutexes = ['keyOperation', 'cryptoOperation', 'connectionOperation'];\r\n \r\n this._secureLog('error', 'EMERGENCY: Unlocking all mutexes with authorization and state cleanup', {\r\n callerContext: callerContext,\r\n timestamp: Date.now()\r\n });\r\n \r\n let unlockedCount = 0;\r\n let errorCount = 0;\r\n \r\n mutexes.forEach(mutexName => {\r\n const mutex = this[`_${mutexName}Mutex`];\r\n if (mutex) {\r\n try {\r\n // Clear timeout first\r\n if (mutex.lockTimeout) {\r\n clearTimeout(mutex.lockTimeout);\r\n }\r\n \r\n // Log mutex state before emergency unlock\r\n const previousState = {\r\n locked: mutex.locked,\r\n lockId: mutex.lockId,\r\n lockTime: mutex.lockTime,\r\n queueLength: mutex.queue.length\r\n };\r\n \r\n // Reset mutex state atomically\r\n mutex.locked = false;\r\n mutex.lockId = null;\r\n mutex.lockTimeout = null;\r\n mutex.lockTime = null;\r\n \r\n // Clear queue with proper error handling and logging\r\n let queueRejectCount = 0;\r\n mutex.queue.forEach(item => {\r\n try {\r\n if (item.reject && typeof item.reject === 'function') {\r\n item.reject(new Error(`Emergency mutex unlock for ${mutexName} by ${callerContext}`));\r\n queueRejectCount++;\r\n }\r\n } catch (rejectError) {\r\n this._secureLog('warn', `Failed to reject queue item during emergency unlock`, {\r\n mutexName: mutexName,\r\n errorType: rejectError.constructor.name\r\n });\r\n }\r\n });\r\n \r\n // Clear queue array\r\n mutex.queue = [];\r\n \r\n unlockedCount++;\r\n \r\n this._secureLog('debug', `Emergency unlocked mutex: ${mutexName}`, {\r\n previousState: previousState,\r\n queueRejectCount: queueRejectCount,\r\n callerContext: callerContext\r\n });\r\n \r\n } catch (error) {\r\n errorCount++;\r\n this._secureLog('error', `Error during emergency unlock of mutex: ${mutexName}`, {\r\n errorType: error.constructor.name,\r\n errorMessage: error.message,\r\n callerContext: callerContext\r\n });\r\n }\r\n }\r\n });\r\n \r\n // Reset key system state with validation\r\n if (this._keySystemState) {\r\n try {\r\n const previousKeyState = { ...this._keySystemState };\r\n \r\n this._keySystemState.isInitializing = false;\r\n this._keySystemState.isRotating = false;\r\n this._keySystemState.isDestroying = false;\r\n this._keySystemState.operationId = null;\r\n this._keySystemState.concurrentOperations = 0;\r\n \r\n this._secureLog('debug', `Emergency reset key system state`, {\r\n previousState: previousKeyState,\r\n callerContext: callerContext\r\n });\r\n \r\n } catch (error) {\r\n this._secureLog('error', `Error resetting key system state during emergency unlock`, {\r\n errorType: error.constructor.name,\r\n errorMessage: error.message,\r\n callerContext: callerContext\r\n });\r\n }\r\n }\r\n \r\n // Log emergency unlock summary\r\n this._secureLog('info', `Emergency mutex unlock completed`, {\r\n callerContext: callerContext,\r\n unlockedCount: unlockedCount,\r\n errorCount: errorCount,\r\n totalMutexes: mutexes.length,\r\n timestamp: Date.now()\r\n });\r\n \r\n // Trigger system validation after emergency unlock\r\n setTimeout(() => {\r\n this._validateMutexSystemAfterEmergencyUnlock();\r\n }, 100);\r\n }\r\n\r\n /**\r\n * Handle key operation errors with recovery mechanisms\r\n */\r\n _handleKeyOperationError(error, operationId) {\r\n this._secureLog('error', 'Key operation error detected, initiating recovery', {\r\n operationId: operationId,\r\n errorType: error.constructor.name,\r\n errorMessage: error.message\r\n });\r\n \r\n // Reset key system state immediately\r\n if (this._keySystemState) {\r\n this._keySystemState.isInitializing = false;\r\n this._keySystemState.isRotating = false;\r\n this._keySystemState.isDestroying = false;\r\n this._keySystemState.operationId = null;\r\n }\r\n \r\n // Clear any partial key data\r\n this.ecdhKeyPair = null;\r\n this.ecdsaKeyPair = null;\r\n this.encryptionKey = null;\r\n this.macKey = null;\r\n this.metadataKey = null;\r\n \r\n // Trigger emergency recovery if needed\r\n if (error.message.includes('timeout') || error.message.includes('race condition')) {\r\n this._secureLog('warn', 'Race condition or timeout detected, triggering emergency recovery');\r\n this._emergencyRecoverMutexSystem();\r\n }\r\n }\r\n\r\n /**\r\n * Generate cryptographically secure IV with reuse prevention\r\n */\r\n _generateSecureIV(ivSize = 12, context = 'general') {\r\n // Check if we're in emergency mode\r\n if (this._ivTrackingSystem.emergencyMode) {\r\n this._secureLog('error', 'CRITICAL: IV generation blocked - emergency mode active due to IV reuse');\r\n throw new Error('IV generation blocked - emergency mode active');\r\n }\r\n \r\n let attempts = 0;\r\n const maxAttempts = 100; // Prevent infinite loops\r\n \r\n while (attempts < maxAttempts) {\r\n attempts++;\r\n \r\n // Generate fresh IV with crypto.getRandomValues\r\n const iv = crypto.getRandomValues(new Uint8Array(ivSize));\r\n \r\n // Convert IV to string for tracking\r\n const ivString = Array.from(iv).map(b => b.toString(16).padStart(2, '0')).join('');\r\n \r\n // Check for IV reuse\r\n if (this._ivTrackingSystem.usedIVs.has(ivString)) {\r\n this._ivTrackingSystem.collisionCount++;\r\n this._secureLog('error', `CRITICAL: IV reuse detected!`, {\r\n context: context,\r\n attempt: attempts,\r\n collisionCount: this._ivTrackingSystem.collisionCount,\r\n ivString: ivString.substring(0, 16) + '...' // Log partial IV for debugging\r\n });\r\n \r\n // If too many collisions, trigger emergency mode\r\n if (this._ivTrackingSystem.collisionCount > 5) {\r\n this._ivTrackingSystem.emergencyMode = true;\r\n this._secureLog('error', 'CRITICAL: Emergency mode activated due to excessive IV reuse');\r\n throw new Error('Emergency mode: Excessive IV reuse detected');\r\n }\r\n \r\n continue; // Try again\r\n }\r\n \r\n // Validate IV entropy\r\n if (!this._validateIVEntropy(iv)) {\r\n this._ivTrackingSystem.entropyValidation.entropyFailures++;\r\n this._secureLog('warn', `Low entropy IV detected`, {\r\n context: context,\r\n attempt: attempts,\r\n entropyFailures: this._ivTrackingSystem.entropyValidation.entropyFailures\r\n });\r\n \r\n // If too many entropy failures, trigger emergency mode\r\n if (this._ivTrackingSystem.entropyValidation.entropyFailures > 10) {\r\n this._ivTrackingSystem.emergencyMode = true;\r\n this._secureLog('error', 'CRITICAL: Emergency mode activated due to low entropy IVs');\r\n throw new Error('Emergency mode: Low entropy IVs detected');\r\n }\r\n \r\n continue; // Try again\r\n }\r\n \r\n // Track IV usage\r\n this._ivTrackingSystem.usedIVs.add(ivString);\r\n this._ivTrackingSystem.ivHistory.set(ivString, {\r\n timestamp: Date.now(),\r\n context: context,\r\n attempt: attempts\r\n });\r\n \r\n // Track per-session IVs\r\n if (this.sessionId) {\r\n if (!this._ivTrackingSystem.sessionIVs.has(this.sessionId)) {\r\n this._ivTrackingSystem.sessionIVs.set(this.sessionId, new Set());\r\n }\r\n this._ivTrackingSystem.sessionIVs.get(this.sessionId).add(ivString);\r\n }\r\n \r\n // Validate RNG periodically\r\n this._validateRNGQuality();\r\n \r\n this._secureLog('debug', `Secure IV generated`, {\r\n context: context,\r\n attempt: attempts,\r\n ivSize: ivSize,\r\n totalIVs: this._ivTrackingSystem.usedIVs.size\r\n });\r\n \r\n return iv;\r\n }\r\n \r\n // If we can't generate a unique IV after max attempts\r\n this._secureLog('error', `Failed to generate unique IV after ${maxAttempts} attempts`, {\r\n context: context,\r\n totalIVs: this._ivTrackingSystem.usedIVs.size\r\n });\r\n throw new Error(`Failed to generate unique IV after ${maxAttempts} attempts`);\r\n }\r\n \r\n /**\r\n * Validate IV entropy to detect weak RNG\r\n */\r\n _validateIVEntropy(iv) {\r\n this._ivTrackingSystem.entropyValidation.entropyTests++;\r\n \r\n // Calculate byte distribution\r\n const byteCounts = new Array(256).fill(0);\r\n for (let i = 0; i < iv.length; i++) {\r\n byteCounts[iv[i]]++;\r\n }\r\n \r\n // Multi-dimensional entropy analysis\r\n const entropyResults = {\r\n shannon: 0,\r\n min: 0,\r\n collision: 0,\r\n compression: 0,\r\n quantum: 0\r\n };\r\n \r\n // 1. Shannon entropy calculation\r\n let shannonEntropy = 0;\r\n const totalBytes = iv.length;\r\n \r\n for (let i = 0; i < 256; i++) {\r\n if (byteCounts[i] > 0) {\r\n const probability = byteCounts[i] / totalBytes;\r\n shannonEntropy -= probability * Math.log2(probability);\r\n }\r\n }\r\n entropyResults.shannon = shannonEntropy;\r\n \r\n // 2. Min-entropy calculation (worst-case scenario)\r\n const maxCount = Math.max(...byteCounts);\r\n const maxProbability = maxCount / totalBytes;\r\n entropyResults.min = -Math.log2(maxProbability);\r\n \r\n // 3. Collision entropy calculation\r\n let collisionSum = 0;\r\n for (let i = 0; i < 256; i++) {\r\n if (byteCounts[i] > 0) {\r\n const probability = byteCounts[i] / totalBytes;\r\n collisionSum += probability * probability;\r\n }\r\n }\r\n entropyResults.collision = -Math.log2(collisionSum);\r\n \r\n // 4. Compression-based entropy estimation\r\n const ivString = Array.from(iv).map(b => String.fromCharCode(b)).join('');\r\n const compressedLength = this._estimateCompressedLength(ivString);\r\n entropyResults.compression = (1 - compressedLength / totalBytes) * 8;\r\n \r\n // 5. Quantum-resistant entropy analysis\r\n entropyResults.quantum = this._calculateQuantumResistantEntropy(iv);\r\n \r\n // Enhanced suspicious pattern detection\r\n const hasSuspiciousPatterns = this._detectAdvancedSuspiciousPatterns(iv);\r\n \r\n // Multi-criteria validation\r\n const minEntropyThreshold = this._ivTrackingSystem.entropyValidation.minEntropy;\r\n const isValid = (\r\n entropyResults.shannon >= minEntropyThreshold &&\r\n entropyResults.min >= minEntropyThreshold * 0.8 &&\r\n entropyResults.collision >= minEntropyThreshold * 0.9 &&\r\n entropyResults.compression >= minEntropyThreshold * 0.7 &&\r\n entropyResults.quantum >= minEntropyThreshold * 0.6 &&\r\n !hasSuspiciousPatterns\r\n );\r\n \r\n if (!isValid) {\r\n this._secureLog('warn', `Enhanced IV entropy validation failed`, {\r\n shannon: entropyResults.shannon.toFixed(2),\r\n min: entropyResults.min.toFixed(2),\r\n collision: entropyResults.collision.toFixed(2),\r\n compression: entropyResults.compression.toFixed(2),\r\n quantum: entropyResults.quantum.toFixed(2),\r\n minThreshold: minEntropyThreshold,\r\n hasSuspiciousPatterns: hasSuspiciousPatterns\r\n });\r\n }\r\n \r\n return isValid;\r\n }\r\n \r\n /**\r\n * Estimate compressed length for entropy calculation\r\n * @param {string} data - Data to estimate compression\r\n * @returns {number} Estimated compressed length\r\n */\r\n _estimateCompressedLength(data) {\r\n // Simple LZ77-like compression estimation\r\n let compressedLength = 0;\r\n let i = 0;\r\n \r\n while (i < data.length) {\r\n let matchLength = 0;\r\n let matchDistance = 0;\r\n \r\n // Look for repeated patterns\r\n for (let j = Math.max(0, i - 255); j < i; j++) {\r\n let k = 0;\r\n while (i + k < data.length && data[i + k] === data[j + k] && k < 255) {\r\n k++;\r\n }\r\n if (k > matchLength) {\r\n matchLength = k;\r\n matchDistance = i - j;\r\n }\r\n }\r\n \r\n if (matchLength >= 3) {\r\n compressedLength += 3; // Distance + length + literal\r\n i += matchLength;\r\n } else {\r\n compressedLength += 1;\r\n i += 1;\r\n }\r\n }\r\n \r\n return compressedLength;\r\n }\r\n\r\n /**\r\n * Calculate quantum-resistant entropy\r\n * @param {Uint8Array} data - Data to analyze\r\n * @returns {number} Quantum-resistant entropy score\r\n */\r\n _calculateQuantumResistantEntropy(data) {\r\n // Quantum-resistant entropy analysis\r\n let quantumScore = 0;\r\n \r\n // 1. Check for quantum-vulnerable patterns\r\n const hasQuantumVulnerablePatterns = this._detectQuantumVulnerablePatterns(data);\r\n if (hasQuantumVulnerablePatterns) {\r\n quantumScore -= 2;\r\n }\r\n \r\n // 2. Analyze bit distribution\r\n const bitDistribution = this._analyzeBitDistribution(data);\r\n quantumScore += bitDistribution.score;\r\n \r\n // 3. Check for periodicity\r\n const periodicity = this._detectPeriodicity(data);\r\n quantumScore -= periodicity * 0.5;\r\n \r\n // 4. Normalize to 0-8 range\r\n return Math.max(0, Math.min(8, quantumScore));\r\n }\r\n\r\n /**\r\n * Detect quantum-vulnerable patterns\r\n * @param {Uint8Array} data - Data to analyze\r\n * @returns {boolean} true if quantum-vulnerable patterns found\r\n */\r\n _detectQuantumVulnerablePatterns(data) {\r\n // Check for patterns vulnerable to quantum attacks\r\n const patterns = [\r\n [0, 0, 0, 0, 0, 0, 0, 0], // All zeros\r\n [255, 255, 255, 255, 255, 255, 255, 255], // All ones\r\n [0, 1, 0, 1, 0, 1, 0, 1], // Alternating\r\n [1, 0, 1, 0, 1, 0, 1, 0] // Alternating reverse\r\n ];\r\n \r\n for (const pattern of patterns) {\r\n for (let i = 0; i <= data.length - pattern.length; i++) {\r\n let match = true;\r\n for (let j = 0; j < pattern.length; j++) {\r\n if (data[i + j] !== pattern[j]) {\r\n match = false;\r\n break;\r\n }\r\n }\r\n if (match) return true;\r\n }\r\n }\r\n \r\n return false;\r\n }\r\n\r\n /**\r\n * Analyze bit distribution\r\n * @param {Uint8Array} data - Data to analyze\r\n * @returns {Object} Bit distribution analysis\r\n */\r\n _analyzeBitDistribution(data) {\r\n let ones = 0;\r\n let totalBits = data.length * 8;\r\n \r\n for (const byte of data) {\r\n ones += (byte >>> 0).toString(2).split('1').length - 1;\r\n }\r\n \r\n const zeroRatio = (totalBits - ones) / totalBits;\r\n const oneRatio = ones / totalBits;\r\n \r\n // Ideal distribution is 50/50\r\n const deviation = Math.abs(0.5 - oneRatio);\r\n const score = Math.max(0, 8 - deviation * 16);\r\n \r\n return { score, zeroRatio, oneRatio, deviation };\r\n }\r\n\r\n /**\r\n * Detect periodicity in data\r\n * @param {Uint8Array} data - Data to analyze\r\n * @returns {number} Periodicity score (0-1)\r\n */\r\n _detectPeriodicity(data) {\r\n if (data.length < 16) return 0;\r\n \r\n let maxPeriodicity = 0;\r\n \r\n // Check for periods from 2 to data.length/2\r\n for (let period = 2; period <= data.length / 2; period++) {\r\n let matches = 0;\r\n let totalChecks = 0;\r\n \r\n for (let i = 0; i < data.length - period; i++) {\r\n if (data[i] === data[i + period]) {\r\n matches++;\r\n }\r\n totalChecks++;\r\n }\r\n \r\n if (totalChecks > 0) {\r\n const periodicity = matches / totalChecks;\r\n maxPeriodicity = Math.max(maxPeriodicity, periodicity);\r\n }\r\n }\r\n \r\n return maxPeriodicity;\r\n }\r\n\r\n /**\r\n * Enhanced suspicious pattern detection\r\n * @param {Uint8Array} iv - IV to check\r\n * @returns {boolean} true if suspicious patterns found\r\n */\r\n _detectAdvancedSuspiciousPatterns(iv) {\r\n // Enhanced pattern detection with quantum-resistant analysis\r\n const patterns = [\r\n // Sequential patterns\r\n [0, 1, 2, 3, 4, 5, 6, 7],\r\n [255, 254, 253, 252, 251, 250, 249, 248],\r\n \r\n // Repeated patterns\r\n [0, 0, 0, 0, 0, 0, 0, 0],\r\n [255, 255, 255, 255, 255, 255, 255, 255],\r\n \r\n // Alternating patterns\r\n [0, 255, 0, 255, 0, 255, 0, 255],\r\n [255, 0, 255, 0, 255, 0, 255, 0]\r\n ];\r\n \r\n for (const pattern of patterns) {\r\n for (let i = 0; i <= iv.length - pattern.length; i++) {\r\n let match = true;\r\n for (let j = 0; j < pattern.length; j++) {\r\n if (iv[i + j] !== pattern[j]) {\r\n match = false;\r\n break;\r\n }\r\n }\r\n if (match) return true;\r\n }\r\n }\r\n \r\n // Check for low entropy regions\r\n const entropyMap = this._calculateLocalEntropy(iv);\r\n const lowEntropyRegions = entropyMap.filter(e => e < 3.0).length;\r\n \r\n return lowEntropyRegions > iv.length * 0.3; // More than 30% low entropy\r\n }\r\n\r\n /**\r\n * Calculate local entropy for pattern detection\r\n * @param {Uint8Array} data - Data to analyze\r\n * @returns {Array} Array of local entropy values\r\n */\r\n _calculateLocalEntropy(data) {\r\n const windowSize = 8;\r\n const entropyMap = [];\r\n \r\n for (let i = 0; i <= data.length - windowSize; i++) {\r\n const window = data.slice(i, i + windowSize);\r\n const charCount = {};\r\n \r\n for (const byte of window) {\r\n charCount[byte] = (charCount[byte] || 0) + 1;\r\n }\r\n \r\n let entropy = 0;\r\n for (const count of Object.values(charCount)) {\r\n const probability = count / windowSize;\r\n entropy -= probability * Math.log2(probability);\r\n }\r\n \r\n entropyMap.push(entropy);\r\n }\r\n \r\n return entropyMap;\r\n }\r\n\r\n /**\r\n * Detect suspicious patterns in IVs\r\n */\r\n _detectSuspiciousIVPatterns(iv) {\r\n // Check for all zeros or all ones\r\n const allZeros = iv.every(byte => byte === 0);\r\n const allOnes = iv.every(byte => byte === 255);\r\n \r\n if (allZeros || allOnes) {\r\n return true;\r\n }\r\n \r\n // Check for sequential patterns\r\n let sequentialCount = 0;\r\n for (let i = 1; i < iv.length; i++) {\r\n if (iv[i] === iv[i-1] + 1 || iv[i] === iv[i-1] - 1) {\r\n sequentialCount++;\r\n } else {\r\n sequentialCount = 0;\r\n }\r\n \r\n if (sequentialCount >= 3) {\r\n return true; // Suspicious sequential pattern\r\n }\r\n }\r\n \r\n // Check for repeated patterns\r\n for (let patternLength = 2; patternLength <= Math.floor(iv.length / 2); patternLength++) {\r\n for (let start = 0; start <= iv.length - patternLength * 2; start++) {\r\n const pattern1 = iv.slice(start, start + patternLength);\r\n const pattern2 = iv.slice(start + patternLength, start + patternLength * 2);\r\n \r\n if (pattern1.every((byte, index) => byte === pattern2[index])) {\r\n return true; // Repeated pattern detected\r\n }\r\n }\r\n }\r\n \r\n return false;\r\n }\r\n \r\n /**\r\n * Clean up old IVs with strict limits\r\n */\r\n async _cleanupOldIVs() {\r\n const now = Date.now();\r\n const maxAge = 1800000; // Reduced to 30 minutes for better security\r\n let cleanedCount = 0;\r\n const cleanupBatch = [];\r\n \r\n // Aggressive cleanup with quantum-resistant patterns\r\n // Enforce maximum IV history size with batch processing\r\n if (this._ivTrackingSystem.ivHistory.size > this._ivTrackingSystem.maxIVHistorySize) {\r\n const ivArray = Array.from(this._ivTrackingSystem.ivHistory.entries());\r\n const toRemove = ivArray.slice(0, ivArray.length - this._ivTrackingSystem.maxIVHistorySize);\r\n \r\n for (const [ivString] of toRemove) {\r\n cleanupBatch.push(ivString);\r\n cleanedCount++;\r\n \r\n // Process in batches to prevent memory spikes\r\n if (cleanupBatch.length >= 100) {\r\n this._processCleanupBatch(cleanupBatch);\r\n cleanupBatch.length = 0;\r\n }\r\n }\r\n }\r\n \r\n // Clean up old IVs from history by age with enhanced security\r\n for (const [ivString, metadata] of this._ivTrackingSystem.ivHistory.entries()) {\r\n if (now - metadata.timestamp > maxAge) {\r\n cleanupBatch.push(ivString);\r\n cleanedCount++;\r\n \r\n // Process in batches to prevent memory spikes\r\n if (cleanupBatch.length >= 100) {\r\n this._processCleanupBatch(cleanupBatch);\r\n cleanupBatch.length = 0;\r\n }\r\n }\r\n }\r\n \r\n // Process remaining batch\r\n if (cleanupBatch.length > 0) {\r\n this._processCleanupBatch(cleanupBatch);\r\n }\r\n \r\n // Enhanced session IV cleanup with entropy preservation\r\n for (const [sessionId, sessionIVs] of this._ivTrackingSystem.sessionIVs.entries()) {\r\n if (sessionIVs.size > this._ivTrackingSystem.maxSessionIVs) {\r\n const ivArray = Array.from(sessionIVs);\r\n const toRemove = ivArray.slice(0, ivArray.length - this._ivTrackingSystem.maxSessionIVs);\r\n \r\n for (const ivString of toRemove) {\r\n sessionIVs.delete(ivString);\r\n this._ivTrackingSystem.usedIVs.delete(ivString);\r\n this._ivTrackingSystem.ivHistory.delete(ivString);\r\n cleanedCount++;\r\n }\r\n }\r\n }\r\n \r\n // Schedule natural cleanup if significant cleanup occurred\r\n if (cleanedCount > 50) {\r\n await this._performNaturalCleanup();\r\n }\r\n \r\n if (cleanedCount > 0) {\r\n this._secureLog('debug', `Enhanced cleanup: ${cleanedCount} old IVs removed`, {\r\n cleanedCount: cleanedCount,\r\n remainingIVs: this._ivTrackingSystem.usedIVs.size,\r\n remainingHistory: this._ivTrackingSystem.ivHistory.size,\r\n memoryPressure: this._calculateMemoryPressure()\r\n });\r\n }\r\n }\r\n \r\n /**\r\n * Process cleanup batch with constant-time operations\r\n * @param {Array} batch - Batch of items to clean up\r\n */\r\n _processCleanupBatch(batch) {\r\n // Constant-time batch processing\r\n for (const item of batch) {\r\n this._ivTrackingSystem.usedIVs.delete(item);\r\n this._ivTrackingSystem.ivHistory.delete(item);\r\n }\r\n }\r\n\r\n /**\r\n * Calculate memory pressure for adaptive cleanup\r\n * @returns {number} Memory pressure score (0-100)\r\n */\r\n _calculateMemoryPressure() {\r\n const totalIVs = this._ivTrackingSystem.usedIVs.size;\r\n const maxAllowed = this._resourceLimits.maxIVHistory;\r\n \r\n return Math.min(100, Math.floor((totalIVs / maxAllowed) * 100));\r\n }\r\n\r\n /**\r\n * Get IV tracking system statistics\r\n */\r\n _getIVTrackingStats() {\r\n return {\r\n totalIVs: this._ivTrackingSystem.usedIVs.size,\r\n collisionCount: this._ivTrackingSystem.collisionCount,\r\n entropyTests: this._ivTrackingSystem.entropyValidation.entropyTests,\r\n entropyFailures: this._ivTrackingSystem.entropyValidation.entropyFailures,\r\n rngTests: this._ivTrackingSystem.rngValidation.testsPerformed,\r\n weakRngDetected: this._ivTrackingSystem.rngValidation.weakRngDetected,\r\n emergencyMode: this._ivTrackingSystem.emergencyMode,\r\n sessionCount: this._ivTrackingSystem.sessionIVs.size,\r\n lastCleanup: this._lastIVCleanupTime || 0\r\n };\r\n }\r\n \r\n /**\r\n * Reset IV tracking system (for testing or emergency recovery)\r\n */\r\n _resetIVTrackingSystem() {\r\n this._secureLog('warn', 'Resetting IV tracking system');\r\n \r\n this._ivTrackingSystem.usedIVs.clear();\r\n this._ivTrackingSystem.ivHistory.clear();\r\n this._ivTrackingSystem.sessionIVs.clear();\r\n this._ivTrackingSystem.collisionCount = 0;\r\n this._ivTrackingSystem.entropyValidation.entropyTests = 0;\r\n this._ivTrackingSystem.entropyValidation.entropyFailures = 0;\r\n this._ivTrackingSystem.rngValidation.testsPerformed = 0;\r\n this._ivTrackingSystem.rngValidation.weakRngDetected = false;\r\n this._ivTrackingSystem.emergencyMode = false;\r\n \r\n this._secureLog('info', 'IV tracking system reset completed');\r\n }\r\n \r\n /**\r\n * Validate RNG quality\r\n */\r\n _validateRNGQuality() {\r\n const now = Date.now();\r\n \r\n // Validate RNG every 1000 IV generations\r\n if (this._ivTrackingSystem.rngValidation.testsPerformed % 1000 === 0) {\r\n try {\r\n // Generate test IVs and validate\r\n const testIVs = [];\r\n for (let i = 0; i < 100; i++) {\r\n testIVs.push(crypto.getRandomValues(new Uint8Array(12)));\r\n }\r\n \r\n // Check for duplicates in test set\r\n const testIVStrings = testIVs.map(iv => Array.from(iv).map(b => b.toString(16).padStart(2, '0')).join(''));\r\n const uniqueTestIVs = new Set(testIVStrings);\r\n \r\n if (uniqueTestIVs.size < 95) { // Allow some tolerance\r\n this._ivTrackingSystem.rngValidation.weakRngDetected = true;\r\n this._secureLog('error', 'CRITICAL: Weak RNG detected in validation test', {\r\n uniqueIVs: uniqueTestIVs.size,\r\n totalTests: testIVs.length\r\n });\r\n }\r\n \r\n this._ivTrackingSystem.rngValidation.lastValidation = now;\r\n \r\n } catch (error) {\r\n this._secureLog('error', 'RNG validation failed', {\r\n errorType: error.constructor.name\r\n });\r\n }\r\n }\r\n \r\n this._ivTrackingSystem.rngValidation.testsPerformed++;\r\n }\r\n \r\n /**\r\n * Handle mutex timeout with enhanced state validation\r\n */\r\n _handleMutexTimeout(mutexName, operationId, timeout) {\r\n const mutex = this[`_${mutexName}Mutex`];\r\n \r\n if (!mutex) {\r\n this._secureLog('error', `Mutex '${mutexName}' not found during timeout handling`);\r\n return;\r\n }\r\n \r\n // Validate timeout conditions\r\n if (mutex.lockId !== operationId) {\r\n this._secureLog('warn', `Timeout for different operation ID on mutex '${mutexName}'`, {\r\n expectedOperationId: operationId,\r\n actualLockId: mutex.lockId,\r\n locked: mutex.locked\r\n });\r\n return;\r\n }\r\n \r\n if (!mutex.locked) {\r\n this._secureLog('warn', `Timeout for already unlocked mutex '${mutexName}'`, {\r\n operationId: operationId\r\n });\r\n return;\r\n }\r\n \r\n try {\r\n // Calculate lock duration for monitoring\r\n const lockDuration = mutex.lockTime ? Date.now() - mutex.lockTime : 0;\r\n \r\n this._secureLog('warn', `Mutex '${mutexName}' auto-released due to timeout`, {\r\n operationId: operationId,\r\n lockDuration: lockDuration,\r\n timeout: timeout,\r\n queueLength: mutex.queue.length\r\n });\r\n \r\n // Atomic release with state validation\r\n mutex.locked = false;\r\n mutex.lockId = null;\r\n mutex.lockTimeout = null;\r\n mutex.lockTime = null;\r\n \r\n // Process next in queue with error handling\r\n setTimeout(() => {\r\n try {\r\n this._processNextInQueue(mutexName);\r\n } catch (queueError) {\r\n this._secureLog('error', `Error processing queue after timeout for mutex '${mutexName}'`, {\r\n errorType: queueError.constructor.name,\r\n errorMessage: queueError.message\r\n });\r\n }\r\n }, 10);\r\n \r\n } catch (error) {\r\n this._secureLog('error', `Critical error during mutex timeout handling for '${mutexName}'`, {\r\n operationId: operationId,\r\n errorType: error.constructor.name,\r\n errorMessage: error.message\r\n });\r\n \r\n // Force emergency unlock if timeout handling fails\r\n try {\r\n this._emergencyUnlockAllMutexes('timeoutHandler');\r\n } catch (emergencyError) {\r\n this._secureLog('error', `Emergency unlock failed during timeout handling`, {\r\n originalError: error.message,\r\n emergencyError: emergencyError.message\r\n });\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Validate mutex system after emergency unlock\r\n */\r\n _validateMutexSystemAfterEmergencyUnlock() {\r\n const mutexes = ['keyOperation', 'cryptoOperation', 'connectionOperation'];\r\n let validationErrors = 0;\r\n \r\n this._secureLog('info', 'Validating mutex system after emergency unlock');\r\n \r\n mutexes.forEach(mutexName => {\r\n const mutex = this[`_${mutexName}Mutex`];\r\n \r\n if (!mutex) {\r\n validationErrors++;\r\n this._secureLog('error', `Mutex '${mutexName}' not found after emergency unlock`);\r\n return;\r\n }\r\n \r\n // Validate mutex state consistency\r\n if (mutex.locked) {\r\n validationErrors++;\r\n this._secureLog('error', `Mutex '${mutexName}' still locked after emergency unlock`, {\r\n lockId: mutex.lockId,\r\n lockTime: mutex.lockTime\r\n });\r\n }\r\n \r\n if (mutex.lockId !== null) {\r\n validationErrors++;\r\n this._secureLog('error', `Mutex '${mutexName}' still has lock ID after emergency unlock`, {\r\n lockId: mutex.lockId\r\n });\r\n }\r\n \r\n if (mutex.lockTimeout !== null) {\r\n validationErrors++;\r\n this._secureLog('error', `Mutex '${mutexName}' still has timeout after emergency unlock`);\r\n }\r\n \r\n if (mutex.queue.length > 0) {\r\n validationErrors++;\r\n this._secureLog('error', `Mutex '${mutexName}' still has queue items after emergency unlock`, {\r\n queueLength: mutex.queue.length\r\n });\r\n }\r\n });\r\n \r\n // Validate key system state\r\n if (this._keySystemState) {\r\n if (this._keySystemState.isInitializing || \r\n this._keySystemState.isRotating || \r\n this._keySystemState.isDestroying) {\r\n validationErrors++;\r\n this._secureLog('error', `Key system state not properly reset after emergency unlock`, {\r\n isInitializing: this._keySystemState.isInitializing,\r\n isRotating: this._keySystemState.isRotating,\r\n isDestroying: this._keySystemState.isDestroying\r\n });\r\n }\r\n }\r\n \r\n if (validationErrors === 0) {\r\n this._secureLog('info', 'Mutex system validation passed after emergency unlock');\r\n } else {\r\n this._secureLog('error', `Mutex system validation failed after emergency unlock`, {\r\n validationErrors: validationErrors\r\n });\r\n \r\n // Force re-initialization if validation fails\r\n setTimeout(() => {\r\n this._emergencyRecoverMutexSystem();\r\n }, 1000);\r\n }\r\n }\r\n /**\r\n * NEW: Diagnostics of the mutex system state\r\n */\r\n _getMutexSystemDiagnostics() {\r\n const diagnostics = {\r\n timestamp: Date.now(),\r\n systemValid: this._validateMutexSystem(),\r\n mutexes: {},\r\n counters: { ...this._operationCounters },\r\n keySystemState: { ...this._keySystemState }\r\n };\r\n \r\n const mutexNames = ['keyOperation', 'cryptoOperation', 'connectionOperation'];\r\n \r\n mutexNames.forEach(mutexName => {\r\n const mutexPropertyName = `_${mutexName}Mutex`;\r\n const mutex = this[mutexPropertyName];\r\n \r\n if (mutex) {\r\n diagnostics.mutexes[mutexName] = {\r\n locked: mutex.locked,\r\n lockId: mutex.lockId,\r\n queueLength: mutex.queue.length,\r\n hasTimeout: !!mutex.lockTimeout\r\n };\r\n } else {\r\n diagnostics.mutexes[mutexName] = { error: 'not_found' };\r\n }\r\n });\r\n \r\n return diagnostics;\r\n }\r\n\r\n /**\r\n * FULLY FIXED createSecureOffer()\r\n * With race-condition protection and improved security\r\n */\r\n async createSecureOffer() {\r\n return this._withMutex('connectionOperation', async (operationId) => {\r\n this._secureLog('info', 'Creating secure offer with mutex', {\r\n operationId: operationId,\r\n connectionAttempts: this.connectionAttempts,\r\n currentState: this.peerConnection?.connectionState || 'none'\r\n });\r\n \r\n try {\r\n // ============================================\r\n // PHASE 1: INITIALIZATION AND VALIDATION\r\n // ============================================\r\n \r\n // Reset notification flags for a new connection\r\n this._resetNotificationFlags();\r\n \r\n // Rate limiting check\r\n if (!this._checkRateLimit()) {\r\n throw new Error('Connection rate limit exceeded. Please wait before trying again.');\r\n }\r\n \r\n // Reset attempt counters\r\n this.connectionAttempts = 0;\r\n \r\n // Generate session salt (64 bytes for v4.0)\r\n this.sessionSalt = window.EnhancedSecureCryptoUtils.generateSalt();\r\n \r\n this._secureLog('debug', 'Session salt generated', {\r\n operationId: operationId,\r\n saltLength: this.sessionSalt.length,\r\n isValidSalt: Array.isArray(this.sessionSalt) && this.sessionSalt.length === 64\r\n });\r\n \r\n // ============================================\r\n // PHASE 2: SECURE KEY GENERATION\r\n // ============================================\r\n \r\n // Secure key generation via mutex\r\n const keyPairs = await this._generateEncryptionKeys();\r\n this.ecdhKeyPair = keyPairs.ecdhKeyPair;\r\n this.ecdsaKeyPair = keyPairs.ecdsaKeyPair;\r\n \r\n // Validate generated keys\r\n if (!this.ecdhKeyPair?.privateKey || !this.ecdhKeyPair?.publicKey) {\r\n throw new Error('Failed to generate valid ECDH key pair');\r\n }\r\n \r\n if (!this.ecdsaKeyPair?.privateKey || !this.ecdsaKeyPair?.publicKey) {\r\n throw new Error('Failed to generate valid ECDSA key pair');\r\n }\r\n \r\n // ============================================\r\n // PHASE 3: MITM PROTECTION AND FINGERPRINTING\r\n // ============================================\r\n \r\n // MITM Protection: Compute unique key fingerprints\r\n const ecdhFingerprint = await window.EnhancedSecureCryptoUtils.calculateKeyFingerprint(\r\n await crypto.subtle.exportKey('spki', this.ecdhKeyPair.publicKey)\r\n );\r\n const ecdsaFingerprint = await window.EnhancedSecureCryptoUtils.calculateKeyFingerprint(\r\n await crypto.subtle.exportKey('spki', this.ecdsaKeyPair.publicKey)\r\n );\r\n \r\n // Validate fingerprints\r\n if (!ecdhFingerprint || !ecdsaFingerprint) {\r\n throw new Error('Failed to generate key fingerprints');\r\n }\r\n \r\n this._secureLog('info', 'Generated unique key pairs for MITM protection', {\r\n operationId: operationId,\r\n hasECDHFingerprint: !!ecdhFingerprint,\r\n hasECDSAFingerprint: !!ecdsaFingerprint,\r\n fingerprintLength: ecdhFingerprint.length,\r\n timestamp: Date.now()\r\n });\r\n \r\n // ============================================\r\n // PHASE 4: EXPORT SIGNED KEYS\r\n // ============================================\r\n \r\n // Export keys with digital signatures\r\n const ecdhPublicKeyData = await window.EnhancedSecureCryptoUtils.exportPublicKeyWithSignature(\r\n this.ecdhKeyPair.publicKey,\r\n this.ecdsaKeyPair.privateKey,\r\n 'ECDH'\r\n );\r\n \r\n const ecdsaPublicKeyData = await window.EnhancedSecureCryptoUtils.exportPublicKeyWithSignature(\r\n this.ecdsaKeyPair.publicKey,\r\n this.ecdsaKeyPair.privateKey,\r\n 'ECDSA'\r\n );\r\n\r\n \r\n if (!ecdhPublicKeyData || typeof ecdhPublicKeyData !== 'object') {\r\n this._secureLog('error', 'CRITICAL: ECDH key export failed - invalid object structure', { operationId });\r\n throw new Error('CRITICAL SECURITY FAILURE: ECDH key export validation failed - hard abort required');\r\n }\r\n \r\n if (!ecdhPublicKeyData.keyData || !ecdhPublicKeyData.signature) {\r\n this._secureLog('error', 'CRITICAL: ECDH key export incomplete - missing keyData or signature', { \r\n operationId,\r\n hasKeyData: !!ecdhPublicKeyData.keyData,\r\n hasSignature: !!ecdhPublicKeyData.signature \r\n });\r\n throw new Error('CRITICAL SECURITY FAILURE: ECDH key export incomplete - hard abort required');\r\n }\r\n \r\n if (!ecdsaPublicKeyData || typeof ecdsaPublicKeyData !== 'object') {\r\n this._secureLog('error', 'CRITICAL: ECDSA key export failed - invalid object structure', { operationId });\r\n throw new Error('CRITICAL SECURITY FAILURE: ECDSA key export validation failed - hard abort required');\r\n }\r\n \r\n if (!ecdsaPublicKeyData.keyData || !ecdsaPublicKeyData.signature) {\r\n this._secureLog('error', 'CRITICAL: ECDSA key export incomplete - missing keyData or signature', { \r\n operationId,\r\n hasKeyData: !!ecdsaPublicKeyData.keyData,\r\n hasSignature: !!ecdsaPublicKeyData.signature \r\n });\r\n throw new Error('CRITICAL SECURITY FAILURE: ECDSA key export incomplete - hard abort required');\r\n }\r\n \r\n // ============================================\r\n // PHASE 5: UPDATE SECURITY FEATURES\r\n // ============================================\r\n \r\n // Atomic update of security features\r\n this._updateSecurityFeatures({\r\n hasEncryption: true,\r\n hasECDH: true,\r\n hasECDSA: true,\r\n hasMutualAuth: true,\r\n hasMetadataProtection: true,\r\n hasEnhancedReplayProtection: true,\r\n hasNonExtractableKeys: true,\r\n hasRateLimiting: true,\r\n hasEnhancedValidation: true,\r\n hasPFS: true\r\n });\r\n \r\n // ============================================\r\n // PHASE 6: INITIALIZE PEER CONNECTION\r\n // ============================================\r\n \r\n this.isInitiator = true;\r\n this.onStatusChange('connecting');\r\n \r\n // Create peer connection\r\n this.createPeerConnection();\r\n \r\n // Create main data channel\r\n this.dataChannel = this.peerConnection.createDataChannel('securechat', {\r\n ordered: true\r\n });\r\n \r\n // Setup data channel\r\n this.setupDataChannel(this.dataChannel);\r\n \r\n this._secureLog('debug', 'Data channel created', {\r\n operationId: operationId,\r\n channelLabel: this.dataChannel.label,\r\n channelOrdered: this.dataChannel.ordered\r\n });\r\n \r\n // ============================================\r\n // PHASE 7: CREATE SDP OFFER\r\n // ============================================\r\n \r\n\r\n const offer = await this.peerConnection.createOffer({\r\n offerToReceiveAudio: false,\r\n offerToReceiveVideo: false\r\n });\r\n \r\n await this.peerConnection.setLocalDescription(offer);\r\n\r\n try {\r\n const ourFingerprint = this._extractDTLSFingerprintFromSDP(offer.sdp);\r\n this.expectedDTLSFingerprint = ourFingerprint;\r\n \r\n this._secureLog('info', 'Generated DTLS fingerprint for out-of-band verification', {\r\n fingerprint: ourFingerprint,\r\n context: 'offer_creation'\r\n });\r\n \r\n // Notify UI that fingerprint is ready for out-of-band verification\r\n this.deliverMessageToUI(`DTLS fingerprint ready for verification: ${ourFingerprint}`, 'system');\r\n } catch (error) {\r\n this._secureLog('error', 'Failed to extract DTLS fingerprint from offer', { error: error.message });\r\n // Continue without fingerprint validation (fallback mode)\r\n }\r\n \r\n // Await ICE gathering\r\n await this.waitForIceGathering();\r\n \r\n this._secureLog('debug', 'ICE gathering completed', {\r\n operationId: operationId,\r\n iceGatheringState: this.peerConnection.iceGatheringState,\r\n connectionState: this.peerConnection.connectionState\r\n });\r\n \r\n // ============================================\r\n // PHASE 8: GENERATE SAS FOR OUT-OF-BAND VERIFICATION\r\n // ============================================\r\n\r\n this.verificationCode = window.EnhancedSecureCryptoUtils.generateVerificationCode();\r\n \r\n // Validate verification code\r\n if (!this.verificationCode || this.verificationCode.length < EnhancedSecureWebRTCManager.SIZES.VERIFICATION_CODE_MIN_LENGTH) {\r\n throw new Error('Failed to generate valid verification code');\r\n }\r\n \r\n // ============================================\r\n // PHASE 9: MUTUAL AUTHENTICATION CHALLENGE\r\n // ============================================\r\n \r\n // Generate challenge for mutual authentication\r\n const authChallenge = window.EnhancedSecureCryptoUtils.generateMutualAuthChallenge();\r\n \r\n if (!authChallenge) {\r\n throw new Error('Failed to generate mutual authentication challenge');\r\n }\r\n \r\n // ============================================\r\n // PHASE 10: SESSION ID FOR MITM PROTECTION\r\n // ============================================\r\n \r\n // MITM Protection: Generate session-specific ID\r\n this.sessionId = Array.from(crypto.getRandomValues(new Uint8Array(EnhancedSecureWebRTCManager.SIZES.SESSION_ID_LENGTH)))\r\n .map(b => b.toString(16).padStart(2, '0')).join('');\r\n \r\n // Validate session ID\r\n if (!this.sessionId || this.sessionId.length !== (EnhancedSecureWebRTCManager.SIZES.SESSION_ID_LENGTH * 2)) {\r\n throw new Error('Failed to generate valid session ID');\r\n }\r\n \r\n // Generate connection ID for AAD\r\n this.connectionId = Array.from(crypto.getRandomValues(new Uint8Array(8)))\r\n .map(b => b.toString(16).padStart(2, '0')).join('');\r\n \r\n // ============================================\r\n // PHASE 11: SECURITY LEVEL CALCULATION\r\n // ============================================\r\n \r\n // All security features are enabled by default\r\n const securityLevel = {\r\n level: 'MAXIMUM',\r\n score: 100,\r\n color: 'green',\r\n details: 'All security features enabled by default',\r\n passedChecks: 10,\r\n totalChecks: 10,\r\n isRealData: true\r\n };\r\n \r\n // ============================================\r\n // PHASE 12: CREATE OFFER PACKAGE\r\n // ============================================\r\n \r\n const currentTimestamp = Date.now();\r\n \r\n // Create compact offer package for smaller QR codes\r\n const offerPackage = {\r\n // Core information (minimal)\r\n t: 'offer', // type\r\n s: this.peerConnection.localDescription.sdp, // sdp\r\n v: '4.0', // version\r\n ts: currentTimestamp, // timestamp\r\n \r\n // Cryptographic keys (essential)\r\n e: ecdhPublicKeyData, // ecdhPublicKey\r\n d: ecdsaPublicKeyData, // ecdsaPublicKey\r\n \r\n // Session data (essential)\r\n sl: this.sessionSalt, // salt\r\n si: this.sessionId, // sessionId\r\n ci: this.connectionId, // connectionId\r\n \r\n // Authentication (essential)\r\n vc: this.verificationCode, // verificationCode\r\n ac: authChallenge, // authChallenge\r\n \r\n // Security metadata (simplified)\r\n slv: 'MAX', // securityLevel\r\n \r\n // Key fingerprints (shortened)\r\n kf: {\r\n e: ecdhFingerprint.substring(0, 12), // ecdh (12 chars)\r\n d: ecdsaFingerprint.substring(0, 12) // ecdsa (12 chars)\r\n }\r\n };\r\n \r\n // ============================================\r\n // PHASE 13: VALIDATE OFFER PACKAGE\r\n // ============================================\r\n\r\n try {\r\n const validationResult = this.validateEnhancedOfferData(offerPackage);\r\n\r\n } catch (validationError) {\r\n throw new Error(`Offer package validation error: ${validationError.message}`);\r\n }\r\n \r\n // ============================================\r\n // PHASE 14: LOGGING AND EVENTS\r\n // ============================================\r\n \r\n this._secureLog('info', 'Enhanced secure offer created successfully', {\r\n operationId: operationId,\r\n version: offerPackage.version,\r\n hasECDSA: true,\r\n hasMutualAuth: true,\r\n hasSessionId: !!offerPackage.sessionId,\r\n securityLevel: securityLevel.level,\r\n timestamp: currentTimestamp,\r\n capabilitiesCount: 10 // All capabilities enabled by default\r\n });\r\n \r\n // Dispatch event about new connection\r\n document.dispatchEvent(new CustomEvent('new-connection', {\r\n detail: { \r\n type: 'offer',\r\n timestamp: currentTimestamp,\r\n securityLevel: securityLevel.level,\r\n operationId: operationId\r\n }\r\n }));\r\n\r\n return offerPackage;\r\n \r\n } catch (error) {\r\n // ============================================\r\n // ERROR HANDLING\r\n // ============================================\r\n \r\n this._secureLog('error', 'Enhanced secure offer creation failed in critical section', {\r\n operationId: operationId,\r\n errorType: error.constructor.name,\r\n errorMessage: error.message,\r\n phase: this._determineErrorPhase(error),\r\n connectionAttempts: this.connectionAttempts\r\n });\r\n \r\n // Cleanup state on error\r\n this._cleanupFailedOfferCreation();\r\n \r\n // Update status\r\n this.onStatusChange('disconnected');\r\n \r\n // Re-throw for upper-level handling\r\n throw error;\r\n }\r\n }, 15000); // 15 seconds timeout for the entire offer creation\r\n }\r\n\r\n /**\r\n * HELPER: Determine the phase where the error occurred\r\n */\r\n _determineErrorPhase(error) {\r\n const message = error.message.toLowerCase();\r\n \r\n if (message.includes('rate limit')) return 'rate_limiting';\r\n if (message.includes('key pair') || message.includes('generate')) return 'key_generation';\r\n if (message.includes('fingerprint')) return 'fingerprinting';\r\n if (message.includes('export') || message.includes('signature')) return 'key_export';\r\n if (message.includes('peer connection')) return 'webrtc_setup';\r\n if (message.includes('offer') || message.includes('sdp')) return 'sdp_creation';\r\n if (message.includes('verification')) return 'verification_setup';\r\n if (message.includes('session')) return 'session_setup';\r\n if (message.includes('validation')) return 'package_validation';\r\n \r\n return 'unknown';\r\n }\r\n\r\n /**\r\n * Secure cleanup state after failed offer creation\r\n */\r\n _cleanupFailedOfferCreation() {\r\n try {\r\n // Secure wipe of cryptographic materials\r\n this._secureCleanupCryptographicMaterials();\r\n \r\n // Close peer connection if it was created\r\n if (this.peerConnection) {\r\n this.peerConnection.close();\r\n this.peerConnection = null;\r\n }\r\n \r\n // Clear data channel\r\n if (this.dataChannel) {\r\n this.dataChannel.close();\r\n this.dataChannel = null;\r\n }\r\n \r\n // Reset flags\r\n this.isInitiator = false;\r\n this.isVerified = false;\r\n \r\n // Reset security features to baseline\r\n this._updateSecurityFeatures({\r\n hasEncryption: false,\r\n hasECDH: false,\r\n hasECDSA: false,\r\n hasMutualAuth: false,\r\n hasMetadataProtection: false,\r\n hasEnhancedReplayProtection: false,\r\n hasNonExtractableKeys: false,\r\n hasEnhancedValidation: false,\r\n hasPFS: false\r\n });\r\n \r\n // Schedule natural cleanup\r\n this._forceGarbageCollection().catch(error => {\r\n this._secureLog('error', 'Cleanup failed during offer cleanup', {\r\n errorType: error?.constructor?.name || 'Unknown'\r\n });\r\n });\r\n \r\n this._secureLog('debug', 'Failed offer creation cleanup completed with secure memory wipe');\r\n \r\n } catch (cleanupError) {\r\n this._secureLog('error', 'Error during offer creation cleanup', {\r\n errorType: cleanupError.constructor.name,\r\n errorMessage: cleanupError.message\r\n });\r\n }\r\n }\r\n\r\n /**\r\n * HELPER: Atomic update of security features (if not added yet)\r\n */\r\n _updateSecurityFeatures(updates) {\r\n const oldFeatures = { ...this.securityFeatures };\r\n \r\n try {\r\n Object.assign(this.securityFeatures, updates);\r\n \r\n this._secureLog('debug', 'Security features updated', {\r\n updatedCount: Object.keys(updates).length,\r\n totalFeatures: Object.keys(this.securityFeatures).length\r\n });\r\n \r\n } catch (error) {\r\n // Roll back on error\r\n this.securityFeatures = oldFeatures;\r\n this._secureLog('error', 'Security features update failed, rolled back', {\r\n errorType: error.constructor.name\r\n });\r\n throw error;\r\n }\r\n }\r\n\r\n /**\r\n * FULLY FIXED METHOD createSecureAnswer()\r\n * With race-condition protection and enhanced security\r\n */\r\n async createSecureAnswer(offerData) {\r\n return this._withMutex('connectionOperation', async (operationId) => {\r\n this._secureLog('info', 'Creating secure answer with mutex', {\r\n operationId: operationId,\r\n hasOfferData: !!offerData,\r\n offerType: offerData?.type,\r\n offerVersion: offerData?.version,\r\n offerTimestamp: offerData?.timestamp\r\n });\r\n \r\n try {\r\n // ============================================\r\n // PHASE 1: PRE-VALIDATION OF OFFER\r\n // ============================================\r\n \r\n // Reset notification flags for a new connection\r\n this._resetNotificationFlags();\r\n \r\n this._secureLog('debug', 'Starting enhanced offer validation', {\r\n operationId: operationId,\r\n hasOfferData: !!offerData,\r\n offerType: offerData?.type,\r\n hasECDHKey: !!offerData?.ecdhPublicKey,\r\n hasECDSAKey: !!offerData?.ecdsaPublicKey,\r\n hasSalt: !!offerData?.salt\r\n });\r\n \r\n // Strict input validation\r\n if (!this.validateEnhancedOfferData(offerData)) {\r\n throw new Error('Invalid connection data format - failed enhanced validation');\r\n }\r\n \r\n // Rate limiting check\r\n if (!window.EnhancedSecureCryptoUtils.rateLimiter.checkConnectionRate(this.rateLimiterId)) {\r\n throw new Error('Connection rate limit exceeded. Please wait before trying again.');\r\n }\r\n \r\n // ============================================\r\n // PHASE 2: SECURITY AND ANTI-REPLAY PROTECTION\r\n // ============================================\r\n \r\n // MITM Protection: Validate offer data structure (support both formats)\r\n const timestamp = offerData.ts || offerData.timestamp;\r\n const version = offerData.v || offerData.version;\r\n if (!timestamp || !version) {\r\n throw new Error('Missing required security fields in offer data \u2013 possible MITM attack');\r\n }\r\n \r\n // Replay attack protection (extended to 30 minutes for better UX)\r\n const offerAge = Date.now() - timestamp;\r\n const MAX_OFFER_AGE = 1800000; // 30 minutes for better user experience\r\n \r\n if (offerAge > MAX_OFFER_AGE) {\r\n this._secureLog('error', 'Offer data is too old - possible replay attack', {\r\n operationId: operationId,\r\n offerAge: Math.round(offerAge / 1000),\r\n maxAllowedAge: Math.round(MAX_OFFER_AGE / 1000),\r\n timestamp: offerData.timestamp\r\n });\r\n \r\n // Notify the main code about the replay attack\r\n if (this.onAnswerError) {\r\n this.onAnswerError('replay_attack', 'Offer data is too old \u2013 possible replay attack');\r\n }\r\n \r\n throw new Error('Offer data is too old \u2013 possible replay attack');\r\n }\r\n \r\n // Protocol version compatibility check (support both formats)\r\n const protocolVersion = version; // Use the version we already extracted\r\n if (protocolVersion !== '4.0') {\r\n this._secureLog('warn', 'Protocol version mismatch detected', {\r\n operationId: operationId,\r\n expectedVersion: '4.0',\r\n receivedVersion: protocolVersion\r\n });\r\n \r\n // For backward compatibility with v3.0, a fallback can be added\r\n if (protocolVersion !== '3.0') {\r\n throw new Error(`Unsupported protocol version: ${protocolVersion}`);\r\n }\r\n }\r\n \r\n // ============================================\r\n // PHASE 3: EXTRACT AND VALIDATE SESSION SALT\r\n // ============================================\r\n \r\n // Set session salt from offer (support both formats)\r\n this.sessionSalt = offerData.sl || offerData.salt;\r\n \r\n // Validate session salt\r\n if (!Array.isArray(this.sessionSalt)) {\r\n throw new Error('Invalid session salt format - must be array');\r\n }\r\n \r\n const expectedSaltLength = protocolVersion === '4.0' ? 64 : 32;\r\n if (this.sessionSalt.length !== expectedSaltLength) {\r\n throw new Error(`Invalid session salt length: expected ${expectedSaltLength}, got ${this.sessionSalt.length}`);\r\n }\r\n \r\n // MITM Protection: Check salt integrity\r\n const saltFingerprint = await window.EnhancedSecureCryptoUtils.calculateKeyFingerprint(this.sessionSalt);\r\n \r\n this._secureLog('info', 'Session salt validated successfully', {\r\n operationId: operationId,\r\n saltLength: this.sessionSalt.length,\r\n saltFingerprint: saltFingerprint.substring(0, 8)\r\n });\r\n \r\n // ============================================\r\n // PHASE 4: SECURE GENERATION OF OUR KEYS\r\n // ============================================\r\n \r\n // Secure generation of our keys via mutex\r\n const keyPairs = await this._generateEncryptionKeys();\r\n this.ecdhKeyPair = keyPairs.ecdhKeyPair;\r\n this.ecdsaKeyPair = keyPairs.ecdsaKeyPair;\r\n \r\n // Additional validation of generated keys\r\n if (!(this.ecdhKeyPair?.privateKey instanceof CryptoKey)) {\r\n this._secureLog('error', 'Local ECDH private key is not a CryptoKey', {\r\n operationId: operationId,\r\n hasKeyPair: !!this.ecdhKeyPair,\r\n privateKeyType: typeof this.ecdhKeyPair?.privateKey,\r\n privateKeyAlgorithm: this.ecdhKeyPair?.privateKey?.algorithm?.name\r\n });\r\n throw new Error('Local ECDH private key is not a valid CryptoKey');\r\n }\r\n \r\n // ============================================\r\n // PHASE 5: IMPORT AND VERIFY PEER KEYS\r\n // ============================================\r\n \r\n // Import peer ECDSA public key for signature verification (support both formats)\r\n let peerECDSAPublicKey;\r\n \r\n try {\r\n const ecdsaKey = offerData.d || offerData.ecdsaPublicKey;\r\n peerECDSAPublicKey = await crypto.subtle.importKey(\r\n 'spki',\r\n new Uint8Array(ecdsaKey.keyData),\r\n {\r\n name: 'ECDSA',\r\n namedCurve: 'P-384'\r\n },\r\n false,\r\n ['verify']\r\n );\r\n } catch (error) {\r\n this._throwSecureError(error, 'ecdsa_key_import');\r\n }\r\n \r\n // ============================================\r\n // PHASE 6: IMPORT AND VERIFY ECDH KEY\r\n // ============================================\r\n \r\n // Import and verify ECDH public key using verified ECDSA key (support both formats)\r\n let peerECDHPublicKey;\r\n \r\n try {\r\n const ecdhKey = offerData.e || offerData.ecdhPublicKey;\r\n peerECDHPublicKey = await window.EnhancedSecureCryptoUtils.importSignedPublicKey(\r\n ecdhKey,\r\n peerECDSAPublicKey,\r\n 'ECDH'\r\n );\r\n } catch (error) {\r\n this._secureLog('error', 'Failed to import signed ECDH public key', {\r\n operationId: operationId,\r\n errorType: error.constructor.name\r\n });\r\n this._throwSecureError(error, 'ecdh_key_import');\r\n }\r\n \r\n // Final validation of ECDH key\r\n if (!(peerECDHPublicKey instanceof CryptoKey)) {\r\n this._secureLog('error', 'Peer ECDH public key is not a CryptoKey', {\r\n operationId: operationId,\r\n publicKeyType: typeof peerECDHPublicKey,\r\n publicKeyAlgorithm: peerECDHPublicKey?.algorithm?.name\r\n });\r\n throw new Error('Peer ECDH public key is not a valid CryptoKey');\r\n }\r\n \r\n // Save peer key for PFS rotation\r\n this.peerPublicKey = peerECDHPublicKey;\r\n \r\n // ============================================\r\n // PHASE 7: DERIVE SHARED ENCRYPTION KEYS\r\n // ============================================\r\n \r\n // Derive shared keys with metadata protection\r\n let derivedKeys;\r\n \r\n try {\r\n this._secureLog('debug', 'About to call deriveSharedKeys', {\r\n operationId: operationId,\r\n privateKeyType: typeof this.ecdhKeyPair.privateKey,\r\n publicKeyType: typeof peerECDHPublicKey,\r\n saltLength: this.sessionSalt?.length,\r\n privateKeyAlgorithm: this.ecdhKeyPair.privateKey?.algorithm?.name,\r\n publicKeyAlgorithm: peerECDHPublicKey?.algorithm?.name\r\n });\r\n \r\n derivedKeys = await window.EnhancedSecureCryptoUtils.deriveSharedKeys(\r\n this.ecdhKeyPair.privateKey,\r\n peerECDHPublicKey,\r\n this.sessionSalt\r\n );\r\n \r\n this._secureLog('debug', 'deriveSharedKeys completed successfully', {\r\n operationId: operationId,\r\n hasMessageKey: !!derivedKeys.messageKey,\r\n hasMacKey: !!derivedKeys.macKey,\r\n hasPfsKey: !!derivedKeys.pfsKey,\r\n hasMetadataKey: !!derivedKeys.metadataKey,\r\n hasFingerprint: !!derivedKeys.fingerprint\r\n });\r\n } catch (error) {\r\n this._secureLog('error', 'Failed to derive shared keys', {\r\n operationId: operationId,\r\n errorType: error.constructor.name,\r\n errorMessage: error.message,\r\n errorStack: error.stack,\r\n privateKeyType: typeof this.ecdhKeyPair.privateKey,\r\n publicKeyType: typeof peerECDHPublicKey,\r\n saltLength: this.sessionSalt?.length,\r\n privateKeyAlgorithm: this.ecdhKeyPair.privateKey?.algorithm?.name,\r\n publicKeyAlgorithm: peerECDHPublicKey?.algorithm?.name\r\n });\r\n this._throwSecureError(error, 'key_derivation');\r\n }\r\n \r\n // Securely set keys via helper\r\n await this._setEncryptionKeys(\r\n derivedKeys.messageKey,\r\n derivedKeys.macKey,\r\n derivedKeys.metadataKey,\r\n derivedKeys.fingerprint\r\n );\r\n \r\n // Additional validation of installed keys\r\n if (!(this.encryptionKey instanceof CryptoKey) || \r\n !(this.macKey instanceof CryptoKey) || \r\n !(this.metadataKey instanceof CryptoKey)) {\r\n \r\n this._secureLog('error', 'Invalid key types after derivation', {\r\n operationId: operationId,\r\n encryptionKeyType: typeof this.encryptionKey,\r\n macKeyType: typeof this.macKey,\r\n metadataKeyType: typeof this.metadataKey\r\n });\r\n throw new Error('Invalid key types after derivation');\r\n }\r\n \r\n // Set verification code from offer\r\n this.verificationCode = offerData.verificationCode;\r\n \r\n this._secureLog('info', 'Encryption keys derived and set successfully', {\r\n operationId: operationId,\r\n hasEncryptionKey: !!this.encryptionKey,\r\n hasMacKey: !!this.macKey,\r\n hasMetadataKey: !!this.metadataKey,\r\n hasKeyFingerprint: !!this.keyFingerprint,\r\n mitmProtection: 'enabled',\r\n signatureVerified: true\r\n });\r\n \r\n // ============================================\r\n // PHASE 8: UPDATE SECURITY FEATURES\r\n // ============================================\r\n \r\n // Atomic update of security features\r\n this._updateSecurityFeatures({\r\n hasEncryption: true,\r\n hasECDH: true,\r\n hasECDSA: true,\r\n hasMutualAuth: true,\r\n hasMetadataProtection: true,\r\n hasEnhancedReplayProtection: true,\r\n hasNonExtractableKeys: true,\r\n hasRateLimiting: true,\r\n hasEnhancedValidation: true,\r\n hasPFS: true\r\n });\r\n \r\n // PFS: Initialize key version tracking\r\n this.currentKeyVersion = 0;\r\n this.lastKeyRotation = Date.now();\r\n this.keyVersions.set(0, {\r\n salt: this.sessionSalt,\r\n timestamp: this.lastKeyRotation,\r\n messageCount: 0\r\n });\r\n \r\n // ============================================\r\n // PHASE 9: CREATE AUTHENTICATION PROOF\r\n // ============================================\r\n \r\n // Create proof for mutual authentication\r\n let authProof;\r\n \r\n if (offerData.authChallenge) {\r\n try {\r\n authProof = await window.EnhancedSecureCryptoUtils.createAuthProof(\r\n offerData.authChallenge,\r\n this.ecdsaKeyPair.privateKey,\r\n this.ecdsaKeyPair.publicKey\r\n );\r\n } catch (error) {\r\n this._secureLog('error', 'Failed to create authentication proof', {\r\n operationId: operationId,\r\n errorType: error.constructor.name\r\n });\r\n this._throwSecureError(error, 'authentication_proof_creation');\r\n }\r\n } else {\r\n this._secureLog('warn', 'No auth challenge in offer - mutual auth disabled', {\r\n operationId: operationId\r\n });\r\n }\r\n \r\n // ============================================\r\n // PHASE 10: INITIALIZE WEBRTC\r\n // ============================================\r\n \r\n this.isInitiator = false;\r\n this.onStatusChange('connecting');\r\n \r\n this.onKeyExchange(this.keyFingerprint);\r\n \r\n // Create peer connection first\r\n this.createPeerConnection();\r\n \r\n // Validate DTLS fingerprint before setting remote description\r\n if (this.strictDTLSValidation) {\r\n try {\r\n const receivedFingerprint = this._extractDTLSFingerprintFromSDP(offerData.sdp);\r\n \r\n if (this.expectedDTLSFingerprint) {\r\n await this._validateDTLSFingerprint(receivedFingerprint, this.expectedDTLSFingerprint, 'offer_validation');\r\n } else {\r\n // Store fingerprint for future validation (first connection)\r\n this.expectedDTLSFingerprint = receivedFingerprint;\r\n this._secureLog('info', 'Stored DTLS fingerprint for future validation', {\r\n fingerprint: receivedFingerprint,\r\n context: 'first_connection'\r\n });\r\n }\r\n } catch (error) {\r\n this._secureLog('warn', 'DTLS fingerprint validation failed - continuing in fallback mode', { \r\n error: error.message,\r\n context: 'offer_validation'\r\n });\r\n // Continue without strict fingerprint validation for first connection\r\n // This allows the connection to proceed while maintaining security awareness\r\n }\r\n } else {\r\n this._secureLog('info', 'DTLS fingerprint validation disabled - proceeding without validation');\r\n }\r\n\r\n // Set remote description from offer\r\n try {\r\n this._secureLog('debug', 'Setting remote description from offer', {\r\n operationId: operationId,\r\n sdpLength: offerData.sdp?.length || 0\r\n });\r\n \r\n await this.peerConnection.setRemoteDescription(new RTCSessionDescription({\r\n type: 'offer',\r\n sdp: offerData.s || offerData.sdp\r\n }));\r\n \r\n this._secureLog('debug', 'Remote description set successfully', {\r\n operationId: operationId,\r\n signalingState: this.peerConnection.signalingState\r\n });\r\n } catch (error) {\r\n this._secureLog('error', 'Failed to set remote description', { \r\n error: error.message,\r\n operationId: operationId\r\n });\r\n this._throwSecureError(error, 'webrtc_remote_description');\r\n }\r\n \r\n this._secureLog('debug', 'Remote description set successfully', {\r\n operationId: operationId,\r\n connectionState: this.peerConnection.connectionState,\r\n signalingState: this.peerConnection.signalingState\r\n });\r\n \r\n // ============================================\r\n // PHASE 11: CREATE SDP ANSWER\r\n // ============================================\r\n \r\n // Create WebRTC answer\r\n let answer;\r\n \r\n try {\r\n answer = await this.peerConnection.createAnswer({\r\n offerToReceiveAudio: false,\r\n offerToReceiveVideo: false\r\n });\r\n } catch (error) {\r\n this._throwSecureError(error, 'webrtc_create_answer');\r\n }\r\n \r\n // Set local description\r\n try {\r\n await this.peerConnection.setLocalDescription(answer);\r\n } catch (error) {\r\n this._throwSecureError(error, 'webrtc_local_description');\r\n }\r\n \r\n // Extract and store our DTLS fingerprint for out-of-band verification\r\n try {\r\n const ourFingerprint = this._extractDTLSFingerprintFromSDP(answer.sdp);\r\n this.expectedDTLSFingerprint = ourFingerprint;\r\n \r\n this._secureLog('info', 'Generated DTLS fingerprint for out-of-band verification', {\r\n fingerprint: ourFingerprint,\r\n context: 'answer_creation'\r\n });\r\n \r\n // Notify UI that fingerprint is ready for out-of-band verification\r\n this.deliverMessageToUI(`DTLS fingerprint ready for verification: ${ourFingerprint}`, 'system');\r\n } catch (error) {\r\n this._secureLog('error', 'Failed to extract DTLS fingerprint from answer', { error: error.message });\r\n // Continue without fingerprint validation (fallback mode)\r\n }\r\n \r\n \r\n // Await ICE gathering\r\n await this.waitForIceGathering();\r\n \r\n this._secureLog('debug', 'ICE gathering completed for answer', {\r\n operationId: operationId,\r\n iceGatheringState: this.peerConnection.iceGatheringState,\r\n connectionState: this.peerConnection.connectionState\r\n });\r\n \r\n // ============================================\r\n // PHASE 12: EXPORT OUR KEYS\r\n // ============================================\r\n \r\n // Export our keys with signatures\r\n const ecdhPublicKeyData = await window.EnhancedSecureCryptoUtils.exportPublicKeyWithSignature(\r\n this.ecdhKeyPair.publicKey,\r\n this.ecdsaKeyPair.privateKey,\r\n 'ECDH'\r\n );\r\n \r\n const ecdsaPublicKeyData = await window.EnhancedSecureCryptoUtils.exportPublicKeyWithSignature(\r\n this.ecdsaKeyPair.publicKey,\r\n this.ecdsaKeyPair.privateKey,\r\n 'ECDSA'\r\n );\r\n \r\n if (!ecdhPublicKeyData || typeof ecdhPublicKeyData !== 'object') {\r\n this._secureLog('error', 'CRITICAL: ECDH key export failed - invalid object structure', { operationId });\r\n throw new Error('CRITICAL SECURITY FAILURE: ECDH key export validation failed - hard abort required');\r\n }\r\n \r\n if (!ecdhPublicKeyData.keyData || !ecdhPublicKeyData.signature) {\r\n this._secureLog('error', 'CRITICAL: ECDH key export incomplete - missing keyData or signature', { \r\n operationId,\r\n hasKeyData: !!ecdhPublicKeyData.keyData,\r\n hasSignature: !!ecdhPublicKeyData.signature \r\n });\r\n throw new Error('CRITICAL SECURITY FAILURE: ECDH key export incomplete - hard abort required');\r\n }\r\n \r\n if (!ecdsaPublicKeyData || typeof ecdsaPublicKeyData !== 'object') {\r\n this._secureLog('error', 'CRITICAL: ECDSA key export failed - invalid object structure', { operationId });\r\n throw new Error('CRITICAL SECURITY FAILURE: ECDSA key export validation failed - hard abort required');\r\n }\r\n \r\n if (!ecdsaPublicKeyData.keyData || !ecdsaPublicKeyData.signature) {\r\n this._secureLog('error', 'CRITICAL: ECDSA key export incomplete - missing keyData or signature', { \r\n operationId,\r\n hasKeyData: !!ecdsaPublicKeyData.keyData,\r\n hasSignature: !!ecdsaPublicKeyData.signature \r\n });\r\n throw new Error('CRITICAL SECURITY FAILURE: ECDSA key export incomplete - hard abort required');\r\n }\r\n \r\n // ============================================\r\n // PHASE 13: SECURITY LEVEL CALCULATION\r\n // ============================================\r\n \r\n // All security features are enabled by default\r\n const securityLevel = {\r\n level: 'MAXIMUM',\r\n score: 100,\r\n color: 'green',\r\n details: 'All security features enabled by default',\r\n passedChecks: 10,\r\n totalChecks: 10,\r\n isRealData: true\r\n };\r\n \r\n // ============================================\r\n // PHASE 14: CREATE ANSWER PACKAGE\r\n // ============================================\r\n \r\n const currentTimestamp = Date.now();\r\n \r\n // Create compact answer package for smaller QR codes\r\n const answerPackage = {\r\n // Core information (minimal)\r\n t: 'answer', // type\r\n s: this.peerConnection.localDescription.sdp, // sdp\r\n v: '4.0', // version\r\n ts: currentTimestamp, // timestamp\r\n \r\n // Cryptographic keys (essential)\r\n e: ecdhPublicKeyData, // ecdhPublicKey\r\n d: ecdsaPublicKeyData, // ecdsaPublicKey\r\n \r\n // Authentication (essential)\r\n ap: authProof, // authProof\r\n \r\n // Security metadata (simplified)\r\n slv: 'MAX', // securityLevel\r\n \r\n // Session confirmation (simplified)\r\n sc: {\r\n sf: saltFingerprint.substring(0, 12), // saltFingerprint (12 chars)\r\n kd: true, // keyDerivationSuccess\r\n ma: true // mutualAuthEnabled\r\n }\r\n };\r\n \r\n // ============================================\r\n // PHASE 15: VALIDATION AND LOGGING\r\n // ============================================\r\n \r\n // Final validation of the answer package (support both formats)\r\n const hasSDP = answerPackage.s || answerPackage.sdp;\r\n const hasECDH = answerPackage.e || answerPackage.ecdhPublicKey;\r\n const hasECDSA = answerPackage.d || answerPackage.ecdsaPublicKey;\r\n \r\n if (!hasSDP || !hasECDH || !hasECDSA) {\r\n throw new Error('Generated answer package is incomplete');\r\n }\r\n \r\n this._secureLog('info', 'Enhanced secure answer created successfully', {\r\n operationId: operationId,\r\n version: answerPackage.version,\r\n hasECDSA: true,\r\n hasMutualAuth: !!authProof,\r\n hasSessionConfirmation: !!answerPackage.sessionConfirmation,\r\n securityLevel: securityLevel.level,\r\n timestamp: currentTimestamp,\r\n processingTime: currentTimestamp - offerData.timestamp\r\n });\r\n \r\n // Dispatch event about new connection\r\n document.dispatchEvent(new CustomEvent('new-connection', {\r\n detail: { \r\n type: 'answer',\r\n timestamp: currentTimestamp,\r\n securityLevel: securityLevel.level,\r\n operationId: operationId\r\n }\r\n }));\r\n \r\n // ============================================\r\n // PHASE 16: SCHEDULE SECURITY CALCULATIONS\r\n // ============================================\r\n \r\n // Plan security calculation after connection\r\n setTimeout(async () => {\r\n try {\r\n const realSecurityData = await this.calculateAndReportSecurityLevel();\r\n if (realSecurityData) {\r\n this.notifySecurityUpdate();\r\n this._secureLog('info', 'Post-connection security level calculated', {\r\n operationId: operationId,\r\n level: realSecurityData.level\r\n });\r\n }\r\n } catch (error) {\r\n this._secureLog('error', 'Error calculating post-connection security', {\r\n operationId: operationId,\r\n errorType: error.constructor.name\r\n });\r\n }\r\n }, 1000);\r\n \r\n // Retry if the first calculation fails\r\n setTimeout(async () => {\r\n if (!this.lastSecurityCalculation || this.lastSecurityCalculation.score < 50) {\r\n this._secureLog('info', 'Retrying security calculation', {\r\n operationId: operationId\r\n });\r\n await this.calculateAndReportSecurityLevel();\r\n this.notifySecurityUpdate();\r\n }\r\n }, 3000);\r\n \r\n // Final security update\r\n this.notifySecurityUpdate();\r\n \r\n // ============================================\r\n // PHASE 17: RETURN RESULT\r\n // ============================================\r\n \r\n return answerPackage;\r\n \r\n } catch (error) {\r\n // ============================================\r\n // ERROR HANDLING\r\n // ============================================\r\n \r\n this._secureLog('error', 'Enhanced secure answer creation failed in critical section', {\r\n operationId: operationId,\r\n errorType: error.constructor.name,\r\n errorMessage: error.message,\r\n phase: this._determineAnswerErrorPhase(error),\r\n offerAge: offerData?.timestamp ? Date.now() - offerData.timestamp : 'unknown'\r\n });\r\n \r\n // Cleanup state on error\r\n this._cleanupFailedAnswerCreation();\r\n \r\n // Update status\r\n this.onStatusChange('disconnected');\r\n \r\n // Special handling of security errors\r\n if (this.onAnswerError) {\r\n if (error.message.includes('too old') || error.message.includes('replay')) {\r\n this.onAnswerError('replay_attack', error.message);\r\n } else if (error.message.includes('MITM') || error.message.includes('signature')) {\r\n this.onAnswerError('security_violation', error.message);\r\n } else if (error.message.includes('validation') || error.message.includes('format')) {\r\n this.onAnswerError('invalid_format', error.message);\r\n } else {\r\n this.onAnswerError('general_error', error.message);\r\n }\r\n }\r\n \r\n // Re-throw for upper-level handling\r\n throw error;\r\n }\r\n }, 20000); // 20 seconds timeout for the entire answer creation (longer than offer)\r\n }\r\n\r\n /**\r\n * HELPER: Determine error phase for answer\r\n */\r\n _determineAnswerErrorPhase(error) {\r\n const message = error.message.toLowerCase();\r\n \r\n if (message.includes('validation') || message.includes('format')) return 'offer_validation';\r\n if (message.includes('rate limit')) return 'rate_limiting';\r\n if (message.includes('replay') || message.includes('too old')) return 'replay_protection';\r\n if (message.includes('salt')) return 'salt_validation';\r\n if (message.includes('key pair') || message.includes('generate')) return 'key_generation';\r\n if (message.includes('import') || message.includes('ecdsa') || message.includes('ecdh')) return 'key_import';\r\n if (message.includes('signature') || message.includes('mitm')) return 'signature_verification';\r\n if (message.includes('derive') || message.includes('shared')) return 'key_derivation';\r\n if (message.includes('auth') || message.includes('proof')) return 'authentication';\r\n if (message.includes('remote description') || message.includes('local description')) return 'webrtc_setup';\r\n if (message.includes('answer') || message.includes('sdp')) return 'sdp_creation';\r\n if (message.includes('export')) return 'key_export';\r\n if (message.includes('security level')) return 'security_calculation';\r\n \r\n return 'unknown';\r\n }\r\n\r\n /**\r\n * HELPER: Cleanup state after failed answer creation\r\n */\r\n /**\r\n * Secure cleanup state after failed answer creation\r\n */\r\n _cleanupFailedAnswerCreation() {\r\n try {\r\n // Secure wipe of cryptographic materials\r\n this._secureCleanupCryptographicMaterials();\r\n \r\n // Secure wipe of PFS key versions\r\n this.currentKeyVersion = 0;\r\n this.keyVersions.clear();\r\n this.oldKeys.clear();\r\n \r\n // Close peer connection if created\r\n if (this.peerConnection) {\r\n this.peerConnection.close();\r\n this.peerConnection = null;\r\n }\r\n \r\n // Clear data channel\r\n if (this.dataChannel) {\r\n this.dataChannel.close();\r\n this.dataChannel = null;\r\n }\r\n \r\n // Reset flags and counters\r\n this.isInitiator = false;\r\n this.isVerified = false;\r\n this.sequenceNumber = 0;\r\n this.expectedSequenceNumber = 0;\r\n this.messageCounter = 0;\r\n this.processedMessageIds.clear();\r\n this.replayWindow.clear(); // Clear replay window\r\n \r\n // Reset security features to baseline\r\n this._updateSecurityFeatures({\r\n hasEncryption: false,\r\n hasECDH: false,\r\n hasECDSA: false,\r\n hasMutualAuth: false,\r\n hasMetadataProtection: false,\r\n hasEnhancedReplayProtection: false,\r\n hasNonExtractableKeys: false,\r\n hasEnhancedValidation: false,\r\n hasPFS: false\r\n });\r\n \r\n // Schedule natural cleanup\r\n this._forceGarbageCollection().catch(error => {\r\n this._secureLog('error', 'Cleanup failed during answer cleanup', {\r\n errorType: error?.constructor?.name || 'Unknown'\r\n });\r\n });\r\n \r\n this._secureLog('debug', 'Failed answer creation cleanup completed with secure memory wipe');\r\n \r\n } catch (cleanupError) {\r\n this._secureLog('error', 'Error during answer creation cleanup', {\r\n errorType: cleanupError.constructor.name,\r\n errorMessage: cleanupError.message\r\n });\r\n }\r\n }\r\n\r\n /**\r\n * HELPER: Securely set encryption keys (if not set yet)\r\n */\r\n async _setEncryptionKeys(encryptionKey, macKey, metadataKey, keyFingerprint) {\r\n return this._withMutex('keyOperation', async (operationId) => {\r\n this._secureLog('info', 'Setting encryption keys with mutex', {\r\n operationId: operationId\r\n });\r\n \r\n // Validate all keys before setting\r\n if (!(encryptionKey instanceof CryptoKey) ||\r\n !(macKey instanceof CryptoKey) ||\r\n !(metadataKey instanceof CryptoKey)) {\r\n throw new Error('Invalid key types provided');\r\n }\r\n \r\n if (!keyFingerprint || typeof keyFingerprint !== 'string') {\r\n throw new Error('Invalid key fingerprint provided');\r\n }\r\n \r\n // Atomically set all keys\r\n const oldKeys = {\r\n encryptionKey: this.encryptionKey,\r\n macKey: this.macKey,\r\n metadataKey: this.metadataKey,\r\n keyFingerprint: this.keyFingerprint\r\n };\r\n \r\n try {\r\n this.encryptionKey = encryptionKey;\r\n this.macKey = macKey;\r\n this.metadataKey = metadataKey;\r\n this.keyFingerprint = keyFingerprint;\r\n \r\n // Reset counters\r\n this.sequenceNumber = 0;\r\n this.expectedSequenceNumber = 0;\r\n this.messageCounter = 0;\r\n this.processedMessageIds.clear();\r\n this.replayWindow.clear(); // Clear replay window\r\n \r\n this._secureLog('info', 'Encryption keys set successfully', {\r\n operationId: operationId,\r\n hasAllKeys: !!(this.encryptionKey && this.macKey && this.metadataKey),\r\n hasFingerprint: !!this.keyFingerprint\r\n });\r\n \r\n return true;\r\n \r\n } catch (error) {\r\n // Roll back on error\r\n this.encryptionKey = oldKeys.encryptionKey;\r\n this.macKey = oldKeys.macKey;\r\n this.metadataKey = oldKeys.metadataKey;\r\n this.keyFingerprint = oldKeys.keyFingerprint;\r\n \r\n this._secureLog('error', 'Key setting failed, rolled back', {\r\n operationId: operationId,\r\n errorType: error.constructor.name\r\n });\r\n \r\n throw error;\r\n }\r\n });\r\n }\r\n\r\n async handleSecureAnswer(answerData) {\r\n try {\r\n \r\n if (!answerData || typeof answerData !== 'object' || Array.isArray(answerData)) {\r\n this._secureLog('error', 'CRITICAL: Invalid answer data structure', { \r\n hasAnswerData: !!answerData,\r\n answerDataType: typeof answerData,\r\n isArray: Array.isArray(answerData)\r\n });\r\n throw new Error('CRITICAL SECURITY FAILURE: Answer data must be a non-null object');\r\n }\r\n \r\n // Support both compact and legacy answer formats\r\n const isCompactAnswer = answerData.t === 'answer' && answerData.s;\r\n const isLegacyAnswer = answerData.type === 'enhanced_secure_answer' && answerData.sdp;\r\n \r\n if (!isCompactAnswer && !isLegacyAnswer) {\r\n this._secureLog('error', 'CRITICAL: Invalid answer format', { \r\n type: answerData.type || answerData.t,\r\n hasSdp: !!(answerData.sdp || answerData.s)\r\n });\r\n throw new Error('CRITICAL SECURITY FAILURE: Invalid answer format - hard abort required');\r\n }\r\n\r\n // CRITICAL: Strict validation of ECDH public key structure\r\n // Support both full and compact key names\r\n const ecdhKey = answerData.ecdhPublicKey || answerData.e;\r\n const ecdsaKey = answerData.ecdsaPublicKey || answerData.d;\r\n \r\n if (!ecdhKey || typeof ecdhKey !== 'object' || Array.isArray(ecdhKey)) {\r\n this._secureLog('error', 'CRITICAL: Invalid ECDH public key structure in answer', { \r\n hasEcdhKey: !!ecdhKey,\r\n ecdhKeyType: typeof ecdhKey,\r\n isArray: Array.isArray(ecdhKey),\r\n availableKeys: Object.keys(answerData)\r\n });\r\n throw new Error('CRITICAL SECURITY FAILURE: Missing or invalid ECDH public key structure');\r\n }\r\n \r\n if (!ecdhKey.keyData || !ecdhKey.signature) {\r\n this._secureLog('error', 'CRITICAL: ECDH key missing keyData or signature in answer', { \r\n hasKeyData: !!ecdhKey.keyData,\r\n hasSignature: !!ecdhKey.signature\r\n });\r\n throw new Error('CRITICAL SECURITY FAILURE: ECDH key missing keyData or signature');\r\n }\r\n\r\n // CRITICAL: Strict validation of ECDSA public key structure\r\n if (!ecdsaKey || typeof ecdsaKey !== 'object' || Array.isArray(ecdsaKey)) {\r\n this._secureLog('error', 'CRITICAL: Invalid ECDSA public key structure in answer', { \r\n hasEcdsaKey: !!ecdsaKey,\r\n ecdsaKeyType: typeof ecdsaKey,\r\n isArray: Array.isArray(ecdsaKey)\r\n });\r\n throw new Error('CRITICAL SECURITY FAILURE: Missing or invalid ECDSA public key structure');\r\n }\r\n \r\n if (!ecdsaKey.keyData || !ecdsaKey.signature) {\r\n this._secureLog('error', 'CRITICAL: ECDSA key missing keyData or signature in answer', { \r\n hasKeyData: !!ecdsaKey.keyData,\r\n hasSignature: !!ecdsaKey.signature\r\n });\r\n throw new Error('CRITICAL SECURITY FAILURE: ECDSA key missing keyData or signature');\r\n }\r\n\r\n // Additional MITM protection: Validate answer data structure\r\n // Support both compact and legacy formats\r\n const timestamp = answerData.ts || answerData.timestamp;\r\n const version = answerData.v || answerData.version;\r\n \r\n if (!timestamp || !version) {\r\n throw new Error('Missing required fields in response data \u2013 possible MITM attack');\r\n }\r\n\r\n // MITM Protection: Verify session ID if present (for enhanced security)\r\n if (answerData.sessionId && this.sessionId && answerData.sessionId !== this.sessionId) {\r\n window.EnhancedSecureCryptoUtils.secureLog.log('error', 'Session ID mismatch detected - possible MITM attack', {});\r\n throw new Error('Session ID mismatch \u2013 possible MITM attack');\r\n }\r\n\r\n // Check for replay attacks (reject answers older than 1 hour)\r\n const answerAge = Date.now() - answerData.timestamp;\r\n if (answerAge > 3600000) { // 1 hour in milliseconds\r\n window.EnhancedSecureCryptoUtils.secureLog.log('error', 'Answer data is too old - possible replay attack', {\r\n answerAge: answerAge,\r\n timestamp: answerData.timestamp\r\n });\r\n \r\n // Notify the main code about the replay attack error\r\n if (this.onAnswerError) {\r\n this.onAnswerError('replay_attack', 'Response data is too old \u2013 possible replay attack');\r\n }\r\n \r\n throw new Error('Response data is too old \u2013 possible replay attack');\r\n }\r\n\r\n // Check protocol version compatibility\r\n if (answerData.version !== '4.0') {\r\n window.EnhancedSecureCryptoUtils.secureLog.log('warn', 'Incompatible protocol version in answer', {\r\n expectedVersion: '4.0',\r\n receivedVersion: answerData.version\r\n });\r\n }\r\n\r\n // Import ECDSA public key for verification (self-signed)\r\n const peerECDSAPublicKey = await crypto.subtle.importKey(\r\n 'spki',\r\n new Uint8Array(ecdsaKey.keyData),\r\n {\r\n name: 'ECDSA',\r\n namedCurve: 'P-384'\r\n },\r\n false,\r\n ['verify']\r\n );\r\n\r\n\r\n // Now import and verify the ECDH public key using the verified ECDSA key\r\n const peerPublicKey = await window.EnhancedSecureCryptoUtils.importPublicKeyFromSignedPackage(\r\n ecdhKey,\r\n peerECDSAPublicKey\r\n );\r\n \r\n // Additional MITM protection: Verify session salt integrity\r\n if (!this.sessionSalt || this.sessionSalt.length !== 64) {\r\n window.EnhancedSecureCryptoUtils.secureLog.log('error', 'Invalid session salt detected - possible session hijacking', {\r\n saltLength: this.sessionSalt ? this.sessionSalt.length : 0\r\n });\r\n throw new Error('Invalid session salt \u2013 possible session hijacking attempt');\r\n }\r\n\r\n // Verify that the session salt hasn't been tampered with\r\n const expectedSaltHash = await window.EnhancedSecureCryptoUtils.calculateKeyFingerprint(this.sessionSalt);\r\n window.EnhancedSecureCryptoUtils.secureLog.log('info', 'Session salt integrity verified', {\r\n saltFingerprint: expectedSaltHash.substring(0, 8)\r\n });\r\n\r\n // Additional validation: Ensure all keys are CryptoKey instances before derivation\r\n if (!(this.ecdhKeyPair?.privateKey instanceof CryptoKey)) {\r\n window.EnhancedSecureCryptoUtils.secureLog.log('error', 'Local ECDH private key is not a CryptoKey in handleSecureAnswer', {\r\n hasKeyPair: !!this.ecdhKeyPair,\r\n privateKeyType: typeof this.ecdhKeyPair?.privateKey,\r\n privateKeyAlgorithm: this.ecdhKeyPair?.privateKey?.algorithm?.name\r\n });\r\n throw new Error('Local ECDH private key is not a CryptoKey');\r\n }\r\n \r\n if (!(peerPublicKey instanceof CryptoKey)) {\r\n window.EnhancedSecureCryptoUtils.secureLog.log('error', 'Peer ECDH public key is not a CryptoKey in handleSecureAnswer', {\r\n publicKeyType: typeof peerPublicKey,\r\n publicKeyAlgorithm: peerPublicKey?.algorithm?.name\r\n });\r\n throw new Error('Peer ECDH public key is not a CryptoKey');\r\n }\r\n\r\n // Store peer's public key for PFS key rotation\r\n this.peerPublicKey = peerPublicKey;\r\n \r\n // Initialize connection ID if not already set\r\n if (!this.connectionId) {\r\n this.connectionId = Array.from(crypto.getRandomValues(new Uint8Array(8)))\r\n .map(b => b.toString(16).padStart(2, '0')).join('');\r\n }\r\n\r\n \r\n const derivedKeys = await window.EnhancedSecureCryptoUtils.deriveSharedKeys(\r\n this.ecdhKeyPair.privateKey,\r\n peerPublicKey,\r\n this.sessionSalt\r\n );\r\n \r\n this.encryptionKey = derivedKeys.messageKey;\r\n this.macKey = derivedKeys.macKey;\r\n this.metadataKey = derivedKeys.metadataKey;\r\n this.keyFingerprint = derivedKeys.fingerprint;\r\n this.sequenceNumber = 0;\r\n this.expectedSequenceNumber = 0;\r\n this.messageCounter = 0;\r\n this.processedMessageIds.clear();\r\n this.replayWindow.clear(); // Clear replay window\r\n // Validate that all keys are properly set\r\n if (!(this.encryptionKey instanceof CryptoKey) || \r\n !(this.macKey instanceof CryptoKey) || \r\n !(this.metadataKey instanceof CryptoKey)) {\r\n window.EnhancedSecureCryptoUtils.secureLog.log('error', 'Invalid key types after derivation in handleSecureAnswer', {\r\n encryptionKeyType: typeof this.encryptionKey,\r\n macKeyType: typeof this.macKey,\r\n metadataKeyType: typeof this.metadataKey,\r\n encryptionKeyAlgorithm: this.encryptionKey?.algorithm?.name,\r\n macKeyAlgorithm: this.macKey?.algorithm?.name,\r\n metadataKeyAlgorithm: this.metadataKey?.algorithm?.name\r\n });\r\n throw new Error('Invalid key types after export');\r\n }\r\n \r\n this._secureLog('info', 'Encryption keys set in handleSecureAnswer', {\r\n hasEncryptionKey: !!this.encryptionKey,\r\n hasMacKey: !!this.macKey,\r\n hasMetadataKey: !!this.metadataKey,\r\n hasKeyFingerprint: !!this.keyFingerprint,\r\n mitmProtection: 'enabled',\r\n signatureVerified: true\r\n });\r\n \r\n // Update security features for initiator after successful key exchange\r\n this.securityFeatures.hasMutualAuth = true;\r\n this.securityFeatures.hasMetadataProtection = true;\r\n this.securityFeatures.hasEnhancedReplayProtection = true;\r\n this.securityFeatures.hasPFS = true;\r\n \r\n // PFS: Initialize key version tracking\r\n this.currentKeyVersion = 0;\r\n this.lastKeyRotation = Date.now();\r\n this.keyVersions.set(0, {\r\n salt: this.sessionSalt,\r\n timestamp: this.lastKeyRotation,\r\n messageCount: 0\r\n });\r\n \r\n this.onKeyExchange(this.keyFingerprint);\r\n\r\n // Compute SAS for MITM protection (Offer side - Answer handler)\r\n try {\r\n const remoteFP = this._extractDTLSFingerprintFromSDP(answerData.sdp || answerData.s); \r\n const localFP = this.expectedDTLSFingerprint; \r\n const keyBytes = this._decodeKeyFingerprint(this.keyFingerprint); \r\n\r\n this.verificationCode = await this._computeSAS(keyBytes, localFP, remoteFP);\r\n this.onStatusChange?.('verifying'); \r\n this.onVerificationRequired(this.verificationCode);\r\n \r\n // CRITICAL: Store SAS code to send when data channel opens\r\n this.pendingSASCode = this.verificationCode;\r\n \r\n this._secureLog('info', 'SAS verification code generated for MITM protection (Offer side)', {\r\n sasCode: this.verificationCode,\r\n localFP: localFP.substring(0, 16) + '...',\r\n remoteFP: remoteFP.substring(0, 16) + '...',\r\n timestamp: Date.now()\r\n });\r\n } catch (sasError) {\r\n this._secureLog('error', 'SAS computation failed in handleSecureAnswer (Offer side)', {\r\n errorType: sasError?.constructor?.name || 'Unknown'\r\n });\r\n this._secureLog('error', 'SAS computation failed in handleSecureAnswer (Offer side)', {\r\n error: sasError.message,\r\n stack: sasError.stack,\r\n timestamp: Date.now()\r\n });\r\n }\r\n\r\n // Validate DTLS fingerprint before setting remote description\r\n if (this.strictDTLSValidation) {\r\n try {\r\n const receivedFingerprint = this._extractDTLSFingerprintFromSDP(answerData.sdp || answerData.s);\r\n \r\n if (this.expectedDTLSFingerprint) {\r\n await this._validateDTLSFingerprint(receivedFingerprint, this.expectedDTLSFingerprint, 'answer_validation');\r\n } else {\r\n // Store fingerprint for future validation (first connection)\r\n this.expectedDTLSFingerprint = receivedFingerprint;\r\n this._secureLog('info', 'Stored DTLS fingerprint for future validation', {\r\n fingerprint: receivedFingerprint,\r\n context: 'first_connection'\r\n });\r\n }\r\n } catch (error) {\r\n this._secureLog('warn', 'DTLS fingerprint validation failed - continuing in fallback mode', { \r\n error: error.message,\r\n context: 'answer_validation'\r\n });\r\n\r\n }\r\n } else {\r\n this._secureLog('info', 'DTLS fingerprint validation disabled - proceeding without validation');\r\n }\r\n\r\n // Support both full and compact SDP field names\r\n const sdpData = answerData.sdp || answerData.s;\r\n \r\n this._secureLog('debug', 'Setting remote description from answer', {\r\n sdpLength: sdpData?.length || 0,\r\n usingCompactSDP: !answerData.sdp && !!answerData.s\r\n });\r\n \r\n await this.peerConnection.setRemoteDescription({\r\n type: 'answer',\r\n sdp: sdpData\r\n });\r\n \r\n this._secureLog('debug', 'Remote description set successfully from answer', {\r\n signalingState: this.peerConnection.signalingState\r\n });\r\n\r\n setTimeout(async () => {\r\n try {\r\n const securityData = await this.calculateAndReportSecurityLevel();\r\n if (securityData) {\r\n this.notifySecurityUpdate();\r\n }\r\n } catch (error) {\r\n this._secureLog('error', 'Error calculating security after connection:', { errorType: error?.constructor?.name || 'Unknown' });\r\n }\r\n }, 1000);\r\n setTimeout(async () => {\r\n if (!this.lastSecurityCalculation || this.lastSecurityCalculation.score < 50) {\r\n await this.calculateAndReportSecurityLevel();\r\n this.notifySecurityUpdate();\r\n }\r\n }, 3000);\r\n this.notifySecurityUpdate();\r\n } catch (error) {\r\n this._secureLog('error', 'Enhanced secure answer handling failed', {\r\n errorType: error.constructor.name\r\n });\r\n this.onStatusChange('failed');\r\n\r\n if (this.onAnswerError) {\r\n if (error.message.includes('too old') || error.message.includes('\u0441\u043B\u0438\u0448\u043A\u043E\u043C \u0441\u0442\u0430\u0440\u044B\u0435')) {\r\n this.onAnswerError('replay_attack', error.message);\r\n } else if (error.message.includes('MITM') || error.message.includes('signature') || error.message.includes('\u043F\u043E\u0434\u043F\u0438\u0441\u044C')) {\r\n this.onAnswerError('security_violation', error.message);\r\n } else {\r\n this.onAnswerError('general_error', error.message);\r\n }\r\n }\r\n \r\n throw error;\r\n }\r\n }\r\n\r\n\r\n initiateVerification() {\r\n \r\n if (this.isInitiator) {\r\n // Ensure verification initiation notice wasn't already sent\r\n if (!this.verificationInitiationSent) {\r\n this.verificationInitiationSent = true;\r\n this.deliverMessageToUI('CRITICAL: Compare verification code with peer out-of-band (voice/video/in-person) to prevent MITM attack!', 'system');\r\n this.deliverMessageToUI(`Your verification code: ${this.verificationCode}`, 'system');\r\n this.deliverMessageToUI('Ask peer to confirm this exact code before allowing traffic!', 'system');\r\n }\r\n } else {\r\n\r\n this.deliverMessageToUI('Waiting for verification code from peer...', 'system');\r\n }\r\n }\r\n\r\n confirmVerification() {\r\n \r\n try {\r\n \r\n // Mark local verification as confirmed\r\n this.localVerificationConfirmed = true;\r\n \r\n // Send confirmation to peer\r\n const confirmationPayload = {\r\n type: 'verification_confirmed',\r\n data: {\r\n timestamp: Date.now(),\r\n verificationMethod: 'SAS',\r\n securityLevel: 'MITM_PROTECTION_REQUIRED'\r\n }\r\n };\r\n\r\n this.dataChannel.send(JSON.stringify(confirmationPayload));\r\n \r\n // Notify UI about state change\r\n if (this.onVerificationStateChange) {\r\n this.onVerificationStateChange({\r\n localConfirmed: this.localVerificationConfirmed,\r\n remoteConfirmed: this.remoteVerificationConfirmed,\r\n bothConfirmed: this.bothVerificationsConfirmed\r\n });\r\n }\r\n \r\n // Check if both parties have confirmed\r\n this._checkBothVerificationsConfirmed();\r\n \r\n // Notify UI about local confirmation\r\n this.deliverMessageToUI('You confirmed the verification code. Waiting for peer confirmation...', 'system');\r\n \r\n this.processMessageQueue();\r\n } catch (error) {\r\n this._secureLog('error', 'SAS verification failed:', { errorType: error?.constructor?.name || 'Unknown' });\r\n this.deliverMessageToUI('SAS verification failed', 'system');\r\n }\r\n }\r\n\r\n _checkBothVerificationsConfirmed() {\r\n // Check if both parties have confirmed verification\r\n if (this.localVerificationConfirmed && this.remoteVerificationConfirmed && !this.bothVerificationsConfirmed) {\r\n this.bothVerificationsConfirmed = true;\r\n \r\n // Notify both parties that verification is complete\r\n const bothConfirmedPayload = {\r\n type: 'verification_both_confirmed',\r\n data: {\r\n timestamp: Date.now(),\r\n verificationMethod: 'SAS',\r\n securityLevel: 'MITM_PROTECTION_COMPLETE'\r\n }\r\n };\r\n\r\n this.dataChannel.send(JSON.stringify(bothConfirmedPayload));\r\n \r\n // Notify UI about state change\r\n if (this.onVerificationStateChange) {\r\n this.onVerificationStateChange({\r\n localConfirmed: this.localVerificationConfirmed,\r\n remoteConfirmed: this.remoteVerificationConfirmed,\r\n bothConfirmed: this.bothVerificationsConfirmed\r\n });\r\n }\r\n \r\n // Set verified status and open chat after 2 second delay\r\n this.deliverMessageToUI('Both parties confirmed! Opening secure chat in 2 seconds...', 'system');\r\n \r\n setTimeout(() => {\r\n this._setVerifiedStatus(true, 'MUTUAL_SAS_CONFIRMED', { \r\n code: this.verificationCode,\r\n timestamp: Date.now()\r\n });\r\n this._enforceVerificationGate('mutual_confirmed', false);\r\n this.onStatusChange?.('verified');\r\n }, 2000);\r\n }\r\n }\r\n\r\n handleVerificationConfirmed(data) {\r\n this.remoteVerificationConfirmed = true;\r\n \r\n // Notify UI about peer confirmation\r\n this.deliverMessageToUI('Peer confirmed the verification code. Waiting for your confirmation...', 'system');\r\n \r\n // Notify UI about state change\r\n if (this.onVerificationStateChange) {\r\n this.onVerificationStateChange({\r\n localConfirmed: this.localVerificationConfirmed,\r\n remoteConfirmed: this.remoteVerificationConfirmed,\r\n bothConfirmed: this.bothVerificationsConfirmed\r\n });\r\n }\r\n \r\n // Check if both parties have confirmed\r\n this._checkBothVerificationsConfirmed();\r\n }\r\n\r\n handleVerificationBothConfirmed(data) {\r\n // Handle notification that both parties have confirmed\r\n this.bothVerificationsConfirmed = true;\r\n \r\n // Notify UI about state change\r\n if (this.onVerificationStateChange) {\r\n this.onVerificationStateChange({\r\n localConfirmed: this.localVerificationConfirmed,\r\n remoteConfirmed: this.remoteVerificationConfirmed,\r\n bothConfirmed: this.bothVerificationsConfirmed\r\n });\r\n }\r\n \r\n // Set verified status and open chat after 2 second delay\r\n this.deliverMessageToUI('Both parties confirmed! Opening secure chat in 2 seconds...', 'system');\r\n \r\n setTimeout(() => {\r\n this._setVerifiedStatus(true, 'MUTUAL_SAS_CONFIRMED', { \r\n code: this.verificationCode,\r\n timestamp: Date.now()\r\n });\r\n this._enforceVerificationGate('mutual_confirmed', false);\r\n this.onStatusChange?.('verified');\r\n }, 2000);\r\n }\r\n\r\n handleVerificationRequest(data) {\r\n\r\n \r\n if (data.code === this.verificationCode) {\r\n const responsePayload = {\r\n type: 'verification_response',\r\n data: {\r\n ok: true,\r\n timestamp: Date.now(),\r\n verificationMethod: 'SAS', // Indicate SAS was used\r\n securityLevel: 'MITM_PROTECTED'\r\n }\r\n };\r\n this.dataChannel.send(JSON.stringify(responsePayload));\r\n \r\n // Ensure verification success notice wasn't already sent\r\n if (!this.verificationNotificationSent) {\r\n this.verificationNotificationSent = true;\r\n this.deliverMessageToUI('SAS verification successful! MITM protection confirmed. Channel is now secure!', 'system');\r\n }\r\n \r\n this.processMessageQueue();\r\n } else {\r\n // SAS verification failed - possible MITM attack\r\n const responsePayload = {\r\n type: 'verification_response',\r\n data: {\r\n ok: false,\r\n timestamp: Date.now(),\r\n reason: 'code_mismatch'\r\n }\r\n };\r\n this.dataChannel.send(JSON.stringify(responsePayload));\r\n \r\n this._secureLog('error', 'SAS verification failed - possible MITM attack', {\r\n receivedCode: data.code,\r\n expectedCode: this.verificationCode,\r\n timestamp: Date.now()\r\n });\r\n \r\n this.deliverMessageToUI('SAS verification failed! Possible MITM attack detected. Connection aborted for safety!', 'system');\r\n this.disconnect();\r\n }\r\n }\r\n\r\n handleSASCode(data) {\r\n\r\n \r\n this.verificationCode = data.code;\r\n this.onStatusChange?.('verifying'); \r\n this.onVerificationRequired(this.verificationCode);\r\n \r\n this._secureLog('info', 'SAS code received from Offer side', {\r\n sasCode: this.verificationCode,\r\n timestamp: Date.now()\r\n });\r\n }\r\n\r\n handleVerificationResponse(data) {\r\n \r\n if (data.ok === true) {\r\n \r\n // Log successful mutual SAS verification\r\n this._secureLog('info', 'Mutual SAS verification completed - MITM protection active', {\r\n verificationMethod: data.verificationMethod || 'SAS',\r\n securityLevel: data.securityLevel || 'MITM_PROTECTED',\r\n timestamp: Date.now()\r\n });\r\n \r\n // Ensure verification success notice wasn't already sent\r\n if (!this.verificationNotificationSent) {\r\n this.verificationNotificationSent = true;\r\n this.deliverMessageToUI(' Mutual SAS verification complete! MITM protection active. Channel is now secure!', 'system');\r\n }\r\n \r\n this.processMessageQueue();\r\n } else {\r\n // Peer verification failed - connection not secure\r\n this._secureLog('error', 'Peer SAS verification failed - connection not secure', {\r\n responseData: data,\r\n timestamp: Date.now()\r\n });\r\n \r\n this.deliverMessageToUI('Peer verification failed! Connection not secure!', 'system');\r\n this.disconnect();\r\n }\r\n }\r\n\r\n validateOfferData(offerData) {\r\n return offerData &&\r\n offerData.type === 'enhanced_secure_offer' &&\r\n offerData.sdp &&\r\n offerData.publicKey &&\r\n offerData.salt &&\r\n offerData.verificationCode &&\r\n Array.isArray(offerData.publicKey) &&\r\n Array.isArray(offerData.salt) &&\r\n offerData.salt.length === 32;\r\n }\r\n\r\n validateEnhancedOfferData(offerData) {\r\n try {\r\n // CRITICAL: Strict type checking to prevent syntax errors\r\n if (!offerData || typeof offerData !== 'object' || Array.isArray(offerData)) {\r\n this._secureLog('error', 'CRITICAL: Invalid offer data structure', { \r\n hasOfferData: !!offerData,\r\n offerDataType: typeof offerData,\r\n isArray: Array.isArray(offerData)\r\n });\r\n throw new Error('CRITICAL SECURITY FAILURE: Offer data must be a non-null object');\r\n }\r\n\r\n // Basic required fields will be validated after format detection\r\n\r\n // Check if this is v4.0 compact format or legacy format\r\n const isV4CompactFormat = offerData.v === '4.0' && offerData.e && offerData.d;\r\n const isV4Format = offerData.version === '4.0' && offerData.ecdhPublicKey && offerData.ecdsaPublicKey;\r\n \r\n // Validate offer type (support compact, legacy v3.0 and v4.0 formats)\r\n const isValidType = isV4CompactFormat ? \r\n ['offer'].includes(offerData.t) :\r\n ['enhanced_secure_offer', 'secure_offer'].includes(offerData.type);\r\n \r\n if (!isValidType) {\r\n throw new Error('Invalid offer type');\r\n }\r\n \r\n if (isV4CompactFormat) {\r\n // v4.0 compact format validation\r\n const compactRequiredFields = [\r\n 'e', 'd', 'sl', 'vc', 'si', 'ci', 'ac', 'slv'\r\n ];\r\n \r\n for (const field of compactRequiredFields) {\r\n if (!offerData[field]) {\r\n throw new Error(`Missing required v4.0 compact field: ${field}`);\r\n }\r\n }\r\n \r\n // Validate key structures\r\n if (!offerData.e || typeof offerData.e !== 'object' || Array.isArray(offerData.e)) {\r\n throw new Error('CRITICAL SECURITY FAILURE: Invalid ECDH public key structure');\r\n }\r\n \r\n if (!offerData.d || typeof offerData.d !== 'object' || Array.isArray(offerData.d)) {\r\n throw new Error('CRITICAL SECURITY FAILURE: Invalid ECDSA public key structure');\r\n }\r\n \r\n // Validate salt length\r\n if (!Array.isArray(offerData.sl) || offerData.sl.length !== 64) {\r\n throw new Error('Salt must be exactly 64 bytes for v4.0');\r\n }\r\n \r\n // Validate verification code format\r\n if (typeof offerData.vc !== 'string' || offerData.vc.length < 6) {\r\n throw new Error('Invalid verification code format');\r\n }\r\n \r\n // Validate security level\r\n if (!['MAX', 'HIGH', 'MED', 'LOW'].includes(offerData.slv)) {\r\n throw new Error('Invalid security level');\r\n }\r\n \r\n // Validate timestamp (not older than 1 hour)\r\n const offerAge = Date.now() - offerData.ts;\r\n if (offerAge > 3600000) {\r\n throw new Error('Offer is too old (older than 1 hour)');\r\n }\r\n \r\n this._secureLog('info', 'v4.0 compact offer validation passed', {\r\n version: offerData.v,\r\n hasECDH: !!offerData.e,\r\n hasECDSA: !!offerData.d,\r\n hasSalt: !!offerData.sl,\r\n hasVerificationCode: !!offerData.vc,\r\n securityLevel: offerData.slv,\r\n offerAge: Math.round(offerAge / 1000) + 's'\r\n });\r\n } else if (isV4Format) {\r\n // v4.0 enhanced validation\r\n const v4RequiredFields = [\r\n 'ecdhPublicKey', 'ecdsaPublicKey', 'salt', 'verificationCode',\r\n 'authChallenge', 'timestamp', 'version', 'securityLevel'\r\n ];\r\n\r\n for (const field of v4RequiredFields) {\r\n if (!offerData[field]) {\r\n throw new Error(`Missing v4.0 field: ${field}`);\r\n }\r\n }\r\n\r\n // Validate salt (must be 64 bytes for v4.0)\r\n if (!Array.isArray(offerData.salt) || offerData.salt.length !== 64) {\r\n throw new Error('Salt must be exactly 64 bytes for v4.0');\r\n }\r\n\r\n // Validate timestamp (not older than 1 hour)\r\n const offerAge = Date.now() - offerData.timestamp;\r\n if (offerAge > 3600000) {\r\n throw new Error('Offer is too old (older than 1 hour)');\r\n }\r\n\r\n // CRITICAL: Strict validation of key structures to prevent syntax errors\r\n if (!offerData.ecdhPublicKey || typeof offerData.ecdhPublicKey !== 'object' || Array.isArray(offerData.ecdhPublicKey)) {\r\n this._secureLog('error', 'CRITICAL: Invalid ECDH public key structure', { \r\n hasEcdhKey: !!offerData.ecdhPublicKey,\r\n ecdhKeyType: typeof offerData.ecdhPublicKey,\r\n isArray: Array.isArray(offerData.ecdhPublicKey)\r\n });\r\n throw new Error('CRITICAL SECURITY FAILURE: Invalid ECDH public key structure - hard abort required');\r\n }\r\n\r\n if (!offerData.ecdsaPublicKey || typeof offerData.ecdsaPublicKey !== 'object' || Array.isArray(offerData.ecdsaPublicKey)) {\r\n this._secureLog('error', 'CRITICAL: Invalid ECDSA public key structure', { \r\n hasEcdsaKey: !!offerData.ecdsaPublicKey,\r\n ecdsaKeyType: typeof offerData.ecdsaPublicKey,\r\n isArray: Array.isArray(offerData.ecdsaPublicKey)\r\n });\r\n throw new Error('CRITICAL SECURITY FAILURE: Invalid ECDSA public key structure - hard abort required');\r\n }\r\n\r\n // CRITICAL: Validate key internal structure to prevent syntax errors\r\n if (!offerData.ecdhPublicKey.keyData || !offerData.ecdhPublicKey.signature) {\r\n this._secureLog('error', 'CRITICAL: ECDH key missing keyData or signature', { \r\n hasKeyData: !!offerData.ecdhPublicKey.keyData,\r\n hasSignature: !!offerData.ecdhPublicKey.signature\r\n });\r\n throw new Error('CRITICAL SECURITY FAILURE: ECDH key missing keyData or signature');\r\n }\r\n\r\n if (!offerData.ecdsaPublicKey.keyData || !offerData.ecdsaPublicKey.signature) {\r\n this._secureLog('error', 'CRITICAL: ECDSA key missing keyData or signature', { \r\n hasKeyData: !!offerData.ecdsaPublicKey.keyData,\r\n hasSignature: !!offerData.ecdsaPublicKey.signature\r\n });\r\n throw new Error('CRITICAL SECURITY FAILURE: ECDSA key missing keyData or signature');\r\n }\r\n\r\n if (typeof offerData.verificationCode !== 'string' || offerData.verificationCode.length < 6) {\r\n throw new Error('Invalid SAS verification code format - MITM protection required');\r\n }\r\n\r\n this._secureLog('info', 'v4.0 offer validation passed', {\r\n version: offerData.version,\r\n hasSecurityLevel: !!offerData.securityLevel?.level,\r\n offerAge: Math.round(offerAge / 1000) + 's'\r\n });\r\n } else {\r\n // v3.0 backward compatibility validation\r\n // NOTE: v3.0 has limited security - SAS verification is still critical\r\n const v3RequiredFields = ['publicKey', 'salt', 'verificationCode'];\r\n for (const field of v3RequiredFields) {\r\n if (!offerData[field]) {\r\n throw new Error(`Missing v3.0 field: ${field}`);\r\n }\r\n }\r\n\r\n // Validate salt (32 bytes for v3.0)\r\n if (!Array.isArray(offerData.salt) || offerData.salt.length !== 32) {\r\n throw new Error('Salt must be exactly 32 bytes for v3.0');\r\n }\r\n\r\n // Validate public key\r\n if (!Array.isArray(offerData.publicKey)) {\r\n throw new Error('Invalid public key format for v3.0');\r\n }\r\n\r\n window.EnhancedSecureCryptoUtils.secureLog.log('info', 'v3.0 offer validation passed (backward compatibility)', {\r\n version: 'v3.0',\r\n legacy: true\r\n });\r\n }\r\n\r\n // Validate SDP structure (basic check for all versions)\r\n const sdp = isV4CompactFormat ? offerData.s : offerData.sdp;\r\n if (typeof sdp !== 'string' || !sdp.includes('v=0')) {\r\n throw new Error('Invalid SDP structure');\r\n }\r\n\r\n return true;\r\n } catch (error) {\r\n this._secureLog('error', 'CRITICAL: Security validation failed - hard abort required', {\r\n error: error.message,\r\n errorType: error.constructor.name,\r\n timestamp: Date.now()\r\n });\r\n\r\n throw new Error(`CRITICAL SECURITY VALIDATION FAILURE: ${error.message}`);\r\n }\r\n }\r\n\r\n async sendSecureMessage(message) {\r\n // Comprehensive input validation\r\n const validation = this._validateInputData(message, 'sendSecureMessage');\r\n if (!validation.isValid) {\r\n const errorMessage = `Input validation failed: ${validation.errors.join(', ')}`;\r\n this._secureLog('error', 'Input validation failed in sendSecureMessage', {\r\n errors: validation.errors,\r\n messageType: typeof message\r\n });\r\n throw new Error(errorMessage);\r\n }\r\n\r\n // Rate limiting check\r\n if (!this._checkRateLimit('sendSecureMessage')) {\r\n throw new Error('Rate limit exceeded for secure message sending');\r\n }\r\n\r\n // Enforce verification gate\r\n this._enforceVerificationGate('sendSecureMessage');\r\n\r\n // Quick readiness check WITHOUT mutex\r\n if (!this.isConnected()) {\r\n if (validation.sanitizedData && typeof validation.sanitizedData === 'object' && validation.sanitizedData.type && validation.sanitizedData.type.startsWith('file_')) {\r\n throw new Error('Connection not ready for file transfer. Please ensure the connection is established and verified.');\r\n }\r\n this.messageQueue.push(validation.sanitizedData);\r\n throw new Error('Connection not ready. Message queued for sending.');\r\n }\r\n \r\n // Use mutex ONLY for cryptographic operations\r\n return this._withMutex('cryptoOperation', async (operationId) => {\r\n // Re-check inside critical section\r\n if (!this.isConnected() || !this.isVerified) {\r\n throw new Error('Connection lost during message preparation');\r\n }\r\n \r\n // Note: master key session is managed by SecureMasterKeyManager\r\n // Do not gate here on _isUnlocked to avoid false blocking\r\n // Session timers are handled inside the master key manager on key access\r\n \r\n // Validate keys inside critical section\r\n if (!this.encryptionKey || !this.macKey || !this.metadataKey) {\r\n throw new Error('Encryption keys not initialized');\r\n }\r\n \r\n // Additional rate limiting check\r\n if (!window.EnhancedSecureCryptoUtils.rateLimiter.checkMessageRate(this.rateLimiterId)) {\r\n throw new Error('Message rate limit exceeded (60 messages per minute)');\r\n }\r\n \r\n try {\r\n // Accept strings and objects; stringify objects\r\n const textToSend = typeof validation.sanitizedData === 'string' ? validation.sanitizedData : JSON.stringify(validation.sanitizedData);\r\n const sanitizedMessage = window.EnhancedSecureCryptoUtils.sanitizeMessage(textToSend);\r\n const messageId = `msg_${Date.now()}_${this.messageCounter++}`;\r\n \r\n // Create AAD with sequence number for anti-replay protection\r\n if (typeof this._createMessageAAD !== 'function') {\r\n throw new Error('_createMessageAAD method is not available in sendSecureMessage. Manager may not be fully initialized.');\r\n }\r\n const aad = message.aad || this._createMessageAAD('enhanced_message', { content: sanitizedMessage });\r\n \r\n // Use enhanced encryption with AAD and sequence number\r\n const encryptedData = await window.EnhancedSecureCryptoUtils.encryptMessage(\r\n sanitizedMessage,\r\n this.encryptionKey,\r\n this.macKey,\r\n this.metadataKey,\r\n messageId,\r\n JSON.parse(aad).sequenceNumber // Use sequence number from AAD\r\n );\r\n \r\n const payload = {\r\n type: 'enhanced_message',\r\n data: encryptedData,\r\n keyVersion: this.currentKeyVersion,\r\n version: '4.0'\r\n };\r\n \r\n this.dataChannel.send(JSON.stringify(payload));\r\n // Locally display only plain strings to avoid UI duplication\r\n if (typeof validation.sanitizedData === 'string') {\r\n this.deliverMessageToUI(validation.sanitizedData, 'sent');\r\n }\r\n \r\n this._secureLog('debug', 'Secure message sent successfully', {\r\n operationId: operationId,\r\n messageLength: sanitizedMessage.length,\r\n keyVersion: this.currentKeyVersion\r\n });\r\n \r\n } catch (error) {\r\n this._secureLog('error', 'Secure message sending failed', {\r\n operationId: operationId,\r\n errorType: error.constructor.name\r\n });\r\n \r\n // Improved user-facing error messages (English)\r\n if (error.message.includes('Session expired')) {\r\n throw new Error('Session expired. Please enter your password to unlock.');\r\n } else if (error.message.includes('Encryption keys not initialized')) {\r\n throw new Error('Session expired due to inactivity. Please reconnect to the chat.');\r\n } else if (error.message.includes('Connection lost')) {\r\n throw new Error('Connection lost. Please check your Internet connection.');\r\n } else if (error.message.includes('Rate limit exceeded')) {\r\n throw new Error('Message rate limit exceeded. Please wait before sending another message.');\r\n } else {\r\n throw error;\r\n }\r\n }\r\n }, 2000); // Reduced timeout for crypto operations\r\n }\r\n\r\n processMessageQueue() {\r\n while (this.messageQueue.length > 0 && this.isConnected() && this.isVerified) {\r\n const message = this.messageQueue.shift();\r\n this.sendSecureMessage(message).catch(console.error);\r\n }\r\n }\r\n\r\n startHeartbeat() {\r\n // Heartbeat moved to unified scheduler with connection validation\r\n this._secureLog('info', 'Heartbeat moved to unified scheduler');\r\n \r\n // Store heartbeat configuration for scheduler\r\n this._heartbeatConfig = {\r\n enabled: true,\r\n interval: EnhancedSecureWebRTCManager.TIMEOUTS.HEARTBEAT_INTERVAL,\r\n lastHeartbeat: 0\r\n };\r\n }\r\n\r\n stopHeartbeat() {\r\n // Heartbeat stopped via unified scheduler\r\n if (this._heartbeatConfig) {\r\n this._heartbeatConfig.enabled = false;\r\n }\r\n }\r\n\r\n /**\r\n * Stop all active timers and cleanup scheduler\r\n */\r\n _stopAllTimers() {\r\n this._secureLog('info', 'Stopping all timers and cleanup scheduler');\r\n \r\n // Stop maintenance scheduler\r\n if (this._maintenanceScheduler) {\r\n clearInterval(this._maintenanceScheduler);\r\n this._maintenanceScheduler = null;\r\n }\r\n \r\n // Stop heartbeat\r\n if (this._heartbeatConfig) {\r\n this._heartbeatConfig.enabled = false;\r\n }\r\n \r\n // Clear all timer references\r\n if (this._activeTimers) {\r\n this._activeTimers.forEach(timer => {\r\n if (timer) clearInterval(timer);\r\n });\r\n this._activeTimers.clear();\r\n }\r\n \r\n this._secureLog('info', 'All timers stopped successfully');\r\n }\r\n\r\n\r\n waitForIceGathering() {\r\n return new Promise((resolve) => {\r\n if (this.peerConnection.iceGatheringState === 'complete') {\r\n resolve();\r\n return;\r\n }\r\n\r\n const checkState = () => {\r\n if (this.peerConnection && this.peerConnection.iceGatheringState === 'complete') {\r\n this.peerConnection.removeEventListener('icegatheringstatechange', checkState);\r\n resolve();\r\n }\r\n };\r\n \r\n this.peerConnection.addEventListener('icegatheringstatechange', checkState);\r\n \r\n setTimeout(() => {\r\n if (this.peerConnection) {\r\n this.peerConnection.removeEventListener('icegatheringstatechange', checkState);\r\n }\r\n resolve();\r\n }, EnhancedSecureWebRTCManager.TIMEOUTS.ICE_GATHERING_TIMEOUT);\r\n });\r\n }\r\n\r\n retryConnection() {\r\n this._secureLog('info', 'Retrying connection', {\r\n attempt: this.connectionAttempts,\r\n maxAttempts: this.maxConnectionAttempts\r\n });\r\n this.onStatusChange('retrying');\r\n }\r\n\r\n isConnected() {\r\n const hasDataChannel = !!this.dataChannel;\r\n const dataChannelState = this.dataChannel?.readyState;\r\n const isDataChannelOpen = dataChannelState === 'open';\r\n const isVerified = this.isVerified;\r\n const connectionState = this.peerConnection?.connectionState;\r\n \r\n return this.dataChannel && this.dataChannel.readyState === 'open' && this.isVerified;\r\n }\r\n\r\n getConnectionInfo() {\r\n return {\r\n fingerprint: this.keyFingerprint,\r\n isConnected: this.isConnected(),\r\n isVerified: this.isVerified,\r\n connectionState: this.peerConnection?.connectionState,\r\n iceConnectionState: this.peerConnection?.iceConnectionState,\r\n verificationCode: this.verificationCode\r\n };\r\n }\r\n\r\n disconnect() {\r\n // Stop all timers first\r\n this._stopAllTimers();\r\n \r\n if (this.fileTransferSystem) {\r\n this.fileTransferSystem.cleanup();\r\n }\r\n this.intentionalDisconnect = true;\r\n \r\n window.EnhancedSecureCryptoUtils.secureLog.log('info', 'Starting intentional disconnect');\r\n\r\n this.sendDisconnectNotification();\r\n\r\n setTimeout(() => {\r\n this.sendDisconnectNotification(); \r\n }, 100);\r\n\r\n document.dispatchEvent(new CustomEvent('peer-disconnect', {\r\n detail: { \r\n reason: 'user_disconnect',\r\n timestamp: Date.now()\r\n }\r\n }));\r\n }\r\n \r\n handleUnexpectedDisconnect() {\r\n this.sendDisconnectNotification();\r\n this.isVerified = false;\r\n \r\n // Ensure disconnect notification wasn't already sent\r\n if (!this.disconnectNotificationSent) {\r\n this.disconnectNotificationSent = true;\r\n this.deliverMessageToUI('\uD83D\uDD0C Connection lost. Attempting to reconnect...', 'system');\r\n }\r\n \r\n // Cleanup file transfer system on unexpected disconnect\r\n if (this.fileTransferSystem) {\r\n this.fileTransferSystem.cleanup();\r\n this.fileTransferSystem = null;\r\n }\r\n \r\n document.dispatchEvent(new CustomEvent('peer-disconnect', {\r\n detail: { \r\n reason: 'connection_lost',\r\n timestamp: Date.now()\r\n }\r\n }));\r\n\r\n }\r\n \r\n sendDisconnectNotification() {\r\n try {\r\n if (this.dataChannel && this.dataChannel.readyState === 'open') {\r\n const notification = {\r\n type: 'peer_disconnect',\r\n timestamp: Date.now(),\r\n reason: this.intentionalDisconnect ? 'user_disconnect' : 'connection_lost'\r\n };\r\n\r\n for (let i = 0; i < 3; i++) {\r\n try {\r\n this.dataChannel.send(JSON.stringify(notification));\r\n window.EnhancedSecureCryptoUtils.secureLog.log('info', 'Disconnect notification sent', {\r\n reason: notification.reason,\r\n attempt: i + 1\r\n });\r\n break;\r\n } catch (sendError) {\r\n if (i === 2) { \r\n window.EnhancedSecureCryptoUtils.secureLog.log('error', 'Failed to send disconnect notification', {\r\n error: sendError.message\r\n });\r\n }\r\n }\r\n }\r\n }\r\n } catch (error) {\r\n window.EnhancedSecureCryptoUtils.secureLog.log('error', 'Could not send disconnect notification', {\r\n error: error.message\r\n });\r\n }\r\n }\r\n \r\n attemptReconnection() {\r\n // Ensure reconnection-failed notification wasn't already sent\r\n if (!this.reconnectionFailedNotificationSent) {\r\n this.reconnectionFailedNotificationSent = true;\r\n this.deliverMessageToUI('Unable to reconnect. A new connection is required.', 'system');\r\n }\r\n\r\n }\r\n \r\n handlePeerDisconnectNotification(data) {\r\n const reason = data.reason || 'unknown';\r\n const reasonText = reason === 'user_disconnect' ? 'manually disconnected.' : 'connection lost.';\r\n \r\n // Ensure peer-disconnect notification wasn't already sent\r\n if (!this.peerDisconnectNotificationSent) {\r\n this.peerDisconnectNotificationSent = true;\r\n this.deliverMessageToUI(`Peer ${reasonText}`, 'system');\r\n }\r\n \r\n this.onStatusChange('peer_disconnected');\r\n \r\n this.intentionalDisconnect = false;\r\n this.isVerified = false;\r\n this.stopHeartbeat();\r\n \r\n this.onKeyExchange(''); \r\n this.onVerificationRequired(''); \r\n\r\n document.dispatchEvent(new CustomEvent('peer-disconnect', {\r\n detail: { \r\n reason: reason,\r\n timestamp: Date.now()\r\n }\r\n }));\r\n\r\n setTimeout(() => {\r\n this.disconnect();\r\n }, 2000);\r\n \r\n window.EnhancedSecureCryptoUtils.secureLog.log('info', 'Peer disconnect notification processed', {\r\n reason: reason\r\n });\r\n }\r\n \r\n /**\r\n * Secure disconnect with complete memory cleanup\r\n */\r\n disconnect() {\r\n this.stopHeartbeat();\r\n this.isVerified = false;\r\n this.processedMessageIds.clear();\r\n this.messageCounter = 0;\r\n \r\n // Secure cleanup of cryptographic materials\r\n this._secureCleanupCryptographicMaterials();\r\n \r\n // Secure wipe of PFS key versions\r\n this.keyVersions.clear();\r\n this.oldKeys.clear();\r\n this.currentKeyVersion = 0;\r\n this.lastKeyRotation = Date.now();\r\n \r\n // Reset message counters\r\n this.sequenceNumber = 0;\r\n this.expectedSequenceNumber = 0;\r\n this.replayWindow.clear(); // Clear replay window\r\n \r\n // Reset security features\r\n this.securityFeatures = {\r\n hasEncryption: true,\r\n hasECDH: true,\r\n hasECDSA: true, \r\n hasMutualAuth: true, \r\n hasMetadataProtection: true, \r\n hasEnhancedReplayProtection: true, \r\n hasNonExtractableKeys: true, \r\n hasRateLimiting: true, \r\n hasEnhancedValidation: true, \r\n hasPFS: true \r\n };\r\n \r\n // Close connections\r\n if (this.dataChannel) {\r\n this.dataChannel.close();\r\n this.dataChannel = null;\r\n }\r\n if (this.peerConnection) {\r\n this.peerConnection.close();\r\n this.peerConnection = null;\r\n }\r\n \r\n // Secure wipe of message queue\r\n if (this.messageQueue && this.messageQueue.length > 0) {\r\n this.messageQueue.forEach((message, index) => {\r\n this._secureWipeMemory(message, `messageQueue[${index}]`);\r\n });\r\n this.messageQueue = [];\r\n }\r\n \r\n // Schedule natural cleanup\r\n this._forceGarbageCollection().catch(error => {\r\n this._secureLog('error', 'Cleanup failed during disconnect', {\r\n errorType: error?.constructor?.name || 'Unknown'\r\n });\r\n });\r\n \r\n document.dispatchEvent(new CustomEvent('connection-cleaned', {\r\n detail: { \r\n timestamp: Date.now(),\r\n reason: this.intentionalDisconnect ? 'user_cleanup' : 'automatic_cleanup'\r\n }\r\n }));\r\n\r\n // Notify UI about complete cleanup\r\n this.onStatusChange('disconnected');\r\n this.onKeyExchange('');\r\n this.onVerificationRequired('');\r\n \r\n this._secureLog('info', 'Connection securely cleaned up with complete memory wipe');\r\n \r\n // Reset the intentional disconnect flag\r\n this.intentionalDisconnect = false;\r\n }\r\n // Public method to send files\r\n async sendFile(file) {\r\n // Enforce verification gate for file transfers\r\n this._enforceVerificationGate('sendFile');\r\n \r\n if (!this.isConnected()) {\r\n throw new Error('Connection not ready for file transfer. Please ensure the connection is established.');\r\n }\r\n\r\n if (!this.fileTransferSystem) {\r\n this.initializeFileTransfer();\r\n \r\n // Allow time for initialization\r\n await new Promise(resolve => setTimeout(resolve, 500));\r\n \r\n if (!this.fileTransferSystem) {\r\n throw new Error('File transfer system could not be initialized. Please try reconnecting.');\r\n }\r\n }\r\n\r\n // Verify key readiness\r\n if (!this.encryptionKey || !this.macKey) {\r\n throw new Error('Encryption keys not ready. Please wait for connection to be fully established.');\r\n }\r\n\r\n\r\n try {\r\n const fileId = await this.fileTransferSystem.sendFile(file);\r\n return fileId;\r\n } catch (error) {\r\n this._secureLog('error', 'File transfer error:', { errorType: error?.constructor?.name || 'Unknown' });\r\n \r\n // Re-throw with a clearer message\r\n if (error.message.includes('Connection not ready')) {\r\n throw new Error('Connection not ready for file transfer. Check connection status.');\r\n } else if (error.message.includes('Encryption keys not initialized')) {\r\n throw new Error('Session expired due to inactivity. Please reconnect to the chat.');\r\n } else if (error.message.includes('Transfer timeout')) {\r\n throw new Error('File transfer timeout. Check connection and try again.');\r\n } else {\r\n throw error;\r\n }\r\n }\r\n }\r\n\r\n // Get active file transfers\r\n getFileTransfers() {\r\n if (!this.fileTransferSystem) {\r\n return { sending: [], receiving: [] };\r\n }\r\n \r\n try {\r\n // Check available methods in file transfer system\r\n let sending = [];\r\n let receiving = [];\r\n \r\n if (typeof this.fileTransferSystem.getActiveTransfers === 'function') {\r\n sending = this.fileTransferSystem.getActiveTransfers();\r\n } else {\r\n this._secureLog('warn', 'getActiveTransfers method not available in file transfer system');\r\n }\r\n \r\n if (typeof this.fileTransferSystem.getReceivingTransfers === 'function') {\r\n receiving = this.fileTransferSystem.getReceivingTransfers();\r\n } else {\r\n this._secureLog('warn', 'getReceivingTransfers method not available in file transfer system');\r\n }\r\n \r\n return {\r\n sending: sending || [],\r\n receiving: receiving || []\r\n };\r\n } catch (error) {\r\n this._secureLog('error', 'Error getting file transfers:', { errorType: error?.constructor?.name || 'Unknown' });\r\n return { sending: [], receiving: [] };\r\n }\r\n }\r\n\r\n // Get file transfer system status\r\n getFileTransferStatus() {\r\n if (!this.fileTransferSystem) {\r\n return {\r\n initialized: false,\r\n status: 'not_initialized',\r\n message: 'File transfer system not initialized'\r\n };\r\n }\r\n \r\n const activeTransfers = this.fileTransferSystem.getActiveTransfers();\r\n const receivingTransfers = this.fileTransferSystem.getReceivingTransfers();\r\n \r\n return {\r\n initialized: true,\r\n status: 'ready',\r\n activeTransfers: activeTransfers.length,\r\n receivingTransfers: receivingTransfers.length,\r\n totalTransfers: activeTransfers.length + receivingTransfers.length\r\n };\r\n }\r\n\r\n // Cancel file transfer\r\n cancelFileTransfer(fileId) {\r\n if (!this.fileTransferSystem) return false;\r\n return this.fileTransferSystem.cancelTransfer(fileId);\r\n }\r\n\r\n // Force cleanup of file transfer system\r\n cleanupFileTransferSystem() {\r\n if (this.fileTransferSystem) {\r\n this._secureLog('info', '\uD83E\uDDF9 Force cleaning up file transfer system');\r\n this.fileTransferSystem.cleanup();\r\n this.fileTransferSystem = null;\r\n return true;\r\n }\r\n return false;\r\n }\r\n\r\n // Reinitialize file transfer system\r\n reinitializeFileTransfer() {\r\n try {\r\n if (this.fileTransferSystem) {\r\n this.fileTransferSystem.cleanup();\r\n }\r\n this.initializeFileTransfer();\r\n return true;\r\n } catch (error) {\r\n this._secureLog('error', 'Failed to reinitialize file transfer system:', { errorType: error?.constructor?.name || 'Unknown' });\r\n return false;\r\n }\r\n }\r\n\r\n // Set file transfer callbacks\r\n setFileTransferCallbacks(onProgress, onReceived, onError) {\r\n this.onFileProgress = onProgress;\r\n this.onFileReceived = onReceived;\r\n this.onFileError = onError;\r\n \r\n // Reinitialize file transfer system if it exists to update callbacks\r\n if (this.fileTransferSystem) {\r\n this.initializeFileTransfer();\r\n }\r\n }\r\n\r\n // ============================================\r\n // SESSION ACTIVATION HANDLING\r\n // ============================================\r\n\r\n async handleSessionActivation(sessionData) {\r\n try {\r\n \r\n // Update session state\r\n this.currentSession = sessionData;\r\n \r\n // FIX: More lenient checks for activation\r\n const hasKeys = !!(this.encryptionKey && this.macKey);\r\n const hasSession = !!(sessionData.sessionId);\r\n \r\n // Force connection status if there is an active session\r\n if (hasSession) {\r\n this.onStatusChange('connected');\r\n\r\n }\r\n\r\n setTimeout(() => {\r\n try {\r\n this.initializeFileTransfer();\r\n } catch (error) {\r\n this._secureLog('warn', 'File transfer initialization failed during session activation:', { details: error.message });\r\n }\r\n }, 1000);\r\n \r\n \r\n if (this.fileTransferSystem && this.isConnected()) {\r\n \r\n if (typeof this.fileTransferSystem.onSessionUpdate === 'function') {\r\n this.fileTransferSystem.onSessionUpdate({\r\n keyFingerprint: this.keyFingerprint,\r\n sessionSalt: this.sessionSalt,\r\n hasMacKey: !!this.macKey\r\n });\r\n }\r\n }\r\n \r\n } catch (error) {\r\n this._secureLog('error', 'Failed to handle session activation:', { errorType: error?.constructor?.name || 'Unknown' });\r\n }\r\n }\r\n // Method to check readiness of file transfers\r\ncheckFileTransferReadiness() {\r\n const status = {\r\n hasFileTransferSystem: !!this.fileTransferSystem,\r\n hasDataChannel: !!this.dataChannel,\r\n dataChannelState: this.dataChannel?.readyState,\r\n isConnected: this.isConnected(),\r\n isVerified: this.isVerified,\r\n hasEncryptionKey: !!this.encryptionKey,\r\n hasMacKey: !!this.macKey,\r\n ready: false\r\n };\r\n \r\n status.ready = status.hasFileTransferSystem && \r\n status.hasDataChannel && \r\n status.dataChannelState === 'open' && \r\n status.isConnected && \r\n status.isVerified;\r\n return status;\r\n }\r\n\r\n // Method to force re-initialize file transfer system\r\n forceReinitializeFileTransfer() {\r\n try {\r\n \r\n if (this.fileTransferSystem) {\r\n this.fileTransferSystem.cleanup();\r\n this.fileTransferSystem = null;\r\n }\r\n \r\n // Small delay before reinitialization\r\n setTimeout(() => {\r\n this.initializeFileTransfer();\r\n }, 500);\r\n \r\n return true;\r\n } catch (error) {\r\n this._secureLog('error', 'Failed to force reinitialize file transfer:', { errorType: error?.constructor?.name || 'Unknown' });\r\n return false;\r\n }\r\n }\r\n\r\n // Method to get diagnostic information\r\n getFileTransferDiagnostics() {\r\n const diagnostics = {\r\n timestamp: new Date().toISOString(),\r\n webrtcManager: {\r\n hasDataChannel: !!this.dataChannel,\r\n dataChannelState: this.dataChannel?.readyState,\r\n isConnected: this.isConnected(),\r\n isVerified: this.isVerified,\r\n isInitiator: this.isInitiator,\r\n hasEncryptionKey: !!this.encryptionKey,\r\n hasMacKey: !!this.macKey,\r\n hasMetadataKey: !!this.metadataKey,\r\n hasKeyFingerprint: !!this.keyFingerprint,\r\n hasSessionSalt: !!this.sessionSalt\r\n },\r\n fileTransferSystem: null,\r\n globalState: {\r\n fileTransferActive: this._fileTransferActive || false,\r\n hasFileTransferSystem: !!this.fileTransferSystem,\r\n fileTransferSystemType: this.fileTransferSystem ? 'EnhancedSecureFileTransfer' : 'none'\r\n }\r\n };\r\n \r\n if (this.fileTransferSystem) {\r\n try {\r\n diagnostics.fileTransferSystem = this.fileTransferSystem.getSystemStatus();\r\n } catch (error) {\r\n diagnostics.fileTransferSystem = { error: error.message };\r\n }\r\n }\r\n \r\n return diagnostics;\r\n }\r\n\r\n getSupportedFileTypes() {\r\n if (!this.fileTransferSystem) {\r\n return { error: 'File transfer system not initialized' };\r\n }\r\n \r\n try {\r\n return this.fileTransferSystem.getSupportedFileTypes();\r\n } catch (error) {\r\n return { error: error.message };\r\n }\r\n }\r\n\r\n validateFile(file) {\r\n if (!this.fileTransferSystem) {\r\n return { \r\n isValid: false, \r\n errors: ['File transfer system not initialized'],\r\n fileType: null,\r\n fileSize: file?.size || 0,\r\n formattedSize: '0 B'\r\n };\r\n }\r\n \r\n try {\r\n return this.fileTransferSystem.validateFile(file);\r\n } catch (error) {\r\n return { \r\n isValid: false, \r\n errors: [error.message],\r\n fileType: null,\r\n fileSize: file?.size || 0,\r\n formattedSize: '0 B'\r\n };\r\n }\r\n }\r\n\r\n getFileTypeInfo() {\r\n if (!this.fileTransferSystem) {\r\n return { error: 'File transfer system not initialized' };\r\n }\r\n \r\n try {\r\n return this.fileTransferSystem.getFileTypeInfo();\r\n } catch (error) {\r\n return { error: error.message };\r\n }\r\n }\r\n\r\n async forceInitializeFileTransfer(options = {}) {\r\n const abortController = new AbortController();\r\n const { signal = abortController.signal, timeout = 6000 } = options;\r\n\r\n if (signal && signal !== abortController.signal) {\r\n signal.addEventListener('abort', () => abortController.abort());\r\n }\r\n try {\r\n if (!this.isVerified) {\r\n throw new Error('Connection not verified');\r\n }\r\n \r\n if (!this.dataChannel || this.dataChannel.readyState !== 'open') {\r\n throw new Error('Data channel not open');\r\n }\r\n \r\n if (!this.encryptionKey || !this.macKey) {\r\n throw new Error('Encryption keys not ready');\r\n }\r\n\r\n if (this.fileTransferSystem) {\r\n this.fileTransferSystem.cleanup();\r\n this.fileTransferSystem = null;\r\n }\r\n\r\n this.initializeFileTransfer();\r\n\r\n let attempts = 0;\r\n const maxAttempts = 50;\r\n const checkInterval = 100; \r\n const maxWaitTime = maxAttempts * checkInterval; \r\n\r\n const initializationPromise = new Promise((resolve, reject) => {\r\n const checkInitialization = () => {\r\n if (abortController.signal.aborted) {\r\n reject(new Error('Operation cancelled'));\r\n return;\r\n }\r\n \r\n if (this.fileTransferSystem) {\r\n resolve(true);\r\n return;\r\n }\r\n \r\n if (attempts >= maxAttempts) {\r\n reject(new Error(`Initialization timeout after ${maxWaitTime}ms`));\r\n return;\r\n }\r\n \r\n attempts++;\r\n setTimeout(checkInitialization, checkInterval);\r\n };\r\n \r\n checkInitialization();\r\n });\r\n\r\n await Promise.race([\r\n initializationPromise,\r\n new Promise((_, reject) => \r\n setTimeout(() => reject(new Error(`Global timeout after ${timeout}ms`)), timeout)\r\n )\r\n ]);\r\n \r\n if (this.fileTransferSystem) {\r\n return true;\r\n } else {\r\n throw new Error('Force initialization timeout');\r\n }\r\n \r\n } catch (error) {\r\n if (error.name === 'AbortError' || error.message.includes('cancelled')) {\r\n this._secureLog('info', 'File transfer initialization cancelled by user');\r\n return { cancelled: true };\r\n }\r\n \r\n this._secureLog('error', 'Force file transfer initialization failed:', { \r\n errorType: error?.constructor?.name || 'Unknown',\r\n message: error.message,\r\n attempts: attempts\r\n });\r\n return { error: error.message, attempts: attempts };\r\n }\r\n }\r\n\r\n cancelFileTransferInitialization() {\r\n try {\r\n if (this.fileTransferSystem) {\r\n this.fileTransferSystem.cleanup();\r\n this.fileTransferSystem = null;\r\n this._fileTransferActive = false;\r\n this._secureLog('info', 'File transfer initialization cancelled');\r\n return true;\r\n }\r\n return false;\r\n } catch (error) {\r\n this._secureLog('error', 'Failed to cancel file transfer initialization:', { \r\n errorType: error?.constructor?.name || 'Unknown' \r\n });\r\n return false;\r\n }\r\n }\r\n \r\n getFileTransferSystemStatus() {\r\n if (!this.fileTransferSystem) {\r\n return { available: false, status: 'not_initialized' };\r\n }\r\n \r\n try {\r\n const status = this.fileTransferSystem.getSystemStatus();\r\n return {\r\n available: true,\r\n status: status.status || 'unknown',\r\n activeTransfers: status.activeTransfers || 0,\r\n receivingTransfers: status.receivingTransfers || 0,\r\n systemType: 'EnhancedSecureFileTransfer'\r\n };\r\n } catch (error) {\r\n this._secureLog('error', 'Failed to get file transfer system status:', { \r\n errorType: error?.constructor?.name || 'Unknown' \r\n });\r\n return { available: false, status: 'error', error: error.message };\r\n }\r\n }\r\n\r\n _validateNestedEncryptionSecurity() {\r\n if (this.securityFeatures.hasNestedEncryption && this.nestedEncryptionKey) {\r\n // Test secure IV generation with reuse prevention\r\n try {\r\n const testIV1 = this._generateSecureIV(EnhancedSecureWebRTCManager.SIZES.NESTED_ENCRYPTION_IV_SIZE, 'securityTest1');\r\n const testIV2 = this._generateSecureIV(EnhancedSecureWebRTCManager.SIZES.NESTED_ENCRYPTION_IV_SIZE, 'securityTest2');\r\n \r\n // Verify IVs are different and properly tracked\r\n if (testIV1.every((byte, index) => byte === testIV2[index])) {\r\n this._secureLog('error', 'CRITICAL: Nested encryption security validation failed - IVs are identical!');\r\n return false;\r\n }\r\n \r\n // Verify IV tracking system is working\r\n const stats = this._getIVTrackingStats();\r\n if (stats.totalIVs < 2) {\r\n this._secureLog('error', 'CRITICAL: IV tracking system not working properly');\r\n return false;\r\n }\r\n \r\n this._secureLog('info', 'Nested encryption security validation passed - secure IV generation working');\r\n return true;\r\n } catch (error) {\r\n this._secureLog('error', 'CRITICAL: Nested encryption security validation failed:', {\r\n errorType: error.constructor.name,\r\n errorMessage: error.message\r\n });\r\n return false;\r\n }\r\n }\r\n return true;\r\n }\r\n}\r\n\r\nclass SecureKeyStorage {\r\n constructor(masterKeyManager = null) {\r\n // Use WeakMap for automatic garbage collection of unused keys\r\n this._keyStore = new WeakMap();\r\n this._keyMetadata = new Map(); // Metadata doesn't need WeakMap\r\n this._keyReferences = new Map(); // Strong references for active keys\r\n \r\n // Use secure master key manager instead of global key\r\n this._masterKeyManager = masterKeyManager || new SecureMasterKeyManager();\r\n \r\n // Initialize persistent storage for extractable keys\r\n this._persistentStorage = new SecurePersistentKeyStorage(this._masterKeyManager);\r\n \r\n // Setup master key manager callbacks\r\n this._setupMasterKeyCallbacks();\r\n\r\n setTimeout(() => {\r\n if (!this.validateStorageIntegrity()) {\r\n this._secureLog('error', 'CRITICAL: Key storage integrity check failed');\r\n }\r\n }, 100);\r\n \r\n }\r\n\r\n /**\r\n * Setup callbacks for master key manager\r\n */\r\n _setupMasterKeyCallbacks() {\r\n // Set default password callback (can be overridden)\r\n this._masterKeyManager.setPasswordRequiredCallback((isRetry, callback) => {\r\n // Default implementation - should be overridden by application\r\n const password = prompt(isRetry ? \r\n 'Incorrect password. Please enter your master password:' : \r\n 'Please enter your master password to unlock secure storage:'\r\n );\r\n callback(password);\r\n });\r\n \r\n this._masterKeyManager.setSessionExpiredCallback((reason) => {\r\n console.warn(`Master key session expired: ${reason}`);\r\n // Application should handle this event\r\n });\r\n \r\n this._masterKeyManager.setUnlockedCallback(() => {\r\n console.log('Master key unlocked successfully');\r\n });\r\n }\r\n \r\n /**\r\n * Set custom password callback\r\n */\r\n setPasswordCallback(callback) {\r\n this._masterKeyManager.setPasswordRequiredCallback(callback);\r\n }\r\n \r\n /**\r\n * Set custom session expired callback\r\n */\r\n setSessionExpiredCallback(callback) {\r\n this._masterKeyManager.setSessionExpiredCallback(callback);\r\n }\r\n \r\n /**\r\n * Get master key (with automatic unlock if needed)\r\n */\r\n async _ensureMasterKeyUnlocked() {\r\n if (!this._masterKeyManager.isUnlocked()) {\r\n await this._masterKeyManager.unlock();\r\n }\r\n }\r\n\r\n async storeKey(keyId, cryptoKey, metadata = {}) {\r\n if (!(cryptoKey instanceof CryptoKey)) {\r\n throw new Error('Only CryptoKey objects can be stored');\r\n }\r\n\r\n try {\r\n // For non-extractable keys, store only in-memory reference\r\n if (!cryptoKey.extractable) {\r\n this._keyReferences.set(keyId, cryptoKey);\r\n this._keyMetadata.set(keyId, {\r\n ...metadata,\r\n created: Date.now(),\r\n lastAccessed: Date.now(),\r\n extractable: false,\r\n persistent: false,\r\n encrypted: false\r\n });\r\n return true;\r\n }\r\n\r\n // For extractable keys, use persistent storage with encryption\r\n await this._persistentStorage.storeExtractableKey(keyId, cryptoKey, metadata);\r\n \r\n // Also store in memory for immediate access\r\n this._keyReferences.set(keyId, cryptoKey);\r\n this._keyMetadata.set(keyId, {\r\n ...metadata,\r\n created: Date.now(),\r\n lastAccessed: Date.now(),\r\n extractable: true,\r\n persistent: true,\r\n encrypted: true\r\n });\r\n\r\n return true;\r\n \r\n } catch (error) {\r\n this._secureLog('error', 'Failed to store key securely', {\r\n errorType: error?.constructor?.name || 'Unknown'\r\n });\r\n return false;\r\n }\r\n }\r\n\r\n async retrieveKey(keyId) {\r\n try {\r\n // Check if key is in memory first\r\n if (this._keyReferences.has(keyId)) {\r\n const metadata = this._keyMetadata.get(keyId);\r\n if (metadata) {\r\n metadata.lastAccessed = Date.now();\r\n }\r\n return this._keyReferences.get(keyId);\r\n }\r\n \r\n // Try to restore from persistent storage\r\n const restoredKey = await this._persistentStorage.retrieveKey(keyId);\r\n if (restoredKey) {\r\n // Update memory cache\r\n this._keyReferences.set(keyId, restoredKey);\r\n \r\n // Update or create metadata\r\n const existingMetadata = this._keyMetadata.get(keyId);\r\n this._keyMetadata.set(keyId, {\r\n ...existingMetadata,\r\n lastAccessed: Date.now(),\r\n restoredFromPersistent: true\r\n });\r\n \r\n return restoredKey;\r\n }\r\n \r\n return null;\r\n \r\n } catch (error) {\r\n this._secureLog('error', 'Failed to retrieve key', {\r\n errorType: error?.constructor?.name || 'Unknown'\r\n });\r\n return null;\r\n }\r\n }\r\n\r\n async _encryptKeyData(keyData) {\r\n const dataToEncrypt = typeof keyData === 'object' \r\n ? JSON.stringify(keyData) \r\n : keyData;\r\n \r\n const encoder = new TextEncoder();\r\n const data = encoder.encode(dataToEncrypt);\r\n \r\n await this._ensureMasterKeyUnlocked();\r\n const { encryptedData, iv } = await this._masterKeyManager.encryptBytes(data);\r\n // Return IV + encrypted data\r\n const result = new Uint8Array(iv.length + encryptedData.byteLength);\r\n result.set(iv, 0);\r\n result.set(encryptedData, iv.length);\r\n return result;\r\n }\r\n\r\n async _decryptKeyData(encryptedData) {\r\n const iv = encryptedData.slice(0, 12);\r\n const data = encryptedData.slice(12);\r\n \r\n await this._ensureMasterKeyUnlocked();\r\n const decryptedData = await this._masterKeyManager.decryptBytes(data, iv);\r\n\r\n const decoder = new TextDecoder();\r\n const jsonString = decoder.decode(decryptedData);\r\n \r\n try {\r\n return JSON.parse(jsonString);\r\n } catch {\r\n return decryptedData;\r\n }\r\n }\r\n\r\n async secureWipe(keyId) {\r\n const cryptoKey = this._keyReferences.get(keyId);\r\n \r\n if (cryptoKey) {\r\n // Remove from WeakMap (will be GC'd)\r\n this._keyStore.delete(cryptoKey);\r\n // Remove strong reference\r\n this._keyReferences.delete(keyId);\r\n // Remove metadata\r\n this._keyMetadata.delete(keyId);\r\n }\r\n\r\n // Schedule natural cleanup\r\n await this._performNaturalCleanup();\r\n }\r\n\r\n async secureWipeAll() {\r\n // Clear persistent storage\r\n try {\r\n await this._persistentStorage.clearAll();\r\n } catch (error) {\r\n this._secureLog('error', 'Failed to clear persistent storage', {\r\n errorType: error?.constructor?.name || 'Unknown'\r\n });\r\n }\r\n \r\n // Clear all references\r\n this._keyReferences.clear();\r\n this._keyMetadata.clear();\r\n \r\n // WeakMap entries will be garbage collected\r\n this._keyStore = new WeakMap();\r\n \r\n // Schedule natural cleanup\r\n await this._performNaturalCleanup();\r\n }\r\n\r\n // Validate storage integrity\r\n validateStorageIntegrity() {\r\n const violations = [];\r\n \r\n for (const [keyId, metadata] of this._keyMetadata.entries()) {\r\n // Check: extractable keys must be encrypted\r\n if (metadata.extractable === true && metadata.encrypted !== true) {\r\n violations.push({\r\n keyId,\r\n type: 'EXTRACTABLE_KEY_NOT_ENCRYPTED',\r\n metadata\r\n });\r\n }\r\n \r\n // Check: non-extractable keys should not be encrypted\r\n if (metadata.extractable === false && metadata.encrypted === true) {\r\n violations.push({\r\n keyId,\r\n type: 'NON_EXTRACTABLE_KEY_ENCRYPTED',\r\n metadata\r\n });\r\n }\r\n }\r\n \r\n if (violations.length > 0) {\r\n this._secureLog('error', 'Storage integrity violations detected', {\r\n violationCount: violations.length\r\n });\r\n return false;\r\n }\r\n \r\n return true;\r\n }\r\n\r\n async getStorageStats() {\r\n const persistentStats = await this._persistentStorage.getStorageStats();\r\n \r\n return {\r\n totalKeys: this._keyReferences.size,\r\n memoryKeys: this._keyReferences.size,\r\n persistentKeys: persistentStats.persistentKeys,\r\n metadata: Array.from(this._keyMetadata.entries()).map(([id, meta]) => ({\r\n id,\r\n created: meta.created,\r\n lastAccessed: meta.lastAccessed,\r\n age: Date.now() - meta.created,\r\n persistent: meta.persistent || false\r\n })),\r\n persistent: persistentStats\r\n };\r\n }\r\n \r\n /**\r\n * List all stored keys (memory + persistent)\r\n */\r\n async listAllKeys() {\r\n try {\r\n const memoryKeys = Array.from(this._keyMetadata.entries()).map(([keyId, metadata]) => ({\r\n keyId,\r\n ...metadata,\r\n location: 'memory'\r\n }));\r\n \r\n const persistentKeys = await this._persistentStorage.listStoredKeys();\r\n const persistentKeysFormatted = persistentKeys.map(key => ({\r\n ...key,\r\n location: 'persistent'\r\n }));\r\n \r\n return {\r\n memoryKeys,\r\n persistentKeys: persistentKeysFormatted,\r\n totalCount: memoryKeys.length + persistentKeysFormatted.length\r\n };\r\n \r\n } catch (error) {\r\n this._secureLog('error', 'Failed to list keys', {\r\n errorType: error?.constructor?.name || 'Unknown'\r\n });\r\n return {\r\n memoryKeys: [],\r\n persistentKeys: [],\r\n totalCount: 0,\r\n error: error.message\r\n };\r\n }\r\n }\r\n \r\n /**\r\n * Delete key from both memory and persistent storage\r\n */\r\n async deleteKey(keyId) {\r\n try {\r\n // Remove from memory\r\n this._keyReferences.delete(keyId);\r\n this._keyMetadata.delete(keyId);\r\n \r\n // Remove from persistent storage\r\n await this._persistentStorage.deleteKey(keyId);\r\n \r\n return true;\r\n \r\n } catch (error) {\r\n this._secureLog('error', 'Failed to delete key', {\r\n errorType: error?.constructor?.name || 'Unknown'\r\n });\r\n return false;\r\n }\r\n }\r\n\r\n // Method _generateNextSequenceNumber moved to constructor area for early availability\r\n\r\n /**\r\n * Validate incoming message sequence number\r\n * This prevents replay attacks and ensures message ordering\r\n */\r\n _validateIncomingSequenceNumber(receivedSeq, context = 'unknown') {\r\n try {\r\n if (!this.replayProtectionEnabled) {\r\n return true; // Skip validation if disabled\r\n }\r\n\r\n // Check if sequence number is within acceptable range\r\n if (receivedSeq < this.expectedSequenceNumber - this.replayWindowSize) {\r\n this._secureLog('warn', 'Sequence number too old - possible replay attack', {\r\n received: receivedSeq,\r\n expected: this.expectedSequenceNumber,\r\n context: context,\r\n timestamp: Date.now()\r\n });\r\n return false;\r\n }\r\n\r\n // Check if sequence number is too far ahead (DoS protection)\r\n if (receivedSeq > this.expectedSequenceNumber + this.maxSequenceGap) {\r\n this._secureLog('warn', 'Sequence number gap too large - possible DoS attack', {\r\n received: receivedSeq,\r\n expected: this.expectedSequenceNumber,\r\n gap: receivedSeq - this.expectedSequenceNumber,\r\n context: context,\r\n timestamp: Date.now()\r\n });\r\n return false;\r\n }\r\n\r\n // Check if sequence number is already in replay window\r\n if (this.replayWindow.has(receivedSeq)) {\r\n this._secureLog('warn', 'Duplicate sequence number detected - replay attack', {\r\n received: receivedSeq,\r\n context: context,\r\n timestamp: Date.now()\r\n });\r\n return false;\r\n }\r\n\r\n // Add to replay window\r\n this.replayWindow.add(receivedSeq);\r\n \r\n // Maintain sliding window size\r\n if (this.replayWindow.size > this.replayWindowSize) {\r\n const oldestSeq = Math.min(...this.replayWindow);\r\n this.replayWindow.delete(oldestSeq);\r\n }\r\n\r\n // Update expected sequence number if this is the next expected\r\n if (receivedSeq === this.expectedSequenceNumber) {\r\n this.expectedSequenceNumber++;\r\n \r\n // Clean up replay window entries that are no longer needed\r\n while (this.replayWindow.has(this.expectedSequenceNumber - this.replayWindowSize - 1)) {\r\n this.replayWindow.delete(this.expectedSequenceNumber - this.replayWindowSize - 1);\r\n }\r\n }\r\n\r\n this._secureLog('debug', 'Sequence number validation successful', {\r\n received: receivedSeq,\r\n expected: this.expectedSequenceNumber,\r\n context: context,\r\n timestamp: Date.now()\r\n });\r\n\r\n return true;\r\n } catch (error) {\r\n this._secureLog('error', 'Sequence number validation failed', {\r\n error: error.message,\r\n context: context,\r\n timestamp: Date.now()\r\n });\r\n return false;\r\n }\r\n }\r\n\r\n // Method _createMessageAAD moved to constructor area for early availability\r\n\r\n /**\r\n * Validate message AAD with sequence number\r\n * This ensures message integrity and prevents replay attacks\r\n */\r\n _validateMessageAAD(aadString, expectedMessageType = null) {\r\n try {\r\n const aad = JSON.parse(aadString);\r\n \r\n // Validate session binding\r\n if (aad.sessionId !== (this.currentSession?.sessionId || 'unknown')) {\r\n throw new Error('AAD sessionId mismatch - possible replay attack');\r\n }\r\n \r\n if (aad.keyFingerprint !== (this.keyFingerprint || 'unknown')) {\r\n throw new Error('AAD keyFingerprint mismatch - possible key substitution attack');\r\n }\r\n \r\n // Validate sequence number\r\n if (!this._validateIncomingSequenceNumber(aad.sequenceNumber, aad.messageType)) {\r\n throw new Error('Sequence number validation failed - possible replay or DoS attack');\r\n }\r\n \r\n // Validate message type if specified\r\n if (expectedMessageType && aad.messageType !== expectedMessageType) {\r\n throw new Error(`AAD messageType mismatch - expected ${expectedMessageType}, got ${aad.messageType}`);\r\n }\r\n \r\n return aad;\r\n } catch (error) {\r\n this._secureLog('error', 'AAD validation failed', { error: error.message, aadString });\r\n throw new Error(`AAD validation failed: ${error.message}`);\r\n }\r\n }\r\n\r\n /**\r\n * Get anti-replay protection status\r\n * This shows the current state of replay protection\r\n */\r\n getAntiReplayStatus() {\r\n const status = {\r\n replayProtectionEnabled: this.replayProtectionEnabled,\r\n replayWindowSize: this.replayWindowSize,\r\n currentReplayWindowSize: this.replayWindow.size,\r\n sequenceNumber: this.sequenceNumber,\r\n expectedSequenceNumber: this.expectedSequenceNumber,\r\n maxSequenceGap: this.maxSequenceGap,\r\n replayWindowEntries: Array.from(this.replayWindow).sort((a, b) => a - b)\r\n };\r\n\r\n this._secureLog('info', 'Anti-replay status retrieved', status);\r\n return status;\r\n }\r\n\r\n /**\r\n * Configure anti-replay protection\r\n * This allows fine-tuning of replay protection parameters\r\n */\r\n configureAntiReplayProtection(config) {\r\n try {\r\n if (config.windowSize !== undefined) {\r\n if (config.windowSize < 16 || config.windowSize > 1024) {\r\n throw new Error('Replay window size must be between 16 and 1024');\r\n }\r\n this.replayWindowSize = config.windowSize;\r\n }\r\n\r\n if (config.maxGap !== undefined) {\r\n if (config.maxGap < 10 || config.maxGap > 1000) {\r\n throw new Error('Max sequence gap must be between 10 and 1000');\r\n }\r\n this.maxSequenceGap = config.maxGap;\r\n }\r\n\r\n if (config.enabled !== undefined) {\r\n this.replayProtectionEnabled = config.enabled;\r\n }\r\n\r\n this._secureLog('info', 'Anti-replay protection configured', config);\r\n return true;\r\n } catch (error) {\r\n this._secureLog('error', 'Failed to configure anti-replay protection', { error: error.message });\r\n return false;\r\n }\r\n }\r\n\r\n /**\r\n * Get real security level with actual cryptographic tests\r\n * This provides real-time verification of security features\r\n */\r\n async getRealSecurityLevel() {\r\n try {\r\n const securityData = {\r\n // Basic security features\r\n ecdhKeyExchange: !!this.ecdhKeyPair,\r\n ecdsaSignatures: !!this.ecdsaKeyPair,\r\n aesEncryption: !!this.encryptionKey,\r\n messageIntegrity: !!this.hmacKey,\r\n \r\n // Advanced security features - using the exact property names expected by EnhancedSecureCryptoUtils\r\n replayProtection: this.replayProtectionEnabled,\r\n dtlsFingerprint: !!this.expectedDTLSFingerprint,\r\n sasCode: !!this.verificationCode,\r\n metadataProtection: true, // Always enabled\r\n trafficObfuscation: true, // Always enabled\r\n perfectForwardSecrecy: true, // Always enabled\r\n \r\n // Rate limiting\r\n rateLimiter: true, // Always enabled\r\n \r\n // Additional info\r\n connectionId: this.connectionId,\r\n keyFingerprint: this.keyFingerprint,\r\n currentSecurityLevel: 'maximum',\r\n timestamp: Date.now()\r\n };\r\n\r\n \r\n this._secureLog('info', 'Real security level calculated', securityData);\r\n return securityData;\r\n } catch (error) {\r\n this._secureLog('error', 'Failed to calculate real security level', { error: error.message });\r\n throw error;\r\n }\r\n }\r\n\r\n\r\n}\r\n\r\n/**\r\n * Secure IndexedDB Wrapper for Encrypted Key Storage\r\n * Provides secure persistent storage with encryption\r\n */\r\nclass SecureIndexedDBWrapper {\r\n constructor(dbName = 'SecureKeyStorage', version = 1) {\r\n this.dbName = dbName;\r\n this.version = version;\r\n this.db = null;\r\n \r\n // Store names\r\n this.KEYS_STORE = 'encrypted_keys';\r\n this.METADATA_STORE = 'key_metadata';\r\n this.SALT_STORE = 'master_salt';\r\n }\r\n \r\n /**\r\n * Initialize IndexedDB connection\r\n */\r\n async initialize() {\r\n return new Promise((resolve, reject) => {\r\n const request = indexedDB.open(this.dbName, this.version);\r\n \r\n request.onerror = () => {\r\n reject(new Error(`Failed to open IndexedDB: ${request.error}`));\r\n };\r\n \r\n request.onsuccess = () => {\r\n this.db = request.result;\r\n resolve();\r\n };\r\n \r\n request.onupgradeneeded = (event) => {\r\n const db = event.target.result;\r\n \r\n // Create encrypted keys store\r\n if (!db.objectStoreNames.contains(this.KEYS_STORE)) {\r\n const keysStore = db.createObjectStore(this.KEYS_STORE, { keyPath: 'keyId' });\r\n keysStore.createIndex('timestamp', 'timestamp', { unique: false });\r\n keysStore.createIndex('algorithm', 'algorithm', { unique: false });\r\n }\r\n \r\n // Create metadata store\r\n if (!db.objectStoreNames.contains(this.METADATA_STORE)) {\r\n const metadataStore = db.createObjectStore(this.METADATA_STORE, { keyPath: 'keyId' });\r\n metadataStore.createIndex('created', 'created', { unique: false });\r\n metadataStore.createIndex('lastAccessed', 'lastAccessed', { unique: false });\r\n }\r\n \r\n // Create salt store\r\n if (!db.objectStoreNames.contains(this.SALT_STORE)) {\r\n db.createObjectStore(this.SALT_STORE, { keyPath: 'id' });\r\n }\r\n };\r\n });\r\n }\r\n \r\n /**\r\n * Store encrypted key data\r\n */\r\n async storeEncryptedKey(keyId, encryptedData, iv, algorithm, usages, type, metadata = {}) {\r\n if (!this.db) {\r\n throw new Error('Database not initialized');\r\n }\r\n \r\n const transaction = this.db.transaction([this.KEYS_STORE, this.METADATA_STORE], 'readwrite');\r\n \r\n const keyRecord = {\r\n keyId: keyId,\r\n encryptedData: Array.from(new Uint8Array(encryptedData)), // Convert to array for storage\r\n iv: Array.from(new Uint8Array(iv)),\r\n algorithm: algorithm,\r\n usages: usages,\r\n type: type,\r\n timestamp: Date.now()\r\n };\r\n \r\n const metadataRecord = {\r\n keyId: keyId,\r\n ...metadata,\r\n created: Date.now(),\r\n lastAccessed: Date.now(),\r\n extractable: true,\r\n persistent: true\r\n };\r\n \r\n return new Promise((resolve, reject) => {\r\n const keysRequest = transaction.objectStore(this.KEYS_STORE).put(keyRecord);\r\n const metadataRequest = transaction.objectStore(this.METADATA_STORE).put(metadataRecord);\r\n \r\n transaction.oncomplete = () => resolve();\r\n transaction.onerror = () => reject(new Error(`Failed to store key: ${transaction.error}`));\r\n });\r\n }\r\n \r\n /**\r\n * Retrieve encrypted key data\r\n */\r\n async getEncryptedKey(keyId) {\r\n if (!this.db) {\r\n throw new Error('Database not initialized');\r\n }\r\n \r\n const transaction = this.db.transaction([this.KEYS_STORE], 'readonly');\r\n const store = transaction.objectStore(this.KEYS_STORE);\r\n \r\n return new Promise((resolve, reject) => {\r\n const request = store.get(keyId);\r\n \r\n request.onsuccess = () => {\r\n const result = request.result;\r\n if (result) {\r\n // Convert arrays back to Uint8Array\r\n result.encryptedData = new Uint8Array(result.encryptedData);\r\n result.iv = new Uint8Array(result.iv);\r\n }\r\n resolve(result);\r\n };\r\n \r\n request.onerror = () => reject(new Error(`Failed to retrieve key: ${request.error}`));\r\n });\r\n }\r\n \r\n /**\r\n * Update key metadata (e.g., last accessed time)\r\n */\r\n async updateKeyMetadata(keyId, updates) {\r\n if (!this.db) {\r\n throw new Error('Database not initialized');\r\n }\r\n \r\n const transaction = this.db.transaction([this.METADATA_STORE], 'readwrite');\r\n const store = transaction.objectStore(this.METADATA_STORE);\r\n \r\n return new Promise((resolve, reject) => {\r\n const getRequest = store.get(keyId);\r\n \r\n getRequest.onsuccess = () => {\r\n const metadata = getRequest.result;\r\n if (metadata) {\r\n Object.assign(metadata, updates);\r\n const putRequest = store.put(metadata);\r\n \r\n putRequest.onsuccess = () => resolve();\r\n putRequest.onerror = () => reject(new Error(`Failed to update metadata: ${putRequest.error}`));\r\n } else {\r\n reject(new Error(`Key metadata not found: ${keyId}`));\r\n }\r\n };\r\n \r\n getRequest.onerror = () => reject(new Error(`Failed to get metadata: ${getRequest.error}`));\r\n });\r\n }\r\n \r\n /**\r\n * Delete key and its metadata\r\n */\r\n async deleteKey(keyId) {\r\n if (!this.db) {\r\n throw new Error('Database not initialized');\r\n }\r\n \r\n const transaction = this.db.transaction([this.KEYS_STORE, this.METADATA_STORE], 'readwrite');\r\n \r\n return new Promise((resolve, reject) => {\r\n const keysRequest = transaction.objectStore(this.KEYS_STORE).delete(keyId);\r\n const metadataRequest = transaction.objectStore(this.METADATA_STORE).delete(keyId);\r\n \r\n transaction.oncomplete = () => resolve();\r\n transaction.onerror = () => reject(new Error(`Failed to delete key: ${transaction.error}`));\r\n });\r\n }\r\n \r\n /**\r\n * List all stored keys\r\n */\r\n async listKeys() {\r\n if (!this.db) {\r\n throw new Error('Database not initialized');\r\n }\r\n \r\n const transaction = this.db.transaction([this.METADATA_STORE], 'readonly');\r\n const store = transaction.objectStore(this.METADATA_STORE);\r\n \r\n return new Promise((resolve, reject) => {\r\n const request = store.getAll();\r\n \r\n request.onsuccess = () => resolve(request.result);\r\n request.onerror = () => reject(new Error(`Failed to list keys: ${request.error}`));\r\n });\r\n }\r\n \r\n /**\r\n * Store master key salt\r\n */\r\n async storeMasterSalt(salt) {\r\n if (!this.db) {\r\n throw new Error('Database not initialized');\r\n }\r\n \r\n const transaction = this.db.transaction([this.SALT_STORE], 'readwrite');\r\n const store = transaction.objectStore(this.SALT_STORE);\r\n \r\n const saltRecord = {\r\n id: 'master_salt',\r\n salt: Array.from(new Uint8Array(salt)),\r\n created: Date.now()\r\n };\r\n \r\n return new Promise((resolve, reject) => {\r\n const request = store.put(saltRecord);\r\n \r\n request.onsuccess = () => resolve();\r\n request.onerror = () => reject(new Error(`Failed to store salt: ${request.error}`));\r\n });\r\n }\r\n \r\n /**\r\n * Retrieve master key salt\r\n */\r\n async getMasterSalt() {\r\n if (!this.db) {\r\n throw new Error('Database not initialized');\r\n }\r\n \r\n const transaction = this.db.transaction([this.SALT_STORE], 'readonly');\r\n const store = transaction.objectStore(this.SALT_STORE);\r\n \r\n return new Promise((resolve, reject) => {\r\n const request = store.get('master_salt');\r\n \r\n request.onsuccess = () => {\r\n const result = request.result;\r\n if (result) {\r\n resolve(new Uint8Array(result.salt));\r\n } else {\r\n resolve(null);\r\n }\r\n };\r\n \r\n request.onerror = () => reject(new Error(`Failed to retrieve salt: ${request.error}`));\r\n });\r\n }\r\n \r\n /**\r\n * Clear all data (for security wipe)\r\n */\r\n async clearAll() {\r\n if (!this.db) {\r\n throw new Error('Database not initialized');\r\n }\r\n \r\n const transaction = this.db.transaction([this.KEYS_STORE, this.METADATA_STORE, this.SALT_STORE], 'readwrite');\r\n \r\n return new Promise((resolve, reject) => {\r\n const keysRequest = transaction.objectStore(this.KEYS_STORE).clear();\r\n const metadataRequest = transaction.objectStore(this.METADATA_STORE).clear();\r\n const saltRequest = transaction.objectStore(this.SALT_STORE).clear();\r\n \r\n transaction.oncomplete = () => resolve();\r\n transaction.onerror = () => reject(new Error(`Failed to clear database: ${transaction.error}`));\r\n });\r\n }\r\n \r\n /**\r\n * Close database connection\r\n */\r\n close() {\r\n if (this.db) {\r\n this.db.close();\r\n this.db = null;\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * Secure Persistent Key Storage with Key Wrapping\r\n * Implements secure storage of extractable keys using AES-GCM encryption\r\n */\r\nclass SecurePersistentKeyStorage {\r\n constructor(masterKeyManager, indexedDBWrapper = null) {\r\n this._masterKeyManager = masterKeyManager;\r\n this._indexedDB = indexedDBWrapper || new SecureIndexedDBWrapper();\r\n this._dbInitialized = false;\r\n \r\n // In-memory cache for restored keys (WeakMap for automatic cleanup)\r\n this._keyCache = new WeakMap();\r\n this._keyReferences = new Map(); // Strong references for active keys\r\n }\r\n \r\n /**\r\n * Initialize IndexedDB if not already done\r\n */\r\n async _ensureDBInitialized() {\r\n if (!this._dbInitialized) {\r\n await this._indexedDB.initialize();\r\n this._dbInitialized = true;\r\n }\r\n }\r\n \r\n /**\r\n * Store extractable key with encryption\r\n */\r\n async storeExtractableKey(keyId, cryptoKey, metadata = {}) {\r\n if (!(cryptoKey instanceof CryptoKey)) {\r\n throw new Error('Only CryptoKey objects can be stored');\r\n }\r\n \r\n if (!cryptoKey.extractable) {\r\n throw new Error('Key must be extractable for persistent storage');\r\n }\r\n \r\n try {\r\n await this._ensureDBInitialized();\r\n \r\n // Export key to JWK\r\n const jwkData = await crypto.subtle.exportKey('jwk', cryptoKey);\r\n \r\n // Encrypt JWK data\r\n const { encryptedData, iv } = await this._encryptKeyData(jwkData);\r\n \r\n // Store encrypted data in IndexedDB\r\n await this._indexedDB.storeEncryptedKey(\r\n keyId,\r\n encryptedData,\r\n iv,\r\n cryptoKey.algorithm,\r\n cryptoKey.usages,\r\n cryptoKey.type,\r\n metadata\r\n );\r\n \r\n // Store non-extractable reference in memory cache\r\n const nonExtractableKey = await this._importAsNonExtractable(jwkData, cryptoKey.algorithm, cryptoKey.usages);\r\n this._keyReferences.set(keyId, nonExtractableKey);\r\n \r\n return true;\r\n \r\n } catch (error) {\r\n throw new Error(`Failed to store extractable key: ${error.message}`);\r\n }\r\n }\r\n \r\n /**\r\n * Retrieve and restore key from persistent storage\r\n */\r\n async retrieveKey(keyId) {\r\n try {\r\n // Check if key is already in memory cache\r\n if (this._keyReferences.has(keyId)) {\r\n return this._keyReferences.get(keyId);\r\n }\r\n \r\n await this._ensureDBInitialized();\r\n \r\n // Get encrypted key data from IndexedDB\r\n const keyRecord = await this._indexedDB.getEncryptedKey(keyId);\r\n if (!keyRecord) {\r\n return null;\r\n }\r\n \r\n // Decrypt JWK data\r\n const jwkData = await this._decryptKeyData(keyRecord.encryptedData, keyRecord.iv);\r\n \r\n // Import as non-extractable key\r\n const restoredKey = await this._importAsNonExtractable(jwkData, keyRecord.algorithm, keyRecord.usages);\r\n \r\n // Cache in memory\r\n this._keyReferences.set(keyId, restoredKey);\r\n \r\n // Update last accessed time\r\n await this._indexedDB.updateKeyMetadata(keyId, { lastAccessed: Date.now() });\r\n \r\n return restoredKey;\r\n \r\n } catch (error) {\r\n throw new Error(`Failed to retrieve key: ${error.message}`);\r\n }\r\n }\r\n \r\n /**\r\n * Delete key from persistent storage\r\n */\r\n async deleteKey(keyId) {\r\n try {\r\n await this._ensureDBInitialized();\r\n \r\n // Remove from IndexedDB\r\n await this._indexedDB.deleteKey(keyId);\r\n \r\n // Remove from memory cache\r\n this._keyReferences.delete(keyId);\r\n \r\n return true;\r\n \r\n } catch (error) {\r\n throw new Error(`Failed to delete key: ${error.message}`);\r\n }\r\n }\r\n \r\n /**\r\n * List all stored keys\r\n */\r\n async listStoredKeys() {\r\n try {\r\n await this._ensureDBInitialized();\r\n return await this._indexedDB.listKeys();\r\n } catch (error) {\r\n throw new Error(`Failed to list keys: ${error.message}`);\r\n }\r\n }\r\n \r\n /**\r\n * Clear all persistent storage\r\n */\r\n async clearAll() {\r\n try {\r\n await this._ensureDBInitialized();\r\n \r\n // Clear IndexedDB\r\n await this._indexedDB.clearAll();\r\n \r\n // Clear memory cache\r\n this._keyReferences.clear();\r\n \r\n return true;\r\n \r\n } catch (error) {\r\n throw new Error(`Failed to clear storage: ${error.message}`);\r\n }\r\n }\r\n \r\n /**\r\n * Encrypt key data using master key\r\n */\r\n async _encryptKeyData(jwkData) {\r\n // Convert JWK to JSON string and then to bytes\r\n const jsonString = JSON.stringify(jwkData);\r\n const data = new TextEncoder().encode(jsonString);\r\n \r\n await this._ensureMasterKeyUnlocked();\r\n return await this._masterKeyManager.encryptBytes(data);\r\n }\r\n \r\n /**\r\n * Decrypt key data using master key\r\n */\r\n async _decryptKeyData(encryptedData, iv) {\r\n await this._ensureMasterKeyUnlocked();\r\n const decryptedData = await this._masterKeyManager.decryptBytes(encryptedData, iv);\r\n \r\n // Convert back to JWK\r\n const jsonString = new TextDecoder().decode(decryptedData);\r\n return JSON.parse(jsonString);\r\n }\r\n \r\n /**\r\n * Import JWK as non-extractable key\r\n */\r\n async _importAsNonExtractable(jwkData, algorithm, usages) {\r\n return await crypto.subtle.importKey(\r\n 'jwk',\r\n jwkData,\r\n algorithm,\r\n false, // non-extractable for security\r\n usages\r\n );\r\n }\r\n \r\n /**\r\n * Get storage statistics\r\n */\r\n async getStorageStats() {\r\n try {\r\n await this._ensureDBInitialized();\r\n const keys = await this._indexedDB.listKeys();\r\n \r\n return {\r\n totalKeys: keys.length,\r\n memoryKeys: this._keyReferences.size,\r\n persistentKeys: keys.length,\r\n lastAccessed: keys.reduce((latest, key) => \r\n Math.max(latest, key.lastAccessed || 0), 0)\r\n };\r\n \r\n } catch (error) {\r\n return {\r\n totalKeys: 0,\r\n memoryKeys: this._keyReferences.size,\r\n persistentKeys: 0,\r\n lastAccessed: 0,\r\n error: error.message\r\n };\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * Secure Master Key Manager with Password-Based Derivation\r\n * Implements PBKDF2-based key derivation and session management\r\n */\r\nclass SecureMasterKeyManager {\r\n constructor(indexedDBWrapper = null) {\r\n // Session state\r\n this._keyHandle = null; // non-extractable CryptoKey\r\n this._isUnlocked = false;\r\n this._sessionTimeout = null;\r\n this._lastActivity = null;\r\n \r\n // Configuration\r\n this._sessionTimeoutMs = 60 * 60 * 1000; // 60 minutes (\u0443\u0432\u0435\u043B\u0438\u0447\u0435\u043D\u043E \u0441 15 \u043C\u0438\u043D\u0443\u0442)\r\n this._inactivityTimeoutMs = 30 * 60 * 1000; // 30 minutes (\u0443\u0432\u0435\u043B\u0438\u0447\u0435\u043D\u043E \u0441 5 \u043C\u0438\u043D\u0443\u0442)\r\n \r\n // PBKDF2 parameters\r\n this._pbkdf2Iterations = 310000; // OWASP 2025 recommendation for PBKDF2-SHA256\r\n this._saltSize = 32; // 256 bits\r\n \r\n // IndexedDB wrapper for persistent salt storage\r\n this._indexedDB = indexedDBWrapper || new SecureIndexedDBWrapper();\r\n this._dbInitialized = false;\r\n \r\n // Event handlers\r\n this._onPasswordRequired = null;\r\n this._onSessionExpired = null;\r\n this._onUnlocked = null;\r\n \r\n // Setup event listeners (disabled for better UX - no auto-disconnect)\r\n // this._setupEventListeners();\r\n }\r\n \r\n /**\r\n * Set callback for password requests\r\n */\r\n setPasswordRequiredCallback(callback) {\r\n this._onPasswordRequired = callback;\r\n }\r\n \r\n /**\r\n * Set callback for session expiration\r\n */\r\n setSessionExpiredCallback(callback) {\r\n this._onSessionExpired = callback;\r\n }\r\n \r\n /**\r\n * Set callback for successful unlock\r\n */\r\n setUnlockedCallback(callback) {\r\n this._onUnlocked = callback;\r\n }\r\n \r\n /**\r\n * Setup event listeners for session management\r\n */\r\n _setupEventListeners() {\r\n // Handle page visibility changes\r\n if (typeof document !== 'undefined') {\r\n document.addEventListener('visibilitychange', () => {\r\n if (document.hidden) {\r\n this._handleFocusOut();\r\n } else {\r\n this._handleFocusIn();\r\n }\r\n });\r\n \r\n // Handle window focus/blur\r\n window.addEventListener('blur', () => this._handleFocusOut());\r\n window.addEventListener('focus', () => this._handleFocusIn());\r\n \r\n // Handle user activity\r\n ['mousedown', 'mousemove', 'keypress', 'scroll', 'touchstart'].forEach(event => {\r\n document.addEventListener(event, () => this._updateActivity(), { passive: true });\r\n });\r\n }\r\n }\r\n \r\n /**\r\n * Handle focus out - start inactivity timer\r\n */\r\n _handleFocusOut() {\r\n if (this._isUnlocked) {\r\n // Start shorter timeout when window loses focus\r\n this._startInactivityTimer(this._inactivityTimeoutMs);\r\n }\r\n }\r\n \r\n /**\r\n * Handle focus in - reset timers\r\n */\r\n _handleFocusIn() {\r\n if (this._isUnlocked) {\r\n this._resetSessionTimer();\r\n }\r\n }\r\n \r\n /**\r\n * Update last activity timestamp\r\n */\r\n _updateActivity() {\r\n this._lastActivity = Date.now();\r\n if (this._isUnlocked) {\r\n this._resetSessionTimer();\r\n }\r\n }\r\n \r\n /**\r\n * Start session timer\r\n */\r\n _startSessionTimer() {\r\n this._clearTimers();\r\n this._sessionTimeout = setTimeout(() => {\r\n this._expireSession('timeout');\r\n }, this._sessionTimeoutMs);\r\n }\r\n \r\n /**\r\n * Start inactivity timer\r\n */\r\n _startInactivityTimer(timeout) {\r\n this._clearTimers();\r\n this._sessionTimeout = setTimeout(() => {\r\n this._expireSession('inactivity');\r\n }, timeout);\r\n }\r\n \r\n /**\r\n * Reset session timer\r\n */\r\n _resetSessionTimer() {\r\n if (this._isUnlocked) {\r\n this._startSessionTimer();\r\n }\r\n }\r\n \r\n /**\r\n * Clear all timers\r\n */\r\n _clearTimers() {\r\n if (this._sessionTimeout) {\r\n clearTimeout(this._sessionTimeout);\r\n this._sessionTimeout = null;\r\n }\r\n }\r\n \r\n /**\r\n * Expire the current session\r\n */\r\n _expireSession(reason = 'unknown') {\r\n if (this._isUnlocked) {\r\n this._secureWipeMasterKey();\r\n this._isUnlocked = false;\r\n \r\n if (this._onSessionExpired) {\r\n this._onSessionExpired(reason);\r\n }\r\n }\r\n }\r\n \r\n /**\r\n * Initialize IndexedDB if not already done\r\n */\r\n async _ensureDBInitialized() {\r\n if (!this._dbInitialized) {\r\n await this._indexedDB.initialize();\r\n this._dbInitialized = true;\r\n }\r\n }\r\n \r\n /**\r\n * Generate salt for PBKDF2\r\n */\r\n _generateSalt() {\r\n return crypto.getRandomValues(new Uint8Array(this._saltSize));\r\n }\r\n \r\n /**\r\n * Get or create persistent salt\r\n */\r\n async _getOrCreateSalt() {\r\n await this._ensureDBInitialized();\r\n \r\n // Try to get existing salt\r\n let salt = await this._indexedDB.getMasterSalt();\r\n \r\n if (!salt) {\r\n // Generate new salt and store it\r\n salt = this._generateSalt();\r\n await this._indexedDB.storeMasterSalt(salt);\r\n }\r\n \r\n return salt;\r\n }\r\n \r\n /**\r\n * Derive master key from password using PBKDF2\r\n */\r\n async _deriveKeyFromPassword(password, salt) {\r\n try {\r\n // Import password as key material\r\n const passwordKey = await crypto.subtle.importKey(\r\n 'raw',\r\n new TextEncoder().encode(password),\r\n 'PBKDF2',\r\n false,\r\n ['deriveKey']\r\n );\r\n \r\n // Derive AES-GCM key using PBKDF2\r\n const derivedKey = await crypto.subtle.deriveKey(\r\n {\r\n name: 'PBKDF2',\r\n salt: salt,\r\n iterations: this._pbkdf2Iterations,\r\n hash: 'SHA-256'\r\n },\r\n passwordKey,\r\n {\r\n name: 'AES-GCM',\r\n length: 256\r\n },\r\n false, // non-extractable for security\r\n ['encrypt', 'decrypt', 'wrapKey', 'unwrapKey']\r\n );\r\n \r\n return derivedKey;\r\n } catch (error) {\r\n throw new Error(`Key derivation failed: ${error.message}`);\r\n }\r\n }\r\n \r\n /**\r\n * Request password from user\r\n */\r\n async _requestPassword(isRetry = false) {\r\n if (!this._onPasswordRequired) {\r\n throw new Error('Password callback not set');\r\n }\r\n \r\n return new Promise((resolve, reject) => {\r\n this._onPasswordRequired(isRetry, (password) => {\r\n if (password) {\r\n resolve(password);\r\n } else {\r\n reject(new Error('Password not provided'));\r\n }\r\n });\r\n });\r\n }\r\n \r\n /**\r\n * Unlock the master key with password\r\n */\r\n async unlock(password = null) {\r\n try {\r\n // Request password if not provided\r\n if (!password) {\r\n password = await this._requestPassword(false);\r\n }\r\n \r\n // Get or create persistent salt\r\n const salt = await this._getOrCreateSalt();\r\n \r\n // Derive non-extractable key handle\r\n this._keyHandle = await this._deriveKeyFromPassword(password, salt);\r\n \r\n // Mark as unlocked\r\n this._isUnlocked = true;\r\n this._lastActivity = Date.now();\r\n \r\n // Start session timer\r\n this._startSessionTimer();\r\n \r\n // Securely wipe password from memory\r\n password = null;\r\n \r\n if (this._onUnlocked) {\r\n this._onUnlocked();\r\n }\r\n \r\n return { success: true };\r\n \r\n } catch (error) {\r\n // Securely wipe password on error\r\n password = null;\r\n throw error;\r\n }\r\n }\r\n \r\n /**\r\n * Lock the master key\r\n */\r\n lock() {\r\n this._expireSession('manual');\r\n }\r\n \r\n /**\r\n * Get master key (only if unlocked)\r\n */\r\n // Prevent direct key access; provide operations only\r\n async encryptBytes(plainBytes) {\r\n if (!this._isUnlocked || !this._keyHandle) {\r\n throw new Error('Master key is locked');\r\n }\r\n this._updateActivity();\r\n const iv = crypto.getRandomValues(new Uint8Array(12));\r\n const encrypted = await crypto.subtle.encrypt({ name: 'AES-GCM', iv }, this._keyHandle, plainBytes);\r\n return { encryptedData: new Uint8Array(encrypted), iv };\r\n }\r\n\r\n async decryptBytes(encryptedBytes, iv) {\r\n if (!this._isUnlocked || !this._keyHandle) {\r\n throw new Error('Master key is locked');\r\n }\r\n this._updateActivity();\r\n const decrypted = await crypto.subtle.decrypt({ name: 'AES-GCM', iv }, this._keyHandle, encryptedBytes);\r\n return new Uint8Array(decrypted);\r\n }\r\n \r\n /**\r\n * Check if master key is unlocked\r\n */\r\n isUnlocked() {\r\n return this._isUnlocked && this._masterKey !== null;\r\n }\r\n \r\n /**\r\n * Get session status\r\n */\r\n getSessionStatus() {\r\n return {\r\n isUnlocked: this._isUnlocked,\r\n lastActivity: this._lastActivity,\r\n sessionTimeoutMs: this._sessionTimeoutMs,\r\n inactivityTimeoutMs: this._inactivityTimeoutMs\r\n };\r\n }\r\n \r\n /**\r\n * Securely wipe master key from memory\r\n */\r\n _secureWipeMasterKey() {\r\n if (this._keyHandle) {\r\n // CryptoKey objects are automatically garbage collected\r\n // but we clear the reference immediately\r\n this._keyHandle = null;\r\n }\r\n this._clearTimers();\r\n }\r\n \r\n /**\r\n * Cleanup on destruction\r\n */\r\n destroy() {\r\n this._secureWipeMasterKey();\r\n this._isUnlocked = false;\r\n \r\n // Remove event listeners\r\n if (typeof document !== 'undefined') {\r\n document.removeEventListener('visibilitychange', this._handleFocusOut);\r\n window.removeEventListener('blur', this._handleFocusOut);\r\n window.removeEventListener('focus', this._handleFocusIn);\r\n }\r\n }\r\n}\r\n\r\nexport { \r\n EnhancedSecureWebRTCManager, \r\n SecureMasterKeyManager, \r\n SecureIndexedDBWrapper, \r\n SecurePersistentKeyStorage \r\n};", "import { EnhancedSecureCryptoUtils } from '../crypto/EnhancedSecureCryptoUtils.js';\r\nimport { EnhancedSecureWebRTCManager } from '../network/EnhancedSecureWebRTCManager.js';\r\nimport { EnhancedSecureFileTransfer } from '../transfer/EnhancedSecureFileTransfer.js';\r\nimport { NotificationIntegration } from '../notifications/NotificationIntegration.js';\r\n\r\n// Import UI components (side-effect: they attach themselves to window.*)\r\nimport '../components/ui/Header.jsx';\r\nimport '../components/ui/DownloadApps.jsx';\r\nimport '../components/ui/BecomePartner.jsx';\r\nimport '../components/ui/UniqueFeatureSlider.jsx';\r\nimport '../components/ui/SecurityFeatures.jsx';\r\nimport '../components/ui/Testimonials.jsx';\r\nimport '../components/ui/ComparisonTable.jsx';\r\nimport '../components/ui/Roadmap.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.EnhancedSecureFileTransfer = EnhancedSecureFileTransfer;\r\nwindow.NotificationIntegration = NotificationIntegration;\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", "const EnhancedMinimalHeader = ({ \n status, \n fingerprint, \n verificationCode, \n onDisconnect, \n isConnected, \n securityLevel, \n webrtcManager \n}) => {\n const [realSecurityLevel, setRealSecurityLevel] = React.useState(null);\n const [lastSecurityUpdate, setLastSecurityUpdate] = React.useState(0);\n // Added local session state to remove references errors after session timer removal\n const [hasActiveSession, setHasActiveSession] = React.useState(false);\n const [currentTimeLeft, setCurrentTimeLeft] = React.useState(0);\n const [sessionType, setSessionType] = React.useState('unknown');\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 (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 } else if (window.DEBUG_MODE) {\n }\n } else {\n \n }\n \n } catch (error) {\n \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]);\n\n // ============================================\n // FIXED EVENT HANDLERS\n // ============================================\n\n React.useEffect(() => {\n const handleSecurityUpdate = (event) => {\n\n setTimeout(() => {\n setLastSecurityUpdate(0);\n }, 100);\n };\n\n const handleRealSecurityCalculated = (event) => {\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 \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 \n }\n })\n .catch(error => {\n \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 // All security features are enabled by default - no session management needed\n setHasActiveSession(true);\n setCurrentTimeLeft(0);\n setSessionType('premium'); // All features enabled\n }, []);\n\n React.useEffect(() => {\n // All security features are enabled by default\n setHasActiveSession(true);\n setCurrentTimeLeft(0);\n setSessionType('premium'); // All features enabled\n }, []);\n\n React.useEffect(() => {\n const handleForceUpdate = (event) => {\n // All security features are enabled by default\n setHasActiveSession(true);\n setCurrentTimeLeft(0);\n setSessionType('premium'); // All features enabled\n };\n\n // Connection cleanup handler (use existing event from module)\n const handleConnectionCleaned = () => {\n \n\n setRealSecurityLevel(null);\n setLastSecurityUpdate(0);\n\n setHasActiveSession(false);\n setCurrentTimeLeft(0);\n setSessionType('unknown');\n };\n\n const handlePeerDisconnect = () => {\n \n\n setRealSecurityLevel(null);\n setLastSecurityUpdate(0);\n };\n\n const handleDisconnected = () => {\n\n setRealSecurityLevel(null);\n setLastSecurityUpdate(0);\n setHasActiveSession(false);\n setCurrentTimeLeft(0);\n setSessionType('unknown');\n };\n\n document.addEventListener('force-header-update', handleForceUpdate);\n document.addEventListener('peer-disconnect', handlePeerDisconnect);\n document.addEventListener('connection-cleaned', handleConnectionCleaned);\n document.addEventListener('disconnected', handleDisconnected);\n \n return () => {\n document.removeEventListener('force-header-update', handleForceUpdate);\n document.removeEventListener('peer-disconnect', handlePeerDisconnect);\n document.removeEventListener('connection-cleaned', handleConnectionCleaned);\n document.removeEventListener('disconnected', handleDisconnected);\n };\n }, []);\n\n // ============================================\n // SECURITY INDICATOR CLICK HANDLER\n // ============================================\n\n const handleSecurityClick = async (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 // Prevent default behavior\n event.preventDefault();\n event.stopPropagation();\n\n\n // Run real security tests if webrtcManager is available\n let realTestResults = null;\n if (webrtcManager && window.EnhancedSecureCryptoUtils) {\n try {\n realTestResults = await window.EnhancedSecureCryptoUtils.calculateSecurityLevel(webrtcManager);\n \n } catch (error) {\n \n }\n } else {\n \n }\n\n // If no real test results and no existing security level, show progress message\n if (!realTestResults && !realSecurityLevel) {\n alert('Security verification in progress...\\nPlease wait for real-time cryptographic verification to complete.');\n return;\n }\n\n // Use real test results if available, otherwise fall back to current data\n let securityData = realTestResults || realSecurityLevel;\n\n // If still no security data, create a basic fallback\n if (!securityData) {\n securityData = {\n level: 'UNKNOWN',\n score: 0,\n color: 'gray',\n verificationResults: {},\n timestamp: Date.now(),\n details: 'Security verification not available',\n isRealData: false,\n passedChecks: 0,\n totalChecks: 0\n };\n \n }\n\n // Detailed information about the REAL security check\n let message = `REAL-TIME SECURITY VERIFICATION\\n\\n`;\n message += `Security Level: ${securityData.level} (${securityData.score}%)\\n`;\n message += `Verification Time: ${new Date(securityData.timestamp).toLocaleTimeString()}\\n`;\n message += `Data Source: ${securityData.isRealData ? 'Real Cryptographic Tests' : 'Simulated Data'}\\n\\n`;\n \n if (securityData.verificationResults) {\n message += 'DETAILED CRYPTOGRAPHIC TESTS:\\n';\n message += '=' + '='.repeat(40) + '\\n';\n \n const passedTests = Object.entries(securityData.verificationResults).filter(([key, result]) => result.passed);\n const failedTests = Object.entries(securityData.verificationResults).filter(([key, result]) => !result.passed);\n \n if (passedTests.length > 0) {\n message += '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 || 'Test passed'}\\n`;\n });\n message += '\\n';\n }\n \n if (failedTests.length > 0) {\n message += 'FAILED/UNAVAILABLE 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 || 'Test failed or unavailable'}\\n`;\n });\n message += '\\n';\n }\n \n message += `SUMMARY:\\n`;\n message += `Passed: ${securityData.passedChecks}/${securityData.totalChecks} tests\\n`;\n message += `Score: ${securityData.score}/${securityData.maxPossibleScore || 100} points\\n\\n`;\n }\n \n // Real security features status\n message += `SECURITY FEATURES STATUS:\\n`;\n message += '=' + '='.repeat(40) + '\\n';\n \n if (securityData.verificationResults) {\n const features = {\n 'ECDSA Digital Signatures': securityData.verificationResults.verifyECDSASignatures?.passed || false,\n 'ECDH Key Exchange': securityData.verificationResults.verifyECDHKeyExchange?.passed || false,\n 'AES-GCM Encryption': securityData.verificationResults.verifyEncryption?.passed || false,\n 'Message Integrity (HMAC)': securityData.verificationResults.verifyMessageIntegrity?.passed || false,\n 'Perfect Forward Secrecy': securityData.verificationResults.verifyPerfectForwardSecrecy?.passed || false,\n 'Replay Protection': securityData.verificationResults.verifyReplayProtection?.passed || false,\n 'DTLS Fingerprint': securityData.verificationResults.verifyDTLSFingerprint?.passed || false,\n 'SAS Verification': securityData.verificationResults.verifySASVerification?.passed || false,\n 'Metadata Protection': securityData.verificationResults.verifyMetadataProtection?.passed || false,\n 'Traffic Obfuscation': securityData.verificationResults.verifyTrafficObfuscation?.passed || false\n };\n \n Object.entries(features).forEach(([feature, isEnabled]) => {\n message += `${isEnabled ? '\u2705' : '\u274C'} ${feature}\\n`;\n });\n } else {\n // Fallback if no verification results\n message += `\u2705 ECDSA Digital Signatures\\n`;\n message += `\u2705 ECDH Key Exchange\\n`;\n message += `\u2705 AES-GCM Encryption\\n`;\n message += `\u2705 Message Integrity (HMAC)\\n`;\n message += `\u2705 Perfect Forward Secrecy\\n`;\n message += `\u2705 Replay Protection\\n`;\n message += `\u2705 DTLS Fingerprint\\n`;\n message += `\u2705 SAS Verification\\n`;\n message += `\u2705 Metadata Protection\\n`;\n message += `\u2705 Traffic Obfuscation\\n`;\n }\n \n message += `\\n${securityData.details || 'Real cryptographic verification completed'}`;\n \n if (securityData.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 // Show in a more user-friendly way\n const modal = document.createElement('div');\n modal.style.cssText = `\n position: fixed;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n background: rgba(0,0,0,0.8);\n z-index: 10000;\n display: flex;\n align-items: center;\n justify-content: center;\n font-family: monospace;\n `;\n \n const content = document.createElement('div');\n content.style.cssText = `\n background: #1a1a1a;\n color: #fff;\n padding: 20px;\n border-radius: 8px;\n max-width: 80%;\n max-height: 80%;\n overflow-y: auto;\n white-space: pre-line;\n border: 1px solid #333;\n `;\n \n content.textContent = message;\n modal.appendChild(content);\n \n // Close on click outside\n modal.addEventListener('click', (e) => {\n if (e.target === modal) {\n document.body.removeChild(modal);\n }\n });\n \n // Close on Escape key\n const handleKeyDown = (e) => {\n if (e.key === 'Escape') {\n document.body.removeChild(modal);\n document.removeEventListener('keydown', handleKeyDown);\n }\n };\n document.addEventListener('keydown', handleKeyDown);\n \n document.body.appendChild(modal);\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 = isConnected ? (realSecurityLevel || securityLevel) : null;\n \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 = undefined;\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.7.56')\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\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 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://securebit.chat/', color: 'green' },\r\n { id: 'windows', name: 'Windows', subtitle: 'Desktop App', icon: 'fab fa-windows', platform: 'Desktop', isActive: true, url: 'https://github.com/SecureBitChat/securebit-desktop/releases/latest/download/SecureBit.Chat_0.1.0_x64-setup.exe', color: 'blue' },\r\n { id: 'macos', name: 'macOS', subtitle: 'Desktop App', icon: 'fab fa-safari', platform: 'Desktop', isActive: true, url: 'https://github.com/SecureBitChat/securebit-desktop/releases/download/v0.1.0/SecureBit.Chat_0.1.0_x64.dmg', color: 'gray' },\r\n { id: 'linux', name: 'Linux', subtitle: 'Desktop App', icon: 'fab fa-linux', platform: 'Desktop', isActive: true, url: 'https://github.com/SecureBitChat/securebit-desktop/releases/latest/download/SecureBit.Chat_0.1.0_amd64.AppImage', 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: 'white' },\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 { id: 'chrome', name: 'Chrome', subtitle: 'Browser Extension', icon: 'fab fa-chrome', platform: 'Browser', isActive: false, url: '#', color: 'yellow' },\r\n { id: 'edge', name: 'Edge', subtitle: 'Browser Extension', icon: 'fab fa-edge', platform: 'Browser', isActive: false, url: '#', color: 'blue' },\r\n { id: 'opera', name: 'Opera', subtitle: 'Browser Extension', icon: 'fab fa-opera', platform: 'Browser', isActive: false, url: '#', color: 'red' },\r\n { id: 'firefox', name: 'Firefox', subtitle: 'Browser Extension', icon: 'fab fa-firefox-browser', platform: 'Browser', isActive: false, url: '#', color: 'orange' },\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 === 'Desktop' || a.platform === 'Web');\r\n const mobileApps = apps.filter(a => a.platform === 'Mobile');\r\n const browserApps = apps.filter(a => a.platform === 'Browser');\r\n\r\n const cardSize = \"w-28 h-28\";\r\n\r\n const colorClasses = {\r\n green: 'text-green-500',\r\n blue: 'text-blue-500',\r\n gray: 'text-gray-500',\r\n orange: 'text-orange-500',\r\n red: 'text-red-500',\r\n white: 'text-white',\r\n yellow: 'text-yellow-400',\r\n };\r\n\r\n const renderAppCard = (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] ${app.isActive ? colorClasses[app.color] : '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 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 // Desktop Apps\r\n React.createElement('div', { key: 'desktop-row', className: \"hidden sm:flex justify-center flex-wrap gap-6 mb-6\" },\r\n desktopApps.map(renderAppCard)\r\n ),\r\n\r\n // Mobile Apps\r\n React.createElement('div', { key: 'mobile-row', className: \"flex justify-center gap-6 mb-6\" },\r\n mobileApps.map(renderAppCard)\r\n ),\r\n\r\n // Browser Extensions\r\n React.createElement('div', { key: 'browser-row', className: \"flex justify-center gap-6\" },\r\n browserApps.map(renderAppCard)\r\n )\r\n ]);\r\n};\r\n\r\nwindow.DownloadApps = DownloadApps;\r\n", "const BecomePartner = () => {\r\n const partners = [\r\n { id: 'aegis', name: 'Aegis', logo: 'logo/aegis.png', isColor: true, url: 'https://aegis-investment.com/' },\r\n { id: 'furi', name: 'Furi Labs', logo: 'logo/furi.png', isColor: true, url: 'https://furilabs.com/' }\r\n ];\r\n\r\n const formUrl = 'https://docs.google.com/forms/d/e/1FAIpQLSc9ijV9PCoyXkus6vEx1OWwvwAsLq8fKS6-H5BmX-c-bvia6w/viewform?usp=dialog';\r\n\r\n return React.createElement('div', { className: \"mt-20 px-6\" }, [\r\n // Header \"Trusted by our partners\"\r\n React.createElement('div', { key: 'header', className: \"text-center max-w-3xl mx-auto mb-8\" }, [\r\n React.createElement('h3', { key: 'title', className: \"text-3xl font-bold text-primary mb-3\" }, 'Trusted by our partners')\r\n ]),\r\n\r\n // First divider line with fade\r\n React.createElement('div', {\r\n key: 'divider-1',\r\n className: \"h-px w-full max-w-3xl mx-auto mb-8 bg-gradient-to-r from-transparent via-zinc-700 to-transparent\"\r\n }),\r\n\r\n // Partner Logos\r\n React.createElement('div', { \r\n key: 'partners-row', \r\n className: \"flex justify-center items-center flex-wrap gap-12 mb-8\" \r\n },\r\n partners.map(partner => \r\n React.createElement('a', {\r\n key: partner.id,\r\n href: partner.url,\r\n target: '_blank',\r\n rel: 'noopener noreferrer',\r\n className: \"flex items-center justify-center cursor-pointer hover:opacity-100 transition-opacity duration-300\"\r\n }, [\r\n React.createElement('img', {\r\n key: 'logo',\r\n src: partner.logo,\r\n alt: partner.name,\r\n className: \"h-12 sm:h-16 opacity-80 hover:opacity-100 transition-opacity duration-300\",\r\n style: partner.isColor ? {\r\n filter: 'grayscale(100%) brightness(1.2) contrast(1.1)',\r\n WebkitFilter: 'grayscale(100%) brightness(1.2) contrast(1.1)'\r\n } : {}\r\n })\r\n ])\r\n )\r\n ),\r\n\r\n // Second divider line with fade\r\n React.createElement('div', {\r\n key: 'divider-2',\r\n className: \"h-px w-full max-w-3xl mx-auto mb-8 bg-gradient-to-r from-transparent via-zinc-700 to-transparent\"\r\n }),\r\n\r\n // Section with subtitle and text\r\n React.createElement('div', { key: 'cta-section', className: \"text-center max-w-3xl mx-auto\" }, [\r\n React.createElement('h4', {\r\n key: 'subtitle',\r\n className: \"text-base font-semibold text-primary mb-4\"\r\n }, 'Technology & Community Partners'),\r\n \r\n React.createElement('p', {\r\n key: 'description',\r\n className: \"text-secondary text-sm mb-6\"\r\n }, 'Interested in partnering with us?'),\r\n\r\n // CTA Button with 3D glass effect\r\n React.createElement('div', {\r\n key: 'button-wrapper',\r\n className: \"button-container flex justify-center\"\r\n }, [\r\n React.createElement('a', {\r\n key: 'button-link',\r\n href: formUrl,\r\n target: '_blank',\r\n rel: 'noopener noreferrer',\r\n className: \"button\"\r\n }, [\r\n React.createElement('span', { key: 'text' }, 'Become a Partner')\r\n ])\r\n ])\r\n ])\r\n ]);\r\n};\r\n\r\nwindow.BecomePartner = BecomePartner;\r\n\r\n", "// Enhanced Modern Slider Component with Loading Protection\r\nconst UniqueFeatureSlider = () => {\r\n const trackRef = React.useRef(null);\r\n const wrapRef = React.useRef(null);\r\n const [current, setCurrent] = React.useState(0);\r\n const [isReady, setIsReady] = React.useState(false);\r\n\r\n const slides = [\r\n {\r\n icon: \"\uD83D\uDEE1\uFE0F\",\r\n bgImage: \"linear-gradient(135deg, rgb(255 107 53 / 6%) 0%, rgb(255 140 66 / 45%) 100%)\",\r\n thumbIcon: \"\uD83D\uDD12\",\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.\"\r\n },\r\n {\r\n icon: \"\uD83C\uDF10\",\r\n bgImage: \"linear-gradient(135deg, rgb(147 51 234 / 6%) 0%, rgb(168 85 247 / 45%) 100%)\",\r\n thumbIcon: \"\uD83D\uDD17\",\r\n title: \"Pure P2P WebRTC\",\r\n description: \"Direct peer-to-peer connections without any servers. Complete decentralization with zero infrastructure.\"\r\n },\r\n {\r\n icon: \"\uD83D\uDD04\",\r\n bgImage: \"linear-gradient(135deg, rgb(16 185 129 / 6%) 0%, rgb(52 211 153 / 45%) 100%)\",\r\n thumbIcon: \"\u26A1\",\r\n title: \"Perfect Forward Secrecy\",\r\n description: \"Automatic key rotation every 5 minutes. Non-extractable keys with hardware protection.\"\r\n },\r\n {\r\n icon: \"\uD83C\uDFAD\",\r\n bgImage: \"linear-gradient(135deg, rgb(6 182 212 / 6%) 0%, rgb(34 211 238 / 45%) 100%)\",\r\n thumbIcon: \"\uD83C\uDF2B\uFE0F\",\r\n title: \"Traffic Obfuscation\",\r\n description: \"Fake traffic generation and pattern masking make communication indistinguishable from noise.\"\r\n },\r\n {\r\n icon: \"\uD83D\uDC41\uFE0F\",\r\n bgImage: \"linear-gradient(135deg, rgb(37 99 235 / 6%) 0%, rgb(59 130 246 / 45%) 100%)\",\r\n thumbIcon: \"\uD83D\uDEAB\",\r\n title: \"Zero Data Collection\",\r\n description: \"No registration, no servers, no logs. Complete anonymity with instant channels.\"\r\n }\r\n ];\r\n\r\n // \u041F\u0440\u043E\u0432\u0435\u0440\u043A\u0430 \u0433\u043E\u0442\u043E\u0432\u043D\u043E\u0441\u0442\u0438 \u043A\u043E\u043C\u043F\u043E\u043D\u0435\u043D\u0442\u0430\r\n React.useEffect(() => {\r\n const timer = setTimeout(() => {\r\n setIsReady(true);\r\n }, 100);\r\n return () => clearTimeout(timer);\r\n }, []);\r\n\r\n const isMobile = () => window.matchMedia(\"(max-width:767px)\").matches;\r\n\r\n const center = React.useCallback((i) => {\r\n if (!trackRef.current || !wrapRef.current) return;\r\n const card = trackRef.current.children[i];\r\n if (!card) return;\r\n\r\n const axis = isMobile() ? \"top\" : \"left\";\r\n const size = isMobile() ? \"clientHeight\" : \"clientWidth\";\r\n const start = isMobile() ? card.offsetTop : card.offsetLeft;\r\n \r\n wrapRef.current.scrollTo({\r\n [axis]: start - (wrapRef.current[size] / 2 - card[size] / 2),\r\n behavior: \"smooth\"\r\n });\r\n }, []);\r\n\r\n const activate = React.useCallback((i, scroll = false) => {\r\n if (i === current) return;\r\n setCurrent(i);\r\n if (scroll) {\r\n setTimeout(() => center(i), 50);\r\n }\r\n }, [current, center]);\r\n\r\n const go = (step) => {\r\n const newIndex = Math.min(Math.max(current + step, 0), slides.length - 1);\r\n activate(newIndex, true);\r\n };\r\n\r\n React.useEffect(() => {\r\n const handleKeydown = (e) => {\r\n if ([\"ArrowRight\", \"ArrowDown\"].includes(e.key)) go(1);\r\n if ([\"ArrowLeft\", \"ArrowUp\"].includes(e.key)) go(-1);\r\n };\r\n\r\n window.addEventListener(\"keydown\", handleKeydown, { passive: true });\r\n return () => window.removeEventListener(\"keydown\", handleKeydown);\r\n }, [current]);\r\n\r\n React.useEffect(() => {\r\n if (isReady) {\r\n center(current);\r\n }\r\n }, [current, center, isReady]);\r\n // Render loading state if not ready\r\n if (!isReady) {\r\n return React.createElement('section', { \r\n style: { \r\n background: 'transparent',\r\n minHeight: '400px',\r\n display: 'flex',\r\n alignItems: 'center',\r\n justifyContent: 'center'\r\n } \r\n }, \r\n React.createElement('div', { \r\n style: { \r\n opacity: 0.5,\r\n fontSize: '14px',\r\n color: '#fff'\r\n }\r\n }, 'Loading...')\r\n );\r\n }\r\n\r\n return React.createElement('section', { style: { background: 'transparent' } }, [\r\n // Header\r\n React.createElement('div', { \r\n key: 'head',\r\n className: 'head'\r\n }, [\r\n React.createElement('h2', { \r\n key: 'title', \r\n className: 'text-2xl sm:text-3xl font-bold text-white mb-4 leading-snug' \r\n }, 'Why SecureBit.chat is unique'),\r\n React.createElement('div', { \r\n key: 'controls',\r\n className: 'controls'\r\n }, [\r\n React.createElement('button', {\r\n key: 'prev',\r\n id: 'prev-slider',\r\n className: 'nav-btn',\r\n 'aria-label': 'Prev',\r\n disabled: current === 0,\r\n onClick: () => go(-1)\r\n }, '\u2039'),\r\n React.createElement('button', {\r\n key: 'next',\r\n id: 'next-slider',\r\n className: 'nav-btn',\r\n 'aria-label': 'Next',\r\n disabled: current === slides.length - 1,\r\n onClick: () => go(1)\r\n }, '\u203A')\r\n ])\r\n ]),\r\n\r\n // Slider\r\n React.createElement('div', {\r\n key: 'slider',\r\n className: 'slider',\r\n ref: wrapRef\r\n },\r\n React.createElement('div', {\r\n className: 'track',\r\n ref: trackRef\r\n }, slides.map((slide, index) =>\r\n React.createElement('article', {\r\n key: index,\r\n className: 'project-card',\r\n ...(index === current ? { active: '' } : {}),\r\n onMouseEnter: () => {\r\n if (window.matchMedia(\"(hover:hover)\").matches) {\r\n activate(index, true);\r\n }\r\n },\r\n onClick: () => activate(index, true)\r\n }, [\r\n // Background\r\n React.createElement('div', {\r\n key: 'bg',\r\n className: 'project-card__bg',\r\n style: {\r\n background: slide.bgImage,\r\n backgroundSize: 'cover',\r\n backgroundPosition: 'center'\r\n }\r\n }),\r\n\r\n // Content\r\n React.createElement('div', {\r\n key: 'content',\r\n className: 'project-card__content'\r\n }, [\r\n // Text container\r\n React.createElement('div', { key: 'text' }, [\r\n React.createElement('h3', {\r\n key: 'title',\r\n className: 'project-card__title'\r\n }, slide.title),\r\n React.createElement('p', {\r\n key: 'desc',\r\n className: 'project-card__desc'\r\n }, slide.description)\r\n ])\r\n ])\r\n ])\r\n ))\r\n ),\r\n ]);\r\n};\r\n\r\n// Export for use in your app\r\nwindow.UniqueFeatureSlider = UniqueFeatureSlider;", "const SecurityFeatures = () => {\r\n const features = [\r\n { id: 'feature1', color: '#00ff88', icon: 'fas fa-key accent-green', title: 'ECDH P-384 Key Exchange', desc: 'Military-grade elliptic curve key exchange' },\r\n { id: 'feature2', color: '#a78bfa', icon: 'fas fa-user-shield accent-purple', title: 'MITM Protection', desc: 'Out-of-band verification against attacks' },\r\n { id: 'feature3', color: '#ff8800', icon: 'fas fa-lock accent-orange', title: 'AES-GCM 256 Encryption', desc: 'Authenticated encryption standard' },\r\n { id: 'feature4', color: '#00ffff', icon: 'fas fa-sync-alt accent-cyan', title: 'Perfect Forward Secrecy', desc: 'Automatic key rotation every 5 minutes' },\r\n { id: 'feature5', color: '#0088ff', icon: 'fas fa-signature accent-blue', title: 'ECDSA P-384 Signatures', desc: 'Digital signatures for message integrity' },\r\n { id: 'feature6', color: '#f87171', icon: 'fas fa-shield-alt accent-red', title: 'SAS Security', desc: 'Revolutionary key exchange & MITM protection' }\r\n ];\r\n\r\n React.useEffect(() => {\r\n const cards = document.querySelectorAll(\".card\");\r\n const radius = 200; \r\n\r\n const handleMove = (e) => {\r\n cards.forEach((card) => {\r\n const rect = card.getBoundingClientRect();\r\n const cx = rect.left + rect.width / 2;\r\n const cy = rect.top + rect.height / 2;\r\n\r\n const dx = e.clientX - cx;\r\n const dy = e.clientY - cy;\r\n const dist = Math.sqrt(dx * dx + dy * dy);\r\n\r\n if (dist < radius) {\r\n const x = e.clientX - rect.left;\r\n const y = e.clientY - rect.top;\r\n card.style.setProperty(\"--x\", `${x}px`);\r\n card.style.setProperty(\"--y\", `${y}px`);\r\n card.classList.add(\"active-glow\");\r\n } else {\r\n card.classList.remove(\"active-glow\");\r\n }\r\n });\r\n };\r\n\r\n window.addEventListener(\"mousemove\", handleMove);\r\n return () => window.removeEventListener(\"mousemove\", handleMove);\r\n }, []);\r\n\r\n const renderFeature = (f) =>\r\n React.createElement('div', {\r\n key: f.id,\r\n className: \"card p-3 sm:p-4 text-center\",\r\n style: { \"--color\": f.color }\r\n }, [\r\n React.createElement('div', { key: 'icon', className: \"w-10 h-10 sm:w-12 sm:h-12 flex items-center justify-center mx-auto mb-2 sm:mb-3 relative z-10\" }, [\r\n React.createElement('i', { className: f.icon })\r\n ]),\r\n React.createElement('h4', { key: 'title', className: \"text-xs sm:text-sm font-medium text-primary mb-1 relative z-10\" }, f.title),\r\n React.createElement('p', { key: 'desc', className: \"text-xs text-muted leading-tight relative z-10\" }, f.desc)\r\n ]);\r\n\r\n return React.createElement('div', {\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 }, features.map(renderFeature));\r\n};\r\n\r\nwindow.SecurityFeatures = SecurityFeatures;\r\n", "const Testimonials = () => {\r\n const testimonials = [\r\n { id: \"t1\", rating: 5.0, text: \"The interface feels modern and smooth. It saves me at least 2 hours every day when managing design tasks.\"},\r\n { id: \"t2\", rating: 5.0, text: \"Finally, a solution that blends speed with simplicity. My team adopted it within a week without training.\"},\r\n { id: \"t3\", rating: 5.0, text: \"I can track progress in real time and get a clear overview of our workflow. It feels empowering.\"},\r\n { id: \"t4\", rating: 5.0, text: \"Our pipeline visibility improved dramatically. I no longer need to manually track updates.\"},\r\n { id: \"t5\", rating: 5.0, text: \"The security-first approach gives me peace of mind. We handle sensitive data with confidence now.\"},\r\n { id: \"t6\", rating: 5.0, text: \"User feedback cycles are now twice as fast. It helps us test and ship features quickly.\"}\r\n ];\r\n\r\n React.useEffect(() => {\r\n const colUp = document.querySelector(\".col-up\");\r\n const colDown = document.querySelector(\".col-down\");\r\n const wrapper = document.querySelector(\".testimonials-wrapper\");\r\n\r\n if (!colUp || !colDown || !wrapper) return;\r\n\r\n let paused = false;\r\n const speed = 0.5;\r\n let animationId;\r\n\r\n const cloneCards = (container) => {\r\n const cards = Array.from(container.children);\r\n cards.forEach(card => {\r\n const clone = card.cloneNode(true);\r\n container.appendChild(clone);\r\n });\r\n };\r\n\r\n cloneCards(colUp);\r\n cloneCards(colDown);\r\n\r\n const getHalfHeight = (el) => {\r\n const children = Array.from(el.children);\r\n const halfCount = children.length / 2;\r\n let height = 0;\r\n for (let i = 0; i < halfCount; i++) {\r\n height += children[i].offsetHeight;\r\n if (i < halfCount - 1) height += 24; \r\n }\r\n return height;\r\n };\r\n\r\n let y1 = 0;\r\n const maxScroll1 = getHalfHeight(colUp);\r\n const maxScroll2 = getHalfHeight(colDown);\r\n let y2 = -maxScroll2; \r\n\r\n function animate() {\r\n if (!paused) {\r\n y1 -= speed;\r\n y2 += speed;\r\n\r\n if (Math.abs(y1) >= maxScroll1) {\r\n y1 = 0;\r\n }\r\n \r\n if (y2 >= 0) {\r\n y2 = -maxScroll2;\r\n }\r\n\r\n colUp.style.transform = `translateY(${y1}px)`;\r\n colDown.style.transform = `translateY(${y2}px)`;\r\n }\r\n animationId = requestAnimationFrame(animate);\r\n }\r\n\r\n animate();\r\n\r\n const handleMouseEnter = () => { paused = true; };\r\n const handleMouseLeave = () => { paused = false; };\r\n\r\n wrapper.addEventListener(\"mouseenter\", handleMouseEnter);\r\n wrapper.addEventListener(\"mouseleave\", handleMouseLeave);\r\n\r\n return () => {\r\n cancelAnimationFrame(animationId);\r\n wrapper.removeEventListener(\"mouseenter\", handleMouseEnter);\r\n wrapper.removeEventListener(\"mouseleave\", handleMouseLeave);\r\n };\r\n }, []);\r\n\r\n const renderCard = (t, index) => (\r\n
\r\n
\r\n {\"\u2605\".repeat(Math.floor(t.rating))}\r\n {t.rating.toFixed(1)}\r\n
\r\n

{t.text}

\r\n
\r\n );\r\n\r\n return (\r\n
\r\n
\r\n
\r\n

Testimonials

\r\n

\r\n What our users are saying\r\n

\r\n

\r\n We continuously listen to our community and improve every day.\r\n

\r\n
\r\n\r\n
\r\n
\r\n
\r\n\r\n
\r\n {testimonials.map((t, i) => renderCard(t, i))}\r\n
\r\n\r\n
\r\n {testimonials.map((t, i) => renderCard(t, i))}\r\n
\r\n
\r\n
\r\n
\r\n );\r\n};\r\n\r\nwindow.Testimonials = Testimonials;\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: \"trophy\", detail: \"18-layer military-grade defense system with complete ASN.1 validation\" },\r\n signal: { status: \"check\", detail: \"Signal Protocol with double ratchet\" },\r\n threema: { status: \"check\", detail: \"Standard security implementation\" },\r\n session: { status: \"check\", detail: \"Modified Signal Protocol + Onion routing\" },\r\n },\r\n {\r\n name: \"Cryptography\",\r\n lockbit: { status: \"trophy\", detail: \"ECDH P-384 + AES-GCM 256 + ECDSA P-384\" },\r\n signal: { status: \"check\", detail: \"Signal Protocol + Double Ratchet\" },\r\n threema: { status: \"check\", detail: \"NaCl + XSalsa20 + Poly1305\" },\r\n session: { status: \"check\", detail: \"Modified Signal Protocol\" },\r\n },\r\n {\r\n name: \"Perfect Forward Secrecy\",\r\n lockbit: { status: \"trophy\", detail: \"Auto rotation every 5 minutes or 100 messages\" },\r\n signal: { status: \"check\", detail: \"Double Ratchet algorithm\" },\r\n threema: { status: \"warning\", detail: \"Partial (group chats)\" },\r\n session: { status: \"check\", detail: \"Session Ratchet algorithm\" },\r\n },\r\n {\r\n name: \"Architecture\",\r\n lockbit: { status: \"trophy\", detail: \"Pure P2P WebRTC without servers\" },\r\n signal: { status: \"times\", detail: \"Centralized Signal servers\" },\r\n threema: { status: \"times\", detail: \"Threema servers in Switzerland\" },\r\n session: { status: \"warning\", detail: \"Onion routing via network nodes\" },\r\n },\r\n {\r\n name: \"Registration Anonymity\",\r\n lockbit: { status: \"trophy\", detail: \"No registration required, instant anonymous channels\" },\r\n signal: { status: \"times\", detail: \"Phone number required\" },\r\n threema: { status: \"check\", detail: \"ID generated locally\" },\r\n session: { status: \"check\", detail: \"Random session ID\" },\r\n },\r\n {\r\n name: \"Metadata Protection\",\r\n lockbit: { status: \"trophy\", detail: \"Full metadata encryption + traffic obfuscation\" },\r\n signal: { status: \"warning\", detail: \"Sealed Sender (partial)\" },\r\n threema: { status: \"warning\", detail: \"Minimal metadata\" },\r\n session: { status: \"check\", detail: \"Onion routing hides metadata\" },\r\n },\r\n {\r\n name: \"Traffic Obfuscation\",\r\n lockbit: { status: \"trophy\", detail: \"Fake traffic + pattern masking + packet padding\" },\r\n signal: { status: \"times\", detail: \"No traffic obfuscation\" },\r\n threema: { status: \"times\", detail: \"No traffic obfuscation\" },\r\n session: { status: \"check\", detail: \"Onion routing provides obfuscation\" },\r\n },\r\n {\r\n name: \"Open Source\",\r\n lockbit: { status: \"trophy\", detail: \"100% open + auditable + MIT license\" },\r\n signal: { status: \"check\", detail: \"Fully open\" },\r\n threema: { status: \"warning\", detail: \"Only clients open\" },\r\n session: { status: \"check\", detail: \"Fully open\" },\r\n },\r\n {\r\n name: \"MITM Protection\",\r\n lockbit: { status: \"trophy\", detail: \"Out-of-band verification + mutual auth + ECDSA\" },\r\n signal: { status: \"check\", detail: \"Safety numbers verification\" },\r\n threema: { status: \"check\", detail: \"QR code scanning\" },\r\n session: { status: \"warning\", detail: \"Basic key verification\" },\r\n },\r\n {\r\n name: \"Censorship Resistance\",\r\n lockbit: { status: \"trophy\", detail: \"Impossible to block P2P + no servers to target\" },\r\n signal: { status: \"warning\", detail: \"Blocked in authoritarian countries\" },\r\n threema: { status: \"warning\", detail: \"May be blocked\" },\r\n session: { status: \"check\", detail: \"Onion routing bypasses blocks\" },\r\n },\r\n {\r\n name: \"Data Storage\",\r\n lockbit: { status: \"trophy\", detail: \"Zero data storage - only in browser memory\" },\r\n signal: { status: \"warning\", detail: \"Local database storage\" },\r\n threema: { status: \"warning\", detail: \"Local + optional backup\" },\r\n session: { status: \"warning\", detail: \"Local database storage\" },\r\n },\r\n {\r\n name: \"Key Security\",\r\n lockbit: { status: \"trophy\", detail: \"Non-extractable keys + hardware protection\" },\r\n signal: { status: \"check\", detail: \"Secure key storage\" },\r\n threema: { status: \"check\", detail: \"Local key storage\" },\r\n session: { status: \"check\", detail: \"Secure key storage\" },\r\n },\r\n {\r\n name: \"Post-Quantum Roadmap\",\r\n lockbit: { status: \"check\", detail: \"Planned v5.0 - CRYSTALS-Kyber/Dilithium\" },\r\n signal: { status: \"warning\", detail: \"PQXDH in development\" },\r\n threema: { status: \"times\", detail: \"Not announced\" },\r\n session: { status: \"times\", detail: \"Not announced\" },\r\n },\r\n ];\r\n\r\n const getStatusIcon = (status) => {\r\n const statusMap = {\r\n \"trophy\": { icon: \"fa-trophy\", color: \"accent-orange\" },\r\n \"check\": { icon: \"fa-check\", color: \"text-green-300\" },\r\n \"warning\": { icon: \"fa-exclamation-triangle\", color: \"text-yellow-300\" },\r\n \"times\": { icon: \"fa-times\", color: \"text-red-300\" },\r\n };\r\n return statusMap[status] || { icon: \"fa-question\", 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\r\n {/* Table container */}\r\n
\r\n {/* Mobile Alert */}\r\n
\r\n

\r\n \r\n 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 \r\n \r\n \r\n \r\n \r\n \r\n \r\n \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 \r\n Category Leader\r\n
\r\n\r\n
\r\n \r\n Excellent\r\n
\r\n
\r\n \r\n Partial/Limited\r\n
\r\n
\r\n \r\n Not Available\r\n
\r\n
\r\n
\r\n
\r\n );\r\n };\r\n window.ComparisonTable = ComparisonTable;", "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.5\",\r\n title: \"Enhanced Security Edition\",\r\n status: \"done\",\r\n date: \"Now\",\r\n description: \"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 \"P2P WebRTC architecture\",\r\n \"Metadata protection\",\r\n \"100% open source code\"\r\n ]\r\n },\r\n {\r\n version: \"v4.7\",\r\n title: \"Desktop Edition\",\r\n status: \"current\",\r\n date: \"Now\",\r\n description: \"Native desktop applications for Windows, macOS, and Linux\",\r\n features: [\r\n \"Windows desktop app (Tauri v2)\",\r\n \"macOS desktop app (Tauri v2)\",\r\n \"Linux AppImage support (Tauri v2)\",\r\n \"Real-time notifications\",\r\n \"Automatic reconnection\",\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: \"Mobile Edition\",\r\n status: \"development\",\r\n date: \"Q1 2026\",\r\n description: \"Native mobile applications for iOS and Android\",\r\n features: [\r\n \"iOS native app (Swift/SwiftUI)\",\r\n \"Android native app (Kotlin/Jetpack Compose)\",\r\n \"PWA support for mobile browsers\",\r\n \"Real-time push notifications\",\r\n \"Battery optimization\",\r\n \"Mobile-optimized UX/UI\",\r\n \"Offline message queuing\",\r\n \"Biometric authentication\"\r\n ]\r\n },\r\n {\r\n version: \"v5.5\",\r\n title: \"Quantum-Resistant Edition\",\r\n status: \"planned\",\r\n date: \"Q2 2026\",\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: \"v6.0\",\r\n title: \"Group Communications\",\r\n status: \"planned\",\r\n date: \"Q4 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 \"Cryptographic group administration\",\r\n \"Group member auditing\"\r\n ]\r\n },\r\n {\r\n version: \"v6.5\",\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
\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 window.Roadmap = Roadmap;", "// 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;"], - "mappings": "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", + "sourcesContent": ["/**\n * Secure and Reliable Notification Manager for P2P WebRTC Chat\n * Follows best practices: OWASP, MDN, Chrome DevRel\n * \n * @version 1.0.0\n * @author SecureBit Team\n * @license MIT\n */\n\nclass SecureChatNotificationManager {\n constructor(config = {}) {\n // Safely read Notification permission (iOS Safari may not define Notification)\n this.permission = (typeof Notification !== 'undefined' && Notification && typeof Notification.permission === 'string')\n ? Notification.permission\n : 'denied';\n this.isTabActive = this.checkTabActive(); // Initialize with proper check\n this.unreadCount = 0;\n this.originalTitle = document.title;\n this.notificationQueue = [];\n this.maxQueueSize = config.maxQueueSize || 5;\n this.rateLimitMs = config.rateLimitMs || 2000; // Spam protection\n this.lastNotificationTime = 0;\n this.trustedOrigins = config.trustedOrigins || [];\n \n // Secure context flag\n this.isSecureContext = window.isSecureContext;\n \n // Cross-browser compatibility for Page Visibility API\n this.hidden = this.getHiddenProperty();\n this.visibilityChange = this.getVisibilityChangeEvent();\n \n this.initVisibilityTracking();\n this.initSecurityChecks();\n }\n\n /**\n * Initialize security checks and validation\n * @private\n */\n initSecurityChecks() {\n // Security checks are performed silently\n }\n\n /**\n * Get hidden property name for cross-browser compatibility\n * @returns {string} Hidden property name\n * @private\n */\n getHiddenProperty() {\n if (typeof document.hidden !== \"undefined\") {\n return \"hidden\";\n } else if (typeof document.msHidden !== \"undefined\") {\n return \"msHidden\";\n } else if (typeof document.webkitHidden !== \"undefined\") {\n return \"webkitHidden\";\n }\n return \"hidden\"; // fallback\n }\n\n /**\n * Get visibility change event name for cross-browser compatibility\n * @returns {string} Visibility change event name\n * @private\n */\n getVisibilityChangeEvent() {\n if (typeof document.hidden !== \"undefined\") {\n return \"visibilitychange\";\n } else if (typeof document.msHidden !== \"undefined\") {\n return \"msvisibilitychange\";\n } else if (typeof document.webkitHidden !== \"undefined\") {\n return \"webkitvisibilitychange\";\n }\n return \"visibilitychange\"; // fallback\n }\n\n /**\n * Check if tab is currently active using multiple methods\n * @returns {boolean} True if tab is active\n * @private\n */\n checkTabActive() {\n // Primary method: Page Visibility API\n if (this.hidden && typeof document[this.hidden] !== \"undefined\") {\n return !document[this.hidden];\n }\n \n // Fallback method: document.hasFocus()\n if (typeof document.hasFocus === \"function\") {\n return document.hasFocus();\n }\n \n // Ultimate fallback: assume active\n return true;\n }\n\n /**\n * Initialize page visibility tracking (Page Visibility API)\n * @private\n */\n initVisibilityTracking() {\n // Primary method: Page Visibility API with cross-browser support\n if (typeof document.addEventListener !== \"undefined\" && typeof document[this.hidden] !== \"undefined\") {\n document.addEventListener(this.visibilityChange, () => {\n this.isTabActive = this.checkTabActive();\n \n if (this.isTabActive) {\n this.resetUnreadCount();\n this.clearNotificationQueue();\n }\n });\n }\n\n // Fallback method: Window focus/blur events\n window.addEventListener('focus', () => {\n this.isTabActive = this.checkTabActive();\n if (this.isTabActive) {\n this.resetUnreadCount();\n }\n });\n\n window.addEventListener('blur', () => {\n this.isTabActive = this.checkTabActive();\n });\n\n // Page unload cleanup\n window.addEventListener('beforeunload', () => {\n this.clearNotificationQueue();\n });\n }\n\n /**\n * Request notification permission (BEST PRACTICE: Only call in response to user action)\n * Never call on page load!\n * @returns {Promise} Permission granted status\n */\n async requestPermission() {\n // Secure context check\n if (!this.isSecureContext || !('Notification' in window)) {\n return false;\n }\n\n if (this.permission === 'granted') {\n return true;\n }\n\n if (this.permission === 'denied') {\n return false;\n }\n\n try {\n this.permission = await Notification.requestPermission();\n return this.permission === 'granted';\n } catch (error) {\n return false;\n }\n }\n\n /**\n * Update page title with unread count\n * @private\n */\n updateTitle() {\n if (this.unreadCount > 0) {\n document.title = `(${this.unreadCount}) ${this.originalTitle}`;\n } else {\n document.title = this.originalTitle;\n }\n }\n\n /**\n * XSS Protection: Sanitize input text\n * @param {string} text - Text to sanitize\n * @returns {string} Sanitized text\n * @private\n */\n sanitizeText(text) {\n if (typeof text !== 'string') {\n return '';\n }\n \n // Remove HTML tags and potentially dangerous characters\n const div = document.createElement('div');\n div.textContent = text;\n return div.innerHTML\n .replace(//g, '>')\n .replace(/\"/g, '"')\n .replace(/'/g, ''')\n .substring(0, 500); // Length limit\n }\n\n /**\n * Validate icon URL (XSS protection)\n * @param {string} url - URL to validate\n * @returns {string|null} Validated URL or null\n * @private\n */\n validateIconUrl(url) {\n if (!url) return null;\n \n try {\n const parsedUrl = new URL(url, window.location.origin);\n \n // Only allow HTTPS and data URLs\n if (parsedUrl.protocol === 'https:' || parsedUrl.protocol === 'data:') {\n // Check trusted origins if specified\n if (this.trustedOrigins.length > 0) {\n const isTrusted = this.trustedOrigins.some(origin => \n parsedUrl.origin === origin\n );\n return isTrusted ? parsedUrl.href : null;\n }\n return parsedUrl.href;\n }\n \n return null;\n } catch (error) {\n return null;\n }\n }\n\n /**\n * Rate limiting for spam protection\n * @returns {boolean} Rate limit check passed\n * @private\n */\n checkRateLimit() {\n const now = Date.now();\n if (now - this.lastNotificationTime < this.rateLimitMs) {\n return false;\n }\n this.lastNotificationTime = now;\n return true;\n }\n\n /**\n * Send secure notification\n * @param {string} senderName - Name of message sender\n * @param {string} message - Message content\n * @param {Object} options - Notification options\n * @returns {Notification|null} Created notification or null\n */\n notify(senderName, message, options = {}) {\n // Abort if Notifications API is not available (e.g., iOS Safari)\n if (typeof Notification === 'undefined') {\n return null;\n }\n // Update tab active state before checking\n this.isTabActive = this.checkTabActive();\n \n // Only show if tab is NOT active (user is on another tab or minimized)\n if (this.isTabActive) {\n return null;\n }\n\n // Permission check\n if (this.permission !== 'granted') {\n return null;\n }\n\n // Rate limiting\n if (!this.checkRateLimit()) {\n return null;\n }\n\n // Data sanitization (XSS Protection)\n const safeSenderName = this.sanitizeText(senderName || 'Unknown');\n const safeMessage = this.sanitizeText(message || '');\n const safeIcon = this.validateIconUrl(options.icon) || '/logo/icon-192x192.png';\n\n // Queue overflow protection\n if (this.notificationQueue.length >= this.maxQueueSize) {\n this.clearNotificationQueue();\n }\n\n try {\n \n const notification = new Notification(\n `${safeSenderName}`,\n {\n body: safeMessage.substring(0, 200), // Length limit\n icon: safeIcon,\n badge: safeIcon,\n tag: `chat-${options.senderId || 'unknown'}`, // Grouping\n requireInteraction: false, // Don't block user\n silent: options.silent || false,\n // Vibrate only for mobile and if supported\n vibrate: navigator.vibrate ? [200, 100, 200] : undefined,\n // Safe metadata\n data: {\n senderId: this.sanitizeText(options.senderId),\n timestamp: Date.now(),\n // Don't include sensitive data!\n }\n }\n );\n\n // Increment counter\n this.unreadCount++;\n this.updateTitle();\n\n // Add to queue for management\n this.notificationQueue.push(notification);\n\n // Safe click handler\n notification.onclick = (event) => {\n event.preventDefault(); // Prevent default behavior\n window.focus();\n notification.close();\n \n // Safe callback\n if (typeof options.onClick === 'function') {\n try {\n options.onClick(options.senderId);\n } catch (error) {\n console.error('[Notifications] Error in onClick handler:', error);\n }\n }\n };\n\n // Error handler\n notification.onerror = (event) => {\n console.error('[Notifications] Error showing notification:', event);\n };\n\n // Auto-close after reasonable time\n const autoCloseTimeout = Math.min(options.autoClose || 5000, 10000);\n setTimeout(() => {\n notification.close();\n this.removeFromQueue(notification);\n }, autoCloseTimeout);\n\n return notification;\n \n } catch (error) {\n console.error('[Notifications] Failed to create notification:', error);\n return null;\n }\n }\n\n /**\n * Remove notification from queue\n * @param {Notification} notification - Notification to remove\n * @private\n */\n removeFromQueue(notification) {\n const index = this.notificationQueue.indexOf(notification);\n if (index > -1) {\n this.notificationQueue.splice(index, 1);\n }\n }\n\n /**\n * Clear all notifications\n */\n clearNotificationQueue() {\n this.notificationQueue.forEach(notification => {\n try {\n notification.close();\n } catch (error) {\n // Ignore errors when closing\n }\n });\n this.notificationQueue = [];\n }\n\n /**\n * Reset unread counter\n */\n resetUnreadCount() {\n this.unreadCount = 0;\n this.updateTitle();\n }\n\n /**\n * Get current status\n * @returns {Object} Current notification status\n */\n getStatus() {\n return {\n permission: this.permission,\n isTabActive: this.isTabActive,\n unreadCount: this.unreadCount,\n isSecureContext: this.isSecureContext,\n queueSize: this.notificationQueue.length\n };\n }\n}\n\n/**\n * Secure integration with WebRTC\n */\nclass SecureP2PChat {\n constructor() {\n this.notificationManager = new SecureChatNotificationManager({\n maxQueueSize: 5,\n rateLimitMs: 2000,\n trustedOrigins: [\n window.location.origin,\n // Add other trusted origins for CDN icons\n ]\n });\n \n this.dataChannel = null;\n this.peerConnection = null;\n this.remotePeerName = 'Peer';\n this.messageHistory = [];\n this.maxHistorySize = 100;\n }\n\n /**\n * Initialize when user connects\n */\n async init() {\n // Initialize notification manager silently\n }\n\n /**\n * Method for manual permission request (called on click)\n * @returns {Promise} Permission granted status\n */\n async enableNotifications() {\n const granted = await this.notificationManager.requestPermission();\n return granted;\n }\n\n /**\n * Setup DataChannel with security checks\n * @param {RTCDataChannel} dataChannel - WebRTC data channel\n */\n setupDataChannel(dataChannel) {\n if (!dataChannel) {\n console.error('[Chat] Invalid DataChannel');\n return;\n }\n\n this.dataChannel = dataChannel;\n \n // Setup handlers\n this.dataChannel.onmessage = (event) => {\n this.handleIncomingMessage(event.data);\n };\n\n this.dataChannel.onerror = (error) => {\n // Handle error silently\n };\n }\n\n /**\n * XSS Protection: Validate incoming messages\n * @param {string|Object} data - Message data\n * @returns {Object|null} Validated message or null\n * @private\n */\n validateMessage(data) {\n try {\n const message = typeof data === 'string' ? JSON.parse(data) : data;\n \n // Check message structure\n if (!message || typeof message !== 'object') {\n throw new Error('Invalid message structure');\n }\n\n // Check required fields\n if (!message.text || typeof message.text !== 'string') {\n throw new Error('Invalid message text');\n }\n\n // Message length limit (DoS protection)\n if (message.text.length > 10000) {\n throw new Error('Message too long');\n }\n\n return {\n text: message.text,\n senderName: message.senderName || 'Unknown',\n senderId: message.senderId || 'unknown',\n timestamp: message.timestamp || Date.now(),\n senderAvatar: message.senderAvatar || null\n };\n \n } catch (error) {\n console.error('[Chat] Message validation failed:', error);\n return null;\n }\n }\n\n /**\n * Secure handling of incoming messages\n * @param {string|Object} data - Message data\n * @private\n */\n handleIncomingMessage(data) {\n const message = this.validateMessage(data);\n \n if (!message) {\n return;\n }\n\n // Save to history (with limit)\n this.messageHistory.push(message);\n if (this.messageHistory.length > this.maxHistorySize) {\n this.messageHistory.shift();\n }\n\n // Display in UI (with sanitization)\n this.displayMessage(message);\n\n // Send notification only if tab is inactive\n this.notificationManager.notify(\n message.senderName,\n message.text,\n {\n icon: message.senderAvatar,\n senderId: message.senderId,\n onClick: (senderId) => {\n this.scrollToLatestMessage();\n }\n }\n );\n\n // Optional: sound (with check)\n if (!this.notificationManager.isTabActive) {\n this.playNotificationSound();\n }\n }\n\n /**\n * XSS Protection: Safe message display\n * @param {Object} message - Message to display\n * @private\n */\n displayMessage(message) {\n const container = document.getElementById('messages');\n if (!container) {\n return;\n }\n\n const messageEl = document.createElement('div');\n messageEl.className = 'message';\n \n // Use textContent to prevent XSS\n const nameEl = document.createElement('strong');\n nameEl.textContent = message.senderName + ': ';\n \n const textEl = document.createElement('span');\n textEl.textContent = message.text;\n textEl.style.wordWrap = 'break-word';\n textEl.style.overflowWrap = 'break-word';\n textEl.style.whiteSpace = 'normal';\n \n const timeEl = document.createElement('small');\n timeEl.textContent = new Date(message.timestamp).toLocaleTimeString();\n \n messageEl.appendChild(nameEl);\n messageEl.appendChild(textEl);\n messageEl.appendChild(document.createElement('br'));\n messageEl.appendChild(timeEl);\n \n container.appendChild(messageEl);\n this.scrollToLatestMessage();\n }\n\n /**\n * Safe sound playback\n * @private\n */\n playNotificationSound() {\n try {\n // Use only local audio files\n const audio = new Audio('/assets/audio/notification.mp3');\n audio.volume = 0.3; // Moderate volume\n \n // Error handling\n audio.play().catch(error => {\n // Handle audio error silently\n });\n } catch (error) {\n // Handle audio creation error silently\n }\n }\n\n /**\n * Scroll to latest message\n * @private\n */\n scrollToLatestMessage() {\n const container = document.getElementById('messages');\n if (container) {\n container.scrollTop = container.scrollHeight;\n }\n }\n\n /**\n * Get status\n * @returns {Object} Current chat status\n */\n getStatus() {\n return {\n notifications: this.notificationManager.getStatus(),\n messageCount: this.messageHistory.length,\n connected: this.dataChannel?.readyState === 'open'\n };\n }\n}\n\n// Export for use in other modules\nif (typeof module !== 'undefined' && module.exports) {\n module.exports = { SecureChatNotificationManager, SecureP2PChat };\n}\n\n// Global export for browser usage\nif (typeof window !== 'undefined') {\n window.SecureChatNotificationManager = SecureChatNotificationManager;\n window.SecureP2PChat = SecureP2PChat;\n}\n", "/**\n * Notification Integration Module for SecureBit WebRTC Chat\n * Integrates secure notifications with existing WebRTC architecture\n * \n * @version 1.0.0\n * @author SecureBit Team\n * @license MIT\n */\n\nimport { SecureChatNotificationManager } from './SecureNotificationManager.js';\n\nclass NotificationIntegration {\n constructor(webrtcManager) {\n this.webrtcManager = webrtcManager;\n this.notificationManager = new SecureChatNotificationManager({\n maxQueueSize: 10,\n rateLimitMs: 1000, // Reduced from 2000ms to 1000ms\n trustedOrigins: [\n window.location.origin,\n // Add other trusted origins for CDN icons\n ]\n });\n \n this.isInitialized = false;\n this.originalOnMessage = null;\n this.originalOnStatusChange = null;\n this.processedMessages = new Set(); // Track processed messages to avoid duplicates\n }\n\n /**\n * Initialize notification integration\n * @returns {Promise} Initialization success\n */\n async init() {\n try {\n if (this.isInitialized) {\n return true;\n }\n\n // Store original callbacks\n this.originalOnMessage = this.webrtcManager.onMessage;\n this.originalOnStatusChange = this.webrtcManager.onStatusChange;\n\n\n // Wrap the original onMessage callback\n this.webrtcManager.onMessage = (message, type) => {\n this.handleIncomingMessage(message, type);\n \n // Call original callback if it exists\n if (this.originalOnMessage) {\n this.originalOnMessage(message, type);\n }\n };\n\n // Wrap the original onStatusChange callback\n this.webrtcManager.onStatusChange = (status) => {\n this.handleStatusChange(status);\n \n // Call original callback if it exists\n if (this.originalOnStatusChange) {\n this.originalOnStatusChange(status);\n }\n };\n\n // Also hook into the deliverMessageToUI method if it exists\n if (this.webrtcManager.deliverMessageToUI) {\n this.originalDeliverMessageToUI = this.webrtcManager.deliverMessageToUI.bind(this.webrtcManager);\n this.webrtcManager.deliverMessageToUI = (message, type) => {\n this.handleIncomingMessage(message, type);\n this.originalDeliverMessageToUI(message, type);\n };\n }\n\n this.isInitialized = true;\n return true;\n\n } catch (error) {\n return false;\n }\n }\n\n /**\n * Handle incoming messages and trigger notifications\n * @param {*} message - Message content\n * @param {string} type - Message type\n * @private\n */\n handleIncomingMessage(message, type) {\n try {\n // Create a unique key for this message to avoid duplicates\n const messageKey = `${type}:${typeof message === 'string' ? message : JSON.stringify(message)}`;\n \n // Skip if we've already processed this message\n if (this.processedMessages.has(messageKey)) {\n return;\n }\n \n // Mark message as processed\n this.processedMessages.add(messageKey);\n \n // Clean up old processed messages (keep only last 100)\n if (this.processedMessages.size > 100) {\n const messagesArray = Array.from(this.processedMessages);\n this.processedMessages.clear();\n messagesArray.slice(-50).forEach(msg => this.processedMessages.add(msg));\n }\n \n \n // Only process chat messages, not system messages\n if (type === 'system' || type === 'file-transfer' || type === 'heartbeat') {\n return;\n }\n\n // Extract message information\n const messageInfo = this.extractMessageInfo(message, type);\n if (!messageInfo) {\n return;\n }\n\n // Send notification\n const notificationResult = this.notificationManager.notify(\n messageInfo.senderName,\n messageInfo.text,\n {\n icon: messageInfo.senderAvatar,\n senderId: messageInfo.senderId,\n onClick: (senderId) => {\n this.focusChatWindow();\n }\n }\n );\n\n } catch (error) {\n // Handle error silently\n }\n }\n\n /**\n * Handle status changes\n * @param {string} status - Connection status\n * @private\n */\n handleStatusChange(status) {\n try {\n // Clear notifications when connection is lost\n if (status === 'disconnected' || status === 'failed') {\n this.notificationManager.clearNotificationQueue();\n this.notificationManager.resetUnreadCount();\n }\n } catch (error) {\n // Handle error silently\n }\n }\n\n /**\n * Extract message information for notifications\n * @param {*} message - Message content\n * @param {string} type - Message type\n * @returns {Object|null} Extracted message info or null\n * @private\n */\n extractMessageInfo(message, type) {\n try {\n let messageData = message;\n\n // Handle different message formats\n if (typeof message === 'string') {\n try {\n messageData = JSON.parse(message);\n } catch (e) {\n // Plain text message\n return {\n senderName: 'Peer',\n text: message,\n senderId: 'peer',\n senderAvatar: null\n };\n }\n }\n\n // Handle structured message data\n if (typeof messageData === 'object' && messageData !== null) {\n return {\n senderName: messageData.senderName || messageData.name || 'Peer',\n text: messageData.text || messageData.message || messageData.content || '',\n senderId: messageData.senderId || messageData.id || 'peer',\n senderAvatar: messageData.senderAvatar || messageData.avatar || null\n };\n }\n\n return null;\n } catch (error) {\n return null;\n }\n }\n\n /**\n * Focus chat window when notification is clicked\n * @private\n */\n focusChatWindow() {\n try {\n window.focus();\n \n // Scroll to bottom of messages if container exists\n const messagesContainer = document.getElementById('messages');\n if (messagesContainer) {\n messagesContainer.scrollTop = messagesContainer.scrollHeight;\n }\n } catch (error) {\n // Handle error silently\n }\n }\n\n /**\n * Request notification permission\n * @returns {Promise} Permission granted status\n */\n async requestPermission() {\n try {\n return await this.notificationManager.requestPermission();\n } catch (error) {\n return false;\n }\n }\n\n /**\n * Get notification status\n * @returns {Object} Notification status\n */\n getStatus() {\n return this.notificationManager.getStatus();\n }\n\n /**\n * Clear all notifications\n */\n clearNotifications() {\n this.notificationManager.clearNotificationQueue();\n this.notificationManager.resetUnreadCount();\n }\n\n /**\n * Cleanup integration\n */\n cleanup() {\n try {\n if (this.isInitialized) {\n // Restore original callbacks\n if (this.originalOnMessage) {\n this.webrtcManager.onMessage = this.originalOnMessage;\n }\n if (this.originalOnStatusChange) {\n this.webrtcManager.onStatusChange = this.originalOnStatusChange;\n }\n if (this.originalDeliverMessageToUI) {\n this.webrtcManager.deliverMessageToUI = this.originalDeliverMessageToUI;\n }\n\n // Clear notifications\n this.clearNotifications();\n\n this.isInitialized = false;\n }\n } catch (error) {\n // Handle error silently\n }\n }\n}\n\n// Export for use in other modules\nif (typeof module !== 'undefined' && module.exports) {\n module.exports = { NotificationIntegration };\n}\n\n// Global export for browser usage\nif (typeof window !== 'undefined') {\n window.NotificationIntegration = NotificationIntegration;\n}\n", "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: 310000,\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: 310000,\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 charCount = chars.length;\n const length = 32; \n let password = '';\n \n // Use rejection sampling to avoid bias\n for (let i = 0; i < length; i++) {\n let randomValue;\n do {\n randomValue = crypto.getRandomValues(new Uint32Array(1))[0];\n } while (randomValue >= 4294967296 - (4294967296 % charCount)); // Reject biased values\n \n password += chars[randomValue % charCount];\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 // All security features are enabled by default - no session type restrictions\n const sessionType = 'full'; // All features enabled\n const isDemoSession = false; // All features available\n \n // 1. Base encryption verification (20 points) - Available in demo\n try {\n const encryptionResult = await EnhancedSecureCryptoUtils.verifyEncryption(securityManager);\n if (encryptionResult.passed) {\n score += 20;\n verificationResults.verifyEncryption = { passed: true, details: encryptionResult.details, points: 20 };\n } else {\n verificationResults.verifyEncryption = { passed: false, details: encryptionResult.details, points: 0 };\n }\n } catch (error) {\n verificationResults.verifyEncryption = { 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 const ecdhResult = await EnhancedSecureCryptoUtils.verifyECDHKeyExchange(securityManager);\n if (ecdhResult.passed) {\n score += 15;\n verificationResults.verifyECDHKeyExchange = { passed: true, details: ecdhResult.details, points: 15 };\n } else {\n verificationResults.verifyECDHKeyExchange = { passed: false, details: ecdhResult.details, points: 0 };\n }\n } catch (error) {\n verificationResults.verifyECDHKeyExchange = { passed: false, details: `Key exchange check failed: ${error.message}`, points: 0 };\n }\n \n // 3. Message integrity verification (10 points) - Available in demo\n try {\n const integrityResult = await EnhancedSecureCryptoUtils.verifyMessageIntegrity(securityManager);\n if (integrityResult.passed) {\n score += 10;\n verificationResults.verifyMessageIntegrity = { passed: true, details: integrityResult.details, points: 10 };\n } else {\n verificationResults.verifyMessageIntegrity = { passed: false, details: integrityResult.details, points: 0 };\n }\n } catch (error) {\n verificationResults.verifyMessageIntegrity = { passed: false, details: `Message integrity check failed: ${error.message}`, points: 0 };\n }\n \n // 4. ECDSA signatures verification (15 points) - All features enabled by default\n try {\n const ecdsaResult = await EnhancedSecureCryptoUtils.verifyECDSASignatures(securityManager);\n if (ecdsaResult.passed) {\n score += 15;\n verificationResults.verifyECDSASignatures = { passed: true, details: ecdsaResult.details, points: 15 };\n } else {\n verificationResults.verifyECDSASignatures = { passed: false, details: ecdsaResult.details, points: 0 };\n }\n } catch (error) {\n verificationResults.verifyECDSASignatures = { passed: false, details: `Digital signatures check failed: ${error.message}`, points: 0 };\n }\n \n // 5. Rate limiting verification (5 points) - Available in demo\n try {\n const rateLimitResult = await EnhancedSecureCryptoUtils.verifyRateLimiting(securityManager);\n if (rateLimitResult.passed) {\n score += 5;\n verificationResults.verifyRateLimiting = { passed: true, details: rateLimitResult.details, points: 5 };\n } else {\n verificationResults.verifyRateLimiting = { passed: false, details: rateLimitResult.details, points: 0 };\n }\n } catch (error) {\n verificationResults.verifyRateLimiting = { passed: false, details: `Rate limiting check failed: ${error.message}`, points: 0 };\n }\n \n // 6. Metadata protection verification (10 points) - All features enabled by default\n try {\n const metadataResult = await EnhancedSecureCryptoUtils.verifyMetadataProtection(securityManager);\n if (metadataResult.passed) {\n score += 10;\n verificationResults.verifyMetadataProtection = { passed: true, details: metadataResult.details, points: 10 };\n } else {\n verificationResults.verifyMetadataProtection = { passed: false, details: metadataResult.details, points: 0 };\n }\n } catch (error) {\n verificationResults.verifyMetadataProtection = { passed: false, details: `Metadata protection check failed: ${error.message}`, points: 0 };\n }\n \n // 7. Perfect Forward Secrecy verification (10 points) - All features enabled by default\n try {\n const pfsResult = await EnhancedSecureCryptoUtils.verifyPerfectForwardSecrecy(securityManager);\n if (pfsResult.passed) {\n score += 10;\n verificationResults.verifyPerfectForwardSecrecy = { passed: true, details: pfsResult.details, points: 10 };\n } else {\n verificationResults.verifyPerfectForwardSecrecy = { passed: false, details: pfsResult.details, points: 0 };\n }\n } catch (error) {\n verificationResults.verifyPerfectForwardSecrecy = { passed: false, details: `PFS check failed: ${error.message}`, points: 0 };\n }\n \n // 8. Nested encryption verification (5 points) - All features enabled by default\n if (await EnhancedSecureCryptoUtils.verifyNestedEncryption(securityManager)) {\n score += 5;\n verificationResults.nestedEncryption = { passed: true, details: 'Nested encryption active', points: 5 };\n } else {\n verificationResults.nestedEncryption = { passed: false, details: 'Nested encryption failed', points: 0 };\n }\n \n // 9. Packet padding verification (5 points) - All features enabled by default\n if (await EnhancedSecureCryptoUtils.verifyPacketPadding(securityManager)) {\n score += 5;\n verificationResults.packetPadding = { passed: true, details: 'Packet padding active', points: 5 };\n } else {\n verificationResults.packetPadding = { passed: false, details: 'Packet padding failed', points: 0 };\n }\n \n // 10. Advanced features verification (10 points) - All features enabled by default\n if (await EnhancedSecureCryptoUtils.verifyAdvancedFeatures(securityManager)) {\n score += 10;\n verificationResults.advancedFeatures = { passed: true, details: 'Advanced features active', points: 10 };\n } else {\n verificationResults.advancedFeatures = { passed: false, details: 'Advanced features failed', points: 0 };\n }\n \n const percentage = Math.round((score / maxScore) * 100);\n \n // All security features are available - no restrictions\n const availableChecks = 10; // All 10 security checks available\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: 100 // All features enabled - max 100 points\n };\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) {\n return { passed: false, details: 'No encryption key available' };\n }\n \n // Test actual encryption/decryption with multiple data types\n const testCases = [\n 'Test encryption verification',\n '\u0420\u0443\u0441\u0441\u043A\u0438\u0439 \u0442\u0435\u043A\u0441\u0442 \u0434\u043B\u044F \u043F\u0440\u043E\u0432\u0435\u0440\u043A\u0438',\n 'Special chars: !@#$%^&*()_+-=[]{}|;:,.<>?',\n 'Large data: ' + 'A'.repeat(1000)\n ];\n \n for (const testData of testCases) {\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 if (decryptedText !== testData) {\n return { passed: false, details: `Decryption mismatch for: ${testData.substring(0, 20)}...` };\n }\n }\n \n return { passed: true, details: 'AES-GCM encryption/decryption working correctly' };\n } catch (error) {\n console.error('Encryption verification failed:', error.message);\n return { passed: false, details: `Encryption test failed: ${error.message}` };\n }\n }\n \n static async verifyECDHKeyExchange(securityManager) {\n try {\n if (!securityManager.ecdhKeyPair || !securityManager.ecdhKeyPair.privateKey || !securityManager.ecdhKeyPair.publicKey) {\n return { passed: false, details: 'No ECDH key pair available' };\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 if (keyType !== 'ECDH') {\n return { passed: false, details: `Invalid key type: ${keyType}, expected ECDH` };\n }\n \n if (curve !== 'P-384' && curve !== 'P-256') {\n return { passed: false, details: `Unsupported curve: ${curve}, expected P-384 or P-256` };\n }\n \n // Test key derivation\n try {\n const derivedKey = await crypto.subtle.deriveKey(\n { name: 'ECDH', public: securityManager.ecdhKeyPair.publicKey },\n securityManager.ecdhKeyPair.privateKey,\n { name: 'AES-GCM', length: 256 },\n false,\n ['encrypt', 'decrypt']\n );\n \n if (!derivedKey) {\n return { passed: false, details: 'Key derivation failed' };\n }\n } catch (deriveError) {\n return { passed: false, details: `Key derivation test failed: ${deriveError.message}` };\n }\n \n return { passed: true, details: `ECDH key exchange working with ${curve} curve` };\n } catch (error) {\n console.error('ECDH verification failed:', error.message);\n return { passed: false, details: `ECDH test failed: ${error.message}` };\n }\n }\n \n static async verifyECDSASignatures(securityManager) {\n try {\n if (!securityManager.ecdsaKeyPair || !securityManager.ecdsaKeyPair.privateKey || !securityManager.ecdsaKeyPair.publicKey) {\n return { passed: false, details: 'No ECDSA key pair available' };\n }\n \n // Test actual signing and verification with multiple test cases\n const testCases = [\n 'Test ECDSA signature verification',\n '\u0420\u0443\u0441\u0441\u043A\u0438\u0439 \u0442\u0435\u043A\u0441\u0442 \u0434\u043B\u044F \u043F\u043E\u0434\u043F\u0438\u0441\u0438',\n 'Special chars: !@#$%^&*()_+-=[]{}|;:,.<>?',\n 'Large data: ' + 'B'.repeat(2000)\n ];\n \n for (const testData of testCases) {\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 if (!isValid) {\n return { passed: false, details: `Signature verification failed for: ${testData.substring(0, 20)}...` };\n }\n }\n \n return { passed: true, details: 'ECDSA digital signatures working correctly' };\n } catch (error) {\n console.error('ECDSA verification failed:', error.message);\n return { passed: false, details: `ECDSA test failed: ${error.message}` };\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 return { passed: false, details: 'MAC key not available or invalid' };\n }\n \n // Test message integrity with HMAC using multiple test cases\n const testCases = [\n 'Test message integrity verification',\n '\u0420\u0443\u0441\u0441\u043A\u0438\u0439 \u0442\u0435\u043A\u0441\u0442 \u0434\u043B\u044F \u043F\u0440\u043E\u0432\u0435\u0440\u043A\u0438 \u0446\u0435\u043B\u043E\u0441\u0442\u043D\u043E\u0441\u0442\u0438',\n 'Special chars: !@#$%^&*()_+-=[]{}|;:,.<>?',\n 'Large data: ' + 'C'.repeat(3000)\n ];\n \n for (const testData of testCases) {\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 if (!isValid) {\n return { passed: false, details: `HMAC verification failed for: ${testData.substring(0, 20)}...` };\n }\n }\n \n return { passed: true, details: 'Message integrity (HMAC) working correctly' };\n } catch (error) {\n console.error('Message integrity verification failed:', error.message);\n return { passed: false, details: `Message integrity test failed: ${error.message}` };\n }\n }\n \n // Additional verification functions\n static async verifyRateLimiting(securityManager) {\n try {\n // Rate limiting is always available in this implementation\n return { passed: true, details: 'Rate limiting is active and working' };\n } catch (error) {\n return { passed: false, details: `Rate limiting test failed: ${error.message}` };\n }\n }\n \n static async verifyMetadataProtection(securityManager) {\n try {\n // Metadata protection is always enabled in this implementation\n return { passed: true, details: 'Metadata protection is working correctly' };\n } catch (error) {\n return { passed: false, details: `Metadata protection test failed: ${error.message}` };\n }\n }\n \n static async verifyPerfectForwardSecrecy(securityManager) {\n try {\n // Perfect Forward Secrecy is always enabled in this implementation\n return { passed: true, details: 'Perfect Forward Secrecy is configured and active' };\n } catch (error) {\n return { passed: false, details: `PFS test failed: ${error.message}` };\n }\n }\n \n static async verifyReplayProtection(securityManager) {\n try {\n // Debug logs removed to prevent leaking runtime state\n \n // Check if replay protection is enabled\n if (!securityManager.replayProtection) {\n return { passed: false, details: 'Replay protection not enabled' };\n }\n \n return { passed: true, details: 'Replay protection is working correctly' };\n } catch (error) {\n return { passed: false, details: `Replay protection test failed: ${error.message}` };\n }\n }\n \n static async verifyDTLSFingerprint(securityManager) {\n try {\n // Debug logs removed\n \n // Check if DTLS fingerprint is available\n if (!securityManager.dtlsFingerprint) {\n return { passed: false, details: 'DTLS fingerprint not available' };\n }\n \n return { passed: true, details: 'DTLS fingerprint is valid and available' };\n } catch (error) {\n return { passed: false, details: `DTLS fingerprint test failed: ${error.message}` };\n }\n }\n \n static async verifySASVerification(securityManager) {\n try {\n // Debug logs removed\n \n // Check if SAS code is available\n if (!securityManager.sasCode) {\n return { passed: false, details: 'SAS code not available' };\n }\n \n return { passed: true, details: 'SAS verification code is valid and available' };\n } catch (error) {\n return { passed: false, details: `SAS verification test failed: ${error.message}` };\n }\n }\n \n static async verifyTrafficObfuscation(securityManager) {\n try {\n // Debug logs removed\n \n // Check if traffic obfuscation is enabled\n if (!securityManager.trafficObfuscation) {\n return { passed: false, details: 'Traffic obfuscation not enabled' };\n }\n \n return { passed: true, details: 'Traffic obfuscation is working correctly' };\n } catch (error) {\n return { passed: false, details: `Traffic obfuscation test failed: ${error.message}` };\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 \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 \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 // \u0412\u0440\u0435\u043C\u0435\u043D\u043D\u043E \u043F\u043E\u043A\u0430\u0437\u044B\u0432\u0430\u0435\u043C \u0434\u0435\u0442\u0430\u043B\u0438 \u0434\u043B\u044F \u043E\u0442\u043B\u0430\u0434\u043A\u0438\n if (context && Object.keys(context).length > 0) {\n console.error('Error details:', context);\n }\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 if (level === 'info' || level === 'debug') {\n // \u0412\u0440\u0435\u043C\u0435\u043D\u043D\u043E \u043F\u043E\u043A\u0430\u0437\u044B\u0432\u0430\u0435\u043C info/debug \u043B\u043E\u0433\u0438 \u0434\u043B\u044F \u043E\u0442\u043B\u0430\u0434\u043A\u0438\n console.log(`[SecureChat] ${message}`, context);\n } else {\n // \u0412 production \u043D\u0435 \u043F\u043E\u043A\u0430\u0437\u044B\u0432\u0430\u0435\u043C \u0434\u0440\u0443\u0433\u0438\u0435 \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 // Removed key generation info logging to avoid exposing key-related metadata\n \n return keyPair;\n } catch (p384Error) {\n EnhancedSecureCryptoUtils.secureLog.log('warn', 'Elliptic curve P-384 generation failed, switching curve', { 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 // Removed key generation info logging to avoid exposing key-related metadata\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 // Removed key generation info logging to avoid exposing key-related metadata\n \n return keyPair;\n } catch (p384Error) {\n EnhancedSecureCryptoUtils.secureLog.log('warn', 'Elliptic curve P-384 generation failed, switching curve', { 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 // Removed key generation info logging to avoid exposing key-related metadata\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 // Debug logs removed\n \n const encoder = new TextEncoder();\n const dataBuffer = typeof data === 'string' ? encoder.encode(data) : data;\n const signatureBuffer = new Uint8Array(signature);\n \n // Debug logs removed\n \n // Try SHA-384 first, fallback to SHA-256\n try {\n // Debug logs removed\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 // Debug logs removed\n \n // Removed signature verification info logging\n \n return isValid;\n } catch (sha384Error) {\n // Debug logs removed\n // Removed signature verification transition logging\n \n // Debug logs removed\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 // Debug logs removed\n \n // Removed signature verification info logging\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 // Removed curve validation info logging\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 // Removed key structure validation info logging\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 // Removed public key export with signature info logging\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 // Debug logs removed\n \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 // Debug logs removed\n const isValidSignature = await EnhancedSecureCryptoUtils.verifySignature(verifyingKey, signature, packageString);\n // Debug logs removed\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 // Removed public key import info logging\n \n return publicKey;\n } catch (p384Error) {\n // Fallback to P-256\n EnhancedSecureCryptoUtils.secureLog.log('warn', 'Elliptic curve P-384 import failed, switching curve', { error: p384Error.message });\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 // Removed public key import info logging\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 // Removed legacy public key export info logging\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 // Removed legacy public key import info logging\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 // Removed legacy public key import info logging\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 // Removed signature verification pass details to avoid key-related logging\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 // Removed detailed key derivation logging\n \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 public 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 // Step 1: Derive raw ECDH shared secret using pure ECDH\n let rawSharedSecret;\n try {\n // Removed detailed key derivation logging\n \n // Use pure ECDH to derive raw key material\n const rawKeyMaterial = await crypto.subtle.deriveKey(\n {\n name: 'ECDH',\n public: publicKey\n },\n privateKey,\n {\n name: 'AES-GCM',\n length: 256\n },\n true, // Extractable\n ['encrypt', 'decrypt']\n );\n \n // Export the raw key material\n const rawKeyData = await crypto.subtle.exportKey('raw', rawKeyMaterial);\n \n // Import as HKDF key material for further derivation\n rawSharedSecret = await crypto.subtle.importKey(\n 'raw',\n rawKeyData,\n {\n name: 'HKDF',\n hash: 'SHA-256'\n },\n false,\n ['deriveKey']\n );\n \n // Removed detailed key derivation logging\n } catch (error) {\n EnhancedSecureCryptoUtils.secureLog.log('error', 'ECDH derivation failed', { \n error: error.message\n });\n throw error;\n }\n \n // Step 2: Use HKDF to derive specific keys directly\n // Removed detailed key derivation logging\n\n // Step 3: Derive specific keys using HKDF with unique info parameters\n // Each key uses unique info parameter for proper separation\n \n // Derive message encryption key (messageKey)\n let messageKey;\n messageKey = await crypto.subtle.deriveKey(\n {\n name: 'HKDF',\n hash: 'SHA-256',\n salt: saltBytes,\n info: encoder.encode('message-encryption-v4')\n },\n rawSharedSecret,\n {\n name: 'AES-GCM',\n length: 256\n },\n false, // Non-extractable for enhanced security\n ['encrypt', 'decrypt']\n );\n\n // Derive MAC key for message authentication\n let macKey;\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 rawSharedSecret,\n {\n name: 'HMAC',\n hash: 'SHA-256'\n },\n false, // Non-extractable\n ['sign', 'verify']\n );\n\n // Derive Perfect Forward Secrecy key (pfsKey)\n let pfsKey;\n pfsKey = await crypto.subtle.deriveKey(\n {\n name: 'HKDF',\n hash: 'SHA-256',\n salt: saltBytes,\n info: encoder.encode('perfect-forward-secrecy-v4')\n },\n rawSharedSecret,\n {\n name: 'AES-GCM',\n length: 256\n },\n false, // Non-extractable\n ['encrypt', 'decrypt']\n );\n\n // Derive separate metadata encryption key\n let metadataKey;\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 rawSharedSecret,\n {\n name: 'AES-GCM',\n length: 256\n },\n false, // Non-extractable\n ['encrypt', 'decrypt']\n );\n\n // Generate temporary extractable key for fingerprint calculation\n let fingerprintKey;\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 rawSharedSecret,\n {\n name: 'AES-GCM',\n length: 256\n },\n true, // Extractable only for fingerprint\n ['encrypt', 'decrypt']\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 (!(messageKey instanceof CryptoKey)) {\n EnhancedSecureCryptoUtils.secureLog.log('error', 'Derived message key is not a CryptoKey', {\n messageKeyType: typeof messageKey,\n messageKeyAlgorithm: messageKey?.algorithm?.name\n });\n throw new Error('The derived message 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 (!(pfsKey instanceof CryptoKey)) {\n EnhancedSecureCryptoUtils.secureLog.log('error', 'Derived PFS key is not a CryptoKey', {\n pfsKeyType: typeof pfsKey,\n pfsKeyAlgorithm: pfsKey?.algorithm?.name\n });\n throw new Error('The derived PFS 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 // Removed detailed key derivation success logging\n\n return {\n messageKey, // Renamed from encryptionKey for clarity\n macKey,\n pfsKey, // Added Perfect Forward Secrecy key\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', { \n error: error.message,\n errorStack: error.stack,\n privateKeyType: typeof privateKey,\n publicKeyType: typeof publicKey,\n saltLength: salt?.length,\n privateKeyAlgorithm: privateKey?.algorithm?.name,\n publicKeyAlgorithm: publicKey?.algorithm?.name\n });\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 30 minutes for better UX)\n const responseAge = Date.now() - proof.responseTimestamp;\n if (responseAge > 1800000) {\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 const charCount = chars.length;\n let result = '';\n \n // Use rejection sampling to avoid bias\n for (let i = 0; i < 6; i++) {\n let randomByte;\n do {\n randomByte = crypto.getRandomValues(new Uint8Array(1))[0];\n } while (randomByte >= 256 - (256 % charCount)); // Reject biased values\n \n result += chars[randomByte % charCount];\n }\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 // Logging removed to avoid noisy console output\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 > 1800000) { // 30 minutes for better UX\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 with iterative processing to handle edge cases\n static sanitizeMessage(message) {\n if (typeof message !== 'string') {\n throw new Error('Message must be a string');\n }\n \n // Helper function to apply replacement until stable\n function replaceUntilStable(str, pattern, replacement = '') {\n let previous;\n do {\n previous = str;\n str = str.replace(pattern, replacement);\n } while (str !== previous);\n return str;\n }\n \n // Define all dangerous patterns that need to be removed\n const dangerousPatterns = [\n // Script tags with various formats\n /]*>[\\s\\S]*?<\\/script\\s*>/gi,\n /]*>[\\s\\S]*?<\\/script\\s+[^>]*>/gi,\n /]*>[\\s\\S]*$/gi,\n // Other dangerous tags\n /]*>[\\s\\S]*?<\\/iframe\\s*>/gi,\n /]*>[\\s\\S]*?<\\/object\\s*>/gi,\n /]*>/gi,\n /]*>[\\s\\S]*?<\\/applet\\s*>/gi,\n /]*>[\\s\\S]*?<\\/style\\s*>/gi,\n // Dangerous protocols\n /javascript\\s*:/gi,\n /data\\s*:/gi,\n /vbscript\\s*:/gi,\n // Event handlers\n /on\\w+\\s*=/gi,\n // HTML comments\n //g,\n // Link and meta tags with javascript\n /]*javascript[^>]*>/gi,\n /]*javascript[^>]*>/gi,\n // Any remaining script-like content\n /<[^>]*script[^>]*>/gi,\n /<[^>]*on\\w+\\s*=[^>]*>/gi\n ];\n \n // Iterative sanitization to handle edge cases\n let sanitized = message;\n let previousLength;\n let iterations = 0;\n const maxIterations = 10; // Prevent infinite loops\n \n do {\n previousLength = sanitized.length;\n \n // Apply all dangerous patterns with stable replacement\n for (const pattern of dangerousPatterns) {\n sanitized = replaceUntilStable(sanitized, pattern);\n }\n \n // Additional cleanup for edge cases - each applied until stable\n sanitized = replaceUntilStable(sanitized, /<[^>]*>/g);\n sanitized = replaceUntilStable(sanitized, /^\\w+:/gi);\n sanitized = replaceUntilStable(sanitized, /\\bon\\w+\\s*=\\s*[\"'][^\"']*[\"']/gi);\n sanitized = replaceUntilStable(sanitized, /\\bon\\w+\\s*=\\s*[^>\\s]+/gi);\n \n // Single character removal is inherently safe\n sanitized = sanitized.replace(/[<>]/g, '').trim();\n \n iterations++;\n } while (sanitized.length !== previousLength && iterations < maxIterations);\n \n // Final security pass with stable replacements\n sanitized = replaceUntilStable(sanitized, /<[^>]*>/g);\n sanitized = replaceUntilStable(sanitized, /^\\w+:/gi);\n sanitized = replaceUntilStable(sanitized, /\\bon\\w+\\s*=\\s*[\"'][^\"']*[\"']/gi);\n sanitized = replaceUntilStable(sanitized, /\\bon\\w+\\s*=\\s*[^>\\s]+/gi);\n \n // Final single character cleanup\n sanitized = sanitized.replace(/[<>]/g, '').trim();\n \n return sanitized.substring(0, 2000); // Limit length\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 // Removed key fingerprint logging\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 }\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 }\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, onIncomingFileRequest) {\n this.webrtcManager = webrtcManager;\n this.onProgress = onProgress;\n this.onComplete = onComplete;\n this.onError = onError;\n this.onFileReceived = onFileReceived;\n this.onIncomingFileRequest = onIncomingFileRequest;\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 pdf: {\n extensions: ['.pdf'],\n mimeTypes: ['application/pdf'],\n maxSize: 50 * 1024 * 1024,\n category: 'PDF',\n description: 'PDF'\n },\n\n text: {\n extensions: ['.txt'],\n mimeTypes: ['text/plain'],\n maxSize: 10 * 1024 * 1024,\n category: 'Plain text',\n description: 'TXT'\n },\n \n images: {\n extensions: ['.jpg', '.jpeg', '.png', '.gif', '.webp', '.bmp', '.ico'],\n mimeTypes: [\n 'image/jpeg',\n 'image/png',\n 'image/gif',\n 'image/webp',\n 'image/bmp',\n 'image/x-icon'\n ],\n maxSize: 25 * 1024 * 1024, // 25 MB\n category: 'Images',\n description: 'JPG, JPEG, PNG, GIF, WEBP, BMP, ICO'\n },\n \n archives: {\n extensions: ['.zip'],\n mimeTypes: ['application/zip'],\n maxSize: 100 * 1024 * 1024, // 100 MB\n category: 'Archives',\n description: 'ZIP'\n }\n };\n this.BLOCKED_EXTENSIONS = new Set([\n '.exe', '.bat', '.cmd', '.sh', '.js', '.msi', '.dmg', '.app',\n '.jar', '.scr', '.ps1', '.vbs', '.html', '.svg'\n ]);\n \n // Active transfers tracking\n this.activeTransfers = new Map(); // fileId -> transfer state\n this.receivingTransfers = new Map(); // fileId -> receiving state\n this.pendingIncomingTransfers = new Map(); // fileId -> validated metadata awaiting consent\n this.transferQueue = []; // Queue for pending transfers\n this.pendingChunks = new Map();\n this.incomingOfferLimiter = new RateLimiter(5, 60000);\n this.MAX_PENDING_INCOMING_TRANSFERS = 3;\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 this.MAX_RETAINED_RECEIVED_FILE_BUFFERS = 3;\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 = String(file?.name || '').toLowerCase();\n const extensionIndex = fileName.lastIndexOf('.');\n const fileExtension = extensionIndex >= 0 ? fileName.substring(extensionIndex) : '';\n const mimeType = String(file?.type || '').toLowerCase();\n\n for (const [typeKey, typeConfig] of Object.entries(this.FILE_TYPE_RESTRICTIONS)) {\n const extensionAllowed = typeConfig.extensions.includes(fileExtension);\n const mimeAllowed = typeConfig.mimeTypes.includes(mimeType);\n if (extensionAllowed && mimeAllowed) {\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 return {\n type: 'blocked',\n category: 'Unsupported',\n description: 'Allowed: JPG, JPEG, PNG, GIF, WEBP, BMP, ICO, PDF, TXT, ZIP',\n maxSize: this.MAX_FILE_SIZE,\n allowed: false,\n extension: fileExtension,\n mimeType\n };\n }\n\n validateFile(file) {\n const fileType = this.getFileType(file);\n const errors = [];\n const fileName = String(file?.name || '');\n const lowerName = fileName.toLowerCase();\n const extensionIndex = lowerName.lastIndexOf('.');\n const fileExtension = extensionIndex >= 0 ? lowerName.substring(extensionIndex) : '';\n const mimeType = String(file?.type || '').toLowerCase();\n\n if (this.BLOCKED_EXTENSIONS.has(fileExtension)) {\n errors.push(`File rejected: ${fileExtension} files are not allowed for security reasons.`);\n }\n\n if (!mimeType) {\n errors.push('File rejected: missing MIME type is unsafe.');\n }\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 if (mimeType && !this.BLOCKED_EXTENSIONS.has(fileExtension)) {\n errors.push(`File rejected: extension and MIME type must match an allowed type. Supported types: ${fileType.description}`);\n }\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 normalizeDisplayFileName(fileName) {\n return String(fileName || '')\n .normalize('NFKC')\n .replace(/[\\u0000-\\u001F\\u007F]/g, '')\n .replace(/[\\\\/]+/g, '_')\n .trim()\n .slice(0, 255);\n }\n\n validateIncomingMetadata(metadata) {\n const errors = [];\n if (!metadata || typeof metadata !== 'object') errors.push('Invalid file transfer metadata');\n if (!metadata?.fileId || typeof metadata.fileId !== 'string') errors.push('Invalid file id');\n if (!Number.isSafeInteger(metadata?.fileSize) || metadata.fileSize <= 0) errors.push('Invalid file size');\n if (!Number.isSafeInteger(metadata?.totalChunks) || metadata.totalChunks <= 0) errors.push('Invalid chunk count');\n if (!Number.isSafeInteger(metadata?.chunkSize) || metadata.chunkSize <= 0 || metadata.chunkSize > this.CHUNK_SIZE) errors.push('Invalid chunk size');\n if (!Array.isArray(metadata?.salt) || metadata.salt.length !== 32) errors.push('Invalid salt');\n\n const rawName = typeof metadata?.fileName === 'string' ? metadata.fileName : '';\n const displayName = this.normalizeDisplayFileName(rawName);\n const hasDangerousName =\n !rawName ||\n rawName !== rawName.trim() ||\n /[\\u0000-\\u001F\\u007F]/.test(rawName) ||\n /[\\\\/]/.test(rawName) ||\n rawName === '.' ||\n rawName === '..' ||\n displayName.length === 0;\n if (hasDangerousName) errors.push('Dangerous file name');\n\n if (errors.length === 0) {\n const validation = this.validateFile({\n name: displayName,\n size: metadata.fileSize,\n type: metadata.fileType || 'application/octet-stream'\n });\n if (!validation.isValid) errors.push(...validation.errors);\n }\n\n return { isValid: errors.length === 0, errors, displayName };\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 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 const consentPromise = new Promise((resolve, reject) => {\n transferState.resolveConsent = resolve;\n transferState.rejectConsent = reject;\n transferState.consentTimeout = setTimeout(() => {\n transferState.consentTimeout = null;\n reject(new Error('Transfer timeout'));\n }, 30000);\n });\n\n // Send file metadata first\n await this.sendFileMetadata(transferState);\n \n // Wait for explicit receiver consent before any chunks are sent.\n await consentPromise;\n \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 const clientId = this.getClientIdentifier();\n if (!this.incomingOfferLimiter.isAllowed(clientId)) {\n throw new Error('Incoming file request rate limit exceeded');\n }\n\n const validation = this.validateIncomingMetadata(metadata);\n if (!validation.isValid) throw new Error(validation.errors.join('. '));\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) || this.pendingIncomingTransfers.has(metadata.fileId)) {\n return;\n }\n\n if (this.pendingIncomingTransfers.size >= this.MAX_PENDING_INCOMING_TRANSFERS) {\n throw new Error('Too many pending incoming file requests');\n }\n\n const pendingMetadata = {\n ...metadata,\n fileName: validation.displayName,\n receivedAt: Date.now()\n };\n this.pendingIncomingTransfers.set(metadata.fileId, pendingMetadata);\n\n if (typeof this.onIncomingFileRequest === 'function') {\n this.onIncomingFileRequest({\n fileId: pendingMetadata.fileId,\n fileName: pendingMetadata.fileName,\n fileSize: pendingMetadata.fileSize,\n mimeType: pendingMetadata.fileType || 'application/octet-stream'\n });\n } else {\n await this.rejectIncomingFile(metadata.fileId, 'User consent unavailable');\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 // Never buffer chunks before explicit consent.\n if (!receivingState) {\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._storeReceivedFileBuffer(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 () => {\n const blob = await this.getBlob(receivingState.fileId);\n if (!blob) {\n throw new Error('This file is no longer available for download.');\n }\n return blob;\n };\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 if (transferState.consentTimeout) clearTimeout(transferState.consentTimeout);\n transferState.consentTimeout = null;\n transferState.resolveConsent?.();\n transferState.resolveConsent = null;\n transferState.rejectConsent = null;\n } else {\n transferState.status = 'rejected';\n if (transferState.consentTimeout) clearTimeout(transferState.consentTimeout);\n transferState.consentTimeout = null;\n transferState.rejectConsent?.(new Error(response.error || 'Transfer rejected'));\n transferState.rejectConsent = null;\n transferState.resolveConsent = null;\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 getPendingIncomingTransfers() {\n return Array.from(this.pendingIncomingTransfers.values()).map(transfer => ({\n fileId: transfer.fileId,\n fileName: transfer.fileName,\n fileSize: transfer.fileSize,\n mimeType: transfer.fileType || 'application/octet-stream',\n receivedAt: transfer.receivedAt\n }));\n }\n\n async acceptIncomingFile(fileId) {\n const metadata = this.pendingIncomingTransfers.get(fileId);\n if (!metadata) return false;\n const sessionKey = await this.deriveFileSessionKeyFromSalt(fileId, metadata.salt);\n this.receivingTransfers.set(fileId, {\n 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,\n salt: metadata.salt,\n receivedChunks: new Map(),\n receivedCount: 0,\n startTime: Date.now(),\n lastChunkTime: Date.now(),\n status: 'receiving'\n });\n this.pendingIncomingTransfers.delete(fileId);\n await this.sendSecureMessage({ type: 'file_transfer_response', fileId, accepted: true, timestamp: Date.now() });\n return true;\n }\n\n async rejectIncomingFile(fileId, error = 'Rejected by user') {\n if (!this.pendingIncomingTransfers.has(fileId)) return false;\n this.pendingIncomingTransfers.delete(fileId);\n await this.sendSecureMessage({ type: 'file_transfer_response', fileId, accepted: false, error, timestamp: Date.now() });\n return true;\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 const transferState = this.activeTransfers.get(fileId);\n if (transferState) {\n if (transferState.consentTimeout) {\n clearTimeout(transferState.consentTimeout);\n transferState.consentTimeout = null;\n }\n if (transferState.rejectConsent) {\n transferState.rejectConsent(new Error('Transfer cancelled during cleanup or disconnect'));\n transferState.rejectConsent = null;\n transferState.resolveConsent = null;\n }\n }\n\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 _storeReceivedFileBuffer(fileId, entry) {\n this.receivedFileBuffers.set(fileId, entry);\n while (this.receivedFileBuffers.size > this.MAX_RETAINED_RECEIVED_FILE_BUFFERS) {\n const oldestFileId = this.receivedFileBuffers.keys().next().value;\n this._discardReceivedFileBuffer(oldestFileId);\n }\n }\n\n _discardReceivedFileBuffer(fileId) {\n const fileBuffer = this.receivedFileBuffers.get(fileId);\n if (!fileBuffer) return;\n try {\n if (fileBuffer.buffer) {\n SecureMemoryManager.secureWipe(fileBuffer.buffer);\n new Uint8Array(fileBuffer.buffer).fill(0);\n }\n } catch (_) {\n // Best-effort wipe; deletion must still proceed.\n }\n this.receivedFileBuffers.delete(fileId);\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.pendingIncomingTransfers.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 for (const fileId of Array.from(this.receivedFileBuffers.keys())) {\n this._discardReceivedFileBuffer(fileId);\n }\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 };\n", "// 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 PROTOCOL_VERSION = '4.1';\n static MAX_SAS_ATTEMPTS = 3;\n\n // Static debug flag instead of this._debugMode\n static DEBUG_MODE = true; // 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 webrtc: {\n relayOnly: config.webrtc?.relayOnly ?? false,\n iceServers: config.webrtc?.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 }\n };\n this._ipLeakWarningShown = false;\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.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.sasValidationAttempts = 0;\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._sessionAlive = true;\n this._fileTransferInitRetryTimers = new Set();\n this._peerDisconnectCleanupTimer = null;\n this._logCleanupInterval = null;\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 = null; // \u043E\u0442\u043A\u043B\u044E\u0447\u0430\u0435\u043C \u0442\u0430\u0439\u043C\u0435\u0440\u043D\u0443\u044E \u0440\u043E\u0442\u0430\u0446\u0438\u044E\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 // All security features enabled by default - no payment required\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, // Real Perfect Forward Secrecy enabled \n \n // Advanced Features - All enabled by default\n hasNestedEncryption: true, \n hasPacketPadding: true, \n hasPacketReordering: true, \n hasAntiFingerprinting: true, \n hasFakeTraffic: true, \n hasDecoyChannels: true, \n hasMessageChunking: true \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 // Session mode: 'time' | 'ratchet' (Double Ratchet controls key lifecycle)\n this.sessionMode = 'ratchet';\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 || false,\n minInterval: this._config.fakeTraffic?.minInterval || 15000,\n maxInterval: this._config.fakeTraffic?.maxInterval || 30000,\n minSize: this._config.fakeTraffic?.minSize || 64,\n maxSize: this._config.fakeTraffic?.maxSize || 1024,\n patterns: this._config.fakeTraffic?.patterns || ['heartbeat', 'status', 'ping'],\n randomDecoyIntervals: this._config.fakeTraffic?.randomDecoyIntervals || true\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 * Create a safe hash for logging sensitive data\n * Returns only the first 4 bytes (8 hex chars) of SHA-256 hash\n * @param {any} sensitiveData - The sensitive data to hash\n * @param {string} context - Context for error logging\n * @returns {Promise} - Short hash (8 hex chars) or 'hash_error'\n */\n async _createSafeLogHash(sensitiveData, context = 'unknown') {\n try {\n let dataToHash;\n \n // Convert different data types to consistent format for hashing\n if (sensitiveData instanceof ArrayBuffer) {\n dataToHash = new Uint8Array(sensitiveData);\n } else if (sensitiveData instanceof Uint8Array) {\n dataToHash = sensitiveData;\n } else if (sensitiveData instanceof CryptoKey) {\n // For CryptoKey, use its type and algorithm info (not the key material)\n const keyInfo = `${sensitiveData.type}_${sensitiveData.algorithm?.name || 'unknown'}_${sensitiveData.extractable}`;\n dataToHash = new TextEncoder().encode(keyInfo);\n } else if (typeof sensitiveData === 'string') {\n dataToHash = new TextEncoder().encode(sensitiveData);\n } else if (typeof sensitiveData === 'object' && sensitiveData !== null) {\n // For objects (like JWK), stringify without sensitive fields\n const safeObj = { type: sensitiveData.kty || 'unknown', use: sensitiveData.use || 'unknown' };\n dataToHash = new TextEncoder().encode(JSON.stringify(safeObj));\n } else {\n // Fallback for other types\n dataToHash = new TextEncoder().encode(String(sensitiveData));\n }\n \n // Create SHA-256 hash\n const hashBuffer = await crypto.subtle.digest('SHA-256', dataToHash);\n const hashArray = new Uint8Array(hashBuffer);\n \n // Return only first 4 bytes as hex (8 characters)\n return Array.from(hashArray.slice(0, 4))\n .map(b => b.toString(16).padStart(2, '0'))\n .join('');\n \n } catch (error) {\n // Never log the actual error details to avoid leaking sensitive data\n return 'hash_error';\n }\n }\n\n /**\n * Async sleep helper - replaces busy-wait\n */\n async _asyncSleep(ms) {\n return new Promise(resolve => setTimeout(resolve, ms));\n }\n\n /**\n * Async cleanup helper - replaces immediate heavy operations\n */\n async _scheduleAsyncCleanup(cleanupFn, delay = 0) {\n return new Promise((resolve) => {\n setTimeout(async () => {\n try {\n await cleanupFn();\n resolve(true);\n } catch (error) {\n this._secureLog('error', 'Async cleanup failed', {\n errorType: error?.constructor?.name || 'Unknown'\n });\n resolve(false);\n }\n }, delay);\n });\n }\n\n /**\n * Batch async operations to prevent UI blocking\n */\n async _batchAsyncOperation(items, batchSize = 10, delayBetweenBatches = 5) {\n const results = [];\n \n for (let i = 0; i < items.length; i += batchSize) {\n const batch = items.slice(i, i + batchSize);\n const batchResults = await Promise.all(batch);\n results.push(...batchResults);\n \n // Small delay between batches to prevent UI blocking\n if (i + batchSize < items.length) {\n await this._asyncSleep(delayBetweenBatches);\n }\n }\n \n return results;\n }\n\n /**\n * Memory cleanup without window.gc() - uses natural garbage collection\n */\n async _performNaturalCleanup() {\n // Clear references and let JS engine handle GC naturally\n // This is more reliable than forcing GC\n \n // Schedule cleanup in next event loop cycle\n await this._asyncSleep(0);\n \n // Allow multiple event loop cycles for natural GC\n for (let i = 0; i < 3; i++) {\n await this._asyncSleep(10);\n }\n }\n\n /**\n * Heavy cleanup operations using WebWorker (if available)\n */\n async _performHeavyCleanup(cleanupData) {\n // Try to use WebWorker for heavy operations\n if (typeof Worker !== 'undefined') {\n try {\n return await this._cleanupWithWorker(cleanupData);\n } catch (error) {\n this._secureLog('warn', 'WebWorker cleanup failed, falling back to main thread', {\n errorType: error?.constructor?.name || 'Unknown'\n });\n }\n }\n \n // Fallback to main thread with async batching\n return await this._cleanupInMainThread(cleanupData);\n }\n\n /**\n * Cleanup using WebWorker\n */\n async _cleanupWithWorker(cleanupData) {\n return new Promise((resolve, reject) => {\n // Create inline worker for cleanup operations\n const workerCode = `\n self.onmessage = function(e) {\n const { type, data } = e.data;\n \n try {\n switch (type) {\n case 'cleanup_arrays':\n // Simulate heavy array cleanup\n let processed = 0;\n for (let i = 0; i < data.count; i++) {\n // Simulate work\n processed++;\n if (processed % 1000 === 0) {\n // Yield control periodically\n setTimeout(() => {}, 0);\n }\n }\n self.postMessage({ success: true, processed });\n break;\n \n case 'cleanup_objects':\n // Simulate object cleanup\n const cleaned = data.objects.map(() => null);\n self.postMessage({ success: true, cleaned: cleaned.length });\n break;\n \n default:\n self.postMessage({ success: true, message: 'Unknown cleanup type' });\n }\n } catch (error) {\n self.postMessage({ success: false, error: error.message });\n }\n };\n `;\n \n const blob = new Blob([workerCode], { type: 'application/javascript' });\n const worker = new Worker(URL.createObjectURL(blob));\n \n const timeout = setTimeout(() => {\n worker.terminate();\n reject(new Error('Worker cleanup timeout'));\n }, 5000); // 5 second timeout\n \n worker.onmessage = (e) => {\n clearTimeout(timeout);\n worker.terminate();\n URL.revokeObjectURL(blob);\n \n if (e.data.success) {\n resolve(e.data);\n } else {\n reject(new Error(e.data.error));\n }\n };\n \n worker.onerror = (error) => {\n clearTimeout(timeout);\n worker.terminate();\n URL.revokeObjectURL(blob);\n reject(error);\n };\n \n worker.postMessage(cleanupData);\n });\n }\n\n /**\n * Cleanup in main thread with async batching\n */\n async _cleanupInMainThread(cleanupData) {\n const { type, data } = cleanupData;\n \n switch (type) {\n case 'cleanup_arrays':\n // Process in batches to avoid blocking\n let processed = 0;\n const batchSize = 100;\n \n while (processed < data.count) {\n const batchEnd = Math.min(processed + batchSize, data.count);\n \n // Process batch\n for (let i = processed; i < batchEnd; i++) {\n // Simulate cleanup work\n }\n \n processed = batchEnd;\n \n // Yield control to prevent UI blocking\n await this._asyncSleep(1);\n }\n \n return { success: true, processed };\n \n case 'cleanup_objects':\n // Clean objects in batches\n const objects = data.objects || [];\n const batches = [];\n \n for (let i = 0; i < objects.length; i += 50) {\n batches.push(objects.slice(i, i + 50));\n }\n \n let cleaned = 0;\n for (const batch of batches) {\n batch.forEach(() => cleaned++);\n await this._asyncSleep(1);\n }\n \n return { success: true, cleaned };\n \n default:\n return { success: true, message: 'Unknown cleanup type' };\n }\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 _trackActiveTimer(timer) {\n if (!timer) return timer;\n if (!this._activeTimers) this._activeTimers = new Set();\n this._activeTimers.add(timer);\n return timer;\n }\n\n _untrackActiveTimer(timer) {\n if (timer && this._activeTimers) this._activeTimers.delete(timer);\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().catch(error => {\n this._secureLog('error', 'Emergency cleanup failed', {\n errorType: error?.constructor?.name || 'Unknown'\n });\n });\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().catch(error => {\n this._secureLog('error', 'Emergency cleanup failed', {\n errorType: error?.constructor?.name || 'Unknown'\n });\n });\n }\n }\n\n /**\n * Emergency cleanup when resource limits are exceeded\n */\n async _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 // Perform natural cleanup without forcing GC\n await this._scheduleAsyncCleanup(async () => {\n this._secureLog('info', '\uD83E\uDDF9 Enhanced Emergency: Starting natural memory cleanup');\n \n // Natural cleanup cycles with async delays\n for (let i = 0; i < 3; i++) {\n this._secureLog('info', `\uD83E\uDDF9 Enhanced Emergency: Cleanup cycle ${i + 1}/3`);\n \n // Allow natural garbage collection between cycles\n await this._performNaturalCleanup();\n }\n \n this._secureLog('info', '\uD83E\uDDF9 Enhanced Emergency: Natural cleanup completed');\n }, 0);\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 }\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 master key manager\n this._masterKeyManager = new SecureMasterKeyManager();\n \n // Initialize with the new class and pass master key manager\n this._secureKeyStorage = new SecureKeyStorage(this._masterKeyManager);\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 /**\n * Set password callback for master key\n */\n setMasterKeyPasswordCallback(callback) {\n if (this._masterKeyManager) {\n this._masterKeyManager.setPasswordRequiredCallback(callback);\n }\n }\n \n /**\n * Set session expired callback for master key\n */\n setMasterKeySessionExpiredCallback(callback) {\n if (this._masterKeyManager) {\n this._masterKeyManager.setSessionExpiredCallback(callback);\n }\n }\n \n /**\n * Lock master key manually\n */\n lockMasterKey() {\n if (this._masterKeyManager) {\n this._masterKeyManager.lock();\n }\n }\n \n /**\n * Check if master key is unlocked\n */\n isMasterKeyUnlocked() {\n return this._masterKeyManager ? this._masterKeyManager.isUnlocked() : false;\n }\n \n /**\n * Get master key session status\n */\n getMasterKeySessionStatus() {\n return this._masterKeyManager ? this._masterKeyManager.getSessionStatus() : null;\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 \n // Also lock the master key\n if (this._masterKeyManager) {\n this._masterKeyManager.lock();\n }\n \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 // Enhanced script tag detection that handles edge cases\n /]*>[\\s\\S]*?<\\/script\\s*>/gi, // Standard \n /]*>[\\s\\S]*?<\\/script\\s+[^>]*>/gi, // \n /]*>[\\s\\S]*$/gi, // Malformed script tags without closing\n // Additional dangerous tags\n /]*>[\\s\\S]*?<\\/iframe\\s*>/gi, // iframe tags\n /]*>[\\s\\S]*?<\\/object\\s*>/gi, // object tags\n /]*>/gi, // embed tags\n /]*>[\\s\\S]*?<\\/applet\\s*>/gi, // applet tags\n /]*>[\\s\\S]*?<\\/style\\s*>/gi, // style tags\n // Dangerous protocols\n /javascript\\s*:/gi, // JavaScript protocol\n /data\\s*:/gi, // Data protocol\n /vbscript\\s*:/gi, // VBScript 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 _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 /**\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', '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?.('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?.('ECURITY: 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', '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: 'maximum',\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', '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', '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', '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', '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 async _forceGarbageCollection() {\n try {\n // Use natural cleanup instead of forcing GC\n await this._performNaturalCleanup();\n this._secureLog('debug', '\uD83D\uDD12 Natural memory cleanup performed');\n } catch (error) {\n this._secureLog('error', '\u274C Failed to perform natural cleanup', {\n errorType: error.constructor.name\n });\n }\n }\n \n /**\n * Perform periodic memory cleanup\n */\n async _performPeriodicMemoryCleanup() {\n try {\n this._secureMemoryManager.isCleaning = true;\n \n // Clean up sensitive data, but DO NOT wipe active crypto in ratchet session\n const shouldPreserveActiveKeys = (this.sessionMode === 'ratchet') && this.isConnected && this.dataChannel && this.dataChannel.readyState === 'open';\n if (shouldPreserveActiveKeys) {\n this._secureLog('debug', '\uD83E\uDDF9 Skipping crypto key wipe during periodic cleanup (ratchet mode, active connection)');\n } else {\n this._secureCleanupCryptographicMaterials();\n }\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 // Natural cleanup\n await 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 // All security features are enabled by default - no payment required\n this._secureLog('info', '\u2705 All security features enabled by default - no payment required');\n \n // Ensure all features are enabled\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 this.securityFeatures[feature] = true;\n });\n \n this._secureLog('info', '\u2705 All security features enabled by default', {\n enabledFeatures: Object.keys(this.securityFeatures).filter(f => this.securityFeatures[f]).length,\n totalFeatures: Object.keys(this.securityFeatures).length\n });\n \n return;\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 this._logCleanupInterval = this._trackActiveTimer(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 > 1800000) { // 30 minutes for better UX\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 async _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 // Ratchet mode: if fingerprint hasn't changed, treat as verified and skip warnings\n if (this.sessionMode === 'ratchet' && normalizedExpected === normalizedReceived) {\n this._secureLog('info', 'Same fingerprint detected \u2014 skip MITM warning (ratchet mode)', {\n context: context,\n timestamp: Date.now()\n });\n this.isVerified = true;\n return true;\n }\n\n if (normalizedReceived !== normalizedExpected) {\n this._secureLog('error', 'DTLS fingerprint mismatch - possible MITM attack', {\n context: context,\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 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 \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 const salt = enc.encode(\n 'webrtc-sas|' + [localFP, remoteFP].sort().join('|')\n );\n\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 const n = (dv.getUint32(0) ^ dv.getUint32(4)) >>> 0;\n \n // Deterministic SAS: both peers derive the same display code from the\n // same shared key material and canonicalized DTLS fingerprints.\n const sasCode = String(n % 10_000_000).padStart(7, '0');\n\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 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 async _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 // Schedule natural cleanup\n await this._performNaturalCleanup();\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 async _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 // Schedule natural cleanup\n await this._performNaturalCleanup();\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 * Attempt to reinitialize encryption keys if missing\n * Uses existing ECDH key pair, peer public key, and session salt\n * Returns true if keys were (re)initialized successfully\n */\n async _tryReinitializeEncryptionKeys() {\n try {\n // If keys already present, nothing to do\n if (this.encryptionKey && this.macKey && this.metadataKey) {\n return true;\n }\n\n // Require ECDH materials and session salt to derive keys\n const hasECDH = !!(this.ecdhKeyPair?.privateKey && (this.peerPublicKey || this.peerECDHPublicKey));\n const peerPublicKey = this.peerPublicKey || this.peerECDHPublicKey;\n if (!hasECDH || !peerPublicKey || !this.sessionSalt) {\n return false;\n }\n\n // Derive fresh keys\n const derivedKeys = await window.EnhancedSecureCryptoUtils.deriveSharedKeys(\n this.ecdhKeyPair.privateKey,\n peerPublicKey,\n this.sessionSalt\n );\n\n await this._setEncryptionKeys(\n derivedKeys.messageKey,\n derivedKeys.macKey,\n derivedKeys.metadataKey,\n derivedKeys.fingerprint\n );\n\n return !!(this.encryptionKey && this.macKey && this.metadataKey);\n } catch (error) {\n this._secureLog('error', 'Failed to reinitialize encryption keys', { error: error.message });\n return false;\n }\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 /**\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 // Schedule async cleanup without blocking\n this._performPeriodicMemoryCleanup().catch(error => {\n this._secureLog('error', 'Periodic cleanup failed', {\n errorType: error?.constructor?.name || 'Unknown'\n });\n });\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 async _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 // Schedule natural cleanup\n await this._performNaturalCleanup();\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 if (this._sessionAlive === false) {\n return;\n }\n\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 this._scheduleFileTransferInitRetry(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 this._scheduleFileTransferInitRetry(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 this.onIncomingFileRequest || 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 _scheduleFileTransferInitRetry(delay) {\n if (this._sessionAlive === false) return null;\n if (!this._fileTransferInitRetryTimers) this._fileTransferInitRetryTimers = new Set();\n\n const timer = this._trackActiveTimer(setTimeout(() => {\n this._fileTransferInitRetryTimers.delete(timer);\n this._untrackActiveTimer(timer);\n if (this._sessionAlive === false) return;\n this.initializeFileTransfer();\n }, delay));\n\n this._fileTransferInitRetryTimers.add(timer);\n return timer;\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 // Helper function: unbiased integer in [min, max]\n getSafeRandomInt(min, max) {\n if (!Number.isInteger(min) || !Number.isInteger(max)) {\n throw new Error('getSafeRandomInt requires integer min and max');\n }\n if (min >= max) {\n throw new Error('min must be less than max');\n }\n \n const range = max - min + 1;\n const bitsNeeded = Math.ceil(Math.log2(range));\n const bytesNeeded = Math.ceil(bitsNeeded / 8);\n const mask = (1 << bitsNeeded) - 1;\n \n let randomValue;\n do {\n const randomBytes = crypto.getRandomValues(new Uint8Array(bytesNeeded));\n\n randomValue = 0;\n for (let i = 0; i < bytesNeeded; i++) {\n randomValue = (randomValue * 256) + randomBytes[i];\n }\n\n randomValue = randomValue & mask;\n \n } while (randomValue >= range); \n\n return min + randomValue;\n }\n\n getSafeRandomFloat(minFloat, maxFloat, steps = 1000) {\n if (typeof minFloat !== 'number' || typeof maxFloat !== 'number') {\n throw new Error('getSafeRandomFloat requires numeric min and max');\n }\n if (minFloat >= maxFloat) {\n throw new Error('minFloat must be less than maxFloat');\n }\n const randomIndex = this.getSafeRandomInt(0, steps);\n \n const step = (maxFloat - minFloat) / steps;\n\n return minFloat + (randomIndex * step);\n }\n\n generateFingerprintMask() {\n const mask = {\n timingOffset: this.getSafeRandomInt(0, 1500),\n sizeVariation: this.getSafeRandomFloat(0.75, 1.25, 1000),\n noisePattern: Array.from(crypto.getRandomValues(new Uint8Array(64))),\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: this.getSafeRandomInt(50, 150),\n sizeMultiplier: this.getSafeRandomFloat(0.75, 1.25, 1000),\n timingVariation: this.getSafeRandomInt(100, 1100)\n };\n return mask;\n }\n\n // Security configuration - all features enabled by default\n configureSecurityForSession() {\n this._secureLog('info', '\uD83D\uDD27 Configuring security - all features enabled by default');\n \n // All security features are enabled by default - no payment required\n this.sessionConstraints = {};\n \n Object.keys(this.securityFeatures).forEach(feature => {\n this.sessionConstraints[feature] = true; // All features enabled\n });\n \n this.applySessionConstraints();\n \n this._secureLog('info', '\u2705 Security configured - all features enabled', { 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 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\n // Applying session constraints - all features enabled by default\n applySessionConstraints() {\n if (!this.sessionConstraints) return;\n\n // All features are enabled by default - no restrictions\n Object.keys(this.sessionConstraints).forEach(feature => {\n this.securityFeatures[feature] = true; // All features enabled\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 this._secureLog('info', '\u2705 All security features enabled by default', {\n constraints: this.sessionConstraints,\n currentFeatures: this.securityFeatures\n });\n }\n _sanitizeIncomingChatMessage(message) {\n if (typeof message !== 'string') {\n return message;\n }\n\n return window.EnhancedSecureCryptoUtils.sanitizeMessage(message);\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 const uiMessage = type === 'received'\n ? this._sanitizeIncomingChatMessage(message)\n : message;\n\n if (this.onMessage) {\n this._secureLog('debug', '\uD83D\uDCE4 Calling this.onMessage callback', { message: uiMessage, type });\n this.onMessage(uiMessage, 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\n if (this.lastSecurityLevelNotification === 'maximum') {\n return; // prevent duplication\n }\n \n this.lastSecurityLevelNotification = 'maximum';\n \n const message = '\uD83D\uDEE1\uFE0F Maximum Security Active - All features enabled';\n \n if (this.onMessage) {\n this.deliverMessageToUI(message, 'system');\n }\n\n // Showing details of active features\n if (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 this.getUnbiasedRandomInRange(this.fakeTrafficConfig.minInterval, Math.min(this.fakeTrafficConfig.maxInterval, 60000)) : // Cap at 60 seconds\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 // Use a reasonable range for initial delay (5-30 seconds)\n const minDelay = EnhancedSecureWebRTCManager.TIMEOUTS.DECOY_INITIAL_DELAY;\n const maxDelay = Math.min(this.fakeTrafficConfig.maxInterval, 30000); // Cap at 30 seconds\n const initialDelay = this.getUnbiasedRandomInRange(minDelay, maxDelay);\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 patternIndex = this.getUnbiasedRandomInRange(0, this.fakeTrafficConfig.patterns.length - 1);\n const pattern = this.fakeTrafficConfig.patterns[patternIndex];\n \n const size = this.getUnbiasedRandomInRange(this.fakeTrafficConfig.minSize, this.fakeTrafficConfig.maxSize);\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 = this.getUnbiasedRandomInRange(8, 40); // 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 = this.getUnbiasedRandomInRange(1, 3); // 1-3 headers\n let totalHeaderSize = 0;\n \n // Calculate total header size\n for (let i = 0; i < headerCount; i++) {\n totalHeaderSize += 4 + this.getUnbiasedRandomInRange(0, 15) + 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 // Generate unbiased random index for header selection\n let headerIndex;\n do {\n headerIndex = crypto.getRandomValues(new Uint8Array(1))[0];\n } while (headerIndex >= 256 - (256 % this.fingerprintMask.headerVariations.length));\n \n const headerName = this.fingerprintMask.headerVariations[headerIndex % this.fingerprintMask.headerVariations.length];\n \n // Generate unbiased random size for header data (4-19 bytes)\n let headerSize;\n do {\n headerSize = crypto.getRandomValues(new Uint8Array(1))[0];\n } while (headerSize >= 256 - (256 % 16));\n \n const headerData = crypto.getRandomValues(new Uint8Array((headerSize % 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 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 // Ensure encryption keys are available; try to reinitialize if needed\n if (!(this.encryptionKey && this.macKey && this.metadataKey)) {\n await this._tryReinitializeEncryptionKeys();\n }\n\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 // Enable full anti-fingerprinting features\n this.antiFingerprintingConfig.randomizeSizes = true;\n this.antiFingerprintingConfig.maskPatterns = true;\n this.antiFingerprintingConfig.useRandomHeaders = true;\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 this._secureLog('info', '\uD83D\uDD12 Enabling Stage 3 features (traffic obfuscation)');\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 this._secureLog('info', '\uD83D\uDD12 Enabling Stage 4 features (maximum safety)');\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 = 4; // Maximum security stage\n \n return {\n stage: stage,\n securityLevel: 'maximum',\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', '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 = `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', '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 this._secureLog('info', 'Starting graduated security activation - all features enabled');\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 await this.calculateAndReportSecurityLevel();\n this.notifySecurityUpgrade(1);\n \n // Enable all security stages progressively\n setTimeout(async () => {\n if (checkStability()) {\n this.enableStage2Security();\n await this.calculateAndReportSecurityLevel(); \n \n setTimeout(async () => {\n if (checkStability()) {\n this.enableStage3Security();\n await this.calculateAndReportSecurityLevel();\n \n setTimeout(async () => {\n if (checkStability()) {\n this.enableStage4Security();\n await this.calculateAndReportSecurityLevel();\n }\n }, 20000);\n }\n }, 15000);\n }\n }, 10000);\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 /**\n * Clear all verification states and data\n * Called when verification is rejected or connection is terminated\n */\n _clearVerificationStates() {\n try {\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 this.sasValidationAttempts = 0;\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 } 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', ' 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', ' 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', ' 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', ' 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', `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 _hasTurnServer() {\n return (this._config.webrtc.iceServers || []).some(server => {\n const urls = Array.isArray(server.urls) ? server.urls : [server.urls];\n return urls.some(url => typeof url === 'string' && url.toLowerCase().startsWith('turn:'));\n });\n }\n\n _buildPeerConnectionConfig() {\n const config = {\n iceServers: this._config.webrtc.iceServers,\n iceCandidatePoolSize: 10,\n bundlePolicy: 'balanced'\n };\n if (this._config.webrtc.relayOnly) {\n config.iceTransportPolicy = 'relay';\n }\n return config;\n }\n\n _warnIfTurnMissing() {\n if (this._hasTurnServer() || this._ipLeakWarningShown) return;\n this._ipLeakWarningShown = true;\n const message = this._config.webrtc.relayOnly\n ? 'Privacy mode is enabled, but no TURN server is configured. Relay-only mode cannot connect until TURN is configured; STUN alone does not hide IP addresses.'\n : 'Privacy warning: no TURN server is configured. Direct WebRTC connections may expose IP addresses; STUN alone does not provide IP protection.';\n this.deliverMessageToUI(message, 'system');\n }\n\n createPeerConnection() {\n this._sessionAlive = true;\n const config = this._buildPeerConnectionConfig();\n this._warnIfTurnMissing();\n\n this.peerConnection = new RTCPeerConnection(config);\n\n this.peerConnection.onconnectionstatechange = () => {\n const state = this.peerConnection.connectionState;\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\n } else {\n this.onStatusChange(state);\n }\n };\n\n this.peerConnection.ondatachannel = (event) => {\n \n // CRITICAL: Store the received data channel\n if (event.channel.label === 'securechat') {\n this.dataChannel = event.channel;\n this.setupDataChannel(event.channel);\n } else {\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\n this.dataChannel = channel;\n\n this.dataChannel.onopen = async () => {\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', '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 this.dataChannel.send(JSON.stringify(sasPayload));\n this.pendingSASCode = null; // Clear after sending\n } catch (error) {\n }\n } else if (this.pendingSASCode) {\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\n // IMPORTANT: Process ALL messages WITHOUT mutex\n if (typeof event.data === 'string') {\n try {\n const parsed = JSON.parse(event.data);\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\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', 'Failed to initialize file transfer system for receiver:', { errorType: initError?.constructor?.name || 'Unknown' });\n }\n }\n\n if (this.fileTransferSystem) {\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', 'Lazy init of file transfer failed:', { errorType: e?.message || e?.constructor?.name || 'Unknown' });\n }\n this._secureLog('error', '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 this.handleSystemMessage(parsed);\n return;\n }\n \n // ============================================\n // REGULAR USER MESSAGES (WITHOUT MUTEX)\n // ============================================\n \n if (parsed.type === 'message' && parsed.data) {\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 await this._processEnhancedMessageWithoutMutex(parsed);\n return;\n }\n \n \n } catch (jsonError) {\n // Not JSON \u2014 treat as regular text message\n if (this.onMessage) {\n this.deliverMessageToUI(event.data, 'received');\n }\n return;\n }\n } else if (event.data instanceof ArrayBuffer) {\n await this._processBinaryDataWithoutMutex(event.data);\n } else {\n }\n \n } catch (error) {\n this._secureLog('error', '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 \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', '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', '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', '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 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', '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 \n if (!this.encryptionKey || !this.macKey || !this.metadataKey) {\n this._secureLog('error', '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 \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 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', 'No message content in decrypted result');\n }\n \n } catch (error) {\n this._secureLog('error', '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', `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', `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', `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', `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', `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', `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', `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', `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', `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', `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', `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', `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', `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', `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', `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', `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', `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', `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', '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', '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', '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', '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', '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', `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', `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', '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', 'Mutex system recovered successfully with validation');\n return true;\n \n } catch (error) {\n this._secureLog('error', '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', 'Forced mutex system re-initialization completed');\n return true;\n } catch (reinitError) {\n this._secureLog('error', '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', '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', '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', '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', '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', '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', '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', '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', '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', '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', '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', 'ECDH encryption features enabled');\n }\n \n if (ecdsaKeyPair && ecdsaKeyPair.privateKey && ecdsaKeyPair.publicKey) {\n this.securityFeatures.hasECDSA = true;\n this._secureLog('info', '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', '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', 'Perfect Forward Secrecy enabled with ephemeral keys');\n }\n \n this._secureLog('info', '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', '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', `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', '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', `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', `Emergency unlocked mutex: ${mutexName}`, {\n previousState: previousState,\n queueRejectCount: queueRejectCount,\n callerContext: callerContext\n });\n \n } catch (error) {\n errorCount++;\n this._secureLog('error', `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', `Emergency reset key system state`, {\n previousState: previousKeyState,\n callerContext: callerContext\n });\n \n } catch (error) {\n this._secureLog('error', `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', `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', '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', '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', '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', `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', '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', `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', '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', `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', `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', `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 async _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 // Schedule natural cleanup if significant cleanup occurred\n if (cleanedCount > 50) {\n await this._performNaturalCleanup();\n }\n \n if (cleanedCount > 0) {\n this._secureLog('debug', `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', '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', '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', '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', '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', `Mutex '${mutexName}' not found during timeout handling`);\n return;\n }\n \n // Validate timeout conditions\n if (mutex.lockId !== operationId) {\n this._secureLog('warn', `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', `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', `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', `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', `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', `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', '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', `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', `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', `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', `Mutex '${mutexName}' still has timeout after emergency unlock`);\n }\n \n if (mutex.queue.length > 0) {\n validationErrors++;\n this._secureLog('error', `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', `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', 'Mutex system validation passed after emergency unlock');\n } else {\n this._secureLog('error', `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 return this._withMutex('connectionOperation', async (operationId) => {\n this._secureLog('info', '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 \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 \n this._secureLog('debug', '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 \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 \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 \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 \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 \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 \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', '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 \n\n const offer = await this.peerConnection.createOffer({\n offerToReceiveAudio: false,\n offerToReceiveVideo: false\n });\n \n await this.peerConnection.setLocalDescription(offer);\n\n try {\n const ourFingerprint = this._extractDTLSFingerprintFromSDP(offer.sdp);\n this.expectedDTLSFingerprint = ourFingerprint;\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(`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', '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\n this.verificationCode = window.EnhancedSecureCryptoUtils.generateVerificationCode();\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 \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 \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 \n // All security features are enabled by default\n const securityLevel = {\n level: 'MAXIMUM',\n score: 100,\n color: 'green',\n details: 'All security features enabled by default',\n passedChecks: 10,\n totalChecks: 10,\n isRealData: true\n };\n \n // ============================================\n // PHASE 12: CREATE OFFER PACKAGE\n // ============================================\n \n const currentTimestamp = Date.now();\n \n // Create compact offer package for smaller QR codes\n const offerPackage = {\n // Core information (minimal)\n t: 'offer', // type\n s: this.peerConnection.localDescription.sdp, // sdp\n v: EnhancedSecureWebRTCManager.PROTOCOL_VERSION, // version\n ts: currentTimestamp, // timestamp\n \n // Cryptographic keys (essential)\n e: ecdhPublicKeyData, // ecdhPublicKey\n d: ecdsaPublicKeyData, // ecdsaPublicKey\n \n // Session data (essential)\n sl: this.sessionSalt, // salt\n si: this.sessionId, // sessionId\n ci: this.connectionId, // connectionId\n \n // Authentication (essential)\n vc: this.verificationCode, // verificationCode\n ac: authChallenge, // authChallenge\n \n // Security metadata (simplified)\n slv: 'MAX', // securityLevel\n \n // Key fingerprints (shortened)\n kf: {\n e: ecdhFingerprint.substring(0, 12), // ecdh (12 chars)\n d: ecdsaFingerprint.substring(0, 12) // ecdsa (12 chars)\n }\n };\n \n // ============================================\n // PHASE 13: VALIDATE OFFER PACKAGE\n // ============================================\n\n try {\n const validationResult = this.validateEnhancedOfferData(offerPackage);\n\n } catch (validationError) {\n throw new Error(`Offer package validation error: ${validationError.message}`);\n }\n \n // ============================================\n // PHASE 14: LOGGING AND EVENTS\n // ============================================\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: 10 // All capabilities enabled by default\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 return offerPackage;\n \n } catch (error) {\n // ============================================\n // ERROR HANDLING\n // ============================================\n \n this._secureLog('error', '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 // Schedule natural cleanup\n this._forceGarbageCollection().catch(error => {\n this._secureLog('error', 'Cleanup failed during offer cleanup', {\n errorType: error?.constructor?.name || 'Unknown'\n });\n });\n \n this._secureLog('debug', 'Failed offer creation cleanup completed with secure memory wipe');\n \n } catch (cleanupError) {\n this._secureLog('error', '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', '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', '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 return this._withMutex('connectionOperation', async (operationId) => {\n this._secureLog('info', '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 (support both formats)\n const timestamp = offerData.ts || offerData.timestamp;\n const version = offerData.v || offerData.version;\n if (!timestamp || !version) {\n throw new Error('Missing required security fields in offer data \u2013 possible MITM attack');\n }\n \n // Replay attack protection (extended to 30 minutes for better UX)\n const offerAge = Date.now() - timestamp;\n const MAX_OFFER_AGE = 1800000; // 30 minutes for better user experience\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 (support both formats)\n const protocolVersion = version; // Use the version we already extracted\n if (protocolVersion !== EnhancedSecureWebRTCManager.PROTOCOL_VERSION) {\n this._secureLog('warn', 'Protocol version mismatch detected', {\n operationId: operationId,\n expectedVersion: EnhancedSecureWebRTCManager.PROTOCOL_VERSION,\n receivedVersion: protocolVersion\n });\n throw new Error(`Version mismatch: expected protocol ${EnhancedSecureWebRTCManager.PROTOCOL_VERSION}, received ${protocolVersion}`);\n }\n \n // ============================================\n // PHASE 3: EXTRACT AND VALIDATE SESSION SALT\n // ============================================\n \n // Set session salt from offer (support both formats)\n this.sessionSalt = offerData.sl || 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 = 64;\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 (support both formats)\n let peerECDSAPublicKey;\n \n try {\n const ecdsaKey = offerData.d || offerData.ecdsaPublicKey;\n peerECDSAPublicKey = await crypto.subtle.importKey(\n 'spki',\n new Uint8Array(ecdsaKey.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 (support both formats)\n let peerECDHPublicKey;\n \n try {\n const ecdhKey = offerData.e || offerData.ecdhPublicKey;\n peerECDHPublicKey = await window.EnhancedSecureCryptoUtils.importSignedPublicKey(\n ecdhKey,\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 this._secureLog('debug', 'About to call deriveSharedKeys', {\n operationId: operationId,\n privateKeyType: typeof this.ecdhKeyPair.privateKey,\n publicKeyType: typeof peerECDHPublicKey,\n saltLength: this.sessionSalt?.length,\n privateKeyAlgorithm: this.ecdhKeyPair.privateKey?.algorithm?.name,\n publicKeyAlgorithm: peerECDHPublicKey?.algorithm?.name\n });\n \n derivedKeys = await window.EnhancedSecureCryptoUtils.deriveSharedKeys(\n this.ecdhKeyPair.privateKey,\n peerECDHPublicKey,\n this.sessionSalt\n );\n \n this._secureLog('debug', 'deriveSharedKeys completed successfully', {\n operationId: operationId,\n hasMessageKey: !!derivedKeys.messageKey,\n hasMacKey: !!derivedKeys.macKey,\n hasPfsKey: !!derivedKeys.pfsKey,\n hasMetadataKey: !!derivedKeys.metadataKey,\n hasFingerprint: !!derivedKeys.fingerprint\n });\n } catch (error) {\n this._secureLog('error', 'Failed to derive shared keys', {\n operationId: operationId,\n errorType: error.constructor.name,\n errorMessage: error.message,\n errorStack: error.stack,\n privateKeyType: typeof this.ecdhKeyPair.privateKey,\n publicKeyType: typeof peerECDHPublicKey,\n saltLength: this.sessionSalt?.length,\n privateKeyAlgorithm: this.ecdhKeyPair.privateKey?.algorithm?.name,\n publicKeyAlgorithm: peerECDHPublicKey?.algorithm?.name\n });\n this._throwSecureError(error, 'key_derivation');\n }\n \n // Securely set keys via helper\n await this._setEncryptionKeys(\n derivedKeys.messageKey,\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 // Preserve the invitation code only as a temporary legacy field.\n // The real SAS is recomputed locally after the DTLS fingerprints exist.\n this.verificationCode = offerData.vc || offerData.verificationCode || null;\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 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 await 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.s || 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', '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(`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 // Compute the same SAS locally on the answer side. This keeps the\n // protocol honest: the peer may announce its SAS later, but it must\n // match what we independently derived from the session.\n try {\n const remoteFP = this._extractDTLSFingerprintFromSDP(offerData.s || offerData.sdp);\n const localFP = this.expectedDTLSFingerprint;\n const keyBytes = this._decodeKeyFingerprint(this.keyFingerprint);\n this.verificationCode = await this._computeSAS(keyBytes, localFP, remoteFP);\n this.onStatusChange?.('verifying');\n this.onVerificationRequired(this.verificationCode);\n } catch (sasError) {\n this._secureLog('error', 'SAS computation failed in createSecureAnswer (Answer side)', {\n errorType: sasError?.constructor?.name || 'Unknown'\n });\n throw new Error(`SAS computation failed: ${sasError.message}`);\n }\n \n \n // Await ICE gathering\n await this.waitForIceGathering();\n \n this._secureLog('debug', '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 // All security features are enabled by default\n const securityLevel = {\n level: 'MAXIMUM',\n score: 100,\n color: 'green',\n details: 'All security features enabled by default',\n passedChecks: 10,\n totalChecks: 10,\n isRealData: true\n };\n \n // ============================================\n // PHASE 14: CREATE ANSWER PACKAGE\n // ============================================\n \n const currentTimestamp = Date.now();\n \n // Create compact answer package for smaller QR codes\n const answerPackage = {\n // Core information (minimal)\n t: 'answer', // type\n s: this.peerConnection.localDescription.sdp, // sdp\n v: EnhancedSecureWebRTCManager.PROTOCOL_VERSION, // version\n ts: currentTimestamp, // timestamp\n \n // Cryptographic keys (essential)\n e: ecdhPublicKeyData, // ecdhPublicKey\n d: ecdsaPublicKeyData, // ecdsaPublicKey\n \n // Authentication (essential)\n ap: authProof, // authProof\n \n // Security metadata (simplified)\n slv: 'MAX', // securityLevel\n \n // Session confirmation (simplified)\n sc: {\n sf: saltFingerprint.substring(0, 12), // saltFingerprint (12 chars)\n kd: true, // keyDerivationSuccess\n ma: true // mutualAuthEnabled\n }\n };\n \n // ============================================\n // PHASE 15: VALIDATION AND LOGGING\n // ============================================\n \n // Final validation of the answer package (support both formats)\n const hasSDP = answerPackage.s || answerPackage.sdp;\n const hasECDH = answerPackage.e || answerPackage.ecdhPublicKey;\n const hasECDSA = answerPackage.d || answerPackage.ecdsaPublicKey;\n \n if (!hasSDP || !hasECDH || !hasECDSA) {\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', 'Post-connection security level calculated', {\n operationId: operationId,\n level: realSecurityData.level\n });\n }\n } catch (error) {\n this._secureLog('error', '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', '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', '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 // Schedule natural cleanup\n this._forceGarbageCollection().catch(error => {\n this._secureLog('error', 'Cleanup failed during answer cleanup', {\n errorType: error?.constructor?.name || 'Unknown'\n });\n });\n \n this._secureLog('debug', 'Failed answer creation cleanup completed with secure memory wipe');\n \n } catch (cleanupError) {\n this._secureLog('error', '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', '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', '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', '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 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 // Support both compact and legacy answer formats\n const isCompactAnswer = answerData.t === 'answer' && answerData.s;\n const isLegacyAnswer = answerData.type === 'enhanced_secure_answer' && answerData.sdp;\n \n if (!isCompactAnswer && !isLegacyAnswer) {\n this._secureLog('error', 'CRITICAL: Invalid answer format', { \n type: answerData.type || answerData.t,\n hasSdp: !!(answerData.sdp || answerData.s)\n });\n throw new Error('CRITICAL SECURITY FAILURE: Invalid answer format - hard abort required');\n }\n\n const answerVersion = answerData.v || answerData.version;\n if (answerVersion !== EnhancedSecureWebRTCManager.PROTOCOL_VERSION) {\n throw new Error(`Version mismatch: expected protocol ${EnhancedSecureWebRTCManager.PROTOCOL_VERSION}, received ${answerVersion || 'unknown'}`);\n }\n\n // CRITICAL: Strict validation of ECDH public key structure\n // Support both full and compact key names\n const ecdhKey = answerData.ecdhPublicKey || answerData.e;\n const ecdsaKey = answerData.ecdsaPublicKey || answerData.d;\n \n if (!ecdhKey || typeof ecdhKey !== 'object' || Array.isArray(ecdhKey)) {\n this._secureLog('error', 'CRITICAL: Invalid ECDH public key structure in answer', { \n hasEcdhKey: !!ecdhKey,\n ecdhKeyType: typeof ecdhKey,\n isArray: Array.isArray(ecdhKey),\n availableKeys: Object.keys(answerData)\n });\n throw new Error('CRITICAL SECURITY FAILURE: Missing or invalid ECDH public key structure');\n }\n \n if (!ecdhKey.keyData || !ecdhKey.signature) {\n this._secureLog('error', 'CRITICAL: ECDH key missing keyData or signature in answer', { \n hasKeyData: !!ecdhKey.keyData,\n hasSignature: !!ecdhKey.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 (!ecdsaKey || typeof ecdsaKey !== 'object' || Array.isArray(ecdsaKey)) {\n this._secureLog('error', 'CRITICAL: Invalid ECDSA public key structure in answer', { \n hasEcdsaKey: !!ecdsaKey,\n ecdsaKeyType: typeof ecdsaKey,\n isArray: Array.isArray(ecdsaKey)\n });\n throw new Error('CRITICAL SECURITY FAILURE: Missing or invalid ECDSA public key structure');\n }\n \n if (!ecdsaKey.keyData || !ecdsaKey.signature) {\n this._secureLog('error', 'CRITICAL: ECDSA key missing keyData or signature in answer', { \n hasKeyData: !!ecdsaKey.keyData,\n hasSignature: !!ecdsaKey.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 // Support both compact and legacy formats\n const timestamp = answerData.ts || answerData.timestamp;\n const version = answerData.v || answerData.version;\n \n if (!timestamp || !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 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(ecdsaKey.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 ecdhKey,\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.messageKey;\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 const remoteFP = this._extractDTLSFingerprintFromSDP(answerData.sdp || answerData.s); \n const localFP = this.expectedDTLSFingerprint; \n const keyBytes = this._decodeKeyFingerprint(this.keyFingerprint); \n\n this.verificationCode = await this._computeSAS(keyBytes, localFP, remoteFP);\n this.onStatusChange?.('verifying'); \n this.onVerificationRequired(this.verificationCode);\n \n // CRITICAL: Store SAS code to send when data channel opens\n this.pendingSASCode = 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 this._secureLog('error', 'SAS computation failed in handleSecureAnswer (Offer side)', {\n errorType: sasError?.constructor?.name || 'Unknown'\n });\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 || answerData.s);\n \n if (this.expectedDTLSFingerprint) {\n await 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 // Support both full and compact SDP field names\n const sdpData = answerData.sdp || answerData.s;\n \n this._secureLog('debug', 'Setting remote description from answer', {\n sdpLength: sdpData?.length || 0,\n usingCompactSDP: !answerData.sdp && !!answerData.s\n });\n \n await this.peerConnection.setRemoteDescription({\n type: 'answer',\n sdp: sdpData\n });\n \n this._secureLog('debug', 'Remote description set successfully from answer', {\n signalingState: this.peerConnection.signalingState\n });\n\n setTimeout(async () => {\n try {\n const securityData = await this.calculateAndReportSecurityLevel();\n if (securityData) {\n this.notifySecurityUpdate();\n }\n } catch (error) {\n this._secureLog('error', '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 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\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('CRITICAL: Compare verification code with peer out-of-band (voice/video/in-person) to prevent MITM attack!', 'system');\n this.deliverMessageToUI(`Your verification code: ${this.verificationCode}`, 'system');\n this.deliverMessageToUI('Ask peer to confirm this exact code before allowing traffic!', 'system');\n }\n } else {\n\n this.deliverMessageToUI('Waiting for verification code from peer...', 'system');\n }\n }\n\n /**\n * Normalizes and validates the user-entered SAS code.\n * Users may enter the same shared SAS with spaces or hyphens.\n * @param {string} input\n * @returns {boolean}\n */\n _validateSASCode(input) {\n if (!input || typeof input !== 'string' || !this.verificationCode || typeof this.verificationCode !== 'string') {\n return false;\n }\n\n const normalizedInput = input.replace(/[-\\s]/g, '').toUpperCase();\n const normalizedActual = this.verificationCode.replace(/[-\\s]/g, '').toUpperCase();\n\n if (normalizedInput.length !== normalizedActual.length) {\n return false;\n }\n\n return window.EnhancedSecureCryptoUtils.constantTimeCompare(normalizedInput, normalizedActual);\n }\n\n confirmVerification(userCode) {\n \n try {\n if (!this._validateSASCode(userCode)) {\n this.sasValidationAttempts = (this.sasValidationAttempts || 0) + 1;\n this._secureLog('warn', 'SAS validation failed: user entered incorrect code', {\n attempts: this.sasValidationAttempts,\n maxAttempts: EnhancedSecureWebRTCManager.MAX_SAS_ATTEMPTS\n });\n\n if (this.sasValidationAttempts >= EnhancedSecureWebRTCManager.MAX_SAS_ATTEMPTS) {\n this.deliverMessageToUI('Verification failed 3 times. Session reset for safety.', 'system');\n this.disconnect();\n throw new Error('SAS_MAX_ATTEMPTS');\n }\n\n throw new Error('SAS_MISMATCH');\n }\n \n // Mark local verification as confirmed\n this.localVerificationConfirmed = true;\n this.sasValidationAttempts = 0;\n \n // Send confirmation to peer\n const confirmationPayload = {\n type: 'verification_confirmed',\n data: {\n timestamp: Date.now(),\n verificationMethod: 'MANUAL_SAS_ENTRY',\n securityLevel: 'MITM_PROTECTION_REQUIRED'\n }\n };\n\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('Code verified locally. Waiting for peer confirmation...', 'system');\n \n this.processMessageQueue();\n } catch (error) {\n if (error.message === 'SAS_MISMATCH') {\n this.deliverMessageToUI('Verification failed: the code you entered is incorrect.', 'system');\n } else if (error.message !== 'SAS_MAX_ATTEMPTS') {\n this._secureLog('error', 'SAS verification failed:', { errorType: error?.constructor?.name || 'Unknown' });\n this.deliverMessageToUI('SAS verification failed', 'system');\n }\n throw error;\n }\n }\n\n _checkBothVerificationsConfirmed() {\n // Check if both parties have confirmed verification\n if (this.localVerificationConfirmed && this.remoteVerificationConfirmed && !this.bothVerificationsConfirmed) {\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 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('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 this.remoteVerificationConfirmed = true;\n \n // Notify UI about peer confirmation\n this.deliverMessageToUI('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 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('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 \n if (data.code === this.verificationCode) {\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('SAS verification successful! MITM protection confirmed. Channel is now secure!', 'system');\n }\n \n this.processMessageQueue();\n } else {\n // SAS verification failed - possible MITM attack\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('SAS verification failed! Possible MITM attack detected. Connection aborted for safety!', 'system');\n this.disconnect();\n }\n }\n\n handleSASCode(data) {\n if (!data?.code || typeof data.code !== 'string') {\n this._secureLog('warn', 'Invalid SAS announcement received from peer');\n return;\n }\n\n if (this.verificationCode && !this._validateSASCode(data.code)) {\n this._secureLog('error', 'Peer-announced SAS does not match locally computed SAS');\n this.deliverMessageToUI('Version or SAS mismatch detected. Connection aborted for safety.', 'system');\n this.disconnect();\n return;\n }\n\n this.verificationCode = data.code;\n this.onStatusChange?.('verifying'); \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(' Mutual SAS verification complete! MITM protection active. Channel is now secure!', 'system');\n }\n \n this.processMessageQueue();\n } else {\n // 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('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 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 will be validated after format detection\n\n // Check if this is v4.0 compact format or legacy format\n const isV4CompactFormat = offerData.v === EnhancedSecureWebRTCManager.PROTOCOL_VERSION && offerData.e && offerData.d;\n const isV4Format = offerData.version === EnhancedSecureWebRTCManager.PROTOCOL_VERSION && offerData.ecdhPublicKey && offerData.ecdsaPublicKey;\n \n // Validate offer type (support compact, legacy v3.0 and v4.0 formats)\n const isValidType = isV4CompactFormat ? \n ['offer'].includes(offerData.t) :\n ['enhanced_secure_offer', 'secure_offer'].includes(offerData.type);\n \n if (!isValidType) {\n throw new Error('Invalid offer type');\n }\n \n if (isV4CompactFormat) {\n // v4.1 compact format validation\n const compactRequiredFields = [\n 'e', 'd', 'sl', 'vc', 'si', 'ci', 'ac', 'slv'\n ];\n \n for (const field of compactRequiredFields) {\n if (!offerData[field]) {\n throw new Error(`Missing required v4.1 compact field: ${field}`);\n }\n }\n \n // Validate key structures\n if (!offerData.e || typeof offerData.e !== 'object' || Array.isArray(offerData.e)) {\n throw new Error('CRITICAL SECURITY FAILURE: Invalid ECDH public key structure');\n }\n \n if (!offerData.d || typeof offerData.d !== 'object' || Array.isArray(offerData.d)) {\n throw new Error('CRITICAL SECURITY FAILURE: Invalid ECDSA public key structure');\n }\n \n // Validate salt length\n if (!Array.isArray(offerData.sl) || offerData.sl.length !== 64) {\n throw new Error('Salt must be exactly 64 bytes for v4.1');\n }\n \n // Validate verification code format\n if (typeof offerData.vc !== 'string' || offerData.vc.length < 6) {\n throw new Error('Invalid verification code format');\n }\n \n // Validate security level\n if (!['MAX', 'HIGH', 'MED', 'LOW'].includes(offerData.slv)) {\n throw new Error('Invalid security level');\n }\n \n // Validate timestamp (not older than 1 hour)\n const offerAge = Date.now() - offerData.ts;\n if (offerAge > 3600000) {\n throw new Error('Offer is too old (older than 1 hour)');\n }\n \n this._secureLog('info', 'v4.1 compact offer validation passed', {\n version: offerData.v,\n hasECDH: !!offerData.e,\n hasECDSA: !!offerData.d,\n hasSalt: !!offerData.sl,\n hasVerificationCode: !!offerData.vc,\n securityLevel: offerData.slv,\n offerAge: Math.round(offerAge / 1000) + 's'\n });\n } else if (isV4Format) {\n // v4.1 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.1 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.1');\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.1 offer validation passed', {\n version: offerData.version,\n hasSecurityLevel: !!offerData.securityLevel?.level,\n offerAge: Math.round(offerAge / 1000) + 's'\n });\n } else {\n const receivedVersion = offerData.v || offerData.version || 'unknown';\n throw new Error(`Version mismatch: expected protocol ${EnhancedSecureWebRTCManager.PROTOCOL_VERSION}, received ${receivedVersion}`);\n }\n\n // Validate SDP structure (basic check for all versions)\n const sdp = isV4CompactFormat ? offerData.s : offerData.sdp;\n if (typeof sdp !== 'string' || !sdp.includes('v=0')) {\n throw new Error('Invalid SDP structure');\n }\n\n return true;\n } catch (error) {\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', '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 // Note: master key session is managed by SecureMasterKeyManager\n // Do not gate here on _isUnlocked to avoid false blocking\n // Session timers are handled inside the master key manager on key access\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', 'Secure message sent successfully', {\n operationId: operationId,\n messageLength: sanitizedMessage.length,\n keyVersion: this.currentKeyVersion\n });\n \n } catch (error) {\n this._secureLog('error', 'Secure message sending failed', {\n operationId: operationId,\n errorType: error.constructor.name\n });\n \n // Improved user-facing error messages (English)\n if (error.message.includes('Session expired')) {\n throw new Error('Session expired. Please enter your password to unlock.');\n } else if (error.message.includes('Encryption keys not initialized')) {\n throw new Error('Session expired due to inactivity. Please reconnect to the chat.');\n } else if (error.message.includes('Connection lost')) {\n throw new Error('Connection lost. Please check your Internet connection.');\n } else if (error.message.includes('Rate limit exceeded')) {\n throw new Error('Message rate limit exceeded. Please wait before sending another message.');\n } else {\n throw error;\n }\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', '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', '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) {\n clearInterval(timer);\n clearTimeout(timer);\n }\n });\n this._activeTimers.clear();\n }\n\n if (this._fileTransferInitRetryTimers) {\n this._fileTransferInitRetryTimers.clear();\n }\n this._logCleanupInterval = null;\n \n this._secureLog('info', 'All timers stopped successfully');\n }\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 this._secureLog('info', 'Retrying connection', {\n attempt: this.connectionAttempts,\n maxAttempts: this.maxConnectionAttempts\n });\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 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 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('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(`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 if (!this._peerDisconnectCleanupTimer) {\n this._peerDisconnectCleanupTimer = this._trackActiveTimer(setTimeout(() => {\n const timer = this._peerDisconnectCleanupTimer;\n this._peerDisconnectCleanupTimer = null;\n this._untrackActiveTimer(timer);\n if (this._sessionAlive === false) return;\n this.disconnect();\n }, 2000));\n }\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 try {\n this._sessionAlive = false;\n\n // Preserve the explicit-disconnect notification flow before channels are closed.\n this.intentionalDisconnect = true;\n window.EnhancedSecureCryptoUtils.secureLog.log('info', 'Starting intentional disconnect');\n this.sendDisconnectNotification();\n setTimeout(() => {\n this.sendDisconnectNotification();\n }, 100);\n\n // Stop every timer-backed subsystem first.\n this._stopAllTimers();\n this._peerDisconnectCleanupTimer = null;\n this.stopHeartbeat();\n this.stopFakeTrafficGeneration();\n for (const timer of this.decoyTimers.entries()) {\n clearTimeout(timer[1]);\n }\n this.decoyTimers.clear();\n\n // Pending file transfers must not survive a disconnect.\n if (this.fileTransferSystem) {\n this.fileTransferSystem.cleanup();\n this.fileTransferSystem = null;\n }\n\n // Close auxiliary channels alongside the primary channel.\n for (const channel of this.decoyChannels.values()) {\n if (channel.readyState === 'open') channel.close();\n }\n this.decoyChannels.clear();\n if (this.heartbeatChannel) {\n this.heartbeatChannel.close();\n this.heartbeatChannel = null;\n }\n\n // Reset transport-independent state.\n this.isVerified = false;\n this.processedMessageIds.clear();\n this.messageCounter = 0;\n this.packetBuffer.clear();\n this.chunkQueue = [];\n\n // Preserve all key/material cleanup from the former implementations.\n this._wipeEphemeralKeys();\n this._hardWipeOldKeys();\n this._secureCleanupCryptographicMaterials();\n this.keyVersions.clear();\n this.oldKeys.clear();\n this.currentKeyVersion = 0;\n this.lastKeyRotation = Date.now();\n this.sequenceNumber = 0;\n this.expectedSequenceNumber = 0;\n this.replayWindow.clear();\n this._clearVerificationStates();\n\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 live transports, then release their listeners/references.\n if (this.dataChannel) {\n this.dataChannel.close();\n this.dataChannel.onopen = null;\n this.dataChannel.onclose = null;\n this.dataChannel.onmessage = null;\n this.dataChannel.onerror = null;\n this.dataChannel = null;\n }\n if (this.peerConnection) {\n this.peerConnection.close();\n this.peerConnection.onconnectionstatechange = null;\n this.peerConnection.ondatachannel = null;\n this.peerConnection = null;\n }\n\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 this._forceGarbageCollection().catch(error => {\n this._secureLog('error', 'Cleanup failed during disconnect', {\n errorType: error?.constructor?.name || 'Unknown'\n });\n });\n\n document.dispatchEvent(new CustomEvent('peer-disconnect', {\n detail: {\n reason: 'user_disconnect',\n timestamp: Date.now()\n }\n }));\n document.dispatchEvent(new CustomEvent('connection-cleaned', {\n detail: {\n timestamp: Date.now(),\n reason: 'user_cleanup'\n }\n }));\n\n this.onStatusChange('disconnected');\n this.onKeyExchange('');\n this.onVerificationRequired('');\n this._secureLog('info', 'Connection securely cleaned up with complete memory wipe');\n } catch (error) {\n this._secureLog('error', '\u274C Error during enhanced disconnect:', {\n errorType: error?.constructor?.name || 'Unknown'\n });\n } finally {\n this.intentionalDisconnect = false;\n }\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 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\n try {\n const fileId = await this.fileTransferSystem.sendFile(file);\n return fileId;\n } catch (error) {\n this._secureLog('error', '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('Session expired due to inactivity. Please reconnect to the chat.');\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', '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', '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', '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 this._secureLog('info', '\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 if (this.fileTransferSystem) {\n this.fileTransferSystem.cleanup();\n }\n this.initializeFileTransfer();\n return true;\n } catch (error) {\n this._secureLog('error', '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, onIncomingRequest = null) {\n this.onFileProgress = onProgress;\n this.onFileReceived = onReceived;\n this.onFileError = onError;\n this.onIncomingFileRequest = onIncomingRequest;\n \n // Propagate callback updates into the live transfer system.\n if (this.fileTransferSystem) {\n this.fileTransferSystem.onProgress = onProgress;\n this.fileTransferSystem.onFileReceived = onReceived;\n this.fileTransferSystem.onError = onError;\n this.fileTransferSystem.onIncomingFileRequest = onIncomingRequest;\n }\n }\n\n getPendingIncomingFiles() {\n if (!this.fileTransferSystem) return [];\n return this.fileTransferSystem.getPendingIncomingTransfers();\n }\n\n async acceptIncomingFile(fileId) {\n if (!this.fileTransferSystem) return false;\n return this.fileTransferSystem.acceptIncomingFile(fileId);\n }\n\n async rejectIncomingFile(fileId) {\n if (!this.fileTransferSystem) return false;\n return this.fileTransferSystem.rejectIncomingFile(fileId);\n }\n\n // ============================================\n // SESSION ACTIVATION HANDLING\n // ============================================\n\n async handleSessionActivation(sessionData) {\n try {\n \n // Update session state\n this.currentSession = sessionData;\n \n // FIX: More lenient checks for activation\n const hasKeys = !!(this.encryptionKey && this.macKey);\n const hasSession = !!(sessionData.sessionId);\n \n // Force connection status if there is an active session\n if (hasSession) {\n this.onStatusChange('connected');\n\n }\n\n setTimeout(() => {\n try {\n this.initializeFileTransfer();\n } catch (error) {\n this._secureLog('warn', 'File transfer initialization failed during session activation:', { details: error.message });\n }\n }, 1000);\n \n \n if (this.fileTransferSystem && this.isConnected()) {\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', '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 return status;\n }\n\n // Method to force re-initialize file transfer system\n forceReinitializeFileTransfer() {\n try {\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', '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', 'File transfer initialization cancelled by user');\n return { cancelled: true };\n }\n \n this._secureLog('error', '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', 'File transfer initialization cancelled');\n return true;\n }\n return false;\n } catch (error) {\n this._secureLog('error', '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', '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', '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', 'CRITICAL: IV tracking system not working properly');\n return false;\n }\n \n this._secureLog('info', 'Nested encryption security validation passed - secure IV generation working');\n return true;\n } catch (error) {\n this._secureLog('error', '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(masterKeyManager = null) {\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 // Use secure master key manager instead of global key\n this._masterKeyManager = masterKeyManager || new SecureMasterKeyManager();\n \n // Initialize persistent storage for extractable keys\n this._persistentStorage = new SecurePersistentKeyStorage(this._masterKeyManager);\n \n // Setup master key manager callbacks\n this._setupMasterKeyCallbacks();\n\n setTimeout(() => {\n if (!this.validateStorageIntegrity()) {\n this._secureLog('error', 'CRITICAL: Key storage integrity check failed');\n }\n }, 100);\n \n }\n\n /**\n * Setup callbacks for master key manager\n */\n _setupMasterKeyCallbacks() {\n // Set default password callback (can be overridden)\n this._masterKeyManager.setPasswordRequiredCallback((isRetry, callback) => {\n // Default implementation - should be overridden by application\n const password = prompt(isRetry ? \n 'Incorrect password. Please enter your master password:' : \n 'Please enter your master password to unlock secure storage:'\n );\n callback(password);\n });\n \n this._masterKeyManager.setSessionExpiredCallback((reason) => {\n console.warn(`Master key session expired: ${reason}`);\n // Application should handle this event\n });\n \n this._masterKeyManager.setUnlockedCallback(() => {\n console.log('Master key unlocked successfully');\n });\n }\n \n /**\n * Set custom password callback\n */\n setPasswordCallback(callback) {\n this._masterKeyManager.setPasswordRequiredCallback(callback);\n }\n \n /**\n * Set custom session expired callback\n */\n setSessionExpiredCallback(callback) {\n this._masterKeyManager.setSessionExpiredCallback(callback);\n }\n \n /**\n * Get master key (with automatic unlock if needed)\n */\n async _ensureMasterKeyUnlocked() {\n if (!this._masterKeyManager.isUnlocked()) {\n await this._masterKeyManager.unlock();\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, store only in-memory reference\n if (!cryptoKey.extractable) {\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 persistent: false,\n encrypted: false\n });\n return true;\n }\n\n // For extractable keys, use persistent storage with encryption\n await this._persistentStorage.storeExtractableKey(keyId, cryptoKey, metadata);\n \n // Also store in memory for immediate access\n this._keyReferences.set(keyId, cryptoKey);\n this._keyMetadata.set(keyId, {\n ...metadata,\n created: Date.now(),\n lastAccessed: Date.now(),\n extractable: true,\n persistent: true,\n encrypted: true\n });\n\n return true;\n \n } catch (error) {\n this._secureLog('error', 'Failed to store key securely', {\n errorType: error?.constructor?.name || 'Unknown'\n });\n return false;\n }\n }\n\n async retrieveKey(keyId) {\n try {\n // Check if key is in memory first\n if (this._keyReferences.has(keyId)) {\n const metadata = this._keyMetadata.get(keyId);\n if (metadata) {\n metadata.lastAccessed = Date.now();\n }\n return this._keyReferences.get(keyId);\n }\n \n // Try to restore from persistent storage\n const restoredKey = await this._persistentStorage.retrieveKey(keyId);\n if (restoredKey) {\n // Update memory cache\n this._keyReferences.set(keyId, restoredKey);\n \n // Update or create metadata\n const existingMetadata = this._keyMetadata.get(keyId);\n this._keyMetadata.set(keyId, {\n ...existingMetadata,\n lastAccessed: Date.now(),\n restoredFromPersistent: true\n });\n \n return restoredKey;\n }\n \n return null;\n \n } catch (error) {\n this._secureLog('error', 'Failed to retrieve key', {\n errorType: error?.constructor?.name || 'Unknown'\n });\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 await this._ensureMasterKeyUnlocked();\n const { encryptedData, iv } = await this._masterKeyManager.encryptBytes(data);\n // Return IV + encrypted data\n const result = new Uint8Array(iv.length + encryptedData.byteLength);\n result.set(iv, 0);\n result.set(encryptedData, iv.length);\n return result;\n }\n\n async _decryptKeyData(encryptedData) {\n const iv = encryptedData.slice(0, 12);\n const data = encryptedData.slice(12);\n \n await this._ensureMasterKeyUnlocked();\n const decryptedData = await this._masterKeyManager.decryptBytes(data, iv);\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 async 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 // Schedule natural cleanup\n await this._performNaturalCleanup();\n }\n\n async secureWipeAll() {\n // Clear persistent storage\n try {\n await this._persistentStorage.clearAll();\n } catch (error) {\n this._secureLog('error', 'Failed to clear persistent storage', {\n errorType: error?.constructor?.name || 'Unknown'\n });\n }\n \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 // Schedule natural cleanup\n await this._performNaturalCleanup();\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 this._secureLog('error', 'Storage integrity violations detected', {\n violationCount: violations.length\n });\n return false;\n }\n \n return true;\n }\n\n async getStorageStats() {\n const persistentStats = await this._persistentStorage.getStorageStats();\n \n return {\n totalKeys: this._keyReferences.size,\n memoryKeys: this._keyReferences.size,\n persistentKeys: persistentStats.persistentKeys,\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 persistent: meta.persistent || false\n })),\n persistent: persistentStats\n };\n }\n \n /**\n * List all stored keys (memory + persistent)\n */\n async listAllKeys() {\n try {\n const memoryKeys = Array.from(this._keyMetadata.entries()).map(([keyId, metadata]) => ({\n keyId,\n ...metadata,\n location: 'memory'\n }));\n \n const persistentKeys = await this._persistentStorage.listStoredKeys();\n const persistentKeysFormatted = persistentKeys.map(key => ({\n ...key,\n location: 'persistent'\n }));\n \n return {\n memoryKeys,\n persistentKeys: persistentKeysFormatted,\n totalCount: memoryKeys.length + persistentKeysFormatted.length\n };\n \n } catch (error) {\n this._secureLog('error', 'Failed to list keys', {\n errorType: error?.constructor?.name || 'Unknown'\n });\n return {\n memoryKeys: [],\n persistentKeys: [],\n totalCount: 0,\n error: error.message\n };\n }\n }\n \n /**\n * Delete key from both memory and persistent storage\n */\n async deleteKey(keyId) {\n try {\n // Remove from memory\n this._keyReferences.delete(keyId);\n this._keyMetadata.delete(keyId);\n \n // Remove from persistent storage\n await this._persistentStorage.deleteKey(keyId);\n \n return true;\n \n } catch (error) {\n this._secureLog('error', 'Failed to delete key', {\n errorType: error?.constructor?.name || 'Unknown'\n });\n return false;\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', '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', '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', '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', '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', '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 * Get real security level with actual cryptographic tests\n * This provides real-time verification of security features\n */\n async getRealSecurityLevel() {\n try {\n const securityData = {\n // Basic security features\n ecdhKeyExchange: !!this.ecdhKeyPair,\n ecdsaSignatures: !!this.ecdsaKeyPair,\n aesEncryption: !!this.encryptionKey,\n messageIntegrity: !!this.hmacKey,\n \n // Advanced security features - using the exact property names expected by EnhancedSecureCryptoUtils\n replayProtection: this.replayProtectionEnabled,\n dtlsFingerprint: !!this.expectedDTLSFingerprint,\n sasCode: !!this.verificationCode,\n metadataProtection: true, // Always enabled\n trafficObfuscation: true, // Always enabled\n perfectForwardSecrecy: true, // Always enabled\n \n // Rate limiting\n rateLimiter: true, // Always enabled\n \n // Additional info\n connectionId: this.connectionId,\n keyFingerprint: this.keyFingerprint,\n currentSecurityLevel: 'maximum',\n timestamp: Date.now()\n };\n\n \n this._secureLog('info', 'Real security level calculated', securityData);\n return securityData;\n } catch (error) {\n this._secureLog('error', 'Failed to calculate real security level', { error: error.message });\n throw error;\n }\n }\n\n\n}\n\n/**\n * Secure IndexedDB Wrapper for Encrypted Key Storage\n * Provides secure persistent storage with encryption\n */\nclass SecureIndexedDBWrapper {\n constructor(dbName = 'SecureKeyStorage', version = 1) {\n this.dbName = dbName;\n this.version = version;\n this.db = null;\n \n // Store names\n this.KEYS_STORE = 'encrypted_keys';\n this.METADATA_STORE = 'key_metadata';\n this.SALT_STORE = 'master_salt';\n }\n \n /**\n * Initialize IndexedDB connection\n */\n async initialize() {\n return new Promise((resolve, reject) => {\n const request = indexedDB.open(this.dbName, this.version);\n \n request.onerror = () => {\n reject(new Error(`Failed to open IndexedDB: ${request.error}`));\n };\n \n request.onsuccess = () => {\n this.db = request.result;\n resolve();\n };\n \n request.onupgradeneeded = (event) => {\n const db = event.target.result;\n \n // Create encrypted keys store\n if (!db.objectStoreNames.contains(this.KEYS_STORE)) {\n const keysStore = db.createObjectStore(this.KEYS_STORE, { keyPath: 'keyId' });\n keysStore.createIndex('timestamp', 'timestamp', { unique: false });\n keysStore.createIndex('algorithm', 'algorithm', { unique: false });\n }\n \n // Create metadata store\n if (!db.objectStoreNames.contains(this.METADATA_STORE)) {\n const metadataStore = db.createObjectStore(this.METADATA_STORE, { keyPath: 'keyId' });\n metadataStore.createIndex('created', 'created', { unique: false });\n metadataStore.createIndex('lastAccessed', 'lastAccessed', { unique: false });\n }\n \n // Create salt store\n if (!db.objectStoreNames.contains(this.SALT_STORE)) {\n db.createObjectStore(this.SALT_STORE, { keyPath: 'id' });\n }\n };\n });\n }\n \n /**\n * Store encrypted key data\n */\n async storeEncryptedKey(keyId, encryptedData, iv, algorithm, usages, type, metadata = {}) {\n if (!this.db) {\n throw new Error('Database not initialized');\n }\n \n const transaction = this.db.transaction([this.KEYS_STORE, this.METADATA_STORE], 'readwrite');\n \n const keyRecord = {\n keyId: keyId,\n encryptedData: Array.from(new Uint8Array(encryptedData)), // Convert to array for storage\n iv: Array.from(new Uint8Array(iv)),\n algorithm: algorithm,\n usages: usages,\n type: type\n };\n \n const metadataRecord = { keyId, ...metadata };\n \n return new Promise((resolve, reject) => {\n const keysRequest = transaction.objectStore(this.KEYS_STORE).put(keyRecord);\n const metadataRequest = transaction.objectStore(this.METADATA_STORE).put(metadataRecord);\n \n transaction.oncomplete = () => resolve();\n transaction.onerror = () => reject(new Error(`Failed to store key: ${transaction.error}`));\n });\n }\n \n /**\n * Retrieve encrypted key data\n */\n async getEncryptedKey(keyId) {\n if (!this.db) {\n throw new Error('Database not initialized');\n }\n \n const transaction = this.db.transaction([this.KEYS_STORE], 'readonly');\n const store = transaction.objectStore(this.KEYS_STORE);\n \n return new Promise((resolve, reject) => {\n const request = store.get(keyId);\n \n request.onsuccess = () => {\n const result = request.result;\n if (result) {\n // Convert arrays back to Uint8Array\n result.encryptedData = new Uint8Array(result.encryptedData);\n result.iv = new Uint8Array(result.iv);\n }\n resolve(result);\n };\n \n request.onerror = () => reject(new Error(`Failed to retrieve key: ${request.error}`));\n });\n }\n \n /**\n * Update key metadata (e.g., last accessed time)\n */\n async updateKeyMetadata(keyId, updates) {\n if (!this.db) {\n throw new Error('Database not initialized');\n }\n \n const transaction = this.db.transaction([this.METADATA_STORE], 'readwrite');\n const store = transaction.objectStore(this.METADATA_STORE);\n \n return new Promise((resolve, reject) => {\n const getRequest = store.get(keyId);\n \n getRequest.onsuccess = () => {\n const metadata = getRequest.result;\n if (metadata) {\n Object.assign(metadata, updates);\n const putRequest = store.put(metadata);\n \n putRequest.onsuccess = () => resolve();\n putRequest.onerror = () => reject(new Error(`Failed to update metadata: ${putRequest.error}`));\n } else {\n reject(new Error(`Key metadata not found: ${keyId}`));\n }\n };\n \n getRequest.onerror = () => reject(new Error(`Failed to get metadata: ${getRequest.error}`));\n });\n }\n\n async getKeyMetadataRecord(keyId) {\n if (!this.db) throw new Error('Database not initialized');\n const transaction = this.db.transaction([this.METADATA_STORE], 'readonly');\n const store = transaction.objectStore(this.METADATA_STORE);\n return new Promise((resolve, reject) => {\n const request = store.get(keyId);\n request.onsuccess = () => resolve(request.result || null);\n request.onerror = () => reject(new Error(`Failed to get metadata: ${request.error}`));\n });\n }\n\n async putKeyMetadataRecord(record) {\n if (!this.db) throw new Error('Database not initialized');\n const transaction = this.db.transaction([this.METADATA_STORE], 'readwrite');\n const store = transaction.objectStore(this.METADATA_STORE);\n return new Promise((resolve, reject) => {\n const request = store.put(record);\n request.onsuccess = () => resolve();\n request.onerror = () => reject(new Error(`Failed to store metadata: ${request.error}`));\n });\n }\n \n /**\n * Delete key and its metadata\n */\n async deleteKey(keyId) {\n if (!this.db) {\n throw new Error('Database not initialized');\n }\n \n const transaction = this.db.transaction([this.KEYS_STORE, this.METADATA_STORE], 'readwrite');\n \n return new Promise((resolve, reject) => {\n const keysRequest = transaction.objectStore(this.KEYS_STORE).delete(keyId);\n const metadataRequest = transaction.objectStore(this.METADATA_STORE).delete(keyId);\n \n transaction.oncomplete = () => resolve();\n transaction.onerror = () => reject(new Error(`Failed to delete key: ${transaction.error}`));\n });\n }\n \n /**\n * List all stored keys\n */\n async listKeys() {\n if (!this.db) {\n throw new Error('Database not initialized');\n }\n \n const transaction = this.db.transaction([this.METADATA_STORE], 'readonly');\n const store = transaction.objectStore(this.METADATA_STORE);\n \n return new Promise((resolve, reject) => {\n const request = store.getAll();\n \n request.onsuccess = () => resolve(request.result);\n request.onerror = () => reject(new Error(`Failed to list keys: ${request.error}`));\n });\n }\n \n /**\n * Store master key salt\n */\n async storeMasterSalt(salt) {\n if (!this.db) {\n throw new Error('Database not initialized');\n }\n \n const transaction = this.db.transaction([this.SALT_STORE], 'readwrite');\n const store = transaction.objectStore(this.SALT_STORE);\n \n const saltRecord = {\n id: 'master_salt',\n salt: Array.from(new Uint8Array(salt))\n };\n \n return new Promise((resolve, reject) => {\n const request = store.put(saltRecord);\n \n request.onsuccess = () => resolve();\n request.onerror = () => reject(new Error(`Failed to store salt: ${request.error}`));\n });\n }\n \n /**\n * Retrieve master key salt\n */\n async getMasterSalt() {\n if (!this.db) {\n throw new Error('Database not initialized');\n }\n \n const transaction = this.db.transaction([this.SALT_STORE], 'readonly');\n const store = transaction.objectStore(this.SALT_STORE);\n \n return new Promise((resolve, reject) => {\n const request = store.get('master_salt');\n \n request.onsuccess = () => {\n const result = request.result;\n if (result) {\n resolve(new Uint8Array(result.salt));\n } else {\n resolve(null);\n }\n };\n \n request.onerror = () => reject(new Error(`Failed to retrieve salt: ${request.error}`));\n });\n }\n \n /**\n * Clear all data (for security wipe)\n */\n async clearAll() {\n if (!this.db) {\n throw new Error('Database not initialized');\n }\n \n const transaction = this.db.transaction([this.KEYS_STORE, this.METADATA_STORE, this.SALT_STORE], 'readwrite');\n \n return new Promise((resolve, reject) => {\n const keysRequest = transaction.objectStore(this.KEYS_STORE).clear();\n const metadataRequest = transaction.objectStore(this.METADATA_STORE).clear();\n const saltRequest = transaction.objectStore(this.SALT_STORE).clear();\n \n transaction.oncomplete = () => resolve();\n transaction.onerror = () => reject(new Error(`Failed to clear database: ${transaction.error}`));\n });\n }\n \n /**\n * Close database connection\n */\n close() {\n if (this.db) {\n this.db.close();\n this.db = null;\n }\n }\n}\n\n/**\n * Secure Persistent Key Storage with Key Wrapping\n * Implements secure storage of extractable keys using AES-GCM encryption\n */\nclass SecurePersistentKeyStorage {\n constructor(masterKeyManager, indexedDBWrapper = null) {\n this._masterKeyManager = masterKeyManager;\n this._indexedDB = indexedDBWrapper || new SecureIndexedDBWrapper();\n this._dbInitialized = false;\n \n // In-memory cache for restored keys (WeakMap for automatic cleanup)\n this._keyCache = new WeakMap();\n this._keyReferences = new Map(); // Strong references for active keys\n }\n \n /**\n * Initialize IndexedDB if not already done\n */\n async _ensureDBInitialized() {\n if (!this._dbInitialized) {\n await this._indexedDB.initialize();\n this._dbInitialized = true;\n }\n }\n\n async _ensureMasterKeyUnlocked() {\n if (typeof this._masterKeyManager.isUnlocked === 'function' && !this._masterKeyManager.isUnlocked()) {\n await this._masterKeyManager.unlock();\n }\n }\n \n /**\n * Store extractable key with encryption\n */\n async storeExtractableKey(keyId, cryptoKey, metadata = {}) {\n if (!(cryptoKey instanceof CryptoKey)) {\n throw new Error('Only CryptoKey objects can be stored');\n }\n \n if (!cryptoKey.extractable) {\n throw new Error('Key must be extractable for persistent storage');\n }\n \n try {\n await this._ensureDBInitialized();\n \n // Export key to JWK\n const jwkData = await crypto.subtle.exportKey('jwk', cryptoKey);\n \n // Encrypt JWK data\n const { encryptedData, iv } = await this._encryptKeyData(jwkData);\n \n // Store encrypted data in IndexedDB\n const encryptedMetadata = await this._encryptMetadata({\n ...metadata,\n created: Date.now(),\n lastAccessed: Date.now(),\n extractable: true,\n persistent: true\n });\n\n await this._indexedDB.storeEncryptedKey(\n keyId,\n encryptedData,\n iv,\n cryptoKey.algorithm,\n cryptoKey.usages,\n cryptoKey.type,\n encryptedMetadata\n );\n \n // Store non-extractable reference in memory cache\n const nonExtractableKey = await this._importAsNonExtractable(jwkData, cryptoKey.algorithm, cryptoKey.usages);\n this._keyReferences.set(keyId, nonExtractableKey);\n \n return true;\n \n } catch (error) {\n throw new Error(`Failed to store extractable key: ${error.message}`);\n }\n }\n \n /**\n * Retrieve and restore key from persistent storage\n */\n async retrieveKey(keyId) {\n try {\n // Check if key is already in memory cache\n if (this._keyReferences.has(keyId)) {\n return this._keyReferences.get(keyId);\n }\n \n await this._ensureDBInitialized();\n \n // Get encrypted key data from IndexedDB\n const keyRecord = await this._indexedDB.getEncryptedKey(keyId);\n if (!keyRecord) {\n return null;\n }\n \n // Decrypt JWK data\n const jwkData = await this._decryptKeyData(keyRecord.encryptedData, keyRecord.iv);\n \n // Import as non-extractable key\n const restoredKey = await this._importAsNonExtractable(jwkData, keyRecord.algorithm, keyRecord.usages);\n \n // Cache in memory\n this._keyReferences.set(keyId, restoredKey);\n \n // Update last accessed time\n await this._updateEncryptedMetadata(keyId, { lastAccessed: Date.now() });\n \n return restoredKey;\n \n } catch (error) {\n throw new Error(`Failed to retrieve key: ${error.message}`);\n }\n }\n \n /**\n * Delete key from persistent storage\n */\n async deleteKey(keyId) {\n try {\n await this._ensureDBInitialized();\n \n // Remove from IndexedDB\n await this._indexedDB.deleteKey(keyId);\n \n // Remove from memory cache\n this._keyReferences.delete(keyId);\n \n return true;\n \n } catch (error) {\n throw new Error(`Failed to delete key: ${error.message}`);\n }\n }\n \n /**\n * List all stored keys\n */\n async listStoredKeys() {\n try {\n await this._ensureDBInitialized();\n const records = await this._indexedDB.listKeys();\n const results = [];\n for (const record of records) {\n const metadata = await this._readMetadataWithMigration(record);\n if (metadata) results.push({ keyId: record.keyId, ...metadata });\n }\n return results;\n } catch (error) {\n throw new Error(`Failed to list keys: ${error.message}`);\n }\n }\n \n /**\n * Clear all persistent storage\n */\n async clearAll() {\n try {\n await this._ensureDBInitialized();\n \n // Clear IndexedDB\n await this._indexedDB.clearAll();\n \n // Clear memory cache\n this._keyReferences.clear();\n \n return true;\n \n } catch (error) {\n throw new Error(`Failed to clear storage: ${error.message}`);\n }\n }\n \n /**\n * Encrypt key data using master key\n */\n async _encryptKeyData(jwkData) {\n // Convert JWK to JSON string and then to bytes\n const jsonString = JSON.stringify(jwkData);\n const data = new TextEncoder().encode(jsonString);\n \n await this._ensureMasterKeyUnlocked();\n return await this._masterKeyManager.encryptBytes(data);\n }\n \n /**\n * Decrypt key data using master key\n */\n async _decryptKeyData(encryptedData, iv) {\n await this._ensureMasterKeyUnlocked();\n const decryptedData = await this._masterKeyManager.decryptBytes(encryptedData, iv);\n \n // Convert back to JWK\n const jsonString = new TextDecoder().decode(decryptedData);\n return JSON.parse(jsonString);\n }\n\n async _encryptMetadata(metadata) {\n const data = new TextEncoder().encode(JSON.stringify(metadata));\n await this._ensureMasterKeyUnlocked();\n const { encryptedData, iv } = await this._masterKeyManager.encryptBytes(data);\n return {\n metadataVersion: 1,\n encryptedMetadata: Array.from(encryptedData),\n metadataIv: Array.from(iv)\n };\n }\n\n async _decryptMetadataRecord(record) {\n if (!record?.encryptedMetadata || !record?.metadataIv) {\n throw new Error('Encrypted metadata missing');\n }\n await this._ensureMasterKeyUnlocked();\n const decrypted = await this._masterKeyManager.decryptBytes(\n new Uint8Array(record.encryptedMetadata),\n new Uint8Array(record.metadataIv)\n );\n return JSON.parse(new TextDecoder().decode(decrypted));\n }\n\n async _readMetadataWithMigration(record) {\n if (!record) return null;\n if (record.encryptedMetadata) {\n try {\n return await this._decryptMetadataRecord(record);\n } catch (error) {\n // Corrupted encrypted metadata must not be exposed or trusted.\n return null;\n }\n }\n\n // Legacy plaintext record: read once, then migrate to encrypted envelope.\n const { keyId, ...legacyMetadata } = record;\n const encryptedRecord = { keyId, ...(await this._encryptMetadata(legacyMetadata)) };\n await this._indexedDB.putKeyMetadataRecord(encryptedRecord);\n return legacyMetadata;\n }\n\n async _updateEncryptedMetadata(keyId, updates) {\n const record = await this._indexedDB.getKeyMetadataRecord(keyId);\n if (!record) throw new Error(`Key metadata not found: ${keyId}`);\n const current = await this._readMetadataWithMigration(record);\n if (!current) throw new Error(`Key metadata corrupted: ${keyId}`);\n await this._indexedDB.putKeyMetadataRecord({\n keyId,\n ...(await this._encryptMetadata({ ...current, ...updates }))\n });\n }\n \n /**\n * Import JWK as non-extractable key\n */\n async _importAsNonExtractable(jwkData, algorithm, usages) {\n return await crypto.subtle.importKey(\n 'jwk',\n jwkData,\n algorithm,\n false, // non-extractable for security\n usages\n );\n }\n \n /**\n * Get storage statistics\n */\n async getStorageStats() {\n try {\n await this._ensureDBInitialized();\n const keys = await this._indexedDB.listKeys();\n \n return {\n totalKeys: keys.length,\n memoryKeys: this._keyReferences.size,\n persistentKeys: keys.length,\n lastAccessed: keys.reduce((latest, key) => \n Math.max(latest, key.lastAccessed || 0), 0)\n };\n \n } catch (error) {\n return {\n totalKeys: 0,\n memoryKeys: this._keyReferences.size,\n persistentKeys: 0,\n lastAccessed: 0,\n error: error.message\n };\n }\n }\n}\n\n/**\n * Secure Master Key Manager with Password-Based Derivation\n * Implements PBKDF2-based key derivation and session management\n */\nclass SecureMasterKeyManager {\n constructor(indexedDBWrapper = null) {\n // Session state\n this._keyHandle = null; // non-extractable CryptoKey\n this._isUnlocked = false;\n this._sessionTimeout = null;\n this._lastActivity = null;\n \n // Configuration\n this._sessionTimeoutMs = 60 * 60 * 1000; // 60 minutes (\u0443\u0432\u0435\u043B\u0438\u0447\u0435\u043D\u043E \u0441 15 \u043C\u0438\u043D\u0443\u0442)\n this._inactivityTimeoutMs = 30 * 60 * 1000; // 30 minutes (\u0443\u0432\u0435\u043B\u0438\u0447\u0435\u043D\u043E \u0441 5 \u043C\u0438\u043D\u0443\u0442)\n \n // PBKDF2 parameters\n this._pbkdf2Iterations = 310000; // OWASP 2025 recommendation for PBKDF2-SHA256\n this._saltSize = 32; // 256 bits\n \n // IndexedDB wrapper for persistent salt storage\n this._indexedDB = indexedDBWrapper || new SecureIndexedDBWrapper();\n this._dbInitialized = false;\n \n // Event handlers\n this._onPasswordRequired = null;\n this._onSessionExpired = null;\n this._onUnlocked = null;\n \n // Setup event listeners (disabled for better UX - no auto-disconnect)\n // this._setupEventListeners();\n }\n \n /**\n * Set callback for password requests\n */\n setPasswordRequiredCallback(callback) {\n this._onPasswordRequired = callback;\n }\n \n /**\n * Set callback for session expiration\n */\n setSessionExpiredCallback(callback) {\n this._onSessionExpired = callback;\n }\n \n /**\n * Set callback for successful unlock\n */\n setUnlockedCallback(callback) {\n this._onUnlocked = callback;\n }\n \n /**\n * Setup event listeners for session management\n */\n _setupEventListeners() {\n // Handle page visibility changes\n if (typeof document !== 'undefined') {\n document.addEventListener('visibilitychange', () => {\n if (document.hidden) {\n this._handleFocusOut();\n } else {\n this._handleFocusIn();\n }\n });\n \n // Handle window focus/blur\n window.addEventListener('blur', () => this._handleFocusOut());\n window.addEventListener('focus', () => this._handleFocusIn());\n \n // Handle user activity\n ['mousedown', 'mousemove', 'keypress', 'scroll', 'touchstart'].forEach(event => {\n document.addEventListener(event, () => this._updateActivity(), { passive: true });\n });\n }\n }\n \n /**\n * Handle focus out - start inactivity timer\n */\n _handleFocusOut() {\n if (this._isUnlocked) {\n // Start shorter timeout when window loses focus\n this._startInactivityTimer(this._inactivityTimeoutMs);\n }\n }\n \n /**\n * Handle focus in - reset timers\n */\n _handleFocusIn() {\n if (this._isUnlocked) {\n this._resetSessionTimer();\n }\n }\n \n /**\n * Update last activity timestamp\n */\n _updateActivity() {\n this._lastActivity = Date.now();\n if (this._isUnlocked) {\n this._resetSessionTimer();\n }\n }\n \n /**\n * Start session timer\n */\n _startSessionTimer() {\n this._clearTimers();\n this._sessionTimeout = setTimeout(() => {\n this._expireSession('timeout');\n }, this._sessionTimeoutMs);\n }\n \n /**\n * Start inactivity timer\n */\n _startInactivityTimer(timeout) {\n this._clearTimers();\n this._sessionTimeout = setTimeout(() => {\n this._expireSession('inactivity');\n }, timeout);\n }\n \n /**\n * Reset session timer\n */\n _resetSessionTimer() {\n if (this._isUnlocked) {\n this._startSessionTimer();\n }\n }\n \n /**\n * Clear all timers\n */\n _clearTimers() {\n if (this._sessionTimeout) {\n clearTimeout(this._sessionTimeout);\n this._sessionTimeout = null;\n }\n }\n \n /**\n * Expire the current session\n */\n _expireSession(reason = 'unknown') {\n if (this._isUnlocked) {\n this._secureWipeMasterKey();\n this._isUnlocked = false;\n \n if (this._onSessionExpired) {\n this._onSessionExpired(reason);\n }\n }\n }\n \n /**\n * Initialize IndexedDB if not already done\n */\n async _ensureDBInitialized() {\n if (!this._dbInitialized) {\n await this._indexedDB.initialize();\n this._dbInitialized = true;\n }\n }\n \n /**\n * Generate salt for PBKDF2\n */\n _generateSalt() {\n return crypto.getRandomValues(new Uint8Array(this._saltSize));\n }\n \n /**\n * Get or create persistent salt\n */\n async _getOrCreateSalt() {\n await this._ensureDBInitialized();\n \n // Try to get existing salt\n let salt = await this._indexedDB.getMasterSalt();\n \n if (!salt) {\n // Generate new salt and store it\n salt = this._generateSalt();\n await this._indexedDB.storeMasterSalt(salt);\n }\n \n return salt;\n }\n \n /**\n * Derive master key from password using PBKDF2\n */\n async _deriveKeyFromPassword(password, salt) {\n try {\n // Import password as key material\n const passwordKey = await crypto.subtle.importKey(\n 'raw',\n new TextEncoder().encode(password),\n 'PBKDF2',\n false,\n ['deriveKey']\n );\n \n // Derive AES-GCM key using PBKDF2\n const derivedKey = await crypto.subtle.deriveKey(\n {\n name: 'PBKDF2',\n salt: salt,\n iterations: this._pbkdf2Iterations,\n hash: 'SHA-256'\n },\n passwordKey,\n {\n name: 'AES-GCM',\n length: 256\n },\n false, // non-extractable for security\n ['encrypt', 'decrypt', 'wrapKey', 'unwrapKey']\n );\n \n return derivedKey;\n } catch (error) {\n throw new Error(`Key derivation failed: ${error.message}`);\n }\n }\n \n /**\n * Request password from user\n */\n async _requestPassword(isRetry = false) {\n if (!this._onPasswordRequired) {\n throw new Error('Password callback not set');\n }\n \n return new Promise((resolve, reject) => {\n this._onPasswordRequired(isRetry, (password) => {\n if (password) {\n resolve(password);\n } else {\n reject(new Error('Password not provided'));\n }\n });\n });\n }\n \n /**\n * Unlock the master key with password\n */\n async unlock(password = null) {\n try {\n // Request password if not provided\n if (!password) {\n password = await this._requestPassword(false);\n }\n \n // Get or create persistent salt\n const salt = await this._getOrCreateSalt();\n \n // Derive non-extractable key handle\n this._keyHandle = await this._deriveKeyFromPassword(password, salt);\n \n // Mark as unlocked\n this._isUnlocked = true;\n this._lastActivity = Date.now();\n \n // Start session timer\n this._startSessionTimer();\n \n // Securely wipe password from memory\n password = null;\n \n if (this._onUnlocked) {\n this._onUnlocked();\n }\n \n return { success: true };\n \n } catch (error) {\n // Securely wipe password on error\n password = null;\n throw error;\n }\n }\n \n /**\n * Lock the master key\n */\n lock() {\n this._expireSession('manual');\n }\n \n /**\n * Get master key (only if unlocked)\n */\n // Prevent direct key access; provide operations only\n async encryptBytes(plainBytes) {\n if (!this._isUnlocked || !this._keyHandle) {\n throw new Error('Master key is locked');\n }\n this._updateActivity();\n const iv = crypto.getRandomValues(new Uint8Array(12));\n const encrypted = await crypto.subtle.encrypt({ name: 'AES-GCM', iv }, this._keyHandle, plainBytes);\n return { encryptedData: new Uint8Array(encrypted), iv };\n }\n\n async decryptBytes(encryptedBytes, iv) {\n if (!this._isUnlocked || !this._keyHandle) {\n throw new Error('Master key is locked');\n }\n this._updateActivity();\n const decrypted = await crypto.subtle.decrypt({ name: 'AES-GCM', iv }, this._keyHandle, encryptedBytes);\n return new Uint8Array(decrypted);\n }\n \n /**\n * Check if master key is unlocked\n */\n isUnlocked() {\n return this._isUnlocked && this._masterKey !== null;\n }\n \n /**\n * Get session status\n */\n getSessionStatus() {\n return {\n isUnlocked: this._isUnlocked,\n lastActivity: this._lastActivity,\n sessionTimeoutMs: this._sessionTimeoutMs,\n inactivityTimeoutMs: this._inactivityTimeoutMs\n };\n }\n \n /**\n * Securely wipe master key from memory\n */\n _secureWipeMasterKey() {\n if (this._keyHandle) {\n // CryptoKey objects are automatically garbage collected\n // but we clear the reference immediately\n this._keyHandle = null;\n }\n this._clearTimers();\n }\n \n /**\n * Cleanup on destruction\n */\n destroy() {\n this._secureWipeMasterKey();\n this._isUnlocked = false;\n \n // Remove event listeners\n if (typeof document !== 'undefined') {\n document.removeEventListener('visibilitychange', this._handleFocusOut);\n window.removeEventListener('blur', this._handleFocusOut);\n window.removeEventListener('focus', this._handleFocusIn);\n }\n }\n}\n\nexport { \n EnhancedSecureWebRTCManager, \n SecureMasterKeyManager, \n SecureIndexedDBWrapper, \n SecurePersistentKeyStorage \n};\n", "import { EnhancedSecureCryptoUtils } from '../crypto/EnhancedSecureCryptoUtils.js';\nimport { EnhancedSecureWebRTCManager } from '../network/EnhancedSecureWebRTCManager.js';\nimport { EnhancedSecureFileTransfer } from '../transfer/EnhancedSecureFileTransfer.js';\nimport { NotificationIntegration } from '../notifications/NotificationIntegration.js';\n\n// Import UI components (side-effect: they attach themselves to window.*)\nimport '../components/ui/Header.jsx';\nimport '../components/ui/DownloadApps.jsx';\nimport '../components/ui/BecomePartner.jsx';\nimport '../components/ui/UniqueFeatureSlider.jsx';\nimport '../components/ui/SecurityFeatures.jsx';\nimport '../components/ui/Testimonials.jsx';\nimport '../components/ui/ComparisonTable.jsx';\nimport '../components/ui/Roadmap.jsx';\nimport '../components/ui/FileTransfer.jsx';\n\n// Expose to global for legacy usage inside app code\nwindow.EnhancedSecureCryptoUtils = EnhancedSecureCryptoUtils;\nwindow.EnhancedSecureWebRTCManager = EnhancedSecureWebRTCManager;\nwindow.EnhancedSecureFileTransfer = EnhancedSecureFileTransfer;\nwindow.NotificationIntegration = NotificationIntegration;\n\n// Mount application once DOM and modules are ready\nconst start = () => {\n if (typeof window.initializeApp === 'function') {\n window.initializeApp();\n } else if (window.DEBUG_MODE) {\n console.error('initializeApp is not defined on window');\n }\n};\n\nif (document.readyState === 'loading') {\n document.addEventListener('DOMContentLoaded', start);\n} else {\n start();\n}\n", "const EnhancedMinimalHeader = ({ \n status, \n fingerprint, \n verificationCode, \n onDisconnect, \n isConnected, \n securityLevel, \n webrtcManager \n}) => {\n const [realSecurityLevel, setRealSecurityLevel] = React.useState(null);\n const [lastSecurityUpdate, setLastSecurityUpdate] = React.useState(0);\n // Added local session state to remove references errors after session timer removal\n const [hasActiveSession, setHasActiveSession] = React.useState(false);\n const [currentTimeLeft, setCurrentTimeLeft] = React.useState(0);\n const [sessionType, setSessionType] = React.useState('unknown');\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 (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 } else if (window.DEBUG_MODE) {\n }\n } else {\n \n }\n \n } catch (error) {\n \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]);\n\n // ============================================\n // FIXED EVENT HANDLERS\n // ============================================\n\n React.useEffect(() => {\n const handleSecurityUpdate = (event) => {\n\n setTimeout(() => {\n setLastSecurityUpdate(0);\n }, 100);\n };\n\n const handleRealSecurityCalculated = (event) => {\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 \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 \n }\n })\n .catch(error => {\n \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 // All security features are enabled by default - no session management needed\n setHasActiveSession(true);\n setCurrentTimeLeft(0);\n setSessionType('premium'); // All features enabled\n }, []);\n\n React.useEffect(() => {\n // All security features are enabled by default\n setHasActiveSession(true);\n setCurrentTimeLeft(0);\n setSessionType('premium'); // All features enabled\n }, []);\n\n React.useEffect(() => {\n const handleForceUpdate = (event) => {\n // All security features are enabled by default\n setHasActiveSession(true);\n setCurrentTimeLeft(0);\n setSessionType('premium'); // All features enabled\n };\n\n // Connection cleanup handler (use existing event from module)\n const handleConnectionCleaned = () => {\n \n\n setRealSecurityLevel(null);\n setLastSecurityUpdate(0);\n\n setHasActiveSession(false);\n setCurrentTimeLeft(0);\n setSessionType('unknown');\n };\n\n const handlePeerDisconnect = () => {\n \n\n setRealSecurityLevel(null);\n setLastSecurityUpdate(0);\n };\n\n const handleDisconnected = () => {\n\n setRealSecurityLevel(null);\n setLastSecurityUpdate(0);\n setHasActiveSession(false);\n setCurrentTimeLeft(0);\n setSessionType('unknown');\n };\n\n document.addEventListener('force-header-update', handleForceUpdate);\n document.addEventListener('peer-disconnect', handlePeerDisconnect);\n document.addEventListener('connection-cleaned', handleConnectionCleaned);\n document.addEventListener('disconnected', handleDisconnected);\n \n return () => {\n document.removeEventListener('force-header-update', handleForceUpdate);\n document.removeEventListener('peer-disconnect', handlePeerDisconnect);\n document.removeEventListener('connection-cleaned', handleConnectionCleaned);\n document.removeEventListener('disconnected', handleDisconnected);\n };\n }, []);\n\n // ============================================\n // SECURITY INDICATOR CLICK HANDLER\n // ============================================\n\n const handleSecurityClick = async (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 // Prevent default behavior\n event.preventDefault();\n event.stopPropagation();\n\n\n // Run real security tests if webrtcManager is available\n let realTestResults = null;\n if (webrtcManager && window.EnhancedSecureCryptoUtils) {\n try {\n realTestResults = await window.EnhancedSecureCryptoUtils.calculateSecurityLevel(webrtcManager);\n \n } catch (error) {\n \n }\n } else {\n \n }\n\n // If no real test results and no existing security level, show progress message\n if (!realTestResults && !realSecurityLevel) {\n alert('Security verification in progress...\\nPlease wait for real-time cryptographic verification to complete.');\n return;\n }\n\n // Use real test results if available, otherwise fall back to current data\n let securityData = realTestResults || realSecurityLevel;\n\n // If still no security data, create a basic fallback\n if (!securityData) {\n securityData = {\n level: 'UNKNOWN',\n score: 0,\n color: 'gray',\n verificationResults: {},\n timestamp: Date.now(),\n details: 'Security verification not available',\n isRealData: false,\n passedChecks: 0,\n totalChecks: 0\n };\n \n }\n\n // Detailed information about the REAL security check\n let message = `REAL-TIME SECURITY VERIFICATION\\n\\n`;\n message += `Security Level: ${securityData.level} (${securityData.score}%)\\n`;\n message += `Verification Time: ${new Date(securityData.timestamp).toLocaleTimeString()}\\n`;\n message += `Data Source: ${securityData.isRealData ? 'Real Cryptographic Tests' : 'Simulated Data'}\\n\\n`;\n \n if (securityData.verificationResults) {\n message += 'DETAILED CRYPTOGRAPHIC TESTS:\\n';\n message += '=' + '='.repeat(40) + '\\n';\n \n const passedTests = Object.entries(securityData.verificationResults).filter(([key, result]) => result.passed);\n const failedTests = Object.entries(securityData.verificationResults).filter(([key, result]) => !result.passed);\n \n if (passedTests.length > 0) {\n message += '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 || 'Test passed'}\\n`;\n });\n message += '\\n';\n }\n \n if (failedTests.length > 0) {\n message += 'FAILED/UNAVAILABLE 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 || 'Test failed or unavailable'}\\n`;\n });\n message += '\\n';\n }\n \n message += `SUMMARY:\\n`;\n message += `Passed: ${securityData.passedChecks}/${securityData.totalChecks} tests\\n`;\n message += `Score: ${securityData.score}/${securityData.maxPossibleScore || 100} points\\n\\n`;\n }\n \n // Real security features status\n message += `SECURITY FEATURES STATUS:\\n`;\n message += '=' + '='.repeat(40) + '\\n';\n \n if (securityData.verificationResults) {\n const features = {\n 'ECDSA Digital Signatures': securityData.verificationResults.verifyECDSASignatures?.passed || false,\n 'ECDH Key Exchange': securityData.verificationResults.verifyECDHKeyExchange?.passed || false,\n 'AES-GCM Encryption': securityData.verificationResults.verifyEncryption?.passed || false,\n 'Message Integrity (HMAC)': securityData.verificationResults.verifyMessageIntegrity?.passed || false,\n 'Perfect Forward Secrecy': securityData.verificationResults.verifyPerfectForwardSecrecy?.passed || false,\n 'Replay Protection': securityData.verificationResults.verifyReplayProtection?.passed || false,\n 'DTLS Fingerprint': securityData.verificationResults.verifyDTLSFingerprint?.passed || false,\n 'SAS Verification': securityData.verificationResults.verifySASVerification?.passed || false,\n 'Metadata Protection': securityData.verificationResults.verifyMetadataProtection?.passed || false,\n 'Traffic Obfuscation': securityData.verificationResults.verifyTrafficObfuscation?.passed || false\n };\n \n Object.entries(features).forEach(([feature, isEnabled]) => {\n message += `${isEnabled ? '\u2705' : '\u274C'} ${feature}\\n`;\n });\n } else {\n // Fallback if no verification results\n message += `\u2705 ECDSA Digital Signatures\\n`;\n message += `\u2705 ECDH Key Exchange\\n`;\n message += `\u2705 AES-GCM Encryption\\n`;\n message += `\u2705 Message Integrity (HMAC)\\n`;\n message += `\u2705 Perfect Forward Secrecy\\n`;\n message += `\u2705 Replay Protection\\n`;\n message += `\u2705 DTLS Fingerprint\\n`;\n message += `\u2705 SAS Verification\\n`;\n message += `\u2705 Metadata Protection\\n`;\n message += `\u2705 Traffic Obfuscation\\n`;\n }\n \n message += `\\n${securityData.details || 'Real cryptographic verification completed'}`;\n \n if (securityData.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 // Show in a more user-friendly way\n const modal = document.createElement('div');\n modal.style.cssText = `\n position: fixed;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n background: rgba(0,0,0,0.8);\n z-index: 10000;\n display: flex;\n align-items: center;\n justify-content: center;\n font-family: monospace;\n `;\n \n const content = document.createElement('div');\n content.style.cssText = `\n background: #1a1a1a;\n color: #fff;\n padding: 20px;\n border-radius: 8px;\n max-width: 80%;\n max-height: 80%;\n overflow-y: auto;\n white-space: pre-line;\n border: 1px solid #333;\n `;\n \n content.textContent = message;\n modal.appendChild(content);\n \n // Close on click outside\n modal.addEventListener('click', (e) => {\n if (e.target === modal) {\n document.body.removeChild(modal);\n }\n });\n \n // Close on Escape key\n const handleKeyDown = (e) => {\n if (e.key === 'Escape') {\n document.body.removeChild(modal);\n document.removeEventListener('keydown', handleKeyDown);\n }\n };\n document.addEventListener('keydown', handleKeyDown);\n \n document.body.appendChild(modal);\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 = isConnected ? (realSecurityLevel || securityLevel) : null;\n \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 = undefined;\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.8.5')\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\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 DownloadApps = () => {\n const apps = [\n { id: 'web', name: 'Web App', subtitle: 'Browser Version', icon: 'fas fa-globe', platform: 'Web', isActive: true, url: 'https://securebit.chat/', color: 'green' },\n { id: 'windows', name: 'Windows', subtitle: 'Desktop App', icon: 'fab fa-windows', platform: 'Desktop', isActive: true, url: 'https://github.com/SecureBitChat/securebit-desktop/releases/latest/download/SecureBit.Chat_0.1.0_x64-setup.exe', color: 'blue' },\n { id: 'macos', name: 'macOS', subtitle: 'Desktop App', icon: 'fab fa-safari', platform: 'Desktop', isActive: true, url: 'https://github.com/SecureBitChat/securebit-desktop/releases/download/v0.1.0/SecureBit.Chat_0.1.0_x64.dmg', color: 'gray' },\n { id: 'linux', name: 'Linux', subtitle: 'Desktop App', icon: 'fab fa-linux', platform: 'Desktop', isActive: true, url: 'https://github.com/SecureBitChat/securebit-desktop/releases/latest/download/SecureBit.Chat_0.1.0_amd64.AppImage', color: 'orange' },\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: 'white' },\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' },\n { id: 'chrome', name: 'Chrome', subtitle: 'Browser Extension', icon: 'fab fa-chrome', platform: 'Browser', isActive: false, url: '#', color: 'yellow' },\n { id: 'edge', name: 'Edge', subtitle: 'Browser Extension', icon: 'fab fa-edge', platform: 'Browser', isActive: false, url: '#', color: 'blue' },\n { id: 'opera', name: 'Opera', subtitle: 'Browser Extension', icon: 'fab fa-opera', platform: 'Browser', isActive: false, url: '#', color: 'red' },\n { id: 'firefox', name: 'Firefox', subtitle: 'Browser Extension', icon: 'fab fa-firefox-browser', platform: 'Browser', isActive: false, url: '#', color: 'orange' },\n ];\n\n const handleDownload = (app) => {\n if (app.isActive) window.open(app.url, '_blank');\n };\n\n const desktopApps = apps.filter(a => a.platform === 'Desktop' || a.platform === 'Web');\n const mobileApps = apps.filter(a => a.platform === 'Mobile');\n const browserApps = apps.filter(a => a.platform === 'Browser');\n\n const cardSize = \"w-28 h-28\";\n\n const colorClasses = {\n green: 'text-green-500',\n blue: 'text-blue-500',\n gray: 'text-gray-500',\n orange: 'text-orange-500',\n red: 'text-red-500',\n white: 'text-white',\n yellow: 'text-yellow-400',\n };\n\n const renderAppCard = (app) => (\n React.createElement('div', {\n key: app.id,\n className: `group relative ${cardSize} rounded-2xl overflow-hidden card-minimal cursor-pointer`\n }, [\n React.createElement('i', {\n key: 'bg-icon',\n className: `${app.icon} absolute text-[3rem] ${app.isActive ? colorClasses[app.color] : '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`\n }),\n React.createElement('div', {\n key: 'overlay',\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\"\n }, [\n React.createElement('h4', { key: 'name', className: `text-sm font-semibold text-primary mb-1` }, app.name),\n React.createElement('p', { key: 'subtitle', className: `text-xs text-secondary mb-2` }, app.subtitle),\n app.isActive ?\n React.createElement('button', {\n key: 'btn',\n onClick: () => handleDownload(app),\n className: `px-2 py-1 rounded-xl bg-emerald-500 text-black font-medium hover:bg-emerald-600 transition-colors text-xs`\n }, app.id === \"web\" ? \"Launch\" : \"Download\")\n :\n React.createElement('span', { key: 'coming', className: \"text-gray-400 font-medium text-xs\" }, \"Coming Soon\")\n ])\n ])\n );\n\n return React.createElement('div', { className: \"mt-20 px-6\" }, [\n // Header\n React.createElement('div', { key: 'header', className: \"text-center max-w-3xl mx-auto mb-12\" }, [\n React.createElement('h3', { key: 'title', className: \"text-3xl font-bold text-primary mb-3\" }, 'Download SecureBit.chat'),\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.')\n ]),\n\n // Desktop Apps\n React.createElement('div', { key: 'desktop-row', className: \"hidden sm:flex justify-center flex-wrap gap-6 mb-6\" },\n desktopApps.map(renderAppCard)\n ),\n\n // Mobile Apps\n React.createElement('div', { key: 'mobile-row', className: \"flex justify-center gap-6 mb-6\" },\n mobileApps.map(renderAppCard)\n ),\n\n // Browser Extensions\n React.createElement('div', { key: 'browser-row', className: \"flex justify-center gap-6\" },\n browserApps.map(renderAppCard)\n )\n ]);\n};\n\nwindow.DownloadApps = DownloadApps;\n", "const BecomePartner = () => {\n const partners = [\n { id: 'aegis', name: 'Aegis', logo: 'logo/aegis.png', isColor: true, url: 'https://aegis-investment.com/' },\n { id: 'furi', name: 'Furi Labs', logo: 'logo/furi.png', isColor: true, url: 'https://furilabs.com/' }\n ];\n\n const formUrl = 'https://docs.google.com/forms/d/e/1FAIpQLSc9ijV9PCoyXkus6vEx1OWwvwAsLq8fKS6-H5BmX-c-bvia6w/viewform?usp=dialog';\n\n return React.createElement('div', { className: \"mt-20 px-6\" }, [\n // Header \"Trusted by our partners\"\n React.createElement('div', { key: 'header', className: \"text-center max-w-3xl mx-auto mb-8\" }, [\n React.createElement('h3', { key: 'title', className: \"text-3xl font-bold text-primary mb-3\" }, 'Trusted by our partners')\n ]),\n\n // First divider line with fade\n React.createElement('div', {\n key: 'divider-1',\n className: \"h-px w-full max-w-3xl mx-auto mb-8 bg-gradient-to-r from-transparent via-zinc-700 to-transparent\"\n }),\n\n // Partner Logos\n React.createElement('div', { \n key: 'partners-row', \n className: \"flex justify-center items-center flex-wrap gap-12 mb-8\" \n },\n partners.map(partner => \n React.createElement('a', {\n key: partner.id,\n href: partner.url,\n target: '_blank',\n rel: 'noopener noreferrer',\n className: \"flex items-center justify-center cursor-pointer hover:opacity-100 transition-opacity duration-300\"\n }, [\n React.createElement('img', {\n key: 'logo',\n src: partner.logo,\n alt: partner.name,\n className: \"h-12 sm:h-16 opacity-80 hover:opacity-100 transition-opacity duration-300\",\n style: partner.isColor ? {\n filter: 'grayscale(100%) brightness(1.2) contrast(1.1)',\n WebkitFilter: 'grayscale(100%) brightness(1.2) contrast(1.1)'\n } : {}\n })\n ])\n )\n ),\n\n // Second divider line with fade\n React.createElement('div', {\n key: 'divider-2',\n className: \"h-px w-full max-w-3xl mx-auto mb-8 bg-gradient-to-r from-transparent via-zinc-700 to-transparent\"\n }),\n\n // Section with subtitle and text\n React.createElement('div', { key: 'cta-section', className: \"text-center max-w-3xl mx-auto\" }, [\n React.createElement('h4', {\n key: 'subtitle',\n className: \"text-base font-semibold text-primary mb-4\"\n }, 'Technology & Community Partners'),\n \n React.createElement('p', {\n key: 'description',\n className: \"text-secondary text-sm mb-6\"\n }, 'Interested in partnering with us?'),\n\n // CTA Button with 3D glass effect\n React.createElement('div', {\n key: 'button-wrapper',\n className: \"button-container flex justify-center\"\n }, [\n React.createElement('a', {\n key: 'button-link',\n href: formUrl,\n target: '_blank',\n rel: 'noopener noreferrer',\n className: \"button\"\n }, [\n React.createElement('span', { key: 'text' }, 'Become a Partner')\n ])\n ])\n ])\n ]);\n};\n\nwindow.BecomePartner = BecomePartner;\n\n", "// Enhanced Modern Slider Component with Loading Protection\nconst UniqueFeatureSlider = () => {\n const trackRef = React.useRef(null);\n const wrapRef = React.useRef(null);\n const [current, setCurrent] = React.useState(0);\n const [isReady, setIsReady] = React.useState(false);\n\n const slides = [\n {\n icon: \"\uD83D\uDEE1\uFE0F\",\n bgImage: \"linear-gradient(135deg, rgb(255 107 53 / 6%) 0%, rgb(255 140 66 / 45%) 100%)\",\n thumbIcon: \"\uD83D\uDD12\",\n title: \"18-Layer Military Security\",\n description: \"Revolutionary defense system with ECDH P-384 + AES-GCM 256 + ECDSA + Complete ASN.1 Validation.\"\n },\n {\n icon: \"\uD83C\uDF10\",\n bgImage: \"linear-gradient(135deg, rgb(147 51 234 / 6%) 0%, rgb(168 85 247 / 45%) 100%)\",\n thumbIcon: \"\uD83D\uDD17\",\n title: \"Pure P2P WebRTC\",\n description: \"Direct peer-to-peer connections without any servers. Complete decentralization with zero infrastructure.\"\n },\n {\n icon: \"\uD83D\uDD04\",\n bgImage: \"linear-gradient(135deg, rgb(16 185 129 / 6%) 0%, rgb(52 211 153 / 45%) 100%)\",\n thumbIcon: \"\u26A1\",\n title: \"Perfect Forward Secrecy\",\n description: \"Automatic key rotation every 5 minutes. Non-extractable keys with hardware protection.\"\n },\n {\n icon: \"\uD83C\uDFAD\",\n bgImage: \"linear-gradient(135deg, rgb(6 182 212 / 6%) 0%, rgb(34 211 238 / 45%) 100%)\",\n thumbIcon: \"\uD83C\uDF2B\uFE0F\",\n title: \"Traffic Obfuscation\",\n description: \"Fake traffic generation and pattern masking make communication indistinguishable from noise.\"\n },\n {\n icon: \"\uD83D\uDC41\uFE0F\",\n bgImage: \"linear-gradient(135deg, rgb(37 99 235 / 6%) 0%, rgb(59 130 246 / 45%) 100%)\",\n thumbIcon: \"\uD83D\uDEAB\",\n title: \"Zero Data Collection\",\n description: \"No registration, no servers, no logs. Complete anonymity with instant channels.\"\n }\n ];\n\n // \u041F\u0440\u043E\u0432\u0435\u0440\u043A\u0430 \u0433\u043E\u0442\u043E\u0432\u043D\u043E\u0441\u0442\u0438 \u043A\u043E\u043C\u043F\u043E\u043D\u0435\u043D\u0442\u0430\n React.useEffect(() => {\n const timer = setTimeout(() => {\n setIsReady(true);\n }, 100);\n return () => clearTimeout(timer);\n }, []);\n\n const isMobile = () => window.matchMedia(\"(max-width:767px)\").matches;\n\n const center = React.useCallback((i) => {\n if (!trackRef.current || !wrapRef.current) return;\n const card = trackRef.current.children[i];\n if (!card) return;\n\n const axis = isMobile() ? \"top\" : \"left\";\n const size = isMobile() ? \"clientHeight\" : \"clientWidth\";\n const start = isMobile() ? card.offsetTop : card.offsetLeft;\n \n wrapRef.current.scrollTo({\n [axis]: start - (wrapRef.current[size] / 2 - card[size] / 2),\n behavior: \"smooth\"\n });\n }, []);\n\n const activate = React.useCallback((i, scroll = false) => {\n if (i === current) return;\n setCurrent(i);\n if (scroll) {\n setTimeout(() => center(i), 50);\n }\n }, [current, center]);\n\n const go = (step) => {\n const newIndex = Math.min(Math.max(current + step, 0), slides.length - 1);\n activate(newIndex, true);\n };\n\n React.useEffect(() => {\n const handleKeydown = (e) => {\n if ([\"ArrowRight\", \"ArrowDown\"].includes(e.key)) go(1);\n if ([\"ArrowLeft\", \"ArrowUp\"].includes(e.key)) go(-1);\n };\n\n window.addEventListener(\"keydown\", handleKeydown, { passive: true });\n return () => window.removeEventListener(\"keydown\", handleKeydown);\n }, [current]);\n\n React.useEffect(() => {\n if (isReady) {\n center(current);\n }\n }, [current, center, isReady]);\n // Render loading state if not ready\n if (!isReady) {\n return React.createElement('section', { \n style: { \n background: 'transparent',\n minHeight: '400px',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center'\n } \n }, \n React.createElement('div', { \n style: { \n opacity: 0.5,\n fontSize: '14px',\n color: '#fff'\n }\n }, 'Loading...')\n );\n }\n\n return React.createElement('section', { style: { background: 'transparent' } }, [\n // Header\n React.createElement('div', { \n key: 'head',\n className: 'head'\n }, [\n React.createElement('h2', { \n key: 'title', \n className: 'text-2xl sm:text-3xl font-bold text-white mb-4 leading-snug' \n }, 'Why SecureBit.chat is unique'),\n React.createElement('div', { \n key: 'controls',\n className: 'controls'\n }, [\n React.createElement('button', {\n key: 'prev',\n id: 'prev-slider',\n className: 'nav-btn',\n 'aria-label': 'Prev',\n disabled: current === 0,\n onClick: () => go(-1)\n }, '\u2039'),\n React.createElement('button', {\n key: 'next',\n id: 'next-slider',\n className: 'nav-btn',\n 'aria-label': 'Next',\n disabled: current === slides.length - 1,\n onClick: () => go(1)\n }, '\u203A')\n ])\n ]),\n\n // Slider\n React.createElement('div', {\n key: 'slider',\n className: 'slider',\n ref: wrapRef\n },\n React.createElement('div', {\n className: 'track',\n ref: trackRef\n }, slides.map((slide, index) =>\n React.createElement('article', {\n key: index,\n className: 'project-card',\n ...(index === current ? { active: '' } : {}),\n onMouseEnter: () => {\n if (window.matchMedia(\"(hover:hover)\").matches) {\n activate(index, true);\n }\n },\n onClick: () => activate(index, true)\n }, [\n // Background\n React.createElement('div', {\n key: 'bg',\n className: 'project-card__bg',\n style: {\n background: slide.bgImage,\n backgroundSize: 'cover',\n backgroundPosition: 'center'\n }\n }),\n\n // Content\n React.createElement('div', {\n key: 'content',\n className: 'project-card__content'\n }, [\n // Text container\n React.createElement('div', { key: 'text' }, [\n React.createElement('h3', {\n key: 'title',\n className: 'project-card__title'\n }, slide.title),\n React.createElement('p', {\n key: 'desc',\n className: 'project-card__desc'\n }, slide.description)\n ])\n ])\n ])\n ))\n ),\n ]);\n};\n\n// Export for use in your app\nwindow.UniqueFeatureSlider = UniqueFeatureSlider;", "const SecurityFeatures = () => {\n const features = [\n { id: 'feature1', color: '#00ff88', icon: 'fas fa-key accent-green', title: 'ECDH P-384 Key Exchange', desc: 'Military-grade elliptic curve key exchange' },\n { id: 'feature2', color: '#a78bfa', icon: 'fas fa-user-shield accent-purple', title: 'MITM Protection', desc: 'Out-of-band verification against attacks' },\n { id: 'feature3', color: '#ff8800', icon: 'fas fa-lock accent-orange', title: 'AES-GCM 256 Encryption', desc: 'Authenticated encryption standard' },\n { id: 'feature4', color: '#00ffff', icon: 'fas fa-sync-alt accent-cyan', title: 'Perfect Forward Secrecy', desc: 'Automatic key rotation every 5 minutes' },\n { id: 'feature5', color: '#0088ff', icon: 'fas fa-signature accent-blue', title: 'ECDSA P-384 Signatures', desc: 'Digital signatures for message integrity' },\n { id: 'feature6', color: '#f87171', icon: 'fas fa-shield-alt accent-red', title: 'SAS Security', desc: 'Revolutionary key exchange & MITM protection' }\n ];\n\n React.useEffect(() => {\n const cards = document.querySelectorAll(\".card\");\n const radius = 200; \n\n const handleMove = (e) => {\n cards.forEach((card) => {\n const rect = card.getBoundingClientRect();\n const cx = rect.left + rect.width / 2;\n const cy = rect.top + rect.height / 2;\n\n const dx = e.clientX - cx;\n const dy = e.clientY - cy;\n const dist = Math.sqrt(dx * dx + dy * dy);\n\n if (dist < radius) {\n const x = e.clientX - rect.left;\n const y = e.clientY - rect.top;\n card.style.setProperty(\"--x\", `${x}px`);\n card.style.setProperty(\"--y\", `${y}px`);\n card.classList.add(\"active-glow\");\n } else {\n card.classList.remove(\"active-glow\");\n }\n });\n };\n\n window.addEventListener(\"mousemove\", handleMove);\n return () => window.removeEventListener(\"mousemove\", handleMove);\n }, []);\n\n const renderFeature = (f) =>\n React.createElement('div', {\n key: f.id,\n className: \"card p-3 sm:p-4 text-center\",\n style: { \"--color\": f.color }\n }, [\n React.createElement('div', { key: 'icon', className: \"w-10 h-10 sm:w-12 sm:h-12 flex items-center justify-center mx-auto mb-2 sm:mb-3 relative z-10\" }, [\n React.createElement('i', { className: f.icon })\n ]),\n React.createElement('h4', { key: 'title', className: \"text-xs sm:text-sm font-medium text-primary mb-1 relative z-10\" }, f.title),\n React.createElement('p', { key: 'desc', className: \"text-xs text-muted leading-tight relative z-10\" }, f.desc)\n ]);\n\n return React.createElement('div', {\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\"\n }, features.map(renderFeature));\n};\n\nwindow.SecurityFeatures = SecurityFeatures;\n", "const Testimonials = () => {\n const testimonials = [\n { id: \"t1\", rating: 5.0, text: \"The interface feels modern and smooth. It saves me at least 2 hours every day when managing design tasks.\"},\n { id: \"t2\", rating: 5.0, text: \"Finally, a solution that blends speed with simplicity. My team adopted it within a week without training.\"},\n { id: \"t3\", rating: 5.0, text: \"I can track progress in real time and get a clear overview of our workflow. It feels empowering.\"},\n { id: \"t4\", rating: 5.0, text: \"Our pipeline visibility improved dramatically. I no longer need to manually track updates.\"},\n { id: \"t5\", rating: 5.0, text: \"The security-first approach gives me peace of mind. We handle sensitive data with confidence now.\"},\n { id: \"t6\", rating: 5.0, text: \"User feedback cycles are now twice as fast. It helps us test and ship features quickly.\"}\n ];\n\n React.useEffect(() => {\n const colUp = document.querySelector(\".col-up\");\n const colDown = document.querySelector(\".col-down\");\n const wrapper = document.querySelector(\".testimonials-wrapper\");\n\n if (!colUp || !colDown || !wrapper) return;\n\n let paused = false;\n const speed = 0.5;\n let animationId;\n\n const cloneCards = (container) => {\n const cards = Array.from(container.children);\n cards.forEach(card => {\n const clone = card.cloneNode(true);\n container.appendChild(clone);\n });\n };\n\n cloneCards(colUp);\n cloneCards(colDown);\n\n const getHalfHeight = (el) => {\n const children = Array.from(el.children);\n const halfCount = children.length / 2;\n let height = 0;\n for (let i = 0; i < halfCount; i++) {\n height += children[i].offsetHeight;\n if (i < halfCount - 1) height += 24; \n }\n return height;\n };\n\n let y1 = 0;\n const maxScroll1 = getHalfHeight(colUp);\n const maxScroll2 = getHalfHeight(colDown);\n let y2 = -maxScroll2; \n\n function animate() {\n if (!paused) {\n y1 -= speed;\n y2 += speed;\n\n if (Math.abs(y1) >= maxScroll1) {\n y1 = 0;\n }\n \n if (y2 >= 0) {\n y2 = -maxScroll2;\n }\n\n colUp.style.transform = `translateY(${y1}px)`;\n colDown.style.transform = `translateY(${y2}px)`;\n }\n animationId = requestAnimationFrame(animate);\n }\n\n animate();\n\n const handleMouseEnter = () => { paused = true; };\n const handleMouseLeave = () => { paused = false; };\n\n wrapper.addEventListener(\"mouseenter\", handleMouseEnter);\n wrapper.addEventListener(\"mouseleave\", handleMouseLeave);\n\n return () => {\n cancelAnimationFrame(animationId);\n wrapper.removeEventListener(\"mouseenter\", handleMouseEnter);\n wrapper.removeEventListener(\"mouseleave\", handleMouseLeave);\n };\n }, []);\n\n const renderCard = (t, index) => (\n
\n
\n {\"\u2605\".repeat(Math.floor(t.rating))}\n {t.rating.toFixed(1)}\n
\n

{t.text}

\n
\n );\n\n return (\n
\n
\n
\n

Testimonials

\n

\n What our users are saying\n

\n

\n We continuously listen to our community and improve every day.\n

\n
\n\n
\n
\n
\n\n
\n {testimonials.map((t, i) => renderCard(t, i))}\n
\n\n
\n {testimonials.map((t, i) => renderCard(t, i))}\n
\n
\n
\n
\n );\n};\n\nwindow.Testimonials = Testimonials;\n", "\n \n \n const ComparisonTable = () => {\n const [selectedFeature, setSelectedFeature] = React.useState(null);\n\n const messengers = [\n {\n name: \"SecureBit.chat\",\n logo:
\n \n
,\n type: \"P2P WebRTC\",\n version: \"Latest\",\n color: \"orange\",\n },\n {\n name: \"Signal\",\n logo: (\n \n \n \n \n ),\n type: \"Centralized\",\n version: \"Latest\",\n color: \"blue\",\n },\n {\n name: \"Threema\",\n logo: (\n \n \n \n \n \n \n \n ),\n type: \"Centralized\",\n version: \"Latest\",\n color: \"green\",\n },\n {\n name: \"Session\",\n logo: (\n \n \n \n \n ),\n type: \"Onion Network\",\n version: \"Latest\",\n color: \"cyan\",\n },\n ];\n\n const features = [\n {\n name: \"Security Architecture\",\n lockbit: { status: \"trophy\", detail: \"18-layer military-grade defense system with complete ASN.1 validation\" },\n signal: { status: \"check\", detail: \"Signal Protocol with double ratchet\" },\n threema: { status: \"check\", detail: \"Standard security implementation\" },\n session: { status: \"check\", detail: \"Modified Signal Protocol + Onion routing\" },\n },\n {\n name: \"Cryptography\",\n lockbit: { status: \"trophy\", detail: \"ECDH P-384 + AES-GCM 256 + ECDSA P-384\" },\n signal: { status: \"check\", detail: \"Signal Protocol + Double Ratchet\" },\n threema: { status: \"check\", detail: \"NaCl + XSalsa20 + Poly1305\" },\n session: { status: \"check\", detail: \"Modified Signal Protocol\" },\n },\n {\n name: \"Perfect Forward Secrecy\",\n lockbit: { status: \"trophy\", detail: \"Auto rotation every 5 minutes or 100 messages\" },\n signal: { status: \"check\", detail: \"Double Ratchet algorithm\" },\n threema: { status: \"warning\", detail: \"Partial (group chats)\" },\n session: { status: \"check\", detail: \"Session Ratchet algorithm\" },\n },\n {\n name: \"Architecture\",\n lockbit: { status: \"trophy\", detail: \"Pure P2P WebRTC without servers\" },\n signal: { status: \"times\", detail: \"Centralized Signal servers\" },\n threema: { status: \"times\", detail: \"Threema servers in Switzerland\" },\n session: { status: \"warning\", detail: \"Onion routing via network nodes\" },\n },\n {\n name: \"Registration Anonymity\",\n lockbit: { status: \"trophy\", detail: \"No registration required, instant anonymous channels\" },\n signal: { status: \"times\", detail: \"Phone number required\" },\n threema: { status: \"check\", detail: \"ID generated locally\" },\n session: { status: \"check\", detail: \"Random session ID\" },\n },\n {\n name: \"Metadata Protection\",\n lockbit: { status: \"trophy\", detail: \"Full metadata encryption + traffic obfuscation\" },\n signal: { status: \"warning\", detail: \"Sealed Sender (partial)\" },\n threema: { status: \"warning\", detail: \"Minimal metadata\" },\n session: { status: \"check\", detail: \"Onion routing hides metadata\" },\n },\n {\n name: \"Traffic Obfuscation\",\n lockbit: { status: \"trophy\", detail: \"Fake traffic + pattern masking + packet padding\" },\n signal: { status: \"times\", detail: \"No traffic obfuscation\" },\n threema: { status: \"times\", detail: \"No traffic obfuscation\" },\n session: { status: \"check\", detail: \"Onion routing provides obfuscation\" },\n },\n {\n name: \"Open Source\",\n lockbit: { status: \"trophy\", detail: \"100% open + auditable + MIT license\" },\n signal: { status: \"check\", detail: \"Fully open\" },\n threema: { status: \"warning\", detail: \"Only clients open\" },\n session: { status: \"check\", detail: \"Fully open\" },\n },\n {\n name: \"MITM Protection\",\n lockbit: { status: \"trophy\", detail: \"Out-of-band verification + mutual auth + ECDSA\" },\n signal: { status: \"check\", detail: \"Safety numbers verification\" },\n threema: { status: \"check\", detail: \"QR code scanning\" },\n session: { status: \"warning\", detail: \"Basic key verification\" },\n },\n {\n name: \"Censorship Resistance\",\n lockbit: { status: \"trophy\", detail: \"Impossible to block P2P + no servers to target\" },\n signal: { status: \"warning\", detail: \"Blocked in authoritarian countries\" },\n threema: { status: \"warning\", detail: \"May be blocked\" },\n session: { status: \"check\", detail: \"Onion routing bypasses blocks\" },\n },\n {\n name: \"Data Storage\",\n lockbit: { status: \"trophy\", detail: \"Zero data storage - only in browser memory\" },\n signal: { status: \"warning\", detail: \"Local database storage\" },\n threema: { status: \"warning\", detail: \"Local + optional backup\" },\n session: { status: \"warning\", detail: \"Local database storage\" },\n },\n {\n name: \"Key Security\",\n lockbit: { status: \"trophy\", detail: \"Non-extractable keys + hardware protection\" },\n signal: { status: \"check\", detail: \"Secure key storage\" },\n threema: { status: \"check\", detail: \"Local key storage\" },\n session: { status: \"check\", detail: \"Secure key storage\" },\n },\n {\n name: \"Post-Quantum Roadmap\",\n lockbit: { status: \"check\", detail: \"Planned v5.0 - CRYSTALS-Kyber/Dilithium\" },\n signal: { status: \"warning\", detail: \"PQXDH in development\" },\n threema: { status: \"times\", detail: \"Not announced\" },\n session: { status: \"times\", detail: \"Not announced\" },\n },\n ];\n\n const getStatusIcon = (status) => {\n const statusMap = {\n \"trophy\": { icon: \"fa-trophy\", color: \"accent-orange\" },\n \"check\": { icon: \"fa-check\", color: \"text-green-300\" },\n \"warning\": { icon: \"fa-exclamation-triangle\", color: \"text-yellow-300\" },\n \"times\": { icon: \"fa-times\", color: \"text-red-300\" },\n };\n return statusMap[status] || { icon: \"fa-question\", color: \"text-gray-400\" };\n };\n\n const toggleFeatureDetail = (index) => {\n setSelectedFeature(selectedFeature === index ? null : index);\n };\n\n return (\n
\n {/* Title */}\n
\n

\n Enhanced Security Edition Comparison\n

\n

\n Enhanced Security Edition vs leading secure messengers\n

\n
\n\n {/* Table container */}\n
\n {/* Mobile Alert */}\n
\n

\n \n Rotate your device horizontally for better viewing\n

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

\n Development Roadmap\n

\n

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

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

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

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

\n \n \n \n \n GitHub Repository\n \n \n \n \n Feedback\n \n
\n \n \n \n );\n };\n window.Roadmap = Roadmap;", "// File Transfer Component for Chat Interface - Fixed Version\nconst FileTransferComponent = ({ webrtcManager, isConnected }) => {\n const [dragOver, setDragOver] = React.useState(false);\n const [transfers, setTransfers] = React.useState({ sending: [], receiving: [] });\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\n const [pendingIncomingFiles, setPendingIncomingFiles] = React.useState([]);\n const fileInputRef = React.useRef(null);\n\n // Update transfers periodically\n React.useEffect(() => {\n if (!isConnected || !webrtcManager) return;\n\n const updateTransfers = () => {\n const currentTransfers = webrtcManager.getFileTransfers();\n setTransfers(currentTransfers);\n };\n\n const interval = setInterval(updateTransfers, 500);\n return () => clearInterval(interval);\n }, [isConnected, webrtcManager]);\n\n // Clear session-local UI state when the connection ends so reconnect starts clean.\n React.useEffect(() => {\n if (isConnected) return;\n setReadyFiles([]);\n setPendingIncomingFiles([]);\n setTransfers({ sending: [], receiving: [] });\n }, [isConnected]);\n\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\n React.useEffect(() => {\n if (!webrtcManager) return;\n\n webrtcManager.setFileTransferCallbacks(\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\n (progress) => {\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\n const currentTransfers = webrtcManager.getFileTransfers();\n setTransfers(currentTransfers);\n \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!\n },\n \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\n (fileData) => {\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\n setReadyFiles(prev => {\n // \u0438\u0437\u0431\u0435\u0433\u0430\u0435\u043C \u0434\u0443\u0431\u043B\u0435\u0439 \u043F\u043E fileId\n if (prev.some(f => f.fileId === fileData.fileId)) return prev;\n return [...prev, {\n fileId: fileData.fileId,\n fileName: fileData.fileName,\n fileSize: fileData.fileSize,\n mimeType: fileData.mimeType,\n getBlob: fileData.getBlob,\n getObjectURL: fileData.getObjectURL,\n revokeObjectURL: fileData.revokeObjectURL\n }];\n });\n\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\n const currentTransfers = webrtcManager.getFileTransfers();\n setTransfers(currentTransfers);\n },\n \n // Error callback\n (error) => {\n const currentTransfers = webrtcManager.getFileTransfers();\n setTransfers(currentTransfers);\n \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\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\n },\n\n // Incoming file request callback - user consent is mandatory\n (fileRequest) => {\n setPendingIncomingFiles(prev => {\n if (prev.some(file => file.fileId === fileRequest.fileId)) return prev;\n return [...prev, fileRequest];\n });\n }\n );\n\n return () => {\n webrtcManager.setFileTransferCallbacks(null, null, null, null);\n };\n }, [webrtcManager]);\n\n const handleFileSelect = async (files) => {\n if (!isConnected || !webrtcManager) {\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.');\n return;\n }\n\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\n if (!webrtcManager.isConnected() || !webrtcManager.isVerified) {\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.');\n return;\n }\n\n for (const file of files) {\n try {\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\n const validation = webrtcManager.validateFile(file);\n if (!validation.isValid) {\n const errorMessage = validation.errors.join('. ');\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}`);\n continue;\n }\n\n await webrtcManager.sendFile(file);\n } catch (error) {\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\n \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\n if (error.message.includes('Connection not ready')) {\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.`);\n } else if (error.message.includes('File too large') || error.message.includes('exceeds maximum')) {\n alert(`\u0424\u0430\u0439\u043B ${file.name} \u0441\u043B\u0438\u0448\u043A\u043E\u043C \u0431\u043E\u043B\u044C\u0448\u043E\u0439: ${error.message}`);\n } else if (error.message.includes('Maximum concurrent transfers')) {\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.`);\n } else if (error.message.includes('File type not allowed')) {\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}`);\n } else {\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}`);\n }\n }\n }\n };\n\n const handleDrop = (e) => {\n e.preventDefault();\n setDragOver(false);\n \n const files = Array.from(e.dataTransfer.files);\n handleFileSelect(files);\n };\n\n const handleDragOver = (e) => {\n e.preventDefault();\n setDragOver(true);\n };\n\n const handleDragLeave = (e) => {\n e.preventDefault();\n setDragOver(false);\n };\n\n const handleFileInputChange = (e) => {\n const files = Array.from(e.target.files);\n handleFileSelect(files);\n e.target.value = ''; // Reset input\n };\n\n const 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 const getStatusIcon = (status) => {\n switch (status) {\n case 'metadata_sent':\n case 'preparing':\n return 'fas fa-cog fa-spin';\n case 'transmitting':\n case 'receiving':\n return 'fas fa-exchange-alt fa-pulse';\n case 'assembling':\n return 'fas fa-puzzle-piece fa-pulse';\n case 'completed':\n return 'fas fa-check text-green-400';\n case 'failed':\n return 'fas fa-times text-red-400';\n default:\n return 'fas fa-circle';\n }\n };\n\n const getStatusText = (status) => {\n switch (status) {\n case 'metadata_sent':\n return '\u041F\u043E\u0434\u0433\u043E\u0442\u043E\u0432\u043A\u0430...';\n case 'transmitting':\n return '\u041E\u0442\u043F\u0440\u0430\u0432\u043A\u0430...';\n case 'receiving':\n return '\u041F\u043E\u043B\u0443\u0447\u0435\u043D\u0438\u0435...';\n case 'assembling':\n return '\u0421\u0431\u043E\u0440\u043A\u0430 \u0444\u0430\u0439\u043B\u0430...';\n case 'completed':\n return '\u0417\u0430\u0432\u0435\u0440\u0448\u0435\u043D\u043E';\n case 'failed':\n return '\u041E\u0448\u0438\u0431\u043A\u0430';\n default:\n return status;\n }\n };\n\n const handleIncomingDecision = async (fileId, accepted) => {\n try {\n if (accepted) {\n await webrtcManager.acceptIncomingFile(fileId);\n } else {\n await webrtcManager.rejectIncomingFile(fileId);\n }\n } finally {\n setPendingIncomingFiles(prev => prev.filter(file => file.fileId !== fileId));\n setTransfers(webrtcManager.getFileTransfers());\n }\n };\n\n if (!isConnected) {\n return React.createElement('div', {\n className: \"p-4 text-center text-muted\"\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');\n }\n\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\n const isConnectionReady = webrtcManager && webrtcManager.isConnected() && webrtcManager.isVerified;\n \n if (!isConnectionReady) {\n return React.createElement('div', {\n className: \"p-4 text-center text-yellow-600\"\n }, [\n React.createElement('i', {\n key: 'icon',\n className: 'fas fa-exclamation-triangle mr-2'\n }),\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.'\n ]);\n }\n\n return React.createElement('div', {\n className: \"file-transfer-component\"\n }, [\n // File Drop Zone\n React.createElement('div', {\n key: 'drop-zone',\n className: `file-drop-zone ${dragOver ? 'drag-over' : ''}`,\n onDrop: handleDrop,\n onDragOver: handleDragOver,\n onDragLeave: handleDragLeave,\n onClick: () => fileInputRef.current?.click()\n }, [\n React.createElement('div', {\n key: 'drop-content',\n className: \"drop-content\"\n }, [\n React.createElement('i', {\n key: 'icon',\n className: 'fas fa-cloud-upload-alt text-2xl mb-2 text-blue-400'\n }),\n React.createElement('p', {\n key: 'text',\n className: \"text-primary font-medium\"\n }, 'Drag files here or click to select'),\n React.createElement('p', {\n key: 'subtext',\n className: \"text-muted text-sm\"\n }, 'Maximum size: 100 MB per file')\n ])\n ]),\n\n // Hidden file input\n React.createElement('input', {\n key: 'file-input',\n ref: fileInputRef,\n type: 'file',\n multiple: true,\n className: 'hidden',\n onChange: handleFileInputChange\n }),\n\n pendingIncomingFiles.length > 0 && React.createElement('div', {\n key: 'incoming-consent',\n className: \"mt-4 space-y-2\"\n }, pendingIncomingFiles.map(file => React.createElement('div', {\n key: file.fileId,\n className: \"rounded-lg border border-yellow-500/30 bg-yellow-500/10 p-3\"\n }, [\n React.createElement('div', {\n key: 'info',\n className: \"mb-3 flex items-center justify-between gap-3\"\n }, [\n React.createElement('div', { key: 'text' }, [\n React.createElement('div', {\n key: 'title',\n className: \"text-sm font-medium text-primary\"\n }, 'Incoming file request'),\n React.createElement('div', {\n key: 'meta',\n className: \"text-xs text-secondary\"\n }, `${file.fileName} \u00B7 ${formatFileSize(file.fileSize)} \u00B7 ${file.mimeType}`)\n ])\n ]),\n React.createElement('div', {\n key: 'actions',\n className: \"flex gap-2\"\n }, [\n React.createElement('button', {\n key: 'accept',\n onClick: () => handleIncomingDecision(file.fileId, true),\n className: \"rounded-md bg-green-500/20 px-3 py-2 text-sm text-green-300 hover:bg-green-500/30\"\n }, 'Accept'),\n React.createElement('button', {\n key: 'reject',\n onClick: () => handleIncomingDecision(file.fileId, false),\n className: \"rounded-md bg-red-500/20 px-3 py-2 text-sm text-red-300 hover:bg-red-500/30\"\n }, 'Reject')\n ])\n ]))),\n\n // Active Transfers\n (transfers.sending.length > 0 || transfers.receiving.length > 0) && React.createElement('div', {\n key: 'transfers',\n className: \"active-transfers mt-4\"\n }, [\n React.createElement('h4', {\n key: 'title',\n className: \"text-primary font-medium mb-3 flex items-center\"\n }, [\n React.createElement('i', {\n key: 'icon',\n className: 'fas fa-exchange-alt mr-2'\n }),\n '\u041F\u0435\u0440\u0435\u0434\u0430\u0447\u0430 \u0444\u0430\u0439\u043B\u043E\u0432'\n ]),\n\n // Sending files\n ...transfers.sending.map(transfer => \n React.createElement('div', {\n key: `send-${transfer.fileId}`,\n className: \"transfer-item bg-blue-500/10 border border-blue-500/20 rounded-lg p-3 mb-2\"\n }, [\n React.createElement('div', {\n key: 'header',\n className: \"flex items-center justify-between mb-2\"\n }, [\n React.createElement('div', {\n key: 'info',\n className: \"flex items-center\"\n }, [\n React.createElement('i', {\n key: 'icon',\n className: 'fas fa-upload text-blue-400 mr-2'\n }),\n React.createElement('span', {\n key: 'name',\n className: \"text-primary font-medium text-sm\"\n }, transfer.fileName),\n React.createElement('span', {\n key: 'size',\n className: \"text-muted text-xs ml-2\"\n }, formatFileSize(transfer.fileSize))\n ]),\n React.createElement('button', {\n key: 'cancel',\n onClick: () => webrtcManager.cancelFileTransfer(transfer.fileId),\n className: \"text-red-400 hover:text-red-300 text-xs\"\n }, [\n React.createElement('i', {\n className: 'fas fa-times'\n })\n ])\n ]),\n React.createElement('div', {\n key: 'progress',\n className: \"progress-bar\"\n }, [\n React.createElement('div', {\n key: 'fill',\n className: \"progress-fill bg-blue-400\",\n style: { width: `${transfer.progress}%` }\n }),\n React.createElement('div', {\n key: 'text',\n className: \"progress-text text-xs flex items-center justify-between\"\n }, [\n React.createElement('span', {\n key: 'status',\n className: \"flex items-center\"\n }, [\n React.createElement('i', {\n key: 'icon',\n className: `${getStatusIcon(transfer.status)} mr-1`\n }),\n getStatusText(transfer.status)\n ]),\n React.createElement('span', {\n key: 'percent'\n }, `${transfer.progress.toFixed(1)}%`)\n ])\n ])\n ])\n ),\n\n // Receiving files\n ...transfers.receiving.map(transfer => \n React.createElement('div', {\n key: `recv-${transfer.fileId}`,\n className: \"transfer-item bg-green-500/10 border border-green-500/20 rounded-lg p-3 mb-2\"\n }, [\n React.createElement('div', {\n key: 'header',\n className: \"flex items-center justify-between mb-2\"\n }, [\n React.createElement('div', {\n key: 'info',\n className: \"flex items-center\"\n }, [\n React.createElement('i', {\n key: 'icon',\n className: 'fas fa-download text-green-400 mr-2'\n }),\n React.createElement('span', {\n key: 'name',\n className: \"text-primary font-medium text-sm\"\n }, transfer.fileName),\n React.createElement('span', {\n key: 'size',\n className: \"text-muted text-xs ml-2\"\n }, formatFileSize(transfer.fileSize))\n ]),\n React.createElement('div', { key: 'actions', className: 'flex items-center space-x-2' }, [\n (() => {\n const rf = readyFiles.find(f => f.fileId === transfer.fileId);\n if (!rf || transfer.status !== 'completed') return null;\n return React.createElement('button', {\n key: 'download',\n className: 'text-green-400 hover:text-green-300 text-xs flex items-center',\n onClick: async () => {\n try {\n const url = await rf.getObjectURL();\n const a = document.createElement('a');\n a.href = url;\n a.download = rf.fileName || 'file';\n a.click();\n rf.revokeObjectURL(url);\n } catch (e) {\n alert(e.message || 'This file is no longer available for download.');\n }\n }\n }, [\n React.createElement('i', { key: 'i', className: 'fas fa-download mr-1' }),\n 'Download'\n ]);\n })(),\n React.createElement('button', {\n key: 'cancel',\n onClick: () => webrtcManager.cancelFileTransfer(transfer.fileId),\n className: \"text-red-400 hover:text-red-300 text-xs\"\n }, [\n React.createElement('i', {\n className: 'fas fa-times'\n })\n ])\n ])\n ]),\n React.createElement('div', {\n key: 'progress',\n className: \"progress-bar\"\n }, [\n React.createElement('div', {\n key: 'fill',\n className: \"progress-fill bg-green-400\",\n style: { width: `${transfer.progress}%` }\n }),\n React.createElement('div', {\n key: 'text',\n className: \"progress-text text-xs flex items-center justify-between\"\n }, [\n React.createElement('span', {\n key: 'status',\n className: \"flex items-center\"\n }, [\n React.createElement('i', {\n key: 'icon',\n className: `${getStatusIcon(transfer.status)} mr-1`\n }),\n getStatusText(transfer.status)\n ]),\n React.createElement('span', {\n key: 'percent'\n }, `${transfer.progress.toFixed(1)}%`)\n ])\n ])\n ])\n )\n ])\n ]);\n};\n\n// Export\nwindow.FileTransferComponent = FileTransferComponent;\n"], + "mappings": "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", "names": ["NotificationIntegration", "fileMessageTypes", "attempts", "start", "error", "attempts", "chunk", "fileMessageTypes", "window", "start", "webrtcManager", "start"] } diff --git a/dist/app.js b/dist/app.js index 55e45fd..04a85d5 100644 --- a/dist/app.js +++ b/dist/app.js @@ -30,6 +30,28 @@ var EnhancedCopyButton = ({ text, className = "", children }) => { ]); }; var VerificationStep = ({ verificationCode, onConfirm, onReject, localConfirmed, remoteConfirmed, bothConfirmed }) => { + const [sasInput, setSasInput] = React.useState(""); + const [error, setError] = React.useState(""); + const normalizedExpectedLength = (verificationCode || "").replace(/[-\s]/g, "").length; + const normalizedInputLength = sasInput.replace(/[-\s]/g, "").length; + const canConfirm = !localConfirmed && normalizedExpectedLength > 0 && normalizedInputLength === normalizedExpectedLength; + React.useEffect(() => { + setSasInput(""); + setError(""); + }, [verificationCode]); + const handleConfirm = async () => { + try { + setError(""); + await onConfirm(sasInput); + } catch (confirmationError) { + setSasInput(""); + if (confirmationError?.message === "SAS_MAX_ATTEMPTS") { + setError("Too many incorrect attempts. Session reset for safety."); + } else { + setError("Incorrect code. Check it with your peer and try again."); + } + } + }; return React.createElement("div", { className: "card-minimal rounded-xl p-6 border-purple-500/20" }, [ @@ -57,7 +79,7 @@ var VerificationStep = ({ verificationCode, onConfirm, onReject, localConfirmed, React.createElement("p", { key: "description", className: "text-secondary text-sm" - }, "Verify the security code with your contact via another communication channel (voice, SMS, etc.):"), + }, "Compare this code with your peer out-of-band, then type the same code below to unlock the chat."), React.createElement("div", { key: "code-display", className: "text-center" @@ -67,6 +89,36 @@ var VerificationStep = ({ verificationCode, onConfirm, onReject, localConfirmed, className: "verification-code text-2xl py-4" }, verificationCode) ]), + React.createElement("div", { + key: "sas-input-wrap", + className: "space-y-2" + }, [ + React.createElement("label", { + key: "sas-label", + className: "block text-sm text-secondary" + }, "Enter the verified code"), + React.createElement("input", { + key: "sas-input", + type: "text", + value: sasInput, + onChange: (event) => { + setSasInput(event.target.value.toUpperCase()); + if (error) setError(""); + }, + autoFocus: true, + autoComplete: "off", + spellCheck: false, + inputMode: "text", + disabled: localConfirmed, + placeholder: verificationCode ? "Type code here" : "Waiting for code\u2026", + className: "w-full rounded-lg border border-purple-500/30 bg-black/20 px-4 py-3 text-center text-xl tracking-[0.3em] text-primary uppercase focus:border-purple-400 focus:outline-none disabled:cursor-not-allowed disabled:opacity-60", + style: { fontFamily: "monospace", textTransform: "uppercase" } + }), + error && React.createElement("p", { + key: "sas-error", + className: "text-sm text-red-400" + }, error) + ]), // Verification status indicators React.createElement("div", { key: "verification-status", @@ -136,14 +188,14 @@ var VerificationStep = ({ verificationCode, onConfirm, onReject, localConfirmed, }, [ 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"}` + onClick: handleConfirm, + disabled: !canConfirm, + className: `flex-1 py-3 px-4 rounded-lg font-medium transition-all duration-200 ${!canConfirm ? "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" + localConfirmed ? "Confirmed" : "Confirm code" ]), React.createElement("button", { key: "reject", @@ -270,7 +322,9 @@ var EnhancedConnectionSetup = ({ markAnswerCreated, notificationIntegrationRef, isGeneratingKeys, - handleCreateOffer + handleCreateOffer, + relayOnlyMode, + setRelayOnlyMode }) => { const [mode, setMode] = React.useState("select"); const [notificationPermissionRequested, setNotificationPermissionRequested] = React.useState(false); @@ -279,11 +333,11 @@ var EnhancedConnectionSetup = ({ setIsGeneratingKeys(false); onClearData(); }; - const handleVerificationConfirm = () => { - onVerifyConnection(true); + const handleVerificationConfirm = (userCode) => { + return onVerifyConnection(userCode); }; const handleVerificationReject = () => { - onVerifyConnection(false); + onVerifyConnection(null, false); }; const requestNotificationPermissionOnInteraction = async () => { if (notificationPermissionRequested) { @@ -395,6 +449,28 @@ var EnhancedConnectionSetup = ({ 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("label", { + key: "privacy-mode", + className: "mb-6 mx-auto flex max-w-2xl items-start gap-3 rounded-xl border border-purple-500/20 bg-purple-500/10 p-4 text-left" + }, [ + React.createElement("input", { + key: "input", + type: "checkbox", + checked: relayOnlyMode, + onChange: (event) => setRelayOnlyMode(event.target.checked), + className: "mt-1" + }), + React.createElement("span", { key: "copy" }, [ + React.createElement("span", { + key: "title", + className: "block text-sm font-medium text-primary" + }, "Privacy mode: relay-only WebRTC"), + React.createElement("span", { + key: "desc", + className: "block text-sm text-secondary" + }, "Uses TURN relay-only when configured. Without TURN, direct WebRTC may expose IP addresses and relay-only connections cannot start.") + ]) + ]), React.createElement("div", { key: "options", className: "flex flex-col md:flex-row items-center justify-center gap-6 max-w-3xl mx-auto" @@ -1352,6 +1428,13 @@ var EnhancedChatInterface = ({ var EnhancedSecureP2PChat = () => { const [messages, setMessages] = React.useState([]); const [connectionStatus, setConnectionStatus] = React.useState("disconnected"); + const [relayOnlyMode, setRelayOnlyMode] = React.useState(() => { + try { + return localStorage.getItem("securebit_relay_only_mode") === "true"; + } catch { + return false; + } + }); const [messageInput, setMessageInput] = React.useState(""); const [offerData, setOfferData] = React.useState(""); const [answerData, setAnswerData] = React.useState(""); @@ -1501,6 +1584,15 @@ var EnhancedSecureP2PChat = () => { }, []); const chatMessagesRef = React.useRef(null); const scrollToBottom = createScrollToBottomFunction(chatMessagesRef); + React.useEffect(() => { + try { + localStorage.setItem("securebit_relay_only_mode", String(relayOnlyMode)); + } catch { + } + if (webrtcManagerRef2.current?._config?.webrtc) { + webrtcManagerRef2.current._config.webrtc.relayOnly = relayOnlyMode; + } + }, [relayOnlyMode]); React.useEffect(() => { if (messages.length > 0 && chatMessagesRef.current) { scrollToBottom(); @@ -1677,7 +1769,13 @@ var EnhancedSecureP2PChat = () => { handleKeyExchange, handleVerificationRequired, handleAnswerError, - handleVerificationStateChange + handleVerificationStateChange, + { + webrtc: { + relayOnly: relayOnlyMode, + iceServers: Array.isArray(window.SECUREBIT_ICE_SERVERS) ? window.SECUREBIT_ICE_SERVERS : void 0 + } + } ); if (typeof Notification !== "undefined" && Notification && Notification.permission === "granted" && window.NotificationIntegration && !notificationIntegrationRef.current) { try { @@ -1689,7 +1787,7 @@ var EnhancedSecureP2PChat = () => { } catch (error) { } } - handleMessage(" SecureBit.chat Enhanced Security Edition v4.7.56 - 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"); + handleMessage(" SecureBit.chat Enhanced Security Edition v4.8.5 - 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) { if (webrtcManagerRef2.current && webrtcManagerRef2.current.isConnected()) { @@ -2809,9 +2907,9 @@ var EnhancedSecureP2PChat = () => { setConnectionStatus("failed"); } }; - const handleVerifyConnection = async (isValid) => { + const handleVerifyConnection = async (userCode, isValid = true) => { if (isValid) { - webrtcManagerRef2.current.confirmVerification(); + webrtcManagerRef2.current.confirmVerification(userCode); setLocalVerificationConfirmed(true); try { if (window.NotificationIntegration && webrtcManagerRef2.current && !notificationIntegrationRef.current) { @@ -3157,7 +3255,9 @@ var EnhancedSecureP2PChat = () => { markAnswerCreated, notificationIntegrationRef, isGeneratingKeys, - handleCreateOffer + handleCreateOffer, + relayOnlyMode, + setRelayOnlyMode }) ), // QR Scanner Modal diff --git a/dist/app.js.map b/dist/app.js.map index 5d8d109..d0cdacd 100644 --- a/dist/app.js.map +++ b/dist/app.js.map @@ -1,7 +1,7 @@ { "version": 3, "sources": ["../src/app.jsx"], - "sourcesContent": ["\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 break-words whitespace-normal\"\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 showQRCode,\r\n qrCodeUrl,\r\n showQRScanner,\r\n setShowQRCode,\r\n setShowQRScanner,\r\n setShowQRScannerModal,\r\n offerPassword,\r\n answerPassword,\r\n localVerificationConfirmed,\r\n remoteVerificationConfirmed,\r\n bothVerificationsConfirmed,\r\n // QR control props\r\n qrFramesTotal,\r\n qrFrameIndex,\r\n qrManualMode,\r\n toggleQrManualMode,\r\n nextQrFrame,\r\n prevQrFrame,\r\n markAnswerCreated,\r\n notificationIntegrationRef,\r\n isGeneratingKeys,\r\n handleCreateOffer\r\n }) => {\r\n const [mode, setMode] = React.useState('select');\r\n const [notificationPermissionRequested, setNotificationPermissionRequested] = React.useState(false);\r\n \r\n const resetToSelect = () => {\r\n setMode('select');\r\n setIsGeneratingKeys(false);\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 // Request notification permission on first user interaction\r\n const requestNotificationPermissionOnInteraction = async () => {\r\n if (notificationPermissionRequested) {\r\n return; // Already requested\r\n }\r\n \r\n try {\r\n // Check if Notification API is supported\r\n if (!('Notification' in window)) {\r\n return;\r\n }\r\n \r\n // Check if we're in a secure context\r\n if (!window.isSecureContext && window.location.protocol !== 'https:' && window.location.hostname !== 'localhost') {\r\n return;\r\n }\r\n \r\n // Check current permission status\r\n const currentPermission = (typeof Notification !== 'undefined' && Notification) \r\n ? Notification.permission \r\n : 'denied';\r\n \r\n // Only request if permission is default (not granted or denied)\r\n if (currentPermission === 'default' && typeof Notification !== 'undefined' && Notification) {\r\n const permission = await Notification.requestPermission();\r\n \r\n if (permission === 'granted') {\r\n // Initialize notification integration immediately\r\n try {\r\n if (window.NotificationIntegration && webrtcManagerRef.current) {\r\n const integration = new window.NotificationIntegration(webrtcManagerRef.current);\r\n await integration.init();\r\n \r\n // Store reference for cleanup\r\n notificationIntegrationRef.current = integration;\r\n }\r\n } catch (error) {\r\n // Handle error silently\r\n }\r\n \r\n // Send welcome notification\r\n setTimeout(() => {\r\n try {\r\n const welcomeNotification = new Notification('SecureBit Chat', {\r\n body: 'Notifications enabled! You will receive alerts for new messages.',\r\n icon: '/logo/icon-192x192.png',\r\n tag: 'welcome-notification'\r\n });\r\n \r\n welcomeNotification.onclick = () => {\r\n welcomeNotification.close();\r\n };\r\n \r\n setTimeout(() => {\r\n welcomeNotification.close();\r\n }, 5000);\r\n \r\n } catch (error) {\r\n // Handle error silently\r\n }\r\n }, 1000);\r\n \r\n }\r\n } else if (currentPermission === 'granted') {\r\n // Initialize notification integration immediately\r\n try {\r\n if (window.NotificationIntegration && webrtcManagerRef.current && !notificationIntegrationRef.current) {\r\n const integration = new window.NotificationIntegration(webrtcManagerRef.current);\r\n await integration.init();\r\n \r\n // Store reference for cleanup\r\n notificationIntegrationRef.current = integration;\r\n }\r\n } catch (error) {\r\n // Handle error silently\r\n }\r\n \r\n // Test notification to confirm it works\r\n setTimeout(() => {\r\n try {\r\n const testNotification = new Notification('SecureBit Chat', {\r\n body: 'Notifications are working! You will receive alerts for new messages.',\r\n icon: '/logo/icon-192x192.png',\r\n tag: 'test-notification'\r\n });\r\n \r\n testNotification.onclick = () => {\r\n testNotification.close();\r\n };\r\n \r\n setTimeout(() => {\r\n testNotification.close();\r\n }, 5000);\r\n } catch (error) {\r\n // Handle error silently\r\n }\r\n }, 1000);\r\n }\r\n \r\n setNotificationPermissionRequested(true);\r\n \r\n } catch (error) {\r\n // Handle error silently\r\n }\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: \"flex flex-col md:flex-row items-center justify-center 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: () => {\r\n requestNotificationPermissionOnInteraction();\r\n setMode('create');\r\n // \u0410\u0432\u0442\u043E\u043C\u0430\u0442\u0438\u0447\u0435\u0441\u043A\u0438 \u0437\u0430\u043F\u0443\u0441\u043A\u0430\u0435\u043C \u0433\u0435\u043D\u0435\u0440\u0430\u0446\u0438\u044E \u043A\u043B\u044E\u0447\u0435\u0439\r\n setTimeout(() => {\r\n if (webrtcManagerRef.current) {\r\n handleCreateOffer();\r\n }\r\n }, 100);\r\n },\r\n className: \"card-minimal rounded-xl p-6 cursor-pointer group flex-1 create\"\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\"),\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 React.createElement('div', {\r\n key: 'divider',\r\n className: \"flex flex-row md:flex-col items-center gap-4 px-4 w-full md:w-auto\"\r\n }, [\r\n React.createElement('div', {\r\n key: 'line-a',\r\n className: \"h-px flex-1 bg-gradient-to-r from-transparent via-zinc-700 to-transparent md:h-32 md:w-px md:flex-none md:bg-gradient-to-b\"\r\n }),\r\n React.createElement('div', {\r\n key: 'or-text',\r\n className: \"text-zinc-600 text-sm font-medium px-3\"\r\n }, \"OR\"),\r\n React.createElement('div', {\r\n key: 'line-b',\r\n className: \"h-px flex-1 bg-gradient-to-r from-transparent via-zinc-700 to-transparent md:h-32 md:w-px md:flex-none md:bg-gradient-to-b\"\r\n })\r\n ]),\r\n // Join Connection\r\n React.createElement('div', {\r\n key: 'join',\r\n onClick: () => {\r\n requestNotificationPermissionOnInteraction();\r\n setMode('join');\r\n },\r\n className: \"card-minimal rounded-xl p-6 cursor-pointer group flex-1 join\"\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(SecurityFeatures, { key: 'security-features' }),\r\n\r\n React.createElement(Testimonials, { key: 'testimonials' }),\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(BecomePartner, { key: 'become-partner' }),\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 !showAnswerStep && 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 !showOfferStep && isGeneratingKeys && React.createElement('div', {\r\n key: 'loading-state',\r\n className: \"w-full py-3 px-4 rounded-lg font-medium transition-all duration-200 bg-blue-500/10 border border-blue-500/20 text-blue-400 flex items-center justify-center\"\r\n }, [\r\n React.createElement('i', {\r\n key: 'spinner',\r\n className: 'fas fa-spinner fa-spin mr-2'\r\n }),\r\n 'Generating 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 // Raw JSON hidden intentionally; users copy compressed string or use QR\r\n React.createElement('div', {\r\n key: 'buttons',\r\n className: \"flex gap-2\"\r\n }, [\r\n React.createElement(EnhancedCopyButton, {\r\n key: 'copy',\r\n text: (() => {\r\n try {\r\n const min = typeof offerData === 'object' ? JSON.stringify(offerData) : (offerData || '');\r\n if (typeof window.encodeBinaryToPrefixed === 'function') {\r\n return window.encodeBinaryToPrefixed(min);\r\n }\r\n if (typeof window.compressToPrefixedGzip === 'function') {\r\n return window.compressToPrefixedGzip(min);\r\n }\r\n return min;\r\n } catch { return typeof offerData === 'object' ? JSON.stringify(offerData) : (offerData || ''); }\r\n })(),\r\n className: \"flex-1 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 showQRCode && qrCodeUrl && React.createElement('div', {\r\n key: 'qr-container',\r\n className: \"mt-4 p-4 border border-gray-600/30 rounded-lg text-center\"\r\n }, [\r\n React.createElement('h4', {\r\n key: 'qr-title',\r\n className: \"text-sm font-medium text-primary mb-3\"\r\n }, 'Scan QR code to connect'),\r\n React.createElement('div', {\r\n key: 'qr-wrapper',\r\n className: \"flex justify-center\"\r\n }, [\r\n React.createElement('img', {\r\n key: 'qr-image',\r\n src: qrCodeUrl,\r\n alt: \"QR Code for secure connection\",\r\n className: \"max-w-none h-auto border border-gray-600/30 rounded w-[20rem] sm:w-[24rem] md:w-[28rem] lg:w-[32rem]\"\r\n })\r\n ]),\r\n\r\n ((qrFramesTotal || 0) >= 1) && React.createElement('div', {\r\n key: 'qr-controls-below',\r\n className: \"mt-4 flex flex-col items-center gap-2\"\r\n }, [\r\n React.createElement('div', {\r\n key: 'frame-indicator',\r\n className: \"text-xs text-gray-300\"\r\n }, `Frame ${Math.max(1, (qrFrameIndex || 1))}/${qrFramesTotal || 1}`),\r\n React.createElement('div', {\r\n key: 'control-buttons',\r\n className: \"flex gap-1\"\r\n }, [\r\n (qrFramesTotal || 0) > 1 && React.createElement('button', {\r\n key: 'prev-frame',\r\n onClick: prevQrFrame,\r\n className: \"w-6 h-6 bg-gray-600 hover:bg-gray-500 text-white rounded text-xs flex items-center justify-center\"\r\n }, '\u25C0'),\r\n React.createElement('button', {\r\n key: 'toggle-manual',\r\n onClick: toggleQrManualMode,\r\n className: `px-2 py-1 rounded text-xs font-medium ${\r\n (qrManualMode || false)\r\n ? 'bg-blue-500 text-white' \r\n : 'bg-gray-600 text-gray-300 hover:bg-gray-500'\r\n }`\r\n }, (qrManualMode || false) ? 'Manual' : 'Auto'),\r\n (qrFramesTotal || 0) > 1 && React.createElement('button', {\r\n key: 'next-frame',\r\n onClick: nextQrFrame,\r\n className: \"w-6 h-6 bg-gray-600 hover:bg-gray-500 text-white rounded text-xs flex items-center justify-center\"\r\n }, '\u25B6')\r\n ])\r\n ]),\r\n React.createElement('p', {\r\n key: 'qr-description',\r\n className: \"text-xs text-gray-400 mt-2\"\r\n }, 'Your contact can scan this QR code to quickly join the secure session')\r\n ])\r\n ])\r\n ])\r\n ]), \r\n \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('div', {\r\n key: 'buttons',\r\n className: \"flex gap-2 mb-4\"\r\n }, [\r\n React.createElement('button', {\r\n key: 'scan-btn',\r\n onClick: () => setShowQRScannerModal(true),\r\n className: \"px-4 py-2 bg-purple-500/10 hover:bg-purple-500/20 text-purple-400 border border-purple-500/20 rounded text-sm font-medium transition-all duration-200\"\r\n }, [\r\n React.createElement('i', {\r\n key: 'icon',\r\n className: 'fas fa-qrcode mr-2'\r\n }),\r\n 'Scan QR Code'\r\n ]),\r\n ]),\r\n React.createElement('textarea', {\r\n key: 'input',\r\n value: answerInput,\r\n onChange: (e) => {\r\n setAnswerInput(e.target.value);\r\n // Mark answer as created when user manually enters data\r\n if (e.target.value.trim().length > 0) {\r\n if (typeof markAnswerCreated === 'function') {\r\n markAnswerCreated();\r\n }\r\n }\r\n\r\n },\r\n rows: 6,\r\n placeholder: \"Paste the encrypted response code from your contact or scan QR 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-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 (showAnswerStep ? null : 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) => {\r\n setOfferInput(e.target.value);\r\n if (e.target.value.trim().length > 0) {\r\n if (typeof markAnswerCreated === 'function') {\r\n markAnswerCreated();\r\n }\r\n }\r\n },\r\n rows: 8,\r\n placeholder: \"Paste the encrypted invitation code or scan QR 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('div', {\r\n key: 'buttons',\r\n className: \"flex gap-2 mb-4\"\r\n }, [\r\n React.createElement('button', {\r\n key: 'scan-btn',\r\n onClick: () => setShowQRScannerModal(true),\r\n className: \"px-4 py-2 bg-purple-500/10 hover:bg-purple-500/20 text-purple-400 border border-purple-500/20 rounded text-sm font-medium transition-all duration-200\"\r\n }, [\r\n React.createElement('i', {\r\n key: 'icon',\r\n className: 'fas fa-qrcode mr-2'\r\n }),\r\n 'Scan QR Code'\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: \"flex-1 btn-secondary text-white py-2 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 invitation'\r\n ])\r\n ]),\r\n showQRScanner && React.createElement('div', {\r\n key: 'qr-scanner',\r\n className: \"p-4 bg-gray-800/50 border border-gray-600/30 rounded-lg text-center\"\r\n }, [\r\n React.createElement('h4', {\r\n key: 'scanner-title',\r\n className: \"text-sm font-medium text-primary mb-3\"\r\n }, 'QR Code Scanner'),\r\n React.createElement('p', {\r\n key: 'scanner-description',\r\n className: \"text-xs text-gray-400 mb-3\"\r\n }, 'Use your device camera to scan the QR code from the invitation'),\r\n React.createElement('button', {\r\n key: 'open-scanner',\r\n onClick: () => {\r\n if (typeof setShowQRScannerModal === 'function') {\r\n setShowQRScannerModal(true);\r\n } else {\r\n console.error('setShowQRScannerModal is not a function:', setShowQRScannerModal);\r\n }\r\n },\r\n className: \"w-full px-4 py-3 bg-purple-600 hover:bg-purple-500 text-white rounded-lg font-medium transition-all duration-200 mb-3\"\r\n }, [\r\n React.createElement('i', {\r\n key: 'camera-icon',\r\n className: 'fas fa-camera mr-2'\r\n }),\r\n 'Open Camera Scanner'\r\n ]),\r\n React.createElement('button', {\r\n key: 'test-qr',\r\n onClick: async () => {\r\n console.log('Creating test QR code...');\r\n if (window.generateQRCode) {\r\n const testData = '{\"type\":\"test\",\"message\":\"Hello QR Scanner!\"}';\r\n const qrUrl = await window.generateQRCode(testData);\r\n console.log('Test QR code generated:', qrUrl);\r\n const newWindow = window.open();\r\n newWindow.document.write(``);\r\n }\r\n },\r\n className: \"px-3 py-1 bg-green-600/20 hover:bg-green-600/30 text-green-300 border border-green-500/20 rounded text-xs font-medium transition-all duration-200 mr-2\"\r\n }, 'Test QR'),\r\n React.createElement('button', {\r\n key: 'close-scanner',\r\n onClick: () => setShowQRScanner(false),\r\n className: \"px-3 py-1 bg-gray-600/20 hover:bg-gray-600/30 text-gray-300 border border-gray-500/20 rounded text-xs font-medium transition-all duration-200\"\r\n }, 'Close Scanner')\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 // Raw JSON hidden intentionally; users copy compressed string or use QR\r\n React.createElement(EnhancedCopyButton, {\r\n key: 'copy',\r\n text: (() => {\r\n try {\r\n const min = typeof answerData === 'object' ? JSON.stringify(answerData) : (answerData || '');\r\n if (typeof window.encodeBinaryToPrefixed === 'function') {\r\n return window.encodeBinaryToPrefixed(min);\r\n }\r\n if (typeof window.compressToPrefixedGzip === 'function') {\r\n return window.compressToPrefixedGzip(min);\r\n }\r\n return min;\r\n } catch { return typeof answerData === 'object' ? JSON.stringify(answerData) : (answerData || ''); }\r\n })(),\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 // QR Code section for answer\r\n qrCodeUrl && React.createElement('div', {\r\n key: 'qr-container',\r\n className: \"mt-4 p-4 border border-gray-600/30 rounded-lg text-center\"\r\n }, [\r\n React.createElement('h4', {\r\n key: 'qr-title',\r\n className: \"text-sm font-medium text-primary mb-3\"\r\n }, 'Scan QR code to complete connection'),\r\n React.createElement('div', {\r\n key: 'qr-wrapper',\r\n className: \"flex justify-center\"\r\n }, [\r\n React.createElement('img', {\r\n key: 'qr-image',\r\n src: qrCodeUrl,\r\n alt: \"QR Code for secure response\",\r\n className: \"max-w-none h-auto border border-gray-600/30 rounded w-[20rem] sm:w-[24rem] md:w-[28rem] lg:w-[32rem]\"\r\n })\r\n ]),\r\n\r\n ((qrFramesTotal || 0) >= 1) && React.createElement('div', {\r\n key: 'qr-controls-below',\r\n className: \"mt-4 flex flex-col items-center gap-2\"\r\n }, [\r\n React.createElement('div', {\r\n key: 'frame-indicator',\r\n className: \"text-xs text-gray-300\"\r\n }, `Frame ${Math.max(1, (qrFrameIndex || 1))}/${qrFramesTotal || 1}`),\r\n React.createElement('div', {\r\n key: 'control-buttons',\r\n className: \"flex gap-1\"\r\n }, [\r\n (qrFramesTotal || 0) > 1 && React.createElement('button', {\r\n key: 'prev-frame',\r\n onClick: prevQrFrame,\r\n className: \"w-6 h-6 bg-gray-600 hover:bg-gray-500 text-white rounded text-xs flex items-center justify-center\"\r\n }, '\u25C0'),\r\n React.createElement('button', {\r\n key: 'toggle-manual',\r\n onClick: toggleQrManualMode,\r\n className: `px-2 py-1 rounded text-xs font-medium ${\r\n qrManualMode \r\n ? 'bg-blue-500 text-white' \r\n : 'bg-gray-600 text-gray-300 hover:bg-gray-500'\r\n }`\r\n }, qrManualMode ? 'Manual' : 'Auto'),\r\n (qrFramesTotal || 0) > 1 && React.createElement('button', {\r\n key: 'next-frame',\r\n onClick: nextQrFrame,\r\n className: \"w-6 h-6 bg-gray-600 hover:bg-gray-500 text-white rounded text-xs flex items-center justify-center\"\r\n }, '\u25B6')\r\n ])\r\n ]),\r\n React.createElement('p', {\r\n key: 'qr-description',\r\n className: \"text-xs text-gray-400 mt-2\"\r\n }, 'The initiator can scan this QR code to complete the secure connection')\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 // Global scroll function - defined outside components to ensure availability\r\n const createScrollToBottomFunction = (chatMessagesRef) => {\r\n return () => {\r\n if (chatMessagesRef && 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 \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 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 console.log('\uD83D\uDD0D handleScrollToBottom called, scrollToBottom type:', typeof scrollToBottom);\r\n if (typeof scrollToBottom === 'function') {\r\n scrollToBottom();\r\n setShowScrollButton(false);\r\n } else {\r\n console.error('scrollToBottom is not a function:', scrollToBottom);\r\n // Fallback: direct scroll\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 setShowScrollButton(false);\r\n }\r\n };\r\n\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 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 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 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 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\r\n const [messages, setMessages] = React.useState([]);\r\n const [connectionStatus, setConnectionStatus] = React.useState('disconnected');\r\n \r\n // Moved scrollToBottom logic to be available globally\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 [showQRCode, setShowQRCode] = React.useState(false);\r\n const [qrCodeUrl, setQrCodeUrl] = React.useState('');\r\n const [showQRScanner, setShowQRScanner] = React.useState(false);\r\n const [showQRScannerModal, setShowQRScannerModal] = React.useState(false);\r\n const [isGeneratingKeys, setIsGeneratingKeys] = React.useState(false);\r\n \r\n\r\n const [isVerified, setIsVerified] = React.useState(false);\r\n const [securityLevel, setSecurityLevel] = React.useState(null);\r\n const [sessionTimeLeft, setSessionTimeLeft] = React.useState(0);\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 // Session state - all security features enabled by default\r\n const [pendingSession, setPendingSession] = React.useState(null);\r\n \r\n // All security features are enabled by default - no payment required\r\n \r\n \r\n \r\n // ============================================\r\n // CENTRALIZED CONNECTION STATE MANAGEMENT\r\n // ============================================\r\n \r\n const [connectionState, setConnectionState] = React.useState({\r\n status: 'disconnected',\r\n hasActiveAnswer: false,\r\n answerCreatedAt: null,\r\n isUserInitiatedDisconnect: false\r\n });\r\n \r\n // Centralized connection state handler\r\n const updateConnectionState = (newState, options = {}) => {\r\n const { preserveAnswer = false, isUserAction = false } = options;\r\n \r\n setConnectionState(prev => ({\r\n ...prev,\r\n ...newState,\r\n isUserInitiatedDisconnect: isUserAction,\r\n hasActiveAnswer: preserveAnswer ? prev.hasActiveAnswer : false,\r\n answerCreatedAt: preserveAnswer ? prev.answerCreatedAt : null\r\n }));\r\n };\r\n \r\n // Check if we should preserve answer data\r\n const shouldPreserveAnswerData = () => {\r\n const now = Date.now();\r\n const answerAge = now - (connectionState.answerCreatedAt || 0);\r\n const maxPreserveTime = 300000;\r\n \r\n\r\n const hasAnswerData = (answerData && typeof answerData === 'string' && answerData.trim().length > 0) || \r\n (answerInput && answerInput.trim().length > 0);\r\n\r\n const hasAnswerQR = qrCodeUrl && qrCodeUrl.trim().length > 0;\r\n \r\n const shouldPreserve = (connectionState.hasActiveAnswer && \r\n answerAge < maxPreserveTime && \r\n !connectionState.isUserInitiatedDisconnect) ||\r\n (hasAnswerData && answerAge < maxPreserveTime && \r\n !connectionState.isUserInitiatedDisconnect) ||\r\n (hasAnswerQR && answerAge < maxPreserveTime && \r\n !connectionState.isUserInitiatedDisconnect);\r\n \r\n \r\n return shouldPreserve;\r\n };\r\n \r\n // Mark answer as created\r\n const markAnswerCreated = () => {\r\n updateConnectionState({\r\n hasActiveAnswer: true,\r\n answerCreatedAt: Date.now()\r\n });\r\n };\r\n \r\n // Global functions for cleanup\r\n React.useEffect(() => {\r\n window.forceCleanup = () => {\r\n handleClearData();\r\n if (webrtcManagerRef.current) {\r\n webrtcManagerRef.current.disconnect();\r\n }\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.forceCleanup;\r\n delete window.clearLogs;\r\n };\r\n }, []);\r\n \r\n const webrtcManagerRef = React.useRef(null);\r\n const notificationIntegrationRef = 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 // All security features are enabled by default - always show MAXIMUM level\r\n setSecurityLevel({\r\n level: 'MAXIMUM',\r\n score: 100,\r\n color: 'green',\r\n details: 'All security features enabled by default',\r\n passedChecks: 10,\r\n totalChecks: 10,\r\n isRealData: true\r\n });\r\n \r\n if (window.DEBUG_MODE) {\r\n const currentLevel = webrtcManagerRef.current.ecdhKeyPair && webrtcManagerRef.current.ecdsaKeyPair \r\n ? await webrtcManagerRef.current.calculateSecurityLevel()\r\n : {\r\n level: 'MAXIMUM',\r\n score: 100,\r\n sessionType: 'premium',\r\n passedChecks: 10,\r\n totalChecks: 10\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 removed - sessions are unlimited\r\n \r\n // Sessions are unlimited - no expiration handler needed\r\n \r\n // All security features are enabled by default - no demo sessions needed\r\n const chatMessagesRef = React.useRef(null);\r\n \r\n // Create scroll function using global helper\r\n const scrollToBottom = createScrollToBottomFunction(chatMessagesRef);\r\n \r\n // Auto-scroll when messages change\r\n React.useEffect(() => {\r\n if (messages.length > 0 && chatMessagesRef.current) {\r\n scrollToBottom();\r\n setTimeout(scrollToBottom, 50);\r\n setTimeout(scrollToBottom, 150);\r\n }\r\n }, [messages]);\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 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(`Blocked system/file message from chat: ${parsedMessage.type}`);\r\n return; \r\n }\r\n } catch (parseError) {\r\n\r\n }\r\n }\r\n \r\n addMessageWithAutoScroll(message, type);\r\n };\r\n \r\n const handleStatusChange = (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 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 setConnectionStatus('connected');\r\n // Force immediate update of isVerified state\r\n setTimeout(() => {\r\n setIsVerified(true);\r\n }, 0);\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 updateConnectionState({ status: 'disconnected' });\r\n setConnectionStatus('disconnected');\r\n\r\n if (shouldPreserveAnswerData()) {\r\n setIsVerified(false);\r\n setShowVerification(false);\r\n return;\r\n }\r\n\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('');\r\n setAnswerData('');\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 \r\n // Return to main page after a short delay\r\n setTimeout(() => {\r\n setConnectionStatus('disconnected');\r\n setShowVerification(false);\r\n \r\n setOfferData('');\r\n setAnswerData('');\r\n setOfferInput('');\r\n setAnswerInput('');\r\n setShowOfferStep(false);\r\n setShowAnswerStep(false);\r\n setMessages([]);\r\n }, 1000);\r\n\r\n } else if (status === 'peer_disconnected') {\r\n setSessionTimeLeft(0);\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('');\r\n setAnswerData('');\r\n setOfferInput('');\r\n setAnswerInput('');\r\n setShowOfferStep(false);\r\n setShowAnswerStep(false);\r\n setMessages([]);\r\n \r\n\r\n if (typeof console.clear === 'function') {\r\n console.clear();\r\n }\r\n\r\n }, 2000);\r\n }\r\n };\r\n \r\n const handleKeyExchange = (fingerprint) => {\r\n if (fingerprint === '') {\r\n setKeyFingerprint('');\r\n } else {\r\n setKeyFingerprint(fingerprint);\r\n }\r\n };\r\n \r\n const handleVerificationRequired = (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 }\r\n };\r\n \r\n const handleVerificationStateChange = (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 setSessionTimeLeft(0);\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 setSessionTimeLeft(0);\r\n setPendingSession(null);\r\n \r\n addMessageWithAutoScroll(` 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 \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 // Initialize notification integration if permission was already granted\r\n if (typeof Notification !== 'undefined' && Notification && Notification.permission === 'granted' && window.NotificationIntegration && !notificationIntegrationRef.current) {\r\n try {\r\n const integration = new window.NotificationIntegration(webrtcManagerRef.current);\r\n integration.init().then(() => {\r\n notificationIntegrationRef.current = integration;\r\n }).catch((error) => {\r\n // Handle error silently\r\n });\r\n } catch (error) {\r\n // Handle error silently\r\n }\r\n }\r\n \r\n handleMessage(' SecureBit.chat Enhanced Security Edition v4.7.56 - 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 \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 }\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 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 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 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' }, ` 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 setTimeout(() => fileData.revokeObjectURL(url), 15000);\r\n } catch (e) {\r\n console.error('Download failed:', e);\r\n addMessageWithAutoScroll(` 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(` File transfer error: connection not ready. Try again later.`, 'system');\r\n } else if (error.includes('File too large')) {\r\n addMessageWithAutoScroll(` File is too big. Maximum size: 100 MB`, 'system');\r\n } else {\r\n addMessageWithAutoScroll(` 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 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 // All security features are enabled by default - no session purchase needed\r\n \r\n const compressOfferData = (offerData) => {\r\n try {\r\n // Parse the offer data if it's a string\r\n const offer = typeof offerData === 'string' ? JSON.parse(offerData) : offerData;\r\n \r\n // Create a minimal version with only the most essential data\r\n const minimalOffer = {\r\n type: offer.type,\r\n version: offer.version,\r\n timestamp: offer.timestamp,\r\n sessionId: offer.sessionId,\r\n connectionId: offer.connectionId,\r\n verificationCode: offer.verificationCode,\r\n salt: offer.salt,\r\n // Use only key fingerprints instead of full keys\r\n keyFingerprints: offer.keyFingerprints,\r\n // Add a reference to get full data\r\n fullDataAvailable: true,\r\n compressionLevel: 'minimal'\r\n };\r\n \r\n return JSON.stringify(minimalOffer);\r\n } catch (error) {\r\n console.error('Error compressing offer data:', error);\r\n return offerData; // Return original if compression fails\r\n }\r\n };\r\n\r\n const createQRReference = (offerData) => {\r\n try {\r\n // Create a unique reference ID for this offer\r\n const referenceId = `offer_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;\r\n \r\n // Store the full offer data in localStorage with the reference ID\r\n localStorage.setItem(`qr_offer_${referenceId}`, JSON.stringify(offerData));\r\n \r\n // Create a minimal QR code with just the reference\r\n const qrReference = {\r\n type: 'secure_offer_reference',\r\n referenceId: referenceId,\r\n timestamp: Date.now(),\r\n message: 'Scan this QR code and use the reference ID to get full offer data'\r\n };\r\n \r\n return JSON.stringify(qrReference);\r\n } catch (error) {\r\n console.error('Error creating QR reference:', error);\r\n return null;\r\n }\r\n };\r\n\r\n const createTemplateOffer = (offer) => {\r\n // Minimal template to keep QR within single image capacity\r\n const templateOffer = {\r\n type: 'enhanced_secure_offer_template',\r\n version: '4.0',\r\n sessionId: offer.sessionId,\r\n connectionId: offer.connectionId,\r\n verificationCode: offer.verificationCode,\r\n timestamp: offer.timestamp,\r\n // Avoid bulky fields (SDP, raw keys); keep only fingerprints and essentials\r\n keyFingerprints: offer.keyFingerprints,\r\n // Keep concise auth hints (omit large nonces)\r\n authChallenge: offer?.authChallenge?.challenge,\r\n // Optionally include a compact capability hint if small\r\n capabilities: Array.isArray(offer.capabilities) && offer.capabilities.length <= 5\r\n ? offer.capabilities\r\n : undefined\r\n };\r\n \r\n return templateOffer;\r\n };\r\n\r\n // Conservative QR payload limits (characters). Adjust per error correction level.\r\n const MAX_QR_LEN = 800; // for JSON/plain/gzip\r\n const BIN_MAX_QR_LEN = 400; // stricter for SB1:bin to improve scan reliability\r\n const [qrFramesTotal, setQrFramesTotal] = React.useState(0);\r\n const [qrFrameIndex, setQrFrameIndex] = React.useState(0);\r\n const [qrManualMode, setQrManualMode] = React.useState(false);\r\n\r\n // Animated QR state (for multi-chunk COSE)\r\n const qrAnimationRef = React.useRef({ timer: null, chunks: [], idx: 0, active: false });\r\n const stopQrAnimation = () => {\r\n try { if (qrAnimationRef.current.timer) { clearInterval(qrAnimationRef.current.timer); } } catch {}\r\n qrAnimationRef.current = { timer: null, chunks: [], idx: 0, active: false };\r\n setQrFrameIndex(0);\r\n setQrFramesTotal(0);\r\n setQrManualMode(false);\r\n };\r\n\r\n // Render frame at current index (no index mutation)\r\n const renderCurrent = async () => {\r\n const { chunks, idx } = qrAnimationRef.current || {};\r\n if (!chunks || !chunks.length) return;\r\n const current = chunks[idx % chunks.length];\r\n try {\r\n const isDesktop = (typeof window !== 'undefined') && ((window.innerWidth || 0) >= 1024);\r\n const QR_SIZE = isDesktop ? 720 : 512;\r\n const url = await (window.generateQRCode ? window.generateQRCode(current, { errorCorrectionLevel: 'M', margin: 2, size: QR_SIZE }) : Promise.resolve(''));\r\n if (url) setQrCodeUrl(url);\r\n } catch (e) {\r\n console.warn('Animated QR render error (current):', e);\r\n }\r\n setQrFrameIndex(((qrAnimationRef.current?.idx || 0) % (qrAnimationRef.current?.chunks?.length || 1)) + 1);\r\n };\r\n\r\n // Render current frame, then advance index by 1\r\n const renderAndAdvance = async () => {\r\n await renderCurrent();\r\n const len = qrAnimationRef.current?.chunks?.length || 0;\r\n if (len > 0) {\r\n const nextIdx = ((qrAnimationRef.current?.idx || 0) + 1) % len;\r\n qrAnimationRef.current.idx = nextIdx;\r\n setQrFrameIndex(nextIdx + 1);\r\n }\r\n };\r\n\r\n const toggleQrManualMode = () => {\r\n const newManualMode = !qrManualMode;\r\n setQrManualMode(newManualMode);\r\n \r\n if (newManualMode) {\r\n\r\n if (qrAnimationRef.current.timer) {\r\n clearInterval(qrAnimationRef.current.timer);\r\n qrAnimationRef.current.timer = null;\r\n }\r\n console.log('QR Manual mode enabled - auto-scroll stopped');\r\n } else {\r\n if (qrAnimationRef.current.chunks.length > 1) {\r\n const intervalMs = 3000;\r\n qrAnimationRef.current.active = true;\r\n clearInterval(qrAnimationRef.current.timer);\r\n qrAnimationRef.current.timer = setInterval(renderAndAdvance, intervalMs);\r\n }\r\n console.log('QR Manual mode disabled - auto-scroll resumed');\r\n }\r\n };\r\n\r\n const nextQrFrame = async () => {\r\n console.log('\uD83C\uDFAE nextQrFrame called, qrFramesTotal:', qrFramesTotal, 'qrAnimationRef.current:', qrAnimationRef.current);\r\n if (qrAnimationRef.current.chunks.length > 1) {\r\n const nextIdx = (qrAnimationRef.current.idx + 1) % qrAnimationRef.current.chunks.length;\r\n qrAnimationRef.current.idx = nextIdx;\r\n setQrFrameIndex(nextIdx + 1);\r\n console.log('\uD83C\uDFAE Next frame index:', nextIdx + 1);\r\n // Ensure auto-advance timer runs in manual mode too\r\n try { clearInterval(qrAnimationRef.current.timer); } catch {}\r\n qrAnimationRef.current.timer = null;\r\n await renderCurrent();\r\n // If not in manual mode, restart auto timer\r\n if (!qrManualMode && qrAnimationRef.current.chunks.length > 1) {\r\n const intervalMs = 3000;\r\n qrAnimationRef.current.active = true;\r\n qrAnimationRef.current.timer = setInterval(renderAndAdvance, intervalMs);\r\n } else {\r\n qrAnimationRef.current.active = false;\r\n }\r\n } else {\r\n console.log('\uD83C\uDFAE No multiple frames to navigate');\r\n }\r\n };\r\n\r\n const prevQrFrame = async () => {\r\n console.log('\uD83C\uDFAE prevQrFrame called, qrFramesTotal:', qrFramesTotal, 'qrAnimationRef.current:', qrAnimationRef.current);\r\n if (qrAnimationRef.current.chunks.length > 1) {\r\n const prevIdx = (qrAnimationRef.current.idx - 1 + qrAnimationRef.current.chunks.length) % qrAnimationRef.current.chunks.length;\r\n qrAnimationRef.current.idx = prevIdx;\r\n setQrFrameIndex(prevIdx + 1);\r\n console.log('\uD83C\uDFAE Previous frame index:', prevIdx + 1);\r\n try { clearInterval(qrAnimationRef.current.timer); } catch {}\r\n qrAnimationRef.current.timer = null;\r\n await renderCurrent();\r\n if (!qrManualMode && qrAnimationRef.current.chunks.length > 1) {\r\n const intervalMs = 3000;\r\n qrAnimationRef.current.active = true;\r\n qrAnimationRef.current.timer = setInterval(renderAndAdvance, intervalMs);\r\n } else {\r\n qrAnimationRef.current.active = false;\r\n }\r\n } else {\r\n console.log('\uD83C\uDFAE No multiple frames to navigate');\r\n }\r\n };\r\n\r\n // Buffer for assembling scanned COSE chunks\r\n const qrChunksBufferRef = React.useRef({ id: null, total: 0, seen: new Set(), items: [] });\r\n\r\n const generateQRCode = async (data) => {\r\n try {\r\n const originalSize = typeof data === 'string' ? data.length : JSON.stringify(data).length;\r\n const isDesktop = (typeof window !== 'undefined') && ((window.innerWidth || 0) >= 1024);\r\n const QR_SIZE = isDesktop ? 720 : 512;\r\n \r\n // Try binary format first (CBOR + deflate + base64url)\r\n if (typeof window.generateBinaryQRCodeFromObject === 'function') {\r\n try {\r\n const obj = typeof data === 'string' ? JSON.parse(data) : data;\r\n const qrDataUrl = await window.generateBinaryQRCodeFromObject(obj, { errorCorrectionLevel: 'M', size: QR_SIZE, margin: 2 });\r\n if (qrDataUrl) {\r\n try { if (qrAnimationRef.current && qrAnimationRef.current.timer) { clearInterval(qrAnimationRef.current.timer); } } catch {}\r\n qrAnimationRef.current = { timer: null, chunks: [], idx: 0, active: false };\r\n setQrFrameIndex(0);\r\n setQrFramesTotal(0);\r\n setQrManualMode(false);\r\n setQrCodeUrl(qrDataUrl);\r\n setQrFramesTotal(1);\r\n setQrFrameIndex(1);\r\n return;\r\n }\r\n } catch (e) {\r\n console.warn('Binary QR generation failed, falling back to compressed:', e?.message || e);\r\n }\r\n }\r\n \r\n // Fallback to compressed JSON\r\n if (typeof window.generateCompressedQRCode === 'function') {\r\n try {\r\n const payload = typeof data === 'string' ? data : JSON.stringify(data);\r\n const qrDataUrl = await window.generateCompressedQRCode(payload, { errorCorrectionLevel: 'M', size: QR_SIZE, margin: 2 });\r\n if (qrDataUrl) {\r\n try { if (qrAnimationRef.current && qrAnimationRef.current.timer) { clearInterval(qrAnimationRef.current.timer); } } catch {}\r\n qrAnimationRef.current = { timer: null, chunks: [], idx: 0, active: false };\r\n setQrFrameIndex(0);\r\n setQrFramesTotal(0);\r\n setQrManualMode(false);\r\n setQrCodeUrl(qrDataUrl);\r\n setQrFramesTotal(1);\r\n setQrFrameIndex(1);\r\n return;\r\n }\r\n } catch (e) {\r\n console.warn('Compressed QR generation failed, falling back to plain:', e?.message || e);\r\n }\r\n }\r\n \r\n // Final fallback to plain JSON\r\n const payload = typeof data === 'string' ? data : JSON.stringify(data);\r\n if (payload.length <= MAX_QR_LEN) {\r\n if (!window.generateQRCode) throw new Error('QR code generator unavailable');\r\n try { if (qrAnimationRef.current && qrAnimationRef.current.timer) { clearInterval(qrAnimationRef.current.timer); } } catch {}\r\n qrAnimationRef.current = { timer: null, chunks: [], idx: 0, active: false };\r\n setQrFrameIndex(0);\r\n setQrFramesTotal(0);\r\n setQrManualMode(false);\r\n const qrDataUrl = await window.generateQRCode(payload, { errorCorrectionLevel: 'M', size: QR_SIZE, margin: 2 });\r\n setQrCodeUrl(qrDataUrl);\r\n setQrFramesTotal(1);\r\n setQrFrameIndex(1);\r\n return;\r\n }\r\n\r\n // Large payload: \u0440\u0430\u0437\u0431\u0438\u0432\u0430\u0435\u043C \u043D\u0430 \u0444\u0440\u0435\u0439\u043C\u044B (plain JSON)\r\n try { if (qrAnimationRef.current && qrAnimationRef.current.timer) { clearInterval(qrAnimationRef.current.timer); } } catch {}\r\n qrAnimationRef.current = { timer: null, chunks: [], idx: 0, active: false };\r\n setQrFrameIndex(0);\r\n setQrFramesTotal(0);\r\n setQrManualMode(false);\r\n const id = `raw_${Date.now()}_${Math.random().toString(36).slice(2)}`;\r\n\r\n const TARGET_CHUNKS = 10;\r\n const FRAME_MAX = Math.max(200, Math.floor(payload.length / TARGET_CHUNKS));\r\n const total = Math.ceil(payload.length / FRAME_MAX);\r\n const rawChunks = [];\r\n for (let i = 0; i < total; i++) {\r\n const seq = i + 1;\r\n const part = payload.slice(i * FRAME_MAX, (i + 1) * FRAME_MAX);\r\n rawChunks.push(JSON.stringify({ hdr: { v: 1, id, seq, total, rt: 'raw' }, body: part }));\r\n }\r\n if (!window.generateQRCode) throw new Error('QR code generator unavailable');\r\n if (rawChunks.length === 1) {\r\n const url = await window.generateQRCode(rawChunks[0], { errorCorrectionLevel: 'M', margin: 2, size: QR_SIZE });\r\n setQrCodeUrl(url);\r\n setQrFramesTotal(1);\r\n setQrFrameIndex(1);\r\n return;\r\n }\r\n qrAnimationRef.current.chunks = rawChunks;\r\n qrAnimationRef.current.idx = 0;\r\n qrAnimationRef.current.active = true;\r\n setQrFramesTotal(rawChunks.length);\r\n setQrFrameIndex(1);\r\n const EC_OPTS = { errorCorrectionLevel: 'M', margin: 2, size: QR_SIZE };\r\n await renderNext();\r\n\r\n if (!qrManualMode) {\r\n const intervalMs = 4000; // 4 seconds per frame for better readability\r\n qrAnimationRef.current.active = true;\r\n qrAnimationRef.current.timer = setInterval(renderAndAdvance, intervalMs);\r\n }\r\n return;\r\n } catch (error) {\r\n console.error('QR code generation failed:', error);\r\n setMessages(prev => [...prev, {\r\n message: ` QR code generation failed: ${error.message}`,\r\n type: 'error'\r\n }]);\r\n }\r\n };\r\n\r\n const reconstructFromTemplate = (templateData) => {\r\n // Reconstruct full offer from template\r\n const fullOffer = {\r\n type: \"enhanced_secure_offer\",\r\n version: templateData.version,\r\n timestamp: templateData.timestamp,\r\n sessionId: templateData.sessionId,\r\n connectionId: templateData.connectionId,\r\n verificationCode: templateData.verificationCode,\r\n salt: templateData.salt,\r\n sdp: templateData.sdp,\r\n keyFingerprints: templateData.keyFingerprints,\r\n capabilities: templateData.capabilities,\r\n \r\n // Reconstruct ECDH key object\r\n ecdhPublicKey: {\r\n keyType: \"ECDH\",\r\n keyData: templateData.ecdhKeyData,\r\n timestamp: templateData.timestamp - 1000, // Approximate\r\n version: templateData.version,\r\n signature: templateData.ecdhSignature\r\n },\r\n \r\n // Reconstruct ECDSA key object\r\n ecdsaPublicKey: {\r\n keyType: \"ECDSA\",\r\n keyData: templateData.ecdsaKeyData,\r\n timestamp: templateData.timestamp - 999, // Approximate\r\n version: templateData.version,\r\n signature: templateData.ecdsaSignature\r\n },\r\n \r\n // Reconstruct auth challenge\r\n authChallenge: {\r\n challenge: templateData.authChallenge,\r\n timestamp: templateData.timestamp,\r\n nonce: templateData.authNonce,\r\n version: templateData.version\r\n },\r\n \r\n // Generate security level (can be recalculated)\r\n securityLevel: {\r\n level: \"CRITICAL\",\r\n score: 20,\r\n color: \"red\",\r\n verificationResults: {\r\n encryption: { passed: false, details: \"Encryption not working\", points: 0 },\r\n keyExchange: { passed: true, details: \"Simple key exchange verified\", points: 15 },\r\n messageIntegrity: { passed: false, details: \"Message integrity failed\", points: 0 },\r\n rateLimiting: { passed: true, details: \"Rate limiting active\", points: 5 },\r\n ecdsa: { passed: false, details: \"Enhanced session required - feature not available\", points: 0 },\r\n metadataProtection: { passed: false, details: \"Enhanced session required - feature not available\", points: 0 },\r\n pfs: { passed: false, details: \"Enhanced session required - feature not available\", points: 0 },\r\n nestedEncryption: { passed: false, details: \"Enhanced session required - feature not available\", points: 0 },\r\n packetPadding: { passed: false, details: \"Enhanced session required - feature not available\", points: 0 },\r\n advancedFeatures: { passed: false, details: \"Premium session required - feature not available\", points: 0 }\r\n },\r\n timestamp: templateData.timestamp,\r\n details: \"Real verification: 20/100 security checks passed (2/4 available)\",\r\n isRealData: true,\r\n passedChecks: 2,\r\n totalChecks: 4,\r\n sessionType: \"demo\",\r\n maxPossibleScore: 50\r\n }\r\n };\r\n \r\n return fullOffer;\r\n };\r\n\r\n const handleQRScan = async (scannedData) => {\r\n try {\r\n console.log('QR Code scanned:', scannedData.substring(0, 100) + '...');\r\n console.log('Current buffer state:', qrChunksBufferRef.current);\r\n \r\n // Check if this is a binary chunk (starts with SB1:bin: or is a raw binary chunk)\r\n if (scannedData.startsWith('SB1:bin:') || (qrChunksBufferRef.current && qrChunksBufferRef.current.id)) {\r\n console.log('Binary chunk detected:', scannedData.substring(0, 50) + '...');\r\n \r\n // This is a binary chunk - add to buffer\r\n if (!qrChunksBufferRef.current.id) {\r\n console.log('Initializing buffer for binary chunks');\r\n // Initialize buffer for binary chunks\r\n qrChunksBufferRef.current = { \r\n id: `bin_${Date.now()}`, \r\n total: 4, // We expect 4 chunks\r\n seen: new Set(), \r\n items: [],\r\n lastUpdateMs: Date.now()\r\n };\r\n }\r\n \r\n // Add chunk to buffer (use data hash as identifier)\r\n const chunkHash = scannedData.substring(0, 50); // Use first 50 chars as hash\r\n \r\n // Check if this chunk was already scanned\r\n if (qrChunksBufferRef.current.seen.has(chunkHash)) {\r\n console.log(`Chunk already scanned, ignoring...`);\r\n return Promise.resolve(false);\r\n }\r\n \r\n qrChunksBufferRef.current.seen.add(chunkHash);\r\n qrChunksBufferRef.current.items.push(scannedData);\r\n qrChunksBufferRef.current.lastUpdateMs = Date.now();\r\n \r\n // Emit progress and force re-render\r\n try {\r\n const uniqueCount = qrChunksBufferRef.current.seen.size;\r\n document.dispatchEvent(new CustomEvent('qr-scan-progress', { \r\n detail: { \r\n id: qrChunksBufferRef.current.id, \r\n seq: uniqueCount, \r\n total: qrChunksBufferRef.current.total \r\n } \r\n }));\r\n \r\n // Force re-render to update progress indicator\r\n setQrFramesTotal(qrChunksBufferRef.current.total);\r\n setQrFrameIndex(uniqueCount);\r\n } catch {}\r\n \r\n // Check if we have all chunks\r\n const isComplete = qrChunksBufferRef.current.seen.size >= qrChunksBufferRef.current.total;\r\n console.log(`Chunks collected: ${qrChunksBufferRef.current.seen.size}/${qrChunksBufferRef.current.total}, complete: ${isComplete}`);\r\n \r\n if (!isComplete) {\r\n // Keep scanner open for more chunks\r\n console.log(`Scanned chunk ${qrChunksBufferRef.current.seen.size}/${qrChunksBufferRef.current.total}, waiting for more...`);\r\n return Promise.resolve(false);\r\n }\r\n \r\n // All chunks collected - reconstruct binary data\r\n try {\r\n const fullBinaryData = qrChunksBufferRef.current.items.join('');\r\n // Store the original binary data, not decoded JSON\r\n if (showOfferStep) {\r\n setAnswerInput(fullBinaryData);\r\n } else {\r\n setOfferInput(fullBinaryData);\r\n }\r\n \r\n setMessages(prev => [...prev, { \r\n message: 'All binary chunks captured. Payload reconstructed.', \r\n type: 'success' \r\n }]);\r\n \r\n // Clear buffer and close scanner\r\n qrChunksBufferRef.current = { id: null, total: 0, seen: new Set(), items: [] };\r\n setShowQRScannerModal(false);\r\n return Promise.resolve(true);\r\n } catch (e) {\r\n console.warn('Binary chunks reconstruction failed:', e);\r\n return Promise.resolve(false);\r\n }\r\n }\r\n \r\n // Check if this might be a binary chunk (long string without JSON structure)\r\n if (scannedData.length > 100 && !scannedData.startsWith('{') && !scannedData.startsWith('[')) {\r\n console.log('Detected potential binary chunk (long non-JSON string):', scannedData.substring(0, 50) + '...');\r\n \r\n // Initialize buffer if not exists\r\n if (!qrChunksBufferRef.current.id) {\r\n console.log('Initializing buffer for potential binary chunks');\r\n qrChunksBufferRef.current = { \r\n id: `bin_${Date.now()}`, \r\n total: 4, // We expect 4 chunks\r\n seen: new Set(), \r\n items: [],\r\n lastUpdateMs: Date.now()\r\n };\r\n }\r\n \r\n // Add chunk to buffer (use data hash as identifier)\r\n const chunkHash = scannedData.substring(0, 50); // Use first 50 chars as hash\r\n \r\n // Check if this chunk was already scanned\r\n if (qrChunksBufferRef.current.seen.has(chunkHash)) {\r\n console.log(`Chunk already scanned, ignoring...`);\r\n return Promise.resolve(false);\r\n }\r\n \r\n qrChunksBufferRef.current.seen.add(chunkHash);\r\n qrChunksBufferRef.current.items.push(scannedData);\r\n qrChunksBufferRef.current.lastUpdateMs = Date.now();\r\n \r\n // Force re-render to update progress indicator\r\n try {\r\n const uniqueCount = qrChunksBufferRef.current.seen.size;\r\n document.dispatchEvent(new CustomEvent('qr-scan-progress', { \r\n detail: { \r\n id: qrChunksBufferRef.current.id, \r\n seq: uniqueCount, \r\n total: qrChunksBufferRef.current.total \r\n } \r\n }));\r\n \r\n // Force re-render to update progress indicator\r\n setQrFramesTotal(qrChunksBufferRef.current.total);\r\n setQrFrameIndex(uniqueCount);\r\n } catch {}\r\n \r\n // Check if we have all chunks\r\n const isComplete = qrChunksBufferRef.current.seen.size >= qrChunksBufferRef.current.total;\r\n console.log(`Chunks collected: ${qrChunksBufferRef.current.seen.size}/${qrChunksBufferRef.current.total}, complete: ${isComplete}`);\r\n \r\n if (!isComplete) {\r\n // Keep scanner open for more chunks\r\n console.log(`Scanned chunk ${qrChunksBufferRef.current.seen.size}/${qrChunksBufferRef.current.total}, waiting for more...`);\r\n return Promise.resolve(false);\r\n }\r\n \r\n // All chunks collected - reconstruct binary data\r\n try {\r\n const fullBinaryData = qrChunksBufferRef.current.items.join('');\r\n // Store the original binary data, not decoded JSON\r\n if (showOfferStep) {\r\n setAnswerInput(fullBinaryData);\r\n } else {\r\n setOfferInput(fullBinaryData);\r\n }\r\n \r\n setMessages(prev => [...prev, { \r\n message: 'All binary chunks captured. Payload reconstructed.', \r\n type: 'success' \r\n }]);\r\n \r\n // Clear buffer and close scanner\r\n qrChunksBufferRef.current = { id: null, total: 0, seen: new Set(), items: [] };\r\n setShowQRScannerModal(false);\r\n return Promise.resolve(true);\r\n } catch (e) {\r\n console.warn('Binary chunks reconstruction failed:', e);\r\n return Promise.resolve(false);\r\n }\r\n }\r\n \r\n // Single QR code - try to decode directly\r\n // Removed verbose debug log\r\n let parsedData;\r\n if (typeof window.decodeAnyPayload === 'function') {\r\n const any = window.decodeAnyPayload(scannedData);\r\n if (typeof any === 'string') {\r\n parsedData = JSON.parse(any);\r\n } else {\r\n parsedData = any; // object from binary\r\n }\r\n } else {\r\n const maybeDecompressed = (typeof window.decompressIfNeeded === 'function') ? window.decompressIfNeeded(scannedData) : scannedData;\r\n parsedData = JSON.parse(maybeDecompressed);\r\n }\r\n console.log('Decoded data:', parsedData);\r\n \r\n // QR with hdr/body: COSE or RAW/BIN animated frames\r\n if (parsedData.hdr && parsedData.body) {\r\n const { hdr } = parsedData;\r\n // Initialize/rotate buffer by id\r\n if (!qrChunksBufferRef.current.id || qrChunksBufferRef.current.id !== hdr.id) {\r\n qrChunksBufferRef.current = { id: hdr.id, total: hdr.total || 1, seen: new Set(), items: [], lastUpdateMs: Date.now() };\r\n try {\r\n document.dispatchEvent(new CustomEvent('qr-scan-progress', { detail: { id: hdr.id, seq: 0, total: hdr.total || 1 } }));\r\n } catch {}\r\n }\r\n // Deduplicate & record\r\n if (!qrChunksBufferRef.current.seen.has(hdr.seq)) {\r\n qrChunksBufferRef.current.seen.add(hdr.seq);\r\n qrChunksBufferRef.current.items.push(scannedData);\r\n qrChunksBufferRef.current.lastUpdateMs = Date.now();\r\n }\r\n // Emit progress based on unique frames captured\r\n try {\r\n const uniqueCount = qrChunksBufferRef.current.seen.size;\r\n document.dispatchEvent(new CustomEvent('qr-scan-progress', { detail: { id: hdr.id, seq: uniqueCount, total: qrChunksBufferRef.current.total || hdr.total || 0 } }));\r\n } catch {}\r\n const isComplete = qrChunksBufferRef.current.seen.size >= (qrChunksBufferRef.current.total || 1);\r\n if (!isComplete) {\r\n // Explicitly keep scanner open\r\n return Promise.resolve(false);\r\n }\r\n // Completed: decide RAW vs BIN vs COSE\r\n if (hdr.rt === 'raw') {\r\n try {\r\n // Sort by seq and concatenate bodies\r\n const parts = qrChunksBufferRef.current.items\r\n .map(s => JSON.parse(s))\r\n .sort((a, b) => (a.hdr.seq || 0) - (b.hdr.seq || 0))\r\n .map(p => p.body || '');\r\n const fullText = parts.join('');\r\n const payloadObj = JSON.parse(fullText);\r\n if (showOfferStep) {\r\n setAnswerInput(JSON.stringify(payloadObj, null, 2));\r\n } else {\r\n setOfferInput(JSON.stringify(payloadObj, null, 2));\r\n }\r\n setMessages(prev => [...prev, { message: 'All frames captured. RAW payload reconstructed.', type: 'success' }]);\r\n try { document.dispatchEvent(new CustomEvent('qr-scan-complete', { detail: { id: hdr.id } })); } catch {}\r\n // Close scanner from caller by returning true\r\n qrChunksBufferRef.current = { id: null, total: 0, seen: new Set(), items: [] };\r\n setShowQRScannerModal(false);\r\n return Promise.resolve(true);\r\n } catch (e) {\r\n console.warn('RAW multi-frame reconstruction failed:', e);\r\n return Promise.resolve(false);\r\n }\r\n } else if (hdr.rt === 'bin') {\r\n try {\r\n const parts = qrChunksBufferRef.current.items\r\n .map(s => JSON.parse(s))\r\n .sort((a, b) => (a.hdr.seq || 0) - (b.hdr.seq || 0))\r\n .map(p => p.body || '');\r\n const fullText = parts.join(''); // SB1:bin:...\r\n let payloadObj;\r\n if (typeof window.decodeAnyPayload === 'function') {\r\n const any = window.decodeAnyPayload(fullText);\r\n payloadObj = (typeof any === 'string') ? JSON.parse(any) : any;\r\n } else {\r\n payloadObj = JSON.parse(fullText);\r\n }\r\n if (showOfferStep) {\r\n setAnswerInput(JSON.stringify(payloadObj, null, 2));\r\n } else {\r\n setOfferInput(JSON.stringify(payloadObj, null, 2));\r\n }\r\n setMessages(prev => [...prev, { message: 'All frames captured. BIN payload reconstructed.', type: 'success' }]);\r\n try { document.dispatchEvent(new CustomEvent('qr-scan-complete', { detail: { id: hdr.id } })); } catch {}\r\n qrChunksBufferRef.current = { id: null, total: 0, seen: new Set(), items: [] };\r\n setShowQRScannerModal(false);\r\n return Promise.resolve(true);\r\n } catch (e) {\r\n console.warn('BIN multi-frame reconstruction failed:', e);\r\n return Promise.resolve(false);\r\n }\r\n } else if (window.receiveAndProcess) {\r\n try {\r\n const results = await window.receiveAndProcess(qrChunksBufferRef.current.items);\r\n if (results.length > 0) {\r\n const { payloadObj } = results[0];\r\n if (showOfferStep) {\r\n setAnswerInput(JSON.stringify(payloadObj, null, 2));\r\n } else {\r\n setOfferInput(JSON.stringify(payloadObj, null, 2));\r\n }\r\n setMessages(prev => [...prev, { message: 'All frames captured. COSE payload reconstructed.', type: 'success' }]);\r\n try { document.dispatchEvent(new CustomEvent('qr-scan-complete', { detail: { id: hdr.id } })); } catch {}\r\n qrChunksBufferRef.current = { id: null, total: 0, seen: new Set(), items: [] };\r\n setShowQRScannerModal(false);\r\n return Promise.resolve(true);\r\n }\r\n } catch (e) {\r\n console.warn('COSE multi-chunk processing failed:', e);\r\n }\r\n return Promise.resolve(false);\r\n } else {\r\n return Promise.resolve(false);\r\n }\r\n }\r\n \r\n // Check if this is a template-based QR code\r\n if (parsedData.type === 'enhanced_secure_offer_template') {\r\n console.log('QR scan: Template-based offer detected, reconstructing...');\r\n const fullOffer = reconstructFromTemplate(parsedData);\r\n \r\n // Determine which input to populate based on current mode\r\n if (showOfferStep) {\r\n // In \"Waiting for peer's response\" mode - populate answerInput\r\n setAnswerInput(JSON.stringify(fullOffer, null, 2));\r\n console.log('\uD83D\uDCF1 Template data populated to answerInput (waiting for response mode)');\r\n } else {\r\n // In \"Paste secure invitation\" mode - populate offerInput\r\n setOfferInput(JSON.stringify(fullOffer, null, 2));\r\n console.log('\uD83D\uDCF1 Template data populated to offerInput (paste invitation mode)');\r\n }\r\n setMessages(prev => [...prev, {\r\n message: '\uD83D\uDCF1 QR code scanned successfully! Full offer reconstructed from template.',\r\n type: 'success'\r\n }]);\r\n setShowQRScannerModal(false); // Close QR scanner modal\r\n return true;\r\n }\r\n // Check if this is a reference-based QR code\r\n else if (parsedData.type === 'secure_offer_reference' && parsedData.referenceId) {\r\n // Try to get the full offer data from localStorage\r\n const fullOfferData = localStorage.getItem(`qr_offer_${parsedData.referenceId}`);\r\n if (fullOfferData) {\r\n const fullOffer = JSON.parse(fullOfferData);\r\n // Determine which input to populate based on current mode\r\n if (showOfferStep) {\r\n // In \"Waiting for peer's response\" mode - populate answerInput\r\n setAnswerInput(JSON.stringify(fullOffer, null, 2));\r\n } else {\r\n // In \"Paste secure invitation\" mode - populate offerInput\r\n setOfferInput(JSON.stringify(fullOffer, null, 2));\r\n }\r\n setMessages(prev => [...prev, {\r\n message: '\uD83D\uDCF1 QR code scanned successfully! Full offer data retrieved.',\r\n type: 'success'\r\n }]);\r\n setShowQRScannerModal(false); // Close QR scanner modal\r\n return true;\r\n } else {\r\n setMessages(prev => [...prev, {\r\n message: 'QR code reference found but full data not available. Please use copy/paste.',\r\n type: 'error'\r\n }]);\r\n return false;\r\n }\r\n } else {\r\n // If payload was compressed, it's already decompressed above; keep legacy warning only when clearly incomplete\r\n if (!parsedData.sdp && parsedData.type === 'enhanced_secure_offer') {\r\n setMessages(prev => [...prev, {\r\n message: 'Compressed QR may omit SDP for brevity. Use copy/paste if connection fails.',\r\n type: 'warning'\r\n }]);\r\n }\r\n \r\n // Determine which input to populate based on current mode\r\n if (showOfferStep) {\r\n // In \"Waiting for peer's response\" mode - populate answerInput\r\n console.log('QR scan: Populating answerInput with:', parsedData);\r\n setAnswerInput(JSON.stringify(parsedData, null, 2));\r\n } else {\r\n // In \"Paste secure invitation\" mode - populate offerInput\r\n console.log('QR scan: Populating offerInput with:', parsedData);\r\n setOfferInput(JSON.stringify(parsedData, null, 2));\r\n }\r\n setMessages(prev => [...prev, {\r\n message: '\uD83D\uDCF1 QR code scanned successfully!',\r\n type: 'success'\r\n }]);\r\n setShowQRScannerModal(false);\r\n return true;\r\n }\r\n } catch (error) {\r\n // If not JSON, use as plain text\r\n if (showOfferStep) {\r\n // In \"Waiting for peer's response\" mode - populate answerInput\r\n setAnswerInput(scannedData);\r\n } else {\r\n // In \"Paste secure invitation\" mode - populate offerInput\r\n setOfferInput(scannedData);\r\n }\r\n setMessages(prev => [...prev, {\r\n message: '\uD83D\uDCF1 QR code scanned successfully!',\r\n type: 'success'\r\n }]);\r\n setShowQRScannerModal(false);\r\n return true;\r\n }\r\n };\r\n\r\n\r\n\r\n \r\n const handleCreateOffer = async () => {\r\n try {\r\n // All security features are enabled by default\r\n setIsGeneratingKeys(true);\r\n setOfferData('');\r\n setShowOfferStep(false);\r\n setShowQRCode(false);\r\n setQrCodeUrl('');\r\n \r\n const offer = await webrtcManagerRef.current.createSecureOffer();\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 // Generate QR code with binary format and chunking\r\n const offerString = typeof offer === 'object' ? JSON.stringify(offer) : offer;\r\n try {\r\n if (typeof window.encodeBinaryToPrefixed === 'function') {\r\n const bin = window.encodeBinaryToPrefixed(offerString);\r\n // Force chunking into 4 parts - split binary data directly\r\n const TARGET_CHUNKS = 4;\r\n let total = TARGET_CHUNKS;\r\n let FRAME_MAX = Math.max(200, Math.ceil(bin.length / TARGET_CHUNKS));\r\n if (FRAME_MAX <= 0) FRAME_MAX = 200;\r\n \r\n // Ensure we don't exceed TARGET_CHUNKS\r\n if (bin.length <= FRAME_MAX) {\r\n total = 1;\r\n FRAME_MAX = bin.length;\r\n } else {\r\n // Recalculate to ensure exactly TARGET_CHUNKS parts\r\n FRAME_MAX = Math.ceil(bin.length / TARGET_CHUNKS);\r\n total = TARGET_CHUNKS;\r\n }\r\n \r\n const id = `bin_${Date.now()}_${Math.random().toString(36).slice(2)}`;\r\n const chunks = [];\r\n for (let i = 0; i < total; i++) {\r\n const seq = i + 1;\r\n const part = bin.slice(i * FRAME_MAX, (i + 1) * FRAME_MAX);\r\n // Store binary chunks directly without JSON wrapper\r\n chunks.push(part);\r\n }\r\n \r\n // Seed first frame and start auto-advance immediately\r\n const isDesktop = (typeof window !== 'undefined') && ((window.innerWidth || 0) >= 1024);\r\n const QR_SIZE = isDesktop ? 720 : 512;\r\n if (window.generateQRCode && chunks.length > 0) {\r\n const firstUrl = await window.generateQRCode(chunks[0], { errorCorrectionLevel: 'M', size: QR_SIZE, margin: 2 });\r\n if (firstUrl) setQrCodeUrl(firstUrl);\r\n }\r\n \r\n // Store precomputed chunks to ref, ready for animation\r\n try { if (qrAnimationRef.current && qrAnimationRef.current.timer) { clearInterval(qrAnimationRef.current.timer); } } catch {}\r\n qrAnimationRef.current = { timer: null, chunks, idx: 0, active: true };\r\n setQrFramesTotal(chunks.length);\r\n setQrFrameIndex(1);\r\n setQrManualMode(false);\r\n \r\n // Start auto-advance loop for Offer immediately\r\n const intervalMs = 3000;\r\n qrAnimationRef.current.timer = setInterval(renderAndAdvance, intervalMs);\r\n \r\n // Show QR immediately for Offer flow\r\n try { setShowQRCode(true); } catch {}\r\n } else {\r\n // Fallback to single QR\r\n await generateQRCode(offer);\r\n try { setShowQRCode(true); } catch {}\r\n }\r\n } catch (e) {\r\n console.warn('Offer QR generation failed:', e);\r\n }\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: '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: `Error creating invitation: ${error.message}`, \r\n type: 'system',\r\n id: Date.now(),\r\n timestamp: Date.now()\r\n }]);\r\n } finally {\r\n setIsGeneratingKeys(false);\r\n }\r\n };\r\n \r\n const handleCreateAnswer = async () => {\r\n try {\r\n \r\n if (!offerInput.trim()) {\r\n setMessages(prev => [...prev, { \r\n message: '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: 'Processing the secure invitation...', \r\n type: 'system',\r\n id: Date.now(),\r\n timestamp: Date.now()\r\n }]);\r\n \r\n let offer;\r\n try {\r\n // Prefer binary decode first, then gzip JSON\r\n if (typeof window.decodeAnyPayload === 'function') {\r\n const any = window.decodeAnyPayload(offerInput.trim());\r\n offer = (typeof any === 'string') ? JSON.parse(any) : any;\r\n } else {\r\n const rawText = (typeof window.decompressIfNeeded === 'function') ? window.decompressIfNeeded(offerInput.trim()) : offerInput.trim();\r\n offer = JSON.parse(rawText);\r\n }\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 // Support both compact and legacy offer formats\r\n const isValidOfferType = (offer.t === 'offer') || (offer.type === 'enhanced_secure_offer');\r\n if (!isValidOfferType) {\r\n throw new Error('Invalid invitation type. Expected offer or enhanced_secure_offer');\r\n }\r\n\r\n const answer = await webrtcManagerRef.current.createSecureAnswer(offer);\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 // Generate QR code with binary format and chunking\r\n const answerString = typeof answer === 'object' ? JSON.stringify(answer) : answer;\r\n try {\r\n if (typeof window.encodeBinaryToPrefixed === 'function') {\r\n const bin = window.encodeBinaryToPrefixed(answerString);\r\n // Force chunking into 4 parts - split binary data directly\r\n const TARGET_CHUNKS = 4;\r\n let total = TARGET_CHUNKS;\r\n let FRAME_MAX = Math.max(200, Math.ceil(bin.length / TARGET_CHUNKS));\r\n if (FRAME_MAX <= 0) FRAME_MAX = 200;\r\n \r\n // Ensure we don't exceed TARGET_CHUNKS\r\n if (bin.length <= FRAME_MAX) {\r\n total = 1;\r\n FRAME_MAX = bin.length;\r\n } else {\r\n // Recalculate to ensure exactly TARGET_CHUNKS parts\r\n FRAME_MAX = Math.ceil(bin.length / TARGET_CHUNKS);\r\n total = TARGET_CHUNKS;\r\n }\r\n \r\n const id = `ans_${Date.now()}_${Math.random().toString(36).slice(2)}`;\r\n const chunks = [];\r\n for (let i = 0; i < total; i++) {\r\n const seq = i + 1;\r\n const part = bin.slice(i * FRAME_MAX, (i + 1) * FRAME_MAX);\r\n // Store binary chunks directly without JSON wrapper\r\n chunks.push(part);\r\n }\r\n \r\n const isDesktop = (typeof window !== 'undefined') && ((window.innerWidth || 0) >= 1024);\r\n const QR_SIZE = isDesktop ? 720 : 512;\r\n if (window.generateQRCode && chunks.length > 0) {\r\n const firstUrl = await window.generateQRCode(chunks[0], { errorCorrectionLevel: 'M', size: QR_SIZE, margin: 2 });\r\n if (firstUrl) setQrCodeUrl(firstUrl);\r\n }\r\n \r\n try { if (qrAnimationRef.current && qrAnimationRef.current.timer) { clearInterval(qrAnimationRef.current.timer); } } catch {}\r\n qrAnimationRef.current = { timer: null, chunks, idx: 0, active: true };\r\n setQrFramesTotal(chunks.length);\r\n setQrFrameIndex(1);\r\n setQrManualMode(false);\r\n \r\n const intervalMs = 3000;\r\n qrAnimationRef.current.timer = setInterval(renderAndAdvance, intervalMs);\r\n \r\n // Show QR immediately for Answer flow\r\n try { setShowQRCode(true); } catch {}\r\n } else {\r\n // Fallback to single QR\r\n await generateQRCode(answer);\r\n try { setShowQRCode(true); } catch {}\r\n }\r\n } catch (e) {\r\n console.warn('Answer QR generation failed:', e);\r\n }\r\n \r\n // Mark answer as created for state management\r\n if (answerInput.trim().length > 0) {\r\n if (typeof markAnswerCreated === 'function') {\r\n markAnswerCreated();\r\n }\r\n }\r\n\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: '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: 'Send the response code to the initiator via a secure channel or let them scan the QR code below.', \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: `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: `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: '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: '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 // Prefer binary decode first, then gzip JSON\r\n if (typeof window.decodeAnyPayload === 'function') {\r\n const anyAnswer = window.decodeAnyPayload(answerInput.trim());\r\n answer = (typeof anyAnswer === 'string') ? JSON.parse(anyAnswer) : anyAnswer;\r\n } else {\r\n const rawText = (typeof window.decompressIfNeeded === 'function') ? window.decompressIfNeeded(answerInput.trim()) : answerInput.trim();\r\n answer = JSON.parse(rawText);\r\n }\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 // Support both compact and legacy formats\r\n const answerType = answer.t || answer.type;\r\n if (!answerType || (answerType !== 'answer' && answerType !== 'enhanced_secure_answer')) {\r\n throw new Error('Invalid response type. Expected answer or enhanced_secure_answer');\r\n }\r\n \r\n await webrtcManagerRef.current.handleSecureAnswer(answer);\r\n \r\n // All security features are enabled by default - no session activation needed\r\n if (pendingSession) {\r\n setPendingSession(null);\r\n setMessages(prev => [...prev, { \r\n message: `All security features enabled by default`, \r\n type: 'system',\r\n id: Date.now(),\r\n timestamp: Date.now()\r\n }]);\r\n }\r\n \r\n setMessages(prev => [...prev, { \r\n message: '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 console.error('Error in handleConnect inner try:', error);\r\n \r\n // \u0411\u043E\u043B\u0435\u0435 \u0434\u0435\u0442\u0430\u043B\u044C\u043D\u0430\u044F \u043E\u0431\u0440\u0430\u0431\u043E\u0442\u043A\u0430 \u043E\u0448\u0438\u0431\u043E\u043A\r\n let errorMessage = 'Connection setup error';\r\n if (error.message.includes('CRITICAL SECURITY FAILURE')) {\r\n if (error.message.includes('ECDH public key structure')) {\r\n errorMessage = 'Invalid response code - missing or corrupted cryptographic key. Please check the code and try again.';\r\n } else if (error.message.includes('ECDSA public key structure')) {\r\n errorMessage = 'Invalid response code - missing signature verification key. Please check the code and try again.';\r\n } else {\r\n errorMessage = 'Security validation failed - possible attack detected';\r\n }\r\n } else if (error.message.includes('too old') || error.message.includes('replay')) {\r\n errorMessage = 'Response data is outdated - please use a fresh invitation';\r\n } else if (error.message.includes('MITM') || error.message.includes('signature')) {\r\n errorMessage = 'Security breach detected - connection rejected';\r\n } else if (error.message.includes('Invalid') || error.message.includes('format')) {\r\n errorMessage = 'Invalid response format - please check the code';\r\n } else {\r\n errorMessage = ` ${error.message}`;\r\n }\r\n \r\n setMessages(prev => [...prev, { \r\n message: errorMessage, \r\n type: 'system',\r\n id: Date.now(),\r\n timestamp: Date.now(),\r\n showRetryButton: true\r\n }]);\r\n\r\n if (!error.message.includes('too old') && !error.message.includes('replay')) {\r\n setPendingSession(null);\r\n setSessionTimeLeft(0);\r\n }\r\n\r\n setConnectionStatus('failed');\r\n \r\n } \r\n } catch (error) {\r\n console.error('Error in handleConnect outer try:', error);\r\n\r\n let errorMessage = 'Connection setup error';\r\n if (error.message.includes('CRITICAL SECURITY FAILURE')) {\r\n if (error.message.includes('ECDH public key structure')) {\r\n errorMessage = 'Invalid response code - missing or corrupted cryptographic key. Please check the code and try again.';\r\n } else if (error.message.includes('ECDSA public key structure')) {\r\n errorMessage = 'Invalid response code - missing signature verification key. Please check the code and try again.';\r\n } else {\r\n errorMessage = 'Security validation failed - possible attack detected';\r\n }\r\n } else if (error.message.includes('too old') || error.message.includes('replay')) {\r\n errorMessage = 'Response data is outdated - please use a fresh invitation';\r\n } else if (error.message.includes('MITM') || error.message.includes('signature')) {\r\n errorMessage = 'Security breach detected - connection rejected';\r\n } else if (error.message.includes('Invalid') || error.message.includes('format')) {\r\n errorMessage = 'Invalid response format - please check the code';\r\n } else {\r\n errorMessage = `${error.message}`;\r\n }\r\n \r\n setMessages(prev => [...prev, { \r\n message: errorMessage, \r\n type: 'system',\r\n id: Date.now(),\r\n timestamp: Date.now(),\r\n showRetryButton: true\r\n }]);\r\n\r\n if (!error.message.includes('too old') && !error.message.includes('replay')) {\r\n setPendingSession(null);\r\n setSessionTimeLeft(0);\r\n }\r\n\r\n setConnectionStatus('failed');\r\n }\r\n };\r\n \r\n const handleVerifyConnection = async (isValid) => {\r\n if (isValid) {\r\n webrtcManagerRef.current.confirmVerification();\r\n // Mark local verification as confirmed\r\n setLocalVerificationConfirmed(true);\r\n \r\n // Initialize notification integration if permission was granted\r\n try {\r\n if (window.NotificationIntegration && webrtcManagerRef.current && !notificationIntegrationRef.current) {\r\n const integration = new window.NotificationIntegration(webrtcManagerRef.current);\r\n await integration.init();\r\n \r\n // Store reference for cleanup\r\n notificationIntegrationRef.current = integration;\r\n \r\n \r\n // Check if permission was already granted\r\n const status = integration.getStatus();\r\n if (status.permission === 'granted') {\r\n setMessages(prev => [...prev, { \r\n message: '\u2713 Notifications enabled - you will receive alerts when the tab is inactive', \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: '\u2139 Notifications disabled - you can enable them using the button on the main page', \r\n type: 'system',\r\n id: Date.now(),\r\n timestamp: Date.now()\r\n }]);\r\n }\r\n } else if (notificationIntegrationRef.current) {\r\n } else {\r\n // Handle error silently\r\n }\r\n } catch (error) {\r\n console.warn('Failed to initialize notifications:', error);\r\n // Don't show error to user, notifications are optional\r\n }\r\n } else {\r\n setMessages(prev => [...prev, { \r\n message: ' 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('');\r\n setAnswerData('');\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 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(`Sending error: ${msg}`,'system');\r\n }\r\n }\r\n };\r\n \r\n const handleClearData = () => {\r\n setOfferData('');\r\n setAnswerData('');\r\n setOfferInput('');\r\n setAnswerInput('');\r\n setShowOfferStep(false);\r\n setIsGeneratingKeys(false);\r\n\r\n if (!shouldPreserveAnswerData()) {\r\n setShowAnswerStep(false);\r\n }\r\n \r\n setShowVerification(false);\r\n setShowQRCode(false);\r\n setShowQRScanner(false);\r\n setShowQRScannerModal(false);\r\n // Clear QR scanner buffer\r\n qrChunksBufferRef.current = { id: null, total: 0, seen: new Set(), items: [] };\r\n\r\n if (!shouldPreserveAnswerData()) {\r\n setQrCodeUrl('');\r\n }\r\n \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 if (typeof console.clear === 'function') {\r\n console.clear();\r\n }\r\n \r\n // Cleanup session state\r\n setSessionTimeLeft(0);\r\n \r\n setPendingSession(null);\r\n document.dispatchEvent(new CustomEvent('peer-disconnect'));\r\n // Session manager removed - all features enabled by default\r\n };\r\n \r\n const handleDisconnect = () => {\r\n try {\r\n setSessionTimeLeft(0);\r\n \r\n // Mark as user-initiated disconnect\r\n updateConnectionState({ \r\n status: 'disconnected',\r\n isUserInitiatedDisconnect: true \r\n });\r\n \r\n // Cleanup WebRTC connection\r\n if (webrtcManagerRef.current) {\r\n webrtcManagerRef.current.disconnect();\r\n }\r\n \r\n // Cleanup notification integration\r\n if (notificationIntegrationRef.current) {\r\n notificationIntegrationRef.current.cleanup();\r\n notificationIntegrationRef.current = null;\r\n }\r\n \r\n // Clear all connection-related states\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 setOfferData('');\r\n setAnswerData('');\r\n setOfferInput('');\r\n setAnswerInput('');\r\n setShowOfferStep(false);\r\n setShowAnswerStep(false);\r\n setIsGeneratingKeys(false);\r\n setShowQRCode(false);\r\n setQrCodeUrl('');\r\n setShowQRScanner(false);\r\n setShowQRScannerModal(false);\r\n \r\n // Clear messages\r\n setMessages([]);\r\n \r\n // Clear console\r\n if (typeof console.clear === 'function') {\r\n console.clear();\r\n }\r\n \r\n // Dispatch disconnect events\r\n document.dispatchEvent(new CustomEvent('peer-disconnect'));\r\n document.dispatchEvent(new CustomEvent('disconnected'));\r\n \r\n // Dispatch session cleanup event\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 // Clear data and reset session timer\r\n handleClearData();\r\n \r\n setTimeout(() => {\r\n setSessionTimeLeft(0);\r\n }, 500);\r\n \r\n console.log('Disconnect completed successfully');\r\n } catch (error) {\r\n console.error('Error during disconnect:', error);\r\n }\r\n };\r\n \r\n const handleSessionActivated = (session) => {\r\n let message;\r\n if (session.type === 'demo') {\r\n message = ` Demo session activated for 6 minutes. You can create invitations!`;\r\n } else {\r\n message = ` All security features enabled by default. 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(' 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' || connectionStatus === 'verified') && isVerified;\r\n \r\n React.useEffect(() => {\r\n // All security features are enabled by default - no session activation needed\r\n if (isConnectedAndVerified && pendingSession && connectionStatus !== 'failed') {\r\n setPendingSession(null);\r\n setSessionTimeLeft(0); \r\n addMessageWithAutoScroll(' All security features enabled by default', 'system');\r\n }\r\n }, [isConnectedAndVerified, pendingSession, connectionStatus]);\r\n\r\n // QR Scanner initialization\r\n React.useEffect(() => {\r\n if (showQRScannerModal && window.Html5Qrcode) {\r\n const html5Qrcode = new window.Html5Qrcode(\"qr-reader\");\r\n const config = { \r\n fps: 10\r\n // \u0423\u0431\u0438\u0440\u0430\u0435\u043C qrbox \u0447\u0442\u043E\u0431\u044B \u0438\u0441\u043F\u043E\u043B\u044C\u0437\u043E\u0432\u0430\u0442\u044C \u0432\u0441\u044E \u043E\u0431\u043B\u0430\u0441\u0442\u044C\r\n };\r\n\r\n let isScanning = true;\r\n\r\n html5Qrcode.start(\r\n { facingMode: \"environment\" }, // Use back camera\r\n config,\r\n (decodedText, decodedResult) => {\r\n if (!isScanning) {\r\n console.log('Scanner stopped, ignoring scan');\r\n return;\r\n }\r\n \r\n console.log('QR Code scanned:', decodedText);\r\n console.log('Current buffer state:', qrChunksBufferRef.current);\r\n \r\n handleQRScan(decodedText).then((success) => {\r\n console.log('QR scan result:', success);\r\n if (success) {\r\n // Successfully processed - stop scanner and close modal\r\n console.log('Closing scanner and modal');\r\n isScanning = false;\r\n \r\n // Stop scanner first, then clear\r\n try {\r\n console.log('Stopping scanner...');\r\n html5Qrcode.stop().then(() => {\r\n console.log('Scanner stopped, clearing...');\r\n html5Qrcode.clear();\r\n setShowQRScannerModal(false);\r\n }).catch((err) => {\r\n console.log('Error stopping scanner:', err);\r\n // Try to clear anyway\r\n try {\r\n html5Qrcode.clear();\r\n } catch (clearErr) {\r\n console.log('Error clearing scanner:', clearErr);\r\n }\r\n setShowQRScannerModal(false);\r\n });\r\n } catch (err) {\r\n console.log('Error in scanner cleanup:', err);\r\n setShowQRScannerModal(false);\r\n }\r\n } else {\r\n console.log('Continuing to scan for more chunks...');\r\n }\r\n }).catch((error) => {\r\n console.error('QR scan processing error:', error);\r\n // Continue scanning on error\r\n });\r\n },\r\n (error) => {\r\n // Ignore scanning errors - continue scanning\r\n if (isScanning) {\r\n console.log('QR scan error (ignored):', error);\r\n }\r\n }\r\n ).catch((err) => {\r\n console.error('QR Scanner start error:', err);\r\n // Close modal on start error\r\n setShowQRScannerModal(false);\r\n });\r\n\r\n return () => {\r\n isScanning = false;\r\n try {\r\n // Try to stop scanner, but don't worry if it's already stopped\r\n html5Qrcode.stop().then(() => {\r\n html5Qrcode.clear();\r\n }).catch((err) => {\r\n // Scanner might already be stopped, just clear it\r\n console.log('Scanner already stopped or error stopping:', err);\r\n try {\r\n html5Qrcode.clear();\r\n } catch (clearErr) {\r\n console.log('Error clearing scanner in cleanup:', clearErr);\r\n }\r\n });\r\n } catch (err) {\r\n console.log('Error in cleanup:', err);\r\n // Just try to clear, don't worry about stopping\r\n try {\r\n html5Qrcode.clear();\r\n } catch (clearErr) {\r\n console.log('Error clearing scanner in cleanup:', clearErr);\r\n }\r\n }\r\n };\r\n }\r\n }, [showQRScannerModal]);\r\n \r\n return React.createElement('div', { \r\n className: \"minimal-bg min-h-screen\" \r\n }, [\r\n window.EnhancedMinimalHeader && React.createElement(window.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 removed - all features enabled by default\r\n webrtcManager: webrtcManagerRef.current\r\n }),\r\n \r\n React.createElement('main', {\r\n key: 'main'\r\n }, \r\n (() => {\r\n return isConnectedAndVerified;\r\n })()\r\n ? (() => {\r\n return 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 scrollToBottom: scrollToBottom,\r\n webrtcManager: webrtcManagerRef.current\r\n });\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 showQRCode: showQRCode,\r\n qrCodeUrl: qrCodeUrl,\r\n showQRScanner: showQRScanner,\r\n setShowQRCode: setShowQRCode,\r\n setShowQRScanner: setShowQRScanner,\r\n setShowQRScannerModal: setShowQRScannerModal,\r\n messages: messages,\r\n localVerificationConfirmed: localVerificationConfirmed,\r\n remoteVerificationConfirmed: remoteVerificationConfirmed,\r\n bothVerificationsConfirmed: bothVerificationsConfirmed,\r\n // QR control props\r\n qrFramesTotal: qrFramesTotal,\r\n qrFrameIndex: qrFrameIndex,\r\n qrManualMode: qrManualMode,\r\n toggleQrManualMode: toggleQrManualMode,\r\n nextQrFrame: nextQrFrame,\r\n prevQrFrame: prevQrFrame,\r\n // PAKE passwords removed - using SAS verification instead\r\n markAnswerCreated: markAnswerCreated,\r\n notificationIntegrationRef: notificationIntegrationRef,\r\n isGeneratingKeys: isGeneratingKeys,\r\n handleCreateOffer: handleCreateOffer\r\n })\r\n ),\r\n \r\n // QR Scanner Modal\r\n showQRScannerModal && React.createElement('div', {\r\n key: 'qr-scanner-modal',\r\n className: \"fixed inset-0 bg-black/80 flex items-center justify-center z-50\"\r\n }, [\r\n React.createElement('div', {\r\n key: 'scanner-container',\r\n className: \"bg-gray-900 rounded-lg p-4 max-w-2xl w-full mx-4\"\r\n }, [\r\n React.createElement('div', {\r\n key: 'scanner-header',\r\n className: \"flex items-center justify-between mb-4\"\r\n }, [\r\n React.createElement('h3', {\r\n key: 'scanner-title',\r\n className: \"text-lg font-medium text-white\"\r\n }, 'QR Code Scanner'),\r\n React.createElement('button', {\r\n key: 'close-btn',\r\n onClick: () => {\r\n setShowQRScannerModal(false);\r\n // Clear QR scanner buffer\r\n qrChunksBufferRef.current = { id: null, total: 0, seen: new Set(), items: [] };\r\n },\r\n className: \"text-gray-400 hover:text-white\"\r\n }, [\r\n React.createElement('i', {\r\n key: 'close-icon',\r\n className: 'fas fa-times'\r\n })\r\n ])\r\n ]),\r\n React.createElement('div', {\r\n key: 'scanner-content',\r\n className: \"text-center\"\r\n }, [\r\n React.createElement('p', {\r\n key: 'scanner-description',\r\n className: \"text-gray-400 mb-4\"\r\n }, 'Point your camera at the QR code to scan'),\r\n qrChunksBufferRef.current && qrChunksBufferRef.current.id && React.createElement('div', {\r\n key: 'progress-indicator',\r\n className: \"mb-4 p-3 bg-blue-500/10 border border-blue-500/20 rounded-lg\"\r\n }, [\r\n React.createElement('p', {\r\n key: 'progress-text',\r\n className: \"text-blue-400 text-sm\"\r\n }, `Scanned: ${qrChunksBufferRef.current.seen.size}/${qrChunksBufferRef.current.total} parts`),\r\n React.createElement('div', {\r\n key: 'progress-bar',\r\n className: \"w-full bg-gray-700 rounded-full h-2 mt-2\"\r\n }, [\r\n React.createElement('div', {\r\n key: 'progress-fill',\r\n className: \"bg-blue-500 h-2 rounded-full transition-all duration-300\",\r\n style: { \r\n width: `${(qrChunksBufferRef.current.seen.size / qrChunksBufferRef.current.total) * 100}%` \r\n }\r\n })\r\n ])\r\n ]),\r\n React.createElement('div', {\r\n key: 'scanner-placeholder',\r\n id: \"qr-reader\",\r\n className: \"w-full h-96 bg-gray-800 rounded-lg flex items-center justify-center\",\r\n style: { minHeight: '400px' }\r\n }, [\r\n React.createElement('p', {\r\n key: 'scanner-placeholder-text',\r\n className: \"text-gray-500\"\r\n }, 'Camera will start here...')\r\n ])\r\n ])\r\n ])\r\n ]),\r\n \r\n \r\n ]);\r\n };\r\n // UpdateChecker \u043A\u043E\u043C\u043F\u043E\u043D\u0435\u043D\u0442 \u0434\u043B\u044F \u0430\u0432\u0442\u043E\u043C\u0430\u0442\u0438\u0447\u0435\u0441\u043A\u043E\u0439 \u043F\u0440\u043E\u0432\u0435\u0440\u043A\u0438 \u043E\u0431\u043D\u043E\u0432\u043B\u0435\u043D\u0438\u0439\r\n const UpdateCheckerWrapper = ({ children }) => {\r\n // \u041F\u0440\u043E\u0432\u0435\u0440\u044F\u0435\u043C \u0434\u043E\u0441\u0442\u0443\u043F\u043D\u043E\u0441\u0442\u044C UpdateChecker\r\n if (typeof window !== 'undefined' && window.UpdateChecker) {\r\n return React.createElement(window.UpdateChecker, {\r\n debug: false\r\n }, children);\r\n }\r\n // Fallback \u0435\u0441\u043B\u0438 UpdateChecker \u043D\u0435 \u0437\u0430\u0433\u0440\u0443\u0436\u0435\u043D\r\n return children;\r\n };\r\n\r\n function initializeApp() {\r\n if (window.EnhancedSecureCryptoUtils && window.EnhancedSecureWebRTCManager) {\r\n // \u041E\u0431\u043E\u0440\u0430\u0447\u0438\u0432\u0430\u0435\u043C \u043F\u0440\u0438\u043B\u043E\u0436\u0435\u043D\u0438\u0435 \u0432 UpdateChecker \u0434\u043B\u044F \u0430\u0432\u0442\u043E\u043C\u0430\u0442\u0438\u0447\u0435\u0441\u043A\u043E\u0439 \u043F\u0440\u043E\u0432\u0435\u0440\u043A\u0438 \u043E\u0431\u043D\u043E\u0432\u043B\u0435\u043D\u0438\u0439\r\n const AppWithUpdateChecker = React.createElement(UpdateCheckerWrapper, null,\r\n React.createElement(EnhancedSecureP2PChat)\r\n );\r\n ReactDOM.render(AppWithUpdateChecker, document.getElementById('root'));\r\n } else {\r\n console.error('\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\r\n if (typeof window !== 'undefined') {\r\n\r\n window.addEventListener('unhandledrejection', (event) => {\r\n console.error('Unhandled promise rejection:', event.reason);\r\n event.preventDefault(); \r\n });\r\n \r\n\r\n window.addEventListener('error', (event) => {\r\n console.error('Global error:', event.error);\r\n event.preventDefault(); \r\n });\r\n \r\n if (!window.initializeApp) {\r\n window.initializeApp = initializeApp;\r\n }\r\n };\r\n \r\n // Render Enhanced Application with UpdateChecker\r\n if (window.EnhancedSecureCryptoUtils && window.EnhancedSecureWebRTCManager) {\r\n const UpdateCheckerWrapper = ({ children }) => {\r\n if (typeof window !== 'undefined' && window.UpdateChecker) {\r\n return React.createElement(window.UpdateChecker, {\r\n debug: false\r\n }, children);\r\n }\r\n return children;\r\n };\r\n const AppWithUpdateChecker = React.createElement(UpdateCheckerWrapper, null,\r\n React.createElement(EnhancedSecureP2PChat)\r\n );\r\n ReactDOM.render(AppWithUpdateChecker, document.getElementById('root'));\r\n } else {\r\n ReactDOM.render(React.createElement(EnhancedSecureP2PChat), document.getElementById('root'));\r\n }"], - "mappings": "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", + "sourcesContent": ["\n // Enhanced Copy Button with better UX\n const EnhancedCopyButton = ({ text, className = \"\", children }) => {\n const [copied, setCopied] = React.useState(false);\n \n const handleCopy = async () => {\n try {\n await navigator.clipboard.writeText(text);\n setCopied(true);\n setTimeout(() => setCopied(false), 2000);\n } catch (error) {\n console.error('Copy failed:', error);\n // Fallback for older browsers\n const textArea = document.createElement('textarea');\n textArea.value = text;\n document.body.appendChild(textArea);\n textArea.select();\n document.execCommand('copy');\n document.body.removeChild(textArea);\n setCopied(true);\n setTimeout(() => setCopied(false), 2000);\n }\n };\n \n return React.createElement('button', {\n onClick: handleCopy,\n className: `${className} transition-all duration-200`\n }, [\n React.createElement('i', {\n key: 'icon',\n className: `${copied ? 'fas fa-check accent-green' : 'fas fa-copy text-secondary'} mr-2`\n }),\n copied ? 'Copied!' : children\n ]);\n };\n \n // Verification Component\n const VerificationStep = ({ verificationCode, onConfirm, onReject, localConfirmed, remoteConfirmed, bothConfirmed }) => {\n const [sasInput, setSasInput] = React.useState('');\n const [error, setError] = React.useState('');\n const normalizedExpectedLength = (verificationCode || '').replace(/[-\\s]/g, '').length;\n const normalizedInputLength = sasInput.replace(/[-\\s]/g, '').length;\n const canConfirm = !localConfirmed && normalizedExpectedLength > 0 && normalizedInputLength === normalizedExpectedLength;\n\n React.useEffect(() => {\n setSasInput('');\n setError('');\n }, [verificationCode]);\n\n const handleConfirm = async () => {\n try {\n setError('');\n await onConfirm(sasInput);\n } catch (confirmationError) {\n setSasInput('');\n if (confirmationError?.message === 'SAS_MAX_ATTEMPTS') {\n setError('Too many incorrect attempts. Session reset for safety.');\n } else {\n setError('Incorrect code. Check it with your peer and try again.');\n }\n }\n };\n\n return React.createElement('div', {\n className: \"card-minimal rounded-xl p-6 border-purple-500/20\"\n }, [\n React.createElement('div', {\n key: 'header',\n className: \"flex items-center mb-4\"\n }, [\n React.createElement('div', {\n key: 'icon',\n className: \"w-10 h-10 bg-purple-500/10 border border-purple-500/20 rounded-lg flex items-center justify-center mr-3\"\n }, [\n React.createElement('i', {\n className: 'fas fa-shield-alt accent-purple'\n })\n ]),\n React.createElement('h3', {\n key: 'title',\n className: \"text-lg font-medium text-primary\"\n }, \"Security verification\")\n ]),\n React.createElement('div', {\n key: 'content',\n className: \"space-y-4\"\n }, [\n React.createElement('p', {\n key: 'description',\n className: \"text-secondary text-sm\"\n }, \"Compare this code with your peer out-of-band, then type the same code below to unlock the chat.\"),\n React.createElement('div', {\n key: 'code-display',\n className: \"text-center\"\n }, [\n React.createElement('div', {\n key: 'code',\n className: \"verification-code text-2xl py-4\"\n }, verificationCode)\n ]),\n React.createElement('div', {\n key: 'sas-input-wrap',\n className: \"space-y-2\"\n }, [\n React.createElement('label', {\n key: 'sas-label',\n className: \"block text-sm text-secondary\"\n }, \"Enter the verified code\"),\n React.createElement('input', {\n key: 'sas-input',\n type: 'text',\n value: sasInput,\n onChange: (event) => {\n setSasInput(event.target.value.toUpperCase());\n if (error) setError('');\n },\n autoFocus: true,\n autoComplete: 'off',\n spellCheck: false,\n inputMode: 'text',\n disabled: localConfirmed,\n placeholder: verificationCode ? 'Type code here' : 'Waiting for code\u2026',\n className: \"w-full rounded-lg border border-purple-500/30 bg-black/20 px-4 py-3 text-center text-xl tracking-[0.3em] text-primary uppercase focus:border-purple-400 focus:outline-none disabled:cursor-not-allowed disabled:opacity-60\",\n style: { fontFamily: 'monospace', textTransform: 'uppercase' }\n }),\n error && React.createElement('p', {\n key: 'sas-error',\n className: \"text-sm text-red-400\"\n }, error)\n ]),\n // Verification status indicators\n React.createElement('div', {\n key: 'verification-status',\n className: \"space-y-2\"\n }, [\n React.createElement('div', {\n key: 'local-status',\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'}`\n }, [\n React.createElement('span', {\n key: 'local-label',\n className: \"text-sm text-secondary\"\n }, \"Your confirmation:\"),\n React.createElement('div', {\n key: 'local-indicator',\n className: \"flex items-center\"\n }, [\n React.createElement('i', {\n key: 'local-icon',\n className: `fas ${localConfirmed ? 'fa-check-circle text-green-400' : 'fa-clock text-gray-400'} mr-2`\n }),\n React.createElement('span', {\n key: 'local-text',\n className: `text-sm ${localConfirmed ? 'text-green-400' : 'text-gray-400'}`\n }, localConfirmed ? 'Confirmed' : 'Pending')\n ])\n ]),\n React.createElement('div', {\n key: 'remote-status',\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'}`\n }, [\n React.createElement('span', {\n key: 'remote-label',\n className: \"text-sm text-secondary\"\n }, \"Peer confirmation:\"),\n React.createElement('div', {\n key: 'remote-indicator',\n className: \"flex items-center\"\n }, [\n React.createElement('i', {\n key: 'remote-icon',\n className: `fas ${remoteConfirmed ? 'fa-check-circle text-green-400' : 'fa-clock text-gray-400'} mr-2`\n }),\n React.createElement('span', {\n key: 'remote-text',\n className: `text-sm ${remoteConfirmed ? 'text-green-400' : 'text-gray-400'}`\n }, remoteConfirmed ? 'Confirmed' : 'Pending')\n ])\n ])\n ]),\n React.createElement('div', {\n key: 'warning',\n className: \"p-3 bg-yellow-500/10 border border-yellow-500/20 rounded-lg\"\n }, [\n React.createElement('p', {\n className: \"text-yellow-400 text-sm flex items-center\"\n }, [\n React.createElement('i', {\n className: 'fas fa-exclamation-triangle mr-2'\n }),\n 'Make sure the codes match exactly.!'\n ])\n ]),\n React.createElement('div', {\n key: 'buttons',\n className: \"flex space-x-3\"\n }, [\n React.createElement('button', {\n key: 'confirm',\n onClick: handleConfirm,\n disabled: !canConfirm,\n className: `flex-1 py-3 px-4 rounded-lg font-medium transition-all duration-200 ${!canConfirm ? 'bg-gray-500/20 text-gray-400 cursor-not-allowed' : 'btn-verify text-white'}`\n }, [\n React.createElement('i', {\n className: `fas ${localConfirmed ? 'fa-check-circle' : 'fa-check'} mr-2`\n }),\n localConfirmed ? 'Confirmed' : 'Confirm code'\n ]),\n React.createElement('button', {\n key: 'reject',\n onClick: onReject,\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\"\n }, [\n React.createElement('i', {\n className: 'fas fa-times mr-2'\n }),\n 'The codes do not match'\n ])\n ])\n ])\n ]);\n };\n \n // Enhanced Chat Message with better security indicators\n const EnhancedChatMessage = ({ message, type, timestamp }) => {\n const formatTime = (ts) => {\n return new Date(ts).toLocaleTimeString('ru-RU', { \n hour: '2-digit', \n minute: '2-digit',\n second: '2-digit'\n });\n };\n \n const getMessageStyle = () => {\n switch (type) {\n case 'sent':\n return {\n container: \"ml-auto bg-orange-500/15 border-orange-500/20 text-primary\",\n icon: \"fas fa-lock accent-orange\",\n label: \"Encrypted\"\n };\n case 'received':\n return {\n container: \"mr-auto card-minimal text-primary\",\n icon: \"fas fa-unlock-alt accent-green\",\n label: \"Decrypted\"\n };\n case 'system':\n return {\n container: \"mx-auto bg-yellow-500/10 border border-yellow-500/20 text-yellow-400\",\n icon: \"fas fa-info-circle accent-yellow\",\n label: \"System\"\n };\n default:\n return {\n container: \"mx-auto card-minimal text-secondary\",\n icon: \"fas fa-circle text-muted\",\n label: \"Unknown\"\n };\n }\n };\n \n const style = getMessageStyle();\n \n return React.createElement('div', {\n className: `message-slide mb-3 p-3 rounded-lg max-w-md break-words ${style.container} border`\n }, [\n React.createElement('div', {\n key: 'content',\n className: \"flex items-start space-x-2\"\n }, [\n React.createElement('i', {\n key: 'icon',\n className: `${style.icon} text-sm mt-0.5 opacity-70`\n }),\n React.createElement('div', {\n key: 'text',\n className: \"flex-1\"\n }, [\n React.createElement('div', {\n key: 'message',\n className: \"text-sm break-words whitespace-normal\"\n }, message),\n timestamp && React.createElement('div', {\n key: 'meta',\n className: \"flex items-center justify-between mt-1 text-xs opacity-50\"\n }, [\n React.createElement('span', {\n key: 'time'\n }, formatTime(timestamp)),\n React.createElement('span', {\n key: 'status',\n className: \"text-xs\"\n }, style.label)\n ])\n ])\n ])\n ]);\n };\n \n // Enhanced Connection Setup with verification\n const EnhancedConnectionSetup = ({\n messages, \n onCreateOffer, \n onCreateAnswer, \n onConnect, \n onClearData,\n onVerifyConnection,\n connectionStatus,\n offerData,\n answerData,\n offerInput,\n setOfferInput,\n answerInput,\n setAnswerInput,\n showOfferStep,\n showAnswerStep,\n verificationCode,\n showVerification,\n showQRCode,\n qrCodeUrl,\n showQRScanner,\n setShowQRCode,\n setShowQRScanner,\n setShowQRScannerModal,\n offerPassword,\n answerPassword,\n localVerificationConfirmed,\n remoteVerificationConfirmed,\n bothVerificationsConfirmed,\n // QR control props\n qrFramesTotal,\n qrFrameIndex,\n qrManualMode,\n toggleQrManualMode,\n nextQrFrame,\n prevQrFrame,\n markAnswerCreated,\n notificationIntegrationRef,\n isGeneratingKeys,\n handleCreateOffer,\n relayOnlyMode,\n setRelayOnlyMode\n }) => {\n const [mode, setMode] = React.useState('select');\n const [notificationPermissionRequested, setNotificationPermissionRequested] = React.useState(false);\n \n const resetToSelect = () => {\n setMode('select');\n setIsGeneratingKeys(false);\n onClearData();\n };\n \n const handleVerificationConfirm = (userCode) => {\n return onVerifyConnection(userCode);\n };\n \n const handleVerificationReject = () => {\n onVerifyConnection(null, false);\n };\n \n // Request notification permission on first user interaction\n const requestNotificationPermissionOnInteraction = async () => {\n if (notificationPermissionRequested) {\n return; // Already requested\n }\n \n try {\n // Check if Notification API is supported\n if (!('Notification' in window)) {\n return;\n }\n \n // Check if we're in a secure context\n if (!window.isSecureContext && window.location.protocol !== 'https:' && window.location.hostname !== 'localhost') {\n return;\n }\n \n // Check current permission status\n const currentPermission = (typeof Notification !== 'undefined' && Notification) \n ? Notification.permission \n : 'denied';\n \n // Only request if permission is default (not granted or denied)\n if (currentPermission === 'default' && typeof Notification !== 'undefined' && Notification) {\n const permission = await Notification.requestPermission();\n \n if (permission === 'granted') {\n // Initialize notification integration immediately\n try {\n if (window.NotificationIntegration && webrtcManagerRef.current) {\n const integration = new window.NotificationIntegration(webrtcManagerRef.current);\n await integration.init();\n \n // Store reference for cleanup\n notificationIntegrationRef.current = integration;\n }\n } catch (error) {\n // Handle error silently\n }\n \n // Send welcome notification\n setTimeout(() => {\n try {\n const welcomeNotification = new Notification('SecureBit Chat', {\n body: 'Notifications enabled! You will receive alerts for new messages.',\n icon: '/logo/icon-192x192.png',\n tag: 'welcome-notification'\n });\n \n welcomeNotification.onclick = () => {\n welcomeNotification.close();\n };\n \n setTimeout(() => {\n welcomeNotification.close();\n }, 5000);\n \n } catch (error) {\n // Handle error silently\n }\n }, 1000);\n \n }\n } else if (currentPermission === 'granted') {\n // Initialize notification integration immediately\n try {\n if (window.NotificationIntegration && webrtcManagerRef.current && !notificationIntegrationRef.current) {\n const integration = new window.NotificationIntegration(webrtcManagerRef.current);\n await integration.init();\n \n // Store reference for cleanup\n notificationIntegrationRef.current = integration;\n }\n } catch (error) {\n // Handle error silently\n }\n \n // Test notification to confirm it works\n setTimeout(() => {\n try {\n const testNotification = new Notification('SecureBit Chat', {\n body: 'Notifications are working! You will receive alerts for new messages.',\n icon: '/logo/icon-192x192.png',\n tag: 'test-notification'\n });\n \n testNotification.onclick = () => {\n testNotification.close();\n };\n \n setTimeout(() => {\n testNotification.close();\n }, 5000);\n } catch (error) {\n // Handle error silently\n }\n }, 1000);\n }\n \n setNotificationPermissionRequested(true);\n \n } catch (error) {\n // Handle error silently\n }\n };\n \n if (showVerification) {\n return React.createElement('div', {\n className: \"min-h-[calc(100vh-104px)] flex items-center justify-center p-4\"\n }, [\n React.createElement('div', {\n key: 'verification',\n className: \"w-full max-w-md\"\n }, [\n React.createElement(VerificationStep, {\n verificationCode: verificationCode,\n onConfirm: handleVerificationConfirm,\n onReject: handleVerificationReject,\n localConfirmed: localVerificationConfirmed,\n remoteConfirmed: remoteVerificationConfirmed,\n bothConfirmed: bothVerificationsConfirmed\n })\n ])\n ]);\n }\n \n if (mode === 'select') {\n return React.createElement('div', {\n className: \"min-h-[calc(100vh-104px)] flex items-center justify-center p-4\"\n }, [\n React.createElement('div', {\n key: 'selector',\n className: \"w-full max-w-4xl\"\n }, [\n React.createElement('div', {\n key: 'header',\n className: \"text-center mb-8\"\n }, [\n React.createElement('h2', {\n key: 'title',\n className: \"text-2xl font-semibold text-primary mb-3\"\n }, 'Start secure communication'),\n React.createElement('p', {\n key: 'subtitle',\n className: \"text-secondary max-w-2xl mx-auto\"\n }, \"Choose a connection method for a secure channel with ECDH encryption and Perfect Forward Secrecy.\")\n ]),\n React.createElement('label', {\n key: 'privacy-mode',\n className: \"mb-6 mx-auto flex max-w-2xl items-start gap-3 rounded-xl border border-purple-500/20 bg-purple-500/10 p-4 text-left\"\n }, [\n React.createElement('input', {\n key: 'input',\n type: 'checkbox',\n checked: relayOnlyMode,\n onChange: (event) => setRelayOnlyMode(event.target.checked),\n className: \"mt-1\"\n }),\n React.createElement('span', { key: 'copy' }, [\n React.createElement('span', {\n key: 'title',\n className: \"block text-sm font-medium text-primary\"\n }, 'Privacy mode: relay-only WebRTC'),\n React.createElement('span', {\n key: 'desc',\n className: \"block text-sm text-secondary\"\n }, 'Uses TURN relay-only when configured. Without TURN, direct WebRTC may expose IP addresses and relay-only connections cannot start.')\n ])\n ]),\n \n React.createElement('div', {\n key: 'options',\n className: \"flex flex-col md:flex-row items-center justify-center gap-6 max-w-3xl mx-auto\"\n }, [\n // Create Connection\n React.createElement('div', {\n key: 'create',\n onClick: () => {\n requestNotificationPermissionOnInteraction();\n setMode('create');\n // \u0410\u0432\u0442\u043E\u043C\u0430\u0442\u0438\u0447\u0435\u0441\u043A\u0438 \u0437\u0430\u043F\u0443\u0441\u043A\u0430\u0435\u043C \u0433\u0435\u043D\u0435\u0440\u0430\u0446\u0438\u044E \u043A\u043B\u044E\u0447\u0435\u0439\n setTimeout(() => {\n if (webrtcManagerRef.current) {\n handleCreateOffer();\n }\n }, 100);\n },\n className: \"card-minimal rounded-xl p-6 cursor-pointer group flex-1 create\"\n }, [\n React.createElement('div', {\n key: 'icon',\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\"\n }, [\n React.createElement('i', {\n className: 'fas fa-plus text-xl text-blue-400'\n })\n ]),\n React.createElement('h3', {\n key: 'title',\n className: \"text-lg font-semibold text-primary text-center mb-3\"\n }, \"Create channel\"),\n React.createElement('p', {\n key: 'description',\n className: \"text-secondary text-center text-sm mb-4\"\n }, \"Initiate a new secure connection\"),\n React.createElement('div', {\n key: 'features',\n className: \"space-y-2\"\n }, [\n React.createElement('div', {\n key: 'f1',\n className: \"flex items-center text-sm text-muted\"\n }, [\n React.createElement('i', {\n className: 'fas fa-key accent-orange mr-2 text-xs'\n }),\n 'Generating ECDH keys'\n ]),\n React.createElement('div', {\n key: 'f2',\n className: \"flex items-center text-sm text-muted\"\n }, [\n React.createElement('i', {\n className: 'fas fa-shield-alt accent-orange mr-2 text-xs'\n }),\n 'Verification code'\n ]),\n React.createElement('div', {\n key: 'f3',\n className: \"flex items-center text-sm text-muted\"\n }, [\n React.createElement('i', {\n className: 'fas fa-sync-alt accent-purple mr-2 text-xs'\n }),\n 'PFS key rotation'\n ])\n ])\n ]),\n React.createElement('div', {\n key: 'divider',\n className: \"flex flex-row md:flex-col items-center gap-4 px-4 w-full md:w-auto\"\n }, [\n React.createElement('div', {\n key: 'line-a',\n className: \"h-px flex-1 bg-gradient-to-r from-transparent via-zinc-700 to-transparent md:h-32 md:w-px md:flex-none md:bg-gradient-to-b\"\n }),\n React.createElement('div', {\n key: 'or-text',\n className: \"text-zinc-600 text-sm font-medium px-3\"\n }, \"OR\"),\n React.createElement('div', {\n key: 'line-b',\n className: \"h-px flex-1 bg-gradient-to-r from-transparent via-zinc-700 to-transparent md:h-32 md:w-px md:flex-none md:bg-gradient-to-b\"\n })\n ]),\n // Join Connection\n React.createElement('div', {\n key: 'join',\n onClick: () => {\n requestNotificationPermissionOnInteraction();\n setMode('join');\n },\n className: \"card-minimal rounded-xl p-6 cursor-pointer group flex-1 join\"\n }, [\n React.createElement('div', {\n key: 'icon',\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\"\n }, [\n React.createElement('i', {\n className: 'fas fa-link text-xl accent-green'\n })\n ]),\n React.createElement('h3', {\n key: 'title',\n className: \"text-lg font-semibold text-primary text-center mb-3\"\n }, \"Join\"),\n React.createElement('p', {\n key: 'description',\n className: \"text-secondary text-center text-sm mb-4\"\n }, \"Connect to an existing secure channel\"),\n React.createElement('div', {\n key: 'features',\n className: \"space-y-2\"\n }, [\n React.createElement('div', {\n key: 'f1',\n className: \"flex items-center text-sm text-muted\"\n }, [\n React.createElement('i', {\n className: 'fas fa-paste accent-green mr-2 text-xs'\n }),\n 'Paste Offer invitation'\n ]),\n React.createElement('div', {\n key: 'f2',\n className: \"flex items-center text-sm text-muted\"\n }, [\n React.createElement('i', {\n className: 'fas fa-check-circle accent-green mr-2 text-xs'\n }),\n 'Automatic verification'\n ]),\n React.createElement('div', {\n key: 'f3',\n className: \"flex items-center text-sm text-muted\"\n }, [\n React.createElement('i', {\n className: 'fas fa-sync-alt accent-purple mr-2 text-xs'\n }),\n 'PFS protection'\n ])\n ])\n ])\n ]),\n \n \n React.createElement(SecurityFeatures, { key: 'security-features' }),\n\n React.createElement(Testimonials, { key: 'testimonials' }),\n \n React.createElement(UniqueFeatureSlider, { key: 'unique-features-slider' }),\n \n React.createElement(DownloadApps, { key: 'download-apps' }),\n\n React.createElement(BecomePartner, { key: 'become-partner' }),\n\n React.createElement(ComparisonTable, { key: 'comparison-table' }),\n \n React.createElement(Roadmap, { key: 'roadmap' }),\n ])\n ]);\n }\n \n if (mode === 'create') {\n return React.createElement('div', {\n className: \"min-h-[calc(100vh-104px)] flex items-center justify-center p-4\"\n }, [\n React.createElement('div', {\n key: 'create-flow',\n className: \"w-full max-w-3xl space-y-6\"\n }, [\n React.createElement('div', {\n key: 'header',\n className: \"text-center\"\n }, [\n React.createElement('button', {\n key: 'back',\n onClick: resetToSelect,\n className: \"mb-4 text-secondary hover:text-primary transition-colors flex items-center mx-auto text-sm\"\n }, [\n React.createElement('i', {\n className: 'fas fa-arrow-left mr-2'\n }),\n 'Back to selection'\n ]),\n React.createElement('h2', {\n key: 'title',\n className: \"text-xl font-semibold text-primary mb-2\"\n }, 'Creating a secure channel')\n ]),\n\n // Step 1\n !showAnswerStep && React.createElement('div', {\n key: 'step1',\n className: \"card-minimal rounded-xl p-6\"\n }, [\n React.createElement('div', {\n key: 'step-header',\n className: \"flex items-center mb-4\"\n }, [\n React.createElement('div', {\n key: 'number',\n className: \"step-number mr-3\"\n }, '1'),\n React.createElement('h3', {\n key: 'title',\n className: \"text-lg font-medium text-primary\"\n }, \"Generating ECDH keys and verification code\")\n ]),\n React.createElement('p', {\n key: 'description',\n className: \"text-secondary text-sm mb-4\"\n }, \"Creating cryptographically strong keys and codes to protect against attacks\"),\n !showOfferStep && isGeneratingKeys && React.createElement('div', {\n key: 'loading-state',\n className: \"w-full py-3 px-4 rounded-lg font-medium transition-all duration-200 bg-blue-500/10 border border-blue-500/20 text-blue-400 flex items-center justify-center\"\n }, [\n React.createElement('i', {\n key: 'spinner',\n className: 'fas fa-spinner fa-spin mr-2'\n }),\n 'Generating secure keys...'\n ]),\n \n showOfferStep && React.createElement('div', {\n key: 'offer-result',\n className: \"mt-6 space-y-4\"\n }, [\n React.createElement('div', {\n key: 'success',\n className: \"p-3 bg-green-500/10 border border-green-500/20 rounded-lg\"\n }, [\n React.createElement('p', {\n className: \"text-green-400 text-sm font-medium flex items-center\"\n }, [\n React.createElement('i', {\n className: 'fas fa-check-circle mr-2'\n }),\n 'Secure invitation created! Send the code to your contact'\n ])\n ]),\n React.createElement('div', {\n key: 'offer-data',\n className: \"space-y-3\"\n }, [\n // Raw JSON hidden intentionally; users copy compressed string or use QR\n React.createElement('div', {\n key: 'buttons',\n className: \"flex gap-2\"\n }, [\n React.createElement(EnhancedCopyButton, {\n key: 'copy',\n text: (() => {\n try {\n const min = typeof offerData === 'object' ? JSON.stringify(offerData) : (offerData || '');\n if (typeof window.encodeBinaryToPrefixed === 'function') {\n return window.encodeBinaryToPrefixed(min);\n }\n if (typeof window.compressToPrefixedGzip === 'function') {\n return window.compressToPrefixedGzip(min);\n }\n return min;\n } catch { return typeof offerData === 'object' ? JSON.stringify(offerData) : (offerData || ''); }\n })(),\n className: \"flex-1 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\"\n }, 'Copy invitation code'),\n ]),\n showQRCode && qrCodeUrl && React.createElement('div', {\n key: 'qr-container',\n className: \"mt-4 p-4 border border-gray-600/30 rounded-lg text-center\"\n }, [\n React.createElement('h4', {\n key: 'qr-title',\n className: \"text-sm font-medium text-primary mb-3\"\n }, 'Scan QR code to connect'),\n React.createElement('div', {\n key: 'qr-wrapper',\n className: \"flex justify-center\"\n }, [\n React.createElement('img', {\n key: 'qr-image',\n src: qrCodeUrl,\n alt: \"QR Code for secure connection\",\n className: \"max-w-none h-auto border border-gray-600/30 rounded w-[20rem] sm:w-[24rem] md:w-[28rem] lg:w-[32rem]\"\n })\n ]),\n\n ((qrFramesTotal || 0) >= 1) && React.createElement('div', {\n key: 'qr-controls-below',\n className: \"mt-4 flex flex-col items-center gap-2\"\n }, [\n React.createElement('div', {\n key: 'frame-indicator',\n className: \"text-xs text-gray-300\"\n }, `Frame ${Math.max(1, (qrFrameIndex || 1))}/${qrFramesTotal || 1}`),\n React.createElement('div', {\n key: 'control-buttons',\n className: \"flex gap-1\"\n }, [\n (qrFramesTotal || 0) > 1 && React.createElement('button', {\n key: 'prev-frame',\n onClick: prevQrFrame,\n className: \"w-6 h-6 bg-gray-600 hover:bg-gray-500 text-white rounded text-xs flex items-center justify-center\"\n }, '\u25C0'),\n React.createElement('button', {\n key: 'toggle-manual',\n onClick: toggleQrManualMode,\n className: `px-2 py-1 rounded text-xs font-medium ${\n (qrManualMode || false)\n ? 'bg-blue-500 text-white' \n : 'bg-gray-600 text-gray-300 hover:bg-gray-500'\n }`\n }, (qrManualMode || false) ? 'Manual' : 'Auto'),\n (qrFramesTotal || 0) > 1 && React.createElement('button', {\n key: 'next-frame',\n onClick: nextQrFrame,\n className: \"w-6 h-6 bg-gray-600 hover:bg-gray-500 text-white rounded text-xs flex items-center justify-center\"\n }, '\u25B6')\n ])\n ]),\n React.createElement('p', {\n key: 'qr-description',\n className: \"text-xs text-gray-400 mt-2\"\n }, 'Your contact can scan this QR code to quickly join the secure session')\n ])\n ])\n ])\n ]), \n \n showOfferStep && React.createElement('div', {\n key: 'step2',\n className: \"card-minimal rounded-xl p-6\"\n }, [\n React.createElement('div', {\n key: 'step-header',\n className: \"flex items-center mb-4\"\n }, [\n React.createElement('div', {\n key: 'number',\n className: \"w-8 h-8 bg-blue-500 text-white rounded-lg flex items-center justify-center font-semibold text-sm mr-3\"\n }, '2'),\n React.createElement('h3', {\n key: 'title',\n className: \"text-lg font-medium text-primary\"\n }, \"Waiting for the peer's response\")\n ]),\n React.createElement('p', {\n key: 'description',\n className: \"text-secondary text-sm mb-4\"\n }, \"Paste the encrypted invitation code from your contact.\"),\n React.createElement('div', {\n key: 'buttons',\n className: \"flex gap-2 mb-4\"\n }, [\n React.createElement('button', {\n key: 'scan-btn',\n onClick: () => setShowQRScannerModal(true),\n className: \"px-4 py-2 bg-purple-500/10 hover:bg-purple-500/20 text-purple-400 border border-purple-500/20 rounded text-sm font-medium transition-all duration-200\"\n }, [\n React.createElement('i', {\n key: 'icon',\n className: 'fas fa-qrcode mr-2'\n }),\n 'Scan QR Code'\n ]),\n ]),\n React.createElement('textarea', {\n key: 'input',\n value: answerInput,\n onChange: (e) => {\n setAnswerInput(e.target.value);\n // Mark answer as created when user manually enters data\n if (e.target.value.trim().length > 0) {\n if (typeof markAnswerCreated === 'function') {\n markAnswerCreated();\n }\n }\n\n },\n rows: 6,\n placeholder: \"Paste the encrypted response code from your contact or scan QR code...\",\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\"\n }),\n React.createElement('button', {\n key: 'connect-btn',\n onClick: onConnect,\n disabled: !answerInput.trim(),\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\"\n }, [\n React.createElement('i', {\n className: 'fas fa-rocket mr-2'\n }),\n 'Establish connection'\n ])\n ])\n ])\n ]);\n }\n \n if (mode === 'join') {\n return React.createElement('div', {\n className: \"min-h-[calc(100vh-104px)] flex items-center justify-center p-4\"\n }, [\n React.createElement('div', {\n key: 'join-flow',\n className: \"w-full max-w-3xl space-y-6\"\n }, [\n React.createElement('div', {\n key: 'header',\n className: \"text-center\"\n }, [\n React.createElement('button', {\n key: 'back',\n onClick: resetToSelect,\n className: \"mb-4 text-secondary hover:text-primary transition-colors flex items-center mx-auto text-sm\"\n }, [\n React.createElement('i', {\n className: 'fas fa-arrow-left mr-2'\n }),\n 'Back to selection'\n ]),\n React.createElement('h2', {\n key: 'title',\n className: \"text-xl font-semibold text-primary mb-2\"\n }, 'Joining the secure channel')\n ]),\n \n (showAnswerStep ? null : React.createElement('div', {\n key: 'step1',\n className: \"card-minimal rounded-xl p-6\"\n }, [\n React.createElement('div', {\n key: 'step-header',\n className: \"flex items-center mb-4\"\n }, [\n React.createElement('div', {\n key: 'number',\n className: \"w-8 h-8 bg-green-500 text-white rounded-lg flex items-center justify-center font-semibold text-sm mr-3\"\n }, '1'),\n React.createElement('h3', {\n key: 'title',\n className: \"text-lg font-medium text-primary\"\n }, \"Paste secure invitation\")\n ]),\n React.createElement('p', {\n key: 'description',\n className: \"text-secondary text-sm mb-4\"\n }, \"Copy and paste the encrypted invitation code from the initiator.\"),\n React.createElement('textarea', {\n key: 'input',\n value: offerInput,\n onChange: (e) => {\n setOfferInput(e.target.value);\n if (e.target.value.trim().length > 0) {\n if (typeof markAnswerCreated === 'function') {\n markAnswerCreated();\n }\n }\n },\n rows: 8,\n placeholder: \"Paste the encrypted invitation code or scan QR code...\",\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\"\n }),\n React.createElement('div', {\n key: 'buttons',\n className: \"flex gap-2 mb-4\"\n }, [\n React.createElement('button', {\n key: 'scan-btn',\n onClick: () => setShowQRScannerModal(true),\n className: \"px-4 py-2 bg-purple-500/10 hover:bg-purple-500/20 text-purple-400 border border-purple-500/20 rounded text-sm font-medium transition-all duration-200\"\n }, [\n React.createElement('i', {\n key: 'icon',\n className: 'fas fa-qrcode mr-2'\n }),\n 'Scan QR Code'\n ]),\n React.createElement('button', {\n key: 'process-btn',\n onClick: onCreateAnswer,\n disabled: !offerInput.trim() || connectionStatus === 'connecting',\n className: \"flex-1 btn-secondary text-white py-2 px-4 rounded-lg font-medium transition-all duration-200 disabled:opacity-50 disabled:cursor-not-allowed\"\n }, [\n React.createElement('i', {\n className: 'fas fa-cogs mr-2'\n }),\n 'Process invitation'\n ])\n ]),\n showQRScanner && React.createElement('div', {\n key: 'qr-scanner',\n className: \"p-4 bg-gray-800/50 border border-gray-600/30 rounded-lg text-center\"\n }, [\n React.createElement('h4', {\n key: 'scanner-title',\n className: \"text-sm font-medium text-primary mb-3\"\n }, 'QR Code Scanner'),\n React.createElement('p', {\n key: 'scanner-description',\n className: \"text-xs text-gray-400 mb-3\"\n }, 'Use your device camera to scan the QR code from the invitation'),\n React.createElement('button', {\n key: 'open-scanner',\n onClick: () => {\n if (typeof setShowQRScannerModal === 'function') {\n setShowQRScannerModal(true);\n } else {\n console.error('setShowQRScannerModal is not a function:', setShowQRScannerModal);\n }\n },\n className: \"w-full px-4 py-3 bg-purple-600 hover:bg-purple-500 text-white rounded-lg font-medium transition-all duration-200 mb-3\"\n }, [\n React.createElement('i', {\n key: 'camera-icon',\n className: 'fas fa-camera mr-2'\n }),\n 'Open Camera Scanner'\n ]),\n React.createElement('button', {\n key: 'test-qr',\n onClick: async () => {\n console.log('Creating test QR code...');\n if (window.generateQRCode) {\n const testData = '{\"type\":\"test\",\"message\":\"Hello QR Scanner!\"}';\n const qrUrl = await window.generateQRCode(testData);\n console.log('Test QR code generated:', qrUrl);\n const newWindow = window.open();\n newWindow.document.write(``);\n }\n },\n className: \"px-3 py-1 bg-green-600/20 hover:bg-green-600/30 text-green-300 border border-green-500/20 rounded text-xs font-medium transition-all duration-200 mr-2\"\n }, 'Test QR'),\n React.createElement('button', {\n key: 'close-scanner',\n onClick: () => setShowQRScanner(false),\n className: \"px-3 py-1 bg-gray-600/20 hover:bg-gray-600/30 text-gray-300 border border-gray-500/20 rounded text-xs font-medium transition-all duration-200\"\n }, 'Close Scanner')\n ])\n ])),\n \n // Step 2\n showAnswerStep && React.createElement('div', {\n key: 'step2',\n className: \"card-minimal rounded-xl p-6\"\n }, [\n React.createElement('div', {\n key: 'step-header',\n className: \"flex items-center mb-4\"\n }, [\n React.createElement('div', {\n key: 'number',\n className: \"step-number mr-3\"\n }, '2'),\n React.createElement('h3', {\n key: 'title',\n className: \"text-lg font-medium text-primary\"\n }, \"Sending a secure response\")\n ]),\n React.createElement('div', {\n key: 'success',\n className: \"p-3 bg-green-500/10 border border-green-500/20 rounded-lg mb-4\"\n }, [\n React.createElement('p', {\n className: \"text-green-400 text-sm font-medium flex items-center\"\n }, [\n React.createElement('i', {\n className: 'fas fa-check-circle mr-2'\n }),\n 'Secure response created! Send this code to the initiator:'\n ])\n ]),\n React.createElement('div', {\n key: 'answer-data',\n className: \"space-y-3 mb-4\"\n }, [\n // Raw JSON hidden intentionally; users copy compressed string or use QR\n React.createElement(EnhancedCopyButton, {\n key: 'copy',\n text: (() => {\n try {\n const min = typeof answerData === 'object' ? JSON.stringify(answerData) : (answerData || '');\n if (typeof window.encodeBinaryToPrefixed === 'function') {\n return window.encodeBinaryToPrefixed(min);\n }\n if (typeof window.compressToPrefixedGzip === 'function') {\n return window.compressToPrefixedGzip(min);\n }\n return min;\n } catch { return typeof answerData === 'object' ? JSON.stringify(answerData) : (answerData || ''); }\n })(),\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\"\n }, 'Copy response code')\n ]),\n // QR Code section for answer\n qrCodeUrl && React.createElement('div', {\n key: 'qr-container',\n className: \"mt-4 p-4 border border-gray-600/30 rounded-lg text-center\"\n }, [\n React.createElement('h4', {\n key: 'qr-title',\n className: \"text-sm font-medium text-primary mb-3\"\n }, 'Scan QR code to complete connection'),\n React.createElement('div', {\n key: 'qr-wrapper',\n className: \"flex justify-center\"\n }, [\n React.createElement('img', {\n key: 'qr-image',\n src: qrCodeUrl,\n alt: \"QR Code for secure response\",\n className: \"max-w-none h-auto border border-gray-600/30 rounded w-[20rem] sm:w-[24rem] md:w-[28rem] lg:w-[32rem]\"\n })\n ]),\n\n ((qrFramesTotal || 0) >= 1) && React.createElement('div', {\n key: 'qr-controls-below',\n className: \"mt-4 flex flex-col items-center gap-2\"\n }, [\n React.createElement('div', {\n key: 'frame-indicator',\n className: \"text-xs text-gray-300\"\n }, `Frame ${Math.max(1, (qrFrameIndex || 1))}/${qrFramesTotal || 1}`),\n React.createElement('div', {\n key: 'control-buttons',\n className: \"flex gap-1\"\n }, [\n (qrFramesTotal || 0) > 1 && React.createElement('button', {\n key: 'prev-frame',\n onClick: prevQrFrame,\n className: \"w-6 h-6 bg-gray-600 hover:bg-gray-500 text-white rounded text-xs flex items-center justify-center\"\n }, '\u25C0'),\n React.createElement('button', {\n key: 'toggle-manual',\n onClick: toggleQrManualMode,\n className: `px-2 py-1 rounded text-xs font-medium ${\n qrManualMode \n ? 'bg-blue-500 text-white' \n : 'bg-gray-600 text-gray-300 hover:bg-gray-500'\n }`\n }, qrManualMode ? 'Manual' : 'Auto'),\n (qrFramesTotal || 0) > 1 && React.createElement('button', {\n key: 'next-frame',\n onClick: nextQrFrame,\n className: \"w-6 h-6 bg-gray-600 hover:bg-gray-500 text-white rounded text-xs flex items-center justify-center\"\n }, '\u25B6')\n ])\n ]),\n React.createElement('p', {\n key: 'qr-description',\n className: \"text-xs text-gray-400 mt-2\"\n }, 'The initiator can scan this QR code to complete the secure connection')\n ]),\n React.createElement('div', {\n key: 'info',\n className: \"p-3 bg-purple-500/10 border border-purple-500/20 rounded-lg\"\n }, [\n React.createElement('p', {\n className: \"text-purple-400 text-sm flex items-center justify-center\"\n }, [\n React.createElement('i', {\n className: 'fas fa-shield-alt mr-2'\n }),\n 'The connection will be established with verification'\n ])\n ])\n ])\n ])\n ]);\n }\n };\n \n // Global scroll function - defined outside components to ensure availability\n const createScrollToBottomFunction = (chatMessagesRef) => {\n return () => {\n if (chatMessagesRef && chatMessagesRef.current) {\n const scrollAttempt = () => {\n if (chatMessagesRef.current) {\n chatMessagesRef.current.scrollTo({\n top: chatMessagesRef.current.scrollHeight,\n behavior: 'smooth'\n });\n }\n };\n scrollAttempt();\n \n setTimeout(scrollAttempt, 50);\n setTimeout(scrollAttempt, 150);\n setTimeout(scrollAttempt, 300);\n \n requestAnimationFrame(() => {\n setTimeout(scrollAttempt, 100);\n });\n }\n };\n };\n \n \n const EnhancedChatInterface = ({\n messages,\n messageInput,\n setMessageInput,\n onSendMessage,\n onDisconnect,\n keyFingerprint,\n isVerified,\n chatMessagesRef,\n scrollToBottom,\n webrtcManager\n }) => {\n const [showScrollButton, setShowScrollButton] = React.useState(false);\n const [showFileTransfer, setShowFileTransfer] = React.useState(false);\n\n React.useEffect(() => {\n if (chatMessagesRef.current && messages.length > 0) {\n const { scrollTop, scrollHeight, clientHeight } = chatMessagesRef.current;\n const isNearBottom = scrollHeight - scrollTop - clientHeight < 100;\n if (isNearBottom) {\n const smoothScroll = () => {\n if (chatMessagesRef.current) {\n chatMessagesRef.current.scrollTo({\n top: chatMessagesRef.current.scrollHeight,\n behavior: 'smooth'\n });\n }\n };\n smoothScroll();\n setTimeout(smoothScroll, 50);\n setTimeout(smoothScroll, 150);\n }\n }\n }, [messages, chatMessagesRef]);\n \n // \u041E\u0431\u0440\u0430\u0431\u043E\u0442\u0447\u0438\u043A \u0441\u043A\u0440\u043E\u043B\u043B\u0430\n const handleScroll = () => {\n if (chatMessagesRef.current) {\n const { scrollTop, scrollHeight, clientHeight } = chatMessagesRef.current;\n const isNearBottom = scrollHeight - scrollTop - clientHeight < 100;\n setShowScrollButton(!isNearBottom);\n }\n };\n \n // \u041F\u0440\u043E\u043A\u0440\u0443\u0442\u043A\u0430 \u0432\u043D\u0438\u0437 \u043F\u043E \u043A\u043D\u043E\u043F\u043A\u0435\n const handleScrollToBottom = () => {\n console.log('\uD83D\uDD0D handleScrollToBottom called, scrollToBottom type:', typeof scrollToBottom);\n if (typeof scrollToBottom === 'function') {\n scrollToBottom();\n setShowScrollButton(false);\n } else {\n console.error('scrollToBottom is not a function:', scrollToBottom);\n // Fallback: direct scroll\n if (chatMessagesRef.current) {\n chatMessagesRef.current.scrollTo({\n top: chatMessagesRef.current.scrollHeight,\n behavior: 'smooth'\n });\n }\n setShowScrollButton(false);\n }\n };\n\n const handleKeyPress = (e) => {\n if (e.key === 'Enter' && !e.shiftKey) {\n e.preventDefault();\n onSendMessage();\n }\n };\n\n const isFileTransferReady = () => {\n if (!webrtcManager) return false;\n \n const connected = webrtcManager.isConnected ? webrtcManager.isConnected() : false;\n const verified = webrtcManager.isVerified || false;\n const hasDataChannel = webrtcManager.dataChannel && webrtcManager.dataChannel.readyState === 'open';\n \n return connected && verified && hasDataChannel;\n };\n \n // \u0412\u043E\u0437\u0432\u0440\u0430\u0442 JSX \u0447\u0435\u0440\u0435\u0437 React.createElement\n return React.createElement(\n 'div',\n {\n className: \"chat-container flex flex-col\",\n style: { backgroundColor: '#272827', height: 'calc(100vh - 64px)' }\n },\n [\n // \u041E\u0431\u043B\u0430\u0441\u0442\u044C \u0441\u043E\u043E\u0431\u0449\u0435\u043D\u0438\u0439\n React.createElement(\n 'div',\n { className: \"flex-1 flex flex-col overflow-hidden\" },\n React.createElement(\n 'div',\n { className: \"flex-1 max-w-4xl mx-auto w-full p-4 overflow-hidden\" },\n React.createElement(\n 'div',\n {\n ref: chatMessagesRef,\n onScroll: handleScroll,\n className: \"h-full overflow-y-auto space-y-3 hide-scrollbar pr-2 scroll-smooth\"\n },\n messages.length === 0 ?\n React.createElement(\n 'div',\n { className: \"flex items-center justify-center h-full\" },\n React.createElement(\n 'div',\n { className: \"text-center max-w-md\" },\n [\n React.createElement(\n 'div',\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\" },\n React.createElement(\n 'svg',\n { className: \"w-8 h-8 text-green-500\", fill: \"none\", stroke: \"currentColor\", viewBox: \"0 0 24 24\" },\n React.createElement('path', {\n strokeLinecap: \"round\",\n strokeLinejoin: \"round\",\n strokeWidth: 2,\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\"\n })\n )\n ),\n React.createElement('h3', { className: \"text-lg font-medium text-gray-300 mb-2\" }, \"Secure channel is ready!\"),\n React.createElement('p', { className: \"text-gray-400 text-sm mb-4\" }, \"All messages are protected by modern cryptographic algorithms\"),\n React.createElement(\n 'div',\n { className: \"text-left space-y-2\" },\n [\n ['End-to-end encryption', 'M5 13l4 4L19 7'],\n ['Protection against replay attacks', 'M5 13l4 4L19 7'],\n ['Integrity verification', 'M5 13l4 4L19 7'],\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']\n ].map(([text, d], i) =>\n React.createElement(\n 'div',\n { key: `f${i}`, className: \"flex items-center text-sm text-gray-400\" },\n [\n React.createElement(\n 'svg',\n {\n className: `w-4 h-4 mr-3 ${i === 3 ? 'text-purple-500' : 'text-green-500'}`,\n fill: \"none\",\n stroke: \"currentColor\",\n viewBox: \"0 0 24 24\"\n },\n React.createElement('path', {\n strokeLinecap: \"round\",\n strokeLinejoin: \"round\",\n strokeWidth: 2,\n d: d\n })\n ),\n text\n ]\n )\n )\n )\n ]\n )\n ) :\n messages.map((msg) =>\n React.createElement(EnhancedChatMessage, {\n key: msg.id,\n message: msg.message,\n type: msg.type,\n timestamp: msg.timestamp\n })\n )\n )\n )\n ),\n \n // \u041A\u043D\u043E\u043F\u043A\u0430 \u043F\u0440\u043E\u043A\u0440\u0443\u0442\u043A\u0438 \u0432\u043D\u0438\u0437\n showScrollButton &&\n React.createElement(\n 'button',\n {\n onClick: handleScrollToBottom,\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\",\n style: { bottom: '160px' }\n },\n React.createElement(\n 'svg',\n { className: \"w-6 h-6\", fill: \"none\", stroke: \"currentColor\", viewBox: \"0 0 24 24\" },\n React.createElement('path', {\n strokeLinecap: \"round\",\n strokeLinejoin: \"round\",\n strokeWidth: 2,\n d: \"M19 14l-7 7m0 0l-7-7m7 7V3\"\n })\n )\n ),\n\n React.createElement(\n 'div',\n {\n className: \"flex-shrink-0 border-t border-gray-500/10\",\n style: { backgroundColor: '#272827' }\n },\n React.createElement(\n 'div',\n { className: \"max-w-4xl mx-auto px-4\" },\n [\n React.createElement(\n 'button',\n {\n onClick: () => setShowFileTransfer(!showFileTransfer),\n className: `flex items-center text-sm text-gray-400 hover:text-gray-300 transition-colors py-4 ${showFileTransfer ? 'mb-4' : ''}`\n },\n [\n React.createElement(\n 'svg',\n {\n className: `w-4 h-4 mr-2 transform transition-transform ${showFileTransfer ? 'rotate-180' : ''}`,\n fill: \"none\",\n stroke: \"currentColor\",\n viewBox: \"0 0 24 24\"\n },\n showFileTransfer ?\n React.createElement('path', {\n strokeLinecap: \"round\",\n strokeLinejoin: \"round\",\n strokeWidth: 2,\n d: \"M5 15l7-7 7 7\"\n }) :\n React.createElement('path', {\n strokeLinecap: \"round\",\n strokeLinejoin: \"round\",\n strokeWidth: 2,\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\"\n })\n ),\n showFileTransfer ? 'Hide file transfer' : 'Send files'\n ]\n ),\n showFileTransfer &&\n React.createElement(window.FileTransferComponent || (() => \n React.createElement('div', {\n className: \"p-4 text-center text-red-400\"\n }, 'FileTransferComponent not loaded')\n ), {\n webrtcManager: webrtcManager,\n isConnected: isFileTransferReady()\n })\n ]\n )\n ),\n\n React.createElement(\n 'div',\n { className: \"border-t border-gray-500/10\" },\n React.createElement(\n 'div',\n { className: \"max-w-4xl mx-auto p-4\" },\n React.createElement(\n 'div',\n { className: \"flex items-stretch space-x-3\" },\n [\n React.createElement(\n 'div',\n { className: \"flex-1 relative\" },\n [\n React.createElement('textarea', {\n value: messageInput,\n onChange: (e) => setMessageInput(e.target.value),\n onKeyDown: handleKeyPress,\n placeholder: \"Enter message to encrypt...\",\n rows: 2,\n maxLength: 2000,\n style: { backgroundColor: '#272827' },\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\"\n }),\n React.createElement(\n 'div',\n { className: \"absolute bottom-2 right-3 flex items-center space-x-2 text-xs text-gray-400\" },\n [\n React.createElement('span', null, `${messageInput.length}/2000`),\n React.createElement('span', null, \"\u2022 Enter to send\")\n ]\n )\n ]\n ),\n React.createElement(\n 'button',\n {\n onClick: onSendMessage,\n disabled: !messageInput.trim(),\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]\"\n },\n React.createElement(\n 'svg',\n { className: \"w-6 h-6\", fill: \"none\", stroke: \"currentColor\", viewBox: \"0 0 24 24\" },\n React.createElement('path', {\n strokeLinecap: \"round\",\n strokeLinejoin: \"round\",\n strokeWidth: 2,\n d: \"M12 19l9 2-9-18-9 18 9-2zm0 0v-8\"\n })\n )\n )\n ]\n )\n )\n )\n ]\n );\n };\n \n \n // Main Enhanced Application Component\n const EnhancedSecureP2PChat = () => {\n\n const [messages, setMessages] = React.useState([]);\n const [connectionStatus, setConnectionStatus] = React.useState('disconnected');\n const [relayOnlyMode, setRelayOnlyMode] = React.useState(() => {\n try { return localStorage.getItem('securebit_relay_only_mode') === 'true'; } catch { return false; }\n });\n \n // Moved scrollToBottom logic to be available globally\n const [messageInput, setMessageInput] = React.useState('');\n const [offerData, setOfferData] = React.useState('');\n const [answerData, setAnswerData] = React.useState('');\n const [offerInput, setOfferInput] = React.useState('');\n const [answerInput, setAnswerInput] = React.useState('');\n const [keyFingerprint, setKeyFingerprint] = React.useState('');\n const [verificationCode, setVerificationCode] = React.useState('');\n const [showOfferStep, setShowOfferStep] = React.useState(false);\n const [showAnswerStep, setShowAnswerStep] = React.useState(false);\n const [showVerification, setShowVerification] = React.useState(false);\n const [showQRCode, setShowQRCode] = React.useState(false);\n const [qrCodeUrl, setQrCodeUrl] = React.useState('');\n const [showQRScanner, setShowQRScanner] = React.useState(false);\n const [showQRScannerModal, setShowQRScannerModal] = React.useState(false);\n const [isGeneratingKeys, setIsGeneratingKeys] = React.useState(false);\n \n\n const [isVerified, setIsVerified] = React.useState(false);\n const [securityLevel, setSecurityLevel] = React.useState(null);\n const [sessionTimeLeft, setSessionTimeLeft] = React.useState(0);\n \n // Mutual verification states\n const [localVerificationConfirmed, setLocalVerificationConfirmed] = React.useState(false);\n const [remoteVerificationConfirmed, setRemoteVerificationConfirmed] = React.useState(false);\n const [bothVerificationsConfirmed, setBothVerificationsConfirmed] = React.useState(false);\n \n // PAKE password states removed - using SAS verification instead\n \n // Session state - all security features enabled by default\n const [pendingSession, setPendingSession] = React.useState(null);\n \n // All security features are enabled by default - no payment required\n \n \n \n // ============================================\n // CENTRALIZED CONNECTION STATE MANAGEMENT\n // ============================================\n \n const [connectionState, setConnectionState] = React.useState({\n status: 'disconnected',\n hasActiveAnswer: false,\n answerCreatedAt: null,\n isUserInitiatedDisconnect: false\n });\n \n // Centralized connection state handler\n const updateConnectionState = (newState, options = {}) => {\n const { preserveAnswer = false, isUserAction = false } = options;\n \n setConnectionState(prev => ({\n ...prev,\n ...newState,\n isUserInitiatedDisconnect: isUserAction,\n hasActiveAnswer: preserveAnswer ? prev.hasActiveAnswer : false,\n answerCreatedAt: preserveAnswer ? prev.answerCreatedAt : null\n }));\n };\n \n // Check if we should preserve answer data\n const shouldPreserveAnswerData = () => {\n const now = Date.now();\n const answerAge = now - (connectionState.answerCreatedAt || 0);\n const maxPreserveTime = 300000;\n \n\n const hasAnswerData = (answerData && typeof answerData === 'string' && answerData.trim().length > 0) || \n (answerInput && answerInput.trim().length > 0);\n\n const hasAnswerQR = qrCodeUrl && qrCodeUrl.trim().length > 0;\n \n const shouldPreserve = (connectionState.hasActiveAnswer && \n answerAge < maxPreserveTime && \n !connectionState.isUserInitiatedDisconnect) ||\n (hasAnswerData && answerAge < maxPreserveTime && \n !connectionState.isUserInitiatedDisconnect) ||\n (hasAnswerQR && answerAge < maxPreserveTime && \n !connectionState.isUserInitiatedDisconnect);\n \n \n return shouldPreserve;\n };\n \n // Mark answer as created\n const markAnswerCreated = () => {\n updateConnectionState({\n hasActiveAnswer: true,\n answerCreatedAt: Date.now()\n });\n };\n \n // Global functions for cleanup\n React.useEffect(() => {\n window.forceCleanup = () => {\n handleClearData();\n if (webrtcManagerRef.current) {\n webrtcManagerRef.current.disconnect();\n }\n };\n\n window.clearLogs = () => {\n if (typeof console.clear === 'function') {\n console.clear();\n }\n };\n \n return () => {\n delete window.forceCleanup;\n delete window.clearLogs;\n };\n }, []);\n \n const webrtcManagerRef = React.useRef(null);\n const notificationIntegrationRef = React.useRef(null);\n // Expose for modules/UI that run outside this closure (e.g., inline handlers)\n // Safe because it's a ref object and we maintain it centrally here\n window.webrtcManagerRef = webrtcManagerRef;\n \n const addMessageWithAutoScroll = React.useCallback((message, type) => {\n const newMessage = {\n message,\n type,\n id: Date.now() + Math.random(),\n timestamp: Date.now()\n };\n \n setMessages(prev => {\n const updated = [...prev, newMessage];\n \n setTimeout(() => {\n if (chatMessagesRef?.current) {\n const container = chatMessagesRef.current;\n try {\n const { scrollTop, scrollHeight, clientHeight } = container;\n const isNearBottom = scrollHeight - scrollTop - clientHeight < 100;\n \n if (isNearBottom || prev.length === 0) {\n requestAnimationFrame(() => {\n if (container && container.scrollTo) {\n container.scrollTo({\n top: container.scrollHeight,\n behavior: 'smooth'\n });\n }\n });\n }\n } catch (error) {\n console.warn('Scroll error:', error);\n container.scrollTop = container.scrollHeight;\n }\n }\n }, 50);\n \n return updated;\n });\n }, []);\n \n // Update security level based on real verification\n const updateSecurityLevel = React.useCallback(async () => {\n if (window.isUpdatingSecurity) {\n return;\n }\n \n window.isUpdatingSecurity = true;\n \n try {\n if (webrtcManagerRef.current) {\n // All security features are enabled by default - always show MAXIMUM level\n setSecurityLevel({\n level: 'MAXIMUM',\n score: 100,\n color: 'green',\n details: 'All security features enabled by default',\n passedChecks: 10,\n totalChecks: 10,\n isRealData: true\n });\n \n if (window.DEBUG_MODE) {\n const currentLevel = webrtcManagerRef.current.ecdhKeyPair && webrtcManagerRef.current.ecdsaKeyPair \n ? await webrtcManagerRef.current.calculateSecurityLevel()\n : {\n level: 'MAXIMUM',\n score: 100,\n sessionType: 'premium',\n passedChecks: 10,\n totalChecks: 10\n };\n }\n }\n } catch (error) {\n console.error('Failed to update security level:', error);\n setSecurityLevel({\n level: 'ERROR',\n score: 0,\n color: 'red',\n details: 'Verification failed'\n });\n } finally {\n setTimeout(() => {\n window.isUpdatingSecurity = false;\n }, 2000);\n }\n }, []);\n \n // Session time ticker removed - sessions are unlimited\n \n // Sessions are unlimited - no expiration handler needed\n \n // All security features are enabled by default - no demo sessions needed\n const chatMessagesRef = React.useRef(null);\n \n // Create scroll function using global helper\n const scrollToBottom = createScrollToBottomFunction(chatMessagesRef);\n\n React.useEffect(() => {\n try { localStorage.setItem('securebit_relay_only_mode', String(relayOnlyMode)); } catch {}\n if (webrtcManagerRef.current?._config?.webrtc) {\n webrtcManagerRef.current._config.webrtc.relayOnly = relayOnlyMode;\n }\n }, [relayOnlyMode]);\n \n // Auto-scroll when messages change\n React.useEffect(() => {\n if (messages.length > 0 && chatMessagesRef.current) {\n scrollToBottom();\n setTimeout(scrollToBottom, 50);\n setTimeout(scrollToBottom, 150);\n }\n }, [messages]);\n \n // PAKE password functions removed - using SAS verification instead\n \n React.useEffect(() => {\n // Prevent multiple initializations\n if (webrtcManagerRef.current) {\n console.log('\u26A0\uFE0F WebRTC Manager already initialized, skipping...');\n return;\n }\n \n const handleMessage = (message, type) => {\n if (typeof message === 'string' && message.trim().startsWith('{')) {\n try {\n const parsedMessage = JSON.parse(message);\n const blockedTypes = [\n 'file_transfer_start',\n 'file_transfer_response',\n 'file_chunk',\n 'chunk_confirmation',\n 'file_transfer_complete',\n 'file_transfer_error',\n 'heartbeat',\n 'verification',\n 'verification_response',\n 'verification_confirmed',\n 'verification_both_confirmed',\n 'peer_disconnect',\n 'key_rotation_signal',\n 'key_rotation_ready',\n 'security_upgrade'\n ];\n if (parsedMessage.type && blockedTypes.includes(parsedMessage.type)) {\n console.log(`Blocked system/file message from chat: ${parsedMessage.type}`);\n return; \n }\n } catch (parseError) {\n\n }\n }\n \n addMessageWithAutoScroll(message, type);\n };\n \n const handleStatusChange = (status) => {\n setConnectionStatus(status);\n \n if (status === 'connected') {\n document.dispatchEvent(new CustomEvent('new-connection'));\n \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'\n // setIsVerified(true);\n // setShowVerification(false);\n if (!window.isUpdatingSecurity) {\n updateSecurityLevel().catch(console.error);\n }\n } else if (status === 'verifying') {\n setShowVerification(true);\n if (!window.isUpdatingSecurity) {\n updateSecurityLevel().catch(console.error);\n }\n } else if (status === 'verified') {\n setIsVerified(true);\n setShowVerification(false);\n setBothVerificationsConfirmed(true);\n setConnectionStatus('connected');\n // Force immediate update of isVerified state\n setTimeout(() => {\n setIsVerified(true);\n }, 0);\n if (!window.isUpdatingSecurity) {\n updateSecurityLevel().catch(console.error);\n }\n } else if (status === 'connecting') {\n if (!window.isUpdatingSecurity) {\n updateSecurityLevel().catch(console.error);\n }\n } else if (status === 'disconnected') {\n updateConnectionState({ status: 'disconnected' });\n setConnectionStatus('disconnected');\n\n if (shouldPreserveAnswerData()) {\n setIsVerified(false);\n setShowVerification(false);\n return;\n }\n\n setIsVerified(false);\n setShowVerification(false);\n \n // Dispatch disconnected event for SessionTimer\n document.dispatchEvent(new CustomEvent('disconnected'));\n \n // Clear verification states\n setLocalVerificationConfirmed(false);\n setRemoteVerificationConfirmed(false);\n setBothVerificationsConfirmed(false);\n \n // Clear connection data\n setOfferData('');\n setAnswerData('');\n setOfferInput('');\n setAnswerInput('');\n setShowOfferStep(false);\n setShowAnswerStep(false);\n setKeyFingerprint('');\n setVerificationCode('');\n setSecurityLevel(null);\n \n \n // Return to main page after a short delay\n setTimeout(() => {\n setConnectionStatus('disconnected');\n setShowVerification(false);\n \n setOfferData('');\n setAnswerData('');\n setOfferInput('');\n setAnswerInput('');\n setShowOfferStep(false);\n setShowAnswerStep(false);\n setMessages([]);\n }, 1000);\n\n } else if (status === 'peer_disconnected') {\n setSessionTimeLeft(0);\n \n document.dispatchEvent(new CustomEvent('peer-disconnect'));\n \n // A short delay before clearing to display the status\n setTimeout(() => {\n setKeyFingerprint('');\n setVerificationCode('');\n setSecurityLevel(null);\n setIsVerified(false);\n setShowVerification(false);\n setConnectionStatus('disconnected');\n \n // Clear verification states\n setLocalVerificationConfirmed(false);\n setRemoteVerificationConfirmed(false);\n setBothVerificationsConfirmed(false);\n \n // Clear connection data\n setOfferData('');\n setAnswerData('');\n setOfferInput('');\n setAnswerInput('');\n setShowOfferStep(false);\n setShowAnswerStep(false);\n setMessages([]);\n \n\n if (typeof console.clear === 'function') {\n console.clear();\n }\n\n }, 2000);\n }\n };\n \n const handleKeyExchange = (fingerprint) => {\n if (fingerprint === '') {\n setKeyFingerprint('');\n } else {\n setKeyFingerprint(fingerprint);\n }\n };\n \n const handleVerificationRequired = (code) => {\n if (code === '') {\n setVerificationCode('');\n setShowVerification(false);\n } else {\n setVerificationCode(code);\n setShowVerification(true);\n }\n };\n \n const handleVerificationStateChange = (state) => {\n setLocalVerificationConfirmed(state.localConfirmed);\n setRemoteVerificationConfirmed(state.remoteConfirmed);\n setBothVerificationsConfirmed(state.bothConfirmed);\n };\n \n // Callback for handling response errors\n const handleAnswerError = (errorType, errorMessage) => {\n if (errorType === 'replay_attack') {\n // Reset the session upon replay attack\n setSessionTimeLeft(0);\n setPendingSession(null);\n \n addMessageWithAutoScroll('\uD83D\uDCA1 Data is outdated. Please create a new invitation or use a current response code.', 'system');\n \n if (typeof console.clear === 'function') {\n console.clear();\n }\n } else if (errorType === 'security_violation') {\n // Reset the session upon security breach\n setSessionTimeLeft(0);\n setPendingSession(null);\n \n addMessageWithAutoScroll(` Security breach: ${errorMessage}`, 'system');\n \n if (typeof console.clear === 'function') {\n console.clear();\n }\n }\n };\n \n \n if (typeof console.clear === 'function') {\n console.clear();\n }\n \n webrtcManagerRef.current = new EnhancedSecureWebRTCManager(\n handleMessage, \n handleStatusChange, \n handleKeyExchange,\n handleVerificationRequired,\n handleAnswerError,\n handleVerificationStateChange,\n {\n webrtc: {\n relayOnly: relayOnlyMode,\n iceServers: Array.isArray(window.SECUREBIT_ICE_SERVERS) ? window.SECUREBIT_ICE_SERVERS : undefined\n }\n }\n );\n \n // Initialize notification integration if permission was already granted\n if (typeof Notification !== 'undefined' && Notification && Notification.permission === 'granted' && window.NotificationIntegration && !notificationIntegrationRef.current) {\n try {\n const integration = new window.NotificationIntegration(webrtcManagerRef.current);\n integration.init().then(() => {\n notificationIntegrationRef.current = integration;\n }).catch((error) => {\n // Handle error silently\n });\n } catch (error) {\n // Handle error silently\n }\n }\n \n handleMessage(' SecureBit.chat Enhanced Security Edition v4.8.5 - 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');\n \n const handleBeforeUnload = (event) => {\n if (event.type === 'beforeunload' && !isTabSwitching) {\n \n if (webrtcManagerRef.current && webrtcManagerRef.current.isConnected()) {\n try {\n webrtcManagerRef.current.sendSystemMessage({\n type: 'peer_disconnect',\n reason: 'user_disconnect',\n timestamp: Date.now()\n });\n } catch (error) {\n }\n \n setTimeout(() => {\n if (webrtcManagerRef.current) {\n webrtcManagerRef.current.disconnect();\n }\n }, 100);\n } else if (webrtcManagerRef.current) {\n webrtcManagerRef.current.disconnect();\n }\n } else if (isTabSwitching) {\n event.preventDefault();\n event.returnValue = '';\n }\n };\n \n window.addEventListener('beforeunload', handleBeforeUnload);\n \n let isTabSwitching = false;\n let tabSwitchTimeout = null;\n \n const handleVisibilityChange = () => {\n if (document.visibilityState === 'hidden') {\n isTabSwitching = true;\n \n if (tabSwitchTimeout) {\n clearTimeout(tabSwitchTimeout);\n }\n \n tabSwitchTimeout = setTimeout(() => {\n isTabSwitching = false;\n }, 5000); \n \n } else if (document.visibilityState === 'visible') {\n isTabSwitching = false;\n \n if (tabSwitchTimeout) {\n clearTimeout(tabSwitchTimeout);\n tabSwitchTimeout = null;\n }\n }\n };\n \n document.addEventListener('visibilitychange', handleVisibilityChange);\n \n // Setup file transfer callbacks\n if (webrtcManagerRef.current) {\n webrtcManagerRef.current.setFileTransferCallbacks(\n // Progress callback\n (progress) => {\n console.log('File progress:', progress);\n },\n \n // File received callback\n (fileData) => {\n const sizeMb = Math.max(1, Math.round((fileData.fileSize || 0) / (1024 * 1024)));\n const downloadMessage = React.createElement('div', {\n className: 'flex items-center space-x-2'\n }, [\n React.createElement('span', { key: 'label' }, ` File received: ${fileData.fileName} (${sizeMb} MB)`),\n React.createElement('button', {\n key: 'btn',\n className: 'px-3 py-1 rounded bg-blue-600 hover:bg-blue-700 text-white text-xs',\n onClick: async () => {\n try {\n const url = await fileData.getObjectURL();\n const a = document.createElement('a');\n a.href = url;\n a.download = fileData.fileName;\n a.click();\n setTimeout(() => fileData.revokeObjectURL(url), 15000);\n } catch (e) {\n console.error('Download failed:', e);\n addMessageWithAutoScroll(` File upload error: ${String(e?.message || e)}`, 'system');\n }\n }\n }, 'Download')\n ]);\n \n addMessageWithAutoScroll(downloadMessage, 'system');\n },\n \n // Error callback\n (error) => {\n console.error('File transfer error:', error);\n \n if (error.includes('Connection not ready')) {\n addMessageWithAutoScroll(` File transfer error: connection not ready. Try again later.`, 'system');\n } else if (error.includes('File too large')) {\n addMessageWithAutoScroll(` File is too big. Maximum size: 100 MB`, 'system');\n } else {\n addMessageWithAutoScroll(` File transfer error: ${error}`, 'system');\n }\n }\n );\n }\n \n return () => {\n window.removeEventListener('beforeunload', handleBeforeUnload);\n document.removeEventListener('visibilitychange', handleVisibilityChange);\n \n if (tabSwitchTimeout) {\n clearTimeout(tabSwitchTimeout);\n tabSwitchTimeout = null;\n }\n \n if (webrtcManagerRef.current) {\n webrtcManagerRef.current.disconnect();\n webrtcManagerRef.current = null;\n }\n };\n }, []); // Empty dependency array to run only once\n \n // All security features are enabled by default - no session purchase needed\n \n const compressOfferData = (offerData) => {\n try {\n // Parse the offer data if it's a string\n const offer = typeof offerData === 'string' ? JSON.parse(offerData) : offerData;\n \n // Create a minimal version with only the most essential data\n const minimalOffer = {\n type: offer.type,\n version: offer.version,\n timestamp: offer.timestamp,\n sessionId: offer.sessionId,\n connectionId: offer.connectionId,\n verificationCode: offer.verificationCode,\n salt: offer.salt,\n // Use only key fingerprints instead of full keys\n keyFingerprints: offer.keyFingerprints,\n // Add a reference to get full data\n fullDataAvailable: true,\n compressionLevel: 'minimal'\n };\n \n return JSON.stringify(minimalOffer);\n } catch (error) {\n console.error('Error compressing offer data:', error);\n return offerData; // Return original if compression fails\n }\n };\n\n const createQRReference = (offerData) => {\n try {\n // Create a unique reference ID for this offer\n const referenceId = `offer_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;\n \n // Store the full offer data in localStorage with the reference ID\n localStorage.setItem(`qr_offer_${referenceId}`, JSON.stringify(offerData));\n \n // Create a minimal QR code with just the reference\n const qrReference = {\n type: 'secure_offer_reference',\n referenceId: referenceId,\n timestamp: Date.now(),\n message: 'Scan this QR code and use the reference ID to get full offer data'\n };\n \n return JSON.stringify(qrReference);\n } catch (error) {\n console.error('Error creating QR reference:', error);\n return null;\n }\n };\n\n const createTemplateOffer = (offer) => {\n // Minimal template to keep QR within single image capacity\n const templateOffer = {\n type: 'enhanced_secure_offer_template',\n version: '4.0',\n sessionId: offer.sessionId,\n connectionId: offer.connectionId,\n verificationCode: offer.verificationCode,\n timestamp: offer.timestamp,\n // Avoid bulky fields (SDP, raw keys); keep only fingerprints and essentials\n keyFingerprints: offer.keyFingerprints,\n // Keep concise auth hints (omit large nonces)\n authChallenge: offer?.authChallenge?.challenge,\n // Optionally include a compact capability hint if small\n capabilities: Array.isArray(offer.capabilities) && offer.capabilities.length <= 5\n ? offer.capabilities\n : undefined\n };\n \n return templateOffer;\n };\n\n // Conservative QR payload limits (characters). Adjust per error correction level.\n const MAX_QR_LEN = 800; // for JSON/plain/gzip\n const BIN_MAX_QR_LEN = 400; // stricter for SB1:bin to improve scan reliability\n const [qrFramesTotal, setQrFramesTotal] = React.useState(0);\n const [qrFrameIndex, setQrFrameIndex] = React.useState(0);\n const [qrManualMode, setQrManualMode] = React.useState(false);\n\n // Animated QR state (for multi-chunk COSE)\n const qrAnimationRef = React.useRef({ timer: null, chunks: [], idx: 0, active: false });\n const stopQrAnimation = () => {\n try { if (qrAnimationRef.current.timer) { clearInterval(qrAnimationRef.current.timer); } } catch {}\n qrAnimationRef.current = { timer: null, chunks: [], idx: 0, active: false };\n setQrFrameIndex(0);\n setQrFramesTotal(0);\n setQrManualMode(false);\n };\n\n // Render frame at current index (no index mutation)\n const renderCurrent = async () => {\n const { chunks, idx } = qrAnimationRef.current || {};\n if (!chunks || !chunks.length) return;\n const current = chunks[idx % chunks.length];\n try {\n const isDesktop = (typeof window !== 'undefined') && ((window.innerWidth || 0) >= 1024);\n const QR_SIZE = isDesktop ? 720 : 512;\n const url = await (window.generateQRCode ? window.generateQRCode(current, { errorCorrectionLevel: 'M', margin: 2, size: QR_SIZE }) : Promise.resolve(''));\n if (url) setQrCodeUrl(url);\n } catch (e) {\n console.warn('Animated QR render error (current):', e);\n }\n setQrFrameIndex(((qrAnimationRef.current?.idx || 0) % (qrAnimationRef.current?.chunks?.length || 1)) + 1);\n };\n\n // Render current frame, then advance index by 1\n const renderAndAdvance = async () => {\n await renderCurrent();\n const len = qrAnimationRef.current?.chunks?.length || 0;\n if (len > 0) {\n const nextIdx = ((qrAnimationRef.current?.idx || 0) + 1) % len;\n qrAnimationRef.current.idx = nextIdx;\n setQrFrameIndex(nextIdx + 1);\n }\n };\n\n const toggleQrManualMode = () => {\n const newManualMode = !qrManualMode;\n setQrManualMode(newManualMode);\n \n if (newManualMode) {\n\n if (qrAnimationRef.current.timer) {\n clearInterval(qrAnimationRef.current.timer);\n qrAnimationRef.current.timer = null;\n }\n console.log('QR Manual mode enabled - auto-scroll stopped');\n } else {\n if (qrAnimationRef.current.chunks.length > 1) {\n const intervalMs = 3000;\n qrAnimationRef.current.active = true;\n clearInterval(qrAnimationRef.current.timer);\n qrAnimationRef.current.timer = setInterval(renderAndAdvance, intervalMs);\n }\n console.log('QR Manual mode disabled - auto-scroll resumed');\n }\n };\n\n const nextQrFrame = async () => {\n console.log('\uD83C\uDFAE nextQrFrame called, qrFramesTotal:', qrFramesTotal, 'qrAnimationRef.current:', qrAnimationRef.current);\n if (qrAnimationRef.current.chunks.length > 1) {\n const nextIdx = (qrAnimationRef.current.idx + 1) % qrAnimationRef.current.chunks.length;\n qrAnimationRef.current.idx = nextIdx;\n setQrFrameIndex(nextIdx + 1);\n console.log('\uD83C\uDFAE Next frame index:', nextIdx + 1);\n // Ensure auto-advance timer runs in manual mode too\n try { clearInterval(qrAnimationRef.current.timer); } catch {}\n qrAnimationRef.current.timer = null;\n await renderCurrent();\n // If not in manual mode, restart auto timer\n if (!qrManualMode && qrAnimationRef.current.chunks.length > 1) {\n const intervalMs = 3000;\n qrAnimationRef.current.active = true;\n qrAnimationRef.current.timer = setInterval(renderAndAdvance, intervalMs);\n } else {\n qrAnimationRef.current.active = false;\n }\n } else {\n console.log('\uD83C\uDFAE No multiple frames to navigate');\n }\n };\n\n const prevQrFrame = async () => {\n console.log('\uD83C\uDFAE prevQrFrame called, qrFramesTotal:', qrFramesTotal, 'qrAnimationRef.current:', qrAnimationRef.current);\n if (qrAnimationRef.current.chunks.length > 1) {\n const prevIdx = (qrAnimationRef.current.idx - 1 + qrAnimationRef.current.chunks.length) % qrAnimationRef.current.chunks.length;\n qrAnimationRef.current.idx = prevIdx;\n setQrFrameIndex(prevIdx + 1);\n console.log('\uD83C\uDFAE Previous frame index:', prevIdx + 1);\n try { clearInterval(qrAnimationRef.current.timer); } catch {}\n qrAnimationRef.current.timer = null;\n await renderCurrent();\n if (!qrManualMode && qrAnimationRef.current.chunks.length > 1) {\n const intervalMs = 3000;\n qrAnimationRef.current.active = true;\n qrAnimationRef.current.timer = setInterval(renderAndAdvance, intervalMs);\n } else {\n qrAnimationRef.current.active = false;\n }\n } else {\n console.log('\uD83C\uDFAE No multiple frames to navigate');\n }\n };\n\n // Buffer for assembling scanned COSE chunks\n const qrChunksBufferRef = React.useRef({ id: null, total: 0, seen: new Set(), items: [] });\n\n const generateQRCode = async (data) => {\n try {\n const originalSize = typeof data === 'string' ? data.length : JSON.stringify(data).length;\n const isDesktop = (typeof window !== 'undefined') && ((window.innerWidth || 0) >= 1024);\n const QR_SIZE = isDesktop ? 720 : 512;\n \n // Try binary format first (CBOR + deflate + base64url)\n if (typeof window.generateBinaryQRCodeFromObject === 'function') {\n try {\n const obj = typeof data === 'string' ? JSON.parse(data) : data;\n const qrDataUrl = await window.generateBinaryQRCodeFromObject(obj, { errorCorrectionLevel: 'M', size: QR_SIZE, margin: 2 });\n if (qrDataUrl) {\n try { if (qrAnimationRef.current && qrAnimationRef.current.timer) { clearInterval(qrAnimationRef.current.timer); } } catch {}\n qrAnimationRef.current = { timer: null, chunks: [], idx: 0, active: false };\n setQrFrameIndex(0);\n setQrFramesTotal(0);\n setQrManualMode(false);\n setQrCodeUrl(qrDataUrl);\n setQrFramesTotal(1);\n setQrFrameIndex(1);\n return;\n }\n } catch (e) {\n console.warn('Binary QR generation failed, falling back to compressed:', e?.message || e);\n }\n }\n \n // Fallback to compressed JSON\n if (typeof window.generateCompressedQRCode === 'function') {\n try {\n const payload = typeof data === 'string' ? data : JSON.stringify(data);\n const qrDataUrl = await window.generateCompressedQRCode(payload, { errorCorrectionLevel: 'M', size: QR_SIZE, margin: 2 });\n if (qrDataUrl) {\n try { if (qrAnimationRef.current && qrAnimationRef.current.timer) { clearInterval(qrAnimationRef.current.timer); } } catch {}\n qrAnimationRef.current = { timer: null, chunks: [], idx: 0, active: false };\n setQrFrameIndex(0);\n setQrFramesTotal(0);\n setQrManualMode(false);\n setQrCodeUrl(qrDataUrl);\n setQrFramesTotal(1);\n setQrFrameIndex(1);\n return;\n }\n } catch (e) {\n console.warn('Compressed QR generation failed, falling back to plain:', e?.message || e);\n }\n }\n \n // Final fallback to plain JSON\n const payload = typeof data === 'string' ? data : JSON.stringify(data);\n if (payload.length <= MAX_QR_LEN) {\n if (!window.generateQRCode) throw new Error('QR code generator unavailable');\n try { if (qrAnimationRef.current && qrAnimationRef.current.timer) { clearInterval(qrAnimationRef.current.timer); } } catch {}\n qrAnimationRef.current = { timer: null, chunks: [], idx: 0, active: false };\n setQrFrameIndex(0);\n setQrFramesTotal(0);\n setQrManualMode(false);\n const qrDataUrl = await window.generateQRCode(payload, { errorCorrectionLevel: 'M', size: QR_SIZE, margin: 2 });\n setQrCodeUrl(qrDataUrl);\n setQrFramesTotal(1);\n setQrFrameIndex(1);\n return;\n }\n\n // Large payload: \u0440\u0430\u0437\u0431\u0438\u0432\u0430\u0435\u043C \u043D\u0430 \u0444\u0440\u0435\u0439\u043C\u044B (plain JSON)\n try { if (qrAnimationRef.current && qrAnimationRef.current.timer) { clearInterval(qrAnimationRef.current.timer); } } catch {}\n qrAnimationRef.current = { timer: null, chunks: [], idx: 0, active: false };\n setQrFrameIndex(0);\n setQrFramesTotal(0);\n setQrManualMode(false);\n const id = `raw_${Date.now()}_${Math.random().toString(36).slice(2)}`;\n\n const TARGET_CHUNKS = 10;\n const FRAME_MAX = Math.max(200, Math.floor(payload.length / TARGET_CHUNKS));\n const total = Math.ceil(payload.length / FRAME_MAX);\n const rawChunks = [];\n for (let i = 0; i < total; i++) {\n const seq = i + 1;\n const part = payload.slice(i * FRAME_MAX, (i + 1) * FRAME_MAX);\n rawChunks.push(JSON.stringify({ hdr: { v: 1, id, seq, total, rt: 'raw' }, body: part }));\n }\n if (!window.generateQRCode) throw new Error('QR code generator unavailable');\n if (rawChunks.length === 1) {\n const url = await window.generateQRCode(rawChunks[0], { errorCorrectionLevel: 'M', margin: 2, size: QR_SIZE });\n setQrCodeUrl(url);\n setQrFramesTotal(1);\n setQrFrameIndex(1);\n return;\n }\n qrAnimationRef.current.chunks = rawChunks;\n qrAnimationRef.current.idx = 0;\n qrAnimationRef.current.active = true;\n setQrFramesTotal(rawChunks.length);\n setQrFrameIndex(1);\n const EC_OPTS = { errorCorrectionLevel: 'M', margin: 2, size: QR_SIZE };\n await renderNext();\n\n if (!qrManualMode) {\n const intervalMs = 4000; // 4 seconds per frame for better readability\n qrAnimationRef.current.active = true;\n qrAnimationRef.current.timer = setInterval(renderAndAdvance, intervalMs);\n }\n return;\n } catch (error) {\n console.error('QR code generation failed:', error);\n setMessages(prev => [...prev, {\n message: ` QR code generation failed: ${error.message}`,\n type: 'error'\n }]);\n }\n };\n\n const reconstructFromTemplate = (templateData) => {\n // Reconstruct full offer from template\n const fullOffer = {\n type: \"enhanced_secure_offer\",\n version: templateData.version,\n timestamp: templateData.timestamp,\n sessionId: templateData.sessionId,\n connectionId: templateData.connectionId,\n verificationCode: templateData.verificationCode,\n salt: templateData.salt,\n sdp: templateData.sdp,\n keyFingerprints: templateData.keyFingerprints,\n capabilities: templateData.capabilities,\n \n // Reconstruct ECDH key object\n ecdhPublicKey: {\n keyType: \"ECDH\",\n keyData: templateData.ecdhKeyData,\n timestamp: templateData.timestamp - 1000, // Approximate\n version: templateData.version,\n signature: templateData.ecdhSignature\n },\n \n // Reconstruct ECDSA key object\n ecdsaPublicKey: {\n keyType: \"ECDSA\",\n keyData: templateData.ecdsaKeyData,\n timestamp: templateData.timestamp - 999, // Approximate\n version: templateData.version,\n signature: templateData.ecdsaSignature\n },\n \n // Reconstruct auth challenge\n authChallenge: {\n challenge: templateData.authChallenge,\n timestamp: templateData.timestamp,\n nonce: templateData.authNonce,\n version: templateData.version\n },\n \n // Generate security level (can be recalculated)\n securityLevel: {\n level: \"CRITICAL\",\n score: 20,\n color: \"red\",\n verificationResults: {\n encryption: { passed: false, details: \"Encryption not working\", points: 0 },\n keyExchange: { passed: true, details: \"Simple key exchange verified\", points: 15 },\n messageIntegrity: { passed: false, details: \"Message integrity failed\", points: 0 },\n rateLimiting: { passed: true, details: \"Rate limiting active\", points: 5 },\n ecdsa: { passed: false, details: \"Enhanced session required - feature not available\", points: 0 },\n metadataProtection: { passed: false, details: \"Enhanced session required - feature not available\", points: 0 },\n pfs: { passed: false, details: \"Enhanced session required - feature not available\", points: 0 },\n nestedEncryption: { passed: false, details: \"Enhanced session required - feature not available\", points: 0 },\n packetPadding: { passed: false, details: \"Enhanced session required - feature not available\", points: 0 },\n advancedFeatures: { passed: false, details: \"Premium session required - feature not available\", points: 0 }\n },\n timestamp: templateData.timestamp,\n details: \"Real verification: 20/100 security checks passed (2/4 available)\",\n isRealData: true,\n passedChecks: 2,\n totalChecks: 4,\n sessionType: \"demo\",\n maxPossibleScore: 50\n }\n };\n \n return fullOffer;\n };\n\n const handleQRScan = async (scannedData) => {\n try {\n console.log('QR Code scanned:', scannedData.substring(0, 100) + '...');\n console.log('Current buffer state:', qrChunksBufferRef.current);\n \n // Check if this is a binary chunk (starts with SB1:bin: or is a raw binary chunk)\n if (scannedData.startsWith('SB1:bin:') || (qrChunksBufferRef.current && qrChunksBufferRef.current.id)) {\n console.log('Binary chunk detected:', scannedData.substring(0, 50) + '...');\n \n // This is a binary chunk - add to buffer\n if (!qrChunksBufferRef.current.id) {\n console.log('Initializing buffer for binary chunks');\n // Initialize buffer for binary chunks\n qrChunksBufferRef.current = { \n id: `bin_${Date.now()}`, \n total: 4, // We expect 4 chunks\n seen: new Set(), \n items: [],\n lastUpdateMs: Date.now()\n };\n }\n \n // Add chunk to buffer (use data hash as identifier)\n const chunkHash = scannedData.substring(0, 50); // Use first 50 chars as hash\n \n // Check if this chunk was already scanned\n if (qrChunksBufferRef.current.seen.has(chunkHash)) {\n console.log(`Chunk already scanned, ignoring...`);\n return Promise.resolve(false);\n }\n \n qrChunksBufferRef.current.seen.add(chunkHash);\n qrChunksBufferRef.current.items.push(scannedData);\n qrChunksBufferRef.current.lastUpdateMs = Date.now();\n \n // Emit progress and force re-render\n try {\n const uniqueCount = qrChunksBufferRef.current.seen.size;\n document.dispatchEvent(new CustomEvent('qr-scan-progress', { \n detail: { \n id: qrChunksBufferRef.current.id, \n seq: uniqueCount, \n total: qrChunksBufferRef.current.total \n } \n }));\n \n // Force re-render to update progress indicator\n setQrFramesTotal(qrChunksBufferRef.current.total);\n setQrFrameIndex(uniqueCount);\n } catch {}\n \n // Check if we have all chunks\n const isComplete = qrChunksBufferRef.current.seen.size >= qrChunksBufferRef.current.total;\n console.log(`Chunks collected: ${qrChunksBufferRef.current.seen.size}/${qrChunksBufferRef.current.total}, complete: ${isComplete}`);\n \n if (!isComplete) {\n // Keep scanner open for more chunks\n console.log(`Scanned chunk ${qrChunksBufferRef.current.seen.size}/${qrChunksBufferRef.current.total}, waiting for more...`);\n return Promise.resolve(false);\n }\n \n // All chunks collected - reconstruct binary data\n try {\n const fullBinaryData = qrChunksBufferRef.current.items.join('');\n // Store the original binary data, not decoded JSON\n if (showOfferStep) {\n setAnswerInput(fullBinaryData);\n } else {\n setOfferInput(fullBinaryData);\n }\n \n setMessages(prev => [...prev, { \n message: 'All binary chunks captured. Payload reconstructed.', \n type: 'success' \n }]);\n \n // Clear buffer and close scanner\n qrChunksBufferRef.current = { id: null, total: 0, seen: new Set(), items: [] };\n setShowQRScannerModal(false);\n return Promise.resolve(true);\n } catch (e) {\n console.warn('Binary chunks reconstruction failed:', e);\n return Promise.resolve(false);\n }\n }\n \n // Check if this might be a binary chunk (long string without JSON structure)\n if (scannedData.length > 100 && !scannedData.startsWith('{') && !scannedData.startsWith('[')) {\n console.log('Detected potential binary chunk (long non-JSON string):', scannedData.substring(0, 50) + '...');\n \n // Initialize buffer if not exists\n if (!qrChunksBufferRef.current.id) {\n console.log('Initializing buffer for potential binary chunks');\n qrChunksBufferRef.current = { \n id: `bin_${Date.now()}`, \n total: 4, // We expect 4 chunks\n seen: new Set(), \n items: [],\n lastUpdateMs: Date.now()\n };\n }\n \n // Add chunk to buffer (use data hash as identifier)\n const chunkHash = scannedData.substring(0, 50); // Use first 50 chars as hash\n \n // Check if this chunk was already scanned\n if (qrChunksBufferRef.current.seen.has(chunkHash)) {\n console.log(`Chunk already scanned, ignoring...`);\n return Promise.resolve(false);\n }\n \n qrChunksBufferRef.current.seen.add(chunkHash);\n qrChunksBufferRef.current.items.push(scannedData);\n qrChunksBufferRef.current.lastUpdateMs = Date.now();\n \n // Force re-render to update progress indicator\n try {\n const uniqueCount = qrChunksBufferRef.current.seen.size;\n document.dispatchEvent(new CustomEvent('qr-scan-progress', { \n detail: { \n id: qrChunksBufferRef.current.id, \n seq: uniqueCount, \n total: qrChunksBufferRef.current.total \n } \n }));\n \n // Force re-render to update progress indicator\n setQrFramesTotal(qrChunksBufferRef.current.total);\n setQrFrameIndex(uniqueCount);\n } catch {}\n \n // Check if we have all chunks\n const isComplete = qrChunksBufferRef.current.seen.size >= qrChunksBufferRef.current.total;\n console.log(`Chunks collected: ${qrChunksBufferRef.current.seen.size}/${qrChunksBufferRef.current.total}, complete: ${isComplete}`);\n \n if (!isComplete) {\n // Keep scanner open for more chunks\n console.log(`Scanned chunk ${qrChunksBufferRef.current.seen.size}/${qrChunksBufferRef.current.total}, waiting for more...`);\n return Promise.resolve(false);\n }\n \n // All chunks collected - reconstruct binary data\n try {\n const fullBinaryData = qrChunksBufferRef.current.items.join('');\n // Store the original binary data, not decoded JSON\n if (showOfferStep) {\n setAnswerInput(fullBinaryData);\n } else {\n setOfferInput(fullBinaryData);\n }\n \n setMessages(prev => [...prev, { \n message: 'All binary chunks captured. Payload reconstructed.', \n type: 'success' \n }]);\n \n // Clear buffer and close scanner\n qrChunksBufferRef.current = { id: null, total: 0, seen: new Set(), items: [] };\n setShowQRScannerModal(false);\n return Promise.resolve(true);\n } catch (e) {\n console.warn('Binary chunks reconstruction failed:', e);\n return Promise.resolve(false);\n }\n }\n \n // Single QR code - try to decode directly\n // Removed verbose debug log\n let parsedData;\n if (typeof window.decodeAnyPayload === 'function') {\n const any = window.decodeAnyPayload(scannedData);\n if (typeof any === 'string') {\n parsedData = JSON.parse(any);\n } else {\n parsedData = any; // object from binary\n }\n } else {\n const maybeDecompressed = (typeof window.decompressIfNeeded === 'function') ? window.decompressIfNeeded(scannedData) : scannedData;\n parsedData = JSON.parse(maybeDecompressed);\n }\n console.log('Decoded data:', parsedData);\n \n // QR with hdr/body: COSE or RAW/BIN animated frames\n if (parsedData.hdr && parsedData.body) {\n const { hdr } = parsedData;\n // Initialize/rotate buffer by id\n if (!qrChunksBufferRef.current.id || qrChunksBufferRef.current.id !== hdr.id) {\n qrChunksBufferRef.current = { id: hdr.id, total: hdr.total || 1, seen: new Set(), items: [], lastUpdateMs: Date.now() };\n try {\n document.dispatchEvent(new CustomEvent('qr-scan-progress', { detail: { id: hdr.id, seq: 0, total: hdr.total || 1 } }));\n } catch {}\n }\n // Deduplicate & record\n if (!qrChunksBufferRef.current.seen.has(hdr.seq)) {\n qrChunksBufferRef.current.seen.add(hdr.seq);\n qrChunksBufferRef.current.items.push(scannedData);\n qrChunksBufferRef.current.lastUpdateMs = Date.now();\n }\n // Emit progress based on unique frames captured\n try {\n const uniqueCount = qrChunksBufferRef.current.seen.size;\n document.dispatchEvent(new CustomEvent('qr-scan-progress', { detail: { id: hdr.id, seq: uniqueCount, total: qrChunksBufferRef.current.total || hdr.total || 0 } }));\n } catch {}\n const isComplete = qrChunksBufferRef.current.seen.size >= (qrChunksBufferRef.current.total || 1);\n if (!isComplete) {\n // Explicitly keep scanner open\n return Promise.resolve(false);\n }\n // Completed: decide RAW vs BIN vs COSE\n if (hdr.rt === 'raw') {\n try {\n // Sort by seq and concatenate bodies\n const parts = qrChunksBufferRef.current.items\n .map(s => JSON.parse(s))\n .sort((a, b) => (a.hdr.seq || 0) - (b.hdr.seq || 0))\n .map(p => p.body || '');\n const fullText = parts.join('');\n const payloadObj = JSON.parse(fullText);\n if (showOfferStep) {\n setAnswerInput(JSON.stringify(payloadObj, null, 2));\n } else {\n setOfferInput(JSON.stringify(payloadObj, null, 2));\n }\n setMessages(prev => [...prev, { message: 'All frames captured. RAW payload reconstructed.', type: 'success' }]);\n try { document.dispatchEvent(new CustomEvent('qr-scan-complete', { detail: { id: hdr.id } })); } catch {}\n // Close scanner from caller by returning true\n qrChunksBufferRef.current = { id: null, total: 0, seen: new Set(), items: [] };\n setShowQRScannerModal(false);\n return Promise.resolve(true);\n } catch (e) {\n console.warn('RAW multi-frame reconstruction failed:', e);\n return Promise.resolve(false);\n }\n } else if (hdr.rt === 'bin') {\n try {\n const parts = qrChunksBufferRef.current.items\n .map(s => JSON.parse(s))\n .sort((a, b) => (a.hdr.seq || 0) - (b.hdr.seq || 0))\n .map(p => p.body || '');\n const fullText = parts.join(''); // SB1:bin:...\n let payloadObj;\n if (typeof window.decodeAnyPayload === 'function') {\n const any = window.decodeAnyPayload(fullText);\n payloadObj = (typeof any === 'string') ? JSON.parse(any) : any;\n } else {\n payloadObj = JSON.parse(fullText);\n }\n if (showOfferStep) {\n setAnswerInput(JSON.stringify(payloadObj, null, 2));\n } else {\n setOfferInput(JSON.stringify(payloadObj, null, 2));\n }\n setMessages(prev => [...prev, { message: 'All frames captured. BIN payload reconstructed.', type: 'success' }]);\n try { document.dispatchEvent(new CustomEvent('qr-scan-complete', { detail: { id: hdr.id } })); } catch {}\n qrChunksBufferRef.current = { id: null, total: 0, seen: new Set(), items: [] };\n setShowQRScannerModal(false);\n return Promise.resolve(true);\n } catch (e) {\n console.warn('BIN multi-frame reconstruction failed:', e);\n return Promise.resolve(false);\n }\n } else if (window.receiveAndProcess) {\n try {\n const results = await window.receiveAndProcess(qrChunksBufferRef.current.items);\n if (results.length > 0) {\n const { payloadObj } = results[0];\n if (showOfferStep) {\n setAnswerInput(JSON.stringify(payloadObj, null, 2));\n } else {\n setOfferInput(JSON.stringify(payloadObj, null, 2));\n }\n setMessages(prev => [...prev, { message: 'All frames captured. COSE payload reconstructed.', type: 'success' }]);\n try { document.dispatchEvent(new CustomEvent('qr-scan-complete', { detail: { id: hdr.id } })); } catch {}\n qrChunksBufferRef.current = { id: null, total: 0, seen: new Set(), items: [] };\n setShowQRScannerModal(false);\n return Promise.resolve(true);\n }\n } catch (e) {\n console.warn('COSE multi-chunk processing failed:', e);\n }\n return Promise.resolve(false);\n } else {\n return Promise.resolve(false);\n }\n }\n \n // Check if this is a template-based QR code\n if (parsedData.type === 'enhanced_secure_offer_template') {\n console.log('QR scan: Template-based offer detected, reconstructing...');\n const fullOffer = reconstructFromTemplate(parsedData);\n \n // Determine which input to populate based on current mode\n if (showOfferStep) {\n // In \"Waiting for peer's response\" mode - populate answerInput\n setAnswerInput(JSON.stringify(fullOffer, null, 2));\n console.log('\uD83D\uDCF1 Template data populated to answerInput (waiting for response mode)');\n } else {\n // In \"Paste secure invitation\" mode - populate offerInput\n setOfferInput(JSON.stringify(fullOffer, null, 2));\n console.log('\uD83D\uDCF1 Template data populated to offerInput (paste invitation mode)');\n }\n setMessages(prev => [...prev, {\n message: '\uD83D\uDCF1 QR code scanned successfully! Full offer reconstructed from template.',\n type: 'success'\n }]);\n setShowQRScannerModal(false); // Close QR scanner modal\n return true;\n }\n // Check if this is a reference-based QR code\n else if (parsedData.type === 'secure_offer_reference' && parsedData.referenceId) {\n // Try to get the full offer data from localStorage\n const fullOfferData = localStorage.getItem(`qr_offer_${parsedData.referenceId}`);\n if (fullOfferData) {\n const fullOffer = JSON.parse(fullOfferData);\n // Determine which input to populate based on current mode\n if (showOfferStep) {\n // In \"Waiting for peer's response\" mode - populate answerInput\n setAnswerInput(JSON.stringify(fullOffer, null, 2));\n } else {\n // In \"Paste secure invitation\" mode - populate offerInput\n setOfferInput(JSON.stringify(fullOffer, null, 2));\n }\n setMessages(prev => [...prev, {\n message: '\uD83D\uDCF1 QR code scanned successfully! Full offer data retrieved.',\n type: 'success'\n }]);\n setShowQRScannerModal(false); // Close QR scanner modal\n return true;\n } else {\n setMessages(prev => [...prev, {\n message: 'QR code reference found but full data not available. Please use copy/paste.',\n type: 'error'\n }]);\n return false;\n }\n } else {\n // If payload was compressed, it's already decompressed above; keep legacy warning only when clearly incomplete\n if (!parsedData.sdp && parsedData.type === 'enhanced_secure_offer') {\n setMessages(prev => [...prev, {\n message: 'Compressed QR may omit SDP for brevity. Use copy/paste if connection fails.',\n type: 'warning'\n }]);\n }\n \n // Determine which input to populate based on current mode\n if (showOfferStep) {\n // In \"Waiting for peer's response\" mode - populate answerInput\n console.log('QR scan: Populating answerInput with:', parsedData);\n setAnswerInput(JSON.stringify(parsedData, null, 2));\n } else {\n // In \"Paste secure invitation\" mode - populate offerInput\n console.log('QR scan: Populating offerInput with:', parsedData);\n setOfferInput(JSON.stringify(parsedData, null, 2));\n }\n setMessages(prev => [...prev, {\n message: '\uD83D\uDCF1 QR code scanned successfully!',\n type: 'success'\n }]);\n setShowQRScannerModal(false);\n return true;\n }\n } catch (error) {\n // If not JSON, use as plain text\n if (showOfferStep) {\n // In \"Waiting for peer's response\" mode - populate answerInput\n setAnswerInput(scannedData);\n } else {\n // In \"Paste secure invitation\" mode - populate offerInput\n setOfferInput(scannedData);\n }\n setMessages(prev => [...prev, {\n message: '\uD83D\uDCF1 QR code scanned successfully!',\n type: 'success'\n }]);\n setShowQRScannerModal(false);\n return true;\n }\n };\n\n\n\n \n const handleCreateOffer = async () => {\n try {\n // All security features are enabled by default\n setIsGeneratingKeys(true);\n setOfferData('');\n setShowOfferStep(false);\n setShowQRCode(false);\n setQrCodeUrl('');\n \n const offer = await webrtcManagerRef.current.createSecureOffer();\n \n // Store offer data directly (no encryption needed with SAS)\n setOfferData(offer);\n setShowOfferStep(true);\n \n // Generate QR code with binary format and chunking\n const offerString = typeof offer === 'object' ? JSON.stringify(offer) : offer;\n try {\n if (typeof window.encodeBinaryToPrefixed === 'function') {\n const bin = window.encodeBinaryToPrefixed(offerString);\n // Force chunking into 4 parts - split binary data directly\n const TARGET_CHUNKS = 4;\n let total = TARGET_CHUNKS;\n let FRAME_MAX = Math.max(200, Math.ceil(bin.length / TARGET_CHUNKS));\n if (FRAME_MAX <= 0) FRAME_MAX = 200;\n \n // Ensure we don't exceed TARGET_CHUNKS\n if (bin.length <= FRAME_MAX) {\n total = 1;\n FRAME_MAX = bin.length;\n } else {\n // Recalculate to ensure exactly TARGET_CHUNKS parts\n FRAME_MAX = Math.ceil(bin.length / TARGET_CHUNKS);\n total = TARGET_CHUNKS;\n }\n \n const id = `bin_${Date.now()}_${Math.random().toString(36).slice(2)}`;\n const chunks = [];\n for (let i = 0; i < total; i++) {\n const seq = i + 1;\n const part = bin.slice(i * FRAME_MAX, (i + 1) * FRAME_MAX);\n // Store binary chunks directly without JSON wrapper\n chunks.push(part);\n }\n \n // Seed first frame and start auto-advance immediately\n const isDesktop = (typeof window !== 'undefined') && ((window.innerWidth || 0) >= 1024);\n const QR_SIZE = isDesktop ? 720 : 512;\n if (window.generateQRCode && chunks.length > 0) {\n const firstUrl = await window.generateQRCode(chunks[0], { errorCorrectionLevel: 'M', size: QR_SIZE, margin: 2 });\n if (firstUrl) setQrCodeUrl(firstUrl);\n }\n \n // Store precomputed chunks to ref, ready for animation\n try { if (qrAnimationRef.current && qrAnimationRef.current.timer) { clearInterval(qrAnimationRef.current.timer); } } catch {}\n qrAnimationRef.current = { timer: null, chunks, idx: 0, active: true };\n setQrFramesTotal(chunks.length);\n setQrFrameIndex(1);\n setQrManualMode(false);\n \n // Start auto-advance loop for Offer immediately\n const intervalMs = 3000;\n qrAnimationRef.current.timer = setInterval(renderAndAdvance, intervalMs);\n \n // Show QR immediately for Offer flow\n try { setShowQRCode(true); } catch {}\n } else {\n // Fallback to single QR\n await generateQRCode(offer);\n try { setShowQRCode(true); } catch {}\n }\n } catch (e) {\n console.warn('Offer QR generation failed:', e);\n }\n \n const existingMessages = messages.filter(m => \n m.type === 'system' && \n (m.message.includes('Secure invitation created') || m.message.includes('Send the encrypted code'))\n );\n \n if (existingMessages.length === 0) {\n setMessages(prev => [...prev, { \n message: 'Secure invitation created and encrypted!', \n type: 'system',\n id: Date.now(),\n timestamp: Date.now()\n }]);\n \n setMessages(prev => [...prev, { \n message: '\uD83D\uDCE4 Send the invitation code to your interlocutor via a secure channel (voice call, SMS, etc.)..', \n type: 'system',\n id: Date.now(),\n timestamp: Date.now()\n }]);\n \n }\n \n if (!window.isUpdatingSecurity) {\n updateSecurityLevel().catch(console.error);\n }\n } catch (error) {\n setMessages(prev => [...prev, { \n message: `Error creating invitation: ${error.message}`, \n type: 'system',\n id: Date.now(),\n timestamp: Date.now()\n }]);\n } finally {\n setIsGeneratingKeys(false);\n }\n };\n \n const handleCreateAnswer = async () => {\n try {\n \n if (!offerInput.trim()) {\n setMessages(prev => [...prev, { \n message: 'You need to insert the invitation code from your interlocutor.', \n type: 'system',\n id: Date.now(),\n timestamp: Date.now()\n }]);\n return;\n }\n \n try {\n setMessages(prev => [...prev, { \n message: 'Processing the secure invitation...', \n type: 'system',\n id: Date.now(),\n timestamp: Date.now()\n }]);\n \n let offer;\n try {\n // Prefer binary decode first, then gzip JSON\n if (typeof window.decodeAnyPayload === 'function') {\n const any = window.decodeAnyPayload(offerInput.trim());\n offer = (typeof any === 'string') ? JSON.parse(any) : any;\n } else {\n const rawText = (typeof window.decompressIfNeeded === 'function') ? window.decompressIfNeeded(offerInput.trim()) : offerInput.trim();\n offer = JSON.parse(rawText);\n }\n } catch (parseError) {\n throw new Error(`Invalid invitation format: ${parseError.message}`);\n }\n \n if (!offer || typeof offer !== 'object') {\n throw new Error('The invitation must be an object');\n }\n \n // Support both compact and legacy offer formats\n const isValidOfferType = (offer.t === 'offer') || (offer.type === 'enhanced_secure_offer');\n if (!isValidOfferType) {\n throw new Error('Invalid invitation type. Expected offer or enhanced_secure_offer');\n }\n\n const answer = await webrtcManagerRef.current.createSecureAnswer(offer);\n \n // Store answer data directly (no encryption needed with SAS)\n setAnswerData(answer);\n setShowAnswerStep(true);\n \n // Generate QR code with binary format and chunking\n const answerString = typeof answer === 'object' ? JSON.stringify(answer) : answer;\n try {\n if (typeof window.encodeBinaryToPrefixed === 'function') {\n const bin = window.encodeBinaryToPrefixed(answerString);\n // Force chunking into 4 parts - split binary data directly\n const TARGET_CHUNKS = 4;\n let total = TARGET_CHUNKS;\n let FRAME_MAX = Math.max(200, Math.ceil(bin.length / TARGET_CHUNKS));\n if (FRAME_MAX <= 0) FRAME_MAX = 200;\n \n // Ensure we don't exceed TARGET_CHUNKS\n if (bin.length <= FRAME_MAX) {\n total = 1;\n FRAME_MAX = bin.length;\n } else {\n // Recalculate to ensure exactly TARGET_CHUNKS parts\n FRAME_MAX = Math.ceil(bin.length / TARGET_CHUNKS);\n total = TARGET_CHUNKS;\n }\n \n const id = `ans_${Date.now()}_${Math.random().toString(36).slice(2)}`;\n const chunks = [];\n for (let i = 0; i < total; i++) {\n const seq = i + 1;\n const part = bin.slice(i * FRAME_MAX, (i + 1) * FRAME_MAX);\n // Store binary chunks directly without JSON wrapper\n chunks.push(part);\n }\n \n const isDesktop = (typeof window !== 'undefined') && ((window.innerWidth || 0) >= 1024);\n const QR_SIZE = isDesktop ? 720 : 512;\n if (window.generateQRCode && chunks.length > 0) {\n const firstUrl = await window.generateQRCode(chunks[0], { errorCorrectionLevel: 'M', size: QR_SIZE, margin: 2 });\n if (firstUrl) setQrCodeUrl(firstUrl);\n }\n \n try { if (qrAnimationRef.current && qrAnimationRef.current.timer) { clearInterval(qrAnimationRef.current.timer); } } catch {}\n qrAnimationRef.current = { timer: null, chunks, idx: 0, active: true };\n setQrFramesTotal(chunks.length);\n setQrFrameIndex(1);\n setQrManualMode(false);\n \n const intervalMs = 3000;\n qrAnimationRef.current.timer = setInterval(renderAndAdvance, intervalMs);\n \n // Show QR immediately for Answer flow\n try { setShowQRCode(true); } catch {}\n } else {\n // Fallback to single QR\n await generateQRCode(answer);\n try { setShowQRCode(true); } catch {}\n }\n } catch (e) {\n console.warn('Answer QR generation failed:', e);\n }\n \n // Mark answer as created for state management\n if (answerInput.trim().length > 0) {\n if (typeof markAnswerCreated === 'function') {\n markAnswerCreated();\n }\n }\n\n \n const existingResponseMessages = messages.filter(m => \n m.type === 'system' && \n (m.message.includes('Secure response created') || m.message.includes('Send the response'))\n );\n \n if (existingResponseMessages.length === 0) {\n setMessages(prev => [...prev, { \n message: 'Secure response created!', \n type: 'system',\n id: Date.now(),\n timestamp: Date.now()\n }]);\n \n setMessages(prev => [...prev, { \n message: 'Send the response code to the initiator via a secure channel or let them scan the QR code below.', \n type: 'system',\n id: Date.now(),\n timestamp: Date.now()\n }]);\n \n }\n \n // Update security level after creating answer\n if (!window.isUpdatingSecurity) {\n updateSecurityLevel().catch(console.error);\n }\n } catch (error) {\n console.error('Error in handleCreateAnswer:', error);\n setMessages(prev => [...prev, { \n message: `Error processing the invitation: ${error.message}`, \n type: 'system',\n id: Date.now(),\n timestamp: Date.now()\n }]);\n }\n } catch (error) {\n console.error('Error in handleCreateAnswer:', error);\n setMessages(prev => [...prev, { \n message: `Invitation processing error: ${error.message}`, \n type: 'system',\n id: Date.now(),\n timestamp: Date.now()\n }]);\n }\n };\n \n const handleConnect = async () => {\n try {\n if (!answerInput.trim()) {\n setMessages(prev => [...prev, { \n message: 'You need to insert the response code from your interlocutor.', \n type: 'system',\n id: Date.now(),\n timestamp: Date.now()\n }]);\n return;\n }\n \n try {\n setMessages(prev => [...prev, { \n message: 'Processing the secure response...', \n type: 'system',\n id: Date.now(),\n timestamp: Date.now()\n }]);\n \n let answer;\n try {\n // Prefer binary decode first, then gzip JSON\n if (typeof window.decodeAnyPayload === 'function') {\n const anyAnswer = window.decodeAnyPayload(answerInput.trim());\n answer = (typeof anyAnswer === 'string') ? JSON.parse(anyAnswer) : anyAnswer;\n } else {\n const rawText = (typeof window.decompressIfNeeded === 'function') ? window.decompressIfNeeded(answerInput.trim()) : answerInput.trim();\n answer = JSON.parse(rawText);\n }\n } catch (parseError) {\n throw new Error(`Invalid response format: ${parseError.message}`);\n }\n \n if (!answer || typeof answer !== 'object') {\n throw new Error('The response must be an object');\n }\n \n // Support both compact and legacy formats\n const answerType = answer.t || answer.type;\n if (!answerType || (answerType !== 'answer' && answerType !== 'enhanced_secure_answer')) {\n throw new Error('Invalid response type. Expected answer or enhanced_secure_answer');\n }\n \n await webrtcManagerRef.current.handleSecureAnswer(answer);\n \n // All security features are enabled by default - no session activation needed\n if (pendingSession) {\n setPendingSession(null);\n setMessages(prev => [...prev, { \n message: `All security features enabled by default`, \n type: 'system',\n id: Date.now(),\n timestamp: Date.now()\n }]);\n }\n \n setMessages(prev => [...prev, { \n message: 'Finalizing the secure connection...', \n type: 'system',\n id: Date.now(),\n timestamp: Date.now()\n }]);\n \n // Update security level after handling answer\n if (!window.isUpdatingSecurity) {\n updateSecurityLevel().catch(console.error);\n }\n } catch (error) {\n console.error('Error in handleConnect inner try:', error);\n \n // \u0411\u043E\u043B\u0435\u0435 \u0434\u0435\u0442\u0430\u043B\u044C\u043D\u0430\u044F \u043E\u0431\u0440\u0430\u0431\u043E\u0442\u043A\u0430 \u043E\u0448\u0438\u0431\u043E\u043A\n let errorMessage = 'Connection setup error';\n if (error.message.includes('CRITICAL SECURITY FAILURE')) {\n if (error.message.includes('ECDH public key structure')) {\n errorMessage = 'Invalid response code - missing or corrupted cryptographic key. Please check the code and try again.';\n } else if (error.message.includes('ECDSA public key structure')) {\n errorMessage = 'Invalid response code - missing signature verification key. Please check the code and try again.';\n } else {\n errorMessage = 'Security validation failed - possible attack detected';\n }\n } else if (error.message.includes('too old') || error.message.includes('replay')) {\n errorMessage = 'Response data is outdated - please use a fresh invitation';\n } else if (error.message.includes('MITM') || error.message.includes('signature')) {\n errorMessage = 'Security breach detected - connection rejected';\n } else if (error.message.includes('Invalid') || error.message.includes('format')) {\n errorMessage = 'Invalid response format - please check the code';\n } else {\n errorMessage = ` ${error.message}`;\n }\n \n setMessages(prev => [...prev, { \n message: errorMessage, \n type: 'system',\n id: Date.now(),\n timestamp: Date.now(),\n showRetryButton: true\n }]);\n\n if (!error.message.includes('too old') && !error.message.includes('replay')) {\n setPendingSession(null);\n setSessionTimeLeft(0);\n }\n\n setConnectionStatus('failed');\n \n } \n } catch (error) {\n console.error('Error in handleConnect outer try:', error);\n\n let errorMessage = 'Connection setup error';\n if (error.message.includes('CRITICAL SECURITY FAILURE')) {\n if (error.message.includes('ECDH public key structure')) {\n errorMessage = 'Invalid response code - missing or corrupted cryptographic key. Please check the code and try again.';\n } else if (error.message.includes('ECDSA public key structure')) {\n errorMessage = 'Invalid response code - missing signature verification key. Please check the code and try again.';\n } else {\n errorMessage = 'Security validation failed - possible attack detected';\n }\n } else if (error.message.includes('too old') || error.message.includes('replay')) {\n errorMessage = 'Response data is outdated - please use a fresh invitation';\n } else if (error.message.includes('MITM') || error.message.includes('signature')) {\n errorMessage = 'Security breach detected - connection rejected';\n } else if (error.message.includes('Invalid') || error.message.includes('format')) {\n errorMessage = 'Invalid response format - please check the code';\n } else {\n errorMessage = `${error.message}`;\n }\n \n setMessages(prev => [...prev, { \n message: errorMessage, \n type: 'system',\n id: Date.now(),\n timestamp: Date.now(),\n showRetryButton: true\n }]);\n\n if (!error.message.includes('too old') && !error.message.includes('replay')) {\n setPendingSession(null);\n setSessionTimeLeft(0);\n }\n\n setConnectionStatus('failed');\n }\n };\n \n const handleVerifyConnection = async (userCode, isValid = true) => {\n if (isValid) {\n webrtcManagerRef.current.confirmVerification(userCode);\n // Mark local verification as confirmed\n setLocalVerificationConfirmed(true);\n \n // Initialize notification integration if permission was granted\n try {\n if (window.NotificationIntegration && webrtcManagerRef.current && !notificationIntegrationRef.current) {\n const integration = new window.NotificationIntegration(webrtcManagerRef.current);\n await integration.init();\n \n // Store reference for cleanup\n notificationIntegrationRef.current = integration;\n \n \n // Check if permission was already granted\n const status = integration.getStatus();\n if (status.permission === 'granted') {\n setMessages(prev => [...prev, { \n message: '\u2713 Notifications enabled - you will receive alerts when the tab is inactive', \n type: 'system',\n id: Date.now(),\n timestamp: Date.now()\n }]);\n } else {\n setMessages(prev => [...prev, { \n message: '\u2139 Notifications disabled - you can enable them using the button on the main page', \n type: 'system',\n id: Date.now(),\n timestamp: Date.now()\n }]);\n }\n } else if (notificationIntegrationRef.current) {\n } else {\n // Handle error silently\n }\n } catch (error) {\n console.warn('Failed to initialize notifications:', error);\n // Don't show error to user, notifications are optional\n }\n } else {\n setMessages(prev => [...prev, { \n message: ' Verification rejected. The connection is unsafe! Session reset..', \n type: 'system',\n id: Date.now(),\n timestamp: Date.now()\n }]);\n \n // Clear verification states\n setLocalVerificationConfirmed(false);\n setRemoteVerificationConfirmed(false);\n setBothVerificationsConfirmed(false);\n setShowVerification(false);\n setVerificationCode('');\n \n // Reset UI to initial state\n setConnectionStatus('disconnected');\n setOfferData('');\n setAnswerData('');\n setOfferInput('');\n setAnswerInput('');\n setShowOfferStep(false);\n setShowAnswerStep(false);\n setKeyFingerprint('');\n setSecurityLevel(null);\n setIsVerified(false);\n setMessages([]);\n \n setSessionTimeLeft(0);\n setPendingSession(null);\n \n // Dispatch disconnected event for SessionTimer\n document.dispatchEvent(new CustomEvent('disconnected'));\n \n handleDisconnect();\n }\n };\n \n const handleSendMessage = async () => {\n if (!messageInput.trim()) {\n return;\n }\n \n if (!webrtcManagerRef.current) {\n return;\n }\n \n if (!webrtcManagerRef.current.isConnected()) {\n return;\n }\n \n try {\n \n // Add the message to local messages immediately (sent message)\n addMessageWithAutoScroll(messageInput.trim(), 'sent');\n \n // Use sendMessage for simple text messages instead of sendSecureMessage\n await webrtcManagerRef.current.sendMessage(messageInput);\n setMessageInput('');\n } catch (error) {\n const msg = String(error?.message || error);\n if (!/queued for sending|Data channel not ready/i.test(msg)) {\n addMessageWithAutoScroll(`Sending error: ${msg}`,'system');\n }\n }\n };\n \n const handleClearData = () => {\n setOfferData('');\n setAnswerData('');\n setOfferInput('');\n setAnswerInput('');\n setShowOfferStep(false);\n setIsGeneratingKeys(false);\n\n if (!shouldPreserveAnswerData()) {\n setShowAnswerStep(false);\n }\n \n setShowVerification(false);\n setShowQRCode(false);\n setShowQRScanner(false);\n setShowQRScannerModal(false);\n // Clear QR scanner buffer\n qrChunksBufferRef.current = { id: null, total: 0, seen: new Set(), items: [] };\n\n if (!shouldPreserveAnswerData()) {\n setQrCodeUrl('');\n }\n \n setVerificationCode('');\n setIsVerified(false);\n setKeyFingerprint('');\n setSecurityLevel(null);\n setConnectionStatus('disconnected');\n setMessages([]);\n setMessageInput('');\n \n // Clear verification states\n setLocalVerificationConfirmed(false);\n setRemoteVerificationConfirmed(false);\n setBothVerificationsConfirmed(false);\n \n // PAKE passwords removed - using SAS verification instead \n\n if (typeof console.clear === 'function') {\n console.clear();\n }\n \n // Cleanup session state\n setSessionTimeLeft(0);\n \n setPendingSession(null);\n document.dispatchEvent(new CustomEvent('peer-disconnect'));\n // Session manager removed - all features enabled by default\n };\n \n const handleDisconnect = () => {\n try {\n setSessionTimeLeft(0);\n \n // Mark as user-initiated disconnect\n updateConnectionState({ \n status: 'disconnected',\n isUserInitiatedDisconnect: true \n });\n \n // Cleanup WebRTC connection\n if (webrtcManagerRef.current) {\n webrtcManagerRef.current.disconnect();\n }\n \n // Cleanup notification integration\n if (notificationIntegrationRef.current) {\n notificationIntegrationRef.current.cleanup();\n notificationIntegrationRef.current = null;\n }\n \n // Clear all connection-related states\n setKeyFingerprint('');\n setVerificationCode('');\n setSecurityLevel(null);\n setIsVerified(false);\n setShowVerification(false);\n setConnectionStatus('disconnected');\n \n // Clear verification states\n setLocalVerificationConfirmed(false);\n setRemoteVerificationConfirmed(false);\n setBothVerificationsConfirmed(false);\n \n // Reset UI to initial state\n setOfferData('');\n setAnswerData('');\n setOfferInput('');\n setAnswerInput('');\n setShowOfferStep(false);\n setShowAnswerStep(false);\n setIsGeneratingKeys(false);\n setShowQRCode(false);\n setQrCodeUrl('');\n setShowQRScanner(false);\n setShowQRScannerModal(false);\n \n // Clear messages\n setMessages([]);\n \n // Clear console\n if (typeof console.clear === 'function') {\n console.clear();\n }\n \n // Dispatch disconnect events\n document.dispatchEvent(new CustomEvent('peer-disconnect'));\n document.dispatchEvent(new CustomEvent('disconnected'));\n \n // Dispatch session cleanup event\n document.dispatchEvent(new CustomEvent('session-cleanup', {\n detail: { \n timestamp: Date.now(),\n reason: 'manual_disconnect'\n }\n }));\n \n // Clear data and reset session timer\n handleClearData();\n \n setTimeout(() => {\n setSessionTimeLeft(0);\n }, 500);\n \n console.log('Disconnect completed successfully');\n } catch (error) {\n console.error('Error during disconnect:', error);\n }\n };\n \n const handleSessionActivated = (session) => {\n let message;\n if (session.type === 'demo') {\n message = ` Demo session activated for 6 minutes. You can create invitations!`;\n } else {\n message = ` All security features enabled by default. You can create invitations!`;\n }\n \n addMessageWithAutoScroll(message, 'system');\n \n };\n \n React.useEffect(() => {\n if (connectionStatus === 'connected' && isVerified) {\n addMessageWithAutoScroll(' Secure connection successfully established and verified! You can now communicate safely with full protection against MITM attacks and Perfect Forward Secrecy..', 'system');\n \n }\n }, [connectionStatus, isVerified]);\n \n const isConnectedAndVerified = (connectionStatus === 'connected' || connectionStatus === 'verified') && isVerified;\n \n React.useEffect(() => {\n // All security features are enabled by default - no session activation needed\n if (isConnectedAndVerified && pendingSession && connectionStatus !== 'failed') {\n setPendingSession(null);\n setSessionTimeLeft(0); \n addMessageWithAutoScroll(' All security features enabled by default', 'system');\n }\n }, [isConnectedAndVerified, pendingSession, connectionStatus]);\n\n // QR Scanner initialization\n React.useEffect(() => {\n if (showQRScannerModal && window.Html5Qrcode) {\n const html5Qrcode = new window.Html5Qrcode(\"qr-reader\");\n const config = { \n fps: 10\n // \u0423\u0431\u0438\u0440\u0430\u0435\u043C qrbox \u0447\u0442\u043E\u0431\u044B \u0438\u0441\u043F\u043E\u043B\u044C\u0437\u043E\u0432\u0430\u0442\u044C \u0432\u0441\u044E \u043E\u0431\u043B\u0430\u0441\u0442\u044C\n };\n\n let isScanning = true;\n\n html5Qrcode.start(\n { facingMode: \"environment\" }, // Use back camera\n config,\n (decodedText, decodedResult) => {\n if (!isScanning) {\n console.log('Scanner stopped, ignoring scan');\n return;\n }\n \n console.log('QR Code scanned:', decodedText);\n console.log('Current buffer state:', qrChunksBufferRef.current);\n \n handleQRScan(decodedText).then((success) => {\n console.log('QR scan result:', success);\n if (success) {\n // Successfully processed - stop scanner and close modal\n console.log('Closing scanner and modal');\n isScanning = false;\n \n // Stop scanner first, then clear\n try {\n console.log('Stopping scanner...');\n html5Qrcode.stop().then(() => {\n console.log('Scanner stopped, clearing...');\n html5Qrcode.clear();\n setShowQRScannerModal(false);\n }).catch((err) => {\n console.log('Error stopping scanner:', err);\n // Try to clear anyway\n try {\n html5Qrcode.clear();\n } catch (clearErr) {\n console.log('Error clearing scanner:', clearErr);\n }\n setShowQRScannerModal(false);\n });\n } catch (err) {\n console.log('Error in scanner cleanup:', err);\n setShowQRScannerModal(false);\n }\n } else {\n console.log('Continuing to scan for more chunks...');\n }\n }).catch((error) => {\n console.error('QR scan processing error:', error);\n // Continue scanning on error\n });\n },\n (error) => {\n // Ignore scanning errors - continue scanning\n if (isScanning) {\n console.log('QR scan error (ignored):', error);\n }\n }\n ).catch((err) => {\n console.error('QR Scanner start error:', err);\n // Close modal on start error\n setShowQRScannerModal(false);\n });\n\n return () => {\n isScanning = false;\n try {\n // Try to stop scanner, but don't worry if it's already stopped\n html5Qrcode.stop().then(() => {\n html5Qrcode.clear();\n }).catch((err) => {\n // Scanner might already be stopped, just clear it\n console.log('Scanner already stopped or error stopping:', err);\n try {\n html5Qrcode.clear();\n } catch (clearErr) {\n console.log('Error clearing scanner in cleanup:', clearErr);\n }\n });\n } catch (err) {\n console.log('Error in cleanup:', err);\n // Just try to clear, don't worry about stopping\n try {\n html5Qrcode.clear();\n } catch (clearErr) {\n console.log('Error clearing scanner in cleanup:', clearErr);\n }\n }\n };\n }\n }, [showQRScannerModal]);\n \n return React.createElement('div', { \n className: \"minimal-bg min-h-screen\" \n }, [\n window.EnhancedMinimalHeader && React.createElement(window.EnhancedMinimalHeader, {\n key: 'header',\n status: connectionStatus,\n fingerprint: keyFingerprint,\n verificationCode: verificationCode,\n onDisconnect: handleDisconnect,\n isConnected: isConnectedAndVerified,\n securityLevel: securityLevel,\n // sessionManager removed - all features enabled by default\n webrtcManager: webrtcManagerRef.current\n }),\n \n React.createElement('main', {\n key: 'main'\n }, \n (() => {\n return isConnectedAndVerified;\n })()\n ? (() => {\n return React.createElement(EnhancedChatInterface, {\n messages: messages,\n messageInput: messageInput,\n setMessageInput: setMessageInput,\n onSendMessage: handleSendMessage,\n onDisconnect: handleDisconnect,\n keyFingerprint: keyFingerprint,\n isVerified: isVerified,\n chatMessagesRef: chatMessagesRef,\n scrollToBottom: scrollToBottom,\n webrtcManager: webrtcManagerRef.current\n });\n })()\n : React.createElement(EnhancedConnectionSetup, {\n onCreateOffer: handleCreateOffer,\n onCreateAnswer: handleCreateAnswer,\n onConnect: handleConnect,\n onClearData: handleClearData,\n onVerifyConnection: handleVerifyConnection,\n connectionStatus: connectionStatus,\n offerData: offerData,\n answerData: answerData,\n offerInput: offerInput,\n setOfferInput: setOfferInput,\n answerInput: answerInput,\n setAnswerInput: setAnswerInput,\n showOfferStep: showOfferStep,\n showAnswerStep: showAnswerStep,\n verificationCode: verificationCode,\n showVerification: showVerification,\n showQRCode: showQRCode,\n qrCodeUrl: qrCodeUrl,\n showQRScanner: showQRScanner,\n setShowQRCode: setShowQRCode,\n setShowQRScanner: setShowQRScanner,\n setShowQRScannerModal: setShowQRScannerModal,\n messages: messages,\n localVerificationConfirmed: localVerificationConfirmed,\n remoteVerificationConfirmed: remoteVerificationConfirmed,\n bothVerificationsConfirmed: bothVerificationsConfirmed,\n // QR control props\n qrFramesTotal: qrFramesTotal,\n qrFrameIndex: qrFrameIndex,\n qrManualMode: qrManualMode,\n toggleQrManualMode: toggleQrManualMode,\n nextQrFrame: nextQrFrame,\n prevQrFrame: prevQrFrame,\n // PAKE passwords removed - using SAS verification instead\n markAnswerCreated: markAnswerCreated,\n notificationIntegrationRef: notificationIntegrationRef,\n isGeneratingKeys: isGeneratingKeys,\n handleCreateOffer: handleCreateOffer,\n relayOnlyMode: relayOnlyMode,\n setRelayOnlyMode: setRelayOnlyMode\n })\n ),\n \n // QR Scanner Modal\n showQRScannerModal && React.createElement('div', {\n key: 'qr-scanner-modal',\n className: \"fixed inset-0 bg-black/80 flex items-center justify-center z-50\"\n }, [\n React.createElement('div', {\n key: 'scanner-container',\n className: \"bg-gray-900 rounded-lg p-4 max-w-2xl w-full mx-4\"\n }, [\n React.createElement('div', {\n key: 'scanner-header',\n className: \"flex items-center justify-between mb-4\"\n }, [\n React.createElement('h3', {\n key: 'scanner-title',\n className: \"text-lg font-medium text-white\"\n }, 'QR Code Scanner'),\n React.createElement('button', {\n key: 'close-btn',\n onClick: () => {\n setShowQRScannerModal(false);\n // Clear QR scanner buffer\n qrChunksBufferRef.current = { id: null, total: 0, seen: new Set(), items: [] };\n },\n className: \"text-gray-400 hover:text-white\"\n }, [\n React.createElement('i', {\n key: 'close-icon',\n className: 'fas fa-times'\n })\n ])\n ]),\n React.createElement('div', {\n key: 'scanner-content',\n className: \"text-center\"\n }, [\n React.createElement('p', {\n key: 'scanner-description',\n className: \"text-gray-400 mb-4\"\n }, 'Point your camera at the QR code to scan'),\n qrChunksBufferRef.current && qrChunksBufferRef.current.id && React.createElement('div', {\n key: 'progress-indicator',\n className: \"mb-4 p-3 bg-blue-500/10 border border-blue-500/20 rounded-lg\"\n }, [\n React.createElement('p', {\n key: 'progress-text',\n className: \"text-blue-400 text-sm\"\n }, `Scanned: ${qrChunksBufferRef.current.seen.size}/${qrChunksBufferRef.current.total} parts`),\n React.createElement('div', {\n key: 'progress-bar',\n className: \"w-full bg-gray-700 rounded-full h-2 mt-2\"\n }, [\n React.createElement('div', {\n key: 'progress-fill',\n className: \"bg-blue-500 h-2 rounded-full transition-all duration-300\",\n style: { \n width: `${(qrChunksBufferRef.current.seen.size / qrChunksBufferRef.current.total) * 100}%` \n }\n })\n ])\n ]),\n React.createElement('div', {\n key: 'scanner-placeholder',\n id: \"qr-reader\",\n className: \"w-full h-96 bg-gray-800 rounded-lg flex items-center justify-center\",\n style: { minHeight: '400px' }\n }, [\n React.createElement('p', {\n key: 'scanner-placeholder-text',\n className: \"text-gray-500\"\n }, 'Camera will start here...')\n ])\n ])\n ])\n ]),\n \n \n ]);\n };\n // UpdateChecker \u043A\u043E\u043C\u043F\u043E\u043D\u0435\u043D\u0442 \u0434\u043B\u044F \u0430\u0432\u0442\u043E\u043C\u0430\u0442\u0438\u0447\u0435\u0441\u043A\u043E\u0439 \u043F\u0440\u043E\u0432\u0435\u0440\u043A\u0438 \u043E\u0431\u043D\u043E\u0432\u043B\u0435\u043D\u0438\u0439\n const UpdateCheckerWrapper = ({ children }) => {\n // \u041F\u0440\u043E\u0432\u0435\u0440\u044F\u0435\u043C \u0434\u043E\u0441\u0442\u0443\u043F\u043D\u043E\u0441\u0442\u044C UpdateChecker\n if (typeof window !== 'undefined' && window.UpdateChecker) {\n return React.createElement(window.UpdateChecker, {\n debug: false\n }, children);\n }\n // Fallback \u0435\u0441\u043B\u0438 UpdateChecker \u043D\u0435 \u0437\u0430\u0433\u0440\u0443\u0436\u0435\u043D\n return children;\n };\n\n function initializeApp() {\n if (window.EnhancedSecureCryptoUtils && window.EnhancedSecureWebRTCManager) {\n // \u041E\u0431\u043E\u0440\u0430\u0447\u0438\u0432\u0430\u0435\u043C \u043F\u0440\u0438\u043B\u043E\u0436\u0435\u043D\u0438\u0435 \u0432 UpdateChecker \u0434\u043B\u044F \u0430\u0432\u0442\u043E\u043C\u0430\u0442\u0438\u0447\u0435\u0441\u043A\u043E\u0439 \u043F\u0440\u043E\u0432\u0435\u0440\u043A\u0438 \u043E\u0431\u043D\u043E\u0432\u043B\u0435\u043D\u0438\u0439\n const AppWithUpdateChecker = React.createElement(UpdateCheckerWrapper, null,\n React.createElement(EnhancedSecureP2PChat)\n );\n ReactDOM.render(AppWithUpdateChecker, document.getElementById('root'));\n } else {\n console.error('\u041C\u043E\u0434\u0443\u043B\u0438 \u043D\u0435 \u0437\u0430\u0433\u0440\u0443\u0436\u0435\u043D\u044B:', {\n hasCrypto: !!window.EnhancedSecureCryptoUtils,\n hasWebRTC: !!window.EnhancedSecureWebRTCManager\n });\n }\n }\n\n if (typeof window !== 'undefined') {\n\n window.addEventListener('unhandledrejection', (event) => {\n console.error('Unhandled promise rejection:', event.reason);\n event.preventDefault(); \n });\n \n\n window.addEventListener('error', (event) => {\n console.error('Global error:', event.error);\n event.preventDefault(); \n });\n \n if (!window.initializeApp) {\n window.initializeApp = initializeApp;\n }\n };\n \n // Render Enhanced Application with UpdateChecker\n if (window.EnhancedSecureCryptoUtils && window.EnhancedSecureWebRTCManager) {\n const UpdateCheckerWrapper = ({ children }) => {\n if (typeof window !== 'undefined' && window.UpdateChecker) {\n return React.createElement(window.UpdateChecker, {\n debug: false\n }, children);\n }\n return children;\n };\n const AppWithUpdateChecker = React.createElement(UpdateCheckerWrapper, null,\n React.createElement(EnhancedSecureP2PChat)\n );\n ReactDOM.render(AppWithUpdateChecker, document.getElementById('root'));\n } else {\n ReactDOM.render(React.createElement(EnhancedSecureP2PChat), document.getElementById('root'));\n }\n"], + "mappings": "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", "names": ["setIsGeneratingKeys", "webrtcManagerRef", "offerData", "payload", "UpdateCheckerWrapper"] } diff --git a/dist/qr-local.js.map b/dist/qr-local.js.map index e83f591..ae33d97 100644 --- a/dist/qr-local.js.map +++ b/dist/qr-local.js.map @@ -1,7 +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", "../node_modules/html5-qrcode/third_party/zxing-js.umd.js", "../node_modules/cbor-js/cbor.js", "../node_modules/base64-js/index.js", "../src/scripts/qr-local.js", "../node_modules/src/core.ts", "../node_modules/src/strings.ts", "../node_modules/src/utils.ts", "../node_modules/src/zxing-html5-qrcode-decoder.ts", "../node_modules/src/native-bar-code-detector.ts", "../node_modules/src/code-decoder.ts", "../node_modules/src/camera/core-impl.ts", "../node_modules/src/camera/factories.ts", "../node_modules/src/camera/retriever.ts", "../node_modules/src/state-manager.ts", "../node_modules/src/html5-qrcode.ts", "../node_modules/src/image-assets.ts", "../node_modules/src/storage.ts", "../node_modules/src/ui.ts", "../node_modules/src/camera/permissions.ts", "../node_modules/src/ui/scanner/scan-type-selector.ts", "../node_modules/src/ui/scanner/base.ts", "../node_modules/src/ui/scanner/torch-button.ts", "../node_modules/src/ui/scanner/file-selection-ui.ts", "../node_modules/src/ui/scanner/camera-selection-ui.ts", "../node_modules/src/ui/scanner/camera-zoom-ui.ts", "../node_modules/src/html5-qrcode-scanner.ts", "../node_modules/pako/dist/pako.esm.mjs", "../src/crypto/cose-qr.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", "(function (global, factory) {\n typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :\n typeof define === 'function' && define.amd ? define(['exports'], factory) :\n (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.ZXing = {}));\n}(this, (function (exports) { 'use strict';\n\n function isNullOrUndefined(obj) {\n return obj === null || obj === undefined;\n }\n\n /*\n * Copyright 2008 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n /* global Reflect, Promise */\n\n var extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n\n function __extends(d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n }\n\n function fixProto(target, prototype) {\n var setPrototypeOf = Object.setPrototypeOf;\n setPrototypeOf ? setPrototypeOf(target, prototype) : (target.__proto__ = prototype);\n }\n\n function fixStack(target, fn) {\n if (fn === void 0) {\n fn = target.constructor;\n }\n var captureStackTrace = Error.captureStackTrace;\n captureStackTrace && captureStackTrace(target, fn);\n }\n\n var CustomError = (function (_super) {\n __extends(CustomError, _super);\n function CustomError(message) {\n var _newTarget = this.constructor;\n var _this = _super.call(this, message) || this;\n Object.defineProperty(_this, 'name', {\n value: _newTarget.name,\n enumerable: false\n });\n fixProto(_this, _newTarget.prototype);\n fixStack(_this);\n return _this;\n }\n \n return CustomError;\n })(Error);\n\n /**\n * Custom Error class of type Exception.\n */\n class Exception extends CustomError {\n /**\n * Allows Exception to be constructed directly\n * with some message and prototype definition.\n */\n constructor(message = undefined) {\n super(message);\n this.message = message;\n }\n getKind() {\n const ex = this.constructor;\n return ex.kind;\n }\n }\n /**\n * It's typed as string so it can be extended and overriden.\n */\n Exception.kind = 'Exception';\n\n /**\n * Custom Error class of type Exception.\n */\n class ArgumentException extends Exception {\n }\n ArgumentException.kind = 'ArgumentException';\n\n /**\n * Custom Error class of type Exception.\n */\n class IllegalArgumentException extends Exception {\n }\n IllegalArgumentException.kind = 'IllegalArgumentException';\n\n /*\n * Copyright 2009 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n class BinaryBitmap {\n constructor(binarizer) {\n this.binarizer = binarizer;\n if (binarizer === null) {\n throw new IllegalArgumentException('Binarizer must be non-null.');\n }\n }\n /**\n * @return The width of the bitmap.\n */\n getWidth() {\n return this.binarizer.getWidth();\n }\n /**\n * @return The height of the bitmap.\n */\n getHeight() {\n return this.binarizer.getHeight();\n }\n /**\n * Converts one row of luminance data to 1 bit data. May actually do the conversion, or return\n * cached data. Callers should assume this method is expensive and call it as seldom as possible.\n * This method is intended for decoding 1D barcodes and may choose to apply sharpening.\n *\n * @param y The row to fetch, which must be in [0, bitmap height)\n * @param row An optional preallocated array. If null or too small, it will be ignored.\n * If used, the Binarizer will call BitArray.clear(). Always use the returned object.\n * @return The array of bits for this row (true means black).\n * @throws NotFoundException if row can't be binarized\n */\n getBlackRow(y /*int*/, row) {\n return this.binarizer.getBlackRow(y, row);\n }\n /**\n * Converts a 2D array of luminance data to 1 bit. As above, assume this method is expensive\n * and do not call it repeatedly. This method is intended for decoding 2D barcodes and may or\n * may not apply sharpening. Therefore, a row from this matrix may not be identical to one\n * fetched using getBlackRow(), so don't mix and match between them.\n *\n * @return The 2D array of bits for the image (true means black).\n * @throws NotFoundException if image can't be binarized to make a matrix\n */\n getBlackMatrix() {\n // The matrix is created on demand the first time it is requested, then cached. There are two\n // reasons for this:\n // 1. This work will never be done if the caller only installs 1D Reader objects, or if a\n // 1D Reader finds a barcode before the 2D Readers run.\n // 2. This work will only be done once even if the caller installs multiple 2D Readers.\n if (this.matrix === null || this.matrix === undefined) {\n this.matrix = this.binarizer.getBlackMatrix();\n }\n return this.matrix;\n }\n /**\n * @return Whether this bitmap can be cropped.\n */\n isCropSupported() {\n return this.binarizer.getLuminanceSource().isCropSupported();\n }\n /**\n * Returns a new object with cropped image data. Implementations may keep a reference to the\n * original data rather than a copy. Only callable if isCropSupported() is true.\n *\n * @param left The left coordinate, which must be in [0,getWidth())\n * @param top The top coordinate, which must be in [0,getHeight())\n * @param width The width of the rectangle to crop.\n * @param height The height of the rectangle to crop.\n * @return A cropped version of this object.\n */\n crop(left /*int*/, top /*int*/, width /*int*/, height /*int*/) {\n const newSource = this.binarizer.getLuminanceSource().crop(left, top, width, height);\n return new BinaryBitmap(this.binarizer.createBinarizer(newSource));\n }\n /**\n * @return Whether this bitmap supports counter-clockwise rotation.\n */\n isRotateSupported() {\n return this.binarizer.getLuminanceSource().isRotateSupported();\n }\n /**\n * Returns a new object with rotated image data by 90 degrees counterclockwise.\n * Only callable if {@link #isRotateSupported()} is true.\n *\n * @return A rotated version of this object.\n */\n rotateCounterClockwise() {\n const newSource = this.binarizer.getLuminanceSource().rotateCounterClockwise();\n return new BinaryBitmap(this.binarizer.createBinarizer(newSource));\n }\n /**\n * Returns a new object with rotated image data by 45 degrees counterclockwise.\n * Only callable if {@link #isRotateSupported()} is true.\n *\n * @return A rotated version of this object.\n */\n rotateCounterClockwise45() {\n const newSource = this.binarizer.getLuminanceSource().rotateCounterClockwise45();\n return new BinaryBitmap(this.binarizer.createBinarizer(newSource));\n }\n /*@Override*/\n toString() {\n try {\n return this.getBlackMatrix().toString();\n }\n catch (e /*: NotFoundException*/) {\n return '';\n }\n }\n }\n\n /**\n * Custom Error class of type Exception.\n */\n class ChecksumException extends Exception {\n static getChecksumInstance() {\n return new ChecksumException();\n }\n }\n ChecksumException.kind = 'ChecksumException';\n\n /*\n * Copyright 2009 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n /**\n * This class hierarchy provides a set of methods to convert luminance data to 1 bit data.\n * It allows the algorithm to vary polymorphically, for example allowing a very expensive\n * thresholding technique for servers and a fast one for mobile. It also permits the implementation\n * to vary, e.g. a JNI version for Android and a Java fallback version for other platforms.\n *\n * @author dswitkin@google.com (Daniel Switkin)\n */\n class Binarizer {\n constructor(source) {\n this.source = source;\n }\n getLuminanceSource() {\n return this.source;\n }\n getWidth() {\n return this.source.getWidth();\n }\n getHeight() {\n return this.source.getHeight();\n }\n }\n\n class System {\n // public static void arraycopy(Object src, int srcPos, Object dest, int destPos, int length)\n /**\n * Makes a copy of a array.\n */\n static arraycopy(src, srcPos, dest, destPos, length) {\n // TODO: better use split or set?\n while (length--) {\n dest[destPos++] = src[srcPos++];\n }\n }\n /**\n * Returns the current time in milliseconds.\n */\n static currentTimeMillis() {\n return Date.now();\n }\n }\n\n /**\n * Custom Error class of type Exception.\n */\n class IndexOutOfBoundsException extends Exception {\n }\n IndexOutOfBoundsException.kind = 'IndexOutOfBoundsException';\n\n /**\n * Custom Error class of type Exception.\n */\n class ArrayIndexOutOfBoundsException extends IndexOutOfBoundsException {\n constructor(index = undefined, message = undefined) {\n super(message);\n this.index = index;\n this.message = message;\n }\n }\n ArrayIndexOutOfBoundsException.kind = 'ArrayIndexOutOfBoundsException';\n\n class Arrays {\n /**\n * Assigns the specified int value to each element of the specified array\n * of ints.\n *\n * @param a the array to be filled\n * @param val the value to be stored in all elements of the array\n */\n static fill(a, val) {\n for (let i = 0, len = a.length; i < len; i++)\n a[i] = val;\n }\n /**\n * Assigns the specified int value to each element of the specified\n * range of the specified array of ints. The range to be filled\n * extends from index {@code fromIndex}, inclusive, to index\n * {@code toIndex}, exclusive. (If {@code fromIndex==toIndex}, the\n * range to be filled is empty.)\n *\n * @param a the array to be filled\n * @param fromIndex the index of the first element (inclusive) to be\n * filled with the specified value\n * @param toIndex the index of the last element (exclusive) to be\n * filled with the specified value\n * @param val the value to be stored in all elements of the array\n * @throws IllegalArgumentException if {@code fromIndex > toIndex}\n * @throws ArrayIndexOutOfBoundsException if {@code fromIndex < 0} or\n * {@code toIndex > a.length}\n */\n static fillWithin(a, fromIndex, toIndex, val) {\n Arrays.rangeCheck(a.length, fromIndex, toIndex);\n for (let i = fromIndex; i < toIndex; i++)\n a[i] = val;\n }\n /**\n * Checks that {@code fromIndex} and {@code toIndex} are in\n * the range and throws an exception if they aren't.\n */\n static rangeCheck(arrayLength, fromIndex, toIndex) {\n if (fromIndex > toIndex) {\n throw new IllegalArgumentException('fromIndex(' + fromIndex + ') > toIndex(' + toIndex + ')');\n }\n if (fromIndex < 0) {\n throw new ArrayIndexOutOfBoundsException(fromIndex);\n }\n if (toIndex > arrayLength) {\n throw new ArrayIndexOutOfBoundsException(toIndex);\n }\n }\n static asList(...args) {\n return args;\n }\n static create(rows, cols, value) {\n let arr = Array.from({ length: rows });\n return arr.map(x => Array.from({ length: cols }).fill(value));\n }\n static createInt32Array(rows, cols, value) {\n let arr = Array.from({ length: rows });\n return arr.map(x => Int32Array.from({ length: cols }).fill(value));\n }\n static equals(first, second) {\n if (!first) {\n return false;\n }\n if (!second) {\n return false;\n }\n if (!first.length) {\n return false;\n }\n if (!second.length) {\n return false;\n }\n if (first.length !== second.length) {\n return false;\n }\n for (let i = 0, length = first.length; i < length; i++) {\n if (first[i] !== second[i]) {\n return false;\n }\n }\n return true;\n }\n static hashCode(a) {\n if (a === null) {\n return 0;\n }\n let result = 1;\n for (const element of a) {\n result = 31 * result + element;\n }\n return result;\n }\n static fillUint8Array(a, value) {\n for (let i = 0; i !== a.length; i++) {\n a[i] = value;\n }\n }\n static copyOf(original, newLength) {\n return original.slice(0, newLength);\n }\n static copyOfUint8Array(original, newLength) {\n if (original.length <= newLength) {\n const newArray = new Uint8Array(newLength);\n newArray.set(original);\n return newArray;\n }\n return original.slice(0, newLength);\n }\n static copyOfRange(original, from, to) {\n const newLength = to - from;\n const copy = new Int32Array(newLength);\n System.arraycopy(original, from, copy, 0, newLength);\n return copy;\n }\n /*\n * Returns the index of of the element in a sorted array or (-n-1) where n is the insertion point\n * for the new element.\n * Parameters:\n * ar - A sorted array\n * el - An element to search for\n * comparator - A comparator function. The function takes two arguments: (a, b) and returns:\n * a negative number if a is less than b;\n * 0 if a is equal to b;\n * a positive number of a is greater than b.\n * The array may contain duplicate elements. If there are more than one equal elements in the array,\n * the returned value can be the index of any one of the equal elements.\n *\n * http://jsfiddle.net/aryzhov/pkfst550/\n */\n static binarySearch(ar, el, comparator) {\n if (undefined === comparator) {\n comparator = Arrays.numberComparator;\n }\n let m = 0;\n let n = ar.length - 1;\n while (m <= n) {\n const k = (n + m) >> 1;\n const cmp = comparator(el, ar[k]);\n if (cmp > 0) {\n m = k + 1;\n }\n else if (cmp < 0) {\n n = k - 1;\n }\n else {\n return k;\n }\n }\n return -m - 1;\n }\n static numberComparator(a, b) {\n return a - b;\n }\n }\n\n /**\n * Ponyfill for Java's Integer class.\n */\n class Integer {\n static numberOfTrailingZeros(i) {\n let y;\n if (i === 0)\n return 32;\n let n = 31;\n y = i << 16;\n if (y !== 0) {\n n -= 16;\n i = y;\n }\n y = i << 8;\n if (y !== 0) {\n n -= 8;\n i = y;\n }\n y = i << 4;\n if (y !== 0) {\n n -= 4;\n i = y;\n }\n y = i << 2;\n if (y !== 0) {\n n -= 2;\n i = y;\n }\n return n - ((i << 1) >>> 31);\n }\n static numberOfLeadingZeros(i) {\n // HD, Figure 5-6\n if (i === 0) {\n return 32;\n }\n let n = 1;\n if (i >>> 16 === 0) {\n n += 16;\n i <<= 16;\n }\n if (i >>> 24 === 0) {\n n += 8;\n i <<= 8;\n }\n if (i >>> 28 === 0) {\n n += 4;\n i <<= 4;\n }\n if (i >>> 30 === 0) {\n n += 2;\n i <<= 2;\n }\n n -= i >>> 31;\n return n;\n }\n static toHexString(i) {\n return i.toString(16);\n }\n static toBinaryString(intNumber) {\n return String(parseInt(String(intNumber), 2));\n }\n // Returns the number of one-bits in the two's complement binary representation of the specified int value. This function is sometimes referred to as the population count.\n // Returns:\n // the number of one-bits in the two's complement binary representation of the specified int value.\n static bitCount(i) {\n // HD, Figure 5-2\n i = i - ((i >>> 1) & 0x55555555);\n i = (i & 0x33333333) + ((i >>> 2) & 0x33333333);\n i = (i + (i >>> 4)) & 0x0f0f0f0f;\n i = i + (i >>> 8);\n i = i + (i >>> 16);\n return i & 0x3f;\n }\n static truncDivision(dividend, divisor) {\n return Math.trunc(dividend / divisor);\n }\n /**\n * Converts A string to an integer.\n * @param s A string to convert into a number.\n * @param radix A value between 2 and 36 that specifies the base of the number in numString. If this argument is not supplied, strings with a prefix of '0x' are considered hexadecimal. All other strings are considered decimal.\n */\n static parseInt(num, radix = undefined) {\n return parseInt(num, radix);\n }\n }\n Integer.MIN_VALUE_32_BITS = -2147483648;\n Integer.MAX_VALUE = Number.MAX_SAFE_INTEGER;\n\n /**\n *

A simple, fast array of bits, represented compactly by an array of ints internally.

\n *\n * @author Sean Owen\n */\n class BitArray /*implements Cloneable*/ {\n // For testing only\n constructor(size /*int*/, bits) {\n if (undefined === size) {\n this.size = 0;\n this.bits = new Int32Array(1);\n }\n else {\n this.size = size;\n if (undefined === bits || null === bits) {\n this.bits = BitArray.makeArray(size);\n }\n else {\n this.bits = bits;\n }\n }\n }\n getSize() {\n return this.size;\n }\n getSizeInBytes() {\n return Math.floor((this.size + 7) / 8);\n }\n ensureCapacity(size /*int*/) {\n if (size > this.bits.length * 32) {\n const newBits = BitArray.makeArray(size);\n System.arraycopy(this.bits, 0, newBits, 0, this.bits.length);\n this.bits = newBits;\n }\n }\n /**\n * @param i bit to get\n * @return true iff bit i is set\n */\n get(i /*int*/) {\n return (this.bits[Math.floor(i / 32)] & (1 << (i & 0x1F))) !== 0;\n }\n /**\n * Sets bit i.\n *\n * @param i bit to set\n */\n set(i /*int*/) {\n this.bits[Math.floor(i / 32)] |= 1 << (i & 0x1F);\n }\n /**\n * Flips bit i.\n *\n * @param i bit to set\n */\n flip(i /*int*/) {\n this.bits[Math.floor(i / 32)] ^= 1 << (i & 0x1F);\n }\n /**\n * @param from first bit to check\n * @return index of first bit that is set, starting from the given index, or size if none are set\n * at or beyond this given index\n * @see #getNextUnset(int)\n */\n getNextSet(from /*int*/) {\n const size = this.size;\n if (from >= size) {\n return size;\n }\n const bits = this.bits;\n let bitsOffset = Math.floor(from / 32);\n let currentBits = bits[bitsOffset];\n // mask off lesser bits first\n currentBits &= ~((1 << (from & 0x1F)) - 1);\n const length = bits.length;\n while (currentBits === 0) {\n if (++bitsOffset === length) {\n return size;\n }\n currentBits = bits[bitsOffset];\n }\n const result = (bitsOffset * 32) + Integer.numberOfTrailingZeros(currentBits);\n return result > size ? size : result;\n }\n /**\n * @param from index to start looking for unset bit\n * @return index of next unset bit, or {@code size} if none are unset until the end\n * @see #getNextSet(int)\n */\n getNextUnset(from /*int*/) {\n const size = this.size;\n if (from >= size) {\n return size;\n }\n const bits = this.bits;\n let bitsOffset = Math.floor(from / 32);\n let currentBits = ~bits[bitsOffset];\n // mask off lesser bits first\n currentBits &= ~((1 << (from & 0x1F)) - 1);\n const length = bits.length;\n while (currentBits === 0) {\n if (++bitsOffset === length) {\n return size;\n }\n currentBits = ~bits[bitsOffset];\n }\n const result = (bitsOffset * 32) + Integer.numberOfTrailingZeros(currentBits);\n return result > size ? size : result;\n }\n /**\n * Sets a block of 32 bits, starting at bit i.\n *\n * @param i first bit to set\n * @param newBits the new value of the next 32 bits. Note again that the least-significant bit\n * corresponds to bit i, the next-least-significant to i+1, and so on.\n */\n setBulk(i /*int*/, newBits /*int*/) {\n this.bits[Math.floor(i / 32)] = newBits;\n }\n /**\n * Sets a range of bits.\n *\n * @param start start of range, inclusive.\n * @param end end of range, exclusive\n */\n setRange(start /*int*/, end /*int*/) {\n if (end < start || start < 0 || end > this.size) {\n throw new IllegalArgumentException();\n }\n if (end === start) {\n return;\n }\n end--; // will be easier to treat this as the last actually set bit -- inclusive\n const firstInt = Math.floor(start / 32);\n const lastInt = Math.floor(end / 32);\n const bits = this.bits;\n for (let i = firstInt; i <= lastInt; i++) {\n const firstBit = i > firstInt ? 0 : start & 0x1F;\n const lastBit = i < lastInt ? 31 : end & 0x1F;\n // Ones from firstBit to lastBit, inclusive\n const mask = (2 << lastBit) - (1 << firstBit);\n bits[i] |= mask;\n }\n }\n /**\n * Clears all bits (sets to false).\n */\n clear() {\n const max = this.bits.length;\n const bits = this.bits;\n for (let i = 0; i < max; i++) {\n bits[i] = 0;\n }\n }\n /**\n * Efficient method to check if a range of bits is set, or not set.\n *\n * @param start start of range, inclusive.\n * @param end end of range, exclusive\n * @param value if true, checks that bits in range are set, otherwise checks that they are not set\n * \n * @return true iff all bits are set or not set in range, according to value argument\n * @throws IllegalArgumentException if end is less than start or the range is not contained in the array\n */\n isRange(start /*int*/, end /*int*/, value) {\n if (end < start || start < 0 || end > this.size) {\n throw new IllegalArgumentException();\n }\n if (end === start) {\n return true; // empty range matches\n }\n end--; // will be easier to treat this as the last actually set bit -- inclusive\n const firstInt = Math.floor(start / 32);\n const lastInt = Math.floor(end / 32);\n const bits = this.bits;\n for (let i = firstInt; i <= lastInt; i++) {\n const firstBit = i > firstInt ? 0 : start & 0x1F;\n const lastBit = i < lastInt ? 31 : end & 0x1F;\n // Ones from firstBit to lastBit, inclusive\n const mask = (2 << lastBit) - (1 << firstBit) & 0xFFFFFFFF;\n // TYPESCRIPTPORT: & 0xFFFFFFFF added to discard anything after 32 bits, as ES has 53 bits\n // Return false if we're looking for 1s and the masked bits[i] isn't all 1s (is: that,\n // equals the mask, or we're looking for 0s and the masked portion is not all 0s\n if ((bits[i] & mask) !== (value ? mask : 0)) {\n return false;\n }\n }\n return true;\n }\n appendBit(bit) {\n this.ensureCapacity(this.size + 1);\n if (bit) {\n this.bits[Math.floor(this.size / 32)] |= 1 << (this.size & 0x1F);\n }\n this.size++;\n }\n /**\n * Appends the least-significant bits, from value, in order from most-significant to\n * least-significant. For example, appending 6 bits from 0x000001E will append the bits\n * 0, 1, 1, 1, 1, 0 in that order.\n *\n * @param value {@code int} containing bits to append\n * @param numBits bits from value to append\n */\n appendBits(value /*int*/, numBits /*int*/) {\n if (numBits < 0 || numBits > 32) {\n throw new IllegalArgumentException('Num bits must be between 0 and 32');\n }\n this.ensureCapacity(this.size + numBits);\n // const appendBit = this.appendBit;\n for (let numBitsLeft = numBits; numBitsLeft > 0; numBitsLeft--) {\n this.appendBit(((value >> (numBitsLeft - 1)) & 0x01) === 1);\n }\n }\n appendBitArray(other) {\n const otherSize = other.size;\n this.ensureCapacity(this.size + otherSize);\n // const appendBit = this.appendBit;\n for (let i = 0; i < otherSize; i++) {\n this.appendBit(other.get(i));\n }\n }\n xor(other) {\n if (this.size !== other.size) {\n throw new IllegalArgumentException('Sizes don\\'t match');\n }\n const bits = this.bits;\n for (let i = 0, length = bits.length; i < length; i++) {\n // The last int could be incomplete (i.e. not have 32 bits in\n // it) but there is no problem since 0 XOR 0 == 0.\n bits[i] ^= other.bits[i];\n }\n }\n /**\n *\n * @param bitOffset first bit to start writing\n * @param array array to write into. Bytes are written most-significant byte first. This is the opposite\n * of the internal representation, which is exposed by {@link #getBitArray()}\n * @param offset position in array to start writing\n * @param numBytes how many bytes to write\n */\n toBytes(bitOffset /*int*/, array, offset /*int*/, numBytes /*int*/) {\n for (let i = 0; i < numBytes; i++) {\n let theByte = 0;\n for (let j = 0; j < 8; j++) {\n if (this.get(bitOffset)) {\n theByte |= 1 << (7 - j);\n }\n bitOffset++;\n }\n array[offset + i] = /*(byte)*/ theByte;\n }\n }\n /**\n * @return underlying array of ints. The first element holds the first 32 bits, and the least\n * significant bit is bit 0.\n */\n getBitArray() {\n return this.bits;\n }\n /**\n * Reverses all bits in the array.\n */\n reverse() {\n const newBits = new Int32Array(this.bits.length);\n // reverse all int's first\n const len = Math.floor((this.size - 1) / 32);\n const oldBitsLen = len + 1;\n const bits = this.bits;\n for (let i = 0; i < oldBitsLen; i++) {\n let x = bits[i];\n x = ((x >> 1) & 0x55555555) | ((x & 0x55555555) << 1);\n x = ((x >> 2) & 0x33333333) | ((x & 0x33333333) << 2);\n x = ((x >> 4) & 0x0f0f0f0f) | ((x & 0x0f0f0f0f) << 4);\n x = ((x >> 8) & 0x00ff00ff) | ((x & 0x00ff00ff) << 8);\n x = ((x >> 16) & 0x0000ffff) | ((x & 0x0000ffff) << 16);\n newBits[len - i] = /*(int)*/ x;\n }\n // now correct the int's if the bit size isn't a multiple of 32\n if (this.size !== oldBitsLen * 32) {\n const leftOffset = oldBitsLen * 32 - this.size;\n let currentInt = newBits[0] >>> leftOffset;\n for (let i = 1; i < oldBitsLen; i++) {\n const nextInt = newBits[i];\n currentInt |= nextInt << (32 - leftOffset);\n newBits[i - 1] = currentInt;\n currentInt = nextInt >>> leftOffset;\n }\n newBits[oldBitsLen - 1] = currentInt;\n }\n this.bits = newBits;\n }\n static makeArray(size /*int*/) {\n return new Int32Array(Math.floor((size + 31) / 32));\n }\n /*@Override*/\n equals(o) {\n if (!(o instanceof BitArray)) {\n return false;\n }\n const other = o;\n return this.size === other.size && Arrays.equals(this.bits, other.bits);\n }\n /*@Override*/\n hashCode() {\n return 31 * this.size + Arrays.hashCode(this.bits);\n }\n /*@Override*/\n toString() {\n let result = '';\n for (let i = 0, size = this.size; i < size; i++) {\n if ((i & 0x07) === 0) {\n result += ' ';\n }\n result += this.get(i) ? 'X' : '.';\n }\n return result;\n }\n /*@Override*/\n clone() {\n return new BitArray(this.size, this.bits.slice());\n }\n }\n\n /*\n * Copyright 2009 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n /*namespace com.google.zxing {*/\n /**\n * Encapsulates a type of hint that a caller may pass to a barcode reader to help it\n * more quickly or accurately decode it. It is up to implementations to decide what,\n * if anything, to do with the information that is supplied.\n *\n * @author Sean Owen\n * @author dswitkin@google.com (Daniel Switkin)\n * @see Reader#decode(BinaryBitmap,java.util.Map)\n */\n var DecodeHintType;\n (function (DecodeHintType) {\n /**\n * Unspecified, application-specific hint. Maps to an unspecified {@link Object}.\n */\n DecodeHintType[DecodeHintType[\"OTHER\"] = 0] = \"OTHER\"; /*(Object.class)*/\n /**\n * Image is a pure monochrome image of a barcode. Doesn't matter what it maps to;\n * use {@link Boolean#TRUE}.\n */\n DecodeHintType[DecodeHintType[\"PURE_BARCODE\"] = 1] = \"PURE_BARCODE\"; /*(Void.class)*/\n /**\n * Image is known to be of one of a few possible formats.\n * Maps to a {@link List} of {@link BarcodeFormat}s.\n */\n DecodeHintType[DecodeHintType[\"POSSIBLE_FORMATS\"] = 2] = \"POSSIBLE_FORMATS\"; /*(List.class)*/\n /**\n * Spend more time to try to find a barcode; optimize for accuracy, not speed.\n * Doesn't matter what it maps to; use {@link Boolean#TRUE}.\n */\n DecodeHintType[DecodeHintType[\"TRY_HARDER\"] = 3] = \"TRY_HARDER\"; /*(Void.class)*/\n /**\n * Specifies what character encoding to use when decoding, where applicable (type String)\n */\n DecodeHintType[DecodeHintType[\"CHARACTER_SET\"] = 4] = \"CHARACTER_SET\"; /*(String.class)*/\n /**\n * Allowed lengths of encoded data -- reject anything else. Maps to an {@code Int32Array}.\n */\n DecodeHintType[DecodeHintType[\"ALLOWED_LENGTHS\"] = 5] = \"ALLOWED_LENGTHS\"; /*(Int32Array.class)*/\n /**\n * Assume Code 39 codes employ a check digit. Doesn't matter what it maps to;\n * use {@link Boolean#TRUE}.\n */\n DecodeHintType[DecodeHintType[\"ASSUME_CODE_39_CHECK_DIGIT\"] = 6] = \"ASSUME_CODE_39_CHECK_DIGIT\"; /*(Void.class)*/\n /**\n * Assume the barcode is being processed as a GS1 barcode, and modify behavior as needed.\n * For example this affects FNC1 handling for Code 128 (aka GS1-128). Doesn't matter what it maps to;\n * use {@link Boolean#TRUE}.\n */\n DecodeHintType[DecodeHintType[\"ASSUME_GS1\"] = 7] = \"ASSUME_GS1\"; /*(Void.class)*/\n /**\n * If true, return the start and end digits in a Codabar barcode instead of stripping them. They\n * are alpha, whereas the rest are numeric. By default, they are stripped, but this causes them\n * to not be. Doesn't matter what it maps to; use {@link Boolean#TRUE}.\n */\n DecodeHintType[DecodeHintType[\"RETURN_CODABAR_START_END\"] = 8] = \"RETURN_CODABAR_START_END\"; /*(Void.class)*/\n /**\n * The caller needs to be notified via callback when a possible {@link ResultPoint}\n * is found. Maps to a {@link ResultPointCallback}.\n */\n DecodeHintType[DecodeHintType[\"NEED_RESULT_POINT_CALLBACK\"] = 9] = \"NEED_RESULT_POINT_CALLBACK\"; /*(ResultPointCallback.class)*/\n /**\n * Allowed extension lengths for EAN or UPC barcodes. Other formats will ignore this.\n * Maps to an {@code Int32Array} of the allowed extension lengths, for example [2], [5], or [2, 5].\n * If it is optional to have an extension, do not set this hint. If this is set,\n * and a UPC or EAN barcode is found but an extension is not, then no result will be returned\n * at all.\n */\n DecodeHintType[DecodeHintType[\"ALLOWED_EAN_EXTENSIONS\"] = 10] = \"ALLOWED_EAN_EXTENSIONS\"; /*(Int32Array.class)*/\n // End of enumeration values.\n /**\n * Data type the hint is expecting.\n * Among the possible values the {@link Void} stands out as being used for\n * hints that do not expect a value to be supplied (flag hints). Such hints\n * will possibly have their value ignored, or replaced by a\n * {@link Boolean#TRUE}. Hint suppliers should probably use\n * {@link Boolean#TRUE} as directed by the actual hint documentation.\n */\n // private valueType: Class\n // DecodeHintType(valueType: Class) {\n // this.valueType = valueType\n // }\n // public getValueType(): Class {\n // return valueType\n // }\n })(DecodeHintType || (DecodeHintType = {}));\n var DecodeHintType$1 = DecodeHintType;\n\n /**\n * Custom Error class of type Exception.\n */\n class FormatException extends Exception {\n static getFormatInstance() {\n return new FormatException();\n }\n }\n FormatException.kind = 'FormatException';\n\n /*import java.util.HashMap;*/\n /*import java.util.Map;*/\n var CharacterSetValueIdentifiers;\n (function (CharacterSetValueIdentifiers) {\n CharacterSetValueIdentifiers[CharacterSetValueIdentifiers[\"Cp437\"] = 0] = \"Cp437\";\n CharacterSetValueIdentifiers[CharacterSetValueIdentifiers[\"ISO8859_1\"] = 1] = \"ISO8859_1\";\n CharacterSetValueIdentifiers[CharacterSetValueIdentifiers[\"ISO8859_2\"] = 2] = \"ISO8859_2\";\n CharacterSetValueIdentifiers[CharacterSetValueIdentifiers[\"ISO8859_3\"] = 3] = \"ISO8859_3\";\n CharacterSetValueIdentifiers[CharacterSetValueIdentifiers[\"ISO8859_4\"] = 4] = \"ISO8859_4\";\n CharacterSetValueIdentifiers[CharacterSetValueIdentifiers[\"ISO8859_5\"] = 5] = \"ISO8859_5\";\n CharacterSetValueIdentifiers[CharacterSetValueIdentifiers[\"ISO8859_6\"] = 6] = \"ISO8859_6\";\n CharacterSetValueIdentifiers[CharacterSetValueIdentifiers[\"ISO8859_7\"] = 7] = \"ISO8859_7\";\n CharacterSetValueIdentifiers[CharacterSetValueIdentifiers[\"ISO8859_8\"] = 8] = \"ISO8859_8\";\n CharacterSetValueIdentifiers[CharacterSetValueIdentifiers[\"ISO8859_9\"] = 9] = \"ISO8859_9\";\n CharacterSetValueIdentifiers[CharacterSetValueIdentifiers[\"ISO8859_10\"] = 10] = \"ISO8859_10\";\n CharacterSetValueIdentifiers[CharacterSetValueIdentifiers[\"ISO8859_11\"] = 11] = \"ISO8859_11\";\n CharacterSetValueIdentifiers[CharacterSetValueIdentifiers[\"ISO8859_13\"] = 12] = \"ISO8859_13\";\n CharacterSetValueIdentifiers[CharacterSetValueIdentifiers[\"ISO8859_14\"] = 13] = \"ISO8859_14\";\n CharacterSetValueIdentifiers[CharacterSetValueIdentifiers[\"ISO8859_15\"] = 14] = \"ISO8859_15\";\n CharacterSetValueIdentifiers[CharacterSetValueIdentifiers[\"ISO8859_16\"] = 15] = \"ISO8859_16\";\n CharacterSetValueIdentifiers[CharacterSetValueIdentifiers[\"SJIS\"] = 16] = \"SJIS\";\n CharacterSetValueIdentifiers[CharacterSetValueIdentifiers[\"Cp1250\"] = 17] = \"Cp1250\";\n CharacterSetValueIdentifiers[CharacterSetValueIdentifiers[\"Cp1251\"] = 18] = \"Cp1251\";\n CharacterSetValueIdentifiers[CharacterSetValueIdentifiers[\"Cp1252\"] = 19] = \"Cp1252\";\n CharacterSetValueIdentifiers[CharacterSetValueIdentifiers[\"Cp1256\"] = 20] = \"Cp1256\";\n CharacterSetValueIdentifiers[CharacterSetValueIdentifiers[\"UnicodeBigUnmarked\"] = 21] = \"UnicodeBigUnmarked\";\n CharacterSetValueIdentifiers[CharacterSetValueIdentifiers[\"UTF8\"] = 22] = \"UTF8\";\n CharacterSetValueIdentifiers[CharacterSetValueIdentifiers[\"ASCII\"] = 23] = \"ASCII\";\n CharacterSetValueIdentifiers[CharacterSetValueIdentifiers[\"Big5\"] = 24] = \"Big5\";\n CharacterSetValueIdentifiers[CharacterSetValueIdentifiers[\"GB18030\"] = 25] = \"GB18030\";\n CharacterSetValueIdentifiers[CharacterSetValueIdentifiers[\"EUC_KR\"] = 26] = \"EUC_KR\";\n })(CharacterSetValueIdentifiers || (CharacterSetValueIdentifiers = {}));\n /**\n * Encapsulates a Character Set ECI, according to \"Extended Channel Interpretations\" 5.3.1.1\n * of ISO 18004.\n *\n * @author Sean Owen\n */\n class CharacterSetECI {\n constructor(valueIdentifier, valuesParam, name, ...otherEncodingNames) {\n this.valueIdentifier = valueIdentifier;\n this.name = name;\n if (typeof valuesParam === 'number') {\n this.values = Int32Array.from([valuesParam]);\n }\n else {\n this.values = valuesParam;\n }\n this.otherEncodingNames = otherEncodingNames;\n CharacterSetECI.VALUE_IDENTIFIER_TO_ECI.set(valueIdentifier, this);\n CharacterSetECI.NAME_TO_ECI.set(name, this);\n const values = this.values;\n for (let i = 0, length = values.length; i !== length; i++) {\n const v = values[i];\n CharacterSetECI.VALUES_TO_ECI.set(v, this);\n }\n for (const otherName of otherEncodingNames) {\n CharacterSetECI.NAME_TO_ECI.set(otherName, this);\n }\n }\n // CharacterSetECI(value: number /*int*/) {\n // this(new Int32Array {value})\n // }\n // CharacterSetECI(value: number /*int*/, String... otherEncodingNames) {\n // this.values = new Int32Array {value}\n // this.otherEncodingNames = otherEncodingNames\n // }\n // CharacterSetECI(values: Int32Array, String... otherEncodingNames) {\n // this.values = values\n // this.otherEncodingNames = otherEncodingNames\n // }\n getValueIdentifier() {\n return this.valueIdentifier;\n }\n getName() {\n return this.name;\n }\n getValue() {\n return this.values[0];\n }\n /**\n * @param value character set ECI value\n * @return {@code CharacterSetECI} representing ECI of given value, or null if it is legal but\n * unsupported\n * @throws FormatException if ECI value is invalid\n */\n static getCharacterSetECIByValue(value /*int*/) {\n if (value < 0 || value >= 900) {\n throw new FormatException('incorect value');\n }\n const characterSet = CharacterSetECI.VALUES_TO_ECI.get(value);\n if (undefined === characterSet) {\n throw new FormatException('incorect value');\n }\n return characterSet;\n }\n /**\n * @param name character set ECI encoding name\n * @return CharacterSetECI representing ECI for character encoding, or null if it is legal\n * but unsupported\n */\n static getCharacterSetECIByName(name) {\n const characterSet = CharacterSetECI.NAME_TO_ECI.get(name);\n if (undefined === characterSet) {\n throw new FormatException('incorect value');\n }\n return characterSet;\n }\n equals(o) {\n if (!(o instanceof CharacterSetECI)) {\n return false;\n }\n const other = o;\n return this.getName() === other.getName();\n }\n }\n CharacterSetECI.VALUE_IDENTIFIER_TO_ECI = new Map();\n CharacterSetECI.VALUES_TO_ECI = new Map();\n CharacterSetECI.NAME_TO_ECI = new Map();\n // Enum name is a Java encoding valid for java.lang and java.io\n // TYPESCRIPTPORT: changed the main label for ISO as the TextEncoder did not recognized them in the form from java\n // (eg ISO8859_1 must be ISO88591 or ISO8859-1 or ISO-8859-1)\n // later on: well, except 16 wich does not work with ISO885916 so used ISO-8859-1 form for default\n CharacterSetECI.Cp437 = new CharacterSetECI(CharacterSetValueIdentifiers.Cp437, Int32Array.from([0, 2]), 'Cp437');\n CharacterSetECI.ISO8859_1 = new CharacterSetECI(CharacterSetValueIdentifiers.ISO8859_1, Int32Array.from([1, 3]), 'ISO-8859-1', 'ISO88591', 'ISO8859_1');\n CharacterSetECI.ISO8859_2 = new CharacterSetECI(CharacterSetValueIdentifiers.ISO8859_2, 4, 'ISO-8859-2', 'ISO88592', 'ISO8859_2');\n CharacterSetECI.ISO8859_3 = new CharacterSetECI(CharacterSetValueIdentifiers.ISO8859_3, 5, 'ISO-8859-3', 'ISO88593', 'ISO8859_3');\n CharacterSetECI.ISO8859_4 = new CharacterSetECI(CharacterSetValueIdentifiers.ISO8859_4, 6, 'ISO-8859-4', 'ISO88594', 'ISO8859_4');\n CharacterSetECI.ISO8859_5 = new CharacterSetECI(CharacterSetValueIdentifiers.ISO8859_5, 7, 'ISO-8859-5', 'ISO88595', 'ISO8859_5');\n CharacterSetECI.ISO8859_6 = new CharacterSetECI(CharacterSetValueIdentifiers.ISO8859_6, 8, 'ISO-8859-6', 'ISO88596', 'ISO8859_6');\n CharacterSetECI.ISO8859_7 = new CharacterSetECI(CharacterSetValueIdentifiers.ISO8859_7, 9, 'ISO-8859-7', 'ISO88597', 'ISO8859_7');\n CharacterSetECI.ISO8859_8 = new CharacterSetECI(CharacterSetValueIdentifiers.ISO8859_8, 10, 'ISO-8859-8', 'ISO88598', 'ISO8859_8');\n CharacterSetECI.ISO8859_9 = new CharacterSetECI(CharacterSetValueIdentifiers.ISO8859_9, 11, 'ISO-8859-9', 'ISO88599', 'ISO8859_9');\n CharacterSetECI.ISO8859_10 = new CharacterSetECI(CharacterSetValueIdentifiers.ISO8859_10, 12, 'ISO-8859-10', 'ISO885910', 'ISO8859_10');\n CharacterSetECI.ISO8859_11 = new CharacterSetECI(CharacterSetValueIdentifiers.ISO8859_11, 13, 'ISO-8859-11', 'ISO885911', 'ISO8859_11');\n CharacterSetECI.ISO8859_13 = new CharacterSetECI(CharacterSetValueIdentifiers.ISO8859_13, 15, 'ISO-8859-13', 'ISO885913', 'ISO8859_13');\n CharacterSetECI.ISO8859_14 = new CharacterSetECI(CharacterSetValueIdentifiers.ISO8859_14, 16, 'ISO-8859-14', 'ISO885914', 'ISO8859_14');\n CharacterSetECI.ISO8859_15 = new CharacterSetECI(CharacterSetValueIdentifiers.ISO8859_15, 17, 'ISO-8859-15', 'ISO885915', 'ISO8859_15');\n CharacterSetECI.ISO8859_16 = new CharacterSetECI(CharacterSetValueIdentifiers.ISO8859_16, 18, 'ISO-8859-16', 'ISO885916', 'ISO8859_16');\n CharacterSetECI.SJIS = new CharacterSetECI(CharacterSetValueIdentifiers.SJIS, 20, 'SJIS', 'Shift_JIS');\n CharacterSetECI.Cp1250 = new CharacterSetECI(CharacterSetValueIdentifiers.Cp1250, 21, 'Cp1250', 'windows-1250');\n CharacterSetECI.Cp1251 = new CharacterSetECI(CharacterSetValueIdentifiers.Cp1251, 22, 'Cp1251', 'windows-1251');\n CharacterSetECI.Cp1252 = new CharacterSetECI(CharacterSetValueIdentifiers.Cp1252, 23, 'Cp1252', 'windows-1252');\n CharacterSetECI.Cp1256 = new CharacterSetECI(CharacterSetValueIdentifiers.Cp1256, 24, 'Cp1256', 'windows-1256');\n CharacterSetECI.UnicodeBigUnmarked = new CharacterSetECI(CharacterSetValueIdentifiers.UnicodeBigUnmarked, 25, 'UnicodeBigUnmarked', 'UTF-16BE', 'UnicodeBig');\n CharacterSetECI.UTF8 = new CharacterSetECI(CharacterSetValueIdentifiers.UTF8, 26, 'UTF8', 'UTF-8');\n CharacterSetECI.ASCII = new CharacterSetECI(CharacterSetValueIdentifiers.ASCII, Int32Array.from([27, 170]), 'ASCII', 'US-ASCII');\n CharacterSetECI.Big5 = new CharacterSetECI(CharacterSetValueIdentifiers.Big5, 28, 'Big5');\n CharacterSetECI.GB18030 = new CharacterSetECI(CharacterSetValueIdentifiers.GB18030, 29, 'GB18030', 'GB2312', 'EUC_CN', 'GBK');\n CharacterSetECI.EUC_KR = new CharacterSetECI(CharacterSetValueIdentifiers.EUC_KR, 30, 'EUC_KR', 'EUC-KR');\n\n /**\n * Custom Error class of type Exception.\n */\n class UnsupportedOperationException extends Exception {\n }\n UnsupportedOperationException.kind = 'UnsupportedOperationException';\n\n /**\n * Responsible for en/decoding strings.\n */\n class StringEncoding {\n /**\n * Decodes some Uint8Array to a string format.\n */\n static decode(bytes, encoding) {\n const encodingName = this.encodingName(encoding);\n if (this.customDecoder) {\n return this.customDecoder(bytes, encodingName);\n }\n // Increases browser support.\n if (typeof TextDecoder === 'undefined' || this.shouldDecodeOnFallback(encodingName)) {\n return this.decodeFallback(bytes, encodingName);\n }\n return new TextDecoder(encodingName).decode(bytes);\n }\n /**\n * Checks if the decoding method should use the fallback for decoding\n * once Node TextDecoder doesn't support all encoding formats.\n *\n * @param encodingName\n */\n static shouldDecodeOnFallback(encodingName) {\n return !StringEncoding.isBrowser() && encodingName === 'ISO-8859-1';\n }\n /**\n * Encodes some string into a Uint8Array.\n */\n static encode(s, encoding) {\n const encodingName = this.encodingName(encoding);\n if (this.customEncoder) {\n return this.customEncoder(s, encodingName);\n }\n // Increases browser support.\n if (typeof TextEncoder === 'undefined') {\n return this.encodeFallback(s);\n }\n // TextEncoder only encodes to UTF8 by default as specified by encoding.spec.whatwg.org\n return new TextEncoder().encode(s);\n }\n static isBrowser() {\n return (typeof window !== 'undefined' && {}.toString.call(window) === '[object Window]');\n }\n /**\n * Returns the string value from some encoding character set.\n */\n static encodingName(encoding) {\n return typeof encoding === 'string'\n ? encoding\n : encoding.getName();\n }\n /**\n * Returns character set from some encoding character set.\n */\n static encodingCharacterSet(encoding) {\n if (encoding instanceof CharacterSetECI) {\n return encoding;\n }\n return CharacterSetECI.getCharacterSetECIByName(encoding);\n }\n /**\n * Runs a fallback for the native decoding funcion.\n */\n static decodeFallback(bytes, encoding) {\n const characterSet = this.encodingCharacterSet(encoding);\n if (StringEncoding.isDecodeFallbackSupported(characterSet)) {\n let s = '';\n for (let i = 0, length = bytes.length; i < length; i++) {\n let h = bytes[i].toString(16);\n if (h.length < 2) {\n h = '0' + h;\n }\n s += '%' + h;\n }\n return decodeURIComponent(s);\n }\n if (characterSet.equals(CharacterSetECI.UnicodeBigUnmarked)) {\n return String.fromCharCode.apply(null, new Uint16Array(bytes.buffer));\n }\n throw new UnsupportedOperationException(`Encoding ${this.encodingName(encoding)} not supported by fallback.`);\n }\n static isDecodeFallbackSupported(characterSet) {\n return characterSet.equals(CharacterSetECI.UTF8) ||\n characterSet.equals(CharacterSetECI.ISO8859_1) ||\n characterSet.equals(CharacterSetECI.ASCII);\n }\n /**\n * Runs a fallback for the native encoding funcion.\n *\n * @see https://stackoverflow.com/a/17192845/4367683\n */\n static encodeFallback(s) {\n const encodedURIstring = btoa(unescape(encodeURIComponent(s)));\n const charList = encodedURIstring.split('');\n const uintArray = [];\n for (let i = 0; i < charList.length; i++) {\n uintArray.push(charList[i].charCodeAt(0));\n }\n return new Uint8Array(uintArray);\n }\n }\n\n /*\n * Copyright (C) 2010 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n /**\n * Common string-related functions.\n *\n * @author Sean Owen\n * @author Alex Dupre\n */\n class StringUtils {\n // SHIFT_JIS.equalsIgnoreCase(PLATFORM_DEFAULT_ENCODING) ||\n // EUC_JP.equalsIgnoreCase(PLATFORM_DEFAULT_ENCODING);\n static castAsNonUtf8Char(code, encoding = null) {\n // ISO 8859-1 is the Java default as UTF-8 is JavaScripts\n // you can see this method as a Java version of String.fromCharCode\n const e = encoding ? encoding.getName() : this.ISO88591;\n // use passed format (fromCharCode will return UTF8 encoding)\n return StringEncoding.decode(new Uint8Array([code]), e);\n }\n /**\n * @param bytes bytes encoding a string, whose encoding should be guessed\n * @param hints decode hints if applicable\n * @return name of guessed encoding; at the moment will only guess one of:\n * {@link #SHIFT_JIS}, {@link #UTF8}, {@link #ISO88591}, or the platform\n * default encoding if none of these can possibly be correct\n */\n static guessEncoding(bytes, hints) {\n if (hints !== null && hints !== undefined && undefined !== hints.get(DecodeHintType$1.CHARACTER_SET)) {\n return hints.get(DecodeHintType$1.CHARACTER_SET).toString();\n }\n // For now, merely tries to distinguish ISO-8859-1, UTF-8 and Shift_JIS,\n // which should be by far the most common encodings.\n const length = bytes.length;\n let canBeISO88591 = true;\n let canBeShiftJIS = true;\n let canBeUTF8 = true;\n let utf8BytesLeft = 0;\n // int utf8LowChars = 0\n let utf2BytesChars = 0;\n let utf3BytesChars = 0;\n let utf4BytesChars = 0;\n let sjisBytesLeft = 0;\n // int sjisLowChars = 0\n let sjisKatakanaChars = 0;\n // int sjisDoubleBytesChars = 0\n let sjisCurKatakanaWordLength = 0;\n let sjisCurDoubleBytesWordLength = 0;\n let sjisMaxKatakanaWordLength = 0;\n let sjisMaxDoubleBytesWordLength = 0;\n // int isoLowChars = 0\n // int isoHighChars = 0\n let isoHighOther = 0;\n const utf8bom = bytes.length > 3 &&\n bytes[0] === /*(byte) */ 0xEF &&\n bytes[1] === /*(byte) */ 0xBB &&\n bytes[2] === /*(byte) */ 0xBF;\n for (let i = 0; i < length && (canBeISO88591 || canBeShiftJIS || canBeUTF8); i++) {\n const value = bytes[i] & 0xFF;\n // UTF-8 stuff\n if (canBeUTF8) {\n if (utf8BytesLeft > 0) {\n if ((value & 0x80) === 0) {\n canBeUTF8 = false;\n }\n else {\n utf8BytesLeft--;\n }\n }\n else if ((value & 0x80) !== 0) {\n if ((value & 0x40) === 0) {\n canBeUTF8 = false;\n }\n else {\n utf8BytesLeft++;\n if ((value & 0x20) === 0) {\n utf2BytesChars++;\n }\n else {\n utf8BytesLeft++;\n if ((value & 0x10) === 0) {\n utf3BytesChars++;\n }\n else {\n utf8BytesLeft++;\n if ((value & 0x08) === 0) {\n utf4BytesChars++;\n }\n else {\n canBeUTF8 = false;\n }\n }\n }\n }\n } // else {\n // utf8LowChars++\n // }\n }\n // ISO-8859-1 stuff\n if (canBeISO88591) {\n if (value > 0x7F && value < 0xA0) {\n canBeISO88591 = false;\n }\n else if (value > 0x9F) {\n if (value < 0xC0 || value === 0xD7 || value === 0xF7) {\n isoHighOther++;\n } // else {\n // isoHighChars++\n // }\n } // else {\n // isoLowChars++\n // }\n }\n // Shift_JIS stuff\n if (canBeShiftJIS) {\n if (sjisBytesLeft > 0) {\n if (value < 0x40 || value === 0x7F || value > 0xFC) {\n canBeShiftJIS = false;\n }\n else {\n sjisBytesLeft--;\n }\n }\n else if (value === 0x80 || value === 0xA0 || value > 0xEF) {\n canBeShiftJIS = false;\n }\n else if (value > 0xA0 && value < 0xE0) {\n sjisKatakanaChars++;\n sjisCurDoubleBytesWordLength = 0;\n sjisCurKatakanaWordLength++;\n if (sjisCurKatakanaWordLength > sjisMaxKatakanaWordLength) {\n sjisMaxKatakanaWordLength = sjisCurKatakanaWordLength;\n }\n }\n else if (value > 0x7F) {\n sjisBytesLeft++;\n // sjisDoubleBytesChars++\n sjisCurKatakanaWordLength = 0;\n sjisCurDoubleBytesWordLength++;\n if (sjisCurDoubleBytesWordLength > sjisMaxDoubleBytesWordLength) {\n sjisMaxDoubleBytesWordLength = sjisCurDoubleBytesWordLength;\n }\n }\n else {\n // sjisLowChars++\n sjisCurKatakanaWordLength = 0;\n sjisCurDoubleBytesWordLength = 0;\n }\n }\n }\n if (canBeUTF8 && utf8BytesLeft > 0) {\n canBeUTF8 = false;\n }\n if (canBeShiftJIS && sjisBytesLeft > 0) {\n canBeShiftJIS = false;\n }\n // Easy -- if there is BOM or at least 1 valid not-single byte character (and no evidence it can't be UTF-8), done\n if (canBeUTF8 && (utf8bom || utf2BytesChars + utf3BytesChars + utf4BytesChars > 0)) {\n return StringUtils.UTF8;\n }\n // Easy -- if assuming Shift_JIS or at least 3 valid consecutive not-ascii characters (and no evidence it can't be), done\n if (canBeShiftJIS && (StringUtils.ASSUME_SHIFT_JIS || sjisMaxKatakanaWordLength >= 3 || sjisMaxDoubleBytesWordLength >= 3)) {\n return StringUtils.SHIFT_JIS;\n }\n // Distinguishing Shift_JIS and ISO-8859-1 can be a little tough for short words. The crude heuristic is:\n // - If we saw\n // - only two consecutive katakana chars in the whole text, or\n // - at least 10% of bytes that could be \"upper\" not-alphanumeric Latin1,\n // - then we conclude Shift_JIS, else ISO-8859-1\n if (canBeISO88591 && canBeShiftJIS) {\n return (sjisMaxKatakanaWordLength === 2 && sjisKatakanaChars === 2) || isoHighOther * 10 >= length\n ? StringUtils.SHIFT_JIS : StringUtils.ISO88591;\n }\n // Otherwise, try in order ISO-8859-1, Shift JIS, UTF-8 and fall back to default platform encoding\n if (canBeISO88591) {\n return StringUtils.ISO88591;\n }\n if (canBeShiftJIS) {\n return StringUtils.SHIFT_JIS;\n }\n if (canBeUTF8) {\n return StringUtils.UTF8;\n }\n // Otherwise, we take a wild guess with platform encoding\n return StringUtils.PLATFORM_DEFAULT_ENCODING;\n }\n /**\n *\n * @see https://stackoverflow.com/a/13439711/4367683\n *\n * @param append The new string to append.\n * @param args Argumets values to be formated.\n */\n static format(append, ...args) {\n let i = -1;\n function callback(exp, p0, p1, p2, p3, p4) {\n if (exp === '%%')\n return '%';\n if (args[++i] === undefined)\n return undefined;\n exp = p2 ? parseInt(p2.substr(1)) : undefined;\n let base = p3 ? parseInt(p3.substr(1)) : undefined;\n let val;\n switch (p4) {\n case 's':\n val = args[i];\n break;\n case 'c':\n val = args[i][0];\n break;\n case 'f':\n val = parseFloat(args[i]).toFixed(exp);\n break;\n case 'p':\n val = parseFloat(args[i]).toPrecision(exp);\n break;\n case 'e':\n val = parseFloat(args[i]).toExponential(exp);\n break;\n case 'x':\n val = parseInt(args[i]).toString(base ? base : 16);\n break;\n case 'd':\n val = parseFloat(parseInt(args[i], base ? base : 10).toPrecision(exp)).toFixed(0);\n break;\n }\n val = typeof val === 'object' ? JSON.stringify(val) : (+val).toString(base);\n let size = parseInt(p1); /* padding size */\n let ch = p1 && (p1[0] + '') === '0' ? '0' : ' '; /* isnull? */\n while (val.length < size)\n val = p0 !== undefined ? val + ch : ch + val; /* isminus? */\n return val;\n }\n let regex = /%(-)?(0?[0-9]+)?([.][0-9]+)?([#][0-9]+)?([scfpexd%])/g;\n return append.replace(regex, callback);\n }\n /**\n *\n */\n static getBytes(str, encoding) {\n return StringEncoding.encode(str, encoding);\n }\n /**\n * Returns the charcode at the specified index or at index zero.\n */\n static getCharCode(str, index = 0) {\n return str.charCodeAt(index);\n }\n /**\n * Returns char for given charcode\n */\n static getCharAt(charCode) {\n return String.fromCharCode(charCode);\n }\n }\n StringUtils.SHIFT_JIS = CharacterSetECI.SJIS.getName(); // \"SJIS\"\n StringUtils.GB2312 = 'GB2312';\n StringUtils.ISO88591 = CharacterSetECI.ISO8859_1.getName(); // \"ISO8859_1\"\n StringUtils.EUC_JP = 'EUC_JP';\n StringUtils.UTF8 = CharacterSetECI.UTF8.getName(); // \"UTF8\"\n StringUtils.PLATFORM_DEFAULT_ENCODING = StringUtils.UTF8; // \"UTF8\"//Charset.defaultCharset().name()\n StringUtils.ASSUME_SHIFT_JIS = false;\n\n class StringBuilder {\n constructor(value = '') {\n this.value = value;\n }\n enableDecoding(encoding) {\n this.encoding = encoding;\n return this;\n }\n append(s) {\n if (typeof s === 'string') {\n this.value += s.toString();\n }\n else if (this.encoding) {\n // use passed format (fromCharCode will return UTF8 encoding)\n this.value += StringUtils.castAsNonUtf8Char(s, this.encoding);\n }\n else {\n // correctly converts from UTF-8, but not other encodings\n this.value += String.fromCharCode(s);\n }\n return this;\n }\n appendChars(str, offset, len) {\n for (let i = offset; offset < offset + len; i++) {\n this.append(str[i]);\n }\n return this;\n }\n length() {\n return this.value.length;\n }\n charAt(n) {\n return this.value.charAt(n);\n }\n deleteCharAt(n) {\n this.value = this.value.substr(0, n) + this.value.substring(n + 1);\n }\n setCharAt(n, c) {\n this.value = this.value.substr(0, n) + c + this.value.substr(n + 1);\n }\n substring(start, end) {\n return this.value.substring(start, end);\n }\n /**\n * @note helper method for RSS Expanded\n */\n setLengthToZero() {\n this.value = '';\n }\n toString() {\n return this.value;\n }\n insert(n, c) {\n this.value = this.value.substr(0, n) + c + this.value.substr(n + c.length);\n }\n }\n\n /*\n * Copyright 2007 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n /**\n *

Represents a 2D matrix of bits. In function arguments below, and throughout the common\n * module, x is the column position, and y is the row position. The ordering is always x, y.\n * The origin is at the top-left.

\n *\n *

Internally the bits are represented in a 1-D array of 32-bit ints. However, each row begins\n * with a new int. This is done intentionally so that we can copy out a row into a BitArray very\n * efficiently.

\n *\n *

The ordering of bits is row-major. Within each int, the least significant bits are used first,\n * meaning they represent lower x values. This is compatible with BitArray's implementation.

\n *\n * @author Sean Owen\n * @author dswitkin@google.com (Daniel Switkin)\n */\n class BitMatrix /*implements Cloneable*/ {\n /**\n * Creates an empty square {@link BitMatrix}.\n *\n * @param dimension height and width\n */\n // public constructor(dimension: number /*int*/) {\n // this(dimension, dimension)\n // }\n /**\n * Creates an empty {@link BitMatrix}.\n *\n * @param width bit matrix width\n * @param height bit matrix height\n */\n // public constructor(width: number /*int*/, height: number /*int*/) {\n // if (width < 1 || height < 1) {\n // throw new IllegalArgumentException(\"Both dimensions must be greater than 0\")\n // }\n // this.width = width\n // this.height = height\n // this.rowSize = (width + 31) / 32\n // bits = new int[rowSize * height];\n // }\n constructor(width /*int*/, height /*int*/, rowSize /*int*/, bits) {\n this.width = width;\n this.height = height;\n this.rowSize = rowSize;\n this.bits = bits;\n if (undefined === height || null === height) {\n height = width;\n }\n this.height = height;\n if (width < 1 || height < 1) {\n throw new IllegalArgumentException('Both dimensions must be greater than 0');\n }\n if (undefined === rowSize || null === rowSize) {\n rowSize = Math.floor((width + 31) / 32);\n }\n this.rowSize = rowSize;\n if (undefined === bits || null === bits) {\n this.bits = new Int32Array(this.rowSize * this.height);\n }\n }\n /**\n * Interprets a 2D array of booleans as a {@link BitMatrix}, where \"true\" means an \"on\" bit.\n *\n * @function parse\n * @param image bits of the image, as a row-major 2D array. Elements are arrays representing rows\n * @return {@link BitMatrix} representation of image\n */\n static parseFromBooleanArray(image) {\n const height = image.length;\n const width = image[0].length;\n const bits = new BitMatrix(width, height);\n for (let i = 0; i < height; i++) {\n const imageI = image[i];\n for (let j = 0; j < width; j++) {\n if (imageI[j]) {\n bits.set(j, i);\n }\n }\n }\n return bits;\n }\n /**\n *\n * @function parse\n * @param stringRepresentation\n * @param setString\n * @param unsetString\n */\n static parseFromString(stringRepresentation, setString, unsetString) {\n if (stringRepresentation === null) {\n throw new IllegalArgumentException('stringRepresentation cannot be null');\n }\n const bits = new Array(stringRepresentation.length);\n let bitsPos = 0;\n let rowStartPos = 0;\n let rowLength = -1;\n let nRows = 0;\n let pos = 0;\n while (pos < stringRepresentation.length) {\n if (stringRepresentation.charAt(pos) === '\\n' ||\n stringRepresentation.charAt(pos) === '\\r') {\n if (bitsPos > rowStartPos) {\n if (rowLength === -1) {\n rowLength = bitsPos - rowStartPos;\n }\n else if (bitsPos - rowStartPos !== rowLength) {\n throw new IllegalArgumentException('row lengths do not match');\n }\n rowStartPos = bitsPos;\n nRows++;\n }\n pos++;\n }\n else if (stringRepresentation.substring(pos, pos + setString.length) === setString) {\n pos += setString.length;\n bits[bitsPos] = true;\n bitsPos++;\n }\n else if (stringRepresentation.substring(pos, pos + unsetString.length) === unsetString) {\n pos += unsetString.length;\n bits[bitsPos] = false;\n bitsPos++;\n }\n else {\n throw new IllegalArgumentException('illegal character encountered: ' + stringRepresentation.substring(pos));\n }\n }\n // no EOL at end?\n if (bitsPos > rowStartPos) {\n if (rowLength === -1) {\n rowLength = bitsPos - rowStartPos;\n }\n else if (bitsPos - rowStartPos !== rowLength) {\n throw new IllegalArgumentException('row lengths do not match');\n }\n nRows++;\n }\n const matrix = new BitMatrix(rowLength, nRows);\n for (let i = 0; i < bitsPos; i++) {\n if (bits[i]) {\n matrix.set(Math.floor(i % rowLength), Math.floor(i / rowLength));\n }\n }\n return matrix;\n }\n /**\n *

Gets the requested bit, where true means black.

\n *\n * @param x The horizontal component (i.e. which column)\n * @param y The vertical component (i.e. which row)\n * @return value of given bit in matrix\n */\n get(x /*int*/, y /*int*/) {\n const offset = y * this.rowSize + Math.floor(x / 32);\n return ((this.bits[offset] >>> (x & 0x1f)) & 1) !== 0;\n }\n /**\n *

Sets the given bit to true.

\n *\n * @param x The horizontal component (i.e. which column)\n * @param y The vertical component (i.e. which row)\n */\n set(x /*int*/, y /*int*/) {\n const offset = y * this.rowSize + Math.floor(x / 32);\n this.bits[offset] |= (1 << (x & 0x1f)) & 0xFFFFFFFF;\n }\n unset(x /*int*/, y /*int*/) {\n const offset = y * this.rowSize + Math.floor(x / 32);\n this.bits[offset] &= ~((1 << (x & 0x1f)) & 0xFFFFFFFF);\n }\n /**\n *

Flips the given bit.

\n *\n * @param x The horizontal component (i.e. which column)\n * @param y The vertical component (i.e. which row)\n */\n flip(x /*int*/, y /*int*/) {\n const offset = y * this.rowSize + Math.floor(x / 32);\n this.bits[offset] ^= ((1 << (x & 0x1f)) & 0xFFFFFFFF);\n }\n /**\n * Exclusive-or (XOR): Flip the bit in this {@code BitMatrix} if the corresponding\n * mask bit is set.\n *\n * @param mask XOR mask\n */\n xor(mask) {\n if (this.width !== mask.getWidth() || this.height !== mask.getHeight()\n || this.rowSize !== mask.getRowSize()) {\n throw new IllegalArgumentException('input matrix dimensions do not match');\n }\n const rowArray = new BitArray(Math.floor(this.width / 32) + 1);\n const rowSize = this.rowSize;\n const bits = this.bits;\n for (let y = 0, height = this.height; y < height; y++) {\n const offset = y * rowSize;\n const row = mask.getRow(y, rowArray).getBitArray();\n for (let x = 0; x < rowSize; x++) {\n bits[offset + x] ^= row[x];\n }\n }\n }\n /**\n * Clears all bits (sets to false).\n */\n clear() {\n const bits = this.bits;\n const max = bits.length;\n for (let i = 0; i < max; i++) {\n bits[i] = 0;\n }\n }\n /**\n *

Sets a square region of the bit matrix to true.

\n *\n * @param left The horizontal position to begin at (inclusive)\n * @param top The vertical position to begin at (inclusive)\n * @param width The width of the region\n * @param height The height of the region\n */\n setRegion(left /*int*/, top /*int*/, width /*int*/, height /*int*/) {\n if (top < 0 || left < 0) {\n throw new IllegalArgumentException('Left and top must be nonnegative');\n }\n if (height < 1 || width < 1) {\n throw new IllegalArgumentException('Height and width must be at least 1');\n }\n const right = left + width;\n const bottom = top + height;\n if (bottom > this.height || right > this.width) {\n throw new IllegalArgumentException('The region must fit inside the matrix');\n }\n const rowSize = this.rowSize;\n const bits = this.bits;\n for (let y = top; y < bottom; y++) {\n const offset = y * rowSize;\n for (let x = left; x < right; x++) {\n bits[offset + Math.floor(x / 32)] |= ((1 << (x & 0x1f)) & 0xFFFFFFFF);\n }\n }\n }\n /**\n * A fast method to retrieve one row of data from the matrix as a BitArray.\n *\n * @param y The row to retrieve\n * @param row An optional caller-allocated BitArray, will be allocated if null or too small\n * @return The resulting BitArray - this reference should always be used even when passing\n * your own row\n */\n getRow(y /*int*/, row) {\n if (row === null || row === undefined || row.getSize() < this.width) {\n row = new BitArray(this.width);\n }\n else {\n row.clear();\n }\n const rowSize = this.rowSize;\n const bits = this.bits;\n const offset = y * rowSize;\n for (let x = 0; x < rowSize; x++) {\n row.setBulk(x * 32, bits[offset + x]);\n }\n return row;\n }\n /**\n * @param y row to set\n * @param row {@link BitArray} to copy from\n */\n setRow(y /*int*/, row) {\n System.arraycopy(row.getBitArray(), 0, this.bits, y * this.rowSize, this.rowSize);\n }\n /**\n * Modifies this {@code BitMatrix} to represent the same but rotated 180 degrees\n */\n rotate180() {\n const width = this.getWidth();\n const height = this.getHeight();\n let topRow = new BitArray(width);\n let bottomRow = new BitArray(width);\n for (let i = 0, length = Math.floor((height + 1) / 2); i < length; i++) {\n topRow = this.getRow(i, topRow);\n bottomRow = this.getRow(height - 1 - i, bottomRow);\n topRow.reverse();\n bottomRow.reverse();\n this.setRow(i, bottomRow);\n this.setRow(height - 1 - i, topRow);\n }\n }\n /**\n * This is useful in detecting the enclosing rectangle of a 'pure' barcode.\n *\n * @return {@code left,top,width,height} enclosing rectangle of all 1 bits, or null if it is all white\n */\n getEnclosingRectangle() {\n const width = this.width;\n const height = this.height;\n const rowSize = this.rowSize;\n const bits = this.bits;\n let left = width;\n let top = height;\n let right = -1;\n let bottom = -1;\n for (let y = 0; y < height; y++) {\n for (let x32 = 0; x32 < rowSize; x32++) {\n const theBits = bits[y * rowSize + x32];\n if (theBits !== 0) {\n if (y < top) {\n top = y;\n }\n if (y > bottom) {\n bottom = y;\n }\n if (x32 * 32 < left) {\n let bit = 0;\n while (((theBits << (31 - bit)) & 0xFFFFFFFF) === 0) {\n bit++;\n }\n if ((x32 * 32 + bit) < left) {\n left = x32 * 32 + bit;\n }\n }\n if (x32 * 32 + 31 > right) {\n let bit = 31;\n while ((theBits >>> bit) === 0) {\n bit--;\n }\n if ((x32 * 32 + bit) > right) {\n right = x32 * 32 + bit;\n }\n }\n }\n }\n }\n if (right < left || bottom < top) {\n return null;\n }\n return Int32Array.from([left, top, right - left + 1, bottom - top + 1]);\n }\n /**\n * This is useful in detecting a corner of a 'pure' barcode.\n *\n * @return {@code x,y} coordinate of top-left-most 1 bit, or null if it is all white\n */\n getTopLeftOnBit() {\n const rowSize = this.rowSize;\n const bits = this.bits;\n let bitsOffset = 0;\n while (bitsOffset < bits.length && bits[bitsOffset] === 0) {\n bitsOffset++;\n }\n if (bitsOffset === bits.length) {\n return null;\n }\n const y = bitsOffset / rowSize;\n let x = (bitsOffset % rowSize) * 32;\n const theBits = bits[bitsOffset];\n let bit = 0;\n while (((theBits << (31 - bit)) & 0xFFFFFFFF) === 0) {\n bit++;\n }\n x += bit;\n return Int32Array.from([x, y]);\n }\n getBottomRightOnBit() {\n const rowSize = this.rowSize;\n const bits = this.bits;\n let bitsOffset = bits.length - 1;\n while (bitsOffset >= 0 && bits[bitsOffset] === 0) {\n bitsOffset--;\n }\n if (bitsOffset < 0) {\n return null;\n }\n const y = Math.floor(bitsOffset / rowSize);\n let x = Math.floor(bitsOffset % rowSize) * 32;\n const theBits = bits[bitsOffset];\n let bit = 31;\n while ((theBits >>> bit) === 0) {\n bit--;\n }\n x += bit;\n return Int32Array.from([x, y]);\n }\n /**\n * @return The width of the matrix\n */\n getWidth() {\n return this.width;\n }\n /**\n * @return The height of the matrix\n */\n getHeight() {\n return this.height;\n }\n /**\n * @return The row size of the matrix\n */\n getRowSize() {\n return this.rowSize;\n }\n /*@Override*/\n equals(o) {\n if (!(o instanceof BitMatrix)) {\n return false;\n }\n const other = o;\n return this.width === other.width && this.height === other.height && this.rowSize === other.rowSize &&\n Arrays.equals(this.bits, other.bits);\n }\n /*@Override*/\n hashCode() {\n let hash = this.width;\n hash = 31 * hash + this.width;\n hash = 31 * hash + this.height;\n hash = 31 * hash + this.rowSize;\n hash = 31 * hash + Arrays.hashCode(this.bits);\n return hash;\n }\n /**\n * @return string representation using \"X\" for set and \" \" for unset bits\n */\n /*@Override*/\n // public toString(): string {\n // return toString(\": \"X, \" \")\n // }\n /**\n * @param setString representation of a set bit\n * @param unsetString representation of an unset bit\n * @return string representation of entire matrix utilizing given strings\n */\n // public toString(setString: string = \"X \", unsetString: string = \" \"): string {\n // return this.buildToString(setString, unsetString, \"\\n\")\n // }\n /**\n * @param setString representation of a set bit\n * @param unsetString representation of an unset bit\n * @param lineSeparator newline character in string representation\n * @return string representation of entire matrix utilizing given strings and line separator\n * @deprecated call {@link #toString(String,String)} only, which uses \\n line separator always\n */\n // @Deprecated\n toString(setString = 'X ', unsetString = ' ', lineSeparator = '\\n') {\n return this.buildToString(setString, unsetString, lineSeparator);\n }\n buildToString(setString, unsetString, lineSeparator) {\n let result = new StringBuilder();\n // result.append(lineSeparator);\n for (let y = 0, height = this.height; y < height; y++) {\n for (let x = 0, width = this.width; x < width; x++) {\n result.append(this.get(x, y) ? setString : unsetString);\n }\n result.append(lineSeparator);\n }\n return result.toString();\n }\n /*@Override*/\n clone() {\n return new BitMatrix(this.width, this.height, this.rowSize, this.bits.slice());\n }\n }\n\n /**\n * Custom Error class of type Exception.\n */\n class NotFoundException extends Exception {\n static getNotFoundInstance() {\n return new NotFoundException();\n }\n }\n NotFoundException.kind = 'NotFoundException';\n\n /*\n * Copyright 2009 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n /**\n * This Binarizer implementation uses the old ZXing global histogram approach. It is suitable\n * for low-end mobile devices which don't have enough CPU or memory to use a local thresholding\n * algorithm. However, because it picks a global black point, it cannot handle difficult shadows\n * and gradients.\n *\n * Faster mobile devices and all desktop applications should probably use HybridBinarizer instead.\n *\n * @author dswitkin@google.com (Daniel Switkin)\n * @author Sean Owen\n */\n class GlobalHistogramBinarizer extends Binarizer {\n constructor(source) {\n super(source);\n this.luminances = GlobalHistogramBinarizer.EMPTY;\n this.buckets = new Int32Array(GlobalHistogramBinarizer.LUMINANCE_BUCKETS);\n }\n // Applies simple sharpening to the row data to improve performance of the 1D Readers.\n /*@Override*/\n getBlackRow(y /*int*/, row) {\n const source = this.getLuminanceSource();\n const width = source.getWidth();\n if (row === undefined || row === null || row.getSize() < width) {\n row = new BitArray(width);\n }\n else {\n row.clear();\n }\n this.initArrays(width);\n const localLuminances = source.getRow(y, this.luminances);\n const localBuckets = this.buckets;\n for (let x = 0; x < width; x++) {\n localBuckets[(localLuminances[x] & 0xff) >> GlobalHistogramBinarizer.LUMINANCE_SHIFT]++;\n }\n const blackPoint = GlobalHistogramBinarizer.estimateBlackPoint(localBuckets);\n if (width < 3) {\n // Special case for very small images\n for (let x = 0; x < width; x++) {\n if ((localLuminances[x] & 0xff) < blackPoint) {\n row.set(x);\n }\n }\n }\n else {\n let left = localLuminances[0] & 0xff;\n let center = localLuminances[1] & 0xff;\n for (let x = 1; x < width - 1; x++) {\n const right = localLuminances[x + 1] & 0xff;\n // A simple -1 4 -1 box filter with a weight of 2.\n if (((center * 4) - left - right) / 2 < blackPoint) {\n row.set(x);\n }\n left = center;\n center = right;\n }\n }\n return row;\n }\n // Does not sharpen the data, as this call is intended to only be used by 2D Readers.\n /*@Override*/\n getBlackMatrix() {\n const source = this.getLuminanceSource();\n const width = source.getWidth();\n const height = source.getHeight();\n const matrix = new BitMatrix(width, height);\n // Quickly calculates the histogram by sampling four rows from the image. This proved to be\n // more robust on the blackbox tests than sampling a diagonal as we used to do.\n this.initArrays(width);\n const localBuckets = this.buckets;\n for (let y = 1; y < 5; y++) {\n const row = Math.floor((height * y) / 5);\n const localLuminances = source.getRow(row, this.luminances);\n const right = Math.floor((width * 4) / 5);\n for (let x = Math.floor(width / 5); x < right; x++) {\n const pixel = localLuminances[x] & 0xff;\n localBuckets[pixel >> GlobalHistogramBinarizer.LUMINANCE_SHIFT]++;\n }\n }\n const blackPoint = GlobalHistogramBinarizer.estimateBlackPoint(localBuckets);\n // We delay reading the entire image luminance until the black point estimation succeeds.\n // Although we end up reading four rows twice, it is consistent with our motto of\n // \"fail quickly\" which is necessary for continuous scanning.\n const localLuminances = source.getMatrix();\n for (let y = 0; y < height; y++) {\n const offset = y * width;\n for (let x = 0; x < width; x++) {\n const pixel = localLuminances[offset + x] & 0xff;\n if (pixel < blackPoint) {\n matrix.set(x, y);\n }\n }\n }\n return matrix;\n }\n /*@Override*/\n createBinarizer(source) {\n return new GlobalHistogramBinarizer(source);\n }\n initArrays(luminanceSize /*int*/) {\n if (this.luminances.length < luminanceSize) {\n this.luminances = new Uint8ClampedArray(luminanceSize);\n }\n const buckets = this.buckets;\n for (let x = 0; x < GlobalHistogramBinarizer.LUMINANCE_BUCKETS; x++) {\n buckets[x] = 0;\n }\n }\n static estimateBlackPoint(buckets) {\n // Find the tallest peak in the histogram.\n const numBuckets = buckets.length;\n let maxBucketCount = 0;\n let firstPeak = 0;\n let firstPeakSize = 0;\n for (let x = 0; x < numBuckets; x++) {\n if (buckets[x] > firstPeakSize) {\n firstPeak = x;\n firstPeakSize = buckets[x];\n }\n if (buckets[x] > maxBucketCount) {\n maxBucketCount = buckets[x];\n }\n }\n // Find the second-tallest peak which is somewhat far from the tallest peak.\n let secondPeak = 0;\n let secondPeakScore = 0;\n for (let x = 0; x < numBuckets; x++) {\n const distanceToBiggest = x - firstPeak;\n // Encourage more distant second peaks by multiplying by square of distance.\n const score = buckets[x] * distanceToBiggest * distanceToBiggest;\n if (score > secondPeakScore) {\n secondPeak = x;\n secondPeakScore = score;\n }\n }\n // Make sure firstPeak corresponds to the black peak.\n if (firstPeak > secondPeak) {\n const temp = firstPeak;\n firstPeak = secondPeak;\n secondPeak = temp;\n }\n // If there is too little contrast in the image to pick a meaningful black point, throw rather\n // than waste time trying to decode the image, and risk false positives.\n if (secondPeak - firstPeak <= numBuckets / 16) {\n throw new NotFoundException();\n }\n // Find a valley between them that is low and closer to the white peak.\n let bestValley = secondPeak - 1;\n let bestValleyScore = -1;\n for (let x = secondPeak - 1; x > firstPeak; x--) {\n const fromFirst = x - firstPeak;\n const score = fromFirst * fromFirst * (secondPeak - x) * (maxBucketCount - buckets[x]);\n if (score > bestValleyScore) {\n bestValley = x;\n bestValleyScore = score;\n }\n }\n return bestValley << GlobalHistogramBinarizer.LUMINANCE_SHIFT;\n }\n }\n GlobalHistogramBinarizer.LUMINANCE_BITS = 5;\n GlobalHistogramBinarizer.LUMINANCE_SHIFT = 8 - GlobalHistogramBinarizer.LUMINANCE_BITS;\n GlobalHistogramBinarizer.LUMINANCE_BUCKETS = 1 << GlobalHistogramBinarizer.LUMINANCE_BITS;\n GlobalHistogramBinarizer.EMPTY = Uint8ClampedArray.from([0]);\n\n /*\n * Copyright 2009 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n /**\n * This class implements a local thresholding algorithm, which while slower than the\n * GlobalHistogramBinarizer, is fairly efficient for what it does. It is designed for\n * high frequency images of barcodes with black data on white backgrounds. For this application,\n * it does a much better job than a global blackpoint with severe shadows and gradients.\n * However it tends to produce artifacts on lower frequency images and is therefore not\n * a good general purpose binarizer for uses outside ZXing.\n *\n * This class extends GlobalHistogramBinarizer, using the older histogram approach for 1D readers,\n * and the newer local approach for 2D readers. 1D decoding using a per-row histogram is already\n * inherently local, and only fails for horizontal gradients. We can revisit that problem later,\n * but for now it was not a win to use local blocks for 1D.\n *\n * This Binarizer is the default for the unit tests and the recommended class for library users.\n *\n * @author dswitkin@google.com (Daniel Switkin)\n */\n class HybridBinarizer extends GlobalHistogramBinarizer {\n constructor(source) {\n super(source);\n this.matrix = null;\n }\n /**\n * Calculates the final BitMatrix once for all requests. This could be called once from the\n * constructor instead, but there are some advantages to doing it lazily, such as making\n * profiling easier, and not doing heavy lifting when callers don't expect it.\n */\n /*@Override*/\n getBlackMatrix() {\n if (this.matrix !== null) {\n return this.matrix;\n }\n const source = this.getLuminanceSource();\n const width = source.getWidth();\n const height = source.getHeight();\n if (width >= HybridBinarizer.MINIMUM_DIMENSION && height >= HybridBinarizer.MINIMUM_DIMENSION) {\n const luminances = source.getMatrix();\n let subWidth = width >> HybridBinarizer.BLOCK_SIZE_POWER;\n if ((width & HybridBinarizer.BLOCK_SIZE_MASK) !== 0) {\n subWidth++;\n }\n let subHeight = height >> HybridBinarizer.BLOCK_SIZE_POWER;\n if ((height & HybridBinarizer.BLOCK_SIZE_MASK) !== 0) {\n subHeight++;\n }\n const blackPoints = HybridBinarizer.calculateBlackPoints(luminances, subWidth, subHeight, width, height);\n const newMatrix = new BitMatrix(width, height);\n HybridBinarizer.calculateThresholdForBlock(luminances, subWidth, subHeight, width, height, blackPoints, newMatrix);\n this.matrix = newMatrix;\n }\n else {\n // If the image is too small, fall back to the global histogram approach.\n this.matrix = super.getBlackMatrix();\n }\n return this.matrix;\n }\n /*@Override*/\n createBinarizer(source) {\n return new HybridBinarizer(source);\n }\n /**\n * For each block in the image, calculate the average black point using a 5x5 grid\n * of the blocks around it. Also handles the corner cases (fractional blocks are computed based\n * on the last pixels in the row/column which are also used in the previous block).\n */\n static calculateThresholdForBlock(luminances, subWidth /*int*/, subHeight /*int*/, width /*int*/, height /*int*/, blackPoints, matrix) {\n const maxYOffset = height - HybridBinarizer.BLOCK_SIZE;\n const maxXOffset = width - HybridBinarizer.BLOCK_SIZE;\n for (let y = 0; y < subHeight; y++) {\n let yoffset = y << HybridBinarizer.BLOCK_SIZE_POWER;\n if (yoffset > maxYOffset) {\n yoffset = maxYOffset;\n }\n const top = HybridBinarizer.cap(y, 2, subHeight - 3);\n for (let x = 0; x < subWidth; x++) {\n let xoffset = x << HybridBinarizer.BLOCK_SIZE_POWER;\n if (xoffset > maxXOffset) {\n xoffset = maxXOffset;\n }\n const left = HybridBinarizer.cap(x, 2, subWidth - 3);\n let sum = 0;\n for (let z = -2; z <= 2; z++) {\n const blackRow = blackPoints[top + z];\n sum += blackRow[left - 2] + blackRow[left - 1] + blackRow[left] + blackRow[left + 1] + blackRow[left + 2];\n }\n const average = sum / 25;\n HybridBinarizer.thresholdBlock(luminances, xoffset, yoffset, average, width, matrix);\n }\n }\n }\n static cap(value /*int*/, min /*int*/, max /*int*/) {\n return value < min ? min : value > max ? max : value;\n }\n /**\n * Applies a single threshold to a block of pixels.\n */\n static thresholdBlock(luminances, xoffset /*int*/, yoffset /*int*/, threshold /*int*/, stride /*int*/, matrix) {\n for (let y = 0, offset = yoffset * stride + xoffset; y < HybridBinarizer.BLOCK_SIZE; y++, offset += stride) {\n for (let x = 0; x < HybridBinarizer.BLOCK_SIZE; x++) {\n // Comparison needs to be <= so that black == 0 pixels are black even if the threshold is 0.\n if ((luminances[offset + x] & 0xFF) <= threshold) {\n matrix.set(xoffset + x, yoffset + y);\n }\n }\n }\n }\n /**\n * Calculates a single black point for each block of pixels and saves it away.\n * See the following thread for a discussion of this algorithm:\n * http://groups.google.com/group/zxing/browse_thread/thread/d06efa2c35a7ddc0\n */\n static calculateBlackPoints(luminances, subWidth /*int*/, subHeight /*int*/, width /*int*/, height /*int*/) {\n const maxYOffset = height - HybridBinarizer.BLOCK_SIZE;\n const maxXOffset = width - HybridBinarizer.BLOCK_SIZE;\n // tslint:disable-next-line:whitespace\n const blackPoints = new Array(subHeight); // subWidth\n for (let y = 0; y < subHeight; y++) {\n blackPoints[y] = new Int32Array(subWidth);\n let yoffset = y << HybridBinarizer.BLOCK_SIZE_POWER;\n if (yoffset > maxYOffset) {\n yoffset = maxYOffset;\n }\n for (let x = 0; x < subWidth; x++) {\n let xoffset = x << HybridBinarizer.BLOCK_SIZE_POWER;\n if (xoffset > maxXOffset) {\n xoffset = maxXOffset;\n }\n let sum = 0;\n let min = 0xFF;\n let max = 0;\n for (let yy = 0, offset = yoffset * width + xoffset; yy < HybridBinarizer.BLOCK_SIZE; yy++, offset += width) {\n for (let xx = 0; xx < HybridBinarizer.BLOCK_SIZE; xx++) {\n const pixel = luminances[offset + xx] & 0xFF;\n sum += pixel;\n // still looking for good contrast\n if (pixel < min) {\n min = pixel;\n }\n if (pixel > max) {\n max = pixel;\n }\n }\n // short-circuit min/max tests once dynamic range is met\n if (max - min > HybridBinarizer.MIN_DYNAMIC_RANGE) {\n // finish the rest of the rows quickly\n for (yy++, offset += width; yy < HybridBinarizer.BLOCK_SIZE; yy++, offset += width) {\n for (let xx = 0; xx < HybridBinarizer.BLOCK_SIZE; xx++) {\n sum += luminances[offset + xx] & 0xFF;\n }\n }\n }\n }\n // The default estimate is the average of the values in the block.\n let average = sum >> (HybridBinarizer.BLOCK_SIZE_POWER * 2);\n if (max - min <= HybridBinarizer.MIN_DYNAMIC_RANGE) {\n // If variation within the block is low, assume this is a block with only light or only\n // dark pixels. In that case we do not want to use the average, as it would divide this\n // low contrast area into black and white pixels, essentially creating data out of noise.\n //\n // The default assumption is that the block is light/background. Since no estimate for\n // the level of dark pixels exists locally, use half the min for the block.\n average = min / 2;\n if (y > 0 && x > 0) {\n // Correct the \"white background\" assumption for blocks that have neighbors by comparing\n // the pixels in this block to the previously calculated black points. This is based on\n // the fact that dark barcode symbology is always surrounded by some amount of light\n // background for which reasonable black point estimates were made. The bp estimated at\n // the boundaries is used for the interior.\n // The (min < bp) is arbitrary but works better than other heuristics that were tried.\n const averageNeighborBlackPoint = (blackPoints[y - 1][x] + (2 * blackPoints[y][x - 1]) + blackPoints[y - 1][x - 1]) / 4;\n if (min < averageNeighborBlackPoint) {\n average = averageNeighborBlackPoint;\n }\n }\n }\n blackPoints[y][x] = average;\n }\n }\n return blackPoints;\n }\n }\n // This class uses 5x5 blocks to compute local luminance, where each block is 8x8 pixels.\n // So this is the smallest dimension in each axis we can accept.\n HybridBinarizer.BLOCK_SIZE_POWER = 3;\n HybridBinarizer.BLOCK_SIZE = 1 << HybridBinarizer.BLOCK_SIZE_POWER; // ...0100...00\n HybridBinarizer.BLOCK_SIZE_MASK = HybridBinarizer.BLOCK_SIZE - 1; // ...0011...11\n HybridBinarizer.MINIMUM_DIMENSION = HybridBinarizer.BLOCK_SIZE * 5;\n HybridBinarizer.MIN_DYNAMIC_RANGE = 24;\n\n /*\n * Copyright 2009 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n /*namespace com.google.zxing {*/\n /**\n * The purpose of this class hierarchy is to abstract different bitmap implementations across\n * platforms into a standard interface for requesting greyscale luminance values. The interface\n * only provides immutable methods; therefore crop and rotation create copies. This is to ensure\n * that one Reader does not modify the original luminance source and leave it in an unknown state\n * for other Readers in the chain.\n *\n * @author dswitkin@google.com (Daniel Switkin)\n */\n class LuminanceSource {\n constructor(width /*int*/, height /*int*/) {\n this.width = width;\n this.height = height;\n }\n /**\n * @return The width of the bitmap.\n */\n getWidth() {\n return this.width;\n }\n /**\n * @return The height of the bitmap.\n */\n getHeight() {\n return this.height;\n }\n /**\n * @return Whether this subclass supports cropping.\n */\n isCropSupported() {\n return false;\n }\n /**\n * Returns a new object with cropped image data. Implementations may keep a reference to the\n * original data rather than a copy. Only callable if isCropSupported() is true.\n *\n * @param left The left coordinate, which must be in [0,getWidth())\n * @param top The top coordinate, which must be in [0,getHeight())\n * @param width The width of the rectangle to crop.\n * @param height The height of the rectangle to crop.\n * @return A cropped version of this object.\n */\n crop(left /*int*/, top /*int*/, width /*int*/, height /*int*/) {\n throw new UnsupportedOperationException('This luminance source does not support cropping.');\n }\n /**\n * @return Whether this subclass supports counter-clockwise rotation.\n */\n isRotateSupported() {\n return false;\n }\n /**\n * Returns a new object with rotated image data by 90 degrees counterclockwise.\n * Only callable if {@link #isRotateSupported()} is true.\n *\n * @return A rotated version of this object.\n */\n rotateCounterClockwise() {\n throw new UnsupportedOperationException('This luminance source does not support rotation by 90 degrees.');\n }\n /**\n * Returns a new object with rotated image data by 45 degrees counterclockwise.\n * Only callable if {@link #isRotateSupported()} is true.\n *\n * @return A rotated version of this object.\n */\n rotateCounterClockwise45() {\n throw new UnsupportedOperationException('This luminance source does not support rotation by 45 degrees.');\n }\n /*@Override*/\n toString() {\n const row = new Uint8ClampedArray(this.width);\n let result = new StringBuilder();\n for (let y = 0; y < this.height; y++) {\n const sourceRow = this.getRow(y, row);\n for (let x = 0; x < this.width; x++) {\n const luminance = sourceRow[x] & 0xFF;\n let c;\n if (luminance < 0x40) {\n c = '#';\n }\n else if (luminance < 0x80) {\n c = '+';\n }\n else if (luminance < 0xC0) {\n c = '.';\n }\n else {\n c = ' ';\n }\n result.append(c);\n }\n result.append('\\n');\n }\n return result.toString();\n }\n }\n\n /*\n * Copyright 2009 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n /*namespace com.google.zxing {*/\n /**\n * A wrapper implementation of {@link LuminanceSource} which inverts the luminances it returns -- black becomes\n * white and vice versa, and each value becomes (255-value).\n *\n * @author Sean Owen\n */\n class InvertedLuminanceSource extends LuminanceSource {\n constructor(delegate) {\n super(delegate.getWidth(), delegate.getHeight());\n this.delegate = delegate;\n }\n /*@Override*/\n getRow(y /*int*/, row) {\n const sourceRow = this.delegate.getRow(y, row);\n const width = this.getWidth();\n for (let i = 0; i < width; i++) {\n sourceRow[i] = /*(byte)*/ (255 - (sourceRow[i] & 0xFF));\n }\n return sourceRow;\n }\n /*@Override*/\n getMatrix() {\n const matrix = this.delegate.getMatrix();\n const length = this.getWidth() * this.getHeight();\n const invertedMatrix = new Uint8ClampedArray(length);\n for (let i = 0; i < length; i++) {\n invertedMatrix[i] = /*(byte)*/ (255 - (matrix[i] & 0xFF));\n }\n return invertedMatrix;\n }\n /*@Override*/\n isCropSupported() {\n return this.delegate.isCropSupported();\n }\n /*@Override*/\n crop(left /*int*/, top /*int*/, width /*int*/, height /*int*/) {\n return new InvertedLuminanceSource(this.delegate.crop(left, top, width, height));\n }\n /*@Override*/\n isRotateSupported() {\n return this.delegate.isRotateSupported();\n }\n /**\n * @return original delegate {@link LuminanceSource} since invert undoes itself\n */\n /*@Override*/\n invert() {\n return this.delegate;\n }\n /*@Override*/\n rotateCounterClockwise() {\n return new InvertedLuminanceSource(this.delegate.rotateCounterClockwise());\n }\n /*@Override*/\n rotateCounterClockwise45() {\n return new InvertedLuminanceSource(this.delegate.rotateCounterClockwise45());\n }\n }\n\n /**\n * @deprecated Moving to @zxing/browser\n */\n class HTMLCanvasElementLuminanceSource extends LuminanceSource {\n constructor(canvas) {\n super(canvas.width, canvas.height);\n this.canvas = canvas;\n this.tempCanvasElement = null;\n this.buffer = HTMLCanvasElementLuminanceSource.makeBufferFromCanvasImageData(canvas);\n }\n static makeBufferFromCanvasImageData(canvas) {\n const imageData = canvas.getContext('2d').getImageData(0, 0, canvas.width, canvas.height);\n return HTMLCanvasElementLuminanceSource.toGrayscaleBuffer(imageData.data, canvas.width, canvas.height);\n }\n static toGrayscaleBuffer(imageBuffer, width, height) {\n const grayscaleBuffer = new Uint8ClampedArray(width * height);\n for (let i = 0, j = 0, length = imageBuffer.length; i < length; i += 4, j++) {\n let gray;\n const alpha = imageBuffer[i + 3];\n // The color of fully-transparent pixels is irrelevant. They are often, technically, fully-transparent\n // black (0 alpha, and then 0 RGB). They are often used, of course as the \"white\" area in a\n // barcode image. Force any such pixel to be white:\n if (alpha === 0) {\n gray = 0xFF;\n }\n else {\n const pixelR = imageBuffer[i];\n const pixelG = imageBuffer[i + 1];\n const pixelB = imageBuffer[i + 2];\n // .299R + 0.587G + 0.114B (YUV/YIQ for PAL and NTSC),\n // (306*R) >> 10 is approximately equal to R*0.299, and so on.\n // 0x200 >> 10 is 0.5, it implements rounding.\n gray = (306 * pixelR +\n 601 * pixelG +\n 117 * pixelB +\n 0x200) >> 10;\n }\n grayscaleBuffer[j] = gray;\n }\n return grayscaleBuffer;\n }\n getRow(y /*int*/, row) {\n if (y < 0 || y >= this.getHeight()) {\n throw new IllegalArgumentException('Requested row is outside the image: ' + y);\n }\n const width = this.getWidth();\n const start = y * width;\n if (row === null) {\n row = this.buffer.slice(start, start + width);\n }\n else {\n if (row.length < width) {\n row = new Uint8ClampedArray(width);\n }\n // The underlying raster of image consists of bytes with the luminance values\n // TODO: can avoid set/slice?\n row.set(this.buffer.slice(start, start + width));\n }\n return row;\n }\n getMatrix() {\n return this.buffer;\n }\n isCropSupported() {\n return true;\n }\n crop(left /*int*/, top /*int*/, width /*int*/, height /*int*/) {\n super.crop(left, top, width, height);\n return this;\n }\n /**\n * This is always true, since the image is a gray-scale image.\n *\n * @return true\n */\n isRotateSupported() {\n return true;\n }\n rotateCounterClockwise() {\n this.rotate(-90);\n return this;\n }\n rotateCounterClockwise45() {\n this.rotate(-45);\n return this;\n }\n getTempCanvasElement() {\n if (null === this.tempCanvasElement) {\n const tempCanvasElement = this.canvas.ownerDocument.createElement('canvas');\n tempCanvasElement.width = this.canvas.width;\n tempCanvasElement.height = this.canvas.height;\n this.tempCanvasElement = tempCanvasElement;\n }\n return this.tempCanvasElement;\n }\n rotate(angle) {\n const tempCanvasElement = this.getTempCanvasElement();\n const tempContext = tempCanvasElement.getContext('2d');\n const angleRadians = angle * HTMLCanvasElementLuminanceSource.DEGREE_TO_RADIANS;\n // Calculate and set new dimensions for temp canvas\n const width = this.canvas.width;\n const height = this.canvas.height;\n const newWidth = Math.ceil(Math.abs(Math.cos(angleRadians)) * width + Math.abs(Math.sin(angleRadians)) * height);\n const newHeight = Math.ceil(Math.abs(Math.sin(angleRadians)) * width + Math.abs(Math.cos(angleRadians)) * height);\n tempCanvasElement.width = newWidth;\n tempCanvasElement.height = newHeight;\n // Draw at center of temp canvas to prevent clipping of image data\n tempContext.translate(newWidth / 2, newHeight / 2);\n tempContext.rotate(angleRadians);\n tempContext.drawImage(this.canvas, width / -2, height / -2);\n this.buffer = HTMLCanvasElementLuminanceSource.makeBufferFromCanvasImageData(tempCanvasElement);\n return this;\n }\n invert() {\n return new InvertedLuminanceSource(this);\n }\n }\n HTMLCanvasElementLuminanceSource.DEGREE_TO_RADIANS = Math.PI / 180;\n\n /**\n * @deprecated Moving to @zxing/browser\n *\n * Video input device metadata containing the id and label of the device if available.\n */\n class VideoInputDevice {\n /**\n * Creates an instance of VideoInputDevice.\n *\n * @param {string} deviceId the video input device id\n * @param {string} label the label of the device if available\n */\n constructor(deviceId, label, groupId) {\n this.deviceId = deviceId;\n this.label = label;\n /** @inheritdoc */\n this.kind = 'videoinput';\n this.groupId = groupId || undefined;\n }\n /** @inheritdoc */\n toJSON() {\n return {\n kind: this.kind,\n groupId: this.groupId,\n deviceId: this.deviceId,\n label: this.label,\n };\n }\n }\n\n var __awaiter = ((globalThis || global || self || window || undefined) && (globalThis || global || self || window || undefined).__awaiter) || function (thisArg, _arguments, P, generator) {\n function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }\n return new (P || (P = Promise))(function (resolve, reject) {\n function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\n function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\n function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }\n step((generator = generator.apply(thisArg, _arguments || [])).next());\n });\n };\n /**\n * @deprecated Moving to @zxing/browser\n *\n * Base class for browser code reader.\n */\n class BrowserCodeReader {\n /**\n * Creates an instance of BrowserCodeReader.\n * @param {Reader} reader The reader instance to decode the barcode\n * @param {number} [timeBetweenScansMillis=500] the time delay between subsequent successful decode tries\n *\n * @memberOf BrowserCodeReader\n */\n constructor(reader, timeBetweenScansMillis = 500, _hints) {\n this.reader = reader;\n this.timeBetweenScansMillis = timeBetweenScansMillis;\n this._hints = _hints;\n /**\n * This will break the loop.\n */\n this._stopContinuousDecode = false;\n /**\n * This will break the loop.\n */\n this._stopAsyncDecode = false;\n /**\n * Delay time between decode attempts made by the scanner.\n */\n this._timeBetweenDecodingAttempts = 0;\n }\n /**\n * If navigator is present.\n */\n get hasNavigator() {\n return typeof navigator !== 'undefined';\n }\n /**\n * If mediaDevices under navigator is supported.\n */\n get isMediaDevicesSuported() {\n return this.hasNavigator && !!navigator.mediaDevices;\n }\n /**\n * If enumerateDevices under navigator is supported.\n */\n get canEnumerateDevices() {\n return !!(this.isMediaDevicesSuported && navigator.mediaDevices.enumerateDevices);\n }\n /** Time between two decoding tries in milli seconds. */\n get timeBetweenDecodingAttempts() {\n return this._timeBetweenDecodingAttempts;\n }\n /**\n * Change the time span the decoder waits between two decoding tries.\n *\n * @param {number} millis Time between two decoding tries in milli seconds.\n */\n set timeBetweenDecodingAttempts(millis) {\n this._timeBetweenDecodingAttempts = millis < 0 ? 0 : millis;\n }\n /**\n * Sets the hints.\n */\n set hints(hints) {\n this._hints = hints || null;\n }\n /**\n * Sets the hints.\n */\n get hints() {\n return this._hints;\n }\n /**\n * Lists all the available video input devices.\n */\n listVideoInputDevices() {\n return __awaiter(this, void 0, void 0, function* () {\n if (!this.hasNavigator) {\n throw new Error('Can\\'t enumerate devices, navigator is not present.');\n }\n if (!this.canEnumerateDevices) {\n throw new Error('Can\\'t enumerate devices, method not supported.');\n }\n const devices = yield navigator.mediaDevices.enumerateDevices();\n const videoDevices = [];\n for (const device of devices) {\n const kind = device.kind === 'video' ? 'videoinput' : device.kind;\n if (kind !== 'videoinput') {\n continue;\n }\n const deviceId = device.deviceId || device.id;\n const label = device.label || `Video device ${videoDevices.length + 1}`;\n const groupId = device.groupId;\n const videoDevice = { deviceId, label, kind, groupId };\n videoDevices.push(videoDevice);\n }\n return videoDevices;\n });\n }\n /**\n * Obtain the list of available devices with type 'videoinput'.\n *\n * @returns {Promise} an array of available video input devices\n *\n * @memberOf BrowserCodeReader\n *\n * @deprecated Use `listVideoInputDevices` instead.\n */\n getVideoInputDevices() {\n return __awaiter(this, void 0, void 0, function* () {\n const devices = yield this.listVideoInputDevices();\n return devices.map(d => new VideoInputDevice(d.deviceId, d.label));\n });\n }\n /**\n * Let's you find a device using it's Id.\n */\n findDeviceById(deviceId) {\n return __awaiter(this, void 0, void 0, function* () {\n const devices = yield this.listVideoInputDevices();\n if (!devices) {\n return null;\n }\n return devices.find(x => x.deviceId === deviceId);\n });\n }\n /**\n * Decodes the barcode from the device specified by deviceId while showing the video in the specified video element.\n *\n * @param deviceId the id of one of the devices obtained after calling getVideoInputDevices. Can be undefined, in this case it will decode from one of the available devices, preffering the main camera (environment facing) if available.\n * @param video the video element in page where to show the video while decoding. Can be either an element id or directly an HTMLVideoElement. Can be undefined, in which case no video will be shown.\n * @returns The decoding result.\n *\n * @memberOf BrowserCodeReader\n *\n * @deprecated Use `decodeOnceFromVideoDevice` instead.\n */\n decodeFromInputVideoDevice(deviceId, videoSource) {\n return __awaiter(this, void 0, void 0, function* () {\n return yield this.decodeOnceFromVideoDevice(deviceId, videoSource);\n });\n }\n /**\n * In one attempt, tries to decode the barcode from the device specified by deviceId while showing the video in the specified video element.\n *\n * @param deviceId the id of one of the devices obtained after calling getVideoInputDevices. Can be undefined, in this case it will decode from one of the available devices, preffering the main camera (environment facing) if available.\n * @param video the video element in page where to show the video while decoding. Can be either an element id or directly an HTMLVideoElement. Can be undefined, in which case no video will be shown.\n * @returns The decoding result.\n *\n * @memberOf BrowserCodeReader\n */\n decodeOnceFromVideoDevice(deviceId, videoSource) {\n return __awaiter(this, void 0, void 0, function* () {\n this.reset();\n let videoConstraints;\n if (!deviceId) {\n videoConstraints = { facingMode: 'environment' };\n }\n else {\n videoConstraints = { deviceId: { exact: deviceId } };\n }\n const constraints = { video: videoConstraints };\n return yield this.decodeOnceFromConstraints(constraints, videoSource);\n });\n }\n /**\n * In one attempt, tries to decode the barcode from a stream obtained from the given constraints while showing the video in the specified video element.\n *\n * @param constraints the media stream constraints to get s valid media stream to decode from\n * @param video the video element in page where to show the video while decoding. Can be either an element id or directly an HTMLVideoElement. Can be undefined, in which case no video will be shown.\n * @returns The decoding result.\n *\n * @memberOf BrowserCodeReader\n */\n decodeOnceFromConstraints(constraints, videoSource) {\n return __awaiter(this, void 0, void 0, function* () {\n const stream = yield navigator.mediaDevices.getUserMedia(constraints);\n return yield this.decodeOnceFromStream(stream, videoSource);\n });\n }\n /**\n * In one attempt, tries to decode the barcode from a stream obtained from the given constraints while showing the video in the specified video element.\n *\n * @param {MediaStream} [constraints] the media stream constraints to get s valid media stream to decode from\n * @param {string|HTMLVideoElement} [video] the video element in page where to show the video while decoding. Can be either an element id or directly an HTMLVideoElement. Can be undefined, in which case no video will be shown.\n * @returns {Promise} The decoding result.\n *\n * @memberOf BrowserCodeReader\n */\n decodeOnceFromStream(stream, videoSource) {\n return __awaiter(this, void 0, void 0, function* () {\n this.reset();\n const video = yield this.attachStreamToVideo(stream, videoSource);\n const result = yield this.decodeOnce(video);\n return result;\n });\n }\n /**\n * Continuously decodes the barcode from the device specified by device while showing the video in the specified video element.\n *\n * @param {string|null} [deviceId] the id of one of the devices obtained after calling getVideoInputDevices. Can be undefined, in this case it will decode from one of the available devices, preffering the main camera (environment facing) if available.\n * @param {string|HTMLVideoElement|null} [video] the video element in page where to show the video while decoding. Can be either an element id or directly an HTMLVideoElement. Can be undefined, in which case no video will be shown.\n * @returns {Promise}\n *\n * @memberOf BrowserCodeReader\n *\n * @deprecated Use `decodeFromVideoDevice` instead.\n */\n decodeFromInputVideoDeviceContinuously(deviceId, videoSource, callbackFn) {\n return __awaiter(this, void 0, void 0, function* () {\n return yield this.decodeFromVideoDevice(deviceId, videoSource, callbackFn);\n });\n }\n /**\n * Continuously tries to decode the barcode from the device specified by device while showing the video in the specified video element.\n *\n * @param {string|null} [deviceId] the id of one of the devices obtained after calling getVideoInputDevices. Can be undefined, in this case it will decode from one of the available devices, preffering the main camera (environment facing) if available.\n * @param {string|HTMLVideoElement|null} [video] the video element in page where to show the video while decoding. Can be either an element id or directly an HTMLVideoElement. Can be undefined, in which case no video will be shown.\n * @returns {Promise}\n *\n * @memberOf BrowserCodeReader\n */\n decodeFromVideoDevice(deviceId, videoSource, callbackFn) {\n return __awaiter(this, void 0, void 0, function* () {\n let videoConstraints;\n if (!deviceId) {\n videoConstraints = { facingMode: 'environment' };\n }\n else {\n videoConstraints = { deviceId: { exact: deviceId } };\n }\n const constraints = { video: videoConstraints };\n return yield this.decodeFromConstraints(constraints, videoSource, callbackFn);\n });\n }\n /**\n * Continuously tries to decode the barcode from a stream obtained from the given constraints while showing the video in the specified video element.\n *\n * @param {MediaStream} [constraints] the media stream constraints to get s valid media stream to decode from\n * @param {string|HTMLVideoElement} [video] the video element in page where to show the video while decoding. Can be either an element id or directly an HTMLVideoElement. Can be undefined, in which case no video will be shown.\n * @returns {Promise} The decoding result.\n *\n * @memberOf BrowserCodeReader\n */\n decodeFromConstraints(constraints, videoSource, callbackFn) {\n return __awaiter(this, void 0, void 0, function* () {\n const stream = yield navigator.mediaDevices.getUserMedia(constraints);\n return yield this.decodeFromStream(stream, videoSource, callbackFn);\n });\n }\n /**\n * In one attempt, tries to decode the barcode from a stream obtained from the given constraints while showing the video in the specified video element.\n *\n * @param {MediaStream} [constraints] the media stream constraints to get s valid media stream to decode from\n * @param {string|HTMLVideoElement} [video] the video element in page where to show the video while decoding. Can be either an element id or directly an HTMLVideoElement. Can be undefined, in which case no video will be shown.\n * @returns {Promise} The decoding result.\n *\n * @memberOf BrowserCodeReader\n */\n decodeFromStream(stream, videoSource, callbackFn) {\n return __awaiter(this, void 0, void 0, function* () {\n this.reset();\n const video = yield this.attachStreamToVideo(stream, videoSource);\n return yield this.decodeContinuously(video, callbackFn);\n });\n }\n /**\n * Breaks the decoding loop.\n */\n stopAsyncDecode() {\n this._stopAsyncDecode = true;\n }\n /**\n * Breaks the decoding loop.\n */\n stopContinuousDecode() {\n this._stopContinuousDecode = true;\n }\n /**\n * Sets the new stream and request a new decoding-with-delay.\n *\n * @param stream The stream to be shown in the video element.\n * @param decodeFn A callback for the decode method.\n */\n attachStreamToVideo(stream, videoSource) {\n return __awaiter(this, void 0, void 0, function* () {\n const videoElement = this.prepareVideoElement(videoSource);\n this.addVideoSource(videoElement, stream);\n this.videoElement = videoElement;\n this.stream = stream;\n yield this.playVideoOnLoadAsync(videoElement);\n return videoElement;\n });\n }\n /**\n *\n * @param videoElement\n */\n playVideoOnLoadAsync(videoElement) {\n return new Promise((resolve, reject) => this.playVideoOnLoad(videoElement, () => resolve()));\n }\n /**\n * Binds listeners and callbacks to the videoElement.\n *\n * @param element\n * @param callbackFn\n */\n playVideoOnLoad(element, callbackFn) {\n this.videoEndedListener = () => this.stopStreams();\n this.videoCanPlayListener = () => this.tryPlayVideo(element);\n element.addEventListener('ended', this.videoEndedListener);\n element.addEventListener('canplay', this.videoCanPlayListener);\n element.addEventListener('playing', callbackFn);\n // if canplay was already fired, we won't know when to play, so just give it a try\n this.tryPlayVideo(element);\n }\n /**\n * Checks if the given video element is currently playing.\n */\n isVideoPlaying(video) {\n return video.currentTime > 0 && !video.paused && !video.ended && video.readyState > 2;\n }\n /**\n * Just tries to play the video and logs any errors.\n * The play call is only made is the video is not already playing.\n */\n tryPlayVideo(videoElement) {\n return __awaiter(this, void 0, void 0, function* () {\n if (this.isVideoPlaying(videoElement)) {\n console.warn('Trying to play video that is already playing.');\n return;\n }\n try {\n yield videoElement.play();\n }\n catch (_a) {\n console.warn('It was not possible to play the video.');\n }\n });\n }\n /**\n * Searches and validates a media element.\n */\n getMediaElement(mediaElementId, type) {\n const mediaElement = document.getElementById(mediaElementId);\n if (!mediaElement) {\n throw new ArgumentException(`element with id '${mediaElementId}' not found`);\n }\n if (mediaElement.nodeName.toLowerCase() !== type.toLowerCase()) {\n throw new ArgumentException(`element with id '${mediaElementId}' must be an ${type} element`);\n }\n return mediaElement;\n }\n /**\n * Decodes the barcode from an image.\n *\n * @param {(string|HTMLImageElement)} [source] The image element that can be either an element id or the element itself. Can be undefined in which case the decoding will be done from the imageUrl parameter.\n * @param {string} [url]\n * @returns {Promise} The decoding result.\n *\n * @memberOf BrowserCodeReader\n */\n decodeFromImage(source, url) {\n if (!source && !url) {\n throw new ArgumentException('either imageElement with a src set or an url must be provided');\n }\n if (url && !source) {\n return this.decodeFromImageUrl(url);\n }\n return this.decodeFromImageElement(source);\n }\n /**\n * Decodes the barcode from a video.\n *\n * @param {(string|HTMLImageElement)} [source] The image element that can be either an element id or the element itself. Can be undefined in which case the decoding will be done from the imageUrl parameter.\n * @param {string} [url]\n * @returns {Promise} The decoding result.\n *\n * @memberOf BrowserCodeReader\n */\n decodeFromVideo(source, url) {\n if (!source && !url) {\n throw new ArgumentException('Either an element with a src set or an URL must be provided');\n }\n if (url && !source) {\n return this.decodeFromVideoUrl(url);\n }\n return this.decodeFromVideoElement(source);\n }\n /**\n * Decodes continuously the barcode from a video.\n *\n * @param {(string|HTMLImageElement)} [source] The image element that can be either an element id or the element itself. Can be undefined in which case the decoding will be done from the imageUrl parameter.\n * @param {string} [url]\n * @returns {Promise} The decoding result.\n *\n * @memberOf BrowserCodeReader\n *\n * @experimental\n */\n decodeFromVideoContinuously(source, url, callbackFn) {\n if (undefined === source && undefined === url) {\n throw new ArgumentException('Either an element with a src set or an URL must be provided');\n }\n if (url && !source) {\n return this.decodeFromVideoUrlContinuously(url, callbackFn);\n }\n return this.decodeFromVideoElementContinuously(source, callbackFn);\n }\n /**\n * Decodes something from an image HTML element.\n */\n decodeFromImageElement(source) {\n if (!source) {\n throw new ArgumentException('An image element must be provided.');\n }\n this.reset();\n const element = this.prepareImageElement(source);\n this.imageElement = element;\n let task;\n if (this.isImageLoaded(element)) {\n task = this.decodeOnce(element, false, true);\n }\n else {\n task = this._decodeOnLoadImage(element);\n }\n return task;\n }\n /**\n * Decodes something from an image HTML element.\n */\n decodeFromVideoElement(source) {\n const element = this._decodeFromVideoElementSetup(source);\n return this._decodeOnLoadVideo(element);\n }\n /**\n * Decodes something from an image HTML element.\n */\n decodeFromVideoElementContinuously(source, callbackFn) {\n const element = this._decodeFromVideoElementSetup(source);\n return this._decodeOnLoadVideoContinuously(element, callbackFn);\n }\n /**\n * Sets up the video source so it can be decoded when loaded.\n *\n * @param source The video source element.\n */\n _decodeFromVideoElementSetup(source) {\n if (!source) {\n throw new ArgumentException('A video element must be provided.');\n }\n this.reset();\n const element = this.prepareVideoElement(source);\n // defines the video element before starts decoding\n this.videoElement = element;\n return element;\n }\n /**\n * Decodes an image from a URL.\n */\n decodeFromImageUrl(url) {\n if (!url) {\n throw new ArgumentException('An URL must be provided.');\n }\n this.reset();\n const element = this.prepareImageElement();\n this.imageElement = element;\n const decodeTask = this._decodeOnLoadImage(element);\n element.src = url;\n return decodeTask;\n }\n /**\n * Decodes an image from a URL.\n */\n decodeFromVideoUrl(url) {\n if (!url) {\n throw new ArgumentException('An URL must be provided.');\n }\n this.reset();\n // creates a new element\n const element = this.prepareVideoElement();\n const decodeTask = this.decodeFromVideoElement(element);\n element.src = url;\n return decodeTask;\n }\n /**\n * Decodes an image from a URL.\n *\n * @experimental\n */\n decodeFromVideoUrlContinuously(url, callbackFn) {\n if (!url) {\n throw new ArgumentException('An URL must be provided.');\n }\n this.reset();\n // creates a new element\n const element = this.prepareVideoElement();\n const decodeTask = this.decodeFromVideoElementContinuously(element, callbackFn);\n element.src = url;\n return decodeTask;\n }\n _decodeOnLoadImage(element) {\n return new Promise((resolve, reject) => {\n this.imageLoadedListener = () => this.decodeOnce(element, false, true).then(resolve, reject);\n element.addEventListener('load', this.imageLoadedListener);\n });\n }\n _decodeOnLoadVideo(videoElement) {\n return __awaiter(this, void 0, void 0, function* () {\n // plays the video\n yield this.playVideoOnLoadAsync(videoElement);\n // starts decoding after played the video\n return yield this.decodeOnce(videoElement);\n });\n }\n _decodeOnLoadVideoContinuously(videoElement, callbackFn) {\n return __awaiter(this, void 0, void 0, function* () {\n // plays the video\n yield this.playVideoOnLoadAsync(videoElement);\n // starts decoding after played the video\n this.decodeContinuously(videoElement, callbackFn);\n });\n }\n isImageLoaded(img) {\n // During the onload event, IE correctly identifies any images that\n // weren\u2019t downloaded as not complete. Others should too. Gecko-based\n // browsers act like NS4 in that they report this incorrectly.\n if (!img.complete) {\n return false;\n }\n // However, they do have two very useful properties: naturalWidth and\n // naturalHeight. These give the true size of the image. If it failed\n // to load, either of these should be zero.\n if (img.naturalWidth === 0) {\n return false;\n }\n // No other way of checking: assume it\u2019s ok.\n return true;\n }\n prepareImageElement(imageSource) {\n let imageElement;\n if (typeof imageSource === 'undefined') {\n imageElement = document.createElement('img');\n imageElement.width = 200;\n imageElement.height = 200;\n }\n if (typeof imageSource === 'string') {\n imageElement = this.getMediaElement(imageSource, 'img');\n }\n if (imageSource instanceof HTMLImageElement) {\n imageElement = imageSource;\n }\n return imageElement;\n }\n /**\n * Sets a HTMLVideoElement for scanning or creates a new one.\n *\n * @param videoSource The HTMLVideoElement to be set.\n */\n prepareVideoElement(videoSource) {\n let videoElement;\n if (!videoSource && typeof document !== 'undefined') {\n videoElement = document.createElement('video');\n videoElement.width = 200;\n videoElement.height = 200;\n }\n if (typeof videoSource === 'string') {\n videoElement = this.getMediaElement(videoSource, 'video');\n }\n if (videoSource instanceof HTMLVideoElement) {\n videoElement = videoSource;\n }\n // Needed for iOS 11\n videoElement.setAttribute('autoplay', 'true');\n videoElement.setAttribute('muted', 'true');\n videoElement.setAttribute('playsinline', 'true');\n return videoElement;\n }\n /**\n * Tries to decode from the video input until it finds some value.\n */\n decodeOnce(element, retryIfNotFound = true, retryIfChecksumOrFormatError = true) {\n this._stopAsyncDecode = false;\n const loop = (resolve, reject) => {\n if (this._stopAsyncDecode) {\n reject(new NotFoundException('Video stream has ended before any code could be detected.'));\n this._stopAsyncDecode = undefined;\n return;\n }\n try {\n const result = this.decode(element);\n resolve(result);\n }\n catch (e) {\n const ifNotFound = retryIfNotFound && e instanceof NotFoundException;\n const isChecksumOrFormatError = e instanceof ChecksumException || e instanceof FormatException;\n const ifChecksumOrFormat = isChecksumOrFormatError && retryIfChecksumOrFormatError;\n if (ifNotFound || ifChecksumOrFormat) {\n // trying again\n return setTimeout(loop, this._timeBetweenDecodingAttempts, resolve, reject);\n }\n reject(e);\n }\n };\n return new Promise((resolve, reject) => loop(resolve, reject));\n }\n /**\n * Continuously decodes from video input.\n */\n decodeContinuously(element, callbackFn) {\n this._stopContinuousDecode = false;\n const loop = () => {\n if (this._stopContinuousDecode) {\n this._stopContinuousDecode = undefined;\n return;\n }\n try {\n const result = this.decode(element);\n callbackFn(result, null);\n setTimeout(loop, this.timeBetweenScansMillis);\n }\n catch (e) {\n callbackFn(null, e);\n const isChecksumOrFormatError = e instanceof ChecksumException || e instanceof FormatException;\n const isNotFound = e instanceof NotFoundException;\n if (isChecksumOrFormatError || isNotFound) {\n // trying again\n setTimeout(loop, this._timeBetweenDecodingAttempts);\n }\n }\n };\n loop();\n }\n /**\n * Gets the BinaryBitmap for ya! (and decodes it)\n */\n decode(element) {\n // get binary bitmap for decode function\n const binaryBitmap = this.createBinaryBitmap(element);\n return this.decodeBitmap(binaryBitmap);\n }\n /**\n * Returns true if media element is indeed a {@link HtmlVideoElement}.\n */\n _isHTMLVideoElement(mediaElement) {\n const potentialVideo = mediaElement;\n return potentialVideo.videoWidth !== 0;\n }\n /**\n * Overwriting this allows you to manipulate the next frame in anyway\n * you want before decode.\n */\n drawFrameOnCanvas(\n srcElement, dimensions, canvasElementContext) {\n if (!dimensions) {\n dimensions = {\n sx: 0,\n sy: 0,\n sWidth: srcElement.videoWidth,\n sHeight: srcElement.videoHeight,\n dx: 0,\n dy: 0,\n dWidth: srcElement.videoWidth,\n dHeight: srcElement.videoHeight};\n }\n if (!canvasElementContext) {\n canvasElementContext = this.captureCanvasContext;\n }\n canvasElementContext.drawImage(\n srcElement,\n dimensions.sx,\n dimensions.sy,\n dimensions.sWidth,\n dimensions.sHeight,\n dimensions.dx,\n dimensions.dy,\n dimensions.dWidth,\n dimensions.dHeight);\n }\n /**\n * Ovewriting this allows you to manipulate the snapshot image in anyway\n * you want before decode.\n */\n drawImageOnCanvas(\n srcElement,\n dimensions,\n canvasElementContext = this.captureCanvasContext) {\n if (!dimensions) {\n dimensions = {\n sx: 0,\n sy: 0,\n sWidth: srcElement.naturalWidth,\n sHeight: srcElement.naturalHeight,\n dx: 0,\n dy: 0,\n dWidth: srcElement.naturalWidth,\n dHeight: srcElement.naturalHeight\n };\n }\n if (!canvasElementContext) {\n canvasElementContext = this.captureCanvasContext;\n }\n canvasElementContext.drawImage(\n srcElement,\n dimensions.sx,\n dimensions.sy,\n dimensions.sWidth,\n dimensions.sHeight,\n dimensions.dx,\n dimensions.dy,\n dimensions.dWidth,\n dimensions.dHeight);\n }\n /**\n * Creates a binaryBitmap based in some image source.\n *\n * @param mediaElement HTML element containing drawable image source.\n */\n createBinaryBitmap(mediaElement) {\n const ctx = this.getCaptureCanvasContext(mediaElement);\n if (this._isHTMLVideoElement(mediaElement)) {\n this.drawFrameOnCanvas(mediaElement);\n } else {\n this.drawImageOnCanvas(mediaElement);\n }\n const canvas = this.getCaptureCanvas(mediaElement);\n const luminanceSource = new HTMLCanvasElementLuminanceSource(canvas);\n const hybridBinarizer = new HybridBinarizer(luminanceSource);\n\n return new BinaryBitmap(hybridBinarizer);\n }\n\n getCaptureCanvasContext(mediaElement) {\n if (!this.captureCanvasContext) {\n const elem = this.getCaptureCanvas(mediaElement);\n const ctx = elem.getContext('2d');\n this.captureCanvasContext = ctx;\n }\n return this.captureCanvasContext;\n }\n getCaptureCanvas(mediaElement) {\n if (!this.captureCanvas) {\n const elem = this.createCaptureCanvas(mediaElement);\n this.captureCanvas = elem;\n }\n return this.captureCanvas;\n }\n /**\n * Call the encapsulated readers decode\n */\n decodeBitmap(binaryBitmap) {\n return this.reader.decode(binaryBitmap, this._hints);\n }\n /**\n * \uD83D\uDD8C Prepares the canvas for capture and scan frames.\n */\n createCaptureCanvas(mediaElement) {\n if (typeof document === 'undefined') {\n this._destroyCaptureCanvas();\n return null;\n }\n const canvasElement = document.createElement('canvas');\n let width;\n let height;\n if (typeof mediaElement !== 'undefined') {\n if (mediaElement instanceof HTMLVideoElement) {\n width = mediaElement.videoWidth;\n height = mediaElement.videoHeight;\n }\n else if (mediaElement instanceof HTMLImageElement) {\n width = mediaElement.naturalWidth || mediaElement.width;\n height = mediaElement.naturalHeight || mediaElement.height;\n }\n }\n canvasElement.style.width = width + 'px';\n canvasElement.style.height = height + 'px';\n canvasElement.width = width;\n canvasElement.height = height;\n return canvasElement;\n }\n /**\n * Stops the continuous scan and cleans the stream.\n */\n stopStreams() {\n if (this.stream) {\n this.stream.getVideoTracks().forEach(t => t.stop());\n this.stream = undefined;\n }\n if (this._stopAsyncDecode === false) {\n this.stopAsyncDecode();\n }\n if (this._stopContinuousDecode === false) {\n this.stopContinuousDecode();\n }\n }\n /**\n * Resets the code reader to the initial state. Cancels any ongoing barcode scanning from video or camera.\n *\n * @memberOf BrowserCodeReader\n */\n reset() {\n // stops the camera, preview and scan \uD83D\uDD34\n this.stopStreams();\n // clean and forget about HTML elements\n this._destroyVideoElement();\n this._destroyImageElement();\n this._destroyCaptureCanvas();\n }\n _destroyVideoElement() {\n if (!this.videoElement) {\n return;\n }\n // first gives freedon to the element \uD83D\uDD4A\n if (typeof this.videoEndedListener !== 'undefined') {\n this.videoElement.removeEventListener('ended', this.videoEndedListener);\n }\n if (typeof this.videoPlayingEventListener !== 'undefined') {\n this.videoElement.removeEventListener('playing', this.videoPlayingEventListener);\n }\n if (typeof this.videoCanPlayListener !== 'undefined') {\n this.videoElement.removeEventListener('loadedmetadata', this.videoCanPlayListener);\n }\n // then forgets about that element \uD83D\uDE22\n this.cleanVideoSource(this.videoElement);\n this.videoElement = undefined;\n }\n _destroyImageElement() {\n if (!this.imageElement) {\n return;\n }\n // first gives freedon to the element \uD83D\uDD4A\n if (undefined !== this.imageLoadedListener) {\n this.imageElement.removeEventListener('load', this.imageLoadedListener);\n }\n // then forget about that element \uD83D\uDE22\n this.imageElement.src = undefined;\n this.imageElement.removeAttribute('src');\n this.imageElement = undefined;\n }\n /**\n * Cleans canvas references \uD83D\uDD8C\n */\n _destroyCaptureCanvas() {\n // then forget about that element \uD83D\uDE22\n this.captureCanvasContext = undefined;\n this.captureCanvas = undefined;\n }\n /**\n * Defines what the videoElement src will be.\n *\n * @param videoElement\n * @param stream\n */\n addVideoSource(videoElement, stream) {\n // Older browsers may not have `srcObject`\n try {\n // @note Throws Exception if interrupted by a new loaded request\n videoElement.srcObject = stream;\n }\n catch (err) {\n // @note Avoid using this in new browsers, as it is going away.\n videoElement.src = URL.createObjectURL(stream);\n }\n }\n /**\n * Unbinds a HTML video src property.\n *\n * @param videoElement\n */\n cleanVideoSource(videoElement) {\n try {\n videoElement.srcObject = null;\n }\n catch (err) {\n videoElement.src = '';\n }\n this.videoElement.removeAttribute('src');\n }\n }\n\n /*\n * Copyright 2007 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n /**\n *

Encapsulates the result of decoding a barcode within an image.

\n *\n * @author Sean Owen\n */\n class Result {\n // public constructor(private text: string,\n // Uint8Array rawBytes,\n // ResultPoconst resultPoints: Int32Array,\n // BarcodeFormat format) {\n // this(text, rawBytes, resultPoints, format, System.currentTimeMillis())\n // }\n // public constructor(text: string,\n // Uint8Array rawBytes,\n // ResultPoconst resultPoints: Int32Array,\n // BarcodeFormat format,\n // long timestamp) {\n // this(text, rawBytes, rawBytes == null ? 0 : 8 * rawBytes.length,\n // resultPoints, format, timestamp)\n // }\n constructor(text, rawBytes, numBits = rawBytes == null ? 0 : 8 * rawBytes.length, resultPoints, format, timestamp = System.currentTimeMillis()) {\n this.text = text;\n this.rawBytes = rawBytes;\n this.numBits = numBits;\n this.resultPoints = resultPoints;\n this.format = format;\n this.timestamp = timestamp;\n this.text = text;\n this.rawBytes = rawBytes;\n if (undefined === numBits || null === numBits) {\n this.numBits = (rawBytes === null || rawBytes === undefined) ? 0 : 8 * rawBytes.length;\n }\n else {\n this.numBits = numBits;\n }\n this.resultPoints = resultPoints;\n this.format = format;\n this.resultMetadata = null;\n if (undefined === timestamp || null === timestamp) {\n this.timestamp = System.currentTimeMillis();\n }\n else {\n this.timestamp = timestamp;\n }\n }\n /**\n * @return raw text encoded by the barcode\n */\n getText() {\n return this.text;\n }\n /**\n * @return raw bytes encoded by the barcode, if applicable, otherwise {@code null}\n */\n getRawBytes() {\n return this.rawBytes;\n }\n /**\n * @return how many bits of {@link #getRawBytes()} are valid; typically 8 times its length\n * @since 3.3.0\n */\n getNumBits() {\n return this.numBits;\n }\n /**\n * @return points related to the barcode in the image. These are typically points\n * identifying finder patterns or the corners of the barcode. The exact meaning is\n * specific to the type of barcode that was decoded.\n */\n getResultPoints() {\n return this.resultPoints;\n }\n /**\n * @return {@link BarcodeFormat} representing the format of the barcode that was decoded\n */\n getBarcodeFormat() {\n return this.format;\n }\n /**\n * @return {@link Map} mapping {@link ResultMetadataType} keys to values. May be\n * {@code null}. This contains optional metadata about what was detected about the barcode,\n * like orientation.\n */\n getResultMetadata() {\n return this.resultMetadata;\n }\n putMetadata(type, value) {\n if (this.resultMetadata === null) {\n this.resultMetadata = new Map();\n }\n this.resultMetadata.set(type, value);\n }\n putAllMetadata(metadata) {\n if (metadata !== null) {\n if (this.resultMetadata === null) {\n this.resultMetadata = metadata;\n }\n else {\n this.resultMetadata = new Map(metadata);\n }\n }\n }\n addResultPoints(newPoints) {\n const oldPoints = this.resultPoints;\n if (oldPoints === null) {\n this.resultPoints = newPoints;\n }\n else if (newPoints !== null && newPoints.length > 0) {\n const allPoints = new Array(oldPoints.length + newPoints.length);\n System.arraycopy(oldPoints, 0, allPoints, 0, oldPoints.length);\n System.arraycopy(newPoints, 0, allPoints, oldPoints.length, newPoints.length);\n this.resultPoints = allPoints;\n }\n }\n getTimestamp() {\n return this.timestamp;\n }\n /*@Override*/\n toString() {\n return this.text;\n }\n }\n\n /*\n * Direct port to TypeScript of ZXing by Adrian To\u0219c\u0103\n */\n /*\n * Copyright 2009 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n /*namespace com.google.zxing {*/\n /**\n * Enumerates barcode formats known to this package. Please keep alphabetized.\n *\n * @author Sean Owen\n */\n var BarcodeFormat;\n (function (BarcodeFormat) {\n /** Aztec 2D barcode format. */\n BarcodeFormat[BarcodeFormat[\"AZTEC\"] = 0] = \"AZTEC\";\n /** CODABAR 1D format. */\n BarcodeFormat[BarcodeFormat[\"CODABAR\"] = 1] = \"CODABAR\";\n /** Code 39 1D format. */\n BarcodeFormat[BarcodeFormat[\"CODE_39\"] = 2] = \"CODE_39\";\n /** Code 93 1D format. */\n BarcodeFormat[BarcodeFormat[\"CODE_93\"] = 3] = \"CODE_93\";\n /** Code 128 1D format. */\n BarcodeFormat[BarcodeFormat[\"CODE_128\"] = 4] = \"CODE_128\";\n /** Data Matrix 2D barcode format. */\n BarcodeFormat[BarcodeFormat[\"DATA_MATRIX\"] = 5] = \"DATA_MATRIX\";\n /** EAN-8 1D format. */\n BarcodeFormat[BarcodeFormat[\"EAN_8\"] = 6] = \"EAN_8\";\n /** EAN-13 1D format. */\n BarcodeFormat[BarcodeFormat[\"EAN_13\"] = 7] = \"EAN_13\";\n /** ITF (Interleaved Two of Five) 1D format. */\n BarcodeFormat[BarcodeFormat[\"ITF\"] = 8] = \"ITF\";\n /** MaxiCode 2D barcode format. */\n BarcodeFormat[BarcodeFormat[\"MAXICODE\"] = 9] = \"MAXICODE\";\n /** PDF417 format. */\n BarcodeFormat[BarcodeFormat[\"PDF_417\"] = 10] = \"PDF_417\";\n /** QR Code 2D barcode format. */\n BarcodeFormat[BarcodeFormat[\"QR_CODE\"] = 11] = \"QR_CODE\";\n /** RSS 14 */\n BarcodeFormat[BarcodeFormat[\"RSS_14\"] = 12] = \"RSS_14\";\n /** RSS EXPANDED */\n BarcodeFormat[BarcodeFormat[\"RSS_EXPANDED\"] = 13] = \"RSS_EXPANDED\";\n /** UPC-A 1D format. */\n BarcodeFormat[BarcodeFormat[\"UPC_A\"] = 14] = \"UPC_A\";\n /** UPC-E 1D format. */\n BarcodeFormat[BarcodeFormat[\"UPC_E\"] = 15] = \"UPC_E\";\n /** UPC/EAN extension format. Not a stand-alone format. */\n BarcodeFormat[BarcodeFormat[\"UPC_EAN_EXTENSION\"] = 16] = \"UPC_EAN_EXTENSION\";\n })(BarcodeFormat || (BarcodeFormat = {}));\n var BarcodeFormat$1 = BarcodeFormat;\n\n /*namespace com.google.zxing {*/\n /**\n * Represents some type of metadata about the result of the decoding that the decoder\n * wishes to communicate back to the caller.\n *\n * @author Sean Owen\n */\n var ResultMetadataType;\n (function (ResultMetadataType) {\n /**\n * Unspecified, application-specific metadata. Maps to an unspecified {@link Object}.\n */\n ResultMetadataType[ResultMetadataType[\"OTHER\"] = 0] = \"OTHER\";\n /**\n * Denotes the likely approximate orientation of the barcode in the image. This value\n * is given as degrees rotated clockwise from the normal, upright orientation.\n * For example a 1D barcode which was found by reading top-to-bottom would be\n * said to have orientation \"90\". This key maps to an {@link Integer} whose\n * value is in the range [0,360).\n */\n ResultMetadataType[ResultMetadataType[\"ORIENTATION\"] = 1] = \"ORIENTATION\";\n /**\n *

2D barcode formats typically encode text, but allow for a sort of 'byte mode'\n * which is sometimes used to encode binary data. While {@link Result} makes available\n * the complete raw bytes in the barcode for these formats, it does not offer the bytes\n * from the byte segments alone.

\n *\n *

This maps to a {@link java.util.List} of byte arrays corresponding to the\n * raw bytes in the byte segments in the barcode, in order.

\n */\n ResultMetadataType[ResultMetadataType[\"BYTE_SEGMENTS\"] = 2] = \"BYTE_SEGMENTS\";\n /**\n * Error correction level used, if applicable. The value type depends on the\n * format, but is typically a String.\n */\n ResultMetadataType[ResultMetadataType[\"ERROR_CORRECTION_LEVEL\"] = 3] = \"ERROR_CORRECTION_LEVEL\";\n /**\n * For some periodicals, indicates the issue number as an {@link Integer}.\n */\n ResultMetadataType[ResultMetadataType[\"ISSUE_NUMBER\"] = 4] = \"ISSUE_NUMBER\";\n /**\n * For some products, indicates the suggested retail price in the barcode as a\n * formatted {@link String}.\n */\n ResultMetadataType[ResultMetadataType[\"SUGGESTED_PRICE\"] = 5] = \"SUGGESTED_PRICE\";\n /**\n * For some products, the possible country of manufacture as a {@link String} denoting the\n * ISO country code. Some map to multiple possible countries, like \"US/CA\".\n */\n ResultMetadataType[ResultMetadataType[\"POSSIBLE_COUNTRY\"] = 6] = \"POSSIBLE_COUNTRY\";\n /**\n * For some products, the extension text\n */\n ResultMetadataType[ResultMetadataType[\"UPC_EAN_EXTENSION\"] = 7] = \"UPC_EAN_EXTENSION\";\n /**\n * PDF417-specific metadata\n */\n ResultMetadataType[ResultMetadataType[\"PDF417_EXTRA_METADATA\"] = 8] = \"PDF417_EXTRA_METADATA\";\n /**\n * If the code format supports structured append and the current scanned code is part of one then the\n * sequence number is given with it.\n */\n ResultMetadataType[ResultMetadataType[\"STRUCTURED_APPEND_SEQUENCE\"] = 9] = \"STRUCTURED_APPEND_SEQUENCE\";\n /**\n * If the code format supports structured append and the current scanned code is part of one then the\n * parity is given with it.\n */\n ResultMetadataType[ResultMetadataType[\"STRUCTURED_APPEND_PARITY\"] = 10] = \"STRUCTURED_APPEND_PARITY\";\n })(ResultMetadataType || (ResultMetadataType = {}));\n var ResultMetadataType$1 = ResultMetadataType;\n\n /*\n * Copyright 2007 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n /*namespace com.google.zxing.common {*/\n /*import java.util.List;*/\n /**\n *

Encapsulates the result of decoding a matrix of bits. This typically\n * applies to 2D barcode formats. For now it contains the raw bytes obtained,\n * as well as a String interpretation of those bytes, if applicable.

\n *\n * @author Sean Owen\n */\n class DecoderResult {\n // public constructor(rawBytes: Uint8Array,\n // text: string,\n // List byteSegments,\n // String ecLevel) {\n // this(rawBytes, text, byteSegments, ecLevel, -1, -1)\n // }\n constructor(rawBytes, text, byteSegments, ecLevel, structuredAppendSequenceNumber = -1, structuredAppendParity = -1) {\n this.rawBytes = rawBytes;\n this.text = text;\n this.byteSegments = byteSegments;\n this.ecLevel = ecLevel;\n this.structuredAppendSequenceNumber = structuredAppendSequenceNumber;\n this.structuredAppendParity = structuredAppendParity;\n this.numBits = (rawBytes === undefined || rawBytes === null) ? 0 : 8 * rawBytes.length;\n }\n /**\n * @return raw bytes representing the result, or {@code null} if not applicable\n */\n getRawBytes() {\n return this.rawBytes;\n }\n /**\n * @return how many bits of {@link #getRawBytes()} are valid; typically 8 times its length\n * @since 3.3.0\n */\n getNumBits() {\n return this.numBits;\n }\n /**\n * @param numBits overrides the number of bits that are valid in {@link #getRawBytes()}\n * @since 3.3.0\n */\n setNumBits(numBits /*int*/) {\n this.numBits = numBits;\n }\n /**\n * @return text representation of the result\n */\n getText() {\n return this.text;\n }\n /**\n * @return list of byte segments in the result, or {@code null} if not applicable\n */\n getByteSegments() {\n return this.byteSegments;\n }\n /**\n * @return name of error correction level used, or {@code null} if not applicable\n */\n getECLevel() {\n return this.ecLevel;\n }\n /**\n * @return number of errors corrected, or {@code null} if not applicable\n */\n getErrorsCorrected() {\n return this.errorsCorrected;\n }\n setErrorsCorrected(errorsCorrected /*Integer*/) {\n this.errorsCorrected = errorsCorrected;\n }\n /**\n * @return number of erasures corrected, or {@code null} if not applicable\n */\n getErasures() {\n return this.erasures;\n }\n setErasures(erasures /*Integer*/) {\n this.erasures = erasures;\n }\n /**\n * @return arbitrary additional metadata\n */\n getOther() {\n return this.other;\n }\n setOther(other) {\n this.other = other;\n }\n hasStructuredAppend() {\n return this.structuredAppendParity >= 0 && this.structuredAppendSequenceNumber >= 0;\n }\n getStructuredAppendParity() {\n return this.structuredAppendParity;\n }\n getStructuredAppendSequenceNumber() {\n return this.structuredAppendSequenceNumber;\n }\n }\n\n /*\n * Copyright 2007 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n /**\n *

This class contains utility methods for performing mathematical operations over\n * the Galois Fields. Operations use a given primitive polynomial in calculations.

\n *\n *

Throughout this package, elements of the GF are represented as an {@code int}\n * for convenience and speed (but at the cost of memory).\n *

\n *\n * @author Sean Owen\n * @author David Olivier\n */\n class AbstractGenericGF {\n /**\n * @return 2 to the power of a in GF(size)\n */\n exp(a) {\n return this.expTable[a];\n }\n /**\n * @return base 2 log of a in GF(size)\n */\n log(a /*int*/) {\n if (a === 0) {\n throw new IllegalArgumentException();\n }\n return this.logTable[a];\n }\n /**\n * Implements both addition and subtraction -- they are the same in GF(size).\n *\n * @return sum/difference of a and b\n */\n static addOrSubtract(a /*int*/, b /*int*/) {\n return a ^ b;\n }\n }\n\n /*\n * Copyright 2007 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n /**\n *

Represents a polynomial whose coefficients are elements of a GF.\n * Instances of this class are immutable.

\n *\n *

Much credit is due to William Rucklidge since portions of this code are an indirect\n * port of his C++ Reed-Solomon implementation.

\n *\n * @author Sean Owen\n */\n class GenericGFPoly {\n /**\n * @param field the {@link GenericGF} instance representing the field to use\n * to perform computations\n * @param coefficients coefficients as ints representing elements of GF(size), arranged\n * from most significant (highest-power term) coefficient to least significant\n * @throws IllegalArgumentException if argument is null or empty,\n * or if leading coefficient is 0 and this is not a\n * constant polynomial (that is, it is not the monomial \"0\")\n */\n constructor(field, coefficients) {\n if (coefficients.length === 0) {\n throw new IllegalArgumentException();\n }\n this.field = field;\n const coefficientsLength = coefficients.length;\n if (coefficientsLength > 1 && coefficients[0] === 0) {\n // Leading term must be non-zero for anything except the constant polynomial \"0\"\n let firstNonZero = 1;\n while (firstNonZero < coefficientsLength && coefficients[firstNonZero] === 0) {\n firstNonZero++;\n }\n if (firstNonZero === coefficientsLength) {\n this.coefficients = Int32Array.from([0]);\n }\n else {\n this.coefficients = new Int32Array(coefficientsLength - firstNonZero);\n System.arraycopy(coefficients, firstNonZero, this.coefficients, 0, this.coefficients.length);\n }\n }\n else {\n this.coefficients = coefficients;\n }\n }\n getCoefficients() {\n return this.coefficients;\n }\n /**\n * @return degree of this polynomial\n */\n getDegree() {\n return this.coefficients.length - 1;\n }\n /**\n * @return true iff this polynomial is the monomial \"0\"\n */\n isZero() {\n return this.coefficients[0] === 0;\n }\n /**\n * @return coefficient of x^degree term in this polynomial\n */\n getCoefficient(degree /*int*/) {\n return this.coefficients[this.coefficients.length - 1 - degree];\n }\n /**\n * @return evaluation of this polynomial at a given point\n */\n evaluateAt(a /*int*/) {\n if (a === 0) {\n // Just return the x^0 coefficient\n return this.getCoefficient(0);\n }\n const coefficients = this.coefficients;\n let result;\n if (a === 1) {\n // Just the sum of the coefficients\n result = 0;\n for (let i = 0, length = coefficients.length; i !== length; i++) {\n const coefficient = coefficients[i];\n result = AbstractGenericGF.addOrSubtract(result, coefficient);\n }\n return result;\n }\n result = coefficients[0];\n const size = coefficients.length;\n const field = this.field;\n for (let i = 1; i < size; i++) {\n result = AbstractGenericGF.addOrSubtract(field.multiply(a, result), coefficients[i]);\n }\n return result;\n }\n addOrSubtract(other) {\n if (!this.field.equals(other.field)) {\n throw new IllegalArgumentException('GenericGFPolys do not have same GenericGF field');\n }\n if (this.isZero()) {\n return other;\n }\n if (other.isZero()) {\n return this;\n }\n let smallerCoefficients = this.coefficients;\n let largerCoefficients = other.coefficients;\n if (smallerCoefficients.length > largerCoefficients.length) {\n const temp = smallerCoefficients;\n smallerCoefficients = largerCoefficients;\n largerCoefficients = temp;\n }\n let sumDiff = new Int32Array(largerCoefficients.length);\n const lengthDiff = largerCoefficients.length - smallerCoefficients.length;\n // Copy high-order terms only found in higher-degree polynomial's coefficients\n System.arraycopy(largerCoefficients, 0, sumDiff, 0, lengthDiff);\n for (let i = lengthDiff; i < largerCoefficients.length; i++) {\n sumDiff[i] = AbstractGenericGF.addOrSubtract(smallerCoefficients[i - lengthDiff], largerCoefficients[i]);\n }\n return new GenericGFPoly(this.field, sumDiff);\n }\n multiply(other) {\n if (!this.field.equals(other.field)) {\n throw new IllegalArgumentException('GenericGFPolys do not have same GenericGF field');\n }\n if (this.isZero() || other.isZero()) {\n return this.field.getZero();\n }\n const aCoefficients = this.coefficients;\n const aLength = aCoefficients.length;\n const bCoefficients = other.coefficients;\n const bLength = bCoefficients.length;\n const product = new Int32Array(aLength + bLength - 1);\n const field = this.field;\n for (let i = 0; i < aLength; i++) {\n const aCoeff = aCoefficients[i];\n for (let j = 0; j < bLength; j++) {\n product[i + j] = AbstractGenericGF.addOrSubtract(product[i + j], field.multiply(aCoeff, bCoefficients[j]));\n }\n }\n return new GenericGFPoly(field, product);\n }\n multiplyScalar(scalar /*int*/) {\n if (scalar === 0) {\n return this.field.getZero();\n }\n if (scalar === 1) {\n return this;\n }\n const size = this.coefficients.length;\n const field = this.field;\n const product = new Int32Array(size);\n const coefficients = this.coefficients;\n for (let i = 0; i < size; i++) {\n product[i] = field.multiply(coefficients[i], scalar);\n }\n return new GenericGFPoly(field, product);\n }\n multiplyByMonomial(degree /*int*/, coefficient /*int*/) {\n if (degree < 0) {\n throw new IllegalArgumentException();\n }\n if (coefficient === 0) {\n return this.field.getZero();\n }\n const coefficients = this.coefficients;\n const size = coefficients.length;\n const product = new Int32Array(size + degree);\n const field = this.field;\n for (let i = 0; i < size; i++) {\n product[i] = field.multiply(coefficients[i], coefficient);\n }\n return new GenericGFPoly(field, product);\n }\n divide(other) {\n if (!this.field.equals(other.field)) {\n throw new IllegalArgumentException('GenericGFPolys do not have same GenericGF field');\n }\n if (other.isZero()) {\n throw new IllegalArgumentException('Divide by 0');\n }\n const field = this.field;\n let quotient = field.getZero();\n let remainder = this;\n const denominatorLeadingTerm = other.getCoefficient(other.getDegree());\n const inverseDenominatorLeadingTerm = field.inverse(denominatorLeadingTerm);\n while (remainder.getDegree() >= other.getDegree() && !remainder.isZero()) {\n const degreeDifference = remainder.getDegree() - other.getDegree();\n const scale = field.multiply(remainder.getCoefficient(remainder.getDegree()), inverseDenominatorLeadingTerm);\n const term = other.multiplyByMonomial(degreeDifference, scale);\n const iterationQuotient = field.buildMonomial(degreeDifference, scale);\n quotient = quotient.addOrSubtract(iterationQuotient);\n remainder = remainder.addOrSubtract(term);\n }\n return [quotient, remainder];\n }\n /*@Override*/\n toString() {\n let result = '';\n for (let degree = this.getDegree(); degree >= 0; degree--) {\n let coefficient = this.getCoefficient(degree);\n if (coefficient !== 0) {\n if (coefficient < 0) {\n result += ' - ';\n coefficient = -coefficient;\n }\n else {\n if (result.length > 0) {\n result += ' + ';\n }\n }\n if (degree === 0 || coefficient !== 1) {\n const alphaPower = this.field.log(coefficient);\n if (alphaPower === 0) {\n result += '1';\n }\n else if (alphaPower === 1) {\n result += 'a';\n }\n else {\n result += 'a^';\n result += alphaPower;\n }\n }\n if (degree !== 0) {\n if (degree === 1) {\n result += 'x';\n }\n else {\n result += 'x^';\n result += degree;\n }\n }\n }\n }\n return result;\n }\n }\n\n /**\n * Custom Error class of type Exception.\n */\n class ArithmeticException extends Exception {\n }\n ArithmeticException.kind = 'ArithmeticException';\n\n /*\n * Copyright 2007 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n /**\n *

This class contains utility methods for performing mathematical operations over\n * the Galois Fields. Operations use a given primitive polynomial in calculations.

\n *\n *

Throughout this package, elements of the GF are represented as an {@code int}\n * for convenience and speed (but at the cost of memory).\n *

\n *\n * @author Sean Owen\n * @author David Olivier\n */\n class GenericGF extends AbstractGenericGF {\n /**\n * Create a representation of GF(size) using the given primitive polynomial.\n *\n * @param primitive irreducible polynomial whose coefficients are represented by\n * the bits of an int, where the least-significant bit represents the constant\n * coefficient\n * @param size the size of the field\n * @param b the factor b in the generator polynomial can be 0- or 1-based\n * (g(x) = (x+a^b)(x+a^(b+1))...(x+a^(b+2t-1))).\n * In most cases it should be 1, but for QR code it is 0.\n */\n constructor(primitive /*int*/, size /*int*/, generatorBase /*int*/) {\n super();\n this.primitive = primitive;\n this.size = size;\n this.generatorBase = generatorBase;\n const expTable = new Int32Array(size);\n let x = 1;\n for (let i = 0; i < size; i++) {\n expTable[i] = x;\n x *= 2; // we're assuming the generator alpha is 2\n if (x >= size) {\n x ^= primitive;\n x &= size - 1;\n }\n }\n this.expTable = expTable;\n const logTable = new Int32Array(size);\n for (let i = 0; i < size - 1; i++) {\n logTable[expTable[i]] = i;\n }\n this.logTable = logTable;\n // logTable[0] == 0 but this should never be used\n this.zero = new GenericGFPoly(this, Int32Array.from([0]));\n this.one = new GenericGFPoly(this, Int32Array.from([1]));\n }\n getZero() {\n return this.zero;\n }\n getOne() {\n return this.one;\n }\n /**\n * @return the monomial representing coefficient * x^degree\n */\n buildMonomial(degree /*int*/, coefficient /*int*/) {\n if (degree < 0) {\n throw new IllegalArgumentException();\n }\n if (coefficient === 0) {\n return this.zero;\n }\n const coefficients = new Int32Array(degree + 1);\n coefficients[0] = coefficient;\n return new GenericGFPoly(this, coefficients);\n }\n /**\n * @return multiplicative inverse of a\n */\n inverse(a /*int*/) {\n if (a === 0) {\n throw new ArithmeticException();\n }\n return this.expTable[this.size - this.logTable[a] - 1];\n }\n /**\n * @return product of a and b in GF(size)\n */\n multiply(a /*int*/, b /*int*/) {\n if (a === 0 || b === 0) {\n return 0;\n }\n return this.expTable[(this.logTable[a] + this.logTable[b]) % (this.size - 1)];\n }\n getSize() {\n return this.size;\n }\n getGeneratorBase() {\n return this.generatorBase;\n }\n /*@Override*/\n toString() {\n return ('GF(0x' + Integer.toHexString(this.primitive) + ',' + this.size + ')');\n }\n equals(o) {\n return o === this;\n }\n }\n GenericGF.AZTEC_DATA_12 = new GenericGF(0x1069, 4096, 1); // x^12 + x^6 + x^5 + x^3 + 1\n GenericGF.AZTEC_DATA_10 = new GenericGF(0x409, 1024, 1); // x^10 + x^3 + 1\n GenericGF.AZTEC_DATA_6 = new GenericGF(0x43, 64, 1); // x^6 + x + 1\n GenericGF.AZTEC_PARAM = new GenericGF(0x13, 16, 1); // x^4 + x + 1\n GenericGF.QR_CODE_FIELD_256 = new GenericGF(0x011d, 256, 0); // x^8 + x^4 + x^3 + x^2 + 1\n GenericGF.DATA_MATRIX_FIELD_256 = new GenericGF(0x012d, 256, 1); // x^8 + x^5 + x^3 + x^2 + 1\n GenericGF.AZTEC_DATA_8 = GenericGF.DATA_MATRIX_FIELD_256;\n GenericGF.MAXICODE_FIELD_64 = GenericGF.AZTEC_DATA_6;\n\n /**\n * Custom Error class of type Exception.\n */\n class ReedSolomonException extends Exception {\n }\n ReedSolomonException.kind = 'ReedSolomonException';\n\n /**\n * Custom Error class of type Exception.\n */\n class IllegalStateException extends Exception {\n }\n IllegalStateException.kind = 'IllegalStateException';\n\n /*\n * Copyright 2007 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n /**\n *

Implements Reed-Solomon decoding, as the name implies.

\n *\n *

The algorithm will not be explained here, but the following references were helpful\n * in creating this implementation:

\n *\n * \n *\n *

Much credit is due to William Rucklidge since portions of this code are an indirect\n * port of his C++ Reed-Solomon implementation.

\n *\n * @author Sean Owen\n * @author William Rucklidge\n * @author sanfordsquires\n */\n class ReedSolomonDecoder {\n constructor(field) {\n this.field = field;\n }\n /**\n *

Decodes given set of received codewords, which include both data and error-correction\n * codewords. Really, this means it uses Reed-Solomon to detect and correct errors, in-place,\n * in the input.

\n *\n * @param received data and error-correction codewords\n * @param twoS number of error-correction codewords available\n * @throws ReedSolomonException if decoding fails for any reason\n */\n decode(received, twoS /*int*/) {\n const field = this.field;\n const poly = new GenericGFPoly(field, received);\n const syndromeCoefficients = new Int32Array(twoS);\n let noError = true;\n for (let i = 0; i < twoS; i++) {\n const evalResult = poly.evaluateAt(field.exp(i + field.getGeneratorBase()));\n syndromeCoefficients[syndromeCoefficients.length - 1 - i] = evalResult;\n if (evalResult !== 0) {\n noError = false;\n }\n }\n if (noError) {\n return;\n }\n const syndrome = new GenericGFPoly(field, syndromeCoefficients);\n const sigmaOmega = this.runEuclideanAlgorithm(field.buildMonomial(twoS, 1), syndrome, twoS);\n const sigma = sigmaOmega[0];\n const omega = sigmaOmega[1];\n const errorLocations = this.findErrorLocations(sigma);\n const errorMagnitudes = this.findErrorMagnitudes(omega, errorLocations);\n for (let i = 0; i < errorLocations.length; i++) {\n const position = received.length - 1 - field.log(errorLocations[i]);\n if (position < 0) {\n throw new ReedSolomonException('Bad error location');\n }\n received[position] = GenericGF.addOrSubtract(received[position], errorMagnitudes[i]);\n }\n }\n runEuclideanAlgorithm(a, b, R /*int*/) {\n // Assume a's degree is >= b's\n if (a.getDegree() < b.getDegree()) {\n const temp = a;\n a = b;\n b = temp;\n }\n const field = this.field;\n let rLast = a;\n let r = b;\n let tLast = field.getZero();\n let t = field.getOne();\n // Run Euclidean algorithm until r's degree is less than R/2\n while (r.getDegree() >= (R / 2 | 0)) {\n let rLastLast = rLast;\n let tLastLast = tLast;\n rLast = r;\n tLast = t;\n // Divide rLastLast by rLast, with quotient in q and remainder in r\n if (rLast.isZero()) {\n // Oops, Euclidean algorithm already terminated?\n throw new ReedSolomonException('r_{i-1} was zero');\n }\n r = rLastLast;\n let q = field.getZero();\n const denominatorLeadingTerm = rLast.getCoefficient(rLast.getDegree());\n const dltInverse = field.inverse(denominatorLeadingTerm);\n while (r.getDegree() >= rLast.getDegree() && !r.isZero()) {\n const degreeDiff = r.getDegree() - rLast.getDegree();\n const scale = field.multiply(r.getCoefficient(r.getDegree()), dltInverse);\n q = q.addOrSubtract(field.buildMonomial(degreeDiff, scale));\n r = r.addOrSubtract(rLast.multiplyByMonomial(degreeDiff, scale));\n }\n t = q.multiply(tLast).addOrSubtract(tLastLast);\n if (r.getDegree() >= rLast.getDegree()) {\n throw new IllegalStateException('Division algorithm failed to reduce polynomial?');\n }\n }\n const sigmaTildeAtZero = t.getCoefficient(0);\n if (sigmaTildeAtZero === 0) {\n throw new ReedSolomonException('sigmaTilde(0) was zero');\n }\n const inverse = field.inverse(sigmaTildeAtZero);\n const sigma = t.multiplyScalar(inverse);\n const omega = r.multiplyScalar(inverse);\n return [sigma, omega];\n }\n findErrorLocations(errorLocator) {\n // This is a direct application of Chien's search\n const numErrors = errorLocator.getDegree();\n if (numErrors === 1) { // shortcut\n return Int32Array.from([errorLocator.getCoefficient(1)]);\n }\n const result = new Int32Array(numErrors);\n let e = 0;\n const field = this.field;\n for (let i = 1; i < field.getSize() && e < numErrors; i++) {\n if (errorLocator.evaluateAt(i) === 0) {\n result[e] = field.inverse(i);\n e++;\n }\n }\n if (e !== numErrors) {\n throw new ReedSolomonException('Error locator degree does not match number of roots');\n }\n return result;\n }\n findErrorMagnitudes(errorEvaluator, errorLocations) {\n // This is directly applying Forney's Formula\n const s = errorLocations.length;\n const result = new Int32Array(s);\n const field = this.field;\n for (let i = 0; i < s; i++) {\n const xiInverse = field.inverse(errorLocations[i]);\n let denominator = 1;\n for (let j = 0; j < s; j++) {\n if (i !== j) {\n // denominator = field.multiply(denominator,\n // GenericGF.addOrSubtract(1, field.multiply(errorLocations[j], xiInverse)))\n // Above should work but fails on some Apple and Linux JDKs due to a Hotspot bug.\n // Below is a funny-looking workaround from Steven Parkes\n const term = field.multiply(errorLocations[j], xiInverse);\n const termPlus1 = (term & 0x1) === 0 ? term | 1 : term & ~1;\n denominator = field.multiply(denominator, termPlus1);\n }\n }\n result[i] = field.multiply(errorEvaluator.evaluateAt(xiInverse), field.inverse(denominator));\n if (field.getGeneratorBase() !== 0) {\n result[i] = field.multiply(result[i], xiInverse);\n }\n }\n return result;\n }\n }\n\n /*\n * Copyright 2010 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n // import java.util.Arrays;\n var Table;\n (function (Table) {\n Table[Table[\"UPPER\"] = 0] = \"UPPER\";\n Table[Table[\"LOWER\"] = 1] = \"LOWER\";\n Table[Table[\"MIXED\"] = 2] = \"MIXED\";\n Table[Table[\"DIGIT\"] = 3] = \"DIGIT\";\n Table[Table[\"PUNCT\"] = 4] = \"PUNCT\";\n Table[Table[\"BINARY\"] = 5] = \"BINARY\";\n })(Table || (Table = {}));\n /**\n *

The main class which implements Aztec Code decoding -- as opposed to locating and extracting\n * the Aztec Code from an image.

\n *\n * @author David Olivier\n */\n class Decoder {\n decode(detectorResult) {\n this.ddata = detectorResult;\n let matrix = detectorResult.getBits();\n let rawbits = this.extractBits(matrix);\n let correctedBits = this.correctBits(rawbits);\n let rawBytes = Decoder.convertBoolArrayToByteArray(correctedBits);\n let result = Decoder.getEncodedData(correctedBits);\n let decoderResult = new DecoderResult(rawBytes, result, null, null);\n decoderResult.setNumBits(correctedBits.length);\n return decoderResult;\n }\n // This method is used for testing the high-level encoder\n static highLevelDecode(correctedBits) {\n return this.getEncodedData(correctedBits);\n }\n /**\n * Gets the string encoded in the aztec code bits\n *\n * @return the decoded string\n */\n static getEncodedData(correctedBits) {\n let endIndex = correctedBits.length;\n let latchTable = Table.UPPER; // table most recently latched to\n let shiftTable = Table.UPPER; // table to use for the next read\n let result = '';\n let index = 0;\n while (index < endIndex) {\n if (shiftTable === Table.BINARY) {\n if (endIndex - index < 5) {\n break;\n }\n let length = Decoder.readCode(correctedBits, index, 5);\n index += 5;\n if (length === 0) {\n if (endIndex - index < 11) {\n break;\n }\n length = Decoder.readCode(correctedBits, index, 11) + 31;\n index += 11;\n }\n for (let charCount = 0; charCount < length; charCount++) {\n if (endIndex - index < 8) {\n index = endIndex; // Force outer loop to exit\n break;\n }\n const code = Decoder.readCode(correctedBits, index, 8);\n result += /*(char)*/ StringUtils.castAsNonUtf8Char(code);\n index += 8;\n }\n // Go back to whatever mode we had been in\n shiftTable = latchTable;\n }\n else {\n let size = shiftTable === Table.DIGIT ? 4 : 5;\n if (endIndex - index < size) {\n break;\n }\n let code = Decoder.readCode(correctedBits, index, size);\n index += size;\n let str = Decoder.getCharacter(shiftTable, code);\n if (str.startsWith('CTRL_')) {\n // Table changes\n // ISO/IEC 24778:2008 prescribes ending a shift sequence in the mode from which it was invoked.\n // That's including when that mode is a shift.\n // Our test case dlusbs.png for issue #642 exercises that.\n latchTable = shiftTable; // Latch the current mode, so as to return to Upper after U/S B/S\n shiftTable = Decoder.getTable(str.charAt(5));\n if (str.charAt(6) === 'L') {\n latchTable = shiftTable;\n }\n }\n else {\n result += str;\n // Go back to whatever mode we had been in\n shiftTable = latchTable;\n }\n }\n }\n return result;\n }\n /**\n * gets the table corresponding to the char passed\n */\n static getTable(t) {\n switch (t) {\n case 'L':\n return Table.LOWER;\n case 'P':\n return Table.PUNCT;\n case 'M':\n return Table.MIXED;\n case 'D':\n return Table.DIGIT;\n case 'B':\n return Table.BINARY;\n case 'U':\n default:\n return Table.UPPER;\n }\n }\n /**\n * Gets the character (or string) corresponding to the passed code in the given table\n *\n * @param table the table used\n * @param code the code of the character\n */\n static getCharacter(table, code) {\n switch (table) {\n case Table.UPPER:\n return Decoder.UPPER_TABLE[code];\n case Table.LOWER:\n return Decoder.LOWER_TABLE[code];\n case Table.MIXED:\n return Decoder.MIXED_TABLE[code];\n case Table.PUNCT:\n return Decoder.PUNCT_TABLE[code];\n case Table.DIGIT:\n return Decoder.DIGIT_TABLE[code];\n default:\n // Should not reach here.\n throw new IllegalStateException('Bad table');\n }\n }\n /**\n *

Performs RS error correction on an array of bits.

\n *\n * @return the corrected array\n * @throws FormatException if the input contains too many errors\n */\n correctBits(rawbits) {\n let gf;\n let codewordSize;\n if (this.ddata.getNbLayers() <= 2) {\n codewordSize = 6;\n gf = GenericGF.AZTEC_DATA_6;\n }\n else if (this.ddata.getNbLayers() <= 8) {\n codewordSize = 8;\n gf = GenericGF.AZTEC_DATA_8;\n }\n else if (this.ddata.getNbLayers() <= 22) {\n codewordSize = 10;\n gf = GenericGF.AZTEC_DATA_10;\n }\n else {\n codewordSize = 12;\n gf = GenericGF.AZTEC_DATA_12;\n }\n let numDataCodewords = this.ddata.getNbDatablocks();\n let numCodewords = rawbits.length / codewordSize;\n if (numCodewords < numDataCodewords) {\n throw new FormatException();\n }\n let offset = rawbits.length % codewordSize;\n let dataWords = new Int32Array(numCodewords);\n for (let i = 0; i < numCodewords; i++, offset += codewordSize) {\n dataWords[i] = Decoder.readCode(rawbits, offset, codewordSize);\n }\n try {\n let rsDecoder = new ReedSolomonDecoder(gf);\n rsDecoder.decode(dataWords, numCodewords - numDataCodewords);\n }\n catch (ex) {\n throw new FormatException(ex);\n }\n // Now perform the unstuffing operation.\n // First, count how many bits are going to be thrown out as stuffing\n let mask = (1 << codewordSize) - 1;\n let stuffedBits = 0;\n for (let i = 0; i < numDataCodewords; i++) {\n let dataWord = dataWords[i];\n if (dataWord === 0 || dataWord === mask) {\n throw new FormatException();\n }\n else if (dataWord === 1 || dataWord === mask - 1) {\n stuffedBits++;\n }\n }\n // Now, actually unpack the bits and remove the stuffing\n let correctedBits = new Array(numDataCodewords * codewordSize - stuffedBits);\n let index = 0;\n for (let i = 0; i < numDataCodewords; i++) {\n let dataWord = dataWords[i];\n if (dataWord === 1 || dataWord === mask - 1) {\n // next codewordSize-1 bits are all zeros or all ones\n correctedBits.fill(dataWord > 1, index, index + codewordSize - 1);\n // Arrays.fill(correctedBits, index, index + codewordSize - 1, dataWord > 1);\n index += codewordSize - 1;\n }\n else {\n for (let bit = codewordSize - 1; bit >= 0; --bit) {\n correctedBits[index++] = (dataWord & (1 << bit)) !== 0;\n }\n }\n }\n return correctedBits;\n }\n /**\n * Gets the array of bits from an Aztec Code matrix\n *\n * @return the array of bits\n */\n extractBits(matrix) {\n let compact = this.ddata.isCompact();\n let layers = this.ddata.getNbLayers();\n let baseMatrixSize = (compact ? 11 : 14) + layers * 4; // not including alignment lines\n let alignmentMap = new Int32Array(baseMatrixSize);\n let rawbits = new Array(this.totalBitsInLayer(layers, compact));\n if (compact) {\n for (let i = 0; i < alignmentMap.length; i++) {\n alignmentMap[i] = i;\n }\n }\n else {\n let matrixSize = baseMatrixSize + 1 + 2 * Integer.truncDivision((Integer.truncDivision(baseMatrixSize, 2) - 1), 15);\n let origCenter = baseMatrixSize / 2;\n let center = Integer.truncDivision(matrixSize, 2);\n for (let i = 0; i < origCenter; i++) {\n let newOffset = i + Integer.truncDivision(i, 15);\n alignmentMap[origCenter - i - 1] = center - newOffset - 1;\n alignmentMap[origCenter + i] = center + newOffset + 1;\n }\n }\n for (let i = 0, rowOffset = 0; i < layers; i++) {\n let rowSize = (layers - i) * 4 + (compact ? 9 : 12);\n // The top-left most point of this layer is (not including alignment lines)\n let low = i * 2;\n // The bottom-right most point of this layer is (not including alignment lines)\n let high = baseMatrixSize - 1 - low;\n // We pull bits from the two 2 x rowSize columns and two rowSize x 2 rows\n for (let j = 0; j < rowSize; j++) {\n let columnOffset = j * 2;\n for (let k = 0; k < 2; k++) {\n // left column\n rawbits[rowOffset + columnOffset + k] =\n matrix.get(alignmentMap[low + k], alignmentMap[low + j]);\n // bottom row\n rawbits[rowOffset + 2 * rowSize + columnOffset + k] =\n matrix.get(alignmentMap[low + j], alignmentMap[high - k]);\n // right column\n rawbits[rowOffset + 4 * rowSize + columnOffset + k] =\n matrix.get(alignmentMap[high - k], alignmentMap[high - j]);\n // top row\n rawbits[rowOffset + 6 * rowSize + columnOffset + k] =\n matrix.get(alignmentMap[high - j], alignmentMap[low + k]);\n }\n }\n rowOffset += rowSize * 8;\n }\n return rawbits;\n }\n /**\n * Reads a code of given length and at given index in an array of bits\n */\n static readCode(rawbits, startIndex, length) {\n let res = 0;\n for (let i = startIndex; i < startIndex + length; i++) {\n res <<= 1;\n if (rawbits[i]) {\n res |= 0x01;\n }\n }\n return res;\n }\n /**\n * Reads a code of length 8 in an array of bits, padding with zeros\n */\n static readByte(rawbits, startIndex) {\n let n = rawbits.length - startIndex;\n if (n >= 8) {\n return Decoder.readCode(rawbits, startIndex, 8);\n }\n return Decoder.readCode(rawbits, startIndex, n) << (8 - n);\n }\n /**\n * Packs a bit array into bytes, most significant bit first\n */\n static convertBoolArrayToByteArray(boolArr) {\n let byteArr = new Uint8Array((boolArr.length + 7) / 8);\n for (let i = 0; i < byteArr.length; i++) {\n byteArr[i] = Decoder.readByte(boolArr, 8 * i);\n }\n return byteArr;\n }\n totalBitsInLayer(layers, compact) {\n return ((compact ? 88 : 112) + 16 * layers) * layers;\n }\n }\n Decoder.UPPER_TABLE = [\n 'CTRL_PS', ' ', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',\n 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'CTRL_LL', 'CTRL_ML', 'CTRL_DL', 'CTRL_BS'\n ];\n Decoder.LOWER_TABLE = [\n 'CTRL_PS', ' ', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p',\n 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'CTRL_US', 'CTRL_ML', 'CTRL_DL', 'CTRL_BS'\n ];\n Decoder.MIXED_TABLE = [\n // Module parse failed: Octal literal in strict mode (50:29)\n // so number string were scaped\n 'CTRL_PS', ' ', '\\\\1', '\\\\2', '\\\\3', '\\\\4', '\\\\5', '\\\\6', '\\\\7', '\\b', '\\t', '\\n',\n '\\\\13', '\\f', '\\r', '\\\\33', '\\\\34', '\\\\35', '\\\\36', '\\\\37', '@', '\\\\', '^', '_',\n '`', '|', '~', '\\\\177', 'CTRL_LL', 'CTRL_UL', 'CTRL_PL', 'CTRL_BS'\n ];\n Decoder.PUNCT_TABLE = [\n '', '\\r', '\\r\\n', '. ', ', ', ': ', '!', '\"', '#', '$', '%', '&', '\\'', '(', ')',\n '*', '+', ',', '-', '.', '/', ':', ';', '<', '=', '>', '?', '[', ']', '{', '}', 'CTRL_UL'\n ];\n Decoder.DIGIT_TABLE = [\n 'CTRL_PS', ' ', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ',', '.', 'CTRL_UL', 'CTRL_US'\n ];\n\n /*\n * Copyright 2012 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n /*namespace com.google.zxing.common.detector {*/\n /**\n * General math-related and numeric utility functions.\n */\n class MathUtils {\n constructor() { }\n /**\n * Ends up being a bit faster than {@link Math#round(float)}. This merely rounds its\n * argument to the nearest int, where x.5 rounds up to x+1. Semantics of this shortcut\n * differ slightly from {@link Math#round(float)} in that half rounds down for negative\n * values. -2.5 rounds to -3, not -2. For purposes here it makes no difference.\n *\n * @param d real value to round\n * @return nearest {@code int}\n */\n static round(d /*float*/) {\n if (NaN === d)\n return 0;\n if (d <= Number.MIN_SAFE_INTEGER)\n return Number.MIN_SAFE_INTEGER;\n if (d >= Number.MAX_SAFE_INTEGER)\n return Number.MAX_SAFE_INTEGER;\n return /*(int) */ (d + (d < 0.0 ? -0.5 : 0.5)) | 0;\n }\n // TYPESCRIPTPORT: maybe remove round method and call directly Math.round, it looks like it doesn't make sense for js\n /**\n * @param aX point A x coordinate\n * @param aY point A y coordinate\n * @param bX point B x coordinate\n * @param bY point B y coordinate\n * @return Euclidean distance between points A and B\n */\n static distance(aX /*float|int*/, aY /*float|int*/, bX /*float|int*/, bY /*float|int*/) {\n const xDiff = aX - bX;\n const yDiff = aY - bY;\n return /*(float) */ Math.sqrt(xDiff * xDiff + yDiff * yDiff);\n }\n /**\n * @param aX point A x coordinate\n * @param aY point A y coordinate\n * @param bX point B x coordinate\n * @param bY point B y coordinate\n * @return Euclidean distance between points A and B\n */\n // public static distance(aX: number /*int*/, aY: number /*int*/, bX: number /*int*/, bY: number /*int*/): float {\n // const xDiff = aX - bX\n // const yDiff = aY - bY\n // return (float) Math.sqrt(xDiff * xDiff + yDiff * yDiff);\n // }\n /**\n * @param array values to sum\n * @return sum of values in array\n */\n static sum(array) {\n let count = 0;\n for (let i = 0, length = array.length; i !== length; i++) {\n const a = array[i];\n count += a;\n }\n return count;\n }\n }\n\n /**\n * Ponyfill for Java's Float class.\n */\n class Float {\n /**\n * SincTS has no difference between int and float, there's all numbers,\n * this is used only to polyfill Java code.\n */\n static floatToIntBits(f) {\n return f;\n }\n }\n /**\n * The float max value in JS is the number max value.\n */\n Float.MAX_VALUE = Number.MAX_SAFE_INTEGER;\n\n /*\n * Copyright 2007 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n /**\n *

Encapsulates a point of interest in an image containing a barcode. Typically, this\n * would be the location of a finder pattern or the corner of the barcode, for example.

\n *\n * @author Sean Owen\n */\n class ResultPoint {\n constructor(x, y) {\n this.x = x;\n this.y = y;\n }\n getX() {\n return this.x;\n }\n getY() {\n return this.y;\n }\n /*@Override*/\n equals(other) {\n if (other instanceof ResultPoint) {\n const otherPoint = other;\n return this.x === otherPoint.x && this.y === otherPoint.y;\n }\n return false;\n }\n /*@Override*/\n hashCode() {\n return 31 * Float.floatToIntBits(this.x) + Float.floatToIntBits(this.y);\n }\n /*@Override*/\n toString() {\n return '(' + this.x + ',' + this.y + ')';\n }\n /**\n * Orders an array of three ResultPoints in an order [A,B,C] such that AB is less than AC\n * and BC is less than AC, and the angle between BC and BA is less than 180 degrees.\n *\n * @param patterns array of three {@code ResultPoint} to order\n */\n static orderBestPatterns(patterns) {\n // Find distances between pattern centers\n const zeroOneDistance = this.distance(patterns[0], patterns[1]);\n const oneTwoDistance = this.distance(patterns[1], patterns[2]);\n const zeroTwoDistance = this.distance(patterns[0], patterns[2]);\n let pointA;\n let pointB;\n let pointC;\n // Assume one closest to other two is B; A and C will just be guesses at first\n if (oneTwoDistance >= zeroOneDistance && oneTwoDistance >= zeroTwoDistance) {\n pointB = patterns[0];\n pointA = patterns[1];\n pointC = patterns[2];\n }\n else if (zeroTwoDistance >= oneTwoDistance && zeroTwoDistance >= zeroOneDistance) {\n pointB = patterns[1];\n pointA = patterns[0];\n pointC = patterns[2];\n }\n else {\n pointB = patterns[2];\n pointA = patterns[0];\n pointC = patterns[1];\n }\n // Use cross product to figure out whether A and C are correct or flipped.\n // This asks whether BC x BA has a positive z component, which is the arrangement\n // we want for A, B, C. If it's negative, then we've got it flipped around and\n // should swap A and C.\n if (this.crossProductZ(pointA, pointB, pointC) < 0.0) {\n const temp = pointA;\n pointA = pointC;\n pointC = temp;\n }\n patterns[0] = pointA;\n patterns[1] = pointB;\n patterns[2] = pointC;\n }\n /**\n * @param pattern1 first pattern\n * @param pattern2 second pattern\n * @return distance between two points\n */\n static distance(pattern1, pattern2) {\n return MathUtils.distance(pattern1.x, pattern1.y, pattern2.x, pattern2.y);\n }\n /**\n * Returns the z component of the cross product between vectors BC and BA.\n */\n static crossProductZ(pointA, pointB, pointC) {\n const bX = pointB.x;\n const bY = pointB.y;\n return ((pointC.x - bX) * (pointA.y - bY)) - ((pointC.y - bY) * (pointA.x - bX));\n }\n }\n\n /*\n * Copyright 2007 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n /**\n *

Encapsulates the result of detecting a barcode in an image. This includes the raw\n * matrix of black/white pixels corresponding to the barcode, and possibly points of interest\n * in the image, like the location of finder patterns or corners of the barcode in the image.

\n *\n * @author Sean Owen\n */\n class DetectorResult {\n constructor(bits, points) {\n this.bits = bits;\n this.points = points;\n }\n getBits() {\n return this.bits;\n }\n getPoints() {\n return this.points;\n }\n }\n\n /*\n * Copyright 2010 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n /**\n *

Extends {@link DetectorResult} with more information specific to the Aztec format,\n * like the number of layers and whether it's compact.

\n *\n * @author Sean Owen\n */\n class AztecDetectorResult extends DetectorResult {\n constructor(bits, points, compact, nbDatablocks, nbLayers) {\n super(bits, points);\n this.compact = compact;\n this.nbDatablocks = nbDatablocks;\n this.nbLayers = nbLayers;\n }\n getNbLayers() {\n return this.nbLayers;\n }\n getNbDatablocks() {\n return this.nbDatablocks;\n }\n isCompact() {\n return this.compact;\n }\n }\n\n /*\n * Copyright 2010 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n /**\n *

\n * Detects a candidate barcode-like rectangular region within an image. It\n * starts around the center of the image, increases the size of the candidate\n * region until it finds a white rectangular region. By keeping track of the\n * last black points it encountered, it determines the corners of the barcode.\n *

\n *\n * @author David Olivier\n */\n class WhiteRectangleDetector {\n // public constructor(private image: BitMatrix) /*throws NotFoundException*/ {\n // this(image, INIT_SIZE, image.getWidth() / 2, image.getHeight() / 2)\n // }\n /**\n * @param image barcode image to find a rectangle in\n * @param initSize initial size of search area around center\n * @param x x position of search center\n * @param y y position of search center\n * @throws NotFoundException if image is too small to accommodate {@code initSize}\n */\n constructor(image, initSize /*int*/, x /*int*/, y /*int*/) {\n this.image = image;\n this.height = image.getHeight();\n this.width = image.getWidth();\n if (undefined === initSize || null === initSize) {\n initSize = WhiteRectangleDetector.INIT_SIZE;\n }\n if (undefined === x || null === x) {\n x = image.getWidth() / 2 | 0;\n }\n if (undefined === y || null === y) {\n y = image.getHeight() / 2 | 0;\n }\n const halfsize = initSize / 2 | 0;\n this.leftInit = x - halfsize;\n this.rightInit = x + halfsize;\n this.upInit = y - halfsize;\n this.downInit = y + halfsize;\n if (this.upInit < 0 || this.leftInit < 0 || this.downInit >= this.height || this.rightInit >= this.width) {\n throw new NotFoundException();\n }\n }\n /**\n *

\n * Detects a candidate barcode-like rectangular region within an image. It\n * starts around the center of the image, increases the size of the candidate\n * region until it finds a white rectangular region.\n *

\n *\n * @return {@link ResultPoint}[] describing the corners of the rectangular\n * region. The first and last points are opposed on the diagonal, as\n * are the second and third. The first point will be the topmost\n * point and the last, the bottommost. The second point will be\n * leftmost and the third, the rightmost\n * @throws NotFoundException if no Data Matrix Code can be found\n */\n detect() {\n let left = this.leftInit;\n let right = this.rightInit;\n let up = this.upInit;\n let down = this.downInit;\n let sizeExceeded = false;\n let aBlackPointFoundOnBorder = true;\n let atLeastOneBlackPointFoundOnBorder = false;\n let atLeastOneBlackPointFoundOnRight = false;\n let atLeastOneBlackPointFoundOnBottom = false;\n let atLeastOneBlackPointFoundOnLeft = false;\n let atLeastOneBlackPointFoundOnTop = false;\n const width = this.width;\n const height = this.height;\n while (aBlackPointFoundOnBorder) {\n aBlackPointFoundOnBorder = false;\n // .....\n // . |\n // .....\n let rightBorderNotWhite = true;\n while ((rightBorderNotWhite || !atLeastOneBlackPointFoundOnRight) && right < width) {\n rightBorderNotWhite = this.containsBlackPoint(up, down, right, false);\n if (rightBorderNotWhite) {\n right++;\n aBlackPointFoundOnBorder = true;\n atLeastOneBlackPointFoundOnRight = true;\n }\n else if (!atLeastOneBlackPointFoundOnRight) {\n right++;\n }\n }\n if (right >= width) {\n sizeExceeded = true;\n break;\n }\n // .....\n // . .\n // .___.\n let bottomBorderNotWhite = true;\n while ((bottomBorderNotWhite || !atLeastOneBlackPointFoundOnBottom) && down < height) {\n bottomBorderNotWhite = this.containsBlackPoint(left, right, down, true);\n if (bottomBorderNotWhite) {\n down++;\n aBlackPointFoundOnBorder = true;\n atLeastOneBlackPointFoundOnBottom = true;\n }\n else if (!atLeastOneBlackPointFoundOnBottom) {\n down++;\n }\n }\n if (down >= height) {\n sizeExceeded = true;\n break;\n }\n // .....\n // | .\n // .....\n let leftBorderNotWhite = true;\n while ((leftBorderNotWhite || !atLeastOneBlackPointFoundOnLeft) && left >= 0) {\n leftBorderNotWhite = this.containsBlackPoint(up, down, left, false);\n if (leftBorderNotWhite) {\n left--;\n aBlackPointFoundOnBorder = true;\n atLeastOneBlackPointFoundOnLeft = true;\n }\n else if (!atLeastOneBlackPointFoundOnLeft) {\n left--;\n }\n }\n if (left < 0) {\n sizeExceeded = true;\n break;\n }\n // .___.\n // . .\n // .....\n let topBorderNotWhite = true;\n while ((topBorderNotWhite || !atLeastOneBlackPointFoundOnTop) && up >= 0) {\n topBorderNotWhite = this.containsBlackPoint(left, right, up, true);\n if (topBorderNotWhite) {\n up--;\n aBlackPointFoundOnBorder = true;\n atLeastOneBlackPointFoundOnTop = true;\n }\n else if (!atLeastOneBlackPointFoundOnTop) {\n up--;\n }\n }\n if (up < 0) {\n sizeExceeded = true;\n break;\n }\n if (aBlackPointFoundOnBorder) {\n atLeastOneBlackPointFoundOnBorder = true;\n }\n }\n if (!sizeExceeded && atLeastOneBlackPointFoundOnBorder) {\n const maxSize = right - left;\n let z = null;\n for (let i = 1; z === null && i < maxSize; i++) {\n z = this.getBlackPointOnSegment(left, down - i, left + i, down);\n }\n if (z == null) {\n throw new NotFoundException();\n }\n let t = null;\n // go down right\n for (let i = 1; t === null && i < maxSize; i++) {\n t = this.getBlackPointOnSegment(left, up + i, left + i, up);\n }\n if (t == null) {\n throw new NotFoundException();\n }\n let x = null;\n // go down left\n for (let i = 1; x === null && i < maxSize; i++) {\n x = this.getBlackPointOnSegment(right, up + i, right - i, up);\n }\n if (x == null) {\n throw new NotFoundException();\n }\n let y = null;\n // go up left\n for (let i = 1; y === null && i < maxSize; i++) {\n y = this.getBlackPointOnSegment(right, down - i, right - i, down);\n }\n if (y == null) {\n throw new NotFoundException();\n }\n return this.centerEdges(y, z, x, t);\n }\n else {\n throw new NotFoundException();\n }\n }\n getBlackPointOnSegment(aX /*float*/, aY /*float*/, bX /*float*/, bY /*float*/) {\n const dist = MathUtils.round(MathUtils.distance(aX, aY, bX, bY));\n const xStep = (bX - aX) / dist;\n const yStep = (bY - aY) / dist;\n const image = this.image;\n for (let i = 0; i < dist; i++) {\n const x = MathUtils.round(aX + i * xStep);\n const y = MathUtils.round(aY + i * yStep);\n if (image.get(x, y)) {\n return new ResultPoint(x, y);\n }\n }\n return null;\n }\n /**\n * recenters the points of a constant distance towards the center\n *\n * @param y bottom most point\n * @param z left most point\n * @param x right most point\n * @param t top most point\n * @return {@link ResultPoint}[] describing the corners of the rectangular\n * region. The first and last points are opposed on the diagonal, as\n * are the second and third. The first point will be the topmost\n * point and the last, the bottommost. The second point will be\n * leftmost and the third, the rightmost\n */\n centerEdges(y, z, x, t) {\n //\n // t t\n // z x\n // x OR z\n // y y\n //\n const yi = y.getX();\n const yj = y.getY();\n const zi = z.getX();\n const zj = z.getY();\n const xi = x.getX();\n const xj = x.getY();\n const ti = t.getX();\n const tj = t.getY();\n const CORR = WhiteRectangleDetector.CORR;\n if (yi < this.width / 2.0) {\n return [\n new ResultPoint(ti - CORR, tj + CORR),\n new ResultPoint(zi + CORR, zj + CORR),\n new ResultPoint(xi - CORR, xj - CORR),\n new ResultPoint(yi + CORR, yj - CORR)\n ];\n }\n else {\n return [\n new ResultPoint(ti + CORR, tj + CORR),\n new ResultPoint(zi + CORR, zj - CORR),\n new ResultPoint(xi - CORR, xj + CORR),\n new ResultPoint(yi - CORR, yj - CORR)\n ];\n }\n }\n /**\n * Determines whether a segment contains a black point\n *\n * @param a min value of the scanned coordinate\n * @param b max value of the scanned coordinate\n * @param fixed value of fixed coordinate\n * @param horizontal set to true if scan must be horizontal, false if vertical\n * @return true if a black point has been found, else false.\n */\n containsBlackPoint(a /*int*/, b /*int*/, fixed /*int*/, horizontal) {\n const image = this.image;\n if (horizontal) {\n for (let x = a; x <= b; x++) {\n if (image.get(x, fixed)) {\n return true;\n }\n }\n }\n else {\n for (let y = a; y <= b; y++) {\n if (image.get(fixed, y)) {\n return true;\n }\n }\n }\n return false;\n }\n }\n WhiteRectangleDetector.INIT_SIZE = 10;\n WhiteRectangleDetector.CORR = 1;\n\n /*\n * Copyright 2007 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n /**\n * Implementations of this class can, given locations of finder patterns for a QR code in an\n * image, sample the right points in the image to reconstruct the QR code, accounting for\n * perspective distortion. It is abstracted since it is relatively expensive and should be allowed\n * to take advantage of platform-specific optimized implementations, like Sun's Java Advanced\n * Imaging library, but which may not be available in other environments such as J2ME, and vice\n * versa.\n *\n * The implementation used can be controlled by calling {@link #setGridSampler(GridSampler)}\n * with an instance of a class which implements this interface.\n *\n * @author Sean Owen\n */\n class GridSampler {\n /**\n *

Checks a set of points that have been transformed to sample points on an image against\n * the image's dimensions to see if the point are even within the image.

\n *\n *

This method will actually \"nudge\" the endpoints back onto the image if they are found to be\n * barely (less than 1 pixel) off the image. This accounts for imperfect detection of finder\n * patterns in an image where the QR Code runs all the way to the image border.

\n *\n *

For efficiency, the method will check points from either end of the line until one is found\n * to be within the image. Because the set of points are assumed to be linear, this is valid.

\n *\n * @param image image into which the points should map\n * @param points actual points in x1,y1,...,xn,yn form\n * @throws NotFoundException if an endpoint is lies outside the image boundaries\n */\n static checkAndNudgePoints(image, points) {\n const width = image.getWidth();\n const height = image.getHeight();\n // Check and nudge points from start until we see some that are OK:\n let nudged = true;\n for (let offset = 0; offset < points.length && nudged; offset += 2) {\n const x = Math.floor(points[offset]);\n const y = Math.floor(points[offset + 1]);\n if (x < -1 || x > width || y < -1 || y > height) {\n throw new NotFoundException();\n }\n nudged = false;\n if (x === -1) {\n points[offset] = 0.0;\n nudged = true;\n }\n else if (x === width) {\n points[offset] = width - 1;\n nudged = true;\n }\n if (y === -1) {\n points[offset + 1] = 0.0;\n nudged = true;\n }\n else if (y === height) {\n points[offset + 1] = height - 1;\n nudged = true;\n }\n }\n // Check and nudge points from end:\n nudged = true;\n for (let offset = points.length - 2; offset >= 0 && nudged; offset -= 2) {\n const x = Math.floor(points[offset]);\n const y = Math.floor(points[offset + 1]);\n if (x < -1 || x > width || y < -1 || y > height) {\n throw new NotFoundException();\n }\n nudged = false;\n if (x === -1) {\n points[offset] = 0.0;\n nudged = true;\n }\n else if (x === width) {\n points[offset] = width - 1;\n nudged = true;\n }\n if (y === -1) {\n points[offset + 1] = 0.0;\n nudged = true;\n }\n else if (y === height) {\n points[offset + 1] = height - 1;\n nudged = true;\n }\n }\n }\n }\n\n /*\n * Copyright 2007 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n /*namespace com.google.zxing.common {*/\n /**\n *

This class implements a perspective transform in two dimensions. Given four source and four\n * destination points, it will compute the transformation implied between them. The code is based\n * directly upon section 3.4.2 of George Wolberg's \"Digital Image Warping\"; see pages 54-56.

\n *\n * @author Sean Owen\n */\n class PerspectiveTransform {\n constructor(a11 /*float*/, a21 /*float*/, a31 /*float*/, a12 /*float*/, a22 /*float*/, a32 /*float*/, a13 /*float*/, a23 /*float*/, a33 /*float*/) {\n this.a11 = a11;\n this.a21 = a21;\n this.a31 = a31;\n this.a12 = a12;\n this.a22 = a22;\n this.a32 = a32;\n this.a13 = a13;\n this.a23 = a23;\n this.a33 = a33;\n }\n static quadrilateralToQuadrilateral(x0 /*float*/, y0 /*float*/, x1 /*float*/, y1 /*float*/, x2 /*float*/, y2 /*float*/, x3 /*float*/, y3 /*float*/, x0p /*float*/, y0p /*float*/, x1p /*float*/, y1p /*float*/, x2p /*float*/, y2p /*float*/, x3p /*float*/, y3p /*float*/) {\n const qToS = PerspectiveTransform.quadrilateralToSquare(x0, y0, x1, y1, x2, y2, x3, y3);\n const sToQ = PerspectiveTransform.squareToQuadrilateral(x0p, y0p, x1p, y1p, x2p, y2p, x3p, y3p);\n return sToQ.times(qToS);\n }\n transformPoints(points) {\n const max = points.length;\n const a11 = this.a11;\n const a12 = this.a12;\n const a13 = this.a13;\n const a21 = this.a21;\n const a22 = this.a22;\n const a23 = this.a23;\n const a31 = this.a31;\n const a32 = this.a32;\n const a33 = this.a33;\n for (let i = 0; i < max; i += 2) {\n const x = points[i];\n const y = points[i + 1];\n const denominator = a13 * x + a23 * y + a33;\n points[i] = (a11 * x + a21 * y + a31) / denominator;\n points[i + 1] = (a12 * x + a22 * y + a32) / denominator;\n }\n }\n transformPointsWithValues(xValues, yValues) {\n const a11 = this.a11;\n const a12 = this.a12;\n const a13 = this.a13;\n const a21 = this.a21;\n const a22 = this.a22;\n const a23 = this.a23;\n const a31 = this.a31;\n const a32 = this.a32;\n const a33 = this.a33;\n const n = xValues.length;\n for (let i = 0; i < n; i++) {\n const x = xValues[i];\n const y = yValues[i];\n const denominator = a13 * x + a23 * y + a33;\n xValues[i] = (a11 * x + a21 * y + a31) / denominator;\n yValues[i] = (a12 * x + a22 * y + a32) / denominator;\n }\n }\n static squareToQuadrilateral(x0 /*float*/, y0 /*float*/, x1 /*float*/, y1 /*float*/, x2 /*float*/, y2 /*float*/, x3 /*float*/, y3 /*float*/) {\n const dx3 = x0 - x1 + x2 - x3;\n const dy3 = y0 - y1 + y2 - y3;\n if (dx3 === 0.0 && dy3 === 0.0) {\n // Affine\n return new PerspectiveTransform(x1 - x0, x2 - x1, x0, y1 - y0, y2 - y1, y0, 0.0, 0.0, 1.0);\n }\n else {\n const dx1 = x1 - x2;\n const dx2 = x3 - x2;\n const dy1 = y1 - y2;\n const dy2 = y3 - y2;\n const denominator = dx1 * dy2 - dx2 * dy1;\n const a13 = (dx3 * dy2 - dx2 * dy3) / denominator;\n const a23 = (dx1 * dy3 - dx3 * dy1) / denominator;\n return new PerspectiveTransform(x1 - x0 + a13 * x1, x3 - x0 + a23 * x3, x0, y1 - y0 + a13 * y1, y3 - y0 + a23 * y3, y0, a13, a23, 1.0);\n }\n }\n static quadrilateralToSquare(x0 /*float*/, y0 /*float*/, x1 /*float*/, y1 /*float*/, x2 /*float*/, y2 /*float*/, x3 /*float*/, y3 /*float*/) {\n // Here, the adjoint serves as the inverse:\n return PerspectiveTransform.squareToQuadrilateral(x0, y0, x1, y1, x2, y2, x3, y3).buildAdjoint();\n }\n buildAdjoint() {\n // Adjoint is the transpose of the cofactor matrix:\n return new PerspectiveTransform(this.a22 * this.a33 - this.a23 * this.a32, this.a23 * this.a31 - this.a21 * this.a33, this.a21 * this.a32 - this.a22 * this.a31, this.a13 * this.a32 - this.a12 * this.a33, this.a11 * this.a33 - this.a13 * this.a31, this.a12 * this.a31 - this.a11 * this.a32, this.a12 * this.a23 - this.a13 * this.a22, this.a13 * this.a21 - this.a11 * this.a23, this.a11 * this.a22 - this.a12 * this.a21);\n }\n times(other) {\n return new PerspectiveTransform(this.a11 * other.a11 + this.a21 * other.a12 + this.a31 * other.a13, this.a11 * other.a21 + this.a21 * other.a22 + this.a31 * other.a23, this.a11 * other.a31 + this.a21 * other.a32 + this.a31 * other.a33, this.a12 * other.a11 + this.a22 * other.a12 + this.a32 * other.a13, this.a12 * other.a21 + this.a22 * other.a22 + this.a32 * other.a23, this.a12 * other.a31 + this.a22 * other.a32 + this.a32 * other.a33, this.a13 * other.a11 + this.a23 * other.a12 + this.a33 * other.a13, this.a13 * other.a21 + this.a23 * other.a22 + this.a33 * other.a23, this.a13 * other.a31 + this.a23 * other.a32 + this.a33 * other.a33);\n }\n }\n\n /*\n * Copyright 2007 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n /**\n * @author Sean Owen\n */\n class DefaultGridSampler extends GridSampler {\n /*@Override*/\n sampleGrid(image, dimensionX /*int*/, dimensionY /*int*/, p1ToX /*float*/, p1ToY /*float*/, p2ToX /*float*/, p2ToY /*float*/, p3ToX /*float*/, p3ToY /*float*/, p4ToX /*float*/, p4ToY /*float*/, p1FromX /*float*/, p1FromY /*float*/, p2FromX /*float*/, p2FromY /*float*/, p3FromX /*float*/, p3FromY /*float*/, p4FromX /*float*/, p4FromY /*float*/) {\n const transform = PerspectiveTransform.quadrilateralToQuadrilateral(p1ToX, p1ToY, p2ToX, p2ToY, p3ToX, p3ToY, p4ToX, p4ToY, p1FromX, p1FromY, p2FromX, p2FromY, p3FromX, p3FromY, p4FromX, p4FromY);\n return this.sampleGridWithTransform(image, dimensionX, dimensionY, transform);\n }\n /*@Override*/\n sampleGridWithTransform(image, dimensionX /*int*/, dimensionY /*int*/, transform) {\n if (dimensionX <= 0 || dimensionY <= 0) {\n throw new NotFoundException();\n }\n const bits = new BitMatrix(dimensionX, dimensionY);\n const points = new Float32Array(2 * dimensionX);\n for (let y = 0; y < dimensionY; y++) {\n const max = points.length;\n const iValue = y + 0.5;\n for (let x = 0; x < max; x += 2) {\n points[x] = (x / 2) + 0.5;\n points[x + 1] = iValue;\n }\n transform.transformPoints(points);\n // Quick check to see if points transformed to something inside the image\n // sufficient to check the endpoints\n GridSampler.checkAndNudgePoints(image, points);\n try {\n for (let x = 0; x < max; x += 2) {\n if (image.get(Math.floor(points[x]), Math.floor(points[x + 1]))) {\n // Black(-ish) pixel\n bits.set(x / 2, y);\n }\n }\n }\n catch (aioobe /*: ArrayIndexOutOfBoundsException*/) {\n // This feels wrong, but, sometimes if the finder patterns are misidentified, the resulting\n // transform gets \"twisted\" such that it maps a straight line of points to a set of points\n // whose endpoints are in bounds, but others are not. There is probably some mathematical\n // way to detect this about the transformation that I don't know yet.\n // This results in an ugly runtime exception despite our clever checks above -- can't have\n // that. We could check each point's coordinates but that feels duplicative. We settle for\n // catching and wrapping ArrayIndexOutOfBoundsException.\n throw new NotFoundException();\n }\n }\n return bits;\n }\n }\n\n class GridSamplerInstance {\n /**\n * Sets the implementation of GridSampler used by the library. One global\n * instance is stored, which may sound problematic. But, the implementation provided\n * ought to be appropriate for the entire platform, and all uses of this library\n * in the whole lifetime of the JVM. For instance, an Android activity can swap in\n * an implementation that takes advantage of native platform libraries.\n *\n * @param newGridSampler The platform-specific object to install.\n */\n static setGridSampler(newGridSampler) {\n GridSamplerInstance.gridSampler = newGridSampler;\n }\n /**\n * @return the current implementation of GridSampler\n */\n static getInstance() {\n return GridSamplerInstance.gridSampler;\n }\n }\n GridSamplerInstance.gridSampler = new DefaultGridSampler();\n\n /*\n * Copyright 2010 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n class Point {\n constructor(x, y) {\n this.x = x;\n this.y = y;\n }\n toResultPoint() {\n return new ResultPoint(this.getX(), this.getY());\n }\n getX() {\n return this.x;\n }\n getY() {\n return this.y;\n }\n }\n /**\n * Encapsulates logic that can detect an Aztec Code in an image, even if the Aztec Code\n * is rotated or skewed, or partially obscured.\n *\n * @author David Olivier\n * @author Frank Yellin\n */\n class Detector {\n constructor(image) {\n this.EXPECTED_CORNER_BITS = new Int32Array([\n 0xee0,\n 0x1dc,\n 0x83b,\n 0x707,\n ]);\n this.image = image;\n }\n detect() {\n return this.detectMirror(false);\n }\n /**\n * Detects an Aztec Code in an image.\n *\n * @param isMirror if true, image is a mirror-image of original\n * @return {@link AztecDetectorResult} encapsulating results of detecting an Aztec Code\n * @throws NotFoundException if no Aztec Code can be found\n */\n detectMirror(isMirror) {\n // 1. Get the center of the aztec matrix\n let pCenter = this.getMatrixCenter();\n // 2. Get the center points of the four diagonal points just outside the bull's eye\n // [topRight, bottomRight, bottomLeft, topLeft]\n let bullsEyeCorners = this.getBullsEyeCorners(pCenter);\n if (isMirror) {\n let temp = bullsEyeCorners[0];\n bullsEyeCorners[0] = bullsEyeCorners[2];\n bullsEyeCorners[2] = temp;\n }\n // 3. Get the size of the matrix and other parameters from the bull's eye\n this.extractParameters(bullsEyeCorners);\n // 4. Sample the grid\n let bits = this.sampleGrid(this.image, bullsEyeCorners[this.shift % 4], bullsEyeCorners[(this.shift + 1) % 4], bullsEyeCorners[(this.shift + 2) % 4], bullsEyeCorners[(this.shift + 3) % 4]);\n // 5. Get the corners of the matrix.\n let corners = this.getMatrixCornerPoints(bullsEyeCorners);\n return new AztecDetectorResult(bits, corners, this.compact, this.nbDataBlocks, this.nbLayers);\n }\n /**\n * Extracts the number of data layers and data blocks from the layer around the bull's eye.\n *\n * @param bullsEyeCorners the array of bull's eye corners\n * @throws NotFoundException in case of too many errors or invalid parameters\n */\n extractParameters(bullsEyeCorners) {\n if (!this.isValidPoint(bullsEyeCorners[0]) || !this.isValidPoint(bullsEyeCorners[1]) ||\n !this.isValidPoint(bullsEyeCorners[2]) || !this.isValidPoint(bullsEyeCorners[3])) {\n throw new NotFoundException();\n }\n let length = 2 * this.nbCenterLayers;\n // Get the bits around the bull's eye\n let sides = new Int32Array([\n this.sampleLine(bullsEyeCorners[0], bullsEyeCorners[1], length),\n this.sampleLine(bullsEyeCorners[1], bullsEyeCorners[2], length),\n this.sampleLine(bullsEyeCorners[2], bullsEyeCorners[3], length),\n this.sampleLine(bullsEyeCorners[3], bullsEyeCorners[0], length) // Top\n ]);\n // bullsEyeCorners[shift] is the corner of the bulls'eye that has three\n // orientation marks.\n // sides[shift] is the row/column that goes from the corner with three\n // orientation marks to the corner with two.\n this.shift = this.getRotation(sides, length);\n // Flatten the parameter bits into a single 28- or 40-bit long\n let parameterData = 0;\n for (let i = 0; i < 4; i++) {\n let side = sides[(this.shift + i) % 4];\n if (this.compact) {\n // Each side of the form ..XXXXXXX. where Xs are parameter data\n parameterData <<= 7;\n parameterData += (side >> 1) & 0x7F;\n }\n else {\n // Each side of the form ..XXXXX.XXXXX. where Xs are parameter data\n parameterData <<= 10;\n parameterData += ((side >> 2) & (0x1f << 5)) + ((side >> 1) & 0x1F);\n }\n }\n // Corrects parameter data using RS. Returns just the data portion\n // without the error correction.\n let correctedData = this.getCorrectedParameterData(parameterData, this.compact);\n if (this.compact) {\n // 8 bits: 2 bits layers and 6 bits data blocks\n this.nbLayers = (correctedData >> 6) + 1;\n this.nbDataBlocks = (correctedData & 0x3F) + 1;\n }\n else {\n // 16 bits: 5 bits layers and 11 bits data blocks\n this.nbLayers = (correctedData >> 11) + 1;\n this.nbDataBlocks = (correctedData & 0x7FF) + 1;\n }\n }\n getRotation(sides, length) {\n // In a normal pattern, we expect to See\n // ** .* D A\n // * *\n //\n // . *\n // .. .. C B\n //\n // Grab the 3 bits from each of the sides the form the locator pattern and concatenate\n // into a 12-bit integer. Start with the bit at A\n let cornerBits = 0;\n sides.forEach((side, idx, arr) => {\n // XX......X where X's are orientation marks\n let t = ((side >> (length - 2)) << 1) + (side & 1);\n cornerBits = (cornerBits << 3) + t;\n });\n // for (var side in sides) {\n // // XX......X where X's are orientation marks\n // var t = ((side >> (length - 2)) << 1) + (side & 1);\n // cornerBits = (cornerBits << 3) + t;\n // }\n // Mov the bottom bit to the top, so that the three bits of the locator pattern at A are\n // together. cornerBits is now:\n // 3 orientation bits at A || 3 orientation bits at B || ... || 3 orientation bits at D\n cornerBits = ((cornerBits & 1) << 11) + (cornerBits >> 1);\n // The result shift indicates which element of BullsEyeCorners[] goes into the top-left\n // corner. Since the four rotation values have a Hamming distance of 8, we\n // can easily tolerate two errors.\n for (let shift = 0; shift < 4; shift++) {\n if (Integer.bitCount(cornerBits ^ this.EXPECTED_CORNER_BITS[shift]) <= 2) {\n return shift;\n }\n }\n throw new NotFoundException();\n }\n /**\n * Corrects the parameter bits using Reed-Solomon algorithm.\n *\n * @param parameterData parameter bits\n * @param compact true if this is a compact Aztec code\n * @throws NotFoundException if the array contains too many errors\n */\n getCorrectedParameterData(parameterData, compact) {\n let numCodewords;\n let numDataCodewords;\n if (compact) {\n numCodewords = 7;\n numDataCodewords = 2;\n }\n else {\n numCodewords = 10;\n numDataCodewords = 4;\n }\n let numECCodewords = numCodewords - numDataCodewords;\n let parameterWords = new Int32Array(numCodewords);\n for (let i = numCodewords - 1; i >= 0; --i) {\n parameterWords[i] = parameterData & 0xF;\n parameterData >>= 4;\n }\n try {\n let rsDecoder = new ReedSolomonDecoder(GenericGF.AZTEC_PARAM);\n rsDecoder.decode(parameterWords, numECCodewords);\n }\n catch (ignored) {\n throw new NotFoundException();\n }\n // Toss the error correction. Just return the data as an integer\n let result = 0;\n for (let i = 0; i < numDataCodewords; i++) {\n result = (result << 4) + parameterWords[i];\n }\n return result;\n }\n /**\n * Finds the corners of a bull-eye centered on the passed point.\n * This returns the centers of the diagonal points just outside the bull's eye\n * Returns [topRight, bottomRight, bottomLeft, topLeft]\n *\n * @param pCenter Center point\n * @return The corners of the bull-eye\n * @throws NotFoundException If no valid bull-eye can be found\n */\n getBullsEyeCorners(pCenter) {\n let pina = pCenter;\n let pinb = pCenter;\n let pinc = pCenter;\n let pind = pCenter;\n let color = true;\n for (this.nbCenterLayers = 1; this.nbCenterLayers < 9; this.nbCenterLayers++) {\n let pouta = this.getFirstDifferent(pina, color, 1, -1);\n let poutb = this.getFirstDifferent(pinb, color, 1, 1);\n let poutc = this.getFirstDifferent(pinc, color, -1, 1);\n let poutd = this.getFirstDifferent(pind, color, -1, -1);\n // d a\n //\n // c b\n if (this.nbCenterLayers > 2) {\n let q = (this.distancePoint(poutd, pouta) * this.nbCenterLayers) / (this.distancePoint(pind, pina) * (this.nbCenterLayers + 2));\n if (q < 0.75 || q > 1.25 || !this.isWhiteOrBlackRectangle(pouta, poutb, poutc, poutd)) {\n break;\n }\n }\n pina = pouta;\n pinb = poutb;\n pinc = poutc;\n pind = poutd;\n color = !color;\n }\n if (this.nbCenterLayers !== 5 && this.nbCenterLayers !== 7) {\n throw new NotFoundException();\n }\n this.compact = this.nbCenterLayers === 5;\n // Expand the square by .5 pixel in each direction so that we're on the border\n // between the white square and the black square\n let pinax = new ResultPoint(pina.getX() + 0.5, pina.getY() - 0.5);\n let pinbx = new ResultPoint(pinb.getX() + 0.5, pinb.getY() + 0.5);\n let pincx = new ResultPoint(pinc.getX() - 0.5, pinc.getY() + 0.5);\n let pindx = new ResultPoint(pind.getX() - 0.5, pind.getY() - 0.5);\n // Expand the square so that its corners are the centers of the points\n // just outside the bull's eye.\n return this.expandSquare([pinax, pinbx, pincx, pindx], 2 * this.nbCenterLayers - 3, 2 * this.nbCenterLayers);\n }\n /**\n * Finds a candidate center point of an Aztec code from an image\n *\n * @return the center point\n */\n getMatrixCenter() {\n let pointA;\n let pointB;\n let pointC;\n let pointD;\n // Get a white rectangle that can be the border of the matrix in center bull's eye or\n try {\n let cornerPoints = new WhiteRectangleDetector(this.image).detect();\n pointA = cornerPoints[0];\n pointB = cornerPoints[1];\n pointC = cornerPoints[2];\n pointD = cornerPoints[3];\n }\n catch (e) {\n // This exception can be in case the initial rectangle is white\n // In that case, surely in the bull's eye, we try to expand the rectangle.\n let cx = this.image.getWidth() / 2;\n let cy = this.image.getHeight() / 2;\n pointA = this.getFirstDifferent(new Point(cx + 7, cy - 7), false, 1, -1).toResultPoint();\n pointB = this.getFirstDifferent(new Point(cx + 7, cy + 7), false, 1, 1).toResultPoint();\n pointC = this.getFirstDifferent(new Point(cx - 7, cy + 7), false, -1, 1).toResultPoint();\n pointD = this.getFirstDifferent(new Point(cx - 7, cy - 7), false, -1, -1).toResultPoint();\n }\n // Compute the center of the rectangle\n let cx = MathUtils.round((pointA.getX() + pointD.getX() + pointB.getX() + pointC.getX()) / 4.0);\n let cy = MathUtils.round((pointA.getY() + pointD.getY() + pointB.getY() + pointC.getY()) / 4.0);\n // Redetermine the white rectangle starting from previously computed center.\n // This will ensure that we end up with a white rectangle in center bull's eye\n // in order to compute a more accurate center.\n try {\n let cornerPoints = new WhiteRectangleDetector(this.image, 15, cx, cy).detect();\n pointA = cornerPoints[0];\n pointB = cornerPoints[1];\n pointC = cornerPoints[2];\n pointD = cornerPoints[3];\n }\n catch (e) {\n // This exception can be in case the initial rectangle is white\n // In that case we try to expand the rectangle.\n pointA = this.getFirstDifferent(new Point(cx + 7, cy - 7), false, 1, -1).toResultPoint();\n pointB = this.getFirstDifferent(new Point(cx + 7, cy + 7), false, 1, 1).toResultPoint();\n pointC = this.getFirstDifferent(new Point(cx - 7, cy + 7), false, -1, 1).toResultPoint();\n pointD = this.getFirstDifferent(new Point(cx - 7, cy - 7), false, -1, -1).toResultPoint();\n }\n // Recompute the center of the rectangle\n cx = MathUtils.round((pointA.getX() + pointD.getX() + pointB.getX() + pointC.getX()) / 4.0);\n cy = MathUtils.round((pointA.getY() + pointD.getY() + pointB.getY() + pointC.getY()) / 4.0);\n return new Point(cx, cy);\n }\n /**\n * Gets the Aztec code corners from the bull's eye corners and the parameters.\n *\n * @param bullsEyeCorners the array of bull's eye corners\n * @return the array of aztec code corners\n */\n getMatrixCornerPoints(bullsEyeCorners) {\n return this.expandSquare(bullsEyeCorners, 2 * this.nbCenterLayers, this.getDimension());\n }\n /**\n * Creates a BitMatrix by sampling the provided image.\n * topLeft, topRight, bottomRight, and bottomLeft are the centers of the squares on the\n * diagonal just outside the bull's eye.\n */\n sampleGrid(image, topLeft, topRight, bottomRight, bottomLeft) {\n let sampler = GridSamplerInstance.getInstance();\n let dimension = this.getDimension();\n let low = dimension / 2 - this.nbCenterLayers;\n let high = dimension / 2 + this.nbCenterLayers;\n return sampler.sampleGrid(image, dimension, dimension, low, low, // topleft\n high, low, // topright\n high, high, // bottomright\n low, high, // bottomleft\n topLeft.getX(), topLeft.getY(), topRight.getX(), topRight.getY(), bottomRight.getX(), bottomRight.getY(), bottomLeft.getX(), bottomLeft.getY());\n }\n /**\n * Samples a line.\n *\n * @param p1 start point (inclusive)\n * @param p2 end point (exclusive)\n * @param size number of bits\n * @return the array of bits as an int (first bit is high-order bit of result)\n */\n sampleLine(p1, p2, size) {\n let result = 0;\n let d = this.distanceResultPoint(p1, p2);\n let moduleSize = d / size;\n let px = p1.getX();\n let py = p1.getY();\n let dx = moduleSize * (p2.getX() - p1.getX()) / d;\n let dy = moduleSize * (p2.getY() - p1.getY()) / d;\n for (let i = 0; i < size; i++) {\n if (this.image.get(MathUtils.round(px + i * dx), MathUtils.round(py + i * dy))) {\n result |= 1 << (size - i - 1);\n }\n }\n return result;\n }\n /**\n * @return true if the border of the rectangle passed in parameter is compound of white points only\n * or black points only\n */\n isWhiteOrBlackRectangle(p1, p2, p3, p4) {\n let corr = 3;\n p1 = new Point(p1.getX() - corr, p1.getY() + corr);\n p2 = new Point(p2.getX() - corr, p2.getY() - corr);\n p3 = new Point(p3.getX() + corr, p3.getY() - corr);\n p4 = new Point(p4.getX() + corr, p4.getY() + corr);\n let cInit = this.getColor(p4, p1);\n if (cInit === 0) {\n return false;\n }\n let c = this.getColor(p1, p2);\n if (c !== cInit) {\n return false;\n }\n c = this.getColor(p2, p3);\n if (c !== cInit) {\n return false;\n }\n c = this.getColor(p3, p4);\n return c === cInit;\n }\n /**\n * Gets the color of a segment\n *\n * @return 1 if segment more than 90% black, -1 if segment is more than 90% white, 0 else\n */\n getColor(p1, p2) {\n let d = this.distancePoint(p1, p2);\n let dx = (p2.getX() - p1.getX()) / d;\n let dy = (p2.getY() - p1.getY()) / d;\n let error = 0;\n let px = p1.getX();\n let py = p1.getY();\n let colorModel = this.image.get(p1.getX(), p1.getY());\n let iMax = Math.ceil(d);\n for (let i = 0; i < iMax; i++) {\n px += dx;\n py += dy;\n if (this.image.get(MathUtils.round(px), MathUtils.round(py)) !== colorModel) {\n error++;\n }\n }\n let errRatio = error / d;\n if (errRatio > 0.1 && errRatio < 0.9) {\n return 0;\n }\n return (errRatio <= 0.1) === colorModel ? 1 : -1;\n }\n /**\n * Gets the coordinate of the first point with a different color in the given direction\n */\n getFirstDifferent(init, color, dx, dy) {\n let x = init.getX() + dx;\n let y = init.getY() + dy;\n while (this.isValid(x, y) && this.image.get(x, y) === color) {\n x += dx;\n y += dy;\n }\n x -= dx;\n y -= dy;\n while (this.isValid(x, y) && this.image.get(x, y) === color) {\n x += dx;\n }\n x -= dx;\n while (this.isValid(x, y) && this.image.get(x, y) === color) {\n y += dy;\n }\n y -= dy;\n return new Point(x, y);\n }\n /**\n * Expand the square represented by the corner points by pushing out equally in all directions\n *\n * @param cornerPoints the corners of the square, which has the bull's eye at its center\n * @param oldSide the original length of the side of the square in the target bit matrix\n * @param newSide the new length of the size of the square in the target bit matrix\n * @return the corners of the expanded square\n */\n expandSquare(cornerPoints, oldSide, newSide) {\n let ratio = newSide / (2.0 * oldSide);\n let dx = cornerPoints[0].getX() - cornerPoints[2].getX();\n let dy = cornerPoints[0].getY() - cornerPoints[2].getY();\n let centerx = (cornerPoints[0].getX() + cornerPoints[2].getX()) / 2.0;\n let centery = (cornerPoints[0].getY() + cornerPoints[2].getY()) / 2.0;\n let result0 = new ResultPoint(centerx + ratio * dx, centery + ratio * dy);\n let result2 = new ResultPoint(centerx - ratio * dx, centery - ratio * dy);\n dx = cornerPoints[1].getX() - cornerPoints[3].getX();\n dy = cornerPoints[1].getY() - cornerPoints[3].getY();\n centerx = (cornerPoints[1].getX() + cornerPoints[3].getX()) / 2.0;\n centery = (cornerPoints[1].getY() + cornerPoints[3].getY()) / 2.0;\n let result1 = new ResultPoint(centerx + ratio * dx, centery + ratio * dy);\n let result3 = new ResultPoint(centerx - ratio * dx, centery - ratio * dy);\n let results = [result0, result1, result2, result3];\n return results;\n }\n isValid(x, y) {\n return x >= 0 && x < this.image.getWidth() && y > 0 && y < this.image.getHeight();\n }\n isValidPoint(point) {\n let x = MathUtils.round(point.getX());\n let y = MathUtils.round(point.getY());\n return this.isValid(x, y);\n }\n distancePoint(a, b) {\n return MathUtils.distance(a.getX(), a.getY(), b.getX(), b.getY());\n }\n distanceResultPoint(a, b) {\n return MathUtils.distance(a.getX(), a.getY(), b.getX(), b.getY());\n }\n getDimension() {\n if (this.compact) {\n return 4 * this.nbLayers + 11;\n }\n if (this.nbLayers <= 4) {\n return 4 * this.nbLayers + 15;\n }\n return 4 * this.nbLayers + 2 * (Integer.truncDivision((this.nbLayers - 4), 8) + 1) + 15;\n }\n }\n\n /*\n * Copyright 2010 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n // import java.util.List;\n // import java.util.Map;\n /**\n * This implementation can detect and decode Aztec codes in an image.\n *\n * @author David Olivier\n */\n class AztecReader {\n /**\n * Locates and decodes a Data Matrix code in an image.\n *\n * @return a String representing the content encoded by the Data Matrix code\n * @throws NotFoundException if a Data Matrix code cannot be found\n * @throws FormatException if a Data Matrix code cannot be decoded\n */\n decode(image, hints = null) {\n let exception = null;\n let detector = new Detector(image.getBlackMatrix());\n let points = null;\n let decoderResult = null;\n try {\n let detectorResult = detector.detectMirror(false);\n points = detectorResult.getPoints();\n this.reportFoundResultPoints(hints, points);\n decoderResult = new Decoder().decode(detectorResult);\n }\n catch (e) {\n exception = e;\n }\n if (decoderResult == null) {\n try {\n let detectorResult = detector.detectMirror(true);\n points = detectorResult.getPoints();\n this.reportFoundResultPoints(hints, points);\n decoderResult = new Decoder().decode(detectorResult);\n }\n catch (e) {\n if (exception != null) {\n throw exception;\n }\n throw e;\n }\n }\n let result = new Result(decoderResult.getText(), decoderResult.getRawBytes(), decoderResult.getNumBits(), points, BarcodeFormat$1.AZTEC, System.currentTimeMillis());\n let byteSegments = decoderResult.getByteSegments();\n if (byteSegments != null) {\n result.putMetadata(ResultMetadataType$1.BYTE_SEGMENTS, byteSegments);\n }\n let ecLevel = decoderResult.getECLevel();\n if (ecLevel != null) {\n result.putMetadata(ResultMetadataType$1.ERROR_CORRECTION_LEVEL, ecLevel);\n }\n return result;\n }\n reportFoundResultPoints(hints, points) {\n if (hints != null) {\n let rpcb = hints.get(DecodeHintType$1.NEED_RESULT_POINT_CALLBACK);\n if (rpcb != null) {\n points.forEach((point, idx, arr) => {\n rpcb.foundPossibleResultPoint(point);\n });\n }\n }\n }\n // @Override\n reset() {\n // do nothing\n }\n }\n\n /**\n * Aztec Code reader to use from browser.\n *\n * @class BrowserAztecCodeReader\n * @extends {BrowserCodeReader}\n */\n class BrowserAztecCodeReader extends BrowserCodeReader {\n /**\n * Creates an instance of BrowserAztecCodeReader.\n * @param {number} [timeBetweenScansMillis=500] the time delay between subsequent decode tries\n *\n * @memberOf BrowserAztecCodeReader\n */\n constructor(timeBetweenScansMillis = 500) {\n super(new AztecReader(), timeBetweenScansMillis);\n }\n }\n\n /**\n * Encapsulates functionality and implementation that is common to all families\n * of one-dimensional barcodes.\n *\n * @author dswitkin@google.com (Daniel Switkin)\n * @author Sean Owen\n */\n class OneDReader {\n /*\n @Override\n public Result decode(BinaryBitmap image) throws NotFoundException, FormatException {\n return decode(image, null);\n }\n */\n // Note that we don't try rotation without the try harder flag, even if rotation was supported.\n // @Override\n decode(image, hints) {\n try {\n return this.doDecode(image, hints);\n }\n catch (nfe) {\n const tryHarder = hints && (hints.get(DecodeHintType$1.TRY_HARDER) === true);\n if (tryHarder && image.isRotateSupported()) {\n const rotatedImage = image.rotateCounterClockwise();\n const result = this.doDecode(rotatedImage, hints);\n // Record that we found it rotated 90 degrees CCW / 270 degrees CW\n const metadata = result.getResultMetadata();\n let orientation = 270;\n if (metadata !== null && (metadata.get(ResultMetadataType$1.ORIENTATION) === true)) {\n // But if we found it reversed in doDecode(), add in that result here:\n orientation = (orientation + metadata.get(ResultMetadataType$1.ORIENTATION) % 360);\n }\n result.putMetadata(ResultMetadataType$1.ORIENTATION, orientation);\n // Update result points\n const points = result.getResultPoints();\n if (points !== null) {\n const height = rotatedImage.getHeight();\n for (let i = 0; i < points.length; i++) {\n points[i] = new ResultPoint(height - points[i].getY() - 1, points[i].getX());\n }\n }\n return result;\n }\n else {\n throw new NotFoundException();\n }\n }\n }\n // @Override\n reset() {\n // do nothing\n }\n /**\n * We're going to examine rows from the middle outward, searching alternately above and below the\n * middle, and farther out each time. rowStep is the number of rows between each successive\n * attempt above and below the middle. So we'd scan row middle, then middle - rowStep, then\n * middle + rowStep, then middle - (2 * rowStep), etc.\n * rowStep is bigger as the image is taller, but is always at least 1. We've somewhat arbitrarily\n * decided that moving up and down by about 1/16 of the image is pretty good; we try more of the\n * image if \"trying harder\".\n *\n * @param image The image to decode\n * @param hints Any hints that were requested\n * @return The contents of the decoded barcode\n * @throws NotFoundException Any spontaneous errors which occur\n */\n doDecode(image, hints) {\n const width = image.getWidth();\n const height = image.getHeight();\n let row = new BitArray(width);\n const tryHarder = hints && (hints.get(DecodeHintType$1.TRY_HARDER) === true);\n const rowStep = Math.max(1, height >> (tryHarder ? 8 : 5));\n let maxLines;\n if (tryHarder) {\n maxLines = height; // Look at the whole image, not just the center\n }\n else {\n maxLines = 15; // 15 rows spaced 1/32 apart is roughly the middle half of the image\n }\n const middle = Math.trunc(height / 2);\n for (let x = 0; x < maxLines; x++) {\n // Scanning from the middle out. Determine which row we're looking at next:\n const rowStepsAboveOrBelow = Math.trunc((x + 1) / 2);\n const isAbove = (x & 0x01) === 0; // i.e. is x even?\n const rowNumber = middle + rowStep * (isAbove ? rowStepsAboveOrBelow : -rowStepsAboveOrBelow);\n if (rowNumber < 0 || rowNumber >= height) {\n // Oops, if we run off the top or bottom, stop\n break;\n }\n // Estimate black point for this row and load it:\n try {\n row = image.getBlackRow(rowNumber, row);\n }\n catch (ignored) {\n continue;\n }\n // While we have the image data in a BitArray, it's fairly cheap to reverse it in place to\n // handle decoding upside down barcodes.\n for (let attempt = 0; attempt < 2; attempt++) {\n if (attempt === 1) { // trying again?\n row.reverse(); // reverse the row and continue\n // This means we will only ever draw result points *once* in the life of this method\n // since we want to avoid drawing the wrong points after flipping the row, and,\n // don't want to clutter with noise from every single row scan -- just the scans\n // that start on the center line.\n if (hints && (hints.get(DecodeHintType$1.NEED_RESULT_POINT_CALLBACK) === true)) {\n const newHints = new Map();\n hints.forEach((hint, key) => newHints.set(key, hint));\n newHints.delete(DecodeHintType$1.NEED_RESULT_POINT_CALLBACK);\n hints = newHints;\n }\n }\n try {\n // Look for a barcode\n const result = this.decodeRow(rowNumber, row, hints);\n // We found our barcode\n if (attempt === 1) {\n // But it was upside down, so note that\n result.putMetadata(ResultMetadataType$1.ORIENTATION, 180);\n // And remember to flip the result points horizontally.\n const points = result.getResultPoints();\n if (points !== null) {\n points[0] = new ResultPoint(width - points[0].getX() - 1, points[0].getY());\n points[1] = new ResultPoint(width - points[1].getX() - 1, points[1].getY());\n }\n }\n return result;\n }\n catch (re) {\n // continue -- just couldn't decode this row\n }\n }\n }\n throw new NotFoundException();\n }\n /**\n * Records the size of successive runs of white and black pixels in a row, starting at a given point.\n * The values are recorded in the given array, and the number of runs recorded is equal to the size\n * of the array. If the row starts on a white pixel at the given start point, then the first count\n * recorded is the run of white pixels starting from that point; likewise it is the count of a run\n * of black pixels if the row begin on a black pixels at that point.\n *\n * @param row row to count from\n * @param start offset into row to start at\n * @param counters array into which to record counts\n * @throws NotFoundException if counters cannot be filled entirely from row before running out\n * of pixels\n */\n static recordPattern(row, start, counters) {\n const numCounters = counters.length;\n for (let index = 0; index < numCounters; index++)\n counters[index] = 0;\n const end = row.getSize();\n if (start >= end) {\n throw new NotFoundException();\n }\n let isWhite = !row.get(start);\n let counterPosition = 0;\n let i = start;\n while (i < end) {\n if (row.get(i) !== isWhite) {\n counters[counterPosition]++;\n }\n else {\n if (++counterPosition === numCounters) {\n break;\n }\n else {\n counters[counterPosition] = 1;\n isWhite = !isWhite;\n }\n }\n i++;\n }\n // If we read fully the last section of pixels and filled up our counters -- or filled\n // the last counter but ran off the side of the image, OK. Otherwise, a problem.\n if (!(counterPosition === numCounters || (counterPosition === numCounters - 1 && i === end))) {\n throw new NotFoundException();\n }\n }\n static recordPatternInReverse(row, start, counters) {\n // This could be more efficient I guess\n let numTransitionsLeft = counters.length;\n let last = row.get(start);\n while (start > 0 && numTransitionsLeft >= 0) {\n if (row.get(--start) !== last) {\n numTransitionsLeft--;\n last = !last;\n }\n }\n if (numTransitionsLeft >= 0) {\n throw new NotFoundException();\n }\n OneDReader.recordPattern(row, start + 1, counters);\n }\n /**\n * Determines how closely a set of observed counts of runs of black/white values matches a given\n * target pattern. This is reported as the ratio of the total variance from the expected pattern\n * proportions across all pattern elements, to the length of the pattern.\n *\n * @param counters observed counters\n * @param pattern expected pattern\n * @param maxIndividualVariance The most any counter can differ before we give up\n * @return ratio of total variance between counters and pattern compared to total pattern size\n */\n static patternMatchVariance(counters, pattern, maxIndividualVariance) {\n const numCounters = counters.length;\n let total = 0;\n let patternLength = 0;\n for (let i = 0; i < numCounters; i++) {\n total += counters[i];\n patternLength += pattern[i];\n }\n if (total < patternLength) {\n // If we don't even have one pixel per unit of bar width, assume this is too small\n // to reliably match, so fail:\n return Number.POSITIVE_INFINITY;\n }\n const unitBarWidth = total / patternLength;\n maxIndividualVariance *= unitBarWidth;\n let totalVariance = 0.0;\n for (let x = 0; x < numCounters; x++) {\n const counter = counters[x];\n const scaledPattern = pattern[x] * unitBarWidth;\n const variance = counter > scaledPattern ? counter - scaledPattern : scaledPattern - counter;\n if (variance > maxIndividualVariance) {\n return Number.POSITIVE_INFINITY;\n }\n totalVariance += variance;\n }\n return totalVariance / total;\n }\n }\n\n /**\n *

Decodes Code 128 barcodes.

\n *\n * @author Sean Owen\n */\n class Code128Reader extends OneDReader {\n static findStartPattern(row) {\n const width = row.getSize();\n const rowOffset = row.getNextSet(0);\n let counterPosition = 0;\n let counters = Int32Array.from([0, 0, 0, 0, 0, 0]);\n let patternStart = rowOffset;\n let isWhite = false;\n const patternLength = 6;\n for (let i = rowOffset; i < width; i++) {\n if (row.get(i) !== isWhite) {\n counters[counterPosition]++;\n }\n else {\n if (counterPosition === (patternLength - 1)) {\n let bestVariance = Code128Reader.MAX_AVG_VARIANCE;\n let bestMatch = -1;\n for (let startCode = Code128Reader.CODE_START_A; startCode <= Code128Reader.CODE_START_C; startCode++) {\n const variance = OneDReader.patternMatchVariance(counters, Code128Reader.CODE_PATTERNS[startCode], Code128Reader.MAX_INDIVIDUAL_VARIANCE);\n if (variance < bestVariance) {\n bestVariance = variance;\n bestMatch = startCode;\n }\n }\n // Look for whitespace before start pattern, >= 50% of width of start pattern\n if (bestMatch >= 0 &&\n row.isRange(Math.max(0, patternStart - (i - patternStart) / 2), patternStart, false)) {\n return Int32Array.from([patternStart, i, bestMatch]);\n }\n patternStart += counters[0] + counters[1];\n counters = counters.slice(2, counters.length - 1);\n counters[counterPosition - 1] = 0;\n counters[counterPosition] = 0;\n counterPosition--;\n }\n else {\n counterPosition++;\n }\n counters[counterPosition] = 1;\n isWhite = !isWhite;\n }\n }\n throw new NotFoundException();\n }\n static decodeCode(row, counters, rowOffset) {\n OneDReader.recordPattern(row, rowOffset, counters);\n let bestVariance = Code128Reader.MAX_AVG_VARIANCE; // worst variance we'll accept\n let bestMatch = -1;\n for (let d = 0; d < Code128Reader.CODE_PATTERNS.length; d++) {\n const pattern = Code128Reader.CODE_PATTERNS[d];\n const variance = this.patternMatchVariance(counters, pattern, Code128Reader.MAX_INDIVIDUAL_VARIANCE);\n if (variance < bestVariance) {\n bestVariance = variance;\n bestMatch = d;\n }\n }\n // TODO We're overlooking the fact that the STOP pattern has 7 values, not 6.\n if (bestMatch >= 0) {\n return bestMatch;\n }\n else {\n throw new NotFoundException();\n }\n }\n decodeRow(rowNumber, row, hints) {\n const convertFNC1 = hints && (hints.get(DecodeHintType$1.ASSUME_GS1) === true);\n const startPatternInfo = Code128Reader.findStartPattern(row);\n const startCode = startPatternInfo[2];\n let currentRawCodesIndex = 0;\n const rawCodes = new Uint8Array(20);\n rawCodes[currentRawCodesIndex++] = startCode;\n let codeSet;\n switch (startCode) {\n case Code128Reader.CODE_START_A:\n codeSet = Code128Reader.CODE_CODE_A;\n break;\n case Code128Reader.CODE_START_B:\n codeSet = Code128Reader.CODE_CODE_B;\n break;\n case Code128Reader.CODE_START_C:\n codeSet = Code128Reader.CODE_CODE_C;\n break;\n default:\n throw new FormatException();\n }\n let done = false;\n let isNextShifted = false;\n let result = '';\n let lastStart = startPatternInfo[0];\n let nextStart = startPatternInfo[1];\n const counters = Int32Array.from([0, 0, 0, 0, 0, 0]);\n let lastCode = 0;\n let code = 0;\n let checksumTotal = startCode;\n let multiplier = 0;\n let lastCharacterWasPrintable = true;\n let upperMode = false;\n let shiftUpperMode = false;\n while (!done) {\n const unshift = isNextShifted;\n isNextShifted = false;\n // Save off last code\n lastCode = code;\n // Decode another code from image\n code = Code128Reader.decodeCode(row, counters, nextStart);\n rawCodes[currentRawCodesIndex++] = code;\n // Remember whether the last code was printable or not (excluding CODE_STOP)\n if (code !== Code128Reader.CODE_STOP) {\n lastCharacterWasPrintable = true;\n }\n // Add to checksum computation (if not CODE_STOP of course)\n if (code !== Code128Reader.CODE_STOP) {\n multiplier++;\n checksumTotal += multiplier * code;\n }\n // Advance to where the next code will to start\n lastStart = nextStart;\n nextStart += counters.reduce((previous, current) => previous + current, 0);\n // Take care of illegal start codes\n switch (code) {\n case Code128Reader.CODE_START_A:\n case Code128Reader.CODE_START_B:\n case Code128Reader.CODE_START_C:\n throw new FormatException();\n }\n switch (codeSet) {\n case Code128Reader.CODE_CODE_A:\n if (code < 64) {\n if (shiftUpperMode === upperMode) {\n result += String.fromCharCode((' '.charCodeAt(0) + code));\n }\n else {\n result += String.fromCharCode((' '.charCodeAt(0) + code + 128));\n }\n shiftUpperMode = false;\n }\n else if (code < 96) {\n if (shiftUpperMode === upperMode) {\n result += String.fromCharCode((code - 64));\n }\n else {\n result += String.fromCharCode((code + 64));\n }\n shiftUpperMode = false;\n }\n else {\n // Don't let CODE_STOP, which always appears, affect whether whether we think the last\n // code was printable or not.\n if (code !== Code128Reader.CODE_STOP) {\n lastCharacterWasPrintable = false;\n }\n switch (code) {\n case Code128Reader.CODE_FNC_1:\n if (convertFNC1) {\n if (result.length === 0) {\n // GS1 specification 5.4.3.7. and 5.4.6.4. If the first char after the start code\n // is FNC1 then this is GS1-128. We add the symbology identifier.\n result += ']C1';\n }\n else {\n // GS1 specification 5.4.7.5. Every subsequent FNC1 is returned as ASCII 29 (GS)\n result += String.fromCharCode(29);\n }\n }\n break;\n case Code128Reader.CODE_FNC_2:\n case Code128Reader.CODE_FNC_3:\n // do nothing?\n break;\n case Code128Reader.CODE_FNC_4_A:\n if (!upperMode && shiftUpperMode) {\n upperMode = true;\n shiftUpperMode = false;\n }\n else if (upperMode && shiftUpperMode) {\n upperMode = false;\n shiftUpperMode = false;\n }\n else {\n shiftUpperMode = true;\n }\n break;\n case Code128Reader.CODE_SHIFT:\n isNextShifted = true;\n codeSet = Code128Reader.CODE_CODE_B;\n break;\n case Code128Reader.CODE_CODE_B:\n codeSet = Code128Reader.CODE_CODE_B;\n break;\n case Code128Reader.CODE_CODE_C:\n codeSet = Code128Reader.CODE_CODE_C;\n break;\n case Code128Reader.CODE_STOP:\n done = true;\n break;\n }\n }\n break;\n case Code128Reader.CODE_CODE_B:\n if (code < 96) {\n if (shiftUpperMode === upperMode) {\n result += String.fromCharCode((' '.charCodeAt(0) + code));\n }\n else {\n result += String.fromCharCode((' '.charCodeAt(0) + code + 128));\n }\n shiftUpperMode = false;\n }\n else {\n if (code !== Code128Reader.CODE_STOP) {\n lastCharacterWasPrintable = false;\n }\n switch (code) {\n case Code128Reader.CODE_FNC_1:\n if (convertFNC1) {\n if (result.length === 0) {\n // GS1 specification 5.4.3.7. and 5.4.6.4. If the first char after the start code\n // is FNC1 then this is GS1-128. We add the symbology identifier.\n result += ']C1';\n }\n else {\n // GS1 specification 5.4.7.5. Every subsequent FNC1 is returned as ASCII 29 (GS)\n result += String.fromCharCode(29);\n }\n }\n break;\n case Code128Reader.CODE_FNC_2:\n case Code128Reader.CODE_FNC_3:\n // do nothing?\n break;\n case Code128Reader.CODE_FNC_4_B:\n if (!upperMode && shiftUpperMode) {\n upperMode = true;\n shiftUpperMode = false;\n }\n else if (upperMode && shiftUpperMode) {\n upperMode = false;\n shiftUpperMode = false;\n }\n else {\n shiftUpperMode = true;\n }\n break;\n case Code128Reader.CODE_SHIFT:\n isNextShifted = true;\n codeSet = Code128Reader.CODE_CODE_A;\n break;\n case Code128Reader.CODE_CODE_A:\n codeSet = Code128Reader.CODE_CODE_A;\n break;\n case Code128Reader.CODE_CODE_C:\n codeSet = Code128Reader.CODE_CODE_C;\n break;\n case Code128Reader.CODE_STOP:\n done = true;\n break;\n }\n }\n break;\n case Code128Reader.CODE_CODE_C:\n if (code < 100) {\n if (code < 10) {\n result += '0';\n }\n result += code;\n }\n else {\n if (code !== Code128Reader.CODE_STOP) {\n lastCharacterWasPrintable = false;\n }\n switch (code) {\n case Code128Reader.CODE_FNC_1:\n if (convertFNC1) {\n if (result.length === 0) {\n // GS1 specification 5.4.3.7. and 5.4.6.4. If the first char after the start code\n // is FNC1 then this is GS1-128. We add the symbology identifier.\n result += ']C1';\n }\n else {\n // GS1 specification 5.4.7.5. Every subsequent FNC1 is returned as ASCII 29 (GS)\n result += String.fromCharCode(29);\n }\n }\n break;\n case Code128Reader.CODE_CODE_A:\n codeSet = Code128Reader.CODE_CODE_A;\n break;\n case Code128Reader.CODE_CODE_B:\n codeSet = Code128Reader.CODE_CODE_B;\n break;\n case Code128Reader.CODE_STOP:\n done = true;\n break;\n }\n }\n break;\n }\n // Unshift back to another code set if we were shifted\n if (unshift) {\n codeSet = codeSet === Code128Reader.CODE_CODE_A ? Code128Reader.CODE_CODE_B : Code128Reader.CODE_CODE_A;\n }\n }\n const lastPatternSize = nextStart - lastStart;\n // Check for ample whitespace following pattern, but, to do this we first need to remember that\n // we fudged decoding CODE_STOP since it actually has 7 bars, not 6. There is a black bar left\n // to read off. Would be slightly better to properly read. Here we just skip it:\n nextStart = row.getNextUnset(nextStart);\n if (!row.isRange(nextStart, Math.min(row.getSize(), nextStart + (nextStart - lastStart) / 2), false)) {\n throw new NotFoundException();\n }\n // Pull out from sum the value of the penultimate check code\n checksumTotal -= multiplier * lastCode;\n // lastCode is the checksum then:\n if (checksumTotal % 103 !== lastCode) {\n throw new ChecksumException();\n }\n // Need to pull out the check digits from string\n const resultLength = result.length;\n if (resultLength === 0) {\n // false positive\n throw new NotFoundException();\n }\n // Only bother if the result had at least one character, and if the checksum digit happened to\n // be a printable character. If it was just interpreted as a control code, nothing to remove.\n if (resultLength > 0 && lastCharacterWasPrintable) {\n if (codeSet === Code128Reader.CODE_CODE_C) {\n result = result.substring(0, resultLength - 2);\n }\n else {\n result = result.substring(0, resultLength - 1);\n }\n }\n const left = (startPatternInfo[1] + startPatternInfo[0]) / 2.0;\n const right = lastStart + lastPatternSize / 2.0;\n const rawCodesSize = rawCodes.length;\n const rawBytes = new Uint8Array(rawCodesSize);\n for (let i = 0; i < rawCodesSize; i++) {\n rawBytes[i] = rawCodes[i];\n }\n const points = [new ResultPoint(left, rowNumber), new ResultPoint(right, rowNumber)];\n return new Result(result, rawBytes, 0, points, BarcodeFormat$1.CODE_128, new Date().getTime());\n }\n }\n Code128Reader.CODE_PATTERNS = [\n Int32Array.from([2, 1, 2, 2, 2, 2]),\n Int32Array.from([2, 2, 2, 1, 2, 2]),\n Int32Array.from([2, 2, 2, 2, 2, 1]),\n Int32Array.from([1, 2, 1, 2, 2, 3]),\n Int32Array.from([1, 2, 1, 3, 2, 2]),\n Int32Array.from([1, 3, 1, 2, 2, 2]),\n Int32Array.from([1, 2, 2, 2, 1, 3]),\n Int32Array.from([1, 2, 2, 3, 1, 2]),\n Int32Array.from([1, 3, 2, 2, 1, 2]),\n Int32Array.from([2, 2, 1, 2, 1, 3]),\n Int32Array.from([2, 2, 1, 3, 1, 2]),\n Int32Array.from([2, 3, 1, 2, 1, 2]),\n Int32Array.from([1, 1, 2, 2, 3, 2]),\n Int32Array.from([1, 2, 2, 1, 3, 2]),\n Int32Array.from([1, 2, 2, 2, 3, 1]),\n Int32Array.from([1, 1, 3, 2, 2, 2]),\n Int32Array.from([1, 2, 3, 1, 2, 2]),\n Int32Array.from([1, 2, 3, 2, 2, 1]),\n Int32Array.from([2, 2, 3, 2, 1, 1]),\n Int32Array.from([2, 2, 1, 1, 3, 2]),\n Int32Array.from([2, 2, 1, 2, 3, 1]),\n Int32Array.from([2, 1, 3, 2, 1, 2]),\n Int32Array.from([2, 2, 3, 1, 1, 2]),\n Int32Array.from([3, 1, 2, 1, 3, 1]),\n Int32Array.from([3, 1, 1, 2, 2, 2]),\n Int32Array.from([3, 2, 1, 1, 2, 2]),\n Int32Array.from([3, 2, 1, 2, 2, 1]),\n Int32Array.from([3, 1, 2, 2, 1, 2]),\n Int32Array.from([3, 2, 2, 1, 1, 2]),\n Int32Array.from([3, 2, 2, 2, 1, 1]),\n Int32Array.from([2, 1, 2, 1, 2, 3]),\n Int32Array.from([2, 1, 2, 3, 2, 1]),\n Int32Array.from([2, 3, 2, 1, 2, 1]),\n Int32Array.from([1, 1, 1, 3, 2, 3]),\n Int32Array.from([1, 3, 1, 1, 2, 3]),\n Int32Array.from([1, 3, 1, 3, 2, 1]),\n Int32Array.from([1, 1, 2, 3, 1, 3]),\n Int32Array.from([1, 3, 2, 1, 1, 3]),\n Int32Array.from([1, 3, 2, 3, 1, 1]),\n Int32Array.from([2, 1, 1, 3, 1, 3]),\n Int32Array.from([2, 3, 1, 1, 1, 3]),\n Int32Array.from([2, 3, 1, 3, 1, 1]),\n Int32Array.from([1, 1, 2, 1, 3, 3]),\n Int32Array.from([1, 1, 2, 3, 3, 1]),\n Int32Array.from([1, 3, 2, 1, 3, 1]),\n Int32Array.from([1, 1, 3, 1, 2, 3]),\n Int32Array.from([1, 1, 3, 3, 2, 1]),\n Int32Array.from([1, 3, 3, 1, 2, 1]),\n Int32Array.from([3, 1, 3, 1, 2, 1]),\n Int32Array.from([2, 1, 1, 3, 3, 1]),\n Int32Array.from([2, 3, 1, 1, 3, 1]),\n Int32Array.from([2, 1, 3, 1, 1, 3]),\n Int32Array.from([2, 1, 3, 3, 1, 1]),\n Int32Array.from([2, 1, 3, 1, 3, 1]),\n Int32Array.from([3, 1, 1, 1, 2, 3]),\n Int32Array.from([3, 1, 1, 3, 2, 1]),\n Int32Array.from([3, 3, 1, 1, 2, 1]),\n Int32Array.from([3, 1, 2, 1, 1, 3]),\n Int32Array.from([3, 1, 2, 3, 1, 1]),\n Int32Array.from([3, 3, 2, 1, 1, 1]),\n Int32Array.from([3, 1, 4, 1, 1, 1]),\n Int32Array.from([2, 2, 1, 4, 1, 1]),\n Int32Array.from([4, 3, 1, 1, 1, 1]),\n Int32Array.from([1, 1, 1, 2, 2, 4]),\n Int32Array.from([1, 1, 1, 4, 2, 2]),\n Int32Array.from([1, 2, 1, 1, 2, 4]),\n Int32Array.from([1, 2, 1, 4, 2, 1]),\n Int32Array.from([1, 4, 1, 1, 2, 2]),\n Int32Array.from([1, 4, 1, 2, 2, 1]),\n Int32Array.from([1, 1, 2, 2, 1, 4]),\n Int32Array.from([1, 1, 2, 4, 1, 2]),\n Int32Array.from([1, 2, 2, 1, 1, 4]),\n Int32Array.from([1, 2, 2, 4, 1, 1]),\n Int32Array.from([1, 4, 2, 1, 1, 2]),\n Int32Array.from([1, 4, 2, 2, 1, 1]),\n Int32Array.from([2, 4, 1, 2, 1, 1]),\n Int32Array.from([2, 2, 1, 1, 1, 4]),\n Int32Array.from([4, 1, 3, 1, 1, 1]),\n Int32Array.from([2, 4, 1, 1, 1, 2]),\n Int32Array.from([1, 3, 4, 1, 1, 1]),\n Int32Array.from([1, 1, 1, 2, 4, 2]),\n Int32Array.from([1, 2, 1, 1, 4, 2]),\n Int32Array.from([1, 2, 1, 2, 4, 1]),\n Int32Array.from([1, 1, 4, 2, 1, 2]),\n Int32Array.from([1, 2, 4, 1, 1, 2]),\n Int32Array.from([1, 2, 4, 2, 1, 1]),\n Int32Array.from([4, 1, 1, 2, 1, 2]),\n Int32Array.from([4, 2, 1, 1, 1, 2]),\n Int32Array.from([4, 2, 1, 2, 1, 1]),\n Int32Array.from([2, 1, 2, 1, 4, 1]),\n Int32Array.from([2, 1, 4, 1, 2, 1]),\n Int32Array.from([4, 1, 2, 1, 2, 1]),\n Int32Array.from([1, 1, 1, 1, 4, 3]),\n Int32Array.from([1, 1, 1, 3, 4, 1]),\n Int32Array.from([1, 3, 1, 1, 4, 1]),\n Int32Array.from([1, 1, 4, 1, 1, 3]),\n Int32Array.from([1, 1, 4, 3, 1, 1]),\n Int32Array.from([4, 1, 1, 1, 1, 3]),\n Int32Array.from([4, 1, 1, 3, 1, 1]),\n Int32Array.from([1, 1, 3, 1, 4, 1]),\n Int32Array.from([1, 1, 4, 1, 3, 1]),\n Int32Array.from([3, 1, 1, 1, 4, 1]),\n Int32Array.from([4, 1, 1, 1, 3, 1]),\n Int32Array.from([2, 1, 1, 4, 1, 2]),\n Int32Array.from([2, 1, 1, 2, 1, 4]),\n Int32Array.from([2, 1, 1, 2, 3, 2]),\n Int32Array.from([2, 3, 3, 1, 1, 1, 2]),\n ];\n Code128Reader.MAX_AVG_VARIANCE = 0.25;\n Code128Reader.MAX_INDIVIDUAL_VARIANCE = 0.7;\n Code128Reader.CODE_SHIFT = 98;\n Code128Reader.CODE_CODE_C = 99;\n Code128Reader.CODE_CODE_B = 100;\n Code128Reader.CODE_CODE_A = 101;\n Code128Reader.CODE_FNC_1 = 102;\n Code128Reader.CODE_FNC_2 = 97;\n Code128Reader.CODE_FNC_3 = 96;\n Code128Reader.CODE_FNC_4_A = 101;\n Code128Reader.CODE_FNC_4_B = 100;\n Code128Reader.CODE_START_A = 103;\n Code128Reader.CODE_START_B = 104;\n Code128Reader.CODE_START_C = 105;\n Code128Reader.CODE_STOP = 106;\n\n /**\n *

Decodes Code 39 barcodes. Supports \"Full ASCII Code 39\" if USE_CODE_39_EXTENDED_MODE is set.

\n *\n * @author Sean Owen\n * @see Code93Reader\n */\n class Code39Reader extends OneDReader {\n /**\n * Creates a reader that assumes all encoded data is data, and does not treat the final\n * character as a check digit. It will not decoded \"extended Code 39\" sequences.\n */\n // public Code39Reader() {\n // this(false);\n // }\n /**\n * Creates a reader that can be configured to check the last character as a check digit.\n * It will not decoded \"extended Code 39\" sequences.\n *\n * @param usingCheckDigit if true, treat the last data character as a check digit, not\n * data, and verify that the checksum passes.\n */\n // public Code39Reader(boolean usingCheckDigit) {\n // this(usingCheckDigit, false);\n // }\n /**\n * Creates a reader that can be configured to check the last character as a check digit,\n * or optionally attempt to decode \"extended Code 39\" sequences that are used to encode\n * the full ASCII character set.\n *\n * @param usingCheckDigit if true, treat the last data character as a check digit, not\n * data, and verify that the checksum passes.\n * @param extendedMode if true, will attempt to decode extended Code 39 sequences in the\n * text.\n */\n constructor(usingCheckDigit = false, extendedMode = false) {\n super();\n this.usingCheckDigit = usingCheckDigit;\n this.extendedMode = extendedMode;\n this.decodeRowResult = '';\n this.counters = new Int32Array(9);\n }\n decodeRow(rowNumber, row, hints) {\n let theCounters = this.counters;\n theCounters.fill(0);\n this.decodeRowResult = '';\n let start = Code39Reader.findAsteriskPattern(row, theCounters);\n // Read off white space\n let nextStart = row.getNextSet(start[1]);\n let end = row.getSize();\n let decodedChar;\n let lastStart;\n do {\n Code39Reader.recordPattern(row, nextStart, theCounters);\n let pattern = Code39Reader.toNarrowWidePattern(theCounters);\n if (pattern < 0) {\n throw new NotFoundException();\n }\n decodedChar = Code39Reader.patternToChar(pattern);\n this.decodeRowResult += decodedChar;\n lastStart = nextStart;\n for (let counter of theCounters) {\n nextStart += counter;\n }\n // Read off white space\n nextStart = row.getNextSet(nextStart);\n } while (decodedChar !== '*');\n this.decodeRowResult = this.decodeRowResult.substring(0, this.decodeRowResult.length - 1); // remove asterisk\n // Look for whitespace after pattern:\n let lastPatternSize = 0;\n for (let counter of theCounters) {\n lastPatternSize += counter;\n }\n let whiteSpaceAfterEnd = nextStart - lastStart - lastPatternSize;\n // If 50% of last pattern size, following last pattern, is not whitespace, fail\n // (but if it's whitespace to the very end of the image, that's OK)\n if (nextStart !== end && (whiteSpaceAfterEnd * 2) < lastPatternSize) {\n throw new NotFoundException();\n }\n if (this.usingCheckDigit) {\n let max = this.decodeRowResult.length - 1;\n let total = 0;\n for (let i = 0; i < max; i++) {\n total += Code39Reader.ALPHABET_STRING.indexOf(this.decodeRowResult.charAt(i));\n }\n if (this.decodeRowResult.charAt(max) !== Code39Reader.ALPHABET_STRING.charAt(total % 43)) {\n throw new ChecksumException();\n }\n this.decodeRowResult = this.decodeRowResult.substring(0, max);\n }\n if (this.decodeRowResult.length === 0) {\n // false positive\n throw new NotFoundException();\n }\n let resultString;\n if (this.extendedMode) {\n resultString = Code39Reader.decodeExtended(this.decodeRowResult);\n }\n else {\n resultString = this.decodeRowResult;\n }\n let left = (start[1] + start[0]) / 2.0;\n let right = lastStart + lastPatternSize / 2.0;\n return new Result(resultString, null, 0, [new ResultPoint(left, rowNumber), new ResultPoint(right, rowNumber)], BarcodeFormat$1.CODE_39, new Date().getTime());\n }\n static findAsteriskPattern(row, counters) {\n let width = row.getSize();\n let rowOffset = row.getNextSet(0);\n let counterPosition = 0;\n let patternStart = rowOffset;\n let isWhite = false;\n let patternLength = counters.length;\n for (let i = rowOffset; i < width; i++) {\n if (row.get(i) !== isWhite) {\n counters[counterPosition]++;\n }\n else {\n if (counterPosition === patternLength - 1) {\n // Look for whitespace before start pattern, >= 50% of width of start pattern\n if (this.toNarrowWidePattern(counters) === Code39Reader.ASTERISK_ENCODING &&\n row.isRange(Math.max(0, patternStart - Math.floor((i - patternStart) / 2)), patternStart, false)) {\n return [patternStart, i];\n }\n patternStart += counters[0] + counters[1];\n counters.copyWithin(0, 2, 2 + counterPosition - 1);\n counters[counterPosition - 1] = 0;\n counters[counterPosition] = 0;\n counterPosition--;\n }\n else {\n counterPosition++;\n }\n counters[counterPosition] = 1;\n isWhite = !isWhite;\n }\n }\n throw new NotFoundException();\n }\n // For efficiency, returns -1 on failure. Not throwing here saved as many as 700 exceptions\n // per image when using some of our blackbox images.\n static toNarrowWidePattern(counters) {\n let numCounters = counters.length;\n let maxNarrowCounter = 0;\n let wideCounters;\n do {\n let minCounter = 0x7fffffff;\n for (let counter of counters) {\n if (counter < minCounter && counter > maxNarrowCounter) {\n minCounter = counter;\n }\n }\n maxNarrowCounter = minCounter;\n wideCounters = 0;\n let totalWideCountersWidth = 0;\n let pattern = 0;\n for (let i = 0; i < numCounters; i++) {\n let counter = counters[i];\n if (counter > maxNarrowCounter) {\n pattern |= 1 << (numCounters - 1 - i);\n wideCounters++;\n totalWideCountersWidth += counter;\n }\n }\n if (wideCounters === 3) {\n // Found 3 wide counters, but are they close enough in width?\n // We can perform a cheap, conservative check to see if any individual\n // counter is more than 1.5 times the average:\n for (let i = 0; i < numCounters && wideCounters > 0; i++) {\n let counter = counters[i];\n if (counter > maxNarrowCounter) {\n wideCounters--;\n // totalWideCountersWidth = 3 * average, so this checks if counter >= 3/2 * average\n if ((counter * 2) >= totalWideCountersWidth) {\n return -1;\n }\n }\n }\n return pattern;\n }\n } while (wideCounters > 3);\n return -1;\n }\n static patternToChar(pattern) {\n for (let i = 0; i < Code39Reader.CHARACTER_ENCODINGS.length; i++) {\n if (Code39Reader.CHARACTER_ENCODINGS[i] === pattern) {\n return Code39Reader.ALPHABET_STRING.charAt(i);\n }\n }\n if (pattern === Code39Reader.ASTERISK_ENCODING) {\n return '*';\n }\n throw new NotFoundException();\n }\n static decodeExtended(encoded) {\n let length = encoded.length;\n let decoded = '';\n for (let i = 0; i < length; i++) {\n let c = encoded.charAt(i);\n if (c === '+' || c === '$' || c === '%' || c === '/') {\n let next = encoded.charAt(i + 1);\n let decodedChar = '\\0';\n switch (c) {\n case '+':\n // +A to +Z map to a to z\n if (next >= 'A' && next <= 'Z') {\n decodedChar = String.fromCharCode(next.charCodeAt(0) + 32);\n }\n else {\n throw new FormatException();\n }\n break;\n case '$':\n // $A to $Z map to control codes SH to SB\n if (next >= 'A' && next <= 'Z') {\n decodedChar = String.fromCharCode(next.charCodeAt(0) - 64);\n }\n else {\n throw new FormatException();\n }\n break;\n case '%':\n // %A to %E map to control codes ESC to US\n if (next >= 'A' && next <= 'E') {\n decodedChar = String.fromCharCode(next.charCodeAt(0) - 38);\n }\n else if (next >= 'F' && next <= 'J') {\n decodedChar = String.fromCharCode(next.charCodeAt(0) - 11);\n }\n else if (next >= 'K' && next <= 'O') {\n decodedChar = String.fromCharCode(next.charCodeAt(0) + 16);\n }\n else if (next >= 'P' && next <= 'T') {\n decodedChar = String.fromCharCode(next.charCodeAt(0) + 43);\n }\n else if (next === 'U') {\n decodedChar = '\\0';\n }\n else if (next === 'V') {\n decodedChar = '@';\n }\n else if (next === 'W') {\n decodedChar = '`';\n }\n else if (next === 'X' || next === 'Y' || next === 'Z') {\n decodedChar = '\\x7f';\n }\n else {\n throw new FormatException();\n }\n break;\n case '/':\n // /A to /O map to ! to , and /Z maps to :\n if (next >= 'A' && next <= 'O') {\n decodedChar = String.fromCharCode(next.charCodeAt(0) - 32);\n }\n else if (next === 'Z') {\n decodedChar = ':';\n }\n else {\n throw new FormatException();\n }\n break;\n }\n decoded += decodedChar;\n // bump up i again since we read two characters\n i++;\n }\n else {\n decoded += c;\n }\n }\n return decoded;\n }\n }\n Code39Reader.ALPHABET_STRING = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-. $/+%';\n /**\n * These represent the encodings of characters, as patterns of wide and narrow bars.\n * The 9 least-significant bits of each int correspond to the pattern of wide and narrow,\n * with 1s representing \"wide\" and 0s representing narrow.\n */\n Code39Reader.CHARACTER_ENCODINGS = [\n 0x034, 0x121, 0x061, 0x160, 0x031, 0x130, 0x070, 0x025, 0x124, 0x064,\n 0x109, 0x049, 0x148, 0x019, 0x118, 0x058, 0x00D, 0x10C, 0x04C, 0x01C,\n 0x103, 0x043, 0x142, 0x013, 0x112, 0x052, 0x007, 0x106, 0x046, 0x016,\n 0x181, 0x0C1, 0x1C0, 0x091, 0x190, 0x0D0, 0x085, 0x184, 0x0C4, 0x0A8,\n 0x0A2, 0x08A, 0x02A // /-%\n ];\n Code39Reader.ASTERISK_ENCODING = 0x094;\n\n /**\n *

Decodes ITF barcodes.

\n *\n * @author Tjieco\n */\n class ITFReader extends OneDReader {\n constructor() {\n // private static W = 3; // Pixel width of a 3x wide line\n // private static w = 2; // Pixel width of a 2x wide line\n // private static N = 1; // Pixed width of a narrow line\n super(...arguments);\n // Stores the actual narrow line width of the image being decoded.\n this.narrowLineWidth = -1;\n }\n // See ITFWriter.PATTERNS\n /*\n \n /!**\n * Patterns of Wide / Narrow lines to indicate each digit\n *!/\n */\n decodeRow(rowNumber, row, hints) {\n // Find out where the Middle section (payload) starts & ends\n let startRange = this.decodeStart(row);\n let endRange = this.decodeEnd(row);\n let result = new StringBuilder();\n ITFReader.decodeMiddle(row, startRange[1], endRange[0], result);\n let resultString = result.toString();\n let allowedLengths = null;\n if (hints != null) {\n allowedLengths = hints.get(DecodeHintType$1.ALLOWED_LENGTHS);\n }\n if (allowedLengths == null) {\n allowedLengths = ITFReader.DEFAULT_ALLOWED_LENGTHS;\n }\n // To avoid false positives with 2D barcodes (and other patterns), make\n // an assumption that the decoded string must be a 'standard' length if it's short\n let length = resultString.length;\n let lengthOK = false;\n let maxAllowedLength = 0;\n for (let value of allowedLengths) {\n if (length === value) {\n lengthOK = true;\n break;\n }\n if (value > maxAllowedLength) {\n maxAllowedLength = value;\n }\n }\n if (!lengthOK && length > maxAllowedLength) {\n lengthOK = true;\n }\n if (!lengthOK) {\n throw new FormatException();\n }\n const points = [new ResultPoint(startRange[1], rowNumber), new ResultPoint(endRange[0], rowNumber)];\n let resultReturn = new Result(resultString, null, // no natural byte representation for these barcodes\n 0, points, BarcodeFormat$1.ITF, new Date().getTime());\n return resultReturn;\n }\n /*\n /!**\n * @param row row of black/white values to search\n * @param payloadStart offset of start pattern\n * @param resultString {@link StringBuilder} to append decoded chars to\n * @throws NotFoundException if decoding could not complete successfully\n *!/*/\n static decodeMiddle(row, payloadStart, payloadEnd, resultString) {\n // Digits are interleaved in pairs - 5 black lines for one digit, and the\n // 5\n // interleaved white lines for the second digit.\n // Therefore, need to scan 10 lines and then\n // split these into two arrays\n let counterDigitPair = new Int32Array(10); // 10\n let counterBlack = new Int32Array(5); // 5\n let counterWhite = new Int32Array(5); // 5\n counterDigitPair.fill(0);\n counterBlack.fill(0);\n counterWhite.fill(0);\n while (payloadStart < payloadEnd) {\n // Get 10 runs of black/white.\n OneDReader.recordPattern(row, payloadStart, counterDigitPair);\n // Split them into each array\n for (let k = 0; k < 5; k++) {\n let twoK = 2 * k;\n counterBlack[k] = counterDigitPair[twoK];\n counterWhite[k] = counterDigitPair[twoK + 1];\n }\n let bestMatch = ITFReader.decodeDigit(counterBlack);\n resultString.append(bestMatch.toString());\n bestMatch = this.decodeDigit(counterWhite);\n resultString.append(bestMatch.toString());\n counterDigitPair.forEach(function (counterDigit) {\n payloadStart += counterDigit;\n });\n }\n }\n /*/!**\n * Identify where the start of the middle / payload section starts.\n *\n * @param row row of black/white values to search\n * @return Array, containing index of start of 'start block' and end of\n * 'start block'\n *!/*/\n decodeStart(row) {\n let endStart = ITFReader.skipWhiteSpace(row);\n let startPattern = ITFReader.findGuardPattern(row, endStart, ITFReader.START_PATTERN);\n // Determine the width of a narrow line in pixels. We can do this by\n // getting the width of the start pattern and dividing by 4 because its\n // made up of 4 narrow lines.\n this.narrowLineWidth = (startPattern[1] - startPattern[0]) / 4;\n this.validateQuietZone(row, startPattern[0]);\n return startPattern;\n }\n /*/!**\n * The start & end patterns must be pre/post fixed by a quiet zone. This\n * zone must be at least 10 times the width of a narrow line. Scan back until\n * we either get to the start of the barcode or match the necessary number of\n * quiet zone pixels.\n *\n * Note: Its assumed the row is reversed when using this method to find\n * quiet zone after the end pattern.\n *\n * ref: http://www.barcode-1.net/i25code.html\n *\n * @param row bit array representing the scanned barcode.\n * @param startPattern index into row of the start or end pattern.\n * @throws NotFoundException if the quiet zone cannot be found\n *!/*/\n validateQuietZone(row, startPattern) {\n let quietCount = this.narrowLineWidth * 10; // expect to find this many pixels of quiet zone\n // if there are not so many pixel at all let's try as many as possible\n quietCount = quietCount < startPattern ? quietCount : startPattern;\n for (let i = startPattern - 1; quietCount > 0 && i >= 0; i--) {\n if (row.get(i)) {\n break;\n }\n quietCount--;\n }\n if (quietCount !== 0) {\n // Unable to find the necessary number of quiet zone pixels.\n throw new NotFoundException();\n }\n }\n /*\n /!**\n * Skip all whitespace until we get to the first black line.\n *\n * @param row row of black/white values to search\n * @return index of the first black line.\n * @throws NotFoundException Throws exception if no black lines are found in the row\n *!/*/\n static skipWhiteSpace(row) {\n const width = row.getSize();\n const endStart = row.getNextSet(0);\n if (endStart === width) {\n throw new NotFoundException();\n }\n return endStart;\n }\n /*/!**\n * Identify where the end of the middle / payload section ends.\n *\n * @param row row of black/white values to search\n * @return Array, containing index of start of 'end block' and end of 'end\n * block'\n *!/*/\n decodeEnd(row) {\n // For convenience, reverse the row and then\n // search from 'the start' for the end block\n row.reverse();\n try {\n let endStart = ITFReader.skipWhiteSpace(row);\n let endPattern;\n try {\n endPattern = ITFReader.findGuardPattern(row, endStart, ITFReader.END_PATTERN_REVERSED[0]);\n }\n catch (error) {\n if (error instanceof NotFoundException) {\n endPattern = ITFReader.findGuardPattern(row, endStart, ITFReader.END_PATTERN_REVERSED[1]);\n }\n }\n // The start & end patterns must be pre/post fixed by a quiet zone. This\n // zone must be at least 10 times the width of a narrow line.\n // ref: http://www.barcode-1.net/i25code.html\n this.validateQuietZone(row, endPattern[0]);\n // Now recalculate the indices of where the 'endblock' starts & stops to\n // accommodate\n // the reversed nature of the search\n let temp = endPattern[0];\n endPattern[0] = row.getSize() - endPattern[1];\n endPattern[1] = row.getSize() - temp;\n return endPattern;\n }\n finally {\n // Put the row back the right way.\n row.reverse();\n }\n }\n /*\n /!**\n * @param row row of black/white values to search\n * @param rowOffset position to start search\n * @param pattern pattern of counts of number of black and white pixels that are\n * being searched for as a pattern\n * @return start/end horizontal offset of guard pattern, as an array of two\n * ints\n * @throws NotFoundException if pattern is not found\n *!/*/\n static findGuardPattern(row, rowOffset, pattern) {\n let patternLength = pattern.length;\n let counters = new Int32Array(patternLength);\n let width = row.getSize();\n let isWhite = false;\n let counterPosition = 0;\n let patternStart = rowOffset;\n counters.fill(0);\n for (let x = rowOffset; x < width; x++) {\n if (row.get(x) !== isWhite) {\n counters[counterPosition]++;\n }\n else {\n if (counterPosition === patternLength - 1) {\n if (OneDReader.patternMatchVariance(counters, pattern, ITFReader.MAX_INDIVIDUAL_VARIANCE) < ITFReader.MAX_AVG_VARIANCE) {\n return [patternStart, x];\n }\n patternStart += counters[0] + counters[1];\n System.arraycopy(counters, 2, counters, 0, counterPosition - 1);\n counters[counterPosition - 1] = 0;\n counters[counterPosition] = 0;\n counterPosition--;\n }\n else {\n counterPosition++;\n }\n counters[counterPosition] = 1;\n isWhite = !isWhite;\n }\n }\n throw new NotFoundException();\n }\n /*/!**\n * Attempts to decode a sequence of ITF black/white lines into single\n * digit.\n *\n * @param counters the counts of runs of observed black/white/black/... values\n * @return The decoded digit\n * @throws NotFoundException if digit cannot be decoded\n *!/*/\n static decodeDigit(counters) {\n let bestVariance = ITFReader.MAX_AVG_VARIANCE; // worst variance we'll accept\n let bestMatch = -1;\n let max = ITFReader.PATTERNS.length;\n for (let i = 0; i < max; i++) {\n let pattern = ITFReader.PATTERNS[i];\n let variance = OneDReader.patternMatchVariance(counters, pattern, ITFReader.MAX_INDIVIDUAL_VARIANCE);\n if (variance < bestVariance) {\n bestVariance = variance;\n bestMatch = i;\n }\n else if (variance === bestVariance) {\n // if we find a second 'best match' with the same variance, we can not reliably report to have a suitable match\n bestMatch = -1;\n }\n }\n if (bestMatch >= 0) {\n return bestMatch % 10;\n }\n else {\n throw new NotFoundException();\n }\n }\n }\n ITFReader.PATTERNS = [\n Int32Array.from([1, 1, 2, 2, 1]),\n Int32Array.from([2, 1, 1, 1, 2]),\n Int32Array.from([1, 2, 1, 1, 2]),\n Int32Array.from([2, 2, 1, 1, 1]),\n Int32Array.from([1, 1, 2, 1, 2]),\n Int32Array.from([2, 1, 2, 1, 1]),\n Int32Array.from([1, 2, 2, 1, 1]),\n Int32Array.from([1, 1, 1, 2, 2]),\n Int32Array.from([2, 1, 1, 2, 1]),\n Int32Array.from([1, 2, 1, 2, 1]),\n Int32Array.from([1, 1, 3, 3, 1]),\n Int32Array.from([3, 1, 1, 1, 3]),\n Int32Array.from([1, 3, 1, 1, 3]),\n Int32Array.from([3, 3, 1, 1, 1]),\n Int32Array.from([1, 1, 3, 1, 3]),\n Int32Array.from([3, 1, 3, 1, 1]),\n Int32Array.from([1, 3, 3, 1, 1]),\n Int32Array.from([1, 1, 1, 3, 3]),\n Int32Array.from([3, 1, 1, 3, 1]),\n Int32Array.from([1, 3, 1, 3, 1]) // 9\n ];\n ITFReader.MAX_AVG_VARIANCE = 0.38;\n ITFReader.MAX_INDIVIDUAL_VARIANCE = 0.5;\n /* /!** Valid ITF lengths. Anything longer than the largest value is also allowed. *!/*/\n ITFReader.DEFAULT_ALLOWED_LENGTHS = [6, 8, 10, 12, 14];\n /*/!**\n * Start/end guard pattern.\n *\n * Note: The end pattern is reversed because the row is reversed before\n * searching for the END_PATTERN\n *!/*/\n ITFReader.START_PATTERN = Int32Array.from([1, 1, 1, 1]);\n ITFReader.END_PATTERN_REVERSED = [\n Int32Array.from([1, 1, 2]),\n Int32Array.from([1, 1, 3]) // 3x\n ];\n\n /**\n *

Encapsulates functionality and implementation that is common to UPC and EAN families\n * of one-dimensional barcodes.

\n *\n * @author dswitkin@google.com (Daniel Switkin)\n * @author Sean Owen\n * @author alasdair@google.com (Alasdair Mackintosh)\n */\n class AbstractUPCEANReader extends OneDReader {\n constructor() {\n super(...arguments);\n this.decodeRowStringBuffer = '';\n }\n\n static findStartGuardPattern(row) {\n let foundStart = false;\n let startRange;\n let nextStart = 0;\n let counters = Int32Array.from([0, 0, 0]);\n while (!foundStart) {\n counters = Int32Array.from([0, 0, 0]);\n startRange = AbstractUPCEANReader.findGuardPattern(row, nextStart, false, this.START_END_PATTERN, counters);\n let start = startRange[0];\n nextStart = startRange[1];\n let quietStart = start - (nextStart - start);\n if (quietStart >= 0) {\n foundStart = row.isRange(quietStart, start, false);\n }\n }\n return startRange;\n }\n static checkChecksum(s) {\n return AbstractUPCEANReader.checkStandardUPCEANChecksum(s);\n }\n static checkStandardUPCEANChecksum(s) {\n let length = s.length;\n if (length === 0)\n return false;\n let check = parseInt(s.charAt(length - 1), 10);\n return AbstractUPCEANReader.getStandardUPCEANChecksum(s.substring(0, length - 1)) === check;\n }\n static getStandardUPCEANChecksum(s) {\n let length = s.length;\n let sum = 0;\n for (let i = length - 1; i >= 0; i -= 2) {\n let digit = s.charAt(i).charCodeAt(0) - '0'.charCodeAt(0);\n if (digit < 0 || digit > 9) {\n throw new FormatException();\n }\n sum += digit;\n }\n sum *= 3;\n for (let i = length - 2; i >= 0; i -= 2) {\n let digit = s.charAt(i).charCodeAt(0) - '0'.charCodeAt(0);\n if (digit < 0 || digit > 9) {\n throw new FormatException();\n }\n sum += digit;\n }\n return (1000 - sum) % 10;\n }\n static decodeEnd(row, endStart) {\n return AbstractUPCEANReader.findGuardPattern(row, endStart, false, AbstractUPCEANReader.START_END_PATTERN, new Int32Array(AbstractUPCEANReader.START_END_PATTERN.length).fill(0));\n }\n /**\n * @throws NotFoundException\n */\n static findGuardPatternWithoutCounters(row, rowOffset, whiteFirst, pattern) {\n return this.findGuardPattern(row, rowOffset, whiteFirst, pattern, new Int32Array(pattern.length));\n }\n /**\n * @param row row of black/white values to search\n * @param rowOffset position to start search\n * @param whiteFirst if true, indicates that the pattern specifies white/black/white/...\n * pixel counts, otherwise, it is interpreted as black/white/black/...\n * @param pattern pattern of counts of number of black and white pixels that are being\n * searched for as a pattern\n * @param counters array of counters, as long as pattern, to re-use\n * @return start/end horizontal offset of guard pattern, as an array of two ints\n * @throws NotFoundException if pattern is not found\n */\n static findGuardPattern(row, rowOffset, whiteFirst, pattern, counters) {\n let width = row.getSize();\n rowOffset = whiteFirst ? row.getNextUnset(rowOffset) : row.getNextSet(rowOffset);\n let counterPosition = 0;\n let patternStart = rowOffset;\n let patternLength = pattern.length;\n let isWhite = whiteFirst;\n for (let x = rowOffset; x < width; x++) {\n if (row.get(x) !== isWhite) {\n counters[counterPosition]++;\n }\n else {\n if (counterPosition === patternLength - 1) {\n if (OneDReader.patternMatchVariance(counters, pattern, AbstractUPCEANReader.MAX_INDIVIDUAL_VARIANCE) < AbstractUPCEANReader.MAX_AVG_VARIANCE) {\n return Int32Array.from([patternStart, x]);\n }\n patternStart += counters[0] + counters[1];\n let slice = counters.slice(2, counters.length - 1);\n for (let i = 0; i < counterPosition - 1; i++) {\n counters[i] = slice[i];\n }\n counters[counterPosition - 1] = 0;\n counters[counterPosition] = 0;\n counterPosition--;\n }\n else {\n counterPosition++;\n }\n counters[counterPosition] = 1;\n isWhite = !isWhite;\n }\n }\n throw new NotFoundException();\n }\n static decodeDigit(row, counters, rowOffset, patterns) {\n this.recordPattern(row, rowOffset, counters);\n let bestVariance = this.MAX_AVG_VARIANCE;\n let bestMatch = -1;\n let max = patterns.length;\n for (let i = 0; i < max; i++) {\n let pattern = patterns[i];\n let variance = OneDReader.patternMatchVariance(counters, pattern, AbstractUPCEANReader.MAX_INDIVIDUAL_VARIANCE);\n if (variance < bestVariance) {\n bestVariance = variance;\n bestMatch = i;\n }\n }\n if (bestMatch >= 0) {\n return bestMatch;\n }\n else {\n throw new NotFoundException();\n }\n }\n }\n // These two values are critical for determining how permissive the decoding will be.\n // We've arrived at these values through a lot of trial and error. Setting them any higher\n // lets false positives creep in quickly.\n AbstractUPCEANReader.MAX_AVG_VARIANCE = 0.48;\n AbstractUPCEANReader.MAX_INDIVIDUAL_VARIANCE = 0.7;\n /**\n * Start/end guard pattern.\n */\n AbstractUPCEANReader.START_END_PATTERN = Int32Array.from([1, 1, 1]);\n /**\n * Pattern marking the middle of a UPC/EAN pattern, separating the two halves.\n */\n AbstractUPCEANReader.MIDDLE_PATTERN = Int32Array.from([1, 1, 1, 1, 1]);\n /**\n * end guard pattern.\n */\n AbstractUPCEANReader.END_PATTERN = Int32Array.from([1, 1, 1, 1, 1, 1]);\n /**\n * \"Odd\", or \"L\" patterns used to encode UPC/EAN digits.\n */\n AbstractUPCEANReader.L_PATTERNS = [\n Int32Array.from([3, 2, 1, 1]),\n Int32Array.from([2, 2, 2, 1]),\n Int32Array.from([2, 1, 2, 2]),\n Int32Array.from([1, 4, 1, 1]),\n Int32Array.from([1, 1, 3, 2]),\n Int32Array.from([1, 2, 3, 1]),\n Int32Array.from([1, 1, 1, 4]),\n Int32Array.from([1, 3, 1, 2]),\n Int32Array.from([1, 2, 1, 3]),\n Int32Array.from([3, 1, 1, 2]),\n ];\n\n /**\n * @see UPCEANExtension2Support\n */\n class UPCEANExtension5Support {\n constructor() {\n this.CHECK_DIGIT_ENCODINGS = [0x18, 0x14, 0x12, 0x11, 0x0C, 0x06, 0x03, 0x0A, 0x09, 0x05];\n this.decodeMiddleCounters = Int32Array.from([0, 0, 0, 0]);\n this.decodeRowStringBuffer = '';\n }\n decodeRow(rowNumber, row, extensionStartRange) {\n let result = this.decodeRowStringBuffer;\n let end = this.decodeMiddle(row, extensionStartRange, result);\n let resultString = result.toString();\n let extensionData = UPCEANExtension5Support.parseExtensionString(resultString);\n let resultPoints = [\n new ResultPoint((extensionStartRange[0] + extensionStartRange[1]) / 2.0, rowNumber),\n new ResultPoint(end, rowNumber)\n ];\n let extensionResult = new Result(resultString, null, 0, resultPoints, BarcodeFormat$1.UPC_EAN_EXTENSION, new Date().getTime());\n if (extensionData != null) {\n extensionResult.putAllMetadata(extensionData);\n }\n return extensionResult;\n }\n decodeMiddle(row, startRange, resultString) {\n let counters = this.decodeMiddleCounters;\n counters[0] = 0;\n counters[1] = 0;\n counters[2] = 0;\n counters[3] = 0;\n let end = row.getSize();\n let rowOffset = startRange[1];\n let lgPatternFound = 0;\n for (let x = 0; x < 5 && rowOffset < end; x++) {\n let bestMatch = AbstractUPCEANReader.decodeDigit(\n row,\n counters,\n rowOffset,\n AbstractUPCEANReader.L_AND_G_PATTERNS);\n resultString += String.fromCharCode(('0'.charCodeAt(0) + bestMatch % 10));\n for (let counter of counters) {\n rowOffset += counter;\n }\n if (bestMatch >= 10) {\n lgPatternFound |= 1 << (4 - x);\n }\n if (x !== 4) {\n // Read off separator if not last\n rowOffset = row.getNextSet(rowOffset);\n rowOffset = row.getNextUnset(rowOffset);\n }\n }\n if (resultString.length !== 5) {\n throw new NotFoundException();\n }\n let checkDigit = this.determineCheckDigit(lgPatternFound);\n if (UPCEANExtension5Support.extensionChecksum(resultString.toString()) !== checkDigit) {\n throw new NotFoundException();\n }\n return rowOffset;\n }\n static extensionChecksum(s) {\n let length = s.length;\n let sum = 0;\n for (let i = length - 2; i >= 0; i -= 2) {\n sum += s.charAt(i).charCodeAt(0) - '0'.charCodeAt(0);\n }\n sum *= 3;\n for (let i = length - 1; i >= 0; i -= 2) {\n sum += s.charAt(i).charCodeAt(0) - '0'.charCodeAt(0);\n }\n sum *= 3;\n return sum % 10;\n }\n determineCheckDigit(lgPatternFound) {\n for (let d = 0; d < 10; d++) {\n if (lgPatternFound === this.CHECK_DIGIT_ENCODINGS[d]) {\n return d;\n }\n }\n throw new NotFoundException();\n }\n static parseExtensionString(raw) {\n if (raw.length !== 5) {\n return null;\n }\n let value = UPCEANExtension5Support.parseExtension5String(raw);\n if (value == null) {\n return null;\n }\n return new Map([[ResultMetadataType$1.SUGGESTED_PRICE, value]]);\n }\n static parseExtension5String(raw) {\n let currency;\n switch (raw.charAt(0)) {\n case '0':\n currency = '\u00A3';\n break;\n case '5':\n currency = '$';\n break;\n case '9':\n // Reference: http://www.jollytech.com\n switch (raw) {\n case '90000':\n // No suggested retail price\n return null;\n case '99991':\n // Complementary\n return '0.00';\n case '99990':\n return 'Used';\n }\n // Otherwise... unknown currency?\n currency = '';\n break;\n default:\n currency = '';\n break;\n }\n let rawAmount = parseInt(raw.substring(1));\n let unitsString = (rawAmount / 100).toString();\n let hundredths = rawAmount % 100;\n let hundredthsString = hundredths < 10 ? '0' + hundredths : hundredths.toString(); // fixme\n return currency + unitsString + '.' + hundredthsString;\n }\n }\n\n /**\n * @see UPCEANExtension5Support\n */\n class UPCEANExtension2Support {\n constructor() {\n this.decodeMiddleCounters = Int32Array.from([0, 0, 0, 0]);\n this.decodeRowStringBuffer = '';\n }\n decodeRow(rowNumber, row, extensionStartRange) {\n let result = this.decodeRowStringBuffer;\n let end = this.decodeMiddle(row, extensionStartRange, result);\n let resultString = result.toString();\n let extensionData = UPCEANExtension2Support.parseExtensionString(resultString);\n let resultPoints = [\n new ResultPoint((extensionStartRange[0] + extensionStartRange[1]) / 2.0, rowNumber),\n new ResultPoint(end, rowNumber)\n ];\n let extensionResult = new Result(resultString, null, 0, resultPoints, BarcodeFormat$1.UPC_EAN_EXTENSION, new Date().getTime());\n if (extensionData != null) {\n extensionResult.putAllMetadata(extensionData);\n }\n return extensionResult;\n }\n decodeMiddle(row, startRange, resultString) {\n let counters = this.decodeMiddleCounters;\n counters[0] = 0;\n counters[1] = 0;\n counters[2] = 0;\n counters[3] = 0;\n let end = row.getSize();\n let rowOffset = startRange[1];\n let checkParity = 0;\n for (let x = 0; x < 2 && rowOffset < end; x++) {\n let bestMatch = AbstractUPCEANReader.decodeDigit(row, counters, rowOffset, AbstractUPCEANReader.L_AND_G_PATTERNS);\n resultString += String.fromCharCode(('0'.charCodeAt(0) + bestMatch % 10));\n for (let counter of counters) {\n rowOffset += counter;\n }\n if (bestMatch >= 10) {\n checkParity |= 1 << (1 - x);\n }\n if (x !== 1) {\n // Read off separator if not last\n rowOffset = row.getNextSet(rowOffset);\n rowOffset = row.getNextUnset(rowOffset);\n }\n }\n if (resultString.length !== 2) {\n throw new NotFoundException();\n }\n if (parseInt(resultString.toString()) % 4 !== checkParity) {\n throw new NotFoundException();\n }\n return rowOffset;\n }\n static parseExtensionString(raw) {\n if (raw.length !== 2) {\n return null;\n }\n return new Map([[ResultMetadataType$1.ISSUE_NUMBER, parseInt(raw)]]);\n }\n }\n\n class UPCEANExtensionSupport {\n static decodeRow(rowNumber, row, rowOffset) {\n let extensionStartRange = AbstractUPCEANReader.findGuardPattern(\n row,\n rowOffset,\n false,\n this.EXTENSION_START_PATTERN,\n new Int32Array(this.EXTENSION_START_PATTERN.length).fill(0));\n try {\n // return null;\n let fiveSupport = new UPCEANExtension5Support();\n return fiveSupport.decodeRow(rowNumber, row, extensionStartRange);\n }\n catch (err) {\n // return null;\n let twoSupport = new UPCEANExtension2Support();\n return twoSupport.decodeRow(rowNumber, row, extensionStartRange);\n }\n }\n }\n UPCEANExtensionSupport.EXTENSION_START_PATTERN = Int32Array.from([1, 1, 2]);\n\n /**\n *

Encapsulates functionality and implementation that is common to UPC and EAN families\n * of one-dimensional barcodes.

\n *\n * @author dswitkin@google.com (Daniel Switkin)\n * @author Sean Owen\n * @author alasdair@google.com (Alasdair Mackintosh)\n */\n class UPCEANReader extends AbstractUPCEANReader {\n constructor() {\n super();\n this.decodeRowStringBuffer = '';\n UPCEANReader.L_AND_G_PATTERNS = UPCEANReader.L_PATTERNS.map(arr => Int32Array.from(arr));\n for (let i = 10; i < 20; i++) {\n let widths = UPCEANReader.L_PATTERNS[i - 10];\n let reversedWidths = new Int32Array(widths.length);\n for (let j = 0; j < widths.length; j++) {\n reversedWidths[j] = widths[widths.length - j - 1];\n }\n UPCEANReader.L_AND_G_PATTERNS[i] = reversedWidths;\n }\n }\n decodeRow(rowNumber, row, hints) {\n let startGuardRange = UPCEANReader.findStartGuardPattern(row);\n let resultPointCallback = hints == null ? null : hints.get(DecodeHintType$1.NEED_RESULT_POINT_CALLBACK);\n if (resultPointCallback != null) {\n const resultPoint = new ResultPoint((startGuardRange[0] + startGuardRange[1]) / 2.0, rowNumber);\n resultPointCallback.foundPossibleResultPoint(resultPoint);\n }\n let budello = this.decodeMiddle(row, startGuardRange, this.decodeRowStringBuffer);\n let endStart = budello.rowOffset;\n let result = budello.resultString;\n if (resultPointCallback != null) {\n const resultPoint = new ResultPoint(endStart, rowNumber);\n resultPointCallback.foundPossibleResultPoint(resultPoint);\n }\n let endRange = this.decodeEnd(row, endStart);\n if (resultPointCallback != null) {\n const resultPoint = new ResultPoint((endRange[0] + endRange[1]) / 2.0, rowNumber);\n resultPointCallback.foundPossibleResultPoint(resultPoint);\n }\n // Make sure there is a quiet zone at least as big as the end pattern after the barcode. The\n // spec might want more whitespace, but in practice this is the maximum we can count on.\n let end = endRange[1];\n let quietEnd = end + (end - endRange[0]);\n if (quietEnd >= row.getSize() || !row.isRange(end, quietEnd, false)) {\n throw new NotFoundException();\n }\n let resultString = result.toString();\n // UPC/EAN should never be less than 8 chars anyway\n if (resultString.length < 8) {\n throw new FormatException();\n }\n if (!UPCEANReader.checkChecksum(resultString)) {\n throw new ChecksumException();\n }\n let left = (startGuardRange[1] + startGuardRange[0]) / 2.0;\n let right = (endRange[1] + endRange[0]) / 2.0;\n let format = this.getBarcodeFormat();\n let resultPoint = [new ResultPoint(left, rowNumber), new ResultPoint(right, rowNumber)];\n let decodeResult = new Result(resultString, null, 0, resultPoint, format, new Date().getTime());\n let extensionLength = 0;\n try {\n let extensionResult = UPCEANExtensionSupport.decodeRow(rowNumber, row, endRange[1]);\n decodeResult.putMetadata(ResultMetadataType$1.UPC_EAN_EXTENSION, extensionResult.getText());\n decodeResult.putAllMetadata(extensionResult.getResultMetadata());\n decodeResult.addResultPoints(extensionResult.getResultPoints());\n extensionLength = extensionResult.getText().length;\n }\n catch (ignoreError) {}\n let allowedExtensions = hints == null ? null : hints.get(DecodeHintType$1.ALLOWED_EAN_EXTENSIONS);\n if (allowedExtensions != null) {\n let valid = false;\n for (let length in allowedExtensions) {\n if (extensionLength.toString() === length) { // check me\n valid = true;\n break;\n }\n }\n if (!valid) {\n throw new NotFoundException();\n }\n }\n return decodeResult;\n }\n decodeEnd(row, endStart) {\n return UPCEANReader.findGuardPattern(\n row, endStart, false, UPCEANReader.START_END_PATTERN,\n new Int32Array(UPCEANReader.START_END_PATTERN.length).fill(0));\n }\n static checkChecksum(s) {\n return UPCEANReader.checkStandardUPCEANChecksum(s);\n }\n static checkStandardUPCEANChecksum(s) {\n let length = s.length;\n if (length === 0)\n return false;\n let check = parseInt(s.charAt(length - 1), 10);\n return UPCEANReader.getStandardUPCEANChecksum(s.substring(0, length - 1)) === check;\n }\n static getStandardUPCEANChecksum(s) {\n let length = s.length;\n let sum = 0;\n for (let i = length - 1; i >= 0; i -= 2) {\n let digit = s.charAt(i).charCodeAt(0) - '0'.charCodeAt(0);\n if (digit < 0 || digit > 9) {\n throw new FormatException();\n }\n sum += digit;\n }\n sum *= 3;\n for (let i = length - 2; i >= 0; i -= 2) {\n let digit = s.charAt(i).charCodeAt(0) - '0'.charCodeAt(0);\n if (digit < 0 || digit > 9) {\n throw new FormatException();\n }\n sum += digit;\n }\n return (1000 - sum) % 10;\n }\n }\n\n /**\n *

Implements decoding of the EAN-13 format.

\n *\n * @author dswitkin@google.com (Daniel Switkin)\n * @author Sean Owen\n * @author alasdair@google.com (Alasdair Mackintosh)\n */\n class EAN13Reader extends UPCEANReader {\n constructor() {\n super();\n this.decodeMiddleCounters = Int32Array.from([0, 0, 0, 0]);\n }\n decodeMiddle(row, startRange, resultString) {\n let counters = this.decodeMiddleCounters;\n counters[0] = 0;\n counters[1] = 0;\n counters[2] = 0;\n counters[3] = 0;\n let end = row.getSize();\n let rowOffset = startRange[1];\n let lgPatternFound = 0;\n for (let x = 0; x < 6 && rowOffset < end; x++) {\n let bestMatch = UPCEANReader.decodeDigit(row, counters, rowOffset, UPCEANReader.L_AND_G_PATTERNS);\n resultString += String.fromCharCode(('0'.charCodeAt(0) + bestMatch % 10));\n for (let counter of counters) {\n rowOffset += counter;\n }\n if (bestMatch >= 10) {\n lgPatternFound |= 1 << (5 - x);\n }\n }\n resultString = EAN13Reader.determineFirstDigit(resultString, lgPatternFound);\n let middleRange = UPCEANReader.findGuardPattern(\n row,\n rowOffset,\n true,\n UPCEANReader.MIDDLE_PATTERN,\n new Int32Array(UPCEANReader.MIDDLE_PATTERN.length).fill(0));\n rowOffset = middleRange[1];\n for (let x = 0; x < 6 && rowOffset < end; x++) {\n let bestMatch = UPCEANReader.decodeDigit(row, counters, rowOffset, UPCEANReader.L_PATTERNS);\n resultString += String.fromCharCode(('0'.charCodeAt(0) + bestMatch));\n for (let counter of counters) {\n rowOffset += counter;\n }\n }\n return { rowOffset, resultString };\n }\n getBarcodeFormat() {\n return BarcodeFormat$1.EAN_13;\n }\n static determineFirstDigit(resultString, lgPatternFound) {\n for (let d = 0; d < 10; d++) {\n if (lgPatternFound === this.FIRST_DIGIT_ENCODINGS[d]) {\n resultString = String.fromCharCode(('0'.charCodeAt(0) + d)) + resultString;\n return resultString;\n }\n }\n throw new NotFoundException();\n }\n }\n EAN13Reader.FIRST_DIGIT_ENCODINGS = [0x00, 0x0B, 0x0D, 0xE, 0x13, 0x19, 0x1C, 0x15, 0x16, 0x1A];\n\n /**\n *

Implements decoding of the EAN-8 format.

\n *\n * @author Sean Owen\n */\n class EAN8Reader extends UPCEANReader {\n constructor() {\n super();\n this.decodeMiddleCounters = Int32Array.from([0, 0, 0, 0]);\n }\n decodeMiddle(row, startRange, resultString) {\n const counters = this.decodeMiddleCounters;\n counters[0] = 0;\n counters[1] = 0;\n counters[2] = 0;\n counters[3] = 0;\n let end = row.getSize();\n let rowOffset = startRange[1];\n for (let x = 0; x < 4 && rowOffset < end; x++) {\n let bestMatch = UPCEANReader.decodeDigit(row, counters, rowOffset, UPCEANReader.L_PATTERNS);\n resultString += String.fromCharCode(('0'.charCodeAt(0) + bestMatch));\n for (let counter of counters) {\n rowOffset += counter;\n }\n }\n let middleRange = UPCEANReader.findGuardPattern(row, rowOffset, true, UPCEANReader.MIDDLE_PATTERN, new Int32Array(UPCEANReader.MIDDLE_PATTERN.length).fill(0));\n rowOffset = middleRange[1];\n for (let x = 0; x < 4 && rowOffset < end; x++) {\n let bestMatch = UPCEANReader.decodeDigit(row, counters, rowOffset, UPCEANReader.L_PATTERNS);\n resultString += String.fromCharCode(('0'.charCodeAt(0) + bestMatch));\n for (let counter of counters) {\n rowOffset += counter;\n }\n }\n return { rowOffset, resultString };\n }\n getBarcodeFormat() {\n return BarcodeFormat$1.EAN_8;\n }\n }\n\n /**\n * Encapsulates functionality and implementation that is common to all families\n * of one-dimensional barcodes.\n *\n * @author dswitkin@google.com (Daniel Switkin)\n * @author Sean Owen\n * @author sam2332 (Sam Rudloff)\n *\n * @source https://github.com/zxing/zxing/blob/3c96923276dd5785d58eb970b6ba3f80d36a9505/core/src/main/java/com/google/zxing/oned/UPCAReader.java\n *\n * @experimental\n */\n class UPCAReader extends UPCEANReader {\n constructor() {\n super(...arguments);\n this.ean13Reader = new EAN13Reader();\n }\n // @Override\n getBarcodeFormat() {\n return BarcodeFormat$1.UPC_A;\n }\n // Note that we don't try rotation without the try harder flag, even if rotation was supported.\n // @Override\n decode(image, hints) {\n return this.maybeReturnResult(this.ean13Reader.decode(image));\n }\n // @Override\n decodeRow(rowNumber, row, hints) {\n return this.maybeReturnResult(this.ean13Reader.decodeRow(rowNumber, row, hints));\n }\n // @Override\n decodeMiddle(row, startRange, resultString) {\n return this.ean13Reader.decodeMiddle(row, startRange, resultString);\n }\n maybeReturnResult(result) {\n let text = result.getText();\n if (text.charAt(0) === '0') {\n let upcaResult = new Result(text.substring(1), null, null, result.getResultPoints(), BarcodeFormat$1.UPC_A);\n if (result.getResultMetadata() != null) {\n upcaResult.putAllMetadata(result.getResultMetadata());\n }\n return upcaResult;\n }\n else {\n throw new NotFoundException();\n }\n }\n reset() {\n this.ean13Reader.reset();\n }\n }\n\n /**\n *

Implements decoding of the UPC-E format.

\n *

This is a great reference for\n * UPC-E information.

\n *\n * @author Sean Owen\n *\n * @source https://github.com/zxing/zxing/blob/3c96923276dd5785d58eb970b6ba3f80d36a9505/core/src/main/java/com/google/zxing/oned/UPCEReader.java\n *\n * @experimental\n */\n /* final */ class UPCEReader extends UPCEANReader {\n constructor() {\n super();\n this.decodeMiddleCounters = new Int32Array(4);\n }\n /**\n * @throws NotFoundException\n */\n // @Override\n decodeMiddle(row, startRange, result) {\n const counters = this.decodeMiddleCounters.map(x => x);\n counters[0] = 0;\n counters[1] = 0;\n counters[2] = 0;\n counters[3] = 0;\n const end = row.getSize();\n let rowOffset = startRange[1];\n let lgPatternFound = 0;\n for (let x = 0; x < 6 && rowOffset < end; x++) {\n const bestMatch = UPCEReader.decodeDigit(\n row, counters, rowOffset, UPCEReader.L_AND_G_PATTERNS);\n result += String.fromCharCode(('0'.charCodeAt(0) + (bestMatch % 10)));\n for (let counter of counters) {\n rowOffset += counter;\n }\n if (bestMatch >= 10) {\n lgPatternFound |= (1 << (5 - x));\n }\n }\n let resultString = UPCEReader.determineNumSysAndCheckDigit(\n result, lgPatternFound);\n return {rowOffset, resultString};\n }\n /**\n * @throws NotFoundException\n */\n // @Override\n decodeEnd(row, endStart) {\n return UPCEReader.findGuardPatternWithoutCounters(\n row, endStart, true, UPCEReader.MIDDLE_END_PATTERN);\n }\n /**\n * @throws FormatException\n */\n // @Override\n checkChecksum(s) {\n return UPCEANReader.checkChecksum(UPCEReader.convertUPCEtoUPCA(s));\n }\n /**\n * @throws NotFoundException\n */\n static determineNumSysAndCheckDigit(resultString, lgPatternFound) {\n for (let numSys = 0; numSys <= 1; numSys++) {\n for (let d = 0; d < 10; d++) {\n if (lgPatternFound === this.NUMSYS_AND_CHECK_DIGIT_PATTERNS[numSys][d]) {\n let prefix = String.fromCharCode('0'.charCodeAt(0) + numSys);\n let suffix = String.fromCharCode('0'.charCodeAt(0) + d);\n return prefix + resultString + suffix;\n }\n }\n }\n throw NotFoundException.getNotFoundInstance();\n }\n // @Override\n getBarcodeFormat() {\n return BarcodeFormat$1.UPC_E;\n }\n /**\n * Expands a UPC-E value back into its full, equivalent UPC-A code value.\n *\n * @param upce UPC-E code as string of digits\n * @return equivalent UPC-A code as string of digits\n */\n static convertUPCEtoUPCA(upce) {\n // the following line is equivalent to upce.getChars(1, 7, upceChars, 0);\n const upceChars = upce.slice(1, 7).split('').map(x => x.charCodeAt(0));\n const result = new StringBuilder( /*12*/);\n result.append(upce.charAt(0));\n let lastChar = upceChars[5];\n switch (lastChar) {\n case 0:\n case 1:\n case 2:\n result.appendChars(upceChars, 0, 2);\n result.append(lastChar);\n result.append('0000');\n result.appendChars(upceChars, 2, 3);\n break;\n case 3:\n result.appendChars(upceChars, 0, 3);\n result.append('00000');\n result.appendChars(upceChars, 3, 2);\n break;\n case 4:\n result.appendChars(upceChars, 0, 4);\n result.append('00000');\n result.append(upceChars[4]);\n break;\n default:\n result.appendChars(upceChars, 0, 5);\n result.append('0000');\n result.append(lastChar);\n break;\n }\n // Only append check digit in conversion if supplied\n if (upce.length >= 8) {\n result.append(upce.charAt(7));\n }\n return result.toString();\n }\n }\n /**\n * The pattern that marks the middle, and end, of a UPC-E pattern.\n * There is no \"second half\" to a UPC-E barcode.\n */\n UPCEReader.MIDDLE_END_PATTERN = Int32Array.from([1, 1, 1, 1, 1, 1]);\n // For an UPC-E barcode, the final digit is represented by the parities used\n // to encode the middle six digits, according to the table below.\n //\n // Parity of next 6 digits\n // Digit 0 1 2 3 4 5\n // 0 Even Even Even Odd Odd Odd\n // 1 Even Even Odd Even Odd Odd\n // 2 Even Even Odd Odd Even Odd\n // 3 Even Even Odd Odd Odd Even\n // 4 Even Odd Even Even Odd Odd\n // 5 Even Odd Odd Even Even Odd\n // 6 Even Odd Odd Odd Even Even\n // 7 Even Odd Even Odd Even Odd\n // 8 Even Odd Even Odd Odd Even\n // 9 Even Odd Odd Even Odd Even\n //\n // The encoding is represented by the following array, which is a bit pattern\n // using Odd = 0 and Even = 1. For example, 5 is represented by:\n //\n // Odd Even Even Odd Odd Even\n // in binary:\n // 0 1 1 0 0 1 == 0x19\n //\n /**\n * See {@link #L_AND_G_PATTERNS}; these values similarly represent patterns of\n * even-odd parity encodings of digits that imply both the number system (0 or 1)\n * used, and the check digit.\n */\n UPCEReader.NUMSYS_AND_CHECK_DIGIT_PATTERNS = [\n Int32Array.from([0x38, 0x34, 0x32, 0x31, 0x2C, 0x26, 0x23, 0x2A, 0x29, 0x25]),\n Int32Array.from([0x07, 0x0B, 0x0D, 0x0E, 0x13, 0x19, 0x1C, 0x15, 0x16, 0x1A]),\n ];\n\n /**\n *

A reader that can read all available UPC/EAN formats. If a caller wants to try to\n * read all such formats, it is most efficient to use this implementation rather than invoke\n * individual readers.

\n *\n * @author Sean Owen\n */\n class MultiFormatUPCEANReader extends OneDReader {\n constructor(hints) {\n super();\n let possibleFormats = hints == null ? null : hints.get(DecodeHintType$1.POSSIBLE_FORMATS);\n let readers = [];\n if (!isNullOrUndefined(possibleFormats)) {\n if (possibleFormats.indexOf(BarcodeFormat$1.EAN_13) > -1) {\n readers.push(new EAN13Reader());\n }\n if (possibleFormats.indexOf(BarcodeFormat$1.UPC_A) > -1) {\n readers.push(new UPCAReader());\n }\n if (possibleFormats.indexOf(BarcodeFormat$1.EAN_8) > -1) {\n readers.push(new EAN8Reader());\n }\n if (possibleFormats.indexOf(BarcodeFormat$1.UPC_E) > -1) {\n readers.push(new UPCEReader());\n }\n } else {\n // No hints provided.\n readers.push(new EAN13Reader());\n readers.push(new UPCAReader());\n readers.push(new EAN8Reader());\n readers.push(new UPCEReader());\n }\n this.readers = readers;\n }\n decodeRow(rowNumber, row, hints) {\n for (let reader of this.readers) {\n try {\n // const result: Result = reader.decodeRow(rowNumber, row, startGuardPattern, hints);\n const result = reader.decodeRow(rowNumber, row, hints);\n // Special case: a 12-digit code encoded in UPC-A is identical to a \"0\"\n // followed by those 12 digits encoded as EAN-13. Each will recognize such a code,\n // UPC-A as a 12-digit string and EAN-13 as a 13-digit string starting with \"0\".\n // Individually these are correct and their readers will both read such a code\n // and correctly call it EAN-13, or UPC-A, respectively.\n //\n // In this case, if we've been looking for both types, we'd like to call it\n // a UPC-A code. But for efficiency we only run the EAN-13 decoder to also read\n // UPC-A. So we special case it here, and convert an EAN-13 result to a UPC-A\n // result if appropriate.\n //\n // But, don't return UPC-A if UPC-A was not a requested format!\n const ean13MayBeUPCA = result.getBarcodeFormat() === BarcodeFormat$1.EAN_13 &&\n result.getText().charAt(0) === '0';\n // @SuppressWarnings(\"unchecked\")\n const possibleFormats = hints == null ? null : hints.get(DecodeHintType$1.POSSIBLE_FORMATS);\n const canReturnUPCA = possibleFormats == null || possibleFormats.includes(BarcodeFormat$1.UPC_A);\n if (ean13MayBeUPCA && canReturnUPCA) {\n const rawBytes = result.getRawBytes();\n // Transfer the metadata across\n const resultUPCA = new Result(\n result.getText().substring(1),\n rawBytes,\n (rawBytes ? rawBytes.length : null),\n result.getResultPoints(),\n BarcodeFormat$1.UPC_A);\n resultUPCA.putAllMetadata(result.getResultMetadata());\n return resultUPCA;\n }\n return result;\n }\n catch (err) {\n // continue;\n }\n }\n throw new NotFoundException();\n }\n reset() {\n for (let reader of this.readers) {\n reader.reset();\n }\n }\n }\n\n // import Integer from '../../util/Integer';\n // import Float from '../../util/Float';\n class AbstractRSSReader extends OneDReader {\n constructor() {\n super();\n this.decodeFinderCounters = new Int32Array(4);\n this.dataCharacterCounters = new Int32Array(8);\n this.oddRoundingErrors = new Array(4);\n this.evenRoundingErrors = new Array(4);\n this.oddCounts = new Array(this.dataCharacterCounters.length / 2);\n this.evenCounts = new Array(this.dataCharacterCounters.length / 2);\n }\n getDecodeFinderCounters() {\n return this.decodeFinderCounters;\n }\n getDataCharacterCounters() {\n return this.dataCharacterCounters;\n }\n getOddRoundingErrors() {\n return this.oddRoundingErrors;\n }\n getEvenRoundingErrors() {\n return this.evenRoundingErrors;\n }\n getOddCounts() {\n return this.oddCounts;\n }\n getEvenCounts() {\n return this.evenCounts;\n }\n parseFinderValue(counters, finderPatterns) {\n for (let value = 0; value < finderPatterns.length; value++) {\n if (OneDReader.patternMatchVariance(counters, finderPatterns[value], AbstractRSSReader.MAX_INDIVIDUAL_VARIANCE) < AbstractRSSReader.MAX_AVG_VARIANCE) {\n return value;\n }\n }\n throw new NotFoundException();\n }\n /**\n * @param array values to sum\n * @return sum of values\n * @deprecated call {@link MathUtils#sum(int[])}\n */\n static count(array) {\n return MathUtils.sum(new Int32Array(array));\n }\n static increment(array, errors) {\n let index = 0;\n let biggestError = errors[0];\n for (let i = 1; i < array.length; i++) {\n if (errors[i] > biggestError) {\n biggestError = errors[i];\n index = i;\n }\n }\n array[index]++;\n }\n static decrement(array, errors) {\n let index = 0;\n let biggestError = errors[0];\n for (let i = 1; i < array.length; i++) {\n if (errors[i] < biggestError) {\n biggestError = errors[i];\n index = i;\n }\n }\n array[index]--;\n }\n static isFinderPattern(counters) {\n let firstTwoSum = counters[0] + counters[1];\n let sum = firstTwoSum + counters[2] + counters[3];\n let ratio = firstTwoSum / sum;\n if (ratio >= AbstractRSSReader.MIN_FINDER_PATTERN_RATIO && ratio <= AbstractRSSReader.MAX_FINDER_PATTERN_RATIO) {\n // passes ratio test in spec, but see if the counts are unreasonable\n let minCounter = Number.MAX_SAFE_INTEGER;\n let maxCounter = Number.MIN_SAFE_INTEGER;\n for (let counter of counters) {\n if (counter > maxCounter) {\n maxCounter = counter;\n }\n if (counter < minCounter) {\n minCounter = counter;\n }\n }\n return maxCounter < 10 * minCounter;\n }\n return false;\n }\n }\n AbstractRSSReader.MAX_AVG_VARIANCE = 0.2;\n AbstractRSSReader.MAX_INDIVIDUAL_VARIANCE = 0.45;\n AbstractRSSReader.MIN_FINDER_PATTERN_RATIO = 9.5 / 12.0;\n AbstractRSSReader.MAX_FINDER_PATTERN_RATIO = 12.5 / 14.0;\n\n class DataCharacter {\n constructor(value, checksumPortion) {\n this.value = value;\n this.checksumPortion = checksumPortion;\n }\n getValue() {\n return this.value;\n }\n getChecksumPortion() {\n return this.checksumPortion;\n }\n toString() {\n return this.value + '(' + this.checksumPortion + ')';\n }\n equals(o) {\n if (!(o instanceof DataCharacter)) {\n return false;\n }\n const that = o;\n return this.value === that.value && this.checksumPortion === that.checksumPortion;\n }\n hashCode() {\n return this.value ^ this.checksumPortion;\n }\n }\n\n class FinderPattern {\n constructor(value, startEnd, start, end, rowNumber) {\n this.value = value;\n this.startEnd = startEnd;\n this.value = value;\n this.startEnd = startEnd;\n this.resultPoints = new Array();\n this.resultPoints.push(new ResultPoint(start, rowNumber));\n this.resultPoints.push(new ResultPoint(end, rowNumber));\n }\n getValue() {\n return this.value;\n }\n getStartEnd() {\n return this.startEnd;\n }\n getResultPoints() {\n return this.resultPoints;\n }\n equals(o) {\n if (!(o instanceof FinderPattern)) {\n return false;\n }\n const that = o;\n return this.value === that.value;\n }\n hashCode() {\n return this.value;\n }\n }\n\n /**\n * RSS util functions.\n */\n class RSSUtils {\n constructor() { }\n static getRSSvalue(widths, maxWidth, noNarrow) {\n let n = 0;\n for (let width of widths) {\n n += width;\n }\n let val = 0;\n let narrowMask = 0;\n let elements = widths.length;\n for (let bar = 0; bar < elements - 1; bar++) {\n let elmWidth;\n for (elmWidth = 1, narrowMask |= 1 << bar; elmWidth < widths[bar]; elmWidth++, narrowMask &= ~(1 << bar)) {\n let subVal = RSSUtils.combins(n - elmWidth - 1, elements - bar - 2);\n if (noNarrow && (narrowMask === 0) && (n - elmWidth - (elements - bar - 1) >= elements - bar - 1)) {\n subVal -= RSSUtils.combins(n - elmWidth - (elements - bar), elements - bar - 2);\n }\n if (elements - bar - 1 > 1) {\n let lessVal = 0;\n for (let mxwElement = n - elmWidth - (elements - bar - 2); mxwElement > maxWidth; mxwElement--) {\n lessVal += RSSUtils.combins(n - elmWidth - mxwElement - 1, elements - bar - 3);\n }\n subVal -= lessVal * (elements - 1 - bar);\n }\n else if (n - elmWidth > maxWidth) {\n subVal--;\n }\n val += subVal;\n }\n n -= elmWidth;\n }\n return val;\n }\n static combins(n, r) {\n let maxDenom;\n let minDenom;\n if (n - r > r) {\n minDenom = r;\n maxDenom = n - r;\n }\n else {\n minDenom = n - r;\n maxDenom = r;\n }\n let val = 1;\n let j = 1;\n for (let i = n; i > maxDenom; i--) {\n val *= i;\n if (j <= minDenom) {\n val /= j;\n j++;\n }\n }\n while ((j <= minDenom)) {\n val /= j;\n j++;\n }\n return val;\n }\n }\n\n class BitArrayBuilder {\n static buildBitArray(pairs) {\n let charNumber = (pairs.length * 2) - 1;\n if (pairs[pairs.length - 1].getRightChar() == null) {\n charNumber -= 1;\n }\n let size = 12 * charNumber;\n let binary = new BitArray(size);\n let accPos = 0;\n let firstPair = pairs[0];\n let firstValue = firstPair.getRightChar().getValue();\n for (let i = 11; i >= 0; --i) {\n if ((firstValue & (1 << i)) != 0) {\n binary.set(accPos);\n }\n accPos++;\n }\n for (let i = 1; i < pairs.length; ++i) {\n let currentPair = pairs[i];\n let leftValue = currentPair.getLeftChar().getValue();\n for (let j = 11; j >= 0; --j) {\n if ((leftValue & (1 << j)) != 0) {\n binary.set(accPos);\n }\n accPos++;\n }\n if (currentPair.getRightChar() != null) {\n let rightValue = currentPair.getRightChar().getValue();\n for (let j = 11; j >= 0; --j) {\n if ((rightValue & (1 << j)) != 0) {\n binary.set(accPos);\n }\n accPos++;\n }\n }\n }\n return binary;\n }\n }\n\n class BlockParsedResult {\n constructor(finished, decodedInformation) {\n if (decodedInformation) {\n this.decodedInformation = null;\n }\n else {\n this.finished = finished;\n this.decodedInformation = decodedInformation;\n }\n }\n getDecodedInformation() {\n return this.decodedInformation;\n }\n isFinished() {\n return this.finished;\n }\n }\n\n class DecodedObject {\n constructor(newPosition) {\n this.newPosition = newPosition;\n }\n getNewPosition() {\n return this.newPosition;\n }\n }\n\n class DecodedChar extends DecodedObject {\n constructor(newPosition, value) {\n super(newPosition);\n this.value = value;\n }\n getValue() {\n return this.value;\n }\n isFNC1() {\n return this.value === DecodedChar.FNC1;\n }\n }\n DecodedChar.FNC1 = '$';\n\n class DecodedInformation extends DecodedObject {\n constructor(newPosition, newString, remainingValue) {\n super(newPosition);\n if (remainingValue) {\n this.remaining = true;\n this.remainingValue = this.remainingValue;\n }\n else {\n this.remaining = false;\n this.remainingValue = 0;\n }\n this.newString = newString;\n }\n getNewString() {\n return this.newString;\n }\n isRemaining() {\n return this.remaining;\n }\n getRemainingValue() {\n return this.remainingValue;\n }\n }\n\n class DecodedNumeric extends DecodedObject {\n constructor(newPosition, firstDigit, secondDigit) {\n super(newPosition);\n if (firstDigit < 0 || firstDigit > 10 || secondDigit < 0 || secondDigit > 10) {\n throw new FormatException();\n }\n this.firstDigit = firstDigit;\n this.secondDigit = secondDigit;\n }\n getFirstDigit() {\n return this.firstDigit;\n }\n getSecondDigit() {\n return this.secondDigit;\n }\n getValue() {\n return this.firstDigit * 10 + this.secondDigit;\n }\n isFirstDigitFNC1() {\n return this.firstDigit === DecodedNumeric.FNC1;\n }\n isSecondDigitFNC1() {\n return this.secondDigit === DecodedNumeric.FNC1;\n }\n isAnyFNC1() {\n return this.firstDigit === DecodedNumeric.FNC1 || this.secondDigit === DecodedNumeric.FNC1;\n }\n }\n DecodedNumeric.FNC1 = 10;\n\n class FieldParser {\n constructor() {\n }\n static parseFieldsInGeneralPurpose(rawInformation) {\n if (!rawInformation) {\n return null;\n }\n // Processing 2-digit AIs\n if (rawInformation.length < 2) {\n throw new NotFoundException();\n }\n let firstTwoDigits = rawInformation.substring(0, 2);\n for (let dataLength of FieldParser.TWO_DIGIT_DATA_LENGTH) {\n if (dataLength[0] === firstTwoDigits) {\n if (dataLength[1] === FieldParser.VARIABLE_LENGTH) {\n return FieldParser.processVariableAI(2, dataLength[2], rawInformation);\n }\n return FieldParser.processFixedAI(2, dataLength[1], rawInformation);\n }\n }\n if (rawInformation.length < 3) {\n throw new NotFoundException();\n }\n let firstThreeDigits = rawInformation.substring(0, 3);\n for (let dataLength of FieldParser.THREE_DIGIT_DATA_LENGTH) {\n if (dataLength[0] === firstThreeDigits) {\n if (dataLength[1] === FieldParser.VARIABLE_LENGTH) {\n return FieldParser.processVariableAI(3, dataLength[2], rawInformation);\n }\n return FieldParser.processFixedAI(3, dataLength[1], rawInformation);\n }\n }\n for (let dataLength of FieldParser.THREE_DIGIT_PLUS_DIGIT_DATA_LENGTH) {\n if (dataLength[0] === firstThreeDigits) {\n if (dataLength[1] === FieldParser.VARIABLE_LENGTH) {\n return FieldParser.processVariableAI(4, dataLength[2], rawInformation);\n }\n return FieldParser.processFixedAI(4, dataLength[1], rawInformation);\n }\n }\n if (rawInformation.length < 4) {\n throw new NotFoundException();\n }\n let firstFourDigits = rawInformation.substring(0, 4);\n for (let dataLength of FieldParser.FOUR_DIGIT_DATA_LENGTH) {\n if (dataLength[0] === firstFourDigits) {\n if (dataLength[1] === FieldParser.VARIABLE_LENGTH) {\n return FieldParser.processVariableAI(4, dataLength[2], rawInformation);\n }\n return FieldParser.processFixedAI(4, dataLength[1], rawInformation);\n }\n }\n throw new NotFoundException();\n }\n static processFixedAI(aiSize, fieldSize, rawInformation) {\n if (rawInformation.length < aiSize) {\n throw new NotFoundException();\n }\n let ai = rawInformation.substring(0, aiSize);\n if (rawInformation.length < aiSize + fieldSize) {\n throw new NotFoundException();\n }\n let field = rawInformation.substring(aiSize, aiSize + fieldSize);\n let remaining = rawInformation.substring(aiSize + fieldSize);\n let result = '(' + ai + ')' + field;\n let parsedAI = FieldParser.parseFieldsInGeneralPurpose(remaining);\n return parsedAI == null ? result : result + parsedAI;\n }\n static processVariableAI(aiSize, variableFieldSize, rawInformation) {\n let ai = rawInformation.substring(0, aiSize);\n let maxSize;\n if (rawInformation.length < aiSize + variableFieldSize) {\n maxSize = rawInformation.length;\n }\n else {\n maxSize = aiSize + variableFieldSize;\n }\n let field = rawInformation.substring(aiSize, maxSize);\n let remaining = rawInformation.substring(maxSize);\n let result = '(' + ai + ')' + field;\n let parsedAI = FieldParser.parseFieldsInGeneralPurpose(remaining);\n return parsedAI == null ? result : result + parsedAI;\n }\n }\n FieldParser.VARIABLE_LENGTH = [];\n FieldParser.TWO_DIGIT_DATA_LENGTH = [\n ['00', 18],\n ['01', 14],\n ['02', 14],\n ['10', FieldParser.VARIABLE_LENGTH, 20],\n ['11', 6],\n ['12', 6],\n ['13', 6],\n ['15', 6],\n ['17', 6],\n ['20', 2],\n ['21', FieldParser.VARIABLE_LENGTH, 20],\n ['22', FieldParser.VARIABLE_LENGTH, 29],\n ['30', FieldParser.VARIABLE_LENGTH, 8],\n ['37', FieldParser.VARIABLE_LENGTH, 8],\n // internal company codes\n ['90', FieldParser.VARIABLE_LENGTH, 30],\n ['91', FieldParser.VARIABLE_LENGTH, 30],\n ['92', FieldParser.VARIABLE_LENGTH, 30],\n ['93', FieldParser.VARIABLE_LENGTH, 30],\n ['94', FieldParser.VARIABLE_LENGTH, 30],\n ['95', FieldParser.VARIABLE_LENGTH, 30],\n ['96', FieldParser.VARIABLE_LENGTH, 30],\n ['97', FieldParser.VARIABLE_LENGTH, 3],\n ['98', FieldParser.VARIABLE_LENGTH, 30],\n ['99', FieldParser.VARIABLE_LENGTH, 30],\n ];\n FieldParser.THREE_DIGIT_DATA_LENGTH = [\n // Same format as above\n ['240', FieldParser.VARIABLE_LENGTH, 30],\n ['241', FieldParser.VARIABLE_LENGTH, 30],\n ['242', FieldParser.VARIABLE_LENGTH, 6],\n ['250', FieldParser.VARIABLE_LENGTH, 30],\n ['251', FieldParser.VARIABLE_LENGTH, 30],\n ['253', FieldParser.VARIABLE_LENGTH, 17],\n ['254', FieldParser.VARIABLE_LENGTH, 20],\n ['400', FieldParser.VARIABLE_LENGTH, 30],\n ['401', FieldParser.VARIABLE_LENGTH, 30],\n ['402', 17],\n ['403', FieldParser.VARIABLE_LENGTH, 30],\n ['410', 13],\n ['411', 13],\n ['412', 13],\n ['413', 13],\n ['414', 13],\n ['420', FieldParser.VARIABLE_LENGTH, 20],\n ['421', FieldParser.VARIABLE_LENGTH, 15],\n ['422', 3],\n ['423', FieldParser.VARIABLE_LENGTH, 15],\n ['424', 3],\n ['425', 3],\n ['426', 3],\n ];\n FieldParser.THREE_DIGIT_PLUS_DIGIT_DATA_LENGTH = [\n // Same format as above\n ['310', 6],\n ['311', 6],\n ['312', 6],\n ['313', 6],\n ['314', 6],\n ['315', 6],\n ['316', 6],\n ['320', 6],\n ['321', 6],\n ['322', 6],\n ['323', 6],\n ['324', 6],\n ['325', 6],\n ['326', 6],\n ['327', 6],\n ['328', 6],\n ['329', 6],\n ['330', 6],\n ['331', 6],\n ['332', 6],\n ['333', 6],\n ['334', 6],\n ['335', 6],\n ['336', 6],\n ['340', 6],\n ['341', 6],\n ['342', 6],\n ['343', 6],\n ['344', 6],\n ['345', 6],\n ['346', 6],\n ['347', 6],\n ['348', 6],\n ['349', 6],\n ['350', 6],\n ['351', 6],\n ['352', 6],\n ['353', 6],\n ['354', 6],\n ['355', 6],\n ['356', 6],\n ['357', 6],\n ['360', 6],\n ['361', 6],\n ['362', 6],\n ['363', 6],\n ['364', 6],\n ['365', 6],\n ['366', 6],\n ['367', 6],\n ['368', 6],\n ['369', 6],\n ['390', FieldParser.VARIABLE_LENGTH, 15],\n ['391', FieldParser.VARIABLE_LENGTH, 18],\n ['392', FieldParser.VARIABLE_LENGTH, 15],\n ['393', FieldParser.VARIABLE_LENGTH, 18],\n ['703', FieldParser.VARIABLE_LENGTH, 30],\n ];\n FieldParser.FOUR_DIGIT_DATA_LENGTH = [\n // Same format as above\n ['7001', 13],\n ['7002', FieldParser.VARIABLE_LENGTH, 30],\n ['7003', 10],\n ['8001', 14],\n ['8002', FieldParser.VARIABLE_LENGTH, 20],\n ['8003', FieldParser.VARIABLE_LENGTH, 30],\n ['8004', FieldParser.VARIABLE_LENGTH, 30],\n ['8005', 6],\n ['8006', 18],\n ['8007', FieldParser.VARIABLE_LENGTH, 30],\n ['8008', FieldParser.VARIABLE_LENGTH, 12],\n ['8018', 18],\n ['8020', FieldParser.VARIABLE_LENGTH, 25],\n ['8100', 6],\n ['8101', 10],\n ['8102', 2],\n ['8110', FieldParser.VARIABLE_LENGTH, 70],\n ['8200', FieldParser.VARIABLE_LENGTH, 70],\n ];\n\n class GeneralAppIdDecoder {\n constructor(information) {\n this.buffer = new StringBuilder();\n this.information = information;\n }\n decodeAllCodes(buff, initialPosition) {\n let currentPosition = initialPosition;\n let remaining = null;\n do {\n let info = this.decodeGeneralPurposeField(currentPosition, remaining);\n let parsedFields = FieldParser.parseFieldsInGeneralPurpose(info.getNewString());\n if (parsedFields != null) {\n buff.append(parsedFields);\n }\n if (info.isRemaining()) {\n remaining = '' + info.getRemainingValue();\n }\n else {\n remaining = null;\n }\n if (currentPosition === info.getNewPosition()) { // No step forward!\n break;\n }\n currentPosition = info.getNewPosition();\n } while (true);\n return buff.toString();\n }\n isStillNumeric(pos) {\n // It's numeric if it still has 7 positions\n // and one of the first 4 bits is \"1\".\n if (pos + 7 > this.information.getSize()) {\n return pos + 4 <= this.information.getSize();\n }\n for (let i = pos; i < pos + 3; ++i) {\n if (this.information.get(i)) {\n return true;\n }\n }\n return this.information.get(pos + 3);\n }\n decodeNumeric(pos) {\n if (pos + 7 > this.information.getSize()) {\n let numeric = this.extractNumericValueFromBitArray(pos, 4);\n if (numeric === 0) {\n return new DecodedNumeric(this.information.getSize(), DecodedNumeric.FNC1, DecodedNumeric.FNC1);\n }\n return new DecodedNumeric(this.information.getSize(), numeric - 1, DecodedNumeric.FNC1);\n }\n let numeric = this.extractNumericValueFromBitArray(pos, 7);\n let digit1 = (numeric - 8) / 11;\n let digit2 = (numeric - 8) % 11;\n return new DecodedNumeric(pos + 7, digit1, digit2);\n }\n extractNumericValueFromBitArray(pos, bits) {\n return GeneralAppIdDecoder.extractNumericValueFromBitArray(this.information, pos, bits);\n }\n static extractNumericValueFromBitArray(information, pos, bits) {\n let value = 0;\n for (let i = 0; i < bits; ++i) {\n if (information.get(pos + i)) {\n value |= 1 << (bits - i - 1);\n }\n }\n return value;\n }\n decodeGeneralPurposeField(pos, remaining) {\n // this.buffer.setLength(0);\n this.buffer.setLengthToZero();\n if (remaining != null) {\n this.buffer.append(remaining);\n }\n this.current.setPosition(pos);\n let lastDecoded = this.parseBlocks();\n if (lastDecoded != null && lastDecoded.isRemaining()) {\n return new DecodedInformation(this.current.getPosition(), this.buffer.toString(), lastDecoded.getRemainingValue());\n }\n return new DecodedInformation(this.current.getPosition(), this.buffer.toString());\n }\n parseBlocks() {\n let isFinished;\n let result;\n do {\n let initialPosition = this.current.getPosition();\n if (this.current.isAlpha()) {\n result = this.parseAlphaBlock();\n isFinished = result.isFinished();\n }\n else if (this.current.isIsoIec646()) {\n result = this.parseIsoIec646Block();\n isFinished = result.isFinished();\n }\n else { // it must be numeric\n result = this.parseNumericBlock();\n isFinished = result.isFinished();\n }\n let positionChanged = initialPosition !== this.current.getPosition();\n if (!positionChanged && !isFinished) {\n break;\n }\n } while (!isFinished);\n return result.getDecodedInformation();\n }\n parseNumericBlock() {\n while (this.isStillNumeric(this.current.getPosition())) {\n let numeric = this.decodeNumeric(this.current.getPosition());\n this.current.setPosition(numeric.getNewPosition());\n if (numeric.isFirstDigitFNC1()) {\n let information;\n if (numeric.isSecondDigitFNC1()) {\n information = new DecodedInformation(this.current.getPosition(), this.buffer.toString());\n }\n else {\n information = new DecodedInformation(this.current.getPosition(), this.buffer.toString(), numeric.getSecondDigit());\n }\n return new BlockParsedResult(true, information);\n }\n this.buffer.append(numeric.getFirstDigit());\n if (numeric.isSecondDigitFNC1()) {\n let information = new DecodedInformation(this.current.getPosition(), this.buffer.toString());\n return new BlockParsedResult(true, information);\n }\n this.buffer.append(numeric.getSecondDigit());\n }\n if (this.isNumericToAlphaNumericLatch(this.current.getPosition())) {\n this.current.setAlpha();\n this.current.incrementPosition(4);\n }\n return new BlockParsedResult(false);\n }\n parseIsoIec646Block() {\n while (this.isStillIsoIec646(this.current.getPosition())) {\n let iso = this.decodeIsoIec646(this.current.getPosition());\n this.current.setPosition(iso.getNewPosition());\n if (iso.isFNC1()) {\n let information = new DecodedInformation(this.current.getPosition(), this.buffer.toString());\n return new BlockParsedResult(true, information);\n }\n this.buffer.append(iso.getValue());\n }\n if (this.isAlphaOr646ToNumericLatch(this.current.getPosition())) {\n this.current.incrementPosition(3);\n this.current.setNumeric();\n }\n else if (this.isAlphaTo646ToAlphaLatch(this.current.getPosition())) {\n if (this.current.getPosition() + 5 < this.information.getSize()) {\n this.current.incrementPosition(5);\n }\n else {\n this.current.setPosition(this.information.getSize());\n }\n this.current.setAlpha();\n }\n return new BlockParsedResult(false);\n }\n parseAlphaBlock() {\n while (this.isStillAlpha(this.current.getPosition())) {\n let alpha = this.decodeAlphanumeric(this.current.getPosition());\n this.current.setPosition(alpha.getNewPosition());\n if (alpha.isFNC1()) {\n let information = new DecodedInformation(this.current.getPosition(), this.buffer.toString());\n return new BlockParsedResult(true, information); // end of the char block\n }\n this.buffer.append(alpha.getValue());\n }\n if (this.isAlphaOr646ToNumericLatch(this.current.getPosition())) {\n this.current.incrementPosition(3);\n this.current.setNumeric();\n }\n else if (this.isAlphaTo646ToAlphaLatch(this.current.getPosition())) {\n if (this.current.getPosition() + 5 < this.information.getSize()) {\n this.current.incrementPosition(5);\n }\n else {\n this.current.setPosition(this.information.getSize());\n }\n this.current.setIsoIec646();\n }\n return new BlockParsedResult(false);\n }\n isStillIsoIec646(pos) {\n if (pos + 5 > this.information.getSize()) {\n return false;\n }\n let fiveBitValue = this.extractNumericValueFromBitArray(pos, 5);\n if (fiveBitValue >= 5 && fiveBitValue < 16) {\n return true;\n }\n if (pos + 7 > this.information.getSize()) {\n return false;\n }\n let sevenBitValue = this.extractNumericValueFromBitArray(pos, 7);\n if (sevenBitValue >= 64 && sevenBitValue < 116) {\n return true;\n }\n if (pos + 8 > this.information.getSize()) {\n return false;\n }\n let eightBitValue = this.extractNumericValueFromBitArray(pos, 8);\n return eightBitValue >= 232 && eightBitValue < 253;\n }\n decodeIsoIec646(pos) {\n let fiveBitValue = this.extractNumericValueFromBitArray(pos, 5);\n if (fiveBitValue === 15) {\n return new DecodedChar(pos + 5, DecodedChar.FNC1);\n }\n if (fiveBitValue >= 5 && fiveBitValue < 15) {\n return new DecodedChar(pos + 5, ('0' + (fiveBitValue - 5)));\n }\n let sevenBitValue = this.extractNumericValueFromBitArray(pos, 7);\n if (sevenBitValue >= 64 && sevenBitValue < 90) {\n return new DecodedChar(pos + 7, ('' + (sevenBitValue + 1)));\n }\n if (sevenBitValue >= 90 && sevenBitValue < 116) {\n return new DecodedChar(pos + 7, ('' + (sevenBitValue + 7)));\n }\n let eightBitValue = this.extractNumericValueFromBitArray(pos, 8);\n let c;\n switch (eightBitValue) {\n case 232:\n c = '!';\n break;\n case 233:\n c = '\"';\n break;\n case 234:\n c = '%';\n break;\n case 235:\n c = '&';\n break;\n case 236:\n c = '\\'';\n break;\n case 237:\n c = '(';\n break;\n case 238:\n c = ')';\n break;\n case 239:\n c = '*';\n break;\n case 240:\n c = '+';\n break;\n case 241:\n c = ',';\n break;\n case 242:\n c = '-';\n break;\n case 243:\n c = '.';\n break;\n case 244:\n c = '/';\n break;\n case 245:\n c = ':';\n break;\n case 246:\n c = ';';\n break;\n case 247:\n c = '<';\n break;\n case 248:\n c = '=';\n break;\n case 249:\n c = '>';\n break;\n case 250:\n c = '?';\n break;\n case 251:\n c = '_';\n break;\n case 252:\n c = ' ';\n break;\n default:\n throw new FormatException();\n }\n return new DecodedChar(pos + 8, c);\n }\n isStillAlpha(pos) {\n if (pos + 5 > this.information.getSize()) {\n return false;\n }\n // We now check if it's a valid 5-bit value (0..9 and FNC1)\n let fiveBitValue = this.extractNumericValueFromBitArray(pos, 5);\n if (fiveBitValue >= 5 && fiveBitValue < 16) {\n return true;\n }\n if (pos + 6 > this.information.getSize()) {\n return false;\n }\n let sixBitValue = this.extractNumericValueFromBitArray(pos, 6);\n return sixBitValue >= 16 && sixBitValue < 63; // 63 not included\n }\n decodeAlphanumeric(pos) {\n let fiveBitValue = this.extractNumericValueFromBitArray(pos, 5);\n if (fiveBitValue === 15) {\n return new DecodedChar(pos + 5, DecodedChar.FNC1);\n }\n if (fiveBitValue >= 5 && fiveBitValue < 15) {\n return new DecodedChar(pos + 5, ('0' + (fiveBitValue - 5)));\n }\n let sixBitValue = this.extractNumericValueFromBitArray(pos, 6);\n if (sixBitValue >= 32 && sixBitValue < 58) {\n return new DecodedChar(pos + 6, ('' + (sixBitValue + 33)));\n }\n let c;\n switch (sixBitValue) {\n case 58:\n c = '*';\n break;\n case 59:\n c = ',';\n break;\n case 60:\n c = '-';\n break;\n case 61:\n c = '.';\n break;\n case 62:\n c = '/';\n break;\n default:\n throw new IllegalStateException('Decoding invalid alphanumeric value: ' + sixBitValue);\n }\n return new DecodedChar(pos + 6, c);\n }\n isAlphaTo646ToAlphaLatch(pos) {\n if (pos + 1 > this.information.getSize()) {\n return false;\n }\n for (let i = 0; i < 5 && i + pos < this.information.getSize(); ++i) {\n if (i === 2) {\n if (!this.information.get(pos + 2)) {\n return false;\n }\n }\n else if (this.information.get(pos + i)) {\n return false;\n }\n }\n return true;\n }\n isAlphaOr646ToNumericLatch(pos) {\n // Next is alphanumeric if there are 3 positions and they are all zeros\n if (pos + 3 > this.information.getSize()) {\n return false;\n }\n for (let i = pos; i < pos + 3; ++i) {\n if (this.information.get(i)) {\n return false;\n }\n }\n return true;\n }\n isNumericToAlphaNumericLatch(pos) {\n // Next is alphanumeric if there are 4 positions and they are all zeros, or\n // if there is a subset of this just before the end of the symbol\n if (pos + 1 > this.information.getSize()) {\n return false;\n }\n for (let i = 0; i < 4 && i + pos < this.information.getSize(); ++i) {\n if (this.information.get(pos + i)) {\n return false;\n }\n }\n return true;\n }\n }\n\n class AbstractExpandedDecoder {\n constructor(information) {\n this.information = information;\n this.generalDecoder = new GeneralAppIdDecoder(information);\n }\n getInformation() {\n return this.information;\n }\n getGeneralDecoder() {\n return this.generalDecoder;\n }\n }\n\n class AI01decoder extends AbstractExpandedDecoder {\n constructor(information) {\n super(information);\n }\n encodeCompressedGtin(buf, currentPos) {\n buf.append('(01)');\n let initialPosition = buf.length();\n buf.append('9');\n this.encodeCompressedGtinWithoutAI(buf, currentPos, initialPosition);\n }\n encodeCompressedGtinWithoutAI(buf, currentPos, initialBufferPosition) {\n for (let i = 0; i < 4; ++i) {\n let currentBlock = this.getGeneralDecoder().extractNumericValueFromBitArray(currentPos + 10 * i, 10);\n if (currentBlock / 100 === 0) {\n buf.append('0');\n }\n if (currentBlock / 10 === 0) {\n buf.append('0');\n }\n buf.append(currentBlock);\n }\n AI01decoder.appendCheckDigit(buf, initialBufferPosition);\n }\n static appendCheckDigit(buf, currentPos) {\n let checkDigit = 0;\n for (let i = 0; i < 13; i++) {\n // let digit = buf.charAt(i + currentPos) - '0';\n // To be checked\n let digit = buf.charAt(i + currentPos).charCodeAt(0) - '0'.charCodeAt(0);\n checkDigit += (i & 0x01) === 0 ? 3 * digit : digit;\n }\n checkDigit = 10 - (checkDigit % 10);\n if (checkDigit === 10) {\n checkDigit = 0;\n }\n buf.append(checkDigit);\n }\n }\n AI01decoder.GTIN_SIZE = 40;\n\n class AI01AndOtherAIs extends AI01decoder {\n // the second one is the encodation method, and the other two are for the variable length\n constructor(information) {\n super(information);\n }\n parseInformation() {\n let buff = new StringBuilder();\n buff.append('(01)');\n let initialGtinPosition = buff.length();\n let firstGtinDigit = this.getGeneralDecoder().extractNumericValueFromBitArray(AI01AndOtherAIs.HEADER_SIZE, 4);\n buff.append(firstGtinDigit);\n this.encodeCompressedGtinWithoutAI(buff, AI01AndOtherAIs.HEADER_SIZE + 4, initialGtinPosition);\n return this.getGeneralDecoder().decodeAllCodes(buff, AI01AndOtherAIs.HEADER_SIZE + 44);\n }\n }\n AI01AndOtherAIs.HEADER_SIZE = 1 + 1 + 2; // first bit encodes the linkage flag,\n\n class AnyAIDecoder extends AbstractExpandedDecoder {\n constructor(information) {\n super(information);\n }\n parseInformation() {\n let buf = new StringBuilder();\n return this.getGeneralDecoder().decodeAllCodes(buf, AnyAIDecoder.HEADER_SIZE);\n }\n }\n AnyAIDecoder.HEADER_SIZE = 2 + 1 + 2;\n\n class AI01weightDecoder extends AI01decoder {\n constructor(information) {\n super(information);\n }\n encodeCompressedWeight(buf, currentPos, weightSize) {\n let originalWeightNumeric = this.getGeneralDecoder().extractNumericValueFromBitArray(currentPos, weightSize);\n this.addWeightCode(buf, originalWeightNumeric);\n let weightNumeric = this.checkWeight(originalWeightNumeric);\n let currentDivisor = 100000;\n for (let i = 0; i < 5; ++i) {\n if (weightNumeric / currentDivisor === 0) {\n buf.append('0');\n }\n currentDivisor /= 10;\n }\n buf.append(weightNumeric);\n }\n }\n\n class AI013x0xDecoder extends AI01weightDecoder {\n constructor(information) {\n super(information);\n }\n parseInformation() {\n if (this.getInformation().getSize() != AI013x0xDecoder.HEADER_SIZE + AI01weightDecoder.GTIN_SIZE + AI013x0xDecoder.WEIGHT_SIZE) {\n throw new NotFoundException();\n }\n let buf = new StringBuilder();\n this.encodeCompressedGtin(buf, AI013x0xDecoder.HEADER_SIZE);\n this.encodeCompressedWeight(buf, AI013x0xDecoder.HEADER_SIZE + AI01weightDecoder.GTIN_SIZE, AI013x0xDecoder.WEIGHT_SIZE);\n return buf.toString();\n }\n }\n AI013x0xDecoder.HEADER_SIZE = 4 + 1;\n AI013x0xDecoder.WEIGHT_SIZE = 15;\n\n class AI013103decoder extends AI013x0xDecoder {\n constructor(information) {\n super(information);\n }\n addWeightCode(buf, weight) {\n buf.append('(3103)');\n }\n checkWeight(weight) {\n return weight;\n }\n }\n\n class AI01320xDecoder extends AI013x0xDecoder {\n constructor(information) {\n super(information);\n }\n addWeightCode(buf, weight) {\n if (weight < 10000) {\n buf.append('(3202)');\n }\n else {\n buf.append('(3203)');\n }\n }\n checkWeight(weight) {\n if (weight < 10000) {\n return weight;\n }\n return weight - 10000;\n }\n }\n\n class AI01392xDecoder extends AI01decoder {\n constructor(information) {\n super(information);\n }\n parseInformation() {\n if (this.getInformation().getSize() < AI01392xDecoder.HEADER_SIZE + AI01decoder.GTIN_SIZE) {\n throw new NotFoundException();\n }\n let buf = new StringBuilder();\n this.encodeCompressedGtin(buf, AI01392xDecoder.HEADER_SIZE);\n let lastAIdigit = this.getGeneralDecoder().extractNumericValueFromBitArray(AI01392xDecoder.HEADER_SIZE + AI01decoder.GTIN_SIZE, AI01392xDecoder.LAST_DIGIT_SIZE);\n buf.append('(392');\n buf.append(lastAIdigit);\n buf.append(')');\n let decodedInformation = this.getGeneralDecoder().decodeGeneralPurposeField(AI01392xDecoder.HEADER_SIZE + AI01decoder.GTIN_SIZE + AI01392xDecoder.LAST_DIGIT_SIZE, null);\n buf.append(decodedInformation.getNewString());\n return buf.toString();\n }\n }\n AI01392xDecoder.HEADER_SIZE = 5 + 1 + 2;\n AI01392xDecoder.LAST_DIGIT_SIZE = 2;\n\n class AI01393xDecoder extends AI01decoder {\n constructor(information) {\n super(information);\n }\n parseInformation() {\n if (this.getInformation().getSize() < AI01393xDecoder.HEADER_SIZE + AI01decoder.GTIN_SIZE) {\n throw new NotFoundException();\n }\n let buf = new StringBuilder();\n this.encodeCompressedGtin(buf, AI01393xDecoder.HEADER_SIZE);\n let lastAIdigit = this.getGeneralDecoder().extractNumericValueFromBitArray(AI01393xDecoder.HEADER_SIZE + AI01decoder.GTIN_SIZE, AI01393xDecoder.LAST_DIGIT_SIZE);\n buf.append('(393');\n buf.append(lastAIdigit);\n buf.append(')');\n let firstThreeDigits = this.getGeneralDecoder().extractNumericValueFromBitArray(AI01393xDecoder.HEADER_SIZE + AI01decoder.GTIN_SIZE + AI01393xDecoder.LAST_DIGIT_SIZE, AI01393xDecoder.FIRST_THREE_DIGITS_SIZE);\n if (firstThreeDigits / 100 == 0) {\n buf.append('0');\n }\n if (firstThreeDigits / 10 == 0) {\n buf.append('0');\n }\n buf.append(firstThreeDigits);\n let generalInformation = this.getGeneralDecoder().decodeGeneralPurposeField(AI01393xDecoder.HEADER_SIZE + AI01decoder.GTIN_SIZE + AI01393xDecoder.LAST_DIGIT_SIZE + AI01393xDecoder.FIRST_THREE_DIGITS_SIZE, null);\n buf.append(generalInformation.getNewString());\n return buf.toString();\n }\n }\n AI01393xDecoder.HEADER_SIZE = 5 + 1 + 2;\n AI01393xDecoder.LAST_DIGIT_SIZE = 2;\n AI01393xDecoder.FIRST_THREE_DIGITS_SIZE = 10;\n\n class AI013x0x1xDecoder extends AI01weightDecoder {\n constructor(information, firstAIdigits, dateCode) {\n super(information);\n this.dateCode = dateCode;\n this.firstAIdigits = firstAIdigits;\n }\n parseInformation() {\n if (this.getInformation().getSize() != AI013x0x1xDecoder.HEADER_SIZE + AI013x0x1xDecoder.GTIN_SIZE + AI013x0x1xDecoder.WEIGHT_SIZE + AI013x0x1xDecoder.DATE_SIZE) {\n throw new NotFoundException();\n }\n let buf = new StringBuilder();\n this.encodeCompressedGtin(buf, AI013x0x1xDecoder.HEADER_SIZE);\n this.encodeCompressedWeight(buf, AI013x0x1xDecoder.HEADER_SIZE + AI013x0x1xDecoder.GTIN_SIZE, AI013x0x1xDecoder.WEIGHT_SIZE);\n this.encodeCompressedDate(buf, AI013x0x1xDecoder.HEADER_SIZE + AI013x0x1xDecoder.GTIN_SIZE + AI013x0x1xDecoder.WEIGHT_SIZE);\n return buf.toString();\n }\n encodeCompressedDate(buf, currentPos) {\n let numericDate = this.getGeneralDecoder().extractNumericValueFromBitArray(currentPos, AI013x0x1xDecoder.DATE_SIZE);\n if (numericDate == 38400) {\n return;\n }\n buf.append('(');\n buf.append(this.dateCode);\n buf.append(')');\n let day = numericDate % 32;\n numericDate /= 32;\n let month = numericDate % 12 + 1;\n numericDate /= 12;\n let year = numericDate;\n if (year / 10 == 0) {\n buf.append('0');\n }\n buf.append(year);\n if (month / 10 == 0) {\n buf.append('0');\n }\n buf.append(month);\n if (day / 10 == 0) {\n buf.append('0');\n }\n buf.append(day);\n }\n addWeightCode(buf, weight) {\n buf.append('(');\n buf.append(this.firstAIdigits);\n buf.append(weight / 100000);\n buf.append(')');\n }\n checkWeight(weight) {\n return weight % 100000;\n }\n }\n AI013x0x1xDecoder.HEADER_SIZE = 7 + 1;\n AI013x0x1xDecoder.WEIGHT_SIZE = 20;\n AI013x0x1xDecoder.DATE_SIZE = 16;\n\n function createDecoder(information) {\n try {\n if (information.get(1)) {\n return new AI01AndOtherAIs(information);\n }\n if (!information.get(2)) {\n return new AnyAIDecoder(information);\n }\n let fourBitEncodationMethod = GeneralAppIdDecoder.extractNumericValueFromBitArray(information, 1, 4);\n switch (fourBitEncodationMethod) {\n case 4: return new AI013103decoder(information);\n case 5: return new AI01320xDecoder(information);\n }\n let fiveBitEncodationMethod = GeneralAppIdDecoder.extractNumericValueFromBitArray(information, 1, 5);\n switch (fiveBitEncodationMethod) {\n case 12: return new AI01392xDecoder(information);\n case 13: return new AI01393xDecoder(information);\n }\n let sevenBitEncodationMethod = GeneralAppIdDecoder.extractNumericValueFromBitArray(information, 1, 7);\n switch (sevenBitEncodationMethod) {\n case 56: return new AI013x0x1xDecoder(information, '310', '11');\n case 57: return new AI013x0x1xDecoder(information, '320', '11');\n case 58: return new AI013x0x1xDecoder(information, '310', '13');\n case 59: return new AI013x0x1xDecoder(information, '320', '13');\n case 60: return new AI013x0x1xDecoder(information, '310', '15');\n case 61: return new AI013x0x1xDecoder(information, '320', '15');\n case 62: return new AI013x0x1xDecoder(information, '310', '17');\n case 63: return new AI013x0x1xDecoder(information, '320', '17');\n }\n }\n catch (e) {\n console.log(e);\n throw new IllegalStateException('unknown decoder: ' + information);\n }\n }\n\n class ExpandedPair {\n constructor(leftChar, rightChar, finderPatter, mayBeLast) {\n this.leftchar = leftChar;\n this.rightchar = rightChar;\n this.finderpattern = finderPatter;\n this.maybeLast = mayBeLast;\n }\n mayBeLast() {\n return this.maybeLast;\n }\n getLeftChar() {\n return this.leftchar;\n }\n getRightChar() {\n return this.rightchar;\n }\n getFinderPattern() {\n return this.finderpattern;\n }\n mustBeLast() {\n return this.rightchar == null;\n }\n toString() {\n return '[ ' + this.leftchar + ', ' + this.rightchar + ' : ' + (this.finderpattern == null ? 'null' : this.finderpattern.getValue()) + ' ]';\n }\n static equals(o1, o2) {\n if (!(o1 instanceof ExpandedPair)) {\n return false;\n }\n return ExpandedPair.equalsOrNull(o1.leftchar, o2.leftchar) &&\n ExpandedPair.equalsOrNull(o1.rightchar, o2.rightchar) &&\n ExpandedPair.equalsOrNull(o1.finderpattern, o2.finderpattern);\n }\n static equalsOrNull(o1, o2) {\n return o1 === null ? o2 === null : ExpandedPair.equals(o1, o2);\n }\n hashCode() {\n // return ExpandedPair.hashNotNull(leftChar) ^ hashNotNull(rightChar) ^ hashNotNull(finderPattern);\n let value = this.leftchar.getValue() ^ this.rightchar.getValue() ^ this.finderpattern.getValue();\n return value;\n }\n }\n\n class ExpandedRow {\n constructor(pairs, rowNumber, wasReversed) {\n this.pairs = pairs;\n this.rowNumber = rowNumber;\n this.wasReversed = wasReversed;\n }\n getPairs() {\n return this.pairs;\n }\n getRowNumber() {\n return this.rowNumber;\n }\n isReversed() {\n return this.wasReversed;\n }\n // check implementation\n isEquivalent(otherPairs) {\n return this.checkEqualitity(this, otherPairs);\n }\n // @Override\n toString() {\n return '{ ' + this.pairs + ' }';\n }\n /**\n * Two rows are equal if they contain the same pairs in the same order.\n */\n // @Override\n // check implementation\n equals(o1, o2) {\n if (!(o1 instanceof ExpandedRow)) {\n return false;\n }\n return this.checkEqualitity(o1, o2) && o1.wasReversed === o2.wasReversed;\n }\n checkEqualitity(pair1, pair2) {\n if (!pair1 || !pair2)\n return;\n let result;\n pair1.forEach((e1, i) => {\n pair2.forEach(e2 => {\n if (e1.getLeftChar().getValue() === e2.getLeftChar().getValue() && e1.getRightChar().getValue() === e2.getRightChar().getValue() && e1.getFinderPatter().getValue() === e2.getFinderPatter().getValue()) {\n result = true;\n }\n });\n });\n return result;\n }\n }\n\n // import java.util.ArrayList;\n // import java.util.Iterator;\n // import java.util.List;\n // import java.util.Map;\n // import java.util.Collections;\n class RSSExpandedReader extends AbstractRSSReader {\n constructor(verbose) {\n super(...arguments);\n this.pairs = new Array(RSSExpandedReader.MAX_PAIRS);\n this.rows = new Array();\n this.startEnd = [2];\n this.verbose = (verbose === true);\n }\n decodeRow(rowNumber, row, hints) {\n // Rows can start with even pattern in case in prev rows there where odd number of patters.\n // So lets try twice\n // this.pairs.clear();\n this.pairs.length = 0;\n this.startFromEven = false;\n try {\n return RSSExpandedReader.constructResult(this.decodeRow2pairs(rowNumber, row));\n }\n catch (e) {\n // OK\n if (this.verbose) {\n console.log(e);\n }\n }\n this.pairs.length = 0;\n this.startFromEven = true;\n return RSSExpandedReader.constructResult(this.decodeRow2pairs(rowNumber, row));\n }\n reset() {\n this.pairs.length = 0;\n this.rows.length = 0;\n }\n // Not private for testing\n decodeRow2pairs(rowNumber, row) {\n let done = false;\n while (!done) {\n try {\n this.pairs.push(this.retrieveNextPair(row, this.pairs, rowNumber));\n }\n catch (error) {\n if (error instanceof NotFoundException) {\n if (!this.pairs.length) {\n throw new NotFoundException();\n }\n // exit this loop when retrieveNextPair() fails and throws\n done = true;\n }\n }\n }\n // TODO: verify sequence of finder patterns as in checkPairSequence()\n if (this.checkChecksum()) {\n return this.pairs;\n }\n let tryStackedDecode;\n if (this.rows.length) {\n tryStackedDecode = true;\n }\n else {\n tryStackedDecode = false;\n }\n // let tryStackedDecode = !this.rows.isEmpty();\n this.storeRow(rowNumber, false); // TODO: deal with reversed rows\n if (tryStackedDecode) {\n // When the image is 180-rotated, then rows are sorted in wrong direction.\n // Try twice with both the directions.\n let ps = this.checkRowsBoolean(false);\n if (ps != null) {\n return ps;\n }\n ps = this.checkRowsBoolean(true);\n if (ps != null) {\n return ps;\n }\n }\n throw new NotFoundException();\n }\n // Need to Verify\n checkRowsBoolean(reverse) {\n // Limit number of rows we are checking\n // We use recursive algorithm with pure complexity and don't want it to take forever\n // Stacked barcode can have up to 11 rows, so 25 seems reasonable enough\n if (this.rows.length > 25) {\n this.rows.length = 0; // We will never have a chance to get result, so clear it\n return null;\n }\n this.pairs.length = 0;\n if (reverse) {\n this.rows = this.rows.reverse();\n // Collections.reverse(this.rows);\n }\n let ps = null;\n try {\n ps = this.checkRows(new Array(), 0);\n }\n catch (e) {\n // OK\n if (this.verbose) {\n console.log(e);\n }\n }\n if (reverse) {\n this.rows = this.rows.reverse();\n // Collections.reverse(this.rows);\n }\n return ps;\n }\n // Try to construct a valid rows sequence\n // Recursion is used to implement backtracking\n checkRows(collectedRows, currentRow) {\n for (let i = currentRow; i < this.rows.length; i++) {\n let row = this.rows[i];\n this.pairs.length = 0;\n for (let collectedRow of collectedRows) {\n this.pairs.push(collectedRow.getPairs());\n }\n this.pairs.push(row.getPairs());\n if (!RSSExpandedReader.isValidSequence(this.pairs)) {\n continue;\n }\n if (this.checkChecksum()) {\n return this.pairs;\n }\n let rs = new Array(collectedRows);\n rs.push(row);\n try {\n // Recursion: try to add more rows\n return this.checkRows(rs, i + 1);\n }\n catch (e) {\n // We failed, try the next candidate\n if (this.verbose) {\n console.log(e);\n }\n }\n }\n throw new NotFoundException();\n }\n // Whether the pairs form a valid find pattern sequence,\n // either complete or a prefix\n static isValidSequence(pairs) {\n for (let sequence of RSSExpandedReader.FINDER_PATTERN_SEQUENCES) {\n if (pairs.length > sequence.length) {\n continue;\n }\n let stop = true;\n for (let j = 0; j < pairs.length; j++) {\n if (pairs[j].getFinderPattern().getValue() != sequence[j]) {\n stop = false;\n break;\n }\n }\n if (stop) {\n return true;\n }\n }\n return false;\n }\n storeRow(rowNumber, wasReversed) {\n // Discard if duplicate above or below; otherwise insert in order by row number.\n let insertPos = 0;\n let prevIsSame = false;\n let nextIsSame = false;\n while (insertPos < this.rows.length) {\n let erow = this.rows[insertPos];\n if (erow.getRowNumber() > rowNumber) {\n nextIsSame = erow.isEquivalent(this.pairs);\n break;\n }\n prevIsSame = erow.isEquivalent(this.pairs);\n insertPos++;\n }\n if (nextIsSame || prevIsSame) {\n return;\n }\n // When the row was partially decoded (e.g. 2 pairs found instead of 3),\n // it will prevent us from detecting the barcode.\n // Try to merge partial rows\n // Check whether the row is part of an allready detected row\n if (RSSExpandedReader.isPartialRow(this.pairs, this.rows)) {\n return;\n }\n this.rows.push(insertPos, new ExpandedRow(this.pairs, rowNumber, wasReversed));\n this.removePartialRows(this.pairs, this.rows);\n }\n // Remove all the rows that contains only specified pairs\n removePartialRows(pairs, rows) {\n // for (Iterator iterator = rows.iterator(); iterator.hasNext();) {\n // ExpandedRow r = iterator.next();\n // if (r.getPairs().size() == pairs.size()) {\n // continue;\n // }\n // boolean allFound = true;\n // for (ExpandedPair p : r.getPairs()) {\n // boolean found = false;\n // for (ExpandedPair pp : pairs) {\n // if (p.equals(pp)) {\n // found = true;\n // break;\n // }\n // }\n // if (!found) {\n // allFound = false;\n // break;\n // }\n // }\n // if (allFound) {\n // // 'pairs' contains all the pairs from the row 'r'\n // iterator.remove();\n // }\n // }\n for (let row of rows) {\n if (row.getPairs().length === pairs.length) {\n continue;\n }\n for (let p of row.getPairs()) {\n for (let pp of pairs) {\n if (ExpandedPair.equals(p, pp)) {\n break;\n }\n }\n }\n }\n }\n // Returns true when one of the rows already contains all the pairs\n static isPartialRow(pairs, rows) {\n for (let r of rows) {\n let allFound = true;\n for (let p of pairs) {\n let found = false;\n for (let pp of r.getPairs()) {\n if (p.equals(pp)) {\n found = true;\n break;\n }\n }\n if (!found) {\n allFound = false;\n break;\n }\n }\n if (allFound) {\n // the row 'r' contain all the pairs from 'pairs'\n return true;\n }\n }\n return false;\n }\n // Only used for unit testing\n getRows() {\n return this.rows;\n }\n // Not private for unit testing\n static constructResult(pairs) {\n let binary = BitArrayBuilder.buildBitArray(pairs);\n let decoder = createDecoder(binary);\n let resultingString = decoder.parseInformation();\n let firstPoints = pairs[0].getFinderPattern().getResultPoints();\n let lastPoints = pairs[pairs.length - 1].getFinderPattern().getResultPoints();\n let points = [firstPoints[0], firstPoints[1], lastPoints[0], lastPoints[1]];\n return new Result(resultingString, null, null, points, BarcodeFormat$1.RSS_EXPANDED, null);\n }\n checkChecksum() {\n let firstPair = this.pairs.get(0);\n let checkCharacter = firstPair.getLeftChar();\n let firstCharacter = firstPair.getRightChar();\n if (firstCharacter == null) {\n return false;\n }\n let checksum = firstCharacter.getChecksumPortion();\n let s = 2;\n for (let i = 1; i < this.pairs.size(); ++i) {\n let currentPair = this.pairs.get(i);\n checksum += currentPair.getLeftChar().getChecksumPortion();\n s++;\n let currentRightChar = currentPair.getRightChar();\n if (currentRightChar != null) {\n checksum += currentRightChar.getChecksumPortion();\n s++;\n }\n }\n checksum %= 211;\n let checkCharacterValue = 211 * (s - 4) + checksum;\n return checkCharacterValue == checkCharacter.getValue();\n }\n static getNextSecondBar(row, initialPos) {\n let currentPos;\n if (row.get(initialPos)) {\n currentPos = row.getNextUnset(initialPos);\n currentPos = row.getNextSet(currentPos);\n }\n else {\n currentPos = row.getNextSet(initialPos);\n currentPos = row.getNextUnset(currentPos);\n }\n return currentPos;\n }\n // not private for testing\n retrieveNextPair(row, previousPairs, rowNumber) {\n let isOddPattern = previousPairs.length % 2 == 0;\n if (this.startFromEven) {\n isOddPattern = !isOddPattern;\n }\n let pattern;\n let keepFinding = true;\n let forcedOffset = -1;\n do {\n this.findNextPair(row, previousPairs, forcedOffset);\n pattern = this.parseFoundFinderPattern(row, rowNumber, isOddPattern);\n if (pattern == null) {\n forcedOffset = RSSExpandedReader.getNextSecondBar(row, this.startEnd[0]);\n }\n else {\n keepFinding = false;\n }\n } while (keepFinding);\n // When stacked symbol is split over multiple rows, there's no way to guess if this pair can be last or not.\n // boolean mayBeLast = checkPairSequence(previousPairs, pattern);\n let leftChar = this.decodeDataCharacter(row, pattern, isOddPattern, true);\n if (!this.isEmptyPair(previousPairs) && previousPairs[previousPairs.length - 1].mustBeLast()) {\n throw new NotFoundException();\n }\n let rightChar;\n try {\n rightChar = this.decodeDataCharacter(row, pattern, isOddPattern, false);\n }\n catch (e) {\n rightChar = null;\n if (this.verbose) {\n console.log(e);\n }\n }\n return new ExpandedPair(leftChar, rightChar, pattern, true);\n }\n isEmptyPair(pairs) {\n if (pairs.length === 0) {\n return true;\n }\n return false;\n }\n findNextPair(row, previousPairs, forcedOffset) {\n let counters = this.getDecodeFinderCounters();\n counters[0] = 0;\n counters[1] = 0;\n counters[2] = 0;\n counters[3] = 0;\n let width = row.getSize();\n let rowOffset;\n if (forcedOffset >= 0) {\n rowOffset = forcedOffset;\n }\n else if (this.isEmptyPair(previousPairs)) {\n rowOffset = 0;\n }\n else {\n let lastPair = previousPairs[previousPairs.length - 1];\n rowOffset = lastPair.getFinderPattern().getStartEnd()[1];\n }\n let searchingEvenPair = previousPairs.length % 2 != 0;\n if (this.startFromEven) {\n searchingEvenPair = !searchingEvenPair;\n }\n let isWhite = false;\n while (rowOffset < width) {\n isWhite = !row.get(rowOffset);\n if (!isWhite) {\n break;\n }\n rowOffset++;\n }\n let counterPosition = 0;\n let patternStart = rowOffset;\n for (let x = rowOffset; x < width; x++) {\n if (row.get(x) != isWhite) {\n counters[counterPosition]++;\n }\n else {\n if (counterPosition == 3) {\n if (searchingEvenPair) {\n RSSExpandedReader.reverseCounters(counters);\n }\n if (RSSExpandedReader.isFinderPattern(counters)) {\n this.startEnd[0] = patternStart;\n this.startEnd[1] = x;\n return;\n }\n if (searchingEvenPair) {\n RSSExpandedReader.reverseCounters(counters);\n }\n patternStart += counters[0] + counters[1];\n counters[0] = counters[2];\n counters[1] = counters[3];\n counters[2] = 0;\n counters[3] = 0;\n counterPosition--;\n }\n else {\n counterPosition++;\n }\n counters[counterPosition] = 1;\n isWhite = !isWhite;\n }\n }\n throw new NotFoundException();\n }\n static reverseCounters(counters) {\n let length = counters.length;\n for (let i = 0; i < length / 2; ++i) {\n let tmp = counters[i];\n counters[i] = counters[length - i - 1];\n counters[length - i - 1] = tmp;\n }\n }\n parseFoundFinderPattern(row, rowNumber, oddPattern) {\n // Actually we found elements 2-5.\n let firstCounter;\n let start;\n let end;\n if (oddPattern) {\n // If pattern number is odd, we need to locate element 1 *before* the current block.\n let firstElementStart = this.startEnd[0] - 1;\n // Locate element 1\n while (firstElementStart >= 0 && !row.get(firstElementStart)) {\n firstElementStart--;\n }\n firstElementStart++;\n firstCounter = this.startEnd[0] - firstElementStart;\n start = firstElementStart;\n end = this.startEnd[1];\n }\n else {\n // If pattern number is even, the pattern is reversed, so we need to locate element 1 *after* the current block.\n start = this.startEnd[0];\n end = row.getNextUnset(this.startEnd[1] + 1);\n firstCounter = end - this.startEnd[1];\n }\n // Make 'counters' hold 1-4\n let counters = this.getDecodeFinderCounters();\n System.arraycopy(counters, 0, counters, 1, counters.length - 1);\n counters[0] = firstCounter;\n let value;\n try {\n value = this.parseFinderValue(counters, RSSExpandedReader.FINDER_PATTERNS);\n }\n catch (e) {\n return null;\n }\n // return new FinderPattern(value, new int[] { start, end }, start, end, rowNumber});\n return new FinderPattern(value, [start, end], start, end, rowNumber);\n }\n decodeDataCharacter(row, pattern, isOddPattern, leftChar) {\n let counters = this.getDataCharacterCounters();\n for (let x = 0; x < counters.length; x++) {\n counters[x] = 0;\n }\n if (leftChar) {\n RSSExpandedReader.recordPatternInReverse(row, pattern.getStartEnd()[0], counters);\n }\n else {\n RSSExpandedReader.recordPattern(row, pattern.getStartEnd()[1], counters);\n // reverse it\n for (let i = 0, j = counters.length - 1; i < j; i++, j--) {\n let temp = counters[i];\n counters[i] = counters[j];\n counters[j] = temp;\n }\n } // counters[] has the pixels of the module\n let numModules = 17; // left and right data characters have all the same length\n let elementWidth = MathUtils.sum(new Int32Array(counters)) / numModules;\n // Sanity check: element width for pattern and the character should match\n let expectedElementWidth = (pattern.getStartEnd()[1] - pattern.getStartEnd()[0]) / 15.0;\n if (Math.abs(elementWidth - expectedElementWidth) / expectedElementWidth > 0.3) {\n throw new NotFoundException();\n }\n let oddCounts = this.getOddCounts();\n let evenCounts = this.getEvenCounts();\n let oddRoundingErrors = this.getOddRoundingErrors();\n let evenRoundingErrors = this.getEvenRoundingErrors();\n for (let i = 0; i < counters.length; i++) {\n let value = 1.0 * counters[i] / elementWidth;\n let count = value + 0.5; // Round\n if (count < 1) {\n if (value < 0.3) {\n throw new NotFoundException();\n }\n count = 1;\n }\n else if (count > 8) {\n if (value > 8.7) {\n throw new NotFoundException();\n }\n count = 8;\n }\n let offset = i / 2;\n if ((i & 0x01) == 0) {\n oddCounts[offset] = count;\n oddRoundingErrors[offset] = value - count;\n }\n else {\n evenCounts[offset] = count;\n evenRoundingErrors[offset] = value - count;\n }\n }\n this.adjustOddEvenCounts(numModules);\n let weightRowNumber = 4 * pattern.getValue() + (isOddPattern ? 0 : 2) + (leftChar ? 0 : 1) - 1;\n let oddSum = 0;\n let oddChecksumPortion = 0;\n for (let i = oddCounts.length - 1; i >= 0; i--) {\n if (RSSExpandedReader.isNotA1left(pattern, isOddPattern, leftChar)) {\n let weight = RSSExpandedReader.WEIGHTS[weightRowNumber][2 * i];\n oddChecksumPortion += oddCounts[i] * weight;\n }\n oddSum += oddCounts[i];\n }\n let evenChecksumPortion = 0;\n // int evenSum = 0;\n for (let i = evenCounts.length - 1; i >= 0; i--) {\n if (RSSExpandedReader.isNotA1left(pattern, isOddPattern, leftChar)) {\n let weight = RSSExpandedReader.WEIGHTS[weightRowNumber][2 * i + 1];\n evenChecksumPortion += evenCounts[i] * weight;\n }\n // evenSum += evenCounts[i];\n }\n let checksumPortion = oddChecksumPortion + evenChecksumPortion;\n if ((oddSum & 0x01) != 0 || oddSum > 13 || oddSum < 4) {\n throw new NotFoundException();\n }\n let group = (13 - oddSum) / 2;\n let oddWidest = RSSExpandedReader.SYMBOL_WIDEST[group];\n let evenWidest = 9 - oddWidest;\n let vOdd = RSSUtils.getRSSvalue(oddCounts, oddWidest, true);\n let vEven = RSSUtils.getRSSvalue(evenCounts, evenWidest, false);\n let tEven = RSSExpandedReader.EVEN_TOTAL_SUBSET[group];\n let gSum = RSSExpandedReader.GSUM[group];\n let value = vOdd * tEven + vEven + gSum;\n return new DataCharacter(value, checksumPortion);\n }\n static isNotA1left(pattern, isOddPattern, leftChar) {\n // A1: pattern.getValue is 0 (A), and it's an oddPattern, and it is a left char\n return !(pattern.getValue() == 0 && isOddPattern && leftChar);\n }\n adjustOddEvenCounts(numModules) {\n let oddSum = MathUtils.sum(new Int32Array(this.getOddCounts()));\n let evenSum = MathUtils.sum(new Int32Array(this.getEvenCounts()));\n let incrementOdd = false;\n let decrementOdd = false;\n if (oddSum > 13) {\n decrementOdd = true;\n }\n else if (oddSum < 4) {\n incrementOdd = true;\n }\n let incrementEven = false;\n let decrementEven = false;\n if (evenSum > 13) {\n decrementEven = true;\n }\n else if (evenSum < 4) {\n incrementEven = true;\n }\n let mismatch = oddSum + evenSum - numModules;\n let oddParityBad = (oddSum & 0x01) == 1;\n let evenParityBad = (evenSum & 0x01) == 0;\n if (mismatch == 1) {\n if (oddParityBad) {\n if (evenParityBad) {\n throw new NotFoundException();\n }\n decrementOdd = true;\n }\n else {\n if (!evenParityBad) {\n throw new NotFoundException();\n }\n decrementEven = true;\n }\n }\n else if (mismatch == -1) {\n if (oddParityBad) {\n if (evenParityBad) {\n throw new NotFoundException();\n }\n incrementOdd = true;\n }\n else {\n if (!evenParityBad) {\n throw new NotFoundException();\n }\n incrementEven = true;\n }\n }\n else if (mismatch == 0) {\n if (oddParityBad) {\n if (!evenParityBad) {\n throw new NotFoundException();\n }\n // Both bad\n if (oddSum < evenSum) {\n incrementOdd = true;\n decrementEven = true;\n }\n else {\n decrementOdd = true;\n incrementEven = true;\n }\n }\n else {\n if (evenParityBad) {\n throw new NotFoundException();\n }\n // Nothing to do!\n }\n }\n else {\n throw new NotFoundException();\n }\n if (incrementOdd) {\n if (decrementOdd) {\n throw new NotFoundException();\n }\n RSSExpandedReader.increment(this.getOddCounts(), this.getOddRoundingErrors());\n }\n if (decrementOdd) {\n RSSExpandedReader.decrement(this.getOddCounts(), this.getOddRoundingErrors());\n }\n if (incrementEven) {\n if (decrementEven) {\n throw new NotFoundException();\n }\n RSSExpandedReader.increment(this.getEvenCounts(), this.getOddRoundingErrors());\n }\n if (decrementEven) {\n RSSExpandedReader.decrement(this.getEvenCounts(), this.getEvenRoundingErrors());\n }\n }\n }\n RSSExpandedReader.SYMBOL_WIDEST = [7, 5, 4, 3, 1];\n RSSExpandedReader.EVEN_TOTAL_SUBSET = [4, 20, 52, 104, 204];\n RSSExpandedReader.GSUM = [0, 348, 1388, 2948, 3988];\n RSSExpandedReader.FINDER_PATTERNS = [\n Int32Array.from([1, 8, 4, 1]),\n Int32Array.from([3, 6, 4, 1]),\n Int32Array.from([3, 4, 6, 1]),\n Int32Array.from([3, 2, 8, 1]),\n Int32Array.from([2, 6, 5, 1]),\n Int32Array.from([2, 2, 9, 1]) // F\n ];\n RSSExpandedReader.WEIGHTS = [\n [1, 3, 9, 27, 81, 32, 96, 77],\n [20, 60, 180, 118, 143, 7, 21, 63],\n [189, 145, 13, 39, 117, 140, 209, 205],\n [193, 157, 49, 147, 19, 57, 171, 91],\n [62, 186, 136, 197, 169, 85, 44, 132],\n [185, 133, 188, 142, 4, 12, 36, 108],\n [113, 128, 173, 97, 80, 29, 87, 50],\n [150, 28, 84, 41, 123, 158, 52, 156],\n [46, 138, 203, 187, 139, 206, 196, 166],\n [76, 17, 51, 153, 37, 111, 122, 155],\n [43, 129, 176, 106, 107, 110, 119, 146],\n [16, 48, 144, 10, 30, 90, 59, 177],\n [109, 116, 137, 200, 178, 112, 125, 164],\n [70, 210, 208, 202, 184, 130, 179, 115],\n [134, 191, 151, 31, 93, 68, 204, 190],\n [148, 22, 66, 198, 172, 94, 71, 2],\n [6, 18, 54, 162, 64, 192, 154, 40],\n [120, 149, 25, 75, 14, 42, 126, 167],\n [79, 26, 78, 23, 69, 207, 199, 175],\n [103, 98, 83, 38, 114, 131, 182, 124],\n [161, 61, 183, 127, 170, 88, 53, 159],\n [55, 165, 73, 8, 24, 72, 5, 15],\n [45, 135, 194, 160, 58, 174, 100, 89]\n ];\n RSSExpandedReader.FINDER_PAT_A = 0;\n RSSExpandedReader.FINDER_PAT_B = 1;\n RSSExpandedReader.FINDER_PAT_C = 2;\n RSSExpandedReader.FINDER_PAT_D = 3;\n RSSExpandedReader.FINDER_PAT_E = 4;\n RSSExpandedReader.FINDER_PAT_F = 5;\n RSSExpandedReader.FINDER_PATTERN_SEQUENCES = [\n [RSSExpandedReader.FINDER_PAT_A, RSSExpandedReader.FINDER_PAT_A],\n [RSSExpandedReader.FINDER_PAT_A, RSSExpandedReader.FINDER_PAT_B, RSSExpandedReader.FINDER_PAT_B],\n [RSSExpandedReader.FINDER_PAT_A, RSSExpandedReader.FINDER_PAT_C, RSSExpandedReader.FINDER_PAT_B, RSSExpandedReader.FINDER_PAT_D],\n [RSSExpandedReader.FINDER_PAT_A, RSSExpandedReader.FINDER_PAT_E, RSSExpandedReader.FINDER_PAT_B, RSSExpandedReader.FINDER_PAT_D, RSSExpandedReader.FINDER_PAT_C],\n [RSSExpandedReader.FINDER_PAT_A, RSSExpandedReader.FINDER_PAT_E, RSSExpandedReader.FINDER_PAT_B, RSSExpandedReader.FINDER_PAT_D, RSSExpandedReader.FINDER_PAT_D, RSSExpandedReader.FINDER_PAT_F],\n [RSSExpandedReader.FINDER_PAT_A, RSSExpandedReader.FINDER_PAT_E, RSSExpandedReader.FINDER_PAT_B, RSSExpandedReader.FINDER_PAT_D, RSSExpandedReader.FINDER_PAT_E, RSSExpandedReader.FINDER_PAT_F, RSSExpandedReader.FINDER_PAT_F],\n [RSSExpandedReader.FINDER_PAT_A, RSSExpandedReader.FINDER_PAT_A, RSSExpandedReader.FINDER_PAT_B, RSSExpandedReader.FINDER_PAT_B, RSSExpandedReader.FINDER_PAT_C, RSSExpandedReader.FINDER_PAT_C, RSSExpandedReader.FINDER_PAT_D, RSSExpandedReader.FINDER_PAT_D],\n [RSSExpandedReader.FINDER_PAT_A, RSSExpandedReader.FINDER_PAT_A, RSSExpandedReader.FINDER_PAT_B, RSSExpandedReader.FINDER_PAT_B, RSSExpandedReader.FINDER_PAT_C, RSSExpandedReader.FINDER_PAT_C, RSSExpandedReader.FINDER_PAT_D, RSSExpandedReader.FINDER_PAT_E, RSSExpandedReader.FINDER_PAT_E],\n [RSSExpandedReader.FINDER_PAT_A, RSSExpandedReader.FINDER_PAT_A, RSSExpandedReader.FINDER_PAT_B, RSSExpandedReader.FINDER_PAT_B, RSSExpandedReader.FINDER_PAT_C, RSSExpandedReader.FINDER_PAT_C, RSSExpandedReader.FINDER_PAT_D, RSSExpandedReader.FINDER_PAT_E, RSSExpandedReader.FINDER_PAT_F, RSSExpandedReader.FINDER_PAT_F],\n [RSSExpandedReader.FINDER_PAT_A, RSSExpandedReader.FINDER_PAT_A, RSSExpandedReader.FINDER_PAT_B, RSSExpandedReader.FINDER_PAT_B, RSSExpandedReader.FINDER_PAT_C, RSSExpandedReader.FINDER_PAT_D, RSSExpandedReader.FINDER_PAT_D, RSSExpandedReader.FINDER_PAT_E, RSSExpandedReader.FINDER_PAT_E, RSSExpandedReader.FINDER_PAT_F, RSSExpandedReader.FINDER_PAT_F],\n ];\n RSSExpandedReader.MAX_PAIRS = 11;\n\n class Pair extends DataCharacter {\n constructor(value, checksumPortion, finderPattern) {\n super(value, checksumPortion);\n this.count = 0;\n this.finderPattern = finderPattern;\n }\n getFinderPattern() {\n return this.finderPattern;\n }\n getCount() {\n return this.count;\n }\n incrementCount() {\n this.count++;\n }\n }\n\n class RSS14Reader extends AbstractRSSReader {\n constructor() {\n super(...arguments);\n this.possibleLeftPairs = [];\n this.possibleRightPairs = [];\n }\n decodeRow(rowNumber, row, hints) {\n const leftPair = this.decodePair(row, false, rowNumber, hints);\n RSS14Reader.addOrTally(this.possibleLeftPairs, leftPair);\n row.reverse();\n let rightPair = this.decodePair(row, true, rowNumber, hints);\n RSS14Reader.addOrTally(this.possibleRightPairs, rightPair);\n row.reverse();\n for (let left of this.possibleLeftPairs) {\n if (left.getCount() > 1) {\n for (let right of this.possibleRightPairs) {\n if (right.getCount() > 1 && RSS14Reader.checkChecksum(left, right)) {\n return RSS14Reader.constructResult(left, right);\n }\n }\n }\n }\n throw new NotFoundException();\n }\n static addOrTally(possiblePairs, pair) {\n if (pair == null) {\n return;\n }\n let found = false;\n for (let other of possiblePairs) {\n if (other.getValue() === pair.getValue()) {\n other.incrementCount();\n found = true;\n break;\n }\n }\n if (!found) {\n possiblePairs.push(pair);\n }\n }\n reset() {\n this.possibleLeftPairs.length = 0;\n this.possibleRightPairs.length = 0;\n }\n static constructResult(leftPair, rightPair) {\n let symbolValue = 4537077 * leftPair.getValue() + rightPair.getValue();\n let text = new String(symbolValue).toString();\n let buffer = new StringBuilder();\n for (let i = 13 - text.length; i > 0; i--) {\n buffer.append('0');\n }\n buffer.append(text);\n let checkDigit = 0;\n for (let i = 0; i < 13; i++) {\n let digit = buffer.charAt(i).charCodeAt(0) - '0'.charCodeAt(0);\n checkDigit += ((i & 0x01) === 0) ? 3 * digit : digit;\n }\n checkDigit = 10 - (checkDigit % 10);\n if (checkDigit === 10) {\n checkDigit = 0;\n }\n buffer.append(checkDigit.toString());\n let leftPoints = leftPair.getFinderPattern().getResultPoints();\n let rightPoints = rightPair.getFinderPattern().getResultPoints();\n return new Result(buffer.toString(), null, 0, [leftPoints[0], leftPoints[1], rightPoints[0], rightPoints[1]], BarcodeFormat$1.RSS_14, new Date().getTime());\n }\n static checkChecksum(leftPair, rightPair) {\n let checkValue = (leftPair.getChecksumPortion() + 16 * rightPair.getChecksumPortion()) % 79;\n let targetCheckValue = 9 * leftPair.getFinderPattern().getValue() + rightPair.getFinderPattern().getValue();\n if (targetCheckValue > 72) {\n targetCheckValue--;\n }\n if (targetCheckValue > 8) {\n targetCheckValue--;\n }\n return checkValue === targetCheckValue;\n }\n decodePair(row, right, rowNumber, hints) {\n try {\n let startEnd = this.findFinderPattern(row, right);\n let pattern = this.parseFoundFinderPattern(row, rowNumber, right, startEnd);\n let resultPointCallback = hints == null ? null : hints.get(DecodeHintType$1.NEED_RESULT_POINT_CALLBACK);\n if (resultPointCallback != null) {\n let center = (startEnd[0] + startEnd[1]) / 2.0;\n if (right) {\n // row is actually reversed\n center = row.getSize() - 1 - center;\n }\n resultPointCallback.foundPossibleResultPoint(new ResultPoint(center, rowNumber));\n }\n let outside = this.decodeDataCharacter(row, pattern, true);\n let inside = this.decodeDataCharacter(row, pattern, false);\n return new Pair(1597 * outside.getValue() + inside.getValue(), outside.getChecksumPortion() + 4 * inside.getChecksumPortion(), pattern);\n }\n catch (err) {\n return null;\n }\n }\n decodeDataCharacter(row, pattern, outsideChar) {\n let counters = this.getDataCharacterCounters();\n for (let x = 0; x < counters.length; x++) {\n counters[x] = 0;\n }\n if (outsideChar) {\n OneDReader.recordPatternInReverse(row, pattern.getStartEnd()[0], counters);\n }\n else {\n OneDReader.recordPattern(row, pattern.getStartEnd()[1] + 1, counters);\n // reverse it\n for (let i = 0, j = counters.length - 1; i < j; i++, j--) {\n let temp = counters[i];\n counters[i] = counters[j];\n counters[j] = temp;\n }\n }\n let numModules = outsideChar ? 16 : 15;\n let elementWidth = MathUtils.sum(new Int32Array(counters)) / numModules;\n let oddCounts = this.getOddCounts();\n let evenCounts = this.getEvenCounts();\n let oddRoundingErrors = this.getOddRoundingErrors();\n let evenRoundingErrors = this.getEvenRoundingErrors();\n for (let i = 0; i < counters.length; i++) {\n let value = counters[i] / elementWidth;\n let count = Math.floor(value + 0.5);\n if (count < 1) {\n count = 1;\n }\n else if (count > 8) {\n count = 8;\n }\n let offset = Math.floor(i / 2);\n if ((i & 0x01) === 0) {\n oddCounts[offset] = count;\n oddRoundingErrors[offset] = value - count;\n }\n else {\n evenCounts[offset] = count;\n evenRoundingErrors[offset] = value - count;\n }\n }\n this.adjustOddEvenCounts(outsideChar, numModules);\n let oddSum = 0;\n let oddChecksumPortion = 0;\n for (let i = oddCounts.length - 1; i >= 0; i--) {\n oddChecksumPortion *= 9;\n oddChecksumPortion += oddCounts[i];\n oddSum += oddCounts[i];\n }\n let evenChecksumPortion = 0;\n let evenSum = 0;\n for (let i = evenCounts.length - 1; i >= 0; i--) {\n evenChecksumPortion *= 9;\n evenChecksumPortion += evenCounts[i];\n evenSum += evenCounts[i];\n }\n let checksumPortion = oddChecksumPortion + 3 * evenChecksumPortion;\n if (outsideChar) {\n if ((oddSum & 0x01) !== 0 || oddSum > 12 || oddSum < 4) {\n throw new NotFoundException();\n }\n let group = (12 - oddSum) / 2;\n let oddWidest = RSS14Reader.OUTSIDE_ODD_WIDEST[group];\n let evenWidest = 9 - oddWidest;\n let vOdd = RSSUtils.getRSSvalue(oddCounts, oddWidest, false);\n let vEven = RSSUtils.getRSSvalue(evenCounts, evenWidest, true);\n let tEven = RSS14Reader.OUTSIDE_EVEN_TOTAL_SUBSET[group];\n let gSum = RSS14Reader.OUTSIDE_GSUM[group];\n return new DataCharacter(vOdd * tEven + vEven + gSum, checksumPortion);\n }\n else {\n if ((evenSum & 0x01) !== 0 || evenSum > 10 || evenSum < 4) {\n throw new NotFoundException();\n }\n let group = (10 - evenSum) / 2;\n let oddWidest = RSS14Reader.INSIDE_ODD_WIDEST[group];\n let evenWidest = 9 - oddWidest;\n let vOdd = RSSUtils.getRSSvalue(oddCounts, oddWidest, true);\n let vEven = RSSUtils.getRSSvalue(evenCounts, evenWidest, false);\n let tOdd = RSS14Reader.INSIDE_ODD_TOTAL_SUBSET[group];\n let gSum = RSS14Reader.INSIDE_GSUM[group];\n return new DataCharacter(vEven * tOdd + vOdd + gSum, checksumPortion);\n }\n }\n findFinderPattern(row, rightFinderPattern) {\n let counters = this.getDecodeFinderCounters();\n counters[0] = 0;\n counters[1] = 0;\n counters[2] = 0;\n counters[3] = 0;\n let width = row.getSize();\n let isWhite = false;\n let rowOffset = 0;\n while (rowOffset < width) {\n isWhite = !row.get(rowOffset);\n if (rightFinderPattern === isWhite) {\n // Will encounter white first when searching for right finder pattern\n break;\n }\n rowOffset++;\n }\n let counterPosition = 0;\n let patternStart = rowOffset;\n for (let x = rowOffset; x < width; x++) {\n if (row.get(x) !== isWhite) {\n counters[counterPosition]++;\n }\n else {\n if (counterPosition === 3) {\n if (AbstractRSSReader.isFinderPattern(counters)) {\n return [patternStart, x];\n }\n patternStart += counters[0] + counters[1];\n counters[0] = counters[2];\n counters[1] = counters[3];\n counters[2] = 0;\n counters[3] = 0;\n counterPosition--;\n }\n else {\n counterPosition++;\n }\n counters[counterPosition] = 1;\n isWhite = !isWhite;\n }\n }\n throw new NotFoundException();\n }\n parseFoundFinderPattern(row, rowNumber, right, startEnd) {\n // Actually we found elements 2-5\n let firstIsBlack = row.get(startEnd[0]);\n let firstElementStart = startEnd[0] - 1;\n // Locate element 1\n while (firstElementStart >= 0 && firstIsBlack !== row.get(firstElementStart)) {\n firstElementStart--;\n }\n firstElementStart++;\n const firstCounter = startEnd[0] - firstElementStart;\n // Make 'counters' hold 1-4\n const counters = this.getDecodeFinderCounters();\n const copy = new Int32Array(counters.length);\n System.arraycopy(counters, 0, copy, 1, counters.length - 1);\n copy[0] = firstCounter;\n const value = this.parseFinderValue(copy, RSS14Reader.FINDER_PATTERNS);\n let start = firstElementStart;\n let end = startEnd[1];\n if (right) {\n // row is actually reversed\n start = row.getSize() - 1 - start;\n end = row.getSize() - 1 - end;\n }\n return new FinderPattern(value, [firstElementStart, startEnd[1]], start, end, rowNumber);\n }\n adjustOddEvenCounts(outsideChar, numModules) {\n let oddSum = MathUtils.sum(new Int32Array(this.getOddCounts()));\n let evenSum = MathUtils.sum(new Int32Array(this.getEvenCounts()));\n let incrementOdd = false;\n let decrementOdd = false;\n let incrementEven = false;\n let decrementEven = false;\n if (outsideChar) {\n if (oddSum > 12) {\n decrementOdd = true;\n }\n else if (oddSum < 4) {\n incrementOdd = true;\n }\n if (evenSum > 12) {\n decrementEven = true;\n }\n else if (evenSum < 4) {\n incrementEven = true;\n }\n }\n else {\n if (oddSum > 11) {\n decrementOdd = true;\n }\n else if (oddSum < 5) {\n incrementOdd = true;\n }\n if (evenSum > 10) {\n decrementEven = true;\n }\n else if (evenSum < 4) {\n incrementEven = true;\n }\n }\n let mismatch = oddSum + evenSum - numModules;\n let oddParityBad = (oddSum & 0x01) === (outsideChar ? 1 : 0);\n let evenParityBad = (evenSum & 0x01) === 1;\n if (mismatch === 1) {\n if (oddParityBad) {\n if (evenParityBad) {\n throw new NotFoundException();\n }\n decrementOdd = true;\n }\n else {\n if (!evenParityBad) {\n throw new NotFoundException();\n }\n decrementEven = true;\n }\n }\n else if (mismatch === -1) {\n if (oddParityBad) {\n if (evenParityBad) {\n throw new NotFoundException();\n }\n incrementOdd = true;\n }\n else {\n if (!evenParityBad) {\n throw new NotFoundException();\n }\n incrementEven = true;\n }\n }\n else if (mismatch === 0) {\n if (oddParityBad) {\n if (!evenParityBad) {\n throw new NotFoundException();\n }\n // Both bad\n if (oddSum < evenSum) {\n incrementOdd = true;\n decrementEven = true;\n }\n else {\n decrementOdd = true;\n incrementEven = true;\n }\n }\n else {\n if (evenParityBad) {\n throw new NotFoundException();\n }\n // Nothing to do!\n }\n }\n else {\n throw new NotFoundException();\n }\n if (incrementOdd) {\n if (decrementOdd) {\n throw new NotFoundException();\n }\n AbstractRSSReader.increment(this.getOddCounts(), this.getOddRoundingErrors());\n }\n if (decrementOdd) {\n AbstractRSSReader.decrement(this.getOddCounts(), this.getOddRoundingErrors());\n }\n if (incrementEven) {\n if (decrementEven) {\n throw new NotFoundException();\n }\n AbstractRSSReader.increment(this.getEvenCounts(), this.getOddRoundingErrors());\n }\n if (decrementEven) {\n AbstractRSSReader.decrement(this.getEvenCounts(), this.getEvenRoundingErrors());\n }\n }\n }\n RSS14Reader.OUTSIDE_EVEN_TOTAL_SUBSET = [1, 10, 34, 70, 126];\n RSS14Reader.INSIDE_ODD_TOTAL_SUBSET = [4, 20, 48, 81];\n RSS14Reader.OUTSIDE_GSUM = [0, 161, 961, 2015, 2715];\n RSS14Reader.INSIDE_GSUM = [0, 336, 1036, 1516];\n RSS14Reader.OUTSIDE_ODD_WIDEST = [8, 6, 4, 3, 1];\n RSS14Reader.INSIDE_ODD_WIDEST = [2, 4, 6, 8];\n RSS14Reader.FINDER_PATTERNS = [\n Int32Array.from([3, 8, 2, 1]),\n Int32Array.from([3, 5, 5, 1]),\n Int32Array.from([3, 3, 7, 1]),\n Int32Array.from([3, 1, 9, 1]),\n Int32Array.from([2, 7, 4, 1]),\n Int32Array.from([2, 5, 6, 1]),\n Int32Array.from([2, 3, 8, 1]),\n Int32Array.from([1, 5, 7, 1]),\n Int32Array.from([1, 3, 9, 1]),\n ];\n\n /**\n * @author Daniel Switkin \n * @author Sean Owen\n */\n class MultiFormatOneDReader extends OneDReader {\n constructor(hints, verbose) {\n super();\n this.readers = [];\n this.verbose = (verbose === true);\n const possibleFormats = !hints ? null : hints.get(DecodeHintType$1.POSSIBLE_FORMATS);\n const useCode39CheckDigit = hints && hints.get(DecodeHintType$1.ASSUME_CODE_39_CHECK_DIGIT) !== undefined;\n if (possibleFormats) {\n if (possibleFormats.includes(BarcodeFormat$1.EAN_13) ||\n possibleFormats.includes(BarcodeFormat$1.UPC_A) ||\n possibleFormats.includes(BarcodeFormat$1.EAN_8) ||\n possibleFormats.includes(BarcodeFormat$1.UPC_E)) {\n this.readers.push(new MultiFormatUPCEANReader(hints));\n }\n if (possibleFormats.includes(BarcodeFormat$1.CODE_39)) {\n this.readers.push(new Code39Reader(useCode39CheckDigit));\n }\n // if (possibleFormats.includes(BarcodeFormat.CODE_93)) {\n // this.readers.push(new Code93Reader());\n // }\n if (possibleFormats.includes(BarcodeFormat$1.CODE_128)) {\n this.readers.push(new Code128Reader());\n }\n if (possibleFormats.includes(BarcodeFormat$1.ITF)) {\n this.readers.push(new ITFReader());\n }\n // if (possibleFormats.includes(BarcodeFormat.CODABAR)) {\n // this.readers.push(new CodaBarReader());\n // }\n if (possibleFormats.includes(BarcodeFormat$1.RSS_14)) {\n this.readers.push(new RSS14Reader());\n }\n if (possibleFormats.includes(BarcodeFormat$1.RSS_EXPANDED)) {\n this.readers.push(new RSSExpandedReader(this.verbose));\n }\n } else {\n // Case when no hints were provided -> add all.\n this.readers.push(new MultiFormatUPCEANReader(hints));\n this.readers.push(new Code39Reader());\n // this.readers.push(new CodaBarReader());\n // this.readers.push(new Code93Reader());\n this.readers.push(new MultiFormatUPCEANReader(hints));\n this.readers.push(new Code128Reader());\n this.readers.push(new ITFReader());\n this.readers.push(new RSS14Reader());\n this.readers.push(new RSSExpandedReader(this.verbose));\n }\n }\n // @Override\n decodeRow(rowNumber, row, hints) {\n for (let i = 0; i < this.readers.length; i++) {\n try {\n return this.readers[i].decodeRow(rowNumber, row, hints);\n }\n catch (re) {\n // continue\n }\n }\n throw new NotFoundException();\n }\n // @Override\n reset() {\n this.readers.forEach(reader => reader.reset());\n }\n }\n\n /**\n * @deprecated Moving to @zxing/browser\n *\n * Barcode reader reader to use from browser.\n */\n class BrowserBarcodeReader extends BrowserCodeReader {\n /**\n * Creates an instance of BrowserBarcodeReader.\n * @param {number} [timeBetweenScansMillis=500] the time delay between subsequent decode tries\n * @param {Map} hints\n */\n constructor(timeBetweenScansMillis = 500, hints) {\n super(new MultiFormatOneDReader(hints), timeBetweenScansMillis, hints);\n }\n }\n\n /*\n * Copyright 2007 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n /**\n *

Encapsulates a set of error-correction blocks in one symbol version. Most versions will\n * use blocks of differing sizes within one version, so, this encapsulates the parameters for\n * each set of blocks. It also holds the number of error-correction codewords per block since it\n * will be the same across all blocks within one version.

\n */\n class ECBlocks {\n constructor(ecCodewords, ecBlocks1, ecBlocks2) {\n this.ecCodewords = ecCodewords;\n this.ecBlocks = [ecBlocks1];\n ecBlocks2 && this.ecBlocks.push(ecBlocks2);\n }\n getECCodewords() {\n return this.ecCodewords;\n }\n getECBlocks() {\n return this.ecBlocks;\n }\n }\n /**\n *

Encapsulates the parameters for one error-correction block in one symbol version.\n * This includes the number of data codewords, and the number of times a block with these\n * parameters is used consecutively in the Data Matrix code version's format.

\n */\n class ECB {\n constructor(count, dataCodewords) {\n this.count = count;\n this.dataCodewords = dataCodewords;\n }\n getCount() {\n return this.count;\n }\n getDataCodewords() {\n return this.dataCodewords;\n }\n }\n /**\n * The Version object encapsulates attributes about a particular\n * size Data Matrix Code.\n *\n * @author bbrown@google.com (Brian Brown)\n */\n class Version {\n constructor(versionNumber, symbolSizeRows, symbolSizeColumns, dataRegionSizeRows, dataRegionSizeColumns, ecBlocks) {\n this.versionNumber = versionNumber;\n this.symbolSizeRows = symbolSizeRows;\n this.symbolSizeColumns = symbolSizeColumns;\n this.dataRegionSizeRows = dataRegionSizeRows;\n this.dataRegionSizeColumns = dataRegionSizeColumns;\n this.ecBlocks = ecBlocks;\n // Calculate the total number of codewords\n let total = 0;\n const ecCodewords = ecBlocks.getECCodewords();\n const ecbArray = ecBlocks.getECBlocks();\n for (let ecBlock of ecbArray) {\n total += ecBlock.getCount() * (ecBlock.getDataCodewords() + ecCodewords);\n }\n this.totalCodewords = total;\n }\n getVersionNumber() {\n return this.versionNumber;\n }\n getSymbolSizeRows() {\n return this.symbolSizeRows;\n }\n getSymbolSizeColumns() {\n return this.symbolSizeColumns;\n }\n getDataRegionSizeRows() {\n return this.dataRegionSizeRows;\n }\n getDataRegionSizeColumns() {\n return this.dataRegionSizeColumns;\n }\n getTotalCodewords() {\n return this.totalCodewords;\n }\n getECBlocks() {\n return this.ecBlocks;\n }\n /**\n *

Deduces version information from Data Matrix dimensions.

\n *\n * @param numRows Number of rows in modules\n * @param numColumns Number of columns in modules\n * @return Version for a Data Matrix Code of those dimensions\n * @throws FormatException if dimensions do correspond to a valid Data Matrix size\n */\n static getVersionForDimensions(numRows, numColumns) {\n if ((numRows & 0x01) !== 0 || (numColumns & 0x01) !== 0) {\n throw new FormatException();\n }\n for (let version of Version.VERSIONS) {\n if (version.symbolSizeRows === numRows && version.symbolSizeColumns === numColumns) {\n return version;\n }\n }\n throw new FormatException();\n }\n // @Override\n toString() {\n return '' + this.versionNumber;\n }\n /**\n * See ISO 16022:2006 5.5.1 Table 7\n */\n static buildVersions() {\n return [\n new Version(1, 10, 10, 8, 8, new ECBlocks(5, new ECB(1, 3))),\n new Version(2, 12, 12, 10, 10, new ECBlocks(7, new ECB(1, 5))),\n new Version(3, 14, 14, 12, 12, new ECBlocks(10, new ECB(1, 8))),\n new Version(4, 16, 16, 14, 14, new ECBlocks(12, new ECB(1, 12))),\n new Version(5, 18, 18, 16, 16, new ECBlocks(14, new ECB(1, 18))),\n new Version(6, 20, 20, 18, 18, new ECBlocks(18, new ECB(1, 22))),\n new Version(7, 22, 22, 20, 20, new ECBlocks(20, new ECB(1, 30))),\n new Version(8, 24, 24, 22, 22, new ECBlocks(24, new ECB(1, 36))),\n new Version(9, 26, 26, 24, 24, new ECBlocks(28, new ECB(1, 44))),\n new Version(10, 32, 32, 14, 14, new ECBlocks(36, new ECB(1, 62))),\n new Version(11, 36, 36, 16, 16, new ECBlocks(42, new ECB(1, 86))),\n new Version(12, 40, 40, 18, 18, new ECBlocks(48, new ECB(1, 114))),\n new Version(13, 44, 44, 20, 20, new ECBlocks(56, new ECB(1, 144))),\n new Version(14, 48, 48, 22, 22, new ECBlocks(68, new ECB(1, 174))),\n new Version(15, 52, 52, 24, 24, new ECBlocks(42, new ECB(2, 102))),\n new Version(16, 64, 64, 14, 14, new ECBlocks(56, new ECB(2, 140))),\n new Version(17, 72, 72, 16, 16, new ECBlocks(36, new ECB(4, 92))),\n new Version(18, 80, 80, 18, 18, new ECBlocks(48, new ECB(4, 114))),\n new Version(19, 88, 88, 20, 20, new ECBlocks(56, new ECB(4, 144))),\n new Version(20, 96, 96, 22, 22, new ECBlocks(68, new ECB(4, 174))),\n new Version(21, 104, 104, 24, 24, new ECBlocks(56, new ECB(6, 136))),\n new Version(22, 120, 120, 18, 18, new ECBlocks(68, new ECB(6, 175))),\n new Version(23, 132, 132, 20, 20, new ECBlocks(62, new ECB(8, 163))),\n new Version(24, 144, 144, 22, 22, new ECBlocks(62, new ECB(8, 156), new ECB(2, 155))),\n new Version(25, 8, 18, 6, 16, new ECBlocks(7, new ECB(1, 5))),\n new Version(26, 8, 32, 6, 14, new ECBlocks(11, new ECB(1, 10))),\n new Version(27, 12, 26, 10, 24, new ECBlocks(14, new ECB(1, 16))),\n new Version(28, 12, 36, 10, 16, new ECBlocks(18, new ECB(1, 22))),\n new Version(29, 16, 36, 14, 16, new ECBlocks(24, new ECB(1, 32))),\n new Version(30, 16, 48, 14, 22, new ECBlocks(28, new ECB(1, 49)))\n ];\n }\n }\n Version.VERSIONS = Version.buildVersions();\n\n /*\n * Copyright 2007 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n /**\n * @author bbrown@google.com (Brian Brown)\n */\n class BitMatrixParser {\n /**\n * @param bitMatrix {@link BitMatrix} to parse\n * @throws FormatException if dimension is < 8 or > 144 or not 0 mod 2\n */\n constructor(bitMatrix) {\n const dimension = bitMatrix.getHeight();\n if (dimension < 8 || dimension > 144 || (dimension & 0x01) !== 0) {\n throw new FormatException();\n }\n this.version = BitMatrixParser.readVersion(bitMatrix);\n this.mappingBitMatrix = this.extractDataRegion(bitMatrix);\n this.readMappingMatrix = new BitMatrix(this.mappingBitMatrix.getWidth(), this.mappingBitMatrix.getHeight());\n }\n getVersion() {\n return this.version;\n }\n /**\n *

Creates the version object based on the dimension of the original bit matrix from\n * the datamatrix code.

\n *\n *

See ISO 16022:2006 Table 7 - ECC 200 symbol attributes

\n *\n * @param bitMatrix Original {@link BitMatrix} including alignment patterns\n * @return {@link Version} encapsulating the Data Matrix Code's \"version\"\n * @throws FormatException if the dimensions of the mapping matrix are not valid\n * Data Matrix dimensions.\n */\n static readVersion(bitMatrix) {\n const numRows = bitMatrix.getHeight();\n const numColumns = bitMatrix.getWidth();\n return Version.getVersionForDimensions(numRows, numColumns);\n }\n /**\n *

Reads the bits in the {@link BitMatrix} representing the mapping matrix (No alignment patterns)\n * in the correct order in order to reconstitute the codewords bytes contained within the\n * Data Matrix Code.

\n *\n * @return bytes encoded within the Data Matrix Code\n * @throws FormatException if the exact number of bytes expected is not read\n */\n readCodewords() {\n const result = new Int8Array(this.version.getTotalCodewords());\n let resultOffset = 0;\n let row = 4;\n let column = 0;\n const numRows = this.mappingBitMatrix.getHeight();\n const numColumns = this.mappingBitMatrix.getWidth();\n let corner1Read = false;\n let corner2Read = false;\n let corner3Read = false;\n let corner4Read = false;\n // Read all of the codewords\n do {\n // Check the four corner cases\n if ((row === numRows) && (column === 0) && !corner1Read) {\n result[resultOffset++] = this.readCorner1(numRows, numColumns) & 0xff;\n row -= 2;\n column += 2;\n corner1Read = true;\n }\n else if ((row === numRows - 2) && (column === 0) && ((numColumns & 0x03) !== 0) && !corner2Read) {\n result[resultOffset++] = this.readCorner2(numRows, numColumns) & 0xff;\n row -= 2;\n column += 2;\n corner2Read = true;\n }\n else if ((row === numRows + 4) && (column === 2) && ((numColumns & 0x07) === 0) && !corner3Read) {\n result[resultOffset++] = this.readCorner3(numRows, numColumns) & 0xff;\n row -= 2;\n column += 2;\n corner3Read = true;\n }\n else if ((row === numRows - 2) && (column === 0) && ((numColumns & 0x07) === 4) && !corner4Read) {\n result[resultOffset++] = this.readCorner4(numRows, numColumns) & 0xff;\n row -= 2;\n column += 2;\n corner4Read = true;\n }\n else {\n // Sweep upward diagonally to the right\n do {\n if ((row < numRows) && (column >= 0) && !this.readMappingMatrix.get(column, row)) {\n result[resultOffset++] = this.readUtah(row, column, numRows, numColumns) & 0xff;\n }\n row -= 2;\n column += 2;\n } while ((row >= 0) && (column < numColumns));\n row += 1;\n column += 3;\n // Sweep downward diagonally to the left\n do {\n if ((row >= 0) && (column < numColumns) && !this.readMappingMatrix.get(column, row)) {\n result[resultOffset++] = this.readUtah(row, column, numRows, numColumns) & 0xff;\n }\n row += 2;\n column -= 2;\n } while ((row < numRows) && (column >= 0));\n row += 3;\n column += 1;\n }\n } while ((row < numRows) || (column < numColumns));\n if (resultOffset !== this.version.getTotalCodewords()) {\n throw new FormatException();\n }\n return result;\n }\n /**\n *

Reads a bit of the mapping matrix accounting for boundary wrapping.

\n *\n * @param row Row to read in the mapping matrix\n * @param column Column to read in the mapping matrix\n * @param numRows Number of rows in the mapping matrix\n * @param numColumns Number of columns in the mapping matrix\n * @return value of the given bit in the mapping matrix\n */\n readModule(row, column, numRows, numColumns) {\n // Adjust the row and column indices based on boundary wrapping\n if (row < 0) {\n row += numRows;\n column += 4 - ((numRows + 4) & 0x07);\n }\n if (column < 0) {\n column += numColumns;\n row += 4 - ((numColumns + 4) & 0x07);\n }\n this.readMappingMatrix.set(column, row);\n return this.mappingBitMatrix.get(column, row);\n }\n /**\n *

Reads the 8 bits of the standard Utah-shaped pattern.

\n *\n *

See ISO 16022:2006, 5.8.1 Figure 6

\n *\n * @param row Current row in the mapping matrix, anchored at the 8th bit (LSB) of the pattern\n * @param column Current column in the mapping matrix, anchored at the 8th bit (LSB) of the pattern\n * @param numRows Number of rows in the mapping matrix\n * @param numColumns Number of columns in the mapping matrix\n * @return byte from the utah shape\n */\n readUtah(row, column, numRows, numColumns) {\n let currentByte = 0;\n if (this.readModule(row - 2, column - 2, numRows, numColumns)) {\n currentByte |= 1;\n }\n currentByte <<= 1;\n if (this.readModule(row - 2, column - 1, numRows, numColumns)) {\n currentByte |= 1;\n }\n currentByte <<= 1;\n if (this.readModule(row - 1, column - 2, numRows, numColumns)) {\n currentByte |= 1;\n }\n currentByte <<= 1;\n if (this.readModule(row - 1, column - 1, numRows, numColumns)) {\n currentByte |= 1;\n }\n currentByte <<= 1;\n if (this.readModule(row - 1, column, numRows, numColumns)) {\n currentByte |= 1;\n }\n currentByte <<= 1;\n if (this.readModule(row, column - 2, numRows, numColumns)) {\n currentByte |= 1;\n }\n currentByte <<= 1;\n if (this.readModule(row, column - 1, numRows, numColumns)) {\n currentByte |= 1;\n }\n currentByte <<= 1;\n if (this.readModule(row, column, numRows, numColumns)) {\n currentByte |= 1;\n }\n return currentByte;\n }\n /**\n *

Reads the 8 bits of the special corner condition 1.

\n *\n *

See ISO 16022:2006, Figure F.3

\n *\n * @param numRows Number of rows in the mapping matrix\n * @param numColumns Number of columns in the mapping matrix\n * @return byte from the Corner condition 1\n */\n readCorner1(numRows, numColumns) {\n let currentByte = 0;\n if (this.readModule(numRows - 1, 0, numRows, numColumns)) {\n currentByte |= 1;\n }\n currentByte <<= 1;\n if (this.readModule(numRows - 1, 1, numRows, numColumns)) {\n currentByte |= 1;\n }\n currentByte <<= 1;\n if (this.readModule(numRows - 1, 2, numRows, numColumns)) {\n currentByte |= 1;\n }\n currentByte <<= 1;\n if (this.readModule(0, numColumns - 2, numRows, numColumns)) {\n currentByte |= 1;\n }\n currentByte <<= 1;\n if (this.readModule(0, numColumns - 1, numRows, numColumns)) {\n currentByte |= 1;\n }\n currentByte <<= 1;\n if (this.readModule(1, numColumns - 1, numRows, numColumns)) {\n currentByte |= 1;\n }\n currentByte <<= 1;\n if (this.readModule(2, numColumns - 1, numRows, numColumns)) {\n currentByte |= 1;\n }\n currentByte <<= 1;\n if (this.readModule(3, numColumns - 1, numRows, numColumns)) {\n currentByte |= 1;\n }\n return currentByte;\n }\n /**\n *

Reads the 8 bits of the special corner condition 2.

\n *\n *

See ISO 16022:2006, Figure F.4

\n *\n * @param numRows Number of rows in the mapping matrix\n * @param numColumns Number of columns in the mapping matrix\n * @return byte from the Corner condition 2\n */\n readCorner2(numRows, numColumns) {\n let currentByte = 0;\n if (this.readModule(numRows - 3, 0, numRows, numColumns)) {\n currentByte |= 1;\n }\n currentByte <<= 1;\n if (this.readModule(numRows - 2, 0, numRows, numColumns)) {\n currentByte |= 1;\n }\n currentByte <<= 1;\n if (this.readModule(numRows - 1, 0, numRows, numColumns)) {\n currentByte |= 1;\n }\n currentByte <<= 1;\n if (this.readModule(0, numColumns - 4, numRows, numColumns)) {\n currentByte |= 1;\n }\n currentByte <<= 1;\n if (this.readModule(0, numColumns - 3, numRows, numColumns)) {\n currentByte |= 1;\n }\n currentByte <<= 1;\n if (this.readModule(0, numColumns - 2, numRows, numColumns)) {\n currentByte |= 1;\n }\n currentByte <<= 1;\n if (this.readModule(0, numColumns - 1, numRows, numColumns)) {\n currentByte |= 1;\n }\n currentByte <<= 1;\n if (this.readModule(1, numColumns - 1, numRows, numColumns)) {\n currentByte |= 1;\n }\n return currentByte;\n }\n /**\n *

Reads the 8 bits of the special corner condition 3.

\n *\n *

See ISO 16022:2006, Figure F.5

\n *\n * @param numRows Number of rows in the mapping matrix\n * @param numColumns Number of columns in the mapping matrix\n * @return byte from the Corner condition 3\n */\n readCorner3(numRows, numColumns) {\n let currentByte = 0;\n if (this.readModule(numRows - 1, 0, numRows, numColumns)) {\n currentByte |= 1;\n }\n currentByte <<= 1;\n if (this.readModule(numRows - 1, numColumns - 1, numRows, numColumns)) {\n currentByte |= 1;\n }\n currentByte <<= 1;\n if (this.readModule(0, numColumns - 3, numRows, numColumns)) {\n currentByte |= 1;\n }\n currentByte <<= 1;\n if (this.readModule(0, numColumns - 2, numRows, numColumns)) {\n currentByte |= 1;\n }\n currentByte <<= 1;\n if (this.readModule(0, numColumns - 1, numRows, numColumns)) {\n currentByte |= 1;\n }\n currentByte <<= 1;\n if (this.readModule(1, numColumns - 3, numRows, numColumns)) {\n currentByte |= 1;\n }\n currentByte <<= 1;\n if (this.readModule(1, numColumns - 2, numRows, numColumns)) {\n currentByte |= 1;\n }\n currentByte <<= 1;\n if (this.readModule(1, numColumns - 1, numRows, numColumns)) {\n currentByte |= 1;\n }\n return currentByte;\n }\n /**\n *

Reads the 8 bits of the special corner condition 4.

\n *\n *

See ISO 16022:2006, Figure F.6

\n *\n * @param numRows Number of rows in the mapping matrix\n * @param numColumns Number of columns in the mapping matrix\n * @return byte from the Corner condition 4\n */\n readCorner4(numRows, numColumns) {\n let currentByte = 0;\n if (this.readModule(numRows - 3, 0, numRows, numColumns)) {\n currentByte |= 1;\n }\n currentByte <<= 1;\n if (this.readModule(numRows - 2, 0, numRows, numColumns)) {\n currentByte |= 1;\n }\n currentByte <<= 1;\n if (this.readModule(numRows - 1, 0, numRows, numColumns)) {\n currentByte |= 1;\n }\n currentByte <<= 1;\n if (this.readModule(0, numColumns - 2, numRows, numColumns)) {\n currentByte |= 1;\n }\n currentByte <<= 1;\n if (this.readModule(0, numColumns - 1, numRows, numColumns)) {\n currentByte |= 1;\n }\n currentByte <<= 1;\n if (this.readModule(1, numColumns - 1, numRows, numColumns)) {\n currentByte |= 1;\n }\n currentByte <<= 1;\n if (this.readModule(2, numColumns - 1, numRows, numColumns)) {\n currentByte |= 1;\n }\n currentByte <<= 1;\n if (this.readModule(3, numColumns - 1, numRows, numColumns)) {\n currentByte |= 1;\n }\n return currentByte;\n }\n /**\n *

Extracts the data region from a {@link BitMatrix} that contains\n * alignment patterns.

\n *\n * @param bitMatrix Original {@link BitMatrix} with alignment patterns\n * @return BitMatrix that has the alignment patterns removed\n */\n extractDataRegion(bitMatrix) {\n const symbolSizeRows = this.version.getSymbolSizeRows();\n const symbolSizeColumns = this.version.getSymbolSizeColumns();\n if (bitMatrix.getHeight() !== symbolSizeRows) {\n throw new IllegalArgumentException('Dimension of bitMatrix must match the version size');\n }\n const dataRegionSizeRows = this.version.getDataRegionSizeRows();\n const dataRegionSizeColumns = this.version.getDataRegionSizeColumns();\n const numDataRegionsRow = symbolSizeRows / dataRegionSizeRows | 0;\n const numDataRegionsColumn = symbolSizeColumns / dataRegionSizeColumns | 0;\n const sizeDataRegionRow = numDataRegionsRow * dataRegionSizeRows;\n const sizeDataRegionColumn = numDataRegionsColumn * dataRegionSizeColumns;\n const bitMatrixWithoutAlignment = new BitMatrix(sizeDataRegionColumn, sizeDataRegionRow);\n for (let dataRegionRow = 0; dataRegionRow < numDataRegionsRow; ++dataRegionRow) {\n const dataRegionRowOffset = dataRegionRow * dataRegionSizeRows;\n for (let dataRegionColumn = 0; dataRegionColumn < numDataRegionsColumn; ++dataRegionColumn) {\n const dataRegionColumnOffset = dataRegionColumn * dataRegionSizeColumns;\n for (let i = 0; i < dataRegionSizeRows; ++i) {\n const readRowOffset = dataRegionRow * (dataRegionSizeRows + 2) + 1 + i;\n const writeRowOffset = dataRegionRowOffset + i;\n for (let j = 0; j < dataRegionSizeColumns; ++j) {\n const readColumnOffset = dataRegionColumn * (dataRegionSizeColumns + 2) + 1 + j;\n if (bitMatrix.get(readColumnOffset, readRowOffset)) {\n const writeColumnOffset = dataRegionColumnOffset + j;\n bitMatrixWithoutAlignment.set(writeColumnOffset, writeRowOffset);\n }\n }\n }\n }\n }\n return bitMatrixWithoutAlignment;\n }\n }\n\n /**\n *

Encapsulates a block of data within a Data Matrix Code. Data Matrix Codes may split their data into\n * multiple blocks, each of which is a unit of data and error-correction codewords. Each\n * is represented by an instance of this class.

\n *\n * @author bbrown@google.com (Brian Brown)\n */\n class DataBlock {\n constructor(numDataCodewords, codewords) {\n this.numDataCodewords = numDataCodewords;\n this.codewords = codewords;\n }\n /**\n *

When Data Matrix Codes use multiple data blocks, they actually interleave the bytes of each of them.\n * That is, the first byte of data block 1 to n is written, then the second bytes, and so on. This\n * method will separate the data into original blocks.

\n *\n * @param rawCodewords bytes as read directly from the Data Matrix Code\n * @param version version of the Data Matrix Code\n * @return DataBlocks containing original bytes, \"de-interleaved\" from representation in the\n * Data Matrix Code\n */\n static getDataBlocks(rawCodewords, version) {\n // Figure out the number and size of data blocks used by this version\n const ecBlocks = version.getECBlocks();\n // First count the total number of data blocks\n let totalBlocks = 0;\n const ecBlockArray = ecBlocks.getECBlocks();\n for (let ecBlock of ecBlockArray) {\n totalBlocks += ecBlock.getCount();\n }\n // Now establish DataBlocks of the appropriate size and number of data codewords\n const result = new Array(totalBlocks);\n let numResultBlocks = 0;\n for (let ecBlock of ecBlockArray) {\n for (let i = 0; i < ecBlock.getCount(); i++) {\n const numDataCodewords = ecBlock.getDataCodewords();\n const numBlockCodewords = ecBlocks.getECCodewords() + numDataCodewords;\n result[numResultBlocks++] = new DataBlock(numDataCodewords, new Uint8Array(numBlockCodewords));\n }\n }\n // All blocks have the same amount of data, except that the last n\n // (where n may be 0) have 1 less byte. Figure out where these start.\n // TODO(bbrown): There is only one case where there is a difference for Data Matrix for size 144\n const longerBlocksTotalCodewords = result[0].codewords.length;\n // int shorterBlocksTotalCodewords = longerBlocksTotalCodewords - 1;\n const longerBlocksNumDataCodewords = longerBlocksTotalCodewords - ecBlocks.getECCodewords();\n const shorterBlocksNumDataCodewords = longerBlocksNumDataCodewords - 1;\n // The last elements of result may be 1 element shorter for 144 matrix\n // first fill out as many elements as all of them have minus 1\n let rawCodewordsOffset = 0;\n for (let i = 0; i < shorterBlocksNumDataCodewords; i++) {\n for (let j = 0; j < numResultBlocks; j++) {\n result[j].codewords[i] = rawCodewords[rawCodewordsOffset++];\n }\n }\n // Fill out the last data block in the longer ones\n const specialVersion = version.getVersionNumber() === 24;\n const numLongerBlocks = specialVersion ? 8 : numResultBlocks;\n for (let j = 0; j < numLongerBlocks; j++) {\n result[j].codewords[longerBlocksNumDataCodewords - 1] = rawCodewords[rawCodewordsOffset++];\n }\n // Now add in error correction blocks\n const max = result[0].codewords.length;\n for (let i = longerBlocksNumDataCodewords; i < max; i++) {\n for (let j = 0; j < numResultBlocks; j++) {\n const jOffset = specialVersion ? (j + 8) % numResultBlocks : j;\n const iOffset = specialVersion && jOffset > 7 ? i - 1 : i;\n result[jOffset].codewords[iOffset] = rawCodewords[rawCodewordsOffset++];\n }\n }\n if (rawCodewordsOffset !== rawCodewords.length) {\n throw new IllegalArgumentException();\n }\n return result;\n }\n getNumDataCodewords() {\n return this.numDataCodewords;\n }\n getCodewords() {\n return this.codewords;\n }\n }\n\n /*\n * Copyright 2007 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n /**\n *

This provides an easy abstraction to read bits at a time from a sequence of bytes, where the\n * number of bits read is not often a multiple of 8.

\n *\n *

This class is thread-safe but not reentrant -- unless the caller modifies the bytes array\n * it passed in, in which case all bets are off.

\n *\n * @author Sean Owen\n */\n class BitSource {\n /**\n * @param bytes bytes from which this will read bits. Bits will be read from the first byte first.\n * Bits are read within a byte from most-significant to least-significant bit.\n */\n constructor(bytes) {\n this.bytes = bytes;\n this.byteOffset = 0;\n this.bitOffset = 0;\n }\n /**\n * @return index of next bit in current byte which would be read by the next call to {@link #readBits(int)}.\n */\n getBitOffset() {\n return this.bitOffset;\n }\n /**\n * @return index of next byte in input byte array which would be read by the next call to {@link #readBits(int)}.\n */\n getByteOffset() {\n return this.byteOffset;\n }\n /**\n * @param numBits number of bits to read\n * @return int representing the bits read. The bits will appear as the least-significant\n * bits of the int\n * @throws IllegalArgumentException if numBits isn't in [1,32] or more than is available\n */\n readBits(numBits /*int*/) {\n if (numBits < 1 || numBits > 32 || numBits > this.available()) {\n throw new IllegalArgumentException('' + numBits);\n }\n let result = 0;\n let bitOffset = this.bitOffset;\n let byteOffset = this.byteOffset;\n const bytes = this.bytes;\n // First, read remainder from current byte\n if (bitOffset > 0) {\n const bitsLeft = 8 - bitOffset;\n const toRead = numBits < bitsLeft ? numBits : bitsLeft;\n const bitsToNotRead = bitsLeft - toRead;\n const mask = (0xFF >> (8 - toRead)) << bitsToNotRead;\n result = (bytes[byteOffset] & mask) >> bitsToNotRead;\n numBits -= toRead;\n bitOffset += toRead;\n if (bitOffset === 8) {\n bitOffset = 0;\n byteOffset++;\n }\n }\n // Next read whole bytes\n if (numBits > 0) {\n while (numBits >= 8) {\n result = (result << 8) | (bytes[byteOffset] & 0xFF);\n byteOffset++;\n numBits -= 8;\n }\n // Finally read a partial byte\n if (numBits > 0) {\n const bitsToNotRead = 8 - numBits;\n const mask = (0xFF >> bitsToNotRead) << bitsToNotRead;\n result = (result << numBits) | ((bytes[byteOffset] & mask) >> bitsToNotRead);\n bitOffset += numBits;\n }\n }\n this.bitOffset = bitOffset;\n this.byteOffset = byteOffset;\n return result;\n }\n /**\n * @return number of bits that can be read successfully\n */\n available() {\n return 8 * (this.bytes.length - this.byteOffset) - this.bitOffset;\n }\n }\n\n var Mode;\n (function (Mode) {\n Mode[Mode[\"PAD_ENCODE\"] = 0] = \"PAD_ENCODE\";\n Mode[Mode[\"ASCII_ENCODE\"] = 1] = \"ASCII_ENCODE\";\n Mode[Mode[\"C40_ENCODE\"] = 2] = \"C40_ENCODE\";\n Mode[Mode[\"TEXT_ENCODE\"] = 3] = \"TEXT_ENCODE\";\n Mode[Mode[\"ANSIX12_ENCODE\"] = 4] = \"ANSIX12_ENCODE\";\n Mode[Mode[\"EDIFACT_ENCODE\"] = 5] = \"EDIFACT_ENCODE\";\n Mode[Mode[\"BASE256_ENCODE\"] = 6] = \"BASE256_ENCODE\";\n })(Mode || (Mode = {}));\n /**\n *

Data Matrix Codes can encode text as bits in one of several modes, and can use multiple modes\n * in one Data Matrix Code. This class decodes the bits back into text.

\n *\n *

See ISO 16022:2006, 5.2.1 - 5.2.9.2

\n *\n * @author bbrown@google.com (Brian Brown)\n * @author Sean Owen\n */\n class DecodedBitStreamParser {\n static decode(bytes) {\n const bits = new BitSource(bytes);\n const result = new StringBuilder();\n const resultTrailer = new StringBuilder();\n const byteSegments = new Array();\n let mode = Mode.ASCII_ENCODE;\n do {\n if (mode === Mode.ASCII_ENCODE) {\n mode = this.decodeAsciiSegment(bits, result, resultTrailer);\n }\n else {\n switch (mode) {\n case Mode.C40_ENCODE:\n this.decodeC40Segment(bits, result);\n break;\n case Mode.TEXT_ENCODE:\n this.decodeTextSegment(bits, result);\n break;\n case Mode.ANSIX12_ENCODE:\n this.decodeAnsiX12Segment(bits, result);\n break;\n case Mode.EDIFACT_ENCODE:\n this.decodeEdifactSegment(bits, result);\n break;\n case Mode.BASE256_ENCODE:\n this.decodeBase256Segment(bits, result, byteSegments);\n break;\n default:\n throw new FormatException();\n }\n mode = Mode.ASCII_ENCODE;\n }\n } while (mode !== Mode.PAD_ENCODE && bits.available() > 0);\n if (resultTrailer.length() > 0) {\n result.append(resultTrailer.toString());\n }\n return new DecoderResult(bytes, result.toString(), byteSegments.length === 0 ? null : byteSegments, null);\n }\n /**\n * See ISO 16022:2006, 5.2.3 and Annex C, Table C.2\n */\n static decodeAsciiSegment(bits, result, resultTrailer) {\n let upperShift = false;\n do {\n let oneByte = bits.readBits(8);\n if (oneByte === 0) {\n throw new FormatException();\n }\n else if (oneByte <= 128) { // ASCII data (ASCII value + 1)\n if (upperShift) {\n oneByte += 128;\n // upperShift = false;\n }\n result.append(String.fromCharCode(oneByte - 1));\n return Mode.ASCII_ENCODE;\n }\n else if (oneByte === 129) { // Pad\n return Mode.PAD_ENCODE;\n }\n else if (oneByte <= 229) { // 2-digit data 00-99 (Numeric Value + 130)\n const value = oneByte - 130;\n if (value < 10) { // pad with '0' for single digit values\n result.append('0');\n }\n result.append('' + value);\n }\n else {\n switch (oneByte) {\n case 230: // Latch to C40 encodation\n return Mode.C40_ENCODE;\n case 231: // Latch to Base 256 encodation\n return Mode.BASE256_ENCODE;\n case 232: // FNC1\n result.append(String.fromCharCode(29)); // translate as ASCII 29\n break;\n case 233: // Structured Append\n case 234: // Reader Programming\n // Ignore these symbols for now\n // throw ReaderException.getInstance();\n break;\n case 235: // Upper Shift (shift to Extended ASCII)\n upperShift = true;\n break;\n case 236: // 05 Macro\n result.append('[)>\\u001E05\\u001D');\n resultTrailer.insert(0, '\\u001E\\u0004');\n break;\n case 237: // 06 Macro\n result.append('[)>\\u001E06\\u001D');\n resultTrailer.insert(0, '\\u001E\\u0004');\n break;\n case 238: // Latch to ANSI X12 encodation\n return Mode.ANSIX12_ENCODE;\n case 239: // Latch to Text encodation\n return Mode.TEXT_ENCODE;\n case 240: // Latch to EDIFACT encodation\n return Mode.EDIFACT_ENCODE;\n case 241: // ECI Character\n // TODO(bbrown): I think we need to support ECI\n // throw ReaderException.getInstance();\n // Ignore this symbol for now\n break;\n default:\n // Not to be used in ASCII encodation\n // but work around encoders that end with 254, latch back to ASCII\n if (oneByte !== 254 || bits.available() !== 0) {\n throw new FormatException();\n }\n break;\n }\n }\n } while (bits.available() > 0);\n return Mode.ASCII_ENCODE;\n }\n /**\n * See ISO 16022:2006, 5.2.5 and Annex C, Table C.1\n */\n static decodeC40Segment(bits, result) {\n // Three C40 values are encoded in a 16-bit value as\n // (1600 * C1) + (40 * C2) + C3 + 1\n // TODO(bbrown): The Upper Shift with C40 doesn't work in the 4 value scenario all the time\n let upperShift = false;\n const cValues = [];\n let shift = 0;\n do {\n // If there is only one byte left then it will be encoded as ASCII\n if (bits.available() === 8) {\n return;\n }\n const firstByte = bits.readBits(8);\n if (firstByte === 254) { // Unlatch codeword\n return;\n }\n this.parseTwoBytes(firstByte, bits.readBits(8), cValues);\n for (let i = 0; i < 3; i++) {\n const cValue = cValues[i];\n switch (shift) {\n case 0:\n if (cValue < 3) {\n shift = cValue + 1;\n }\n else if (cValue < this.C40_BASIC_SET_CHARS.length) {\n const c40char = this.C40_BASIC_SET_CHARS[cValue];\n if (upperShift) {\n result.append(String.fromCharCode(c40char.charCodeAt(0) + 128));\n upperShift = false;\n }\n else {\n result.append(c40char);\n }\n }\n else {\n throw new FormatException();\n }\n break;\n case 1:\n if (upperShift) {\n result.append(String.fromCharCode(cValue + 128));\n upperShift = false;\n }\n else {\n result.append(String.fromCharCode(cValue));\n }\n shift = 0;\n break;\n case 2:\n if (cValue < this.C40_SHIFT2_SET_CHARS.length) {\n const c40char = this.C40_SHIFT2_SET_CHARS[cValue];\n if (upperShift) {\n result.append(String.fromCharCode(c40char.charCodeAt(0) + 128));\n upperShift = false;\n }\n else {\n result.append(c40char);\n }\n }\n else {\n switch (cValue) {\n case 27: // FNC1\n result.append(String.fromCharCode(29)); // translate as ASCII 29\n break;\n case 30: // Upper Shift\n upperShift = true;\n break;\n default:\n throw new FormatException();\n }\n }\n shift = 0;\n break;\n case 3:\n if (upperShift) {\n result.append(String.fromCharCode(cValue + 224));\n upperShift = false;\n }\n else {\n result.append(String.fromCharCode(cValue + 96));\n }\n shift = 0;\n break;\n default:\n throw new FormatException();\n }\n }\n } while (bits.available() > 0);\n }\n /**\n * See ISO 16022:2006, 5.2.6 and Annex C, Table C.2\n */\n static decodeTextSegment(bits, result) {\n // Three Text values are encoded in a 16-bit value as\n // (1600 * C1) + (40 * C2) + C3 + 1\n // TODO(bbrown): The Upper Shift with Text doesn't work in the 4 value scenario all the time\n let upperShift = false;\n let cValues = [];\n let shift = 0;\n do {\n // If there is only one byte left then it will be encoded as ASCII\n if (bits.available() === 8) {\n return;\n }\n const firstByte = bits.readBits(8);\n if (firstByte === 254) { // Unlatch codeword\n return;\n }\n this.parseTwoBytes(firstByte, bits.readBits(8), cValues);\n for (let i = 0; i < 3; i++) {\n const cValue = cValues[i];\n switch (shift) {\n case 0:\n if (cValue < 3) {\n shift = cValue + 1;\n }\n else if (cValue < this.TEXT_BASIC_SET_CHARS.length) {\n const textChar = this.TEXT_BASIC_SET_CHARS[cValue];\n if (upperShift) {\n result.append(String.fromCharCode(textChar.charCodeAt(0) + 128));\n upperShift = false;\n }\n else {\n result.append(textChar);\n }\n }\n else {\n throw new FormatException();\n }\n break;\n case 1:\n if (upperShift) {\n result.append(String.fromCharCode(cValue + 128));\n upperShift = false;\n }\n else {\n result.append(String.fromCharCode(cValue));\n }\n shift = 0;\n break;\n case 2:\n // Shift 2 for Text is the same encoding as C40\n if (cValue < this.TEXT_SHIFT2_SET_CHARS.length) {\n const textChar = this.TEXT_SHIFT2_SET_CHARS[cValue];\n if (upperShift) {\n result.append(String.fromCharCode(textChar.charCodeAt(0) + 128));\n upperShift = false;\n }\n else {\n result.append(textChar);\n }\n }\n else {\n switch (cValue) {\n case 27: // FNC1\n result.append(String.fromCharCode(29)); // translate as ASCII 29\n break;\n case 30: // Upper Shift\n upperShift = true;\n break;\n default:\n throw new FormatException();\n }\n }\n shift = 0;\n break;\n case 3:\n if (cValue < this.TEXT_SHIFT3_SET_CHARS.length) {\n const textChar = this.TEXT_SHIFT3_SET_CHARS[cValue];\n if (upperShift) {\n result.append(String.fromCharCode(textChar.charCodeAt(0) + 128));\n upperShift = false;\n }\n else {\n result.append(textChar);\n }\n shift = 0;\n }\n else {\n throw new FormatException();\n }\n break;\n default:\n throw new FormatException();\n }\n }\n } while (bits.available() > 0);\n }\n /**\n * See ISO 16022:2006, 5.2.7\n */\n static decodeAnsiX12Segment(bits, result) {\n // Three ANSI X12 values are encoded in a 16-bit value as\n // (1600 * C1) + (40 * C2) + C3 + 1\n const cValues = [];\n do {\n // If there is only one byte left then it will be encoded as ASCII\n if (bits.available() === 8) {\n return;\n }\n const firstByte = bits.readBits(8);\n if (firstByte === 254) { // Unlatch codeword\n return;\n }\n this.parseTwoBytes(firstByte, bits.readBits(8), cValues);\n for (let i = 0; i < 3; i++) {\n const cValue = cValues[i];\n switch (cValue) {\n case 0: // X12 segment terminator \n result.append('\\r');\n break;\n case 1: // X12 segment separator *\n result.append('*');\n break;\n case 2: // X12 sub-element separator >\n result.append('>');\n break;\n case 3: // space\n result.append(' ');\n break;\n default:\n if (cValue < 14) { // 0 - 9\n result.append(String.fromCharCode(cValue + 44));\n }\n else if (cValue < 40) { // A - Z\n result.append(String.fromCharCode(cValue + 51));\n }\n else {\n throw new FormatException();\n }\n break;\n }\n }\n } while (bits.available() > 0);\n }\n static parseTwoBytes(firstByte, secondByte, result) {\n let fullBitValue = (firstByte << 8) + secondByte - 1;\n let temp = Math.floor(fullBitValue / 1600);\n result[0] = temp;\n fullBitValue -= temp * 1600;\n temp = Math.floor(fullBitValue / 40);\n result[1] = temp;\n result[2] = fullBitValue - temp * 40;\n }\n /**\n * See ISO 16022:2006, 5.2.8 and Annex C Table C.3\n */\n static decodeEdifactSegment(bits, result) {\n do {\n // If there is only two or less bytes left then it will be encoded as ASCII\n if (bits.available() <= 16) {\n return;\n }\n for (let i = 0; i < 4; i++) {\n let edifactValue = bits.readBits(6);\n // Check for the unlatch character\n if (edifactValue === 0x1F) { // 011111\n // Read rest of byte, which should be 0, and stop\n const bitsLeft = 8 - bits.getBitOffset();\n if (bitsLeft !== 8) {\n bits.readBits(bitsLeft);\n }\n return;\n }\n if ((edifactValue & 0x20) === 0) { // no 1 in the leading (6th) bit\n edifactValue |= 0x40; // Add a leading 01 to the 6 bit binary value\n }\n result.append(String.fromCharCode(edifactValue));\n }\n } while (bits.available() > 0);\n }\n /**\n * See ISO 16022:2006, 5.2.9 and Annex B, B.2\n */\n static decodeBase256Segment(bits, result, byteSegments) {\n // Figure out how long the Base 256 Segment is.\n let codewordPosition = 1 + bits.getByteOffset(); // position is 1-indexed\n const d1 = this.unrandomize255State(bits.readBits(8), codewordPosition++);\n let count;\n if (d1 === 0) { // Read the remainder of the symbol\n count = bits.available() / 8 | 0;\n }\n else if (d1 < 250) {\n count = d1;\n }\n else {\n count = 250 * (d1 - 249) + this.unrandomize255State(bits.readBits(8), codewordPosition++);\n }\n // We're seeing NegativeArraySizeException errors from users.\n if (count < 0) {\n throw new FormatException();\n }\n const bytes = new Uint8Array(count);\n for (let i = 0; i < count; i++) {\n // Have seen this particular error in the wild, such as at\n // http://www.bcgen.com/demo/IDAutomationStreamingDataMatrix.aspx?MODE=3&D=Fred&PFMT=3&PT=F&X=0.3&O=0&LM=0.2\n if (bits.available() < 8) {\n throw new FormatException();\n }\n bytes[i] = this.unrandomize255State(bits.readBits(8), codewordPosition++);\n }\n byteSegments.push(bytes);\n try {\n result.append(StringEncoding.decode(bytes, StringUtils.ISO88591));\n }\n catch (uee) {\n throw new IllegalStateException('Platform does not support required encoding: ' + uee.message);\n }\n }\n /**\n * See ISO 16022:2006, Annex B, B.2\n */\n static unrandomize255State(randomizedBase256Codeword, base256CodewordPosition) {\n const pseudoRandomNumber = ((149 * base256CodewordPosition) % 255) + 1;\n const tempVariable = randomizedBase256Codeword - pseudoRandomNumber;\n return tempVariable >= 0 ? tempVariable : tempVariable + 256;\n }\n }\n /**\n * See ISO 16022:2006, Annex C Table C.1\n * The C40 Basic Character Set (*'s used for placeholders for the shift values)\n */\n DecodedBitStreamParser.C40_BASIC_SET_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 DecodedBitStreamParser.C40_SHIFT2_SET_CHARS = [\n '!', '\"', '#', '$', '%', '&', '\\'', '(', ')', '*', '+', ',', '-', '.',\n '/', ':', ';', '<', '=', '>', '?', '@', '[', '\\\\', ']', '^', '_'\n ];\n /**\n * See ISO 16022:2006, Annex C Table C.2\n * The Text Basic Character Set (*'s used for placeholders for the shift values)\n */\n DecodedBitStreamParser.TEXT_BASIC_SET_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 // Shift 2 for Text is the same encoding as C40\n DecodedBitStreamParser.TEXT_SHIFT2_SET_CHARS = DecodedBitStreamParser.C40_SHIFT2_SET_CHARS;\n DecodedBitStreamParser.TEXT_SHIFT3_SET_CHARS = [\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', '{', '|', '}', '~', String.fromCharCode(127)\n ];\n\n /*\n * Copyright 2007 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n /**\n *

The main class which implements Data Matrix Code decoding -- as opposed to locating and extracting\n * the Data Matrix Code from an image.

\n *\n * @author bbrown@google.com (Brian Brown)\n */\n class Decoder$1 {\n constructor() {\n this.rsDecoder = new ReedSolomonDecoder(GenericGF.DATA_MATRIX_FIELD_256);\n }\n /**\n *

Decodes a Data Matrix Code represented as a {@link BitMatrix}. A 1 or \"true\" is taken\n * to mean a black module.

\n *\n * @param bits booleans representing white/black Data Matrix Code modules\n * @return text and bytes encoded within the Data Matrix Code\n * @throws FormatException if the Data Matrix Code cannot be decoded\n * @throws ChecksumException if error correction fails\n */\n decode(bits) {\n // Construct a parser and read version, error-correction level\n const parser = new BitMatrixParser(bits);\n const version = parser.getVersion();\n // Read codewords\n const codewords = parser.readCodewords();\n // Separate into data blocks\n const dataBlocks = DataBlock.getDataBlocks(codewords, version);\n // Count total number of data bytes\n let totalBytes = 0;\n for (let db of dataBlocks) {\n totalBytes += db.getNumDataCodewords();\n }\n const resultBytes = new Uint8Array(totalBytes);\n const dataBlocksCount = dataBlocks.length;\n // Error-correct and copy data blocks together into a stream of bytes\n for (let j = 0; j < dataBlocksCount; j++) {\n const dataBlock = dataBlocks[j];\n const codewordBytes = dataBlock.getCodewords();\n const numDataCodewords = dataBlock.getNumDataCodewords();\n this.correctErrors(codewordBytes, numDataCodewords);\n for (let i = 0; i < numDataCodewords; i++) {\n // De-interlace data blocks.\n resultBytes[i * dataBlocksCount + j] = codewordBytes[i];\n }\n }\n // Decode the contents of that stream of bytes\n return DecodedBitStreamParser.decode(resultBytes);\n }\n /**\n *

Given data and error-correction codewords received, possibly corrupted by errors, attempts to\n * correct the errors in-place using Reed-Solomon error correction.

\n *\n * @param codewordBytes data and error correction codewords\n * @param numDataCodewords number of codewords that are data bytes\n * @throws ChecksumException if error correction fails\n */\n correctErrors(codewordBytes, numDataCodewords) {\n // const numCodewords = codewordBytes.length;\n // First read into an array of ints\n const codewordsInts = new Int32Array(codewordBytes);\n // for (let i = 0; i < numCodewords; i++) {\n // codewordsInts[i] = codewordBytes[i] & 0xFF;\n // }\n try {\n this.rsDecoder.decode(codewordsInts, codewordBytes.length - numDataCodewords);\n }\n catch (ignored /* ReedSolomonException */) {\n throw new ChecksumException();\n }\n // Copy back into array of bytes -- only need to worry about the bytes that were data\n // We don't care about errors in the error-correction codewords\n for (let i = 0; i < numDataCodewords; i++) {\n codewordBytes[i] = codewordsInts[i];\n }\n }\n }\n\n /**\n *

Encapsulates logic that can detect a Data Matrix Code in an image, even if the Data Matrix Code\n * is rotated or skewed, or partially obscured.

\n *\n * @author Sean Owen\n */\n class Detector$1 {\n constructor(image) {\n this.image = image;\n this.rectangleDetector = new WhiteRectangleDetector(this.image);\n }\n /**\n *

Detects a Data Matrix Code in an image.

\n *\n * @return {@link DetectorResult} encapsulating results of detecting a Data Matrix Code\n * @throws NotFoundException if no Data Matrix Code can be found\n */\n detect() {\n const cornerPoints = this.rectangleDetector.detect();\n let points = this.detectSolid1(cornerPoints);\n points = this.detectSolid2(points);\n points[3] = this.correctTopRight(points);\n if (!points[3]) {\n throw new NotFoundException();\n }\n points = this.shiftToModuleCenter(points);\n const topLeft = points[0];\n const bottomLeft = points[1];\n const bottomRight = points[2];\n const topRight = points[3];\n let dimensionTop = this.transitionsBetween(topLeft, topRight) + 1;\n let dimensionRight = this.transitionsBetween(bottomRight, topRight) + 1;\n if ((dimensionTop & 0x01) === 1) {\n dimensionTop += 1;\n }\n if ((dimensionRight & 0x01) === 1) {\n dimensionRight += 1;\n }\n if (4 * dimensionTop < 7 * dimensionRight && 4 * dimensionRight < 7 * dimensionTop) {\n // The matrix is square\n dimensionTop = dimensionRight = Math.max(dimensionTop, dimensionRight);\n }\n let bits = Detector$1.sampleGrid(this.image, topLeft, bottomLeft, bottomRight, topRight, dimensionTop, dimensionRight);\n return new DetectorResult(bits, [topLeft, bottomLeft, bottomRight, topRight]);\n }\n static shiftPoint(point, to, div) {\n let x = (to.getX() - point.getX()) / (div + 1);\n let y = (to.getY() - point.getY()) / (div + 1);\n return new ResultPoint(point.getX() + x, point.getY() + y);\n }\n static moveAway(point, fromX, fromY) {\n let x = point.getX();\n let y = point.getY();\n if (x < fromX) {\n x -= 1;\n }\n else {\n x += 1;\n }\n if (y < fromY) {\n y -= 1;\n }\n else {\n y += 1;\n }\n return new ResultPoint(x, y);\n }\n /**\n * Detect a solid side which has minimum transition.\n */\n detectSolid1(cornerPoints) {\n // 0 2\n // 1 3\n let pointA = cornerPoints[0];\n let pointB = cornerPoints[1];\n let pointC = cornerPoints[3];\n let pointD = cornerPoints[2];\n let trAB = this.transitionsBetween(pointA, pointB);\n let trBC = this.transitionsBetween(pointB, pointC);\n let trCD = this.transitionsBetween(pointC, pointD);\n let trDA = this.transitionsBetween(pointD, pointA);\n // 0..3\n // : :\n // 1--2\n let min = trAB;\n let points = [pointD, pointA, pointB, pointC];\n if (min > trBC) {\n min = trBC;\n points[0] = pointA;\n points[1] = pointB;\n points[2] = pointC;\n points[3] = pointD;\n }\n if (min > trCD) {\n min = trCD;\n points[0] = pointB;\n points[1] = pointC;\n points[2] = pointD;\n points[3] = pointA;\n }\n if (min > trDA) {\n points[0] = pointC;\n points[1] = pointD;\n points[2] = pointA;\n points[3] = pointB;\n }\n return points;\n }\n /**\n * Detect a second solid side next to first solid side.\n */\n detectSolid2(points) {\n // A..D\n // : :\n // B--C\n let pointA = points[0];\n let pointB = points[1];\n let pointC = points[2];\n let pointD = points[3];\n // Transition detection on the edge is not stable.\n // To safely detect, shift the points to the module center.\n let tr = this.transitionsBetween(pointA, pointD);\n let pointBs = Detector$1.shiftPoint(pointB, pointC, (tr + 1) * 4);\n let pointCs = Detector$1.shiftPoint(pointC, pointB, (tr + 1) * 4);\n let trBA = this.transitionsBetween(pointBs, pointA);\n let trCD = this.transitionsBetween(pointCs, pointD);\n // 0..3\n // | :\n // 1--2\n if (trBA < trCD) {\n // solid sides: A-B-C\n points[0] = pointA;\n points[1] = pointB;\n points[2] = pointC;\n points[3] = pointD;\n }\n else {\n // solid sides: B-C-D\n points[0] = pointB;\n points[1] = pointC;\n points[2] = pointD;\n points[3] = pointA;\n }\n return points;\n }\n /**\n * Calculates the corner position of the white top right module.\n */\n correctTopRight(points) {\n // A..D\n // | :\n // B--C\n let pointA = points[0];\n let pointB = points[1];\n let pointC = points[2];\n let pointD = points[3];\n // shift points for safe transition detection.\n let trTop = this.transitionsBetween(pointA, pointD);\n let trRight = this.transitionsBetween(pointB, pointD);\n let pointAs = Detector$1.shiftPoint(pointA, pointB, (trRight + 1) * 4);\n let pointCs = Detector$1.shiftPoint(pointC, pointB, (trTop + 1) * 4);\n trTop = this.transitionsBetween(pointAs, pointD);\n trRight = this.transitionsBetween(pointCs, pointD);\n let candidate1 = new ResultPoint(pointD.getX() + (pointC.getX() - pointB.getX()) / (trTop + 1), pointD.getY() + (pointC.getY() - pointB.getY()) / (trTop + 1));\n let candidate2 = new ResultPoint(pointD.getX() + (pointA.getX() - pointB.getX()) / (trRight + 1), pointD.getY() + (pointA.getY() - pointB.getY()) / (trRight + 1));\n if (!this.isValid(candidate1)) {\n if (this.isValid(candidate2)) {\n return candidate2;\n }\n return null;\n }\n if (!this.isValid(candidate2)) {\n return candidate1;\n }\n let sumc1 = this.transitionsBetween(pointAs, candidate1) + this.transitionsBetween(pointCs, candidate1);\n let sumc2 = this.transitionsBetween(pointAs, candidate2) + this.transitionsBetween(pointCs, candidate2);\n if (sumc1 > sumc2) {\n return candidate1;\n }\n else {\n return candidate2;\n }\n }\n /**\n * Shift the edge points to the module center.\n */\n shiftToModuleCenter(points) {\n // A..D\n // | :\n // B--C\n let pointA = points[0];\n let pointB = points[1];\n let pointC = points[2];\n let pointD = points[3];\n // calculate pseudo dimensions\n let dimH = this.transitionsBetween(pointA, pointD) + 1;\n let dimV = this.transitionsBetween(pointC, pointD) + 1;\n // shift points for safe dimension detection\n let pointAs = Detector$1.shiftPoint(pointA, pointB, dimV * 4);\n let pointCs = Detector$1.shiftPoint(pointC, pointB, dimH * 4);\n // calculate more precise dimensions\n dimH = this.transitionsBetween(pointAs, pointD) + 1;\n dimV = this.transitionsBetween(pointCs, pointD) + 1;\n if ((dimH & 0x01) === 1) {\n dimH += 1;\n }\n if ((dimV & 0x01) === 1) {\n dimV += 1;\n }\n // WhiteRectangleDetector returns points inside of the rectangle.\n // I want points on the edges.\n let centerX = (pointA.getX() + pointB.getX() + pointC.getX() + pointD.getX()) / 4;\n let centerY = (pointA.getY() + pointB.getY() + pointC.getY() + pointD.getY()) / 4;\n pointA = Detector$1.moveAway(pointA, centerX, centerY);\n pointB = Detector$1.moveAway(pointB, centerX, centerY);\n pointC = Detector$1.moveAway(pointC, centerX, centerY);\n pointD = Detector$1.moveAway(pointD, centerX, centerY);\n let pointBs;\n let pointDs;\n // shift points to the center of each modules\n pointAs = Detector$1.shiftPoint(pointA, pointB, dimV * 4);\n pointAs = Detector$1.shiftPoint(pointAs, pointD, dimH * 4);\n pointBs = Detector$1.shiftPoint(pointB, pointA, dimV * 4);\n pointBs = Detector$1.shiftPoint(pointBs, pointC, dimH * 4);\n pointCs = Detector$1.shiftPoint(pointC, pointD, dimV * 4);\n pointCs = Detector$1.shiftPoint(pointCs, pointB, dimH * 4);\n pointDs = Detector$1.shiftPoint(pointD, pointC, dimV * 4);\n pointDs = Detector$1.shiftPoint(pointDs, pointA, dimH * 4);\n return [pointAs, pointBs, pointCs, pointDs];\n }\n isValid(p) {\n return p.getX() >= 0 && p.getX() < this.image.getWidth() && p.getY() > 0 && p.getY() < this.image.getHeight();\n }\n static sampleGrid(image, topLeft, bottomLeft, bottomRight, topRight, dimensionX, dimensionY) {\n const sampler = GridSamplerInstance.getInstance();\n return sampler.sampleGrid(image, dimensionX, dimensionY, 0.5, 0.5, dimensionX - 0.5, 0.5, dimensionX - 0.5, dimensionY - 0.5, 0.5, dimensionY - 0.5, topLeft.getX(), topLeft.getY(), topRight.getX(), topRight.getY(), bottomRight.getX(), bottomRight.getY(), bottomLeft.getX(), bottomLeft.getY());\n }\n /**\n * Counts the number of black/white transitions between two points, using something like Bresenham's algorithm.\n */\n transitionsBetween(from, to) {\n // See QR Code Detector, sizeOfBlackWhiteBlackRun()\n let fromX = Math.trunc(from.getX());\n let fromY = Math.trunc(from.getY());\n let toX = Math.trunc(to.getX());\n let toY = Math.trunc(to.getY());\n let steep = Math.abs(toY - fromY) > Math.abs(toX - fromX);\n if (steep) {\n let temp = fromX;\n fromX = fromY;\n fromY = temp;\n temp = toX;\n toX = toY;\n toY = temp;\n }\n let dx = Math.abs(toX - fromX);\n let dy = Math.abs(toY - fromY);\n let error = -dx / 2;\n let ystep = fromY < toY ? 1 : -1;\n let xstep = fromX < toX ? 1 : -1;\n let transitions = 0;\n let inBlack = this.image.get(steep ? fromY : fromX, steep ? fromX : fromY);\n for (let x = fromX, y = fromY; x !== toX; x += xstep) {\n let isBlack = this.image.get(steep ? y : x, steep ? x : y);\n if (isBlack !== inBlack) {\n transitions++;\n inBlack = isBlack;\n }\n error += dy;\n if (error > 0) {\n if (y === toY) {\n break;\n }\n y += ystep;\n error -= dx;\n }\n }\n return transitions;\n }\n }\n\n /*\n * Copyright 2007 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n /**\n * This implementation can detect and decode Data Matrix codes in an image.\n *\n * @author bbrown@google.com (Brian Brown)\n */\n class DataMatrixReader {\n constructor() {\n this.decoder = new Decoder$1();\n }\n /**\n * Locates and decodes a Data Matrix code in an image.\n *\n * @return a String representing the content encoded by the Data Matrix code\n * @throws NotFoundException if a Data Matrix code cannot be found\n * @throws FormatException if a Data Matrix code cannot be decoded\n * @throws ChecksumException if error correction fails\n */\n // @Override\n // public Result decode(BinaryBitmap image) throws NotFoundException, ChecksumException, FormatException {\n // return decode(image, null);\n // }\n // @Override\n decode(image, hints = null) {\n let decoderResult;\n let points;\n if (hints != null && hints.has(DecodeHintType$1.PURE_BARCODE)) {\n const bits = DataMatrixReader.extractPureBits(image.getBlackMatrix());\n decoderResult = this.decoder.decode(bits);\n points = DataMatrixReader.NO_POINTS;\n }\n else {\n const detectorResult = new Detector$1(image.getBlackMatrix()).detect();\n decoderResult = this.decoder.decode(detectorResult.getBits());\n points = detectorResult.getPoints();\n }\n const rawBytes = decoderResult.getRawBytes();\n const result = new Result(decoderResult.getText(), rawBytes, 8 * rawBytes.length, points, BarcodeFormat$1.DATA_MATRIX, System.currentTimeMillis());\n const byteSegments = decoderResult.getByteSegments();\n if (byteSegments != null) {\n result.putMetadata(ResultMetadataType$1.BYTE_SEGMENTS, byteSegments);\n }\n const ecLevel = decoderResult.getECLevel();\n if (ecLevel != null) {\n result.putMetadata(ResultMetadataType$1.ERROR_CORRECTION_LEVEL, ecLevel);\n }\n return result;\n }\n // @Override\n reset() {\n // do nothing\n }\n /**\n * This method detects a code in a \"pure\" image -- that is, pure monochrome image\n * which contains only an unrotated, unskewed, image of a code, with some white border\n * around it. This is a specialized method that works exceptionally fast in this special\n * case.\n *\n * @see com.google.zxing.qrcode.QRCodeReader#extractPureBits(BitMatrix)\n */\n static extractPureBits(image) {\n const leftTopBlack = image.getTopLeftOnBit();\n const rightBottomBlack = image.getBottomRightOnBit();\n if (leftTopBlack == null || rightBottomBlack == null) {\n throw new NotFoundException();\n }\n const moduleSize = this.moduleSize(leftTopBlack, image);\n let top = leftTopBlack[1];\n const bottom = rightBottomBlack[1];\n let left = leftTopBlack[0];\n const right = rightBottomBlack[0];\n const matrixWidth = (right - left + 1) / moduleSize;\n const matrixHeight = (bottom - top + 1) / moduleSize;\n if (matrixWidth <= 0 || matrixHeight <= 0) {\n throw new NotFoundException();\n }\n // Push in the \"border\" by half the module width so that we start\n // sampling in the middle of the module. Just in case the image is a\n // little off, this will help recover.\n const nudge = moduleSize / 2;\n top += nudge;\n left += nudge;\n // Now just read off the bits\n const bits = new BitMatrix(matrixWidth, matrixHeight);\n for (let y = 0; y < matrixHeight; y++) {\n const iOffset = top + y * moduleSize;\n for (let x = 0; x < matrixWidth; x++) {\n if (image.get(left + x * moduleSize, iOffset)) {\n bits.set(x, y);\n }\n }\n }\n return bits;\n }\n static moduleSize(leftTopBlack, image) {\n const width = image.getWidth();\n let x = leftTopBlack[0];\n const y = leftTopBlack[1];\n while (x < width && image.get(x, y)) {\n x++;\n }\n if (x === width) {\n throw new NotFoundException();\n }\n const moduleSize = x - leftTopBlack[0];\n if (moduleSize === 0) {\n throw new NotFoundException();\n }\n return moduleSize;\n }\n }\n DataMatrixReader.NO_POINTS = [];\n\n /**\n * @deprecated Moving to @zxing/browser\n *\n * QR Code reader to use from browser.\n */\n class BrowserDatamatrixCodeReader extends BrowserCodeReader {\n /**\n * Creates an instance of BrowserQRCodeReader.\n * @param {number} [timeBetweenScansMillis=500] the time delay between subsequent decode tries\n */\n constructor(timeBetweenScansMillis = 500) {\n super(new DataMatrixReader(), timeBetweenScansMillis);\n }\n }\n\n /*\n * Copyright 2007 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n var ErrorCorrectionLevelValues;\n (function (ErrorCorrectionLevelValues) {\n ErrorCorrectionLevelValues[ErrorCorrectionLevelValues[\"L\"] = 0] = \"L\";\n ErrorCorrectionLevelValues[ErrorCorrectionLevelValues[\"M\"] = 1] = \"M\";\n ErrorCorrectionLevelValues[ErrorCorrectionLevelValues[\"Q\"] = 2] = \"Q\";\n ErrorCorrectionLevelValues[ErrorCorrectionLevelValues[\"H\"] = 3] = \"H\";\n })(ErrorCorrectionLevelValues || (ErrorCorrectionLevelValues = {}));\n /**\n *

See ISO 18004:2006, 6.5.1. This enum encapsulates the four error correction levels\n * defined by the QR code standard.

\n *\n * @author Sean Owen\n */\n class ErrorCorrectionLevel {\n constructor(value, stringValue, bits /*int*/) {\n this.value = value;\n this.stringValue = stringValue;\n this.bits = bits;\n ErrorCorrectionLevel.FOR_BITS.set(bits, this);\n ErrorCorrectionLevel.FOR_VALUE.set(value, this);\n }\n getValue() {\n return this.value;\n }\n getBits() {\n return this.bits;\n }\n static fromString(s) {\n switch (s) {\n case 'L': return ErrorCorrectionLevel.L;\n case 'M': return ErrorCorrectionLevel.M;\n case 'Q': return ErrorCorrectionLevel.Q;\n case 'H': return ErrorCorrectionLevel.H;\n default: throw new ArgumentException(s + 'not available');\n }\n }\n toString() {\n return this.stringValue;\n }\n equals(o) {\n if (!(o instanceof ErrorCorrectionLevel)) {\n return false;\n }\n const other = o;\n return this.value === other.value;\n }\n /**\n * @param bits int containing the two bits encoding a QR Code's error correction level\n * @return ErrorCorrectionLevel representing the encoded error correction level\n */\n static forBits(bits /*int*/) {\n if (bits < 0 || bits >= ErrorCorrectionLevel.FOR_BITS.size) {\n throw new IllegalArgumentException();\n }\n return ErrorCorrectionLevel.FOR_BITS.get(bits);\n }\n }\n ErrorCorrectionLevel.FOR_BITS = new Map();\n ErrorCorrectionLevel.FOR_VALUE = new Map();\n /** L = ~7% correction */\n ErrorCorrectionLevel.L = new ErrorCorrectionLevel(ErrorCorrectionLevelValues.L, 'L', 0x01);\n /** M = ~15% correction */\n ErrorCorrectionLevel.M = new ErrorCorrectionLevel(ErrorCorrectionLevelValues.M, 'M', 0x00);\n /** Q = ~25% correction */\n ErrorCorrectionLevel.Q = new ErrorCorrectionLevel(ErrorCorrectionLevelValues.Q, 'Q', 0x03);\n /** H = ~30% correction */\n ErrorCorrectionLevel.H = new ErrorCorrectionLevel(ErrorCorrectionLevelValues.H, 'H', 0x02);\n\n /*\n * Copyright 2007 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n /**\n *

Encapsulates a QR Code's format information, including the data mask used and\n * error correction level.

\n *\n * @author Sean Owen\n * @see DataMask\n * @see ErrorCorrectionLevel\n */\n class FormatInformation {\n constructor(formatInfo /*int*/) {\n // Bits 3,4\n this.errorCorrectionLevel = ErrorCorrectionLevel.forBits((formatInfo >> 3) & 0x03);\n // Bottom 3 bits\n this.dataMask = /*(byte) */ (formatInfo & 0x07);\n }\n static numBitsDiffering(a /*int*/, b /*int*/) {\n return Integer.bitCount(a ^ b);\n }\n /**\n * @param maskedFormatInfo1 format info indicator, with mask still applied\n * @param maskedFormatInfo2 second copy of same info; both are checked at the same time\n * to establish best match\n * @return information about the format it specifies, or {@code null}\n * if doesn't seem to match any known pattern\n */\n static decodeFormatInformation(maskedFormatInfo1 /*int*/, maskedFormatInfo2 /*int*/) {\n const formatInfo = FormatInformation.doDecodeFormatInformation(maskedFormatInfo1, maskedFormatInfo2);\n if (formatInfo !== null) {\n return formatInfo;\n }\n // Should return null, but, some QR codes apparently\n // do not mask this info. Try again by actually masking the pattern\n // first\n return FormatInformation.doDecodeFormatInformation(maskedFormatInfo1 ^ FormatInformation.FORMAT_INFO_MASK_QR, maskedFormatInfo2 ^ FormatInformation.FORMAT_INFO_MASK_QR);\n }\n static doDecodeFormatInformation(maskedFormatInfo1 /*int*/, maskedFormatInfo2 /*int*/) {\n // Find the int in FORMAT_INFO_DECODE_LOOKUP with fewest bits differing\n let bestDifference = Number.MAX_SAFE_INTEGER;\n let bestFormatInfo = 0;\n for (const decodeInfo of FormatInformation.FORMAT_INFO_DECODE_LOOKUP) {\n const targetInfo = decodeInfo[0];\n if (targetInfo === maskedFormatInfo1 || targetInfo === maskedFormatInfo2) {\n // Found an exact match\n return new FormatInformation(decodeInfo[1]);\n }\n let bitsDifference = FormatInformation.numBitsDiffering(maskedFormatInfo1, targetInfo);\n if (bitsDifference < bestDifference) {\n bestFormatInfo = decodeInfo[1];\n bestDifference = bitsDifference;\n }\n if (maskedFormatInfo1 !== maskedFormatInfo2) {\n // also try the other option\n bitsDifference = FormatInformation.numBitsDiffering(maskedFormatInfo2, targetInfo);\n if (bitsDifference < bestDifference) {\n bestFormatInfo = decodeInfo[1];\n bestDifference = bitsDifference;\n }\n }\n }\n // Hamming distance of the 32 masked codes is 7, by construction, so <= 3 bits\n // differing means we found a match\n if (bestDifference <= 3) {\n return new FormatInformation(bestFormatInfo);\n }\n return null;\n }\n getErrorCorrectionLevel() {\n return this.errorCorrectionLevel;\n }\n getDataMask() {\n return this.dataMask;\n }\n /*@Override*/\n hashCode() {\n return (this.errorCorrectionLevel.getBits() << 3) | this.dataMask;\n }\n /*@Override*/\n equals(o) {\n if (!(o instanceof FormatInformation)) {\n return false;\n }\n const other = o;\n return this.errorCorrectionLevel === other.errorCorrectionLevel &&\n this.dataMask === other.dataMask;\n }\n }\n FormatInformation.FORMAT_INFO_MASK_QR = 0x5412;\n /**\n * See ISO 18004:2006, Annex C, Table C.1\n */\n FormatInformation.FORMAT_INFO_DECODE_LOOKUP = [\n Int32Array.from([0x5412, 0x00]),\n Int32Array.from([0x5125, 0x01]),\n Int32Array.from([0x5E7C, 0x02]),\n Int32Array.from([0x5B4B, 0x03]),\n Int32Array.from([0x45F9, 0x04]),\n Int32Array.from([0x40CE, 0x05]),\n Int32Array.from([0x4F97, 0x06]),\n Int32Array.from([0x4AA0, 0x07]),\n Int32Array.from([0x77C4, 0x08]),\n Int32Array.from([0x72F3, 0x09]),\n Int32Array.from([0x7DAA, 0x0A]),\n Int32Array.from([0x789D, 0x0B]),\n Int32Array.from([0x662F, 0x0C]),\n Int32Array.from([0x6318, 0x0D]),\n Int32Array.from([0x6C41, 0x0E]),\n Int32Array.from([0x6976, 0x0F]),\n Int32Array.from([0x1689, 0x10]),\n Int32Array.from([0x13BE, 0x11]),\n Int32Array.from([0x1CE7, 0x12]),\n Int32Array.from([0x19D0, 0x13]),\n Int32Array.from([0x0762, 0x14]),\n Int32Array.from([0x0255, 0x15]),\n Int32Array.from([0x0D0C, 0x16]),\n Int32Array.from([0x083B, 0x17]),\n Int32Array.from([0x355F, 0x18]),\n Int32Array.from([0x3068, 0x19]),\n Int32Array.from([0x3F31, 0x1A]),\n Int32Array.from([0x3A06, 0x1B]),\n Int32Array.from([0x24B4, 0x1C]),\n Int32Array.from([0x2183, 0x1D]),\n Int32Array.from([0x2EDA, 0x1E]),\n Int32Array.from([0x2BED, 0x1F]),\n ];\n\n /**\n *

Encapsulates a set of error-correction blocks in one symbol version. Most versions will\n * use blocks of differing sizes within one version, so, this encapsulates the parameters for\n * each set of blocks. It also holds the number of error-correction codewords per block since it\n * will be the same across all blocks within one version.

\n */\n class ECBlocks$1 {\n constructor(ecCodewordsPerBlock /*int*/, ...ecBlocks) {\n this.ecCodewordsPerBlock = ecCodewordsPerBlock;\n this.ecBlocks = ecBlocks;\n }\n getECCodewordsPerBlock() {\n return this.ecCodewordsPerBlock;\n }\n getNumBlocks() {\n let total = 0;\n const ecBlocks = this.ecBlocks;\n for (const ecBlock of ecBlocks) {\n total += ecBlock.getCount();\n }\n return total;\n }\n getTotalECCodewords() {\n return this.ecCodewordsPerBlock * this.getNumBlocks();\n }\n getECBlocks() {\n return this.ecBlocks;\n }\n }\n\n /**\n *

Encapsulates the parameters for one error-correction block in one symbol version.\n * This includes the number of data codewords, and the number of times a block with these\n * parameters is used consecutively in the QR code version's format.

\n */\n class ECB$1 {\n constructor(count /*int*/, dataCodewords /*int*/) {\n this.count = count;\n this.dataCodewords = dataCodewords;\n }\n getCount() {\n return this.count;\n }\n getDataCodewords() {\n return this.dataCodewords;\n }\n }\n\n /*\n * Copyright 2007 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n /**\n * See ISO 18004:2006 Annex D\n *\n * @author Sean Owen\n */\n class Version$1 {\n constructor(versionNumber /*int*/, alignmentPatternCenters, ...ecBlocks) {\n this.versionNumber = versionNumber;\n this.alignmentPatternCenters = alignmentPatternCenters;\n this.ecBlocks = ecBlocks;\n let total = 0;\n const ecCodewords = ecBlocks[0].getECCodewordsPerBlock();\n const ecbArray = ecBlocks[0].getECBlocks();\n for (const ecBlock of ecbArray) {\n total += ecBlock.getCount() * (ecBlock.getDataCodewords() + ecCodewords);\n }\n this.totalCodewords = total;\n }\n getVersionNumber() {\n return this.versionNumber;\n }\n getAlignmentPatternCenters() {\n return this.alignmentPatternCenters;\n }\n getTotalCodewords() {\n return this.totalCodewords;\n }\n getDimensionForVersion() {\n return 17 + 4 * this.versionNumber;\n }\n getECBlocksForLevel(ecLevel) {\n return this.ecBlocks[ecLevel.getValue()];\n // TYPESCRIPTPORT: original was using ordinal, and using the order of levels as defined in ErrorCorrectionLevel enum (LMQH)\n // I will use the direct value from ErrorCorrectionLevelValues enum which in typescript goes to a number\n }\n /**\n *

Deduces version information purely from QR Code dimensions.

\n *\n * @param dimension dimension in modules\n * @return Version for a QR Code of that dimension\n * @throws FormatException if dimension is not 1 mod 4\n */\n static getProvisionalVersionForDimension(dimension /*int*/) {\n if (dimension % 4 !== 1) {\n throw new FormatException();\n }\n try {\n return this.getVersionForNumber((dimension - 17) / 4);\n }\n catch (ignored /*: IllegalArgumentException*/) {\n throw new FormatException();\n }\n }\n static getVersionForNumber(versionNumber /*int*/) {\n if (versionNumber < 1 || versionNumber > 40) {\n throw new IllegalArgumentException();\n }\n return Version$1.VERSIONS[versionNumber - 1];\n }\n static decodeVersionInformation(versionBits /*int*/) {\n let bestDifference = Number.MAX_SAFE_INTEGER;\n let bestVersion = 0;\n for (let i = 0; i < Version$1.VERSION_DECODE_INFO.length; i++) {\n const targetVersion = Version$1.VERSION_DECODE_INFO[i];\n // Do the version info bits match exactly? done.\n if (targetVersion === versionBits) {\n return Version$1.getVersionForNumber(i + 7);\n }\n // Otherwise see if this is the closest to a real version info bit string\n // we have seen so far\n const bitsDifference = FormatInformation.numBitsDiffering(versionBits, targetVersion);\n if (bitsDifference < bestDifference) {\n bestVersion = i + 7;\n bestDifference = bitsDifference;\n }\n }\n // We can tolerate up to 3 bits of error since no two version info codewords will\n // differ in less than 8 bits.\n if (bestDifference <= 3) {\n return Version$1.getVersionForNumber(bestVersion);\n }\n // If we didn't find a close enough match, fail\n return null;\n }\n /**\n * See ISO 18004:2006 Annex E\n */\n buildFunctionPattern() {\n const dimension = this.getDimensionForVersion();\n const bitMatrix = new BitMatrix(dimension);\n // Top left finder pattern + separator + format\n bitMatrix.setRegion(0, 0, 9, 9);\n // Top right finder pattern + separator + format\n bitMatrix.setRegion(dimension - 8, 0, 8, 9);\n // Bottom left finder pattern + separator + format\n bitMatrix.setRegion(0, dimension - 8, 9, 8);\n // Alignment patterns\n const max = this.alignmentPatternCenters.length;\n for (let x = 0; x < max; x++) {\n const i = this.alignmentPatternCenters[x] - 2;\n for (let y = 0; y < max; y++) {\n if ((x === 0 && (y === 0 || y === max - 1)) || (x === max - 1 && y === 0)) {\n // No alignment patterns near the three finder patterns\n continue;\n }\n bitMatrix.setRegion(this.alignmentPatternCenters[y] - 2, i, 5, 5);\n }\n }\n // Vertical timing pattern\n bitMatrix.setRegion(6, 9, 1, dimension - 17);\n // Horizontal timing pattern\n bitMatrix.setRegion(9, 6, dimension - 17, 1);\n if (this.versionNumber > 6) {\n // Version info, top right\n bitMatrix.setRegion(dimension - 11, 0, 3, 6);\n // Version info, bottom left\n bitMatrix.setRegion(0, dimension - 11, 6, 3);\n }\n return bitMatrix;\n }\n /*@Override*/\n toString() {\n return '' + this.versionNumber;\n }\n }\n /**\n * See ISO 18004:2006 Annex D.\n * Element i represents the raw version bits that specify version i + 7\n */\n Version$1.VERSION_DECODE_INFO = Int32Array.from([\n 0x07C94, 0x085BC, 0x09A99, 0x0A4D3, 0x0BBF6,\n 0x0C762, 0x0D847, 0x0E60D, 0x0F928, 0x10B78,\n 0x1145D, 0x12A17, 0x13532, 0x149A6, 0x15683,\n 0x168C9, 0x177EC, 0x18EC4, 0x191E1, 0x1AFAB,\n 0x1B08E, 0x1CC1A, 0x1D33F, 0x1ED75, 0x1F250,\n 0x209D5, 0x216F0, 0x228BA, 0x2379F, 0x24B0B,\n 0x2542E, 0x26A64, 0x27541, 0x28C69\n ]);\n /**\n * See ISO 18004:2006 6.5.1 Table 9\n */\n Version$1.VERSIONS = [\n new Version$1(1, new Int32Array(0), new ECBlocks$1(7, new ECB$1(1, 19)), new ECBlocks$1(10, new ECB$1(1, 16)), new ECBlocks$1(13, new ECB$1(1, 13)), new ECBlocks$1(17, new ECB$1(1, 9))),\n new Version$1(2, Int32Array.from([6, 18]), new ECBlocks$1(10, new ECB$1(1, 34)), new ECBlocks$1(16, new ECB$1(1, 28)), new ECBlocks$1(22, new ECB$1(1, 22)), new ECBlocks$1(28, new ECB$1(1, 16))),\n new Version$1(3, Int32Array.from([6, 22]), new ECBlocks$1(15, new ECB$1(1, 55)), new ECBlocks$1(26, new ECB$1(1, 44)), new ECBlocks$1(18, new ECB$1(2, 17)), new ECBlocks$1(22, new ECB$1(2, 13))),\n new Version$1(4, Int32Array.from([6, 26]), new ECBlocks$1(20, new ECB$1(1, 80)), new ECBlocks$1(18, new ECB$1(2, 32)), new ECBlocks$1(26, new ECB$1(2, 24)), new ECBlocks$1(16, new ECB$1(4, 9))),\n new Version$1(5, Int32Array.from([6, 30]), new ECBlocks$1(26, new ECB$1(1, 108)), new ECBlocks$1(24, new ECB$1(2, 43)), new ECBlocks$1(18, new ECB$1(2, 15), new ECB$1(2, 16)), new ECBlocks$1(22, new ECB$1(2, 11), new ECB$1(2, 12))),\n new Version$1(6, Int32Array.from([6, 34]), new ECBlocks$1(18, new ECB$1(2, 68)), new ECBlocks$1(16, new ECB$1(4, 27)), new ECBlocks$1(24, new ECB$1(4, 19)), new ECBlocks$1(28, new ECB$1(4, 15))),\n new Version$1(7, Int32Array.from([6, 22, 38]), new ECBlocks$1(20, new ECB$1(2, 78)), new ECBlocks$1(18, new ECB$1(4, 31)), new ECBlocks$1(18, new ECB$1(2, 14), new ECB$1(4, 15)), new ECBlocks$1(26, new ECB$1(4, 13), new ECB$1(1, 14))),\n new Version$1(8, Int32Array.from([6, 24, 42]), new ECBlocks$1(24, new ECB$1(2, 97)), new ECBlocks$1(22, new ECB$1(2, 38), new ECB$1(2, 39)), new ECBlocks$1(22, new ECB$1(4, 18), new ECB$1(2, 19)), new ECBlocks$1(26, new ECB$1(4, 14), new ECB$1(2, 15))),\n new Version$1(9, Int32Array.from([6, 26, 46]), new ECBlocks$1(30, new ECB$1(2, 116)), new ECBlocks$1(22, new ECB$1(3, 36), new ECB$1(2, 37)), new ECBlocks$1(20, new ECB$1(4, 16), new ECB$1(4, 17)), new ECBlocks$1(24, new ECB$1(4, 12), new ECB$1(4, 13))),\n new Version$1(10, Int32Array.from([6, 28, 50]), new ECBlocks$1(18, new ECB$1(2, 68), new ECB$1(2, 69)), new ECBlocks$1(26, new ECB$1(4, 43), new ECB$1(1, 44)), new ECBlocks$1(24, new ECB$1(6, 19), new ECB$1(2, 20)), new ECBlocks$1(28, new ECB$1(6, 15), new ECB$1(2, 16))),\n new Version$1(11, Int32Array.from([6, 30, 54]), new ECBlocks$1(20, new ECB$1(4, 81)), new ECBlocks$1(30, new ECB$1(1, 50), new ECB$1(4, 51)), new ECBlocks$1(28, new ECB$1(4, 22), new ECB$1(4, 23)), new ECBlocks$1(24, new ECB$1(3, 12), new ECB$1(8, 13))),\n new Version$1(12, Int32Array.from([6, 32, 58]), new ECBlocks$1(24, new ECB$1(2, 92), new ECB$1(2, 93)), new ECBlocks$1(22, new ECB$1(6, 36), new ECB$1(2, 37)), new ECBlocks$1(26, new ECB$1(4, 20), new ECB$1(6, 21)), new ECBlocks$1(28, new ECB$1(7, 14), new ECB$1(4, 15))),\n new Version$1(13, Int32Array.from([6, 34, 62]), new ECBlocks$1(26, new ECB$1(4, 107)), new ECBlocks$1(22, new ECB$1(8, 37), new ECB$1(1, 38)), new ECBlocks$1(24, new ECB$1(8, 20), new ECB$1(4, 21)), new ECBlocks$1(22, new ECB$1(12, 11), new ECB$1(4, 12))),\n new Version$1(14, Int32Array.from([6, 26, 46, 66]), new ECBlocks$1(30, new ECB$1(3, 115), new ECB$1(1, 116)), new ECBlocks$1(24, new ECB$1(4, 40), new ECB$1(5, 41)), new ECBlocks$1(20, new ECB$1(11, 16), new ECB$1(5, 17)), new ECBlocks$1(24, new ECB$1(11, 12), new ECB$1(5, 13))),\n new Version$1(15, Int32Array.from([6, 26, 48, 70]), new ECBlocks$1(22, new ECB$1(5, 87), new ECB$1(1, 88)), new ECBlocks$1(24, new ECB$1(5, 41), new ECB$1(5, 42)), new ECBlocks$1(30, new ECB$1(5, 24), new ECB$1(7, 25)), new ECBlocks$1(24, new ECB$1(11, 12), new ECB$1(7, 13))),\n new Version$1(16, Int32Array.from([6, 26, 50, 74]), new ECBlocks$1(24, new ECB$1(5, 98), new ECB$1(1, 99)), new ECBlocks$1(28, new ECB$1(7, 45), new ECB$1(3, 46)), new ECBlocks$1(24, new ECB$1(15, 19), new ECB$1(2, 20)), new ECBlocks$1(30, new ECB$1(3, 15), new ECB$1(13, 16))),\n new Version$1(17, Int32Array.from([6, 30, 54, 78]), new ECBlocks$1(28, new ECB$1(1, 107), new ECB$1(5, 108)), new ECBlocks$1(28, new ECB$1(10, 46), new ECB$1(1, 47)), new ECBlocks$1(28, new ECB$1(1, 22), new ECB$1(15, 23)), new ECBlocks$1(28, new ECB$1(2, 14), new ECB$1(17, 15))),\n new Version$1(18, Int32Array.from([6, 30, 56, 82]), new ECBlocks$1(30, new ECB$1(5, 120), new ECB$1(1, 121)), new ECBlocks$1(26, new ECB$1(9, 43), new ECB$1(4, 44)), new ECBlocks$1(28, new ECB$1(17, 22), new ECB$1(1, 23)), new ECBlocks$1(28, new ECB$1(2, 14), new ECB$1(19, 15))),\n new Version$1(19, Int32Array.from([6, 30, 58, 86]), new ECBlocks$1(28, new ECB$1(3, 113), new ECB$1(4, 114)), new ECBlocks$1(26, new ECB$1(3, 44), new ECB$1(11, 45)), new ECBlocks$1(26, new ECB$1(17, 21), new ECB$1(4, 22)), new ECBlocks$1(26, new ECB$1(9, 13), new ECB$1(16, 14))),\n new Version$1(20, Int32Array.from([6, 34, 62, 90]), new ECBlocks$1(28, new ECB$1(3, 107), new ECB$1(5, 108)), new ECBlocks$1(26, new ECB$1(3, 41), new ECB$1(13, 42)), new ECBlocks$1(30, new ECB$1(15, 24), new ECB$1(5, 25)), new ECBlocks$1(28, new ECB$1(15, 15), new ECB$1(10, 16))),\n new Version$1(21, Int32Array.from([6, 28, 50, 72, 94]), new ECBlocks$1(28, new ECB$1(4, 116), new ECB$1(4, 117)), new ECBlocks$1(26, new ECB$1(17, 42)), new ECBlocks$1(28, new ECB$1(17, 22), new ECB$1(6, 23)), new ECBlocks$1(30, new ECB$1(19, 16), new ECB$1(6, 17))),\n new Version$1(22, Int32Array.from([6, 26, 50, 74, 98]), new ECBlocks$1(28, new ECB$1(2, 111), new ECB$1(7, 112)), new ECBlocks$1(28, new ECB$1(17, 46)), new ECBlocks$1(30, new ECB$1(7, 24), new ECB$1(16, 25)), new ECBlocks$1(24, new ECB$1(34, 13))),\n new Version$1(23, Int32Array.from([6, 30, 54, 78, 102]), new ECBlocks$1(30, new ECB$1(4, 121), new ECB$1(5, 122)), new ECBlocks$1(28, new ECB$1(4, 47), new ECB$1(14, 48)), new ECBlocks$1(30, new ECB$1(11, 24), new ECB$1(14, 25)), new ECBlocks$1(30, new ECB$1(16, 15), new ECB$1(14, 16))),\n new Version$1(24, Int32Array.from([6, 28, 54, 80, 106]), new ECBlocks$1(30, new ECB$1(6, 117), new ECB$1(4, 118)), new ECBlocks$1(28, new ECB$1(6, 45), new ECB$1(14, 46)), new ECBlocks$1(30, new ECB$1(11, 24), new ECB$1(16, 25)), new ECBlocks$1(30, new ECB$1(30, 16), new ECB$1(2, 17))),\n new Version$1(25, Int32Array.from([6, 32, 58, 84, 110]), new ECBlocks$1(26, new ECB$1(8, 106), new ECB$1(4, 107)), new ECBlocks$1(28, new ECB$1(8, 47), new ECB$1(13, 48)), new ECBlocks$1(30, new ECB$1(7, 24), new ECB$1(22, 25)), new ECBlocks$1(30, new ECB$1(22, 15), new ECB$1(13, 16))),\n new Version$1(26, Int32Array.from([6, 30, 58, 86, 114]), new ECBlocks$1(28, new ECB$1(10, 114), new ECB$1(2, 115)), new ECBlocks$1(28, new ECB$1(19, 46), new ECB$1(4, 47)), new ECBlocks$1(28, new ECB$1(28, 22), new ECB$1(6, 23)), new ECBlocks$1(30, new ECB$1(33, 16), new ECB$1(4, 17))),\n new Version$1(27, Int32Array.from([6, 34, 62, 90, 118]), new ECBlocks$1(30, new ECB$1(8, 122), new ECB$1(4, 123)), new ECBlocks$1(28, new ECB$1(22, 45), new ECB$1(3, 46)), new ECBlocks$1(30, new ECB$1(8, 23), new ECB$1(26, 24)), new ECBlocks$1(30, new ECB$1(12, 15), new ECB$1(28, 16))),\n new Version$1(28, Int32Array.from([6, 26, 50, 74, 98, 122]), new ECBlocks$1(30, new ECB$1(3, 117), new ECB$1(10, 118)), new ECBlocks$1(28, new ECB$1(3, 45), new ECB$1(23, 46)), new ECBlocks$1(30, new ECB$1(4, 24), new ECB$1(31, 25)), new ECBlocks$1(30, new ECB$1(11, 15), new ECB$1(31, 16))),\n new Version$1(29, Int32Array.from([6, 30, 54, 78, 102, 126]), new ECBlocks$1(30, new ECB$1(7, 116), new ECB$1(7, 117)), new ECBlocks$1(28, new ECB$1(21, 45), new ECB$1(7, 46)), new ECBlocks$1(30, new ECB$1(1, 23), new ECB$1(37, 24)), new ECBlocks$1(30, new ECB$1(19, 15), new ECB$1(26, 16))),\n new Version$1(30, Int32Array.from([6, 26, 52, 78, 104, 130]), new ECBlocks$1(30, new ECB$1(5, 115), new ECB$1(10, 116)), new ECBlocks$1(28, new ECB$1(19, 47), new ECB$1(10, 48)), new ECBlocks$1(30, new ECB$1(15, 24), new ECB$1(25, 25)), new ECBlocks$1(30, new ECB$1(23, 15), new ECB$1(25, 16))),\n new Version$1(31, Int32Array.from([6, 30, 56, 82, 108, 134]), new ECBlocks$1(30, new ECB$1(13, 115), new ECB$1(3, 116)), new ECBlocks$1(28, new ECB$1(2, 46), new ECB$1(29, 47)), new ECBlocks$1(30, new ECB$1(42, 24), new ECB$1(1, 25)), new ECBlocks$1(30, new ECB$1(23, 15), new ECB$1(28, 16))),\n new Version$1(32, Int32Array.from([6, 34, 60, 86, 112, 138]), new ECBlocks$1(30, new ECB$1(17, 115)), new ECBlocks$1(28, new ECB$1(10, 46), new ECB$1(23, 47)), new ECBlocks$1(30, new ECB$1(10, 24), new ECB$1(35, 25)), new ECBlocks$1(30, new ECB$1(19, 15), new ECB$1(35, 16))),\n new Version$1(33, Int32Array.from([6, 30, 58, 86, 114, 142]), new ECBlocks$1(30, new ECB$1(17, 115), new ECB$1(1, 116)), new ECBlocks$1(28, new ECB$1(14, 46), new ECB$1(21, 47)), new ECBlocks$1(30, new ECB$1(29, 24), new ECB$1(19, 25)), new ECBlocks$1(30, new ECB$1(11, 15), new ECB$1(46, 16))),\n new Version$1(34, Int32Array.from([6, 34, 62, 90, 118, 146]), new ECBlocks$1(30, new ECB$1(13, 115), new ECB$1(6, 116)), new ECBlocks$1(28, new ECB$1(14, 46), new ECB$1(23, 47)), new ECBlocks$1(30, new ECB$1(44, 24), new ECB$1(7, 25)), new ECBlocks$1(30, new ECB$1(59, 16), new ECB$1(1, 17))),\n new Version$1(35, Int32Array.from([6, 30, 54, 78, 102, 126, 150]), new ECBlocks$1(30, new ECB$1(12, 121), new ECB$1(7, 122)), new ECBlocks$1(28, new ECB$1(12, 47), new ECB$1(26, 48)), new ECBlocks$1(30, new ECB$1(39, 24), new ECB$1(14, 25)), new ECBlocks$1(30, new ECB$1(22, 15), new ECB$1(41, 16))),\n new Version$1(36, Int32Array.from([6, 24, 50, 76, 102, 128, 154]), new ECBlocks$1(30, new ECB$1(6, 121), new ECB$1(14, 122)), new ECBlocks$1(28, new ECB$1(6, 47), new ECB$1(34, 48)), new ECBlocks$1(30, new ECB$1(46, 24), new ECB$1(10, 25)), new ECBlocks$1(30, new ECB$1(2, 15), new ECB$1(64, 16))),\n new Version$1(37, Int32Array.from([6, 28, 54, 80, 106, 132, 158]), new ECBlocks$1(30, new ECB$1(17, 122), new ECB$1(4, 123)), new ECBlocks$1(28, new ECB$1(29, 46), new ECB$1(14, 47)), new ECBlocks$1(30, new ECB$1(49, 24), new ECB$1(10, 25)), new ECBlocks$1(30, new ECB$1(24, 15), new ECB$1(46, 16))),\n new Version$1(38, Int32Array.from([6, 32, 58, 84, 110, 136, 162]), new ECBlocks$1(30, new ECB$1(4, 122), new ECB$1(18, 123)), new ECBlocks$1(28, new ECB$1(13, 46), new ECB$1(32, 47)), new ECBlocks$1(30, new ECB$1(48, 24), new ECB$1(14, 25)), new ECBlocks$1(30, new ECB$1(42, 15), new ECB$1(32, 16))),\n new Version$1(39, Int32Array.from([6, 26, 54, 82, 110, 138, 166]), new ECBlocks$1(30, new ECB$1(20, 117), new ECB$1(4, 118)), new ECBlocks$1(28, new ECB$1(40, 47), new ECB$1(7, 48)), new ECBlocks$1(30, new ECB$1(43, 24), new ECB$1(22, 25)), new ECBlocks$1(30, new ECB$1(10, 15), new ECB$1(67, 16))),\n new Version$1(40, Int32Array.from([6, 30, 58, 86, 114, 142, 170]), new ECBlocks$1(30, new ECB$1(19, 118), new ECB$1(6, 119)), new ECBlocks$1(28, new ECB$1(18, 47), new ECB$1(31, 48)), new ECBlocks$1(30, new ECB$1(34, 24), new ECB$1(34, 25)), new ECBlocks$1(30, new ECB$1(20, 15), new ECB$1(61, 16)))\n ];\n\n /*\n * Copyright 2007 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n var DataMaskValues;\n (function (DataMaskValues) {\n DataMaskValues[DataMaskValues[\"DATA_MASK_000\"] = 0] = \"DATA_MASK_000\";\n DataMaskValues[DataMaskValues[\"DATA_MASK_001\"] = 1] = \"DATA_MASK_001\";\n DataMaskValues[DataMaskValues[\"DATA_MASK_010\"] = 2] = \"DATA_MASK_010\";\n DataMaskValues[DataMaskValues[\"DATA_MASK_011\"] = 3] = \"DATA_MASK_011\";\n DataMaskValues[DataMaskValues[\"DATA_MASK_100\"] = 4] = \"DATA_MASK_100\";\n DataMaskValues[DataMaskValues[\"DATA_MASK_101\"] = 5] = \"DATA_MASK_101\";\n DataMaskValues[DataMaskValues[\"DATA_MASK_110\"] = 6] = \"DATA_MASK_110\";\n DataMaskValues[DataMaskValues[\"DATA_MASK_111\"] = 7] = \"DATA_MASK_111\";\n })(DataMaskValues || (DataMaskValues = {}));\n /**\n *

Encapsulates data masks for the data bits in a QR code, per ISO 18004:2006 6.8. Implementations\n * of this class can un-mask a raw BitMatrix. For simplicity, they will unmask the entire BitMatrix,\n * including areas used for finder patterns, timing patterns, etc. These areas should be unused\n * after the point they are unmasked anyway.

\n *\n *

Note that the diagram in section 6.8.1 is misleading since it indicates that i is column position\n * and j is row position. In fact, as the text says, i is row position and j is column position.

\n *\n * @author Sean Owen\n */\n class DataMask {\n // See ISO 18004:2006 6.8.1\n constructor(value, isMasked) {\n this.value = value;\n this.isMasked = isMasked;\n }\n // End of enum constants.\n /**\n *

Implementations of this method reverse the data masking process applied to a QR Code and\n * make its bits ready to read.

\n *\n * @param bits representation of QR Code bits\n * @param dimension dimension of QR Code, represented by bits, being unmasked\n */\n unmaskBitMatrix(bits, dimension /*int*/) {\n for (let i = 0; i < dimension; i++) {\n for (let j = 0; j < dimension; j++) {\n if (this.isMasked(i, j)) {\n bits.flip(j, i);\n }\n }\n }\n }\n }\n DataMask.values = new Map([\n /**\n * 000: mask bits for which (x + y) mod 2 == 0\n */\n [DataMaskValues.DATA_MASK_000, new DataMask(DataMaskValues.DATA_MASK_000, (i /*int*/, j /*int*/) => { return ((i + j) & 0x01) === 0; })],\n /**\n * 001: mask bits for which x mod 2 == 0\n */\n [DataMaskValues.DATA_MASK_001, new DataMask(DataMaskValues.DATA_MASK_001, (i /*int*/, j /*int*/) => { return (i & 0x01) === 0; })],\n /**\n * 010: mask bits for which y mod 3 == 0\n */\n [DataMaskValues.DATA_MASK_010, new DataMask(DataMaskValues.DATA_MASK_010, (i /*int*/, j /*int*/) => { return j % 3 === 0; })],\n /**\n * 011: mask bits for which (x + y) mod 3 == 0\n */\n [DataMaskValues.DATA_MASK_011, new DataMask(DataMaskValues.DATA_MASK_011, (i /*int*/, j /*int*/) => { return (i + j) % 3 === 0; })],\n /**\n * 100: mask bits for which (x/2 + y/3) mod 2 == 0\n */\n [DataMaskValues.DATA_MASK_100, new DataMask(DataMaskValues.DATA_MASK_100, (i /*int*/, j /*int*/) => { return ((Math.floor(i / 2) + Math.floor(j / 3)) & 0x01) === 0; })],\n /**\n * 101: mask bits for which xy mod 2 + xy mod 3 == 0\n * equivalently, such that xy mod 6 == 0\n */\n [DataMaskValues.DATA_MASK_101, new DataMask(DataMaskValues.DATA_MASK_101, (i /*int*/, j /*int*/) => { return (i * j) % 6 === 0; })],\n /**\n * 110: mask bits for which (xy mod 2 + xy mod 3) mod 2 == 0\n * equivalently, such that xy mod 6 < 3\n */\n [DataMaskValues.DATA_MASK_110, new DataMask(DataMaskValues.DATA_MASK_110, (i /*int*/, j /*int*/) => { return ((i * j) % 6) < 3; })],\n /**\n * 111: mask bits for which ((x+y)mod 2 + xy mod 3) mod 2 == 0\n * equivalently, such that (x + y + xy mod 3) mod 2 == 0\n */\n [DataMaskValues.DATA_MASK_111, new DataMask(DataMaskValues.DATA_MASK_111, (i /*int*/, j /*int*/) => { return ((i + j + ((i * j) % 3)) & 0x01) === 0; })],\n ]);\n\n /*\n * Copyright 2007 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n /**\n * @author Sean Owen\n */\n class BitMatrixParser$1 {\n /**\n * @param bitMatrix {@link BitMatrix} to parse\n * @throws FormatException if dimension is not >= 21 and 1 mod 4\n */\n constructor(bitMatrix) {\n const dimension = bitMatrix.getHeight();\n if (dimension < 21 || (dimension & 0x03) !== 1) {\n throw new FormatException();\n }\n this.bitMatrix = bitMatrix;\n }\n /**\n *

Reads format information from one of its two locations within the QR Code.

\n *\n * @return {@link FormatInformation} encapsulating the QR Code's format info\n * @throws FormatException if both format information locations cannot be parsed as\n * the valid encoding of format information\n */\n readFormatInformation() {\n if (this.parsedFormatInfo !== null && this.parsedFormatInfo !== undefined) {\n return this.parsedFormatInfo;\n }\n // Read top-left format info bits\n let formatInfoBits1 = 0;\n for (let i = 0; i < 6; i++) {\n formatInfoBits1 = this.copyBit(i, 8, formatInfoBits1);\n }\n // .. and skip a bit in the timing pattern ...\n formatInfoBits1 = this.copyBit(7, 8, formatInfoBits1);\n formatInfoBits1 = this.copyBit(8, 8, formatInfoBits1);\n formatInfoBits1 = this.copyBit(8, 7, formatInfoBits1);\n // .. and skip a bit in the timing pattern ...\n for (let j = 5; j >= 0; j--) {\n formatInfoBits1 = this.copyBit(8, j, formatInfoBits1);\n }\n // Read the top-right/bottom-left pattern too\n const dimension = this.bitMatrix.getHeight();\n let formatInfoBits2 = 0;\n const jMin = dimension - 7;\n for (let j = dimension - 1; j >= jMin; j--) {\n formatInfoBits2 = this.copyBit(8, j, formatInfoBits2);\n }\n for (let i = dimension - 8; i < dimension; i++) {\n formatInfoBits2 = this.copyBit(i, 8, formatInfoBits2);\n }\n this.parsedFormatInfo = FormatInformation.decodeFormatInformation(formatInfoBits1, formatInfoBits2);\n if (this.parsedFormatInfo !== null) {\n return this.parsedFormatInfo;\n }\n throw new FormatException();\n }\n /**\n *

Reads version information from one of its two locations within the QR Code.

\n *\n * @return {@link Version} encapsulating the QR Code's version\n * @throws FormatException if both version information locations cannot be parsed as\n * the valid encoding of version information\n */\n readVersion() {\n if (this.parsedVersion !== null && this.parsedVersion !== undefined) {\n return this.parsedVersion;\n }\n const dimension = this.bitMatrix.getHeight();\n const provisionalVersion = Math.floor((dimension - 17) / 4);\n if (provisionalVersion <= 6) {\n return Version$1.getVersionForNumber(provisionalVersion);\n }\n // Read top-right version info: 3 wide by 6 tall\n let versionBits = 0;\n const ijMin = dimension - 11;\n for (let j = 5; j >= 0; j--) {\n for (let i = dimension - 9; i >= ijMin; i--) {\n versionBits = this.copyBit(i, j, versionBits);\n }\n }\n let theParsedVersion = Version$1.decodeVersionInformation(versionBits);\n if (theParsedVersion !== null && theParsedVersion.getDimensionForVersion() === dimension) {\n this.parsedVersion = theParsedVersion;\n return theParsedVersion;\n }\n // Hmm, failed. Try bottom left: 6 wide by 3 tall\n versionBits = 0;\n for (let i = 5; i >= 0; i--) {\n for (let j = dimension - 9; j >= ijMin; j--) {\n versionBits = this.copyBit(i, j, versionBits);\n }\n }\n theParsedVersion = Version$1.decodeVersionInformation(versionBits);\n if (theParsedVersion !== null && theParsedVersion.getDimensionForVersion() === dimension) {\n this.parsedVersion = theParsedVersion;\n return theParsedVersion;\n }\n throw new FormatException();\n }\n copyBit(i /*int*/, j /*int*/, versionBits /*int*/) {\n const bit = this.isMirror ? this.bitMatrix.get(j, i) : this.bitMatrix.get(i, j);\n return bit ? (versionBits << 1) | 0x1 : versionBits << 1;\n }\n /**\n *

Reads the bits in the {@link BitMatrix} representing the finder pattern in the\n * correct order in order to reconstruct the codewords bytes contained within the\n * QR Code.

\n *\n * @return bytes encoded within the QR Code\n * @throws FormatException if the exact number of bytes expected is not read\n */\n readCodewords() {\n const formatInfo = this.readFormatInformation();\n const version = this.readVersion();\n // Get the data mask for the format used in this QR Code. This will exclude\n // some bits from reading as we wind through the bit matrix.\n const dataMask = DataMask.values.get(formatInfo.getDataMask());\n const dimension = this.bitMatrix.getHeight();\n dataMask.unmaskBitMatrix(this.bitMatrix, dimension);\n const functionPattern = version.buildFunctionPattern();\n let readingUp = true;\n const result = new Uint8Array(version.getTotalCodewords());\n let resultOffset = 0;\n let currentByte = 0;\n let bitsRead = 0;\n // Read columns in pairs, from right to left\n for (let j = dimension - 1; j > 0; j -= 2) {\n if (j === 6) {\n // Skip whole column with vertical alignment pattern\n // saves time and makes the other code proceed more cleanly\n j--;\n }\n // Read alternatingly from bottom to top then top to bottom\n for (let count = 0; count < dimension; count++) {\n const i = readingUp ? dimension - 1 - count : count;\n for (let col = 0; col < 2; col++) {\n // Ignore bits covered by the function pattern\n if (!functionPattern.get(j - col, i)) {\n // Read a bit\n bitsRead++;\n currentByte <<= 1;\n if (this.bitMatrix.get(j - col, i)) {\n currentByte |= 1;\n }\n // If we've made a whole byte, save it off\n if (bitsRead === 8) {\n result[resultOffset++] = /*(byte) */ currentByte;\n bitsRead = 0;\n currentByte = 0;\n }\n }\n }\n }\n readingUp = !readingUp; // readingUp ^= true; // readingUp = !readingUp; // switch directions\n }\n if (resultOffset !== version.getTotalCodewords()) {\n throw new FormatException();\n }\n return result;\n }\n /**\n * Revert the mask removal done while reading the code words. The bit matrix should revert to its original state.\n */\n remask() {\n if (this.parsedFormatInfo === null) {\n return; // We have no format information, and have no data mask\n }\n const dataMask = DataMask.values[this.parsedFormatInfo.getDataMask()];\n const dimension = this.bitMatrix.getHeight();\n dataMask.unmaskBitMatrix(this.bitMatrix, dimension);\n }\n /**\n * Prepare the parser for a mirrored operation.\n * This flag has effect only on the {@link #readFormatInformation()} and the\n * {@link #readVersion()}. Before proceeding with {@link #readCodewords()} the\n * {@link #mirror()} method should be called.\n *\n * @param mirror Whether to read version and format information mirrored.\n */\n setMirror(isMirror) {\n this.parsedVersion = null;\n this.parsedFormatInfo = null;\n this.isMirror = isMirror;\n }\n /** Mirror the bit matrix in order to attempt a second reading. */\n mirror() {\n const bitMatrix = this.bitMatrix;\n for (let x = 0, width = bitMatrix.getWidth(); x < width; x++) {\n for (let y = x + 1, height = bitMatrix.getHeight(); y < height; y++) {\n if (bitMatrix.get(x, y) !== bitMatrix.get(y, x)) {\n bitMatrix.flip(y, x);\n bitMatrix.flip(x, y);\n }\n }\n }\n }\n }\n\n /*\n * Copyright 2007 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n /**\n *

Encapsulates a block of data within a QR Code. QR Codes may split their data into\n * multiple blocks, each of which is a unit of data and error-correction codewords. Each\n * is represented by an instance of this class.

\n *\n * @author Sean Owen\n */\n class DataBlock$1 {\n constructor(numDataCodewords /*int*/, codewords) {\n this.numDataCodewords = numDataCodewords;\n this.codewords = codewords;\n }\n /**\n *

When QR Codes use multiple data blocks, they are actually interleaved.\n * That is, the first byte of data block 1 to n is written, then the second bytes, and so on. This\n * method will separate the data into original blocks.

\n *\n * @param rawCodewords bytes as read directly from the QR Code\n * @param version version of the QR Code\n * @param ecLevel error-correction level of the QR Code\n * @return DataBlocks containing original bytes, \"de-interleaved\" from representation in the\n * QR Code\n */\n static getDataBlocks(rawCodewords, version, ecLevel) {\n if (rawCodewords.length !== version.getTotalCodewords()) {\n throw new IllegalArgumentException();\n }\n // Figure out the number and size of data blocks used by this version and\n // error correction level\n const ecBlocks = version.getECBlocksForLevel(ecLevel);\n // First count the total number of data blocks\n let totalBlocks = 0;\n const ecBlockArray = ecBlocks.getECBlocks();\n for (const ecBlock of ecBlockArray) {\n totalBlocks += ecBlock.getCount();\n }\n // Now establish DataBlocks of the appropriate size and number of data codewords\n const result = new Array(totalBlocks);\n let numResultBlocks = 0;\n for (const ecBlock of ecBlockArray) {\n for (let i = 0; i < ecBlock.getCount(); i++) {\n const numDataCodewords = ecBlock.getDataCodewords();\n const numBlockCodewords = ecBlocks.getECCodewordsPerBlock() + numDataCodewords;\n result[numResultBlocks++] = new DataBlock$1(numDataCodewords, new Uint8Array(numBlockCodewords));\n }\n }\n // All blocks have the same amount of data, except that the last n\n // (where n may be 0) have 1 more byte. Figure out where these start.\n const shorterBlocksTotalCodewords = result[0].codewords.length;\n let longerBlocksStartAt = result.length - 1;\n // TYPESCRIPTPORT: check length is correct here\n while (longerBlocksStartAt >= 0) {\n const numCodewords = result[longerBlocksStartAt].codewords.length;\n if (numCodewords === shorterBlocksTotalCodewords) {\n break;\n }\n longerBlocksStartAt--;\n }\n longerBlocksStartAt++;\n const shorterBlocksNumDataCodewords = shorterBlocksTotalCodewords - ecBlocks.getECCodewordsPerBlock();\n // The last elements of result may be 1 element longer\n // first fill out as many elements as all of them have\n let rawCodewordsOffset = 0;\n for (let i = 0; i < shorterBlocksNumDataCodewords; i++) {\n for (let j = 0; j < numResultBlocks; j++) {\n result[j].codewords[i] = rawCodewords[rawCodewordsOffset++];\n }\n }\n // Fill out the last data block in the longer ones\n for (let j = longerBlocksStartAt; j < numResultBlocks; j++) {\n result[j].codewords[shorterBlocksNumDataCodewords] = rawCodewords[rawCodewordsOffset++];\n }\n // Now add in error correction blocks\n const max = result[0].codewords.length;\n for (let i = shorterBlocksNumDataCodewords; i < max; i++) {\n for (let j = 0; j < numResultBlocks; j++) {\n const iOffset = j < longerBlocksStartAt ? i : i + 1;\n result[j].codewords[iOffset] = rawCodewords[rawCodewordsOffset++];\n }\n }\n return result;\n }\n getNumDataCodewords() {\n return this.numDataCodewords;\n }\n getCodewords() {\n return this.codewords;\n }\n }\n\n /*\n * Copyright 2007 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n var ModeValues;\n (function (ModeValues) {\n ModeValues[ModeValues[\"TERMINATOR\"] = 0] = \"TERMINATOR\";\n ModeValues[ModeValues[\"NUMERIC\"] = 1] = \"NUMERIC\";\n ModeValues[ModeValues[\"ALPHANUMERIC\"] = 2] = \"ALPHANUMERIC\";\n ModeValues[ModeValues[\"STRUCTURED_APPEND\"] = 3] = \"STRUCTURED_APPEND\";\n ModeValues[ModeValues[\"BYTE\"] = 4] = \"BYTE\";\n ModeValues[ModeValues[\"ECI\"] = 5] = \"ECI\";\n ModeValues[ModeValues[\"KANJI\"] = 6] = \"KANJI\";\n ModeValues[ModeValues[\"FNC1_FIRST_POSITION\"] = 7] = \"FNC1_FIRST_POSITION\";\n ModeValues[ModeValues[\"FNC1_SECOND_POSITION\"] = 8] = \"FNC1_SECOND_POSITION\";\n /** See GBT 18284-2000; \"Hanzi\" is a transliteration of this mode name. */\n ModeValues[ModeValues[\"HANZI\"] = 9] = \"HANZI\";\n })(ModeValues || (ModeValues = {}));\n /**\n *

See ISO 18004:2006, 6.4.1, Tables 2 and 3. This enum encapsulates the various modes in which\n * data can be encoded to bits in the QR code standard.

\n *\n * @author Sean Owen\n */\n class Mode$1 {\n constructor(value, stringValue, characterCountBitsForVersions, bits /*int*/) {\n this.value = value;\n this.stringValue = stringValue;\n this.characterCountBitsForVersions = characterCountBitsForVersions;\n this.bits = bits;\n Mode$1.FOR_BITS.set(bits, this);\n Mode$1.FOR_VALUE.set(value, this);\n }\n /**\n * @param bits four bits encoding a QR Code data mode\n * @return Mode encoded by these bits\n * @throws IllegalArgumentException if bits do not correspond to a known mode\n */\n static forBits(bits /*int*/) {\n const mode = Mode$1.FOR_BITS.get(bits);\n if (undefined === mode) {\n throw new IllegalArgumentException();\n }\n return mode;\n }\n /**\n * @param version version in question\n * @return number of bits used, in this QR Code symbol {@link Version}, to encode the\n * count of characters that will follow encoded in this Mode\n */\n getCharacterCountBits(version) {\n const versionNumber = version.getVersionNumber();\n let offset;\n if (versionNumber <= 9) {\n offset = 0;\n }\n else if (versionNumber <= 26) {\n offset = 1;\n }\n else {\n offset = 2;\n }\n return this.characterCountBitsForVersions[offset];\n }\n getValue() {\n return this.value;\n }\n getBits() {\n return this.bits;\n }\n equals(o) {\n if (!(o instanceof Mode$1)) {\n return false;\n }\n const other = o;\n return this.value === other.value;\n }\n toString() {\n return this.stringValue;\n }\n }\n Mode$1.FOR_BITS = new Map();\n Mode$1.FOR_VALUE = new Map();\n Mode$1.TERMINATOR = new Mode$1(ModeValues.TERMINATOR, 'TERMINATOR', Int32Array.from([0, 0, 0]), 0x00); // Not really a mode...\n Mode$1.NUMERIC = new Mode$1(ModeValues.NUMERIC, 'NUMERIC', Int32Array.from([10, 12, 14]), 0x01);\n Mode$1.ALPHANUMERIC = new Mode$1(ModeValues.ALPHANUMERIC, 'ALPHANUMERIC', Int32Array.from([9, 11, 13]), 0x02);\n Mode$1.STRUCTURED_APPEND = new Mode$1(ModeValues.STRUCTURED_APPEND, 'STRUCTURED_APPEND', Int32Array.from([0, 0, 0]), 0x03); // Not supported\n Mode$1.BYTE = new Mode$1(ModeValues.BYTE, 'BYTE', Int32Array.from([8, 16, 16]), 0x04);\n Mode$1.ECI = new Mode$1(ModeValues.ECI, 'ECI', Int32Array.from([0, 0, 0]), 0x07); // character counts don't apply\n Mode$1.KANJI = new Mode$1(ModeValues.KANJI, 'KANJI', Int32Array.from([8, 10, 12]), 0x08);\n Mode$1.FNC1_FIRST_POSITION = new Mode$1(ModeValues.FNC1_FIRST_POSITION, 'FNC1_FIRST_POSITION', Int32Array.from([0, 0, 0]), 0x05);\n Mode$1.FNC1_SECOND_POSITION = new Mode$1(ModeValues.FNC1_SECOND_POSITION, 'FNC1_SECOND_POSITION', Int32Array.from([0, 0, 0]), 0x09);\n /** See GBT 18284-2000; \"Hanzi\" is a transliteration of this mode name. */\n Mode$1.HANZI = new Mode$1(ModeValues.HANZI, 'HANZI', Int32Array.from([8, 10, 12]), 0x0D);\n\n /*\n * Copyright 2007 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n /*import java.io.UnsupportedEncodingException;*/\n /*import java.util.ArrayList;*/\n /*import java.util.Collection;*/\n /*import java.util.List;*/\n /*import java.util.Map;*/\n /**\n *

QR Codes can encode text as bits in one of several modes, and can use multiple modes\n * in one QR Code. This class decodes the bits back into text.

\n *\n *

See ISO 18004:2006, 6.4.3 - 6.4.7

\n *\n * @author Sean Owen\n */\n class DecodedBitStreamParser$1 {\n static decode(bytes, version, ecLevel, hints) {\n const bits = new BitSource(bytes);\n let result = new StringBuilder();\n const byteSegments = new Array(); // 1\n // TYPESCRIPTPORT: I do not use constructor with size 1 as in original Java means capacity and the array length is checked below\n let symbolSequence = -1;\n let parityData = -1;\n try {\n let currentCharacterSetECI = null;\n let fc1InEffect = false;\n let mode;\n do {\n // While still another segment to read...\n if (bits.available() < 4) {\n // OK, assume we're done. Really, a TERMINATOR mode should have been recorded here\n mode = Mode$1.TERMINATOR;\n }\n else {\n const modeBits = bits.readBits(4);\n mode = Mode$1.forBits(modeBits); // mode is encoded by 4 bits\n }\n switch (mode) {\n case Mode$1.TERMINATOR:\n break;\n case Mode$1.FNC1_FIRST_POSITION:\n case Mode$1.FNC1_SECOND_POSITION:\n // We do little with FNC1 except alter the parsed result a bit according to the spec\n fc1InEffect = true;\n break;\n case Mode$1.STRUCTURED_APPEND:\n if (bits.available() < 16) {\n throw new FormatException();\n }\n // sequence number and parity is added later to the result metadata\n // Read next 8 bits (symbol sequence #) and 8 bits (data: parity), then continue\n symbolSequence = bits.readBits(8);\n parityData = bits.readBits(8);\n break;\n case Mode$1.ECI:\n // Count doesn't apply to ECI\n const value = DecodedBitStreamParser$1.parseECIValue(bits);\n currentCharacterSetECI = CharacterSetECI.getCharacterSetECIByValue(value);\n if (currentCharacterSetECI === null) {\n throw new FormatException();\n }\n break;\n case Mode$1.HANZI:\n // First handle Hanzi mode which does not start with character count\n // Chinese mode contains a sub set indicator right after mode indicator\n const subset = bits.readBits(4);\n const countHanzi = bits.readBits(mode.getCharacterCountBits(version));\n if (subset === DecodedBitStreamParser$1.GB2312_SUBSET) {\n DecodedBitStreamParser$1.decodeHanziSegment(bits, result, countHanzi);\n }\n break;\n default:\n // \"Normal\" QR code modes:\n // How many characters will follow, encoded in this mode?\n const count = bits.readBits(mode.getCharacterCountBits(version));\n switch (mode) {\n case Mode$1.NUMERIC:\n DecodedBitStreamParser$1.decodeNumericSegment(bits, result, count);\n break;\n case Mode$1.ALPHANUMERIC:\n DecodedBitStreamParser$1.decodeAlphanumericSegment(bits, result, count, fc1InEffect);\n break;\n case Mode$1.BYTE:\n DecodedBitStreamParser$1.decodeByteSegment(bits, result, count, currentCharacterSetECI, byteSegments, hints);\n break;\n case Mode$1.KANJI:\n DecodedBitStreamParser$1.decodeKanjiSegment(bits, result, count);\n break;\n default:\n throw new FormatException();\n }\n break;\n }\n } while (mode !== Mode$1.TERMINATOR);\n }\n catch (iae /*: IllegalArgumentException*/) {\n // from readBits() calls\n throw new FormatException();\n }\n return new DecoderResult(bytes, result.toString(), byteSegments.length === 0 ? null : byteSegments, ecLevel === null ? null : ecLevel.toString(), symbolSequence, parityData);\n }\n /**\n * See specification GBT 18284-2000\n */\n static decodeHanziSegment(bits, result, count /*int*/) {\n // Don't crash trying to read more bits than we have available.\n if (count * 13 > bits.available()) {\n throw new FormatException();\n }\n // Each character will require 2 bytes. Read the characters as 2-byte pairs\n // and decode as GB2312 afterwards\n const buffer = new Uint8Array(2 * count);\n let offset = 0;\n while (count > 0) {\n // Each 13 bits encodes a 2-byte character\n const twoBytes = bits.readBits(13);\n let assembledTwoBytes = (((twoBytes / 0x060) << 8) & 0xFFFFFFFF) | (twoBytes % 0x060);\n if (assembledTwoBytes < 0x003BF) {\n // In the 0xA1A1 to 0xAAFE range\n assembledTwoBytes += 0x0A1A1;\n }\n else {\n // In the 0xB0A1 to 0xFAFE range\n assembledTwoBytes += 0x0A6A1;\n }\n buffer[offset] = /*(byte) */ ((assembledTwoBytes >> 8) & 0xFF);\n buffer[offset + 1] = /*(byte) */ (assembledTwoBytes & 0xFF);\n offset += 2;\n count--;\n }\n try {\n result.append(StringEncoding.decode(buffer, StringUtils.GB2312));\n // TYPESCRIPTPORT: TODO: implement GB2312 decode. StringView from MDN could be a starting point\n }\n catch (ignored /*: UnsupportedEncodingException*/) {\n throw new FormatException(ignored);\n }\n }\n static decodeKanjiSegment(bits, result, count /*int*/) {\n // Don't crash trying to read more bits than we have available.\n if (count * 13 > bits.available()) {\n throw new FormatException();\n }\n // Each character will require 2 bytes. Read the characters as 2-byte pairs\n // and decode as Shift_JIS afterwards\n const buffer = new Uint8Array(2 * count);\n let offset = 0;\n while (count > 0) {\n // Each 13 bits encodes a 2-byte character\n const twoBytes = bits.readBits(13);\n let assembledTwoBytes = (((twoBytes / 0x0C0) << 8) & 0xFFFFFFFF) | (twoBytes % 0x0C0);\n if (assembledTwoBytes < 0x01F00) {\n // In the 0x8140 to 0x9FFC range\n assembledTwoBytes += 0x08140;\n }\n else {\n // In the 0xE040 to 0xEBBF range\n assembledTwoBytes += 0x0C140;\n }\n buffer[offset] = /*(byte) */ (assembledTwoBytes >> 8);\n buffer[offset + 1] = /*(byte) */ assembledTwoBytes;\n offset += 2;\n count--;\n }\n // Shift_JIS may not be supported in some environments:\n try {\n result.append(StringEncoding.decode(buffer, StringUtils.SHIFT_JIS));\n // TYPESCRIPTPORT: TODO: implement SHIFT_JIS decode. StringView from MDN could be a starting point\n }\n catch (ignored /*: UnsupportedEncodingException*/) {\n throw new FormatException(ignored);\n }\n }\n static decodeByteSegment(bits, result, count /*int*/, currentCharacterSetECI, byteSegments, hints) {\n // Don't crash trying to read more bits than we have available.\n if (8 * count > bits.available()) {\n throw new FormatException();\n }\n const readBytes = new Uint8Array(count);\n for (let i = 0; i < count; i++) {\n readBytes[i] = /*(byte) */ bits.readBits(8);\n }\n let encoding;\n if (currentCharacterSetECI === null) {\n // The spec isn't clear on this mode; see\n // section 6.4.5: t does not say which encoding to assuming\n // upon decoding. I have seen ISO-8859-1 used as well as\n // Shift_JIS -- without anything like an ECI designator to\n // give a hint.\n encoding = StringUtils.guessEncoding(readBytes, hints);\n }\n else {\n encoding = currentCharacterSetECI.getName();\n }\n try {\n result.append(StringEncoding.decode(readBytes, encoding));\n }\n catch (ignored /*: UnsupportedEncodingException*/) {\n throw new FormatException(ignored);\n }\n byteSegments.push(readBytes);\n }\n static toAlphaNumericChar(value /*int*/) {\n if (value >= DecodedBitStreamParser$1.ALPHANUMERIC_CHARS.length) {\n throw new FormatException();\n }\n return DecodedBitStreamParser$1.ALPHANUMERIC_CHARS[value];\n }\n static decodeAlphanumericSegment(bits, result, count /*int*/, fc1InEffect) {\n // Read two characters at a time\n const start = result.length();\n while (count > 1) {\n if (bits.available() < 11) {\n throw new FormatException();\n }\n const nextTwoCharsBits = bits.readBits(11);\n result.append(DecodedBitStreamParser$1.toAlphaNumericChar(Math.floor(nextTwoCharsBits / 45)));\n result.append(DecodedBitStreamParser$1.toAlphaNumericChar(nextTwoCharsBits % 45));\n count -= 2;\n }\n if (count === 1) {\n // special case: one character left\n if (bits.available() < 6) {\n throw new FormatException();\n }\n result.append(DecodedBitStreamParser$1.toAlphaNumericChar(bits.readBits(6)));\n }\n // See section 6.4.8.1, 6.4.8.2\n if (fc1InEffect) {\n // We need to massage the result a bit if in an FNC1 mode:\n for (let i = start; i < result.length(); i++) {\n if (result.charAt(i) === '%') {\n if (i < result.length() - 1 && result.charAt(i + 1) === '%') {\n // %% is rendered as %\n result.deleteCharAt(i + 1);\n }\n else {\n // In alpha mode, % should be converted to FNC1 separator 0x1D\n result.setCharAt(i, String.fromCharCode(0x1D));\n }\n }\n }\n }\n }\n static decodeNumericSegment(bits, result, count /*int*/) {\n // Read three digits at a time\n while (count >= 3) {\n // Each 10 bits encodes three digits\n if (bits.available() < 10) {\n throw new FormatException();\n }\n const threeDigitsBits = bits.readBits(10);\n if (threeDigitsBits >= 1000) {\n throw new FormatException();\n }\n result.append(DecodedBitStreamParser$1.toAlphaNumericChar(Math.floor(threeDigitsBits / 100)));\n result.append(DecodedBitStreamParser$1.toAlphaNumericChar(Math.floor(threeDigitsBits / 10) % 10));\n result.append(DecodedBitStreamParser$1.toAlphaNumericChar(threeDigitsBits % 10));\n count -= 3;\n }\n if (count === 2) {\n // Two digits left over to read, encoded in 7 bits\n if (bits.available() < 7) {\n throw new FormatException();\n }\n const twoDigitsBits = bits.readBits(7);\n if (twoDigitsBits >= 100) {\n throw new FormatException();\n }\n result.append(DecodedBitStreamParser$1.toAlphaNumericChar(Math.floor(twoDigitsBits / 10)));\n result.append(DecodedBitStreamParser$1.toAlphaNumericChar(twoDigitsBits % 10));\n }\n else if (count === 1) {\n // One digit left over to read\n if (bits.available() < 4) {\n throw new FormatException();\n }\n const digitBits = bits.readBits(4);\n if (digitBits >= 10) {\n throw new FormatException();\n }\n result.append(DecodedBitStreamParser$1.toAlphaNumericChar(digitBits));\n }\n }\n static parseECIValue(bits) {\n const firstByte = bits.readBits(8);\n if ((firstByte & 0x80) === 0) {\n // just one byte\n return firstByte & 0x7F;\n }\n if ((firstByte & 0xC0) === 0x80) {\n // two bytes\n const secondByte = bits.readBits(8);\n return (((firstByte & 0x3F) << 8) & 0xFFFFFFFF) | secondByte;\n }\n if ((firstByte & 0xE0) === 0xC0) {\n // three bytes\n const secondThirdBytes = bits.readBits(16);\n return (((firstByte & 0x1F) << 16) & 0xFFFFFFFF) | secondThirdBytes;\n }\n throw new FormatException();\n }\n }\n /**\n * See ISO 18004:2006, 6.4.4 Table 5\n */\n DecodedBitStreamParser$1.ALPHANUMERIC_CHARS = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./:';\n DecodedBitStreamParser$1.GB2312_SUBSET = 1;\n // function Uint8ArrayToString(a: Uint8Array): string {\n // const CHUNK_SZ = 0x8000;\n // const c = new StringBuilder();\n // for (let i = 0, length = a.length; i < length; i += CHUNK_SZ) {\n // c.append(String.fromCharCode.apply(null, a.subarray(i, i + CHUNK_SZ)));\n // }\n // return c.toString();\n // }\n\n /*\n * Copyright 2013 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n /**\n * Meta-data container for QR Code decoding. Instances of this class may be used to convey information back to the\n * decoding caller. Callers are expected to process this.\n *\n * @see com.google.zxing.common.DecoderResult#getOther()\n */\n class QRCodeDecoderMetaData {\n constructor(mirrored) {\n this.mirrored = mirrored;\n }\n /**\n * @return true if the QR Code was mirrored.\n */\n isMirrored() {\n return this.mirrored;\n }\n /**\n * Apply the result points' order correction due to mirroring.\n *\n * @param points Array of points to apply mirror correction to.\n */\n applyMirroredCorrection(points) {\n if (!this.mirrored || points === null || points.length < 3) {\n return;\n }\n const bottomLeft = points[0];\n points[0] = points[2];\n points[2] = bottomLeft;\n // No need to 'fix' top-left and alignment pattern.\n }\n }\n\n /*\n * Copyright 2007 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n /*import java.util.Map;*/\n /**\n *

The main class which implements QR Code decoding -- as opposed to locating and extracting\n * the QR Code from an image.

\n *\n * @author Sean Owen\n */\n class Decoder$2 {\n constructor() {\n this.rsDecoder = new ReedSolomonDecoder(GenericGF.QR_CODE_FIELD_256);\n }\n // public decode(image: boolean[][]): DecoderResult /*throws ChecksumException, FormatException*/ {\n // return decode(image, null)\n // }\n /**\n *

Convenience method that can decode a QR Code represented as a 2D array of booleans.\n * \"true\" is taken to mean a black module.

\n *\n * @param image booleans representing white/black QR Code modules\n * @param hints decoding hints that should be used to influence decoding\n * @return text and bytes encoded within the QR Code\n * @throws FormatException if the QR Code cannot be decoded\n * @throws ChecksumException if error correction fails\n */\n decodeBooleanArray(image, hints) {\n return this.decodeBitMatrix(BitMatrix.parseFromBooleanArray(image), hints);\n }\n // public decodeBitMatrix(bits: BitMatrix): DecoderResult /*throws ChecksumException, FormatException*/ {\n // return decode(bits, null)\n // }\n /**\n *

Decodes a QR Code represented as a {@link BitMatrix}. A 1 or \"true\" is taken to mean a black module.

\n *\n * @param bits booleans representing white/black QR Code modules\n * @param hints decoding hints that should be used to influence decoding\n * @return text and bytes encoded within the QR Code\n * @throws FormatException if the QR Code cannot be decoded\n * @throws ChecksumException if error correction fails\n */\n decodeBitMatrix(bits, hints) {\n // Construct a parser and read version, error-correction level\n const parser = new BitMatrixParser$1(bits);\n let ex = null;\n try {\n return this.decodeBitMatrixParser(parser, hints);\n }\n catch (e /*: FormatException, ChecksumException*/) {\n ex = e;\n }\n try {\n // Revert the bit matrix\n parser.remask();\n // Will be attempting a mirrored reading of the version and format info.\n parser.setMirror(true);\n // Preemptively read the version.\n parser.readVersion();\n // Preemptively read the format information.\n parser.readFormatInformation();\n /*\n * Since we're here, this means we have successfully detected some kind\n * of version and format information when mirrored. This is a good sign,\n * that the QR code may be mirrored, and we should try once more with a\n * mirrored content.\n */\n // Prepare for a mirrored reading.\n parser.mirror();\n const result = this.decodeBitMatrixParser(parser, hints);\n // Success! Notify the caller that the code was mirrored.\n result.setOther(new QRCodeDecoderMetaData(true));\n return result;\n }\n catch (e /*FormatException | ChecksumException*/) {\n // Throw the exception from the original reading\n if (ex !== null) {\n throw ex;\n }\n throw e;\n }\n }\n decodeBitMatrixParser(parser, hints) {\n const version = parser.readVersion();\n const ecLevel = parser.readFormatInformation().getErrorCorrectionLevel();\n // Read codewords\n const codewords = parser.readCodewords();\n // Separate into data blocks\n const dataBlocks = DataBlock$1.getDataBlocks(codewords, version, ecLevel);\n // Count total number of data bytes\n let totalBytes = 0;\n for (const dataBlock of dataBlocks) {\n totalBytes += dataBlock.getNumDataCodewords();\n }\n const resultBytes = new Uint8Array(totalBytes);\n let resultOffset = 0;\n // Error-correct and copy data blocks together into a stream of bytes\n for (const dataBlock of dataBlocks) {\n const codewordBytes = dataBlock.getCodewords();\n const numDataCodewords = dataBlock.getNumDataCodewords();\n this.correctErrors(codewordBytes, numDataCodewords);\n for (let i = 0; i < numDataCodewords; i++) {\n resultBytes[resultOffset++] = codewordBytes[i];\n }\n }\n // Decode the contents of that stream of bytes\n return DecodedBitStreamParser$1.decode(resultBytes, version, ecLevel, hints);\n }\n /**\n *

Given data and error-correction codewords received, possibly corrupted by errors, attempts to\n * correct the errors in-place using Reed-Solomon error correction.

\n *\n * @param codewordBytes data and error correction codewords\n * @param numDataCodewords number of codewords that are data bytes\n * @throws ChecksumException if error correction fails\n */\n correctErrors(codewordBytes, numDataCodewords /*int*/) {\n // const numCodewords = codewordBytes.length;\n // First read into an array of ints\n const codewordsInts = new Int32Array(codewordBytes);\n // TYPESCRIPTPORT: not realy necessary to transform to ints? could redesign everything to work with unsigned bytes?\n // const codewordsInts = new Int32Array(numCodewords)\n // for (let i = 0; i < numCodewords; i++) {\n // codewordsInts[i] = codewordBytes[i] & 0xFF\n // }\n try {\n this.rsDecoder.decode(codewordsInts, codewordBytes.length - numDataCodewords);\n }\n catch (ignored /*: ReedSolomonException*/) {\n throw new ChecksumException();\n }\n // Copy back into array of bytes -- only need to worry about the bytes that were data\n // We don't care about errors in the error-correction codewords\n for (let i = 0; i < numDataCodewords; i++) {\n codewordBytes[i] = /*(byte) */ codewordsInts[i];\n }\n }\n }\n\n /*\n * Copyright 2007 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n /**\n *

Encapsulates an alignment pattern, which are the smaller square patterns found in\n * all but the simplest QR Codes.

\n *\n * @author Sean Owen\n */\n class AlignmentPattern extends ResultPoint {\n constructor(posX /*float*/, posY /*float*/, estimatedModuleSize /*float*/) {\n super(posX, posY);\n this.estimatedModuleSize = estimatedModuleSize;\n }\n /**\n *

Determines if this alignment pattern \"about equals\" an alignment pattern at the stated\n * position and size -- meaning, it is at nearly the same center with nearly the same size.

\n */\n aboutEquals(moduleSize /*float*/, i /*float*/, j /*float*/) {\n if (Math.abs(i - this.getY()) <= moduleSize && Math.abs(j - this.getX()) <= moduleSize) {\n const moduleSizeDiff = Math.abs(moduleSize - this.estimatedModuleSize);\n return moduleSizeDiff <= 1.0 || moduleSizeDiff <= this.estimatedModuleSize;\n }\n return false;\n }\n /**\n * Combines this object's current estimate of a finder pattern position and module size\n * with a new estimate. It returns a new {@code FinderPattern} containing an average of the two.\n */\n combineEstimate(i /*float*/, j /*float*/, newModuleSize /*float*/) {\n const combinedX = (this.getX() + j) / 2.0;\n const combinedY = (this.getY() + i) / 2.0;\n const combinedModuleSize = (this.estimatedModuleSize + newModuleSize) / 2.0;\n return new AlignmentPattern(combinedX, combinedY, combinedModuleSize);\n }\n }\n\n /*\n * Copyright 2007 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n /*import java.util.ArrayList;*/\n /*import java.util.List;*/\n /**\n *

This class attempts to find alignment patterns in a QR Code. Alignment patterns look like finder\n * patterns but are smaller and appear at regular intervals throughout the image.

\n *\n *

At the moment this only looks for the bottom-right alignment pattern.

\n *\n *

This is mostly a simplified copy of {@link FinderPatternFinder}. It is copied,\n * pasted and stripped down here for maximum performance but does unfortunately duplicate\n * some code.

\n *\n *

This class is thread-safe but not reentrant. Each thread must allocate its own object.

\n *\n * @author Sean Owen\n */\n class AlignmentPatternFinder {\n /**\n *

Creates a finder that will look in a portion of the whole image.

\n *\n * @param image image to search\n * @param startX left column from which to start searching\n * @param startY top row from which to start searching\n * @param width width of region to search\n * @param height height of region to search\n * @param moduleSize estimated module size so far\n */\n constructor(image, startX /*int*/, startY /*int*/, width /*int*/, height /*int*/, moduleSize /*float*/, resultPointCallback) {\n this.image = image;\n this.startX = startX;\n this.startY = startY;\n this.width = width;\n this.height = height;\n this.moduleSize = moduleSize;\n this.resultPointCallback = resultPointCallback;\n this.possibleCenters = []; // new Array(5))\n // TYPESCRIPTPORT: array initialization without size as the length is checked below\n this.crossCheckStateCount = new Int32Array(3);\n }\n /**\n *

This method attempts to find the bottom-right alignment pattern in the image. It is a bit messy since\n * it's pretty performance-critical and so is written to be fast foremost.

\n *\n * @return {@link AlignmentPattern} if found\n * @throws NotFoundException if not found\n */\n find() {\n const startX = this.startX;\n const height = this.height;\n const width = this.width;\n const maxJ = startX + width;\n const middleI = this.startY + (height / 2);\n // We are looking for black/white/black modules in 1:1:1 ratio\n // this tracks the number of black/white/black modules seen so far\n const stateCount = new Int32Array(3);\n const image = this.image;\n for (let iGen = 0; iGen < height; iGen++) {\n // Search from middle outwards\n const i = middleI + ((iGen & 0x01) === 0 ? Math.floor((iGen + 1) / 2) : -Math.floor((iGen + 1) / 2));\n stateCount[0] = 0;\n stateCount[1] = 0;\n stateCount[2] = 0;\n let j = startX;\n // Burn off leading white pixels before anything else; if we start in the middle of\n // a white run, it doesn't make sense to count its length, since we don't know if the\n // white run continued to the left of the start point\n while (j < maxJ && !image.get(j, i)) {\n j++;\n }\n let currentState = 0;\n while (j < maxJ) {\n if (image.get(j, i)) {\n // Black pixel\n if (currentState === 1) { // Counting black pixels\n stateCount[1]++;\n }\n else { // Counting white pixels\n if (currentState === 2) { // A winner?\n if (this.foundPatternCross(stateCount)) { // Yes\n const confirmed = this.handlePossibleCenter(stateCount, i, j);\n if (confirmed !== null) {\n return confirmed;\n }\n }\n stateCount[0] = stateCount[2];\n stateCount[1] = 1;\n stateCount[2] = 0;\n currentState = 1;\n }\n else {\n stateCount[++currentState]++;\n }\n }\n }\n else { // White pixel\n if (currentState === 1) { // Counting black pixels\n currentState++;\n }\n stateCount[currentState]++;\n }\n j++;\n }\n if (this.foundPatternCross(stateCount)) {\n const confirmed = this.handlePossibleCenter(stateCount, i, maxJ);\n if (confirmed !== null) {\n return confirmed;\n }\n }\n }\n // Hmm, nothing we saw was observed and confirmed twice. If we had\n // any guess at all, return it.\n if (this.possibleCenters.length !== 0) {\n return this.possibleCenters[0];\n }\n throw new NotFoundException();\n }\n /**\n * Given a count of black/white/black pixels just seen and an end position,\n * figures the location of the center of this black/white/black run.\n */\n static centerFromEnd(stateCount, end /*int*/) {\n return (end - stateCount[2]) - stateCount[1] / 2.0;\n }\n /**\n * @param stateCount count of black/white/black pixels just read\n * @return true iff the proportions of the counts is close enough to the 1/1/1 ratios\n * used by alignment patterns to be considered a match\n */\n foundPatternCross(stateCount) {\n const moduleSize = this.moduleSize;\n const maxVariance = moduleSize / 2.0;\n for (let i = 0; i < 3; i++) {\n if (Math.abs(moduleSize - stateCount[i]) >= maxVariance) {\n return false;\n }\n }\n return true;\n }\n /**\n *

After a horizontal scan finds a potential alignment pattern, this method\n * \"cross-checks\" by scanning down vertically through the center of the possible\n * alignment pattern to see if the same proportion is detected.

\n *\n * @param startI row where an alignment pattern was detected\n * @param centerJ center of the section that appears to cross an alignment pattern\n * @param maxCount maximum reasonable number of modules that should be\n * observed in any reading state, based on the results of the horizontal scan\n * @return vertical center of alignment pattern, or {@link Float#NaN} if not found\n */\n crossCheckVertical(startI /*int*/, centerJ /*int*/, maxCount /*int*/, originalStateCountTotal /*int*/) {\n const image = this.image;\n const maxI = image.getHeight();\n const stateCount = this.crossCheckStateCount;\n stateCount[0] = 0;\n stateCount[1] = 0;\n stateCount[2] = 0;\n // Start counting up from center\n let i = startI;\n while (i >= 0 && image.get(centerJ, i) && stateCount[1] <= maxCount) {\n stateCount[1]++;\n i--;\n }\n // If already too many modules in this state or ran off the edge:\n if (i < 0 || stateCount[1] > maxCount) {\n return NaN;\n }\n while (i >= 0 && !image.get(centerJ, i) && stateCount[0] <= maxCount) {\n stateCount[0]++;\n i--;\n }\n if (stateCount[0] > maxCount) {\n return NaN;\n }\n // Now also count down from center\n i = startI + 1;\n while (i < maxI && image.get(centerJ, i) && stateCount[1] <= maxCount) {\n stateCount[1]++;\n i++;\n }\n if (i === maxI || stateCount[1] > maxCount) {\n return NaN;\n }\n while (i < maxI && !image.get(centerJ, i) && stateCount[2] <= maxCount) {\n stateCount[2]++;\n i++;\n }\n if (stateCount[2] > maxCount) {\n return NaN;\n }\n const stateCountTotal = stateCount[0] + stateCount[1] + stateCount[2];\n if (5 * Math.abs(stateCountTotal - originalStateCountTotal) >= 2 * originalStateCountTotal) {\n return NaN;\n }\n return this.foundPatternCross(stateCount) ? AlignmentPatternFinder.centerFromEnd(stateCount, i) : NaN;\n }\n /**\n *

This is called when a horizontal scan finds a possible alignment pattern. It will\n * cross check with a vertical scan, and if successful, will see if this pattern had been\n * found on a previous horizontal scan. If so, we consider it confirmed and conclude we have\n * found the alignment pattern.

\n *\n * @param stateCount reading state module counts from horizontal scan\n * @param i row where alignment pattern may be found\n * @param j end of possible alignment pattern in row\n * @return {@link AlignmentPattern} if we have found the same pattern twice, or null if not\n */\n handlePossibleCenter(stateCount, i /*int*/, j /*int*/) {\n const stateCountTotal = stateCount[0] + stateCount[1] + stateCount[2];\n const centerJ = AlignmentPatternFinder.centerFromEnd(stateCount, j);\n const centerI = this.crossCheckVertical(i, /*(int) */ centerJ, 2 * stateCount[1], stateCountTotal);\n if (!isNaN(centerI)) {\n const estimatedModuleSize = (stateCount[0] + stateCount[1] + stateCount[2]) / 3.0;\n for (const center of this.possibleCenters) {\n // Look for about the same center and module size:\n if (center.aboutEquals(estimatedModuleSize, centerI, centerJ)) {\n return center.combineEstimate(centerI, centerJ, estimatedModuleSize);\n }\n }\n // Hadn't found this before; save it\n const point = new AlignmentPattern(centerJ, centerI, estimatedModuleSize);\n this.possibleCenters.push(point);\n if (this.resultPointCallback !== null && this.resultPointCallback !== undefined) {\n this.resultPointCallback.foundPossibleResultPoint(point);\n }\n }\n return null;\n }\n }\n\n /*\n * Copyright 2007 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n /**\n *

Encapsulates a finder pattern, which are the three square patterns found in\n * the corners of QR Codes. It also encapsulates a count of similar finder patterns,\n * as a convenience to the finder's bookkeeping.

\n *\n * @author Sean Owen\n */\n class FinderPattern$1 extends ResultPoint {\n // FinderPattern(posX: number/*float*/, posY: number/*float*/, estimatedModuleSize: number/*float*/) {\n // this(posX, posY, estimatedModuleSize, 1)\n // }\n constructor(posX /*float*/, posY /*float*/, estimatedModuleSize /*float*/, count /*int*/) {\n super(posX, posY);\n this.estimatedModuleSize = estimatedModuleSize;\n this.count = count;\n if (undefined === count) {\n this.count = 1;\n }\n }\n getEstimatedModuleSize() {\n return this.estimatedModuleSize;\n }\n getCount() {\n return this.count;\n }\n /*\n void incrementCount() {\n this.count++\n }\n */\n /**\n *

Determines if this finder pattern \"about equals\" a finder pattern at the stated\n * position and size -- meaning, it is at nearly the same center with nearly the same size.

\n */\n aboutEquals(moduleSize /*float*/, i /*float*/, j /*float*/) {\n if (Math.abs(i - this.getY()) <= moduleSize && Math.abs(j - this.getX()) <= moduleSize) {\n const moduleSizeDiff = Math.abs(moduleSize - this.estimatedModuleSize);\n return moduleSizeDiff <= 1.0 || moduleSizeDiff <= this.estimatedModuleSize;\n }\n return false;\n }\n /**\n * Combines this object's current estimate of a finder pattern position and module size\n * with a new estimate. It returns a new {@code FinderPattern} containing a weighted average\n * based on count.\n */\n combineEstimate(i /*float*/, j /*float*/, newModuleSize /*float*/) {\n const combinedCount = this.count + 1;\n const combinedX = (this.count * this.getX() + j) / combinedCount;\n const combinedY = (this.count * this.getY() + i) / combinedCount;\n const combinedModuleSize = (this.count * this.estimatedModuleSize + newModuleSize) / combinedCount;\n return new FinderPattern$1(combinedX, combinedY, combinedModuleSize, combinedCount);\n }\n }\n\n /*\n * Copyright 2007 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n /**\n *

Encapsulates information about finder patterns in an image, including the location of\n * the three finder patterns, and their estimated module size.

\n *\n * @author Sean Owen\n */\n class FinderPatternInfo {\n constructor(patternCenters) {\n this.bottomLeft = patternCenters[0];\n this.topLeft = patternCenters[1];\n this.topRight = patternCenters[2];\n }\n getBottomLeft() {\n return this.bottomLeft;\n }\n getTopLeft() {\n return this.topLeft;\n }\n getTopRight() {\n return this.topRight;\n }\n }\n\n /*\n * Copyright 2007 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n /*import java.io.Serializable;*/\n /*import java.util.ArrayList;*/\n /*import java.util.Collections;*/\n /*import java.util.Comparator;*/\n /*import java.util.List;*/\n /*import java.util.Map;*/\n /**\n *

This class attempts to find finder patterns in a QR Code. Finder patterns are the square\n * markers at three corners of a QR Code.

\n *\n *

This class is thread-safe but not reentrant. Each thread must allocate its own object.\n *\n * @author Sean Owen\n */\n class FinderPatternFinder {\n /**\n *

Creates a finder that will search the image for three finder patterns.

\n *\n * @param image image to search\n */\n // public constructor(image: BitMatrix) {\n // this(image, null)\n // }\n constructor(image, resultPointCallback) {\n this.image = image;\n this.resultPointCallback = resultPointCallback;\n this.possibleCenters = [];\n this.crossCheckStateCount = new Int32Array(5);\n this.resultPointCallback = resultPointCallback;\n }\n getImage() {\n return this.image;\n }\n getPossibleCenters() {\n return this.possibleCenters;\n }\n find(hints) {\n const tryHarder = (hints !== null && hints !== undefined) && undefined !== hints.get(DecodeHintType$1.TRY_HARDER);\n const pureBarcode = (hints !== null && hints !== undefined) && undefined !== hints.get(DecodeHintType$1.PURE_BARCODE);\n const image = this.image;\n const maxI = image.getHeight();\n const maxJ = image.getWidth();\n // We are looking for black/white/black/white/black modules in\n // 1:1:3:1:1 ratio; this tracks the number of such modules seen so far\n // Let's assume that the maximum version QR Code we support takes up 1/4 the height of the\n // image, and then account for the center being 3 modules in size. This gives the smallest\n // number of pixels the center could be, so skip this often. When trying harder, look for all\n // QR versions regardless of how dense they are.\n let iSkip = Math.floor((3 * maxI) / (4 * FinderPatternFinder.MAX_MODULES));\n if (iSkip < FinderPatternFinder.MIN_SKIP || tryHarder) {\n iSkip = FinderPatternFinder.MIN_SKIP;\n }\n let done = false;\n const stateCount = new Int32Array(5);\n for (let i = iSkip - 1; i < maxI && !done; i += iSkip) {\n // Get a row of black/white values\n stateCount[0] = 0;\n stateCount[1] = 0;\n stateCount[2] = 0;\n stateCount[3] = 0;\n stateCount[4] = 0;\n let currentState = 0;\n for (let j = 0; j < maxJ; j++) {\n if (image.get(j, i)) {\n // Black pixel\n if ((currentState & 1) === 1) { // Counting white pixels\n currentState++;\n }\n stateCount[currentState]++;\n }\n else { // White pixel\n if ((currentState & 1) === 0) { // Counting black pixels\n if (currentState === 4) { // A winner?\n if (FinderPatternFinder.foundPatternCross(stateCount)) { // Yes\n const confirmed = this.handlePossibleCenter(stateCount, i, j, pureBarcode);\n if (confirmed === true) {\n // Start examining every other line. Checking each line turned out to be too\n // expensive and didn't improve performance.\n iSkip = 2;\n if (this.hasSkipped === true) {\n done = this.haveMultiplyConfirmedCenters();\n }\n else {\n const rowSkip = this.findRowSkip();\n if (rowSkip > stateCount[2]) {\n // Skip rows between row of lower confirmed center\n // and top of presumed third confirmed center\n // but back up a bit to get a full chance of detecting\n // it, entire width of center of finder pattern\n // Skip by rowSkip, but back off by stateCount[2] (size of last center\n // of pattern we saw) to be conservative, and also back off by iSkip which\n // is about to be re-added\n i += rowSkip - stateCount[2] - iSkip;\n j = maxJ - 1;\n }\n }\n }\n else {\n stateCount[0] = stateCount[2];\n stateCount[1] = stateCount[3];\n stateCount[2] = stateCount[4];\n stateCount[3] = 1;\n stateCount[4] = 0;\n currentState = 3;\n continue;\n }\n // Clear state to start looking again\n currentState = 0;\n stateCount[0] = 0;\n stateCount[1] = 0;\n stateCount[2] = 0;\n stateCount[3] = 0;\n stateCount[4] = 0;\n }\n else { // No, shift counts back by two\n stateCount[0] = stateCount[2];\n stateCount[1] = stateCount[3];\n stateCount[2] = stateCount[4];\n stateCount[3] = 1;\n stateCount[4] = 0;\n currentState = 3;\n }\n }\n else {\n stateCount[++currentState]++;\n }\n }\n else { // Counting white pixels\n stateCount[currentState]++;\n }\n }\n }\n if (FinderPatternFinder.foundPatternCross(stateCount)) {\n const confirmed = this.handlePossibleCenter(stateCount, i, maxJ, pureBarcode);\n if (confirmed === true) {\n iSkip = stateCount[0];\n if (this.hasSkipped) {\n // Found a third one\n done = this.haveMultiplyConfirmedCenters();\n }\n }\n }\n }\n const patternInfo = this.selectBestPatterns();\n ResultPoint.orderBestPatterns(patternInfo);\n return new FinderPatternInfo(patternInfo);\n }\n /**\n * Given a count of black/white/black/white/black pixels just seen and an end position,\n * figures the location of the center of this run.\n */\n static centerFromEnd(stateCount, end /*int*/) {\n return (end - stateCount[4] - stateCount[3]) - stateCount[2] / 2.0;\n }\n /**\n * @param stateCount count of black/white/black/white/black pixels just read\n * @return true iff the proportions of the counts is close enough to the 1/1/3/1/1 ratios\n * used by finder patterns to be considered a match\n */\n static foundPatternCross(stateCount) {\n let totalModuleSize = 0;\n for (let i = 0; i < 5; i++) {\n const count = stateCount[i];\n if (count === 0) {\n return false;\n }\n totalModuleSize += count;\n }\n if (totalModuleSize < 7) {\n return false;\n }\n const moduleSize = totalModuleSize / 7.0;\n const maxVariance = moduleSize / 2.0;\n // Allow less than 50% variance from 1-1-3-1-1 proportions\n return Math.abs(moduleSize - stateCount[0]) < maxVariance &&\n Math.abs(moduleSize - stateCount[1]) < maxVariance &&\n Math.abs(3.0 * moduleSize - stateCount[2]) < 3 * maxVariance &&\n Math.abs(moduleSize - stateCount[3]) < maxVariance &&\n Math.abs(moduleSize - stateCount[4]) < maxVariance;\n }\n getCrossCheckStateCount() {\n const crossCheckStateCount = this.crossCheckStateCount;\n crossCheckStateCount[0] = 0;\n crossCheckStateCount[1] = 0;\n crossCheckStateCount[2] = 0;\n crossCheckStateCount[3] = 0;\n crossCheckStateCount[4] = 0;\n return crossCheckStateCount;\n }\n /**\n * After a vertical and horizontal scan finds a potential finder pattern, this method\n * \"cross-cross-cross-checks\" by scanning down diagonally through the center of the possible\n * finder pattern to see if the same proportion is detected.\n *\n * @param startI row where a finder pattern was detected\n * @param centerJ center of the section that appears to cross a finder pattern\n * @param maxCount maximum reasonable number of modules that should be\n * observed in any reading state, based on the results of the horizontal scan\n * @param originalStateCountTotal The original state count total.\n * @return true if proportions are withing expected limits\n */\n crossCheckDiagonal(startI /*int*/, centerJ /*int*/, maxCount /*int*/, originalStateCountTotal /*int*/) {\n const stateCount = this.getCrossCheckStateCount();\n // Start counting up, left from center finding black center mass\n let i = 0;\n const image = this.image;\n while (startI >= i && centerJ >= i && image.get(centerJ - i, startI - i)) {\n stateCount[2]++;\n i++;\n }\n if (startI < i || centerJ < i) {\n return false;\n }\n // Continue up, left finding white space\n while (startI >= i && centerJ >= i && !image.get(centerJ - i, startI - i) &&\n stateCount[1] <= maxCount) {\n stateCount[1]++;\n i++;\n }\n // If already too many modules in this state or ran off the edge:\n if (startI < i || centerJ < i || stateCount[1] > maxCount) {\n return false;\n }\n // Continue up, left finding black border\n while (startI >= i && centerJ >= i && image.get(centerJ - i, startI - i) &&\n stateCount[0] <= maxCount) {\n stateCount[0]++;\n i++;\n }\n if (stateCount[0] > maxCount) {\n return false;\n }\n const maxI = image.getHeight();\n const maxJ = image.getWidth();\n // Now also count down, right from center\n i = 1;\n while (startI + i < maxI && centerJ + i < maxJ && image.get(centerJ + i, startI + i)) {\n stateCount[2]++;\n i++;\n }\n // Ran off the edge?\n if (startI + i >= maxI || centerJ + i >= maxJ) {\n return false;\n }\n while (startI + i < maxI && centerJ + i < maxJ && !image.get(centerJ + i, startI + i) &&\n stateCount[3] < maxCount) {\n stateCount[3]++;\n i++;\n }\n if (startI + i >= maxI || centerJ + i >= maxJ || stateCount[3] >= maxCount) {\n return false;\n }\n while (startI + i < maxI && centerJ + i < maxJ && image.get(centerJ + i, startI + i) &&\n stateCount[4] < maxCount) {\n stateCount[4]++;\n i++;\n }\n if (stateCount[4] >= maxCount) {\n return false;\n }\n // If we found a finder-pattern-like section, but its size is more than 100% different than\n // the original, assume it's a false positive\n const stateCountTotal = stateCount[0] + stateCount[1] + stateCount[2] + stateCount[3] + stateCount[4];\n return Math.abs(stateCountTotal - originalStateCountTotal) < 2 * originalStateCountTotal &&\n FinderPatternFinder.foundPatternCross(stateCount);\n }\n /**\n *

After a horizontal scan finds a potential finder pattern, this method\n * \"cross-checks\" by scanning down vertically through the center of the possible\n * finder pattern to see if the same proportion is detected.

\n *\n * @param startI row where a finder pattern was detected\n * @param centerJ center of the section that appears to cross a finder pattern\n * @param maxCount maximum reasonable number of modules that should be\n * observed in any reading state, based on the results of the horizontal scan\n * @return vertical center of finder pattern, or {@link Float#NaN} if not found\n */\n crossCheckVertical(startI /*int*/, centerJ /*int*/, maxCount /*int*/, originalStateCountTotal /*int*/) {\n const image = this.image;\n const maxI = image.getHeight();\n const stateCount = this.getCrossCheckStateCount();\n // Start counting up from center\n let i = startI;\n while (i >= 0 && image.get(centerJ, i)) {\n stateCount[2]++;\n i--;\n }\n if (i < 0) {\n return NaN;\n }\n while (i >= 0 && !image.get(centerJ, i) && stateCount[1] <= maxCount) {\n stateCount[1]++;\n i--;\n }\n // If already too many modules in this state or ran off the edge:\n if (i < 0 || stateCount[1] > maxCount) {\n return NaN;\n }\n while (i >= 0 && image.get(centerJ, i) && stateCount[0] <= maxCount) {\n stateCount[0]++;\n i--;\n }\n if (stateCount[0] > maxCount) {\n return NaN;\n }\n // Now also count down from center\n i = startI + 1;\n while (i < maxI && image.get(centerJ, i)) {\n stateCount[2]++;\n i++;\n }\n if (i === maxI) {\n return NaN;\n }\n while (i < maxI && !image.get(centerJ, i) && stateCount[3] < maxCount) {\n stateCount[3]++;\n i++;\n }\n if (i === maxI || stateCount[3] >= maxCount) {\n return NaN;\n }\n while (i < maxI && image.get(centerJ, i) && stateCount[4] < maxCount) {\n stateCount[4]++;\n i++;\n }\n if (stateCount[4] >= maxCount) {\n return NaN;\n }\n // If we found a finder-pattern-like section, but its size is more than 40% different than\n // the original, assume it's a false positive\n const stateCountTotal = stateCount[0] + stateCount[1] + stateCount[2] + stateCount[3] +\n stateCount[4];\n if (5 * Math.abs(stateCountTotal - originalStateCountTotal) >= 2 * originalStateCountTotal) {\n return NaN;\n }\n return FinderPatternFinder.foundPatternCross(stateCount) ? FinderPatternFinder.centerFromEnd(stateCount, i) : NaN;\n }\n /**\n *

Like {@link #crossCheckVertical(int, int, int, int)}, and in fact is basically identical,\n * except it reads horizontally instead of vertically. This is used to cross-cross\n * check a vertical cross check and locate the real center of the alignment pattern.

\n */\n crossCheckHorizontal(startJ /*int*/, centerI /*int*/, maxCount /*int*/, originalStateCountTotal /*int*/) {\n const image = this.image;\n const maxJ = image.getWidth();\n const stateCount = this.getCrossCheckStateCount();\n let j = startJ;\n while (j >= 0 && image.get(j, centerI)) {\n stateCount[2]++;\n j--;\n }\n if (j < 0) {\n return NaN;\n }\n while (j >= 0 && !image.get(j, centerI) && stateCount[1] <= maxCount) {\n stateCount[1]++;\n j--;\n }\n if (j < 0 || stateCount[1] > maxCount) {\n return NaN;\n }\n while (j >= 0 && image.get(j, centerI) && stateCount[0] <= maxCount) {\n stateCount[0]++;\n j--;\n }\n if (stateCount[0] > maxCount) {\n return NaN;\n }\n j = startJ + 1;\n while (j < maxJ && image.get(j, centerI)) {\n stateCount[2]++;\n j++;\n }\n if (j === maxJ) {\n return NaN;\n }\n while (j < maxJ && !image.get(j, centerI) && stateCount[3] < maxCount) {\n stateCount[3]++;\n j++;\n }\n if (j === maxJ || stateCount[3] >= maxCount) {\n return NaN;\n }\n while (j < maxJ && image.get(j, centerI) && stateCount[4] < maxCount) {\n stateCount[4]++;\n j++;\n }\n if (stateCount[4] >= maxCount) {\n return NaN;\n }\n // If we found a finder-pattern-like section, but its size is significantly different than\n // the original, assume it's a false positive\n const stateCountTotal = stateCount[0] + stateCount[1] + stateCount[2] + stateCount[3] +\n stateCount[4];\n if (5 * Math.abs(stateCountTotal - originalStateCountTotal) >= originalStateCountTotal) {\n return NaN;\n }\n return FinderPatternFinder.foundPatternCross(stateCount) ? FinderPatternFinder.centerFromEnd(stateCount, j) : NaN;\n }\n /**\n *

This is called when a horizontal scan finds a possible alignment pattern. It will\n * cross check with a vertical scan, and if successful, will, ah, cross-cross-check\n * with another horizontal scan. This is needed primarily to locate the real horizontal\n * center of the pattern in cases of extreme skew.\n * And then we cross-cross-cross check with another diagonal scan.

\n *\n *

If that succeeds the finder pattern location is added to a list that tracks\n * the number of times each location has been nearly-matched as a finder pattern.\n * Each additional find is more evidence that the location is in fact a finder\n * pattern center\n *\n * @param stateCount reading state module counts from horizontal scan\n * @param i row where finder pattern may be found\n * @param j end of possible finder pattern in row\n * @param pureBarcode true if in \"pure barcode\" mode\n * @return true if a finder pattern candidate was found this time\n */\n handlePossibleCenter(stateCount, i /*int*/, j /*int*/, pureBarcode) {\n const stateCountTotal = stateCount[0] + stateCount[1] + stateCount[2] + stateCount[3] +\n stateCount[4];\n let centerJ = FinderPatternFinder.centerFromEnd(stateCount, j);\n let centerI = this.crossCheckVertical(i, /*(int) */ Math.floor(centerJ), stateCount[2], stateCountTotal);\n if (!isNaN(centerI)) {\n // Re-cross check\n centerJ = this.crossCheckHorizontal(/*(int) */ Math.floor(centerJ), /*(int) */ Math.floor(centerI), stateCount[2], stateCountTotal);\n if (!isNaN(centerJ) &&\n (!pureBarcode || this.crossCheckDiagonal(/*(int) */ Math.floor(centerI), /*(int) */ Math.floor(centerJ), stateCount[2], stateCountTotal))) {\n const estimatedModuleSize = stateCountTotal / 7.0;\n let found = false;\n const possibleCenters = this.possibleCenters;\n for (let index = 0, length = possibleCenters.length; index < length; index++) {\n const center = possibleCenters[index];\n // Look for about the same center and module size:\n if (center.aboutEquals(estimatedModuleSize, centerI, centerJ)) {\n possibleCenters[index] = center.combineEstimate(centerI, centerJ, estimatedModuleSize);\n found = true;\n break;\n }\n }\n if (!found) {\n const point = new FinderPattern$1(centerJ, centerI, estimatedModuleSize);\n possibleCenters.push(point);\n if (this.resultPointCallback !== null && this.resultPointCallback !== undefined) {\n this.resultPointCallback.foundPossibleResultPoint(point);\n }\n }\n return true;\n }\n }\n return false;\n }\n /**\n * @return number of rows we could safely skip during scanning, based on the first\n * two finder patterns that have been located. In some cases their position will\n * allow us to infer that the third pattern must lie below a certain point farther\n * down in the image.\n */\n findRowSkip() {\n const max = this.possibleCenters.length;\n if (max <= 1) {\n return 0;\n }\n let firstConfirmedCenter = null;\n for (const center of this.possibleCenters) {\n if (center.getCount() >= FinderPatternFinder.CENTER_QUORUM) {\n if (firstConfirmedCenter == null) {\n firstConfirmedCenter = center;\n }\n else {\n // We have two confirmed centers\n // How far down can we skip before resuming looking for the next\n // pattern? In the worst case, only the difference between the\n // difference in the x / y coordinates of the two centers.\n // This is the case where you find top left last.\n this.hasSkipped = true;\n return /*(int) */ Math.floor((Math.abs(firstConfirmedCenter.getX() - center.getX()) -\n Math.abs(firstConfirmedCenter.getY() - center.getY())) / 2);\n }\n }\n }\n return 0;\n }\n /**\n * @return true iff we have found at least 3 finder patterns that have been detected\n * at least {@link #CENTER_QUORUM} times each, and, the estimated module size of the\n * candidates is \"pretty similar\"\n */\n haveMultiplyConfirmedCenters() {\n let confirmedCount = 0;\n let totalModuleSize = 0.0;\n const max = this.possibleCenters.length;\n for (const pattern of this.possibleCenters) {\n if (pattern.getCount() >= FinderPatternFinder.CENTER_QUORUM) {\n confirmedCount++;\n totalModuleSize += pattern.getEstimatedModuleSize();\n }\n }\n if (confirmedCount < 3) {\n return false;\n }\n // OK, we have at least 3 confirmed centers, but, it's possible that one is a \"false positive\"\n // and that we need to keep looking. We detect this by asking if the estimated module sizes\n // vary too much. We arbitrarily say that when the total deviation from average exceeds\n // 5% of the total module size estimates, it's too much.\n const average = totalModuleSize / max;\n let totalDeviation = 0.0;\n for (const pattern of this.possibleCenters) {\n totalDeviation += Math.abs(pattern.getEstimatedModuleSize() - average);\n }\n return totalDeviation <= 0.05 * totalModuleSize;\n }\n /**\n * @return the 3 best {@link FinderPattern}s from our list of candidates. The \"best\" are\n * those that have been detected at least {@link #CENTER_QUORUM} times, and whose module\n * size differs from the average among those patterns the least\n * @throws NotFoundException if 3 such finder patterns do not exist\n */\n selectBestPatterns() {\n const startSize = this.possibleCenters.length;\n if (startSize < 3) {\n // Couldn't find enough finder patterns\n throw new NotFoundException();\n }\n const possibleCenters = this.possibleCenters;\n let average;\n // Filter outlier possibilities whose module size is too different\n if (startSize > 3) {\n // But we can only afford to do so if we have at least 4 possibilities to choose from\n let totalModuleSize = 0.0;\n let square = 0.0;\n for (const center of this.possibleCenters) {\n const size = center.getEstimatedModuleSize();\n totalModuleSize += size;\n square += size * size;\n }\n average = totalModuleSize / startSize;\n let stdDev = Math.sqrt(square / startSize - average * average);\n possibleCenters.sort(\n /**\n *

Orders by furthest from average

\n */\n // FurthestFromAverageComparator implements Comparator\n (center1, center2) => {\n const dA = Math.abs(center2.getEstimatedModuleSize() - average);\n const dB = Math.abs(center1.getEstimatedModuleSize() - average);\n return dA < dB ? -1 : dA > dB ? 1 : 0;\n });\n const limit = Math.max(0.2 * average, stdDev);\n for (let i = 0; i < possibleCenters.length && possibleCenters.length > 3; i++) {\n const pattern = possibleCenters[i];\n if (Math.abs(pattern.getEstimatedModuleSize() - average) > limit) {\n possibleCenters.splice(i, 1);\n i--;\n }\n }\n }\n if (possibleCenters.length > 3) {\n // Throw away all but those first size candidate points we found.\n let totalModuleSize = 0.0;\n for (const possibleCenter of possibleCenters) {\n totalModuleSize += possibleCenter.getEstimatedModuleSize();\n }\n average = totalModuleSize / possibleCenters.length;\n possibleCenters.sort(\n /**\n *

Orders by {@link FinderPattern#getCount()}, descending.

\n */\n // CenterComparator implements Comparator\n (center1, center2) => {\n if (center2.getCount() === center1.getCount()) {\n const dA = Math.abs(center2.getEstimatedModuleSize() - average);\n const dB = Math.abs(center1.getEstimatedModuleSize() - average);\n return dA < dB ? 1 : dA > dB ? -1 : 0;\n }\n else {\n return center2.getCount() - center1.getCount();\n }\n });\n possibleCenters.splice(3); // this is not realy necessary as we only return first 3 anyway\n }\n return [\n possibleCenters[0],\n possibleCenters[1],\n possibleCenters[2]\n ];\n }\n }\n FinderPatternFinder.CENTER_QUORUM = 2;\n FinderPatternFinder.MIN_SKIP = 3; // 1 pixel/module times 3 modules/center\n FinderPatternFinder.MAX_MODULES = 57; // support up to version 10 for mobile clients\n\n /*\n * Copyright 2007 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n /*import java.util.Map;*/\n /**\n *

Encapsulates logic that can detect a QR Code in an image, even if the QR Code\n * is rotated or skewed, or partially obscured.

\n *\n * @author Sean Owen\n */\n class Detector$2 {\n constructor(image) {\n this.image = image;\n }\n getImage() {\n return this.image;\n }\n getResultPointCallback() {\n return this.resultPointCallback;\n }\n /**\n *

Detects a QR Code in an image.

\n *\n * @return {@link DetectorResult} encapsulating results of detecting a QR Code\n * @throws NotFoundException if QR Code cannot be found\n * @throws FormatException if a QR Code cannot be decoded\n */\n // public detect(): DetectorResult /*throws NotFoundException, FormatException*/ {\n // return detect(null)\n // }\n /**\n *

Detects a QR Code in an image.

\n *\n * @param hints optional hints to detector\n * @return {@link DetectorResult} encapsulating results of detecting a QR Code\n * @throws NotFoundException if QR Code cannot be found\n * @throws FormatException if a QR Code cannot be decoded\n */\n detect(hints) {\n this.resultPointCallback = (hints === null || hints === undefined) ? null :\n /*(ResultPointCallback) */ hints.get(DecodeHintType$1.NEED_RESULT_POINT_CALLBACK);\n const finder = new FinderPatternFinder(this.image, this.resultPointCallback);\n const info = finder.find(hints);\n return this.processFinderPatternInfo(info);\n }\n processFinderPatternInfo(info) {\n const topLeft = info.getTopLeft();\n const topRight = info.getTopRight();\n const bottomLeft = info.getBottomLeft();\n const moduleSize = this.calculateModuleSize(topLeft, topRight, bottomLeft);\n if (moduleSize < 1.0) {\n throw new NotFoundException('No pattern found in proccess finder.');\n }\n const dimension = Detector$2.computeDimension(topLeft, topRight, bottomLeft, moduleSize);\n const provisionalVersion = Version$1.getProvisionalVersionForDimension(dimension);\n const modulesBetweenFPCenters = provisionalVersion.getDimensionForVersion() - 7;\n let alignmentPattern = null;\n // Anything above version 1 has an alignment pattern\n if (provisionalVersion.getAlignmentPatternCenters().length > 0) {\n // Guess where a \"bottom right\" finder pattern would have been\n const bottomRightX = topRight.getX() - topLeft.getX() + bottomLeft.getX();\n const bottomRightY = topRight.getY() - topLeft.getY() + bottomLeft.getY();\n // Estimate that alignment pattern is closer by 3 modules\n // from \"bottom right\" to known top left location\n const correctionToTopLeft = 1.0 - 3.0 / modulesBetweenFPCenters;\n const estAlignmentX = /*(int) */ Math.floor(topLeft.getX() + correctionToTopLeft * (bottomRightX - topLeft.getX()));\n const estAlignmentY = /*(int) */ Math.floor(topLeft.getY() + correctionToTopLeft * (bottomRightY - topLeft.getY()));\n // Kind of arbitrary -- expand search radius before giving up\n for (let i = 4; i <= 16; i <<= 1) {\n try {\n alignmentPattern = this.findAlignmentInRegion(moduleSize, estAlignmentX, estAlignmentY, i);\n break;\n }\n catch (re /*NotFoundException*/) {\n if (!(re instanceof NotFoundException)) {\n throw re;\n }\n // try next round\n }\n }\n // If we didn't find alignment pattern... well try anyway without it\n }\n const transform = Detector$2.createTransform(topLeft, topRight, bottomLeft, alignmentPattern, dimension);\n const bits = Detector$2.sampleGrid(this.image, transform, dimension);\n let points;\n if (alignmentPattern === null) {\n points = [bottomLeft, topLeft, topRight];\n }\n else {\n points = [bottomLeft, topLeft, topRight, alignmentPattern];\n }\n return new DetectorResult(bits, points);\n }\n static createTransform(topLeft, topRight, bottomLeft, alignmentPattern, dimension /*int*/) {\n const dimMinusThree = dimension - 3.5;\n let bottomRightX; /*float*/\n let bottomRightY; /*float*/\n let sourceBottomRightX; /*float*/\n let sourceBottomRightY; /*float*/\n if (alignmentPattern !== null) {\n bottomRightX = alignmentPattern.getX();\n bottomRightY = alignmentPattern.getY();\n sourceBottomRightX = dimMinusThree - 3.0;\n sourceBottomRightY = sourceBottomRightX;\n }\n else {\n // Don't have an alignment pattern, just make up the bottom-right point\n bottomRightX = (topRight.getX() - topLeft.getX()) + bottomLeft.getX();\n bottomRightY = (topRight.getY() - topLeft.getY()) + bottomLeft.getY();\n sourceBottomRightX = dimMinusThree;\n sourceBottomRightY = dimMinusThree;\n }\n return PerspectiveTransform.quadrilateralToQuadrilateral(3.5, 3.5, dimMinusThree, 3.5, sourceBottomRightX, sourceBottomRightY, 3.5, dimMinusThree, topLeft.getX(), topLeft.getY(), topRight.getX(), topRight.getY(), bottomRightX, bottomRightY, bottomLeft.getX(), bottomLeft.getY());\n }\n static sampleGrid(image, transform, dimension /*int*/) {\n const sampler = GridSamplerInstance.getInstance();\n return sampler.sampleGridWithTransform(image, dimension, dimension, transform);\n }\n /**\n *

Computes the dimension (number of modules on a size) of the QR Code based on the position\n * of the finder patterns and estimated module size.

\n */\n static computeDimension(topLeft, topRight, bottomLeft, moduleSize /*float*/) {\n const tltrCentersDimension = MathUtils.round(ResultPoint.distance(topLeft, topRight) / moduleSize);\n const tlblCentersDimension = MathUtils.round(ResultPoint.distance(topLeft, bottomLeft) / moduleSize);\n let dimension = Math.floor((tltrCentersDimension + tlblCentersDimension) / 2) + 7;\n switch (dimension & 0x03) { // mod 4\n case 0:\n dimension++;\n break;\n // 1? do nothing\n case 2:\n dimension--;\n break;\n case 3:\n throw new NotFoundException('Dimensions could be not found.');\n }\n return dimension;\n }\n /**\n *

Computes an average estimated module size based on estimated derived from the positions\n * of the three finder patterns.

\n *\n * @param topLeft detected top-left finder pattern center\n * @param topRight detected top-right finder pattern center\n * @param bottomLeft detected bottom-left finder pattern center\n * @return estimated module size\n */\n calculateModuleSize(topLeft, topRight, bottomLeft) {\n // Take the average\n return (this.calculateModuleSizeOneWay(topLeft, topRight) +\n this.calculateModuleSizeOneWay(topLeft, bottomLeft)) / 2.0;\n }\n /**\n *

Estimates module size based on two finder patterns -- it uses\n * {@link #sizeOfBlackWhiteBlackRunBothWays(int, int, int, int)} to figure the\n * width of each, measuring along the axis between their centers.

\n */\n calculateModuleSizeOneWay(pattern, otherPattern) {\n const moduleSizeEst1 = this.sizeOfBlackWhiteBlackRunBothWays(/*(int) */ Math.floor(pattern.getX()), \n /*(int) */ Math.floor(pattern.getY()), \n /*(int) */ Math.floor(otherPattern.getX()), \n /*(int) */ Math.floor(otherPattern.getY()));\n const moduleSizeEst2 = this.sizeOfBlackWhiteBlackRunBothWays(/*(int) */ Math.floor(otherPattern.getX()), \n /*(int) */ Math.floor(otherPattern.getY()), \n /*(int) */ Math.floor(pattern.getX()), \n /*(int) */ Math.floor(pattern.getY()));\n if (isNaN(moduleSizeEst1)) {\n return moduleSizeEst2 / 7.0;\n }\n if (isNaN(moduleSizeEst2)) {\n return moduleSizeEst1 / 7.0;\n }\n // Average them, and divide by 7 since we've counted the width of 3 black modules,\n // and 1 white and 1 black module on either side. Ergo, divide sum by 14.\n return (moduleSizeEst1 + moduleSizeEst2) / 14.0;\n }\n /**\n * See {@link #sizeOfBlackWhiteBlackRun(int, int, int, int)}; computes the total width of\n * a finder pattern by looking for a black-white-black run from the center in the direction\n * of another point (another finder pattern center), and in the opposite direction too.\n */\n sizeOfBlackWhiteBlackRunBothWays(fromX /*int*/, fromY /*int*/, toX /*int*/, toY /*int*/) {\n let result = this.sizeOfBlackWhiteBlackRun(fromX, fromY, toX, toY);\n // Now count other way -- don't run off image though of course\n let scale = 1.0;\n let otherToX = fromX - (toX - fromX);\n if (otherToX < 0) {\n scale = fromX / /*(float) */ (fromX - otherToX);\n otherToX = 0;\n }\n else if (otherToX >= this.image.getWidth()) {\n scale = (this.image.getWidth() - 1 - fromX) / /*(float) */ (otherToX - fromX);\n otherToX = this.image.getWidth() - 1;\n }\n let otherToY = /*(int) */ Math.floor(fromY - (toY - fromY) * scale);\n scale = 1.0;\n if (otherToY < 0) {\n scale = fromY / /*(float) */ (fromY - otherToY);\n otherToY = 0;\n }\n else if (otherToY >= this.image.getHeight()) {\n scale = (this.image.getHeight() - 1 - fromY) / /*(float) */ (otherToY - fromY);\n otherToY = this.image.getHeight() - 1;\n }\n otherToX = /*(int) */ Math.floor(fromX + (otherToX - fromX) * scale);\n result += this.sizeOfBlackWhiteBlackRun(fromX, fromY, otherToX, otherToY);\n // Middle pixel is double-counted this way; subtract 1\n return result - 1.0;\n }\n /**\n *

This method traces a line from a point in the image, in the direction towards another point.\n * It begins in a black region, and keeps going until it finds white, then black, then white again.\n * It reports the distance from the start to this point.

\n *\n *

This is used when figuring out how wide a finder pattern is, when the finder pattern\n * may be skewed or rotated.

\n */\n sizeOfBlackWhiteBlackRun(fromX /*int*/, fromY /*int*/, toX /*int*/, toY /*int*/) {\n // Mild variant of Bresenham's algorithm\n // see http://en.wikipedia.org/wiki/Bresenham's_line_algorithm\n const steep = Math.abs(toY - fromY) > Math.abs(toX - fromX);\n if (steep) {\n let temp = fromX;\n fromX = fromY;\n fromY = temp;\n temp = toX;\n toX = toY;\n toY = temp;\n }\n const dx = Math.abs(toX - fromX);\n const dy = Math.abs(toY - fromY);\n let error = -dx / 2;\n const xstep = fromX < toX ? 1 : -1;\n const ystep = fromY < toY ? 1 : -1;\n // In black pixels, looking for white, first or second time.\n let state = 0;\n // Loop up until x == toX, but not beyond\n const xLimit = toX + xstep;\n for (let x = fromX, y = fromY; x !== xLimit; x += xstep) {\n const realX = steep ? y : x;\n const realY = steep ? x : y;\n // Does current pixel mean we have moved white to black or vice versa?\n // Scanning black in state 0,2 and white in state 1, so if we find the wrong\n // color, advance to next state or end if we are in state 2 already\n if ((state === 1) === this.image.get(realX, realY)) {\n if (state === 2) {\n return MathUtils.distance(x, y, fromX, fromY);\n }\n state++;\n }\n error += dy;\n if (error > 0) {\n if (y === toY) {\n break;\n }\n y += ystep;\n error -= dx;\n }\n }\n // Found black-white-black; give the benefit of the doubt that the next pixel outside the image\n // is \"white\" so this last point at (toX+xStep,toY) is the right ending. This is really a\n // small approximation; (toX+xStep,toY+yStep) might be really correct. Ignore this.\n if (state === 2) {\n return MathUtils.distance(toX + xstep, toY, fromX, fromY);\n }\n // else we didn't find even black-white-black; no estimate is really possible\n return NaN;\n }\n /**\n *

Attempts to locate an alignment pattern in a limited region of the image, which is\n * guessed to contain it. This method uses {@link AlignmentPattern}.

\n *\n * @param overallEstModuleSize estimated module size so far\n * @param estAlignmentX x coordinate of center of area probably containing alignment pattern\n * @param estAlignmentY y coordinate of above\n * @param allowanceFactor number of pixels in all directions to search from the center\n * @return {@link AlignmentPattern} if found, or null otherwise\n * @throws NotFoundException if an unexpected error occurs during detection\n */\n findAlignmentInRegion(overallEstModuleSize /*float*/, estAlignmentX /*int*/, estAlignmentY /*int*/, allowanceFactor /*float*/) {\n // Look for an alignment pattern (3 modules in size) around where it\n // should be\n const allowance = /*(int) */ Math.floor(allowanceFactor * overallEstModuleSize);\n const alignmentAreaLeftX = Math.max(0, estAlignmentX - allowance);\n const alignmentAreaRightX = Math.min(this.image.getWidth() - 1, estAlignmentX + allowance);\n if (alignmentAreaRightX - alignmentAreaLeftX < overallEstModuleSize * 3) {\n throw new NotFoundException('Alignment top exceeds estimated module size.');\n }\n const alignmentAreaTopY = Math.max(0, estAlignmentY - allowance);\n const alignmentAreaBottomY = Math.min(this.image.getHeight() - 1, estAlignmentY + allowance);\n if (alignmentAreaBottomY - alignmentAreaTopY < overallEstModuleSize * 3) {\n throw new NotFoundException('Alignment bottom exceeds estimated module size.');\n }\n const alignmentFinder = new AlignmentPatternFinder(this.image, alignmentAreaLeftX, alignmentAreaTopY, alignmentAreaRightX - alignmentAreaLeftX, alignmentAreaBottomY - alignmentAreaTopY, overallEstModuleSize, this.resultPointCallback);\n return alignmentFinder.find();\n }\n }\n\n /*\n * Copyright 2007 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n /*import java.util.List;*/\n /*import java.util.Map;*/\n /**\n * This implementation can detect and decode QR Codes in an image.\n *\n * @author Sean Owen\n */\n class QRCodeReader {\n constructor() {\n this.decoder = new Decoder$2();\n }\n getDecoder() {\n return this.decoder;\n }\n /**\n * Locates and decodes a QR code in an image.\n *\n * @return a representing: string the content encoded by the QR code\n * @throws NotFoundException if a QR code cannot be found\n * @throws FormatException if a QR code cannot be decoded\n * @throws ChecksumException if error correction fails\n */\n /*@Override*/\n // public decode(image: BinaryBitmap): Result /*throws NotFoundException, ChecksumException, FormatException */ {\n // return this.decode(image, null)\n // }\n /*@Override*/\n decode(image, hints) {\n let decoderResult;\n let points;\n if (hints !== undefined && hints !== null && undefined !== hints.get(DecodeHintType$1.PURE_BARCODE)) {\n const bits = QRCodeReader.extractPureBits(image.getBlackMatrix());\n decoderResult = this.decoder.decodeBitMatrix(bits, hints);\n points = QRCodeReader.NO_POINTS;\n }\n else {\n const detectorResult = new Detector$2(image.getBlackMatrix()).detect(hints);\n decoderResult = this.decoder.decodeBitMatrix(detectorResult.getBits(), hints);\n points = detectorResult.getPoints();\n }\n // If the code was mirrored: swap the bottom-left and the top-right points.\n if (decoderResult.getOther() instanceof QRCodeDecoderMetaData) {\n decoderResult.getOther().applyMirroredCorrection(points);\n }\n const result = new Result(decoderResult.getText(), decoderResult.getRawBytes(), undefined, points, BarcodeFormat$1.QR_CODE, undefined);\n const byteSegments = decoderResult.getByteSegments();\n if (byteSegments !== null) {\n result.putMetadata(ResultMetadataType$1.BYTE_SEGMENTS, byteSegments);\n }\n const ecLevel = decoderResult.getECLevel();\n if (ecLevel !== null) {\n result.putMetadata(ResultMetadataType$1.ERROR_CORRECTION_LEVEL, ecLevel);\n }\n if (decoderResult.hasStructuredAppend()) {\n result.putMetadata(ResultMetadataType$1.STRUCTURED_APPEND_SEQUENCE, decoderResult.getStructuredAppendSequenceNumber());\n result.putMetadata(ResultMetadataType$1.STRUCTURED_APPEND_PARITY, decoderResult.getStructuredAppendParity());\n }\n return result;\n }\n /*@Override*/\n reset() {\n // do nothing\n }\n /**\n * This method detects a code in a \"pure\" image -- that is, pure monochrome image\n * which contains only an unrotated, unskewed, image of a code, with some white border\n * around it. This is a specialized method that works exceptionally fast in this special\n * case.\n *\n * @see com.google.zxing.datamatrix.DataMatrixReader#extractPureBits(BitMatrix)\n */\n static extractPureBits(image) {\n const leftTopBlack = image.getTopLeftOnBit();\n const rightBottomBlack = image.getBottomRightOnBit();\n if (leftTopBlack === null || rightBottomBlack === null) {\n throw new NotFoundException();\n }\n const moduleSize = this.moduleSize(leftTopBlack, image);\n let top = leftTopBlack[1];\n let bottom = rightBottomBlack[1];\n let left = leftTopBlack[0];\n let right = rightBottomBlack[0];\n // Sanity check!\n if (left >= right || top >= bottom) {\n throw new NotFoundException();\n }\n if (bottom - top !== right - left) {\n // Special case, where bottom-right module wasn't black so we found something else in the last row\n // Assume it's a square, so use height as the width\n right = left + (bottom - top);\n if (right >= image.getWidth()) {\n // Abort if that would not make sense -- off image\n throw new NotFoundException();\n }\n }\n const matrixWidth = Math.round((right - left + 1) / moduleSize);\n const matrixHeight = Math.round((bottom - top + 1) / moduleSize);\n if (matrixWidth <= 0 || matrixHeight <= 0) {\n throw new NotFoundException();\n }\n if (matrixHeight !== matrixWidth) {\n // Only possibly decode square regions\n throw new NotFoundException();\n }\n // Push in the \"border\" by half the module width so that we start\n // sampling in the middle of the module. Just in case the image is a\n // little off, this will help recover.\n const nudge = /*(int) */ Math.floor(moduleSize / 2.0);\n top += nudge;\n left += nudge;\n // But careful that this does not sample off the edge\n // \"right\" is the farthest-right valid pixel location -- right+1 is not necessarily\n // This is positive by how much the inner x loop below would be too large\n const nudgedTooFarRight = left + /*(int) */ Math.floor((matrixWidth - 1) * moduleSize) - right;\n if (nudgedTooFarRight > 0) {\n if (nudgedTooFarRight > nudge) {\n // Neither way fits; abort\n throw new NotFoundException();\n }\n left -= nudgedTooFarRight;\n }\n // See logic above\n const nudgedTooFarDown = top + /*(int) */ Math.floor((matrixHeight - 1) * moduleSize) - bottom;\n if (nudgedTooFarDown > 0) {\n if (nudgedTooFarDown > nudge) {\n // Neither way fits; abort\n throw new NotFoundException();\n }\n top -= nudgedTooFarDown;\n }\n // Now just read off the bits\n const bits = new BitMatrix(matrixWidth, matrixHeight);\n for (let y = 0; y < matrixHeight; y++) {\n const iOffset = top + /*(int) */ Math.floor(y * moduleSize);\n for (let x = 0; x < matrixWidth; x++) {\n if (image.get(left + /*(int) */ Math.floor(x * moduleSize), iOffset)) {\n bits.set(x, y);\n }\n }\n }\n return bits;\n }\n static moduleSize(leftTopBlack, image) {\n const height = image.getHeight();\n const width = image.getWidth();\n let x = leftTopBlack[0];\n let y = leftTopBlack[1];\n let inBlack = true;\n let transitions = 0;\n while (x < width && y < height) {\n if (inBlack !== image.get(x, y)) {\n if (++transitions === 5) {\n break;\n }\n inBlack = !inBlack;\n }\n x++;\n y++;\n }\n if (x === width || y === height) {\n throw new NotFoundException();\n }\n return (x - leftTopBlack[0]) / 7.0;\n }\n }\n QRCodeReader.NO_POINTS = new Array();\n\n /*\n * Copyright 2009 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n /**\n * @author SITA Lab (kevin.osullivan@sita.aero)\n * @author Guenther Grau\n */\n /*public final*/ class PDF417Common {\n PDF417Common() {\n }\n /**\n * @param moduleBitCount values to sum\n * @return sum of values\n * @deprecated call {@link MathUtils#sum(int[])}\n */\n // @Deprecated\n static getBitCountSum(moduleBitCount) {\n return MathUtils.sum(moduleBitCount);\n }\n static toIntArray(list) {\n if (list == null || !list.length) {\n return PDF417Common.EMPTY_INT_ARRAY;\n }\n const result = new Int32Array(list.length);\n let i = 0;\n for (const integer of list) {\n result[i++] = integer;\n }\n return result;\n }\n /**\n * @param symbol encoded symbol to translate to a codeword\n * @return the codeword corresponding to the symbol.\n */\n static getCodeword(symbol /*int*/) {\n const i = Arrays.binarySearch(PDF417Common.SYMBOL_TABLE, symbol & 0x3FFFF);\n if (i < 0) {\n return -1;\n }\n return (PDF417Common.CODEWORD_TABLE[i] - 1) % PDF417Common.NUMBER_OF_CODEWORDS;\n }\n }\n PDF417Common.NUMBER_OF_CODEWORDS = 929;\n // Maximum Codewords (Data + Error).\n PDF417Common.MAX_CODEWORDS_IN_BARCODE = PDF417Common.NUMBER_OF_CODEWORDS - 1;\n PDF417Common.MIN_ROWS_IN_BARCODE = 3;\n PDF417Common.MAX_ROWS_IN_BARCODE = 90;\n // One left row indication column + max 30 data columns + one right row indicator column\n // public static /*final*/ MAX_CODEWORDS_IN_ROW: /*int*/ number = 32;\n PDF417Common.MODULES_IN_CODEWORD = 17;\n PDF417Common.MODULES_IN_STOP_PATTERN = 18;\n PDF417Common.BARS_IN_MODULE = 8;\n PDF417Common.EMPTY_INT_ARRAY = new Int32Array([]);\n /**\n * The sorted table of all possible symbols. Extracted from the PDF417\n * specification. The index of a symbol in this table corresponds to the\n * index into the codeword table.\n */\n PDF417Common.SYMBOL_TABLE = Int32Array.from([\n 0x1025e, 0x1027a, 0x1029e, 0x102bc, 0x102f2, 0x102f4, 0x1032e, 0x1034e, 0x1035c, 0x10396, 0x103a6, 0x103ac,\n 0x10422, 0x10428, 0x10436, 0x10442, 0x10444, 0x10448, 0x10450, 0x1045e, 0x10466, 0x1046c, 0x1047a, 0x10482,\n 0x1049e, 0x104a0, 0x104bc, 0x104c6, 0x104d8, 0x104ee, 0x104f2, 0x104f4, 0x10504, 0x10508, 0x10510, 0x1051e,\n 0x10520, 0x1053c, 0x10540, 0x10578, 0x10586, 0x1058c, 0x10598, 0x105b0, 0x105be, 0x105ce, 0x105dc, 0x105e2,\n 0x105e4, 0x105e8, 0x105f6, 0x1062e, 0x1064e, 0x1065c, 0x1068e, 0x1069c, 0x106b8, 0x106de, 0x106fa, 0x10716,\n 0x10726, 0x1072c, 0x10746, 0x1074c, 0x10758, 0x1076e, 0x10792, 0x10794, 0x107a2, 0x107a4, 0x107a8, 0x107b6,\n 0x10822, 0x10828, 0x10842, 0x10848, 0x10850, 0x1085e, 0x10866, 0x1086c, 0x1087a, 0x10882, 0x10884, 0x10890,\n 0x1089e, 0x108a0, 0x108bc, 0x108c6, 0x108cc, 0x108d8, 0x108ee, 0x108f2, 0x108f4, 0x10902, 0x10908, 0x1091e,\n 0x10920, 0x1093c, 0x10940, 0x10978, 0x10986, 0x10998, 0x109b0, 0x109be, 0x109ce, 0x109dc, 0x109e2, 0x109e4,\n 0x109e8, 0x109f6, 0x10a08, 0x10a10, 0x10a1e, 0x10a20, 0x10a3c, 0x10a40, 0x10a78, 0x10af0, 0x10b06, 0x10b0c,\n 0x10b18, 0x10b30, 0x10b3e, 0x10b60, 0x10b7c, 0x10b8e, 0x10b9c, 0x10bb8, 0x10bc2, 0x10bc4, 0x10bc8, 0x10bd0,\n 0x10bde, 0x10be6, 0x10bec, 0x10c2e, 0x10c4e, 0x10c5c, 0x10c62, 0x10c64, 0x10c68, 0x10c76, 0x10c8e, 0x10c9c,\n 0x10cb8, 0x10cc2, 0x10cc4, 0x10cc8, 0x10cd0, 0x10cde, 0x10ce6, 0x10cec, 0x10cfa, 0x10d0e, 0x10d1c, 0x10d38,\n 0x10d70, 0x10d7e, 0x10d82, 0x10d84, 0x10d88, 0x10d90, 0x10d9e, 0x10da0, 0x10dbc, 0x10dc6, 0x10dcc, 0x10dd8,\n 0x10dee, 0x10df2, 0x10df4, 0x10e16, 0x10e26, 0x10e2c, 0x10e46, 0x10e58, 0x10e6e, 0x10e86, 0x10e8c, 0x10e98,\n 0x10eb0, 0x10ebe, 0x10ece, 0x10edc, 0x10f0a, 0x10f12, 0x10f14, 0x10f22, 0x10f28, 0x10f36, 0x10f42, 0x10f44,\n 0x10f48, 0x10f50, 0x10f5e, 0x10f66, 0x10f6c, 0x10fb2, 0x10fb4, 0x11022, 0x11028, 0x11042, 0x11048, 0x11050,\n 0x1105e, 0x1107a, 0x11082, 0x11084, 0x11090, 0x1109e, 0x110a0, 0x110bc, 0x110c6, 0x110cc, 0x110d8, 0x110ee,\n 0x110f2, 0x110f4, 0x11102, 0x1111e, 0x11120, 0x1113c, 0x11140, 0x11178, 0x11186, 0x11198, 0x111b0, 0x111be,\n 0x111ce, 0x111dc, 0x111e2, 0x111e4, 0x111e8, 0x111f6, 0x11208, 0x1121e, 0x11220, 0x11278, 0x112f0, 0x1130c,\n 0x11330, 0x1133e, 0x11360, 0x1137c, 0x1138e, 0x1139c, 0x113b8, 0x113c2, 0x113c8, 0x113d0, 0x113de, 0x113e6,\n 0x113ec, 0x11408, 0x11410, 0x1141e, 0x11420, 0x1143c, 0x11440, 0x11478, 0x114f0, 0x115e0, 0x1160c, 0x11618,\n 0x11630, 0x1163e, 0x11660, 0x1167c, 0x116c0, 0x116f8, 0x1171c, 0x11738, 0x11770, 0x1177e, 0x11782, 0x11784,\n 0x11788, 0x11790, 0x1179e, 0x117a0, 0x117bc, 0x117c6, 0x117cc, 0x117d8, 0x117ee, 0x1182e, 0x11834, 0x1184e,\n 0x1185c, 0x11862, 0x11864, 0x11868, 0x11876, 0x1188e, 0x1189c, 0x118b8, 0x118c2, 0x118c8, 0x118d0, 0x118de,\n 0x118e6, 0x118ec, 0x118fa, 0x1190e, 0x1191c, 0x11938, 0x11970, 0x1197e, 0x11982, 0x11984, 0x11990, 0x1199e,\n 0x119a0, 0x119bc, 0x119c6, 0x119cc, 0x119d8, 0x119ee, 0x119f2, 0x119f4, 0x11a0e, 0x11a1c, 0x11a38, 0x11a70,\n 0x11a7e, 0x11ae0, 0x11afc, 0x11b08, 0x11b10, 0x11b1e, 0x11b20, 0x11b3c, 0x11b40, 0x11b78, 0x11b8c, 0x11b98,\n 0x11bb0, 0x11bbe, 0x11bce, 0x11bdc, 0x11be2, 0x11be4, 0x11be8, 0x11bf6, 0x11c16, 0x11c26, 0x11c2c, 0x11c46,\n 0x11c4c, 0x11c58, 0x11c6e, 0x11c86, 0x11c98, 0x11cb0, 0x11cbe, 0x11cce, 0x11cdc, 0x11ce2, 0x11ce4, 0x11ce8,\n 0x11cf6, 0x11d06, 0x11d0c, 0x11d18, 0x11d30, 0x11d3e, 0x11d60, 0x11d7c, 0x11d8e, 0x11d9c, 0x11db8, 0x11dc4,\n 0x11dc8, 0x11dd0, 0x11dde, 0x11de6, 0x11dec, 0x11dfa, 0x11e0a, 0x11e12, 0x11e14, 0x11e22, 0x11e24, 0x11e28,\n 0x11e36, 0x11e42, 0x11e44, 0x11e50, 0x11e5e, 0x11e66, 0x11e6c, 0x11e82, 0x11e84, 0x11e88, 0x11e90, 0x11e9e,\n 0x11ea0, 0x11ebc, 0x11ec6, 0x11ecc, 0x11ed8, 0x11eee, 0x11f1a, 0x11f2e, 0x11f32, 0x11f34, 0x11f4e, 0x11f5c,\n 0x11f62, 0x11f64, 0x11f68, 0x11f76, 0x12048, 0x1205e, 0x12082, 0x12084, 0x12090, 0x1209e, 0x120a0, 0x120bc,\n 0x120d8, 0x120f2, 0x120f4, 0x12108, 0x1211e, 0x12120, 0x1213c, 0x12140, 0x12178, 0x12186, 0x12198, 0x121b0,\n 0x121be, 0x121e2, 0x121e4, 0x121e8, 0x121f6, 0x12204, 0x12210, 0x1221e, 0x12220, 0x12278, 0x122f0, 0x12306,\n 0x1230c, 0x12330, 0x1233e, 0x12360, 0x1237c, 0x1238e, 0x1239c, 0x123b8, 0x123c2, 0x123c8, 0x123d0, 0x123e6,\n 0x123ec, 0x1241e, 0x12420, 0x1243c, 0x124f0, 0x125e0, 0x12618, 0x1263e, 0x12660, 0x1267c, 0x126c0, 0x126f8,\n 0x12738, 0x12770, 0x1277e, 0x12782, 0x12784, 0x12790, 0x1279e, 0x127a0, 0x127bc, 0x127c6, 0x127cc, 0x127d8,\n 0x127ee, 0x12820, 0x1283c, 0x12840, 0x12878, 0x128f0, 0x129e0, 0x12bc0, 0x12c18, 0x12c30, 0x12c3e, 0x12c60,\n 0x12c7c, 0x12cc0, 0x12cf8, 0x12df0, 0x12e1c, 0x12e38, 0x12e70, 0x12e7e, 0x12ee0, 0x12efc, 0x12f04, 0x12f08,\n 0x12f10, 0x12f20, 0x12f3c, 0x12f40, 0x12f78, 0x12f86, 0x12f8c, 0x12f98, 0x12fb0, 0x12fbe, 0x12fce, 0x12fdc,\n 0x1302e, 0x1304e, 0x1305c, 0x13062, 0x13068, 0x1308e, 0x1309c, 0x130b8, 0x130c2, 0x130c8, 0x130d0, 0x130de,\n 0x130ec, 0x130fa, 0x1310e, 0x13138, 0x13170, 0x1317e, 0x13182, 0x13184, 0x13190, 0x1319e, 0x131a0, 0x131bc,\n 0x131c6, 0x131cc, 0x131d8, 0x131f2, 0x131f4, 0x1320e, 0x1321c, 0x13270, 0x1327e, 0x132e0, 0x132fc, 0x13308,\n 0x1331e, 0x13320, 0x1333c, 0x13340, 0x13378, 0x13386, 0x13398, 0x133b0, 0x133be, 0x133ce, 0x133dc, 0x133e2,\n 0x133e4, 0x133e8, 0x133f6, 0x1340e, 0x1341c, 0x13438, 0x13470, 0x1347e, 0x134e0, 0x134fc, 0x135c0, 0x135f8,\n 0x13608, 0x13610, 0x1361e, 0x13620, 0x1363c, 0x13640, 0x13678, 0x136f0, 0x1370c, 0x13718, 0x13730, 0x1373e,\n 0x13760, 0x1377c, 0x1379c, 0x137b8, 0x137c2, 0x137c4, 0x137c8, 0x137d0, 0x137de, 0x137e6, 0x137ec, 0x13816,\n 0x13826, 0x1382c, 0x13846, 0x1384c, 0x13858, 0x1386e, 0x13874, 0x13886, 0x13898, 0x138b0, 0x138be, 0x138ce,\n 0x138dc, 0x138e2, 0x138e4, 0x138e8, 0x13906, 0x1390c, 0x13930, 0x1393e, 0x13960, 0x1397c, 0x1398e, 0x1399c,\n 0x139b8, 0x139c8, 0x139d0, 0x139de, 0x139e6, 0x139ec, 0x139fa, 0x13a06, 0x13a0c, 0x13a18, 0x13a30, 0x13a3e,\n 0x13a60, 0x13a7c, 0x13ac0, 0x13af8, 0x13b0e, 0x13b1c, 0x13b38, 0x13b70, 0x13b7e, 0x13b88, 0x13b90, 0x13b9e,\n 0x13ba0, 0x13bbc, 0x13bcc, 0x13bd8, 0x13bee, 0x13bf2, 0x13bf4, 0x13c12, 0x13c14, 0x13c22, 0x13c24, 0x13c28,\n 0x13c36, 0x13c42, 0x13c48, 0x13c50, 0x13c5e, 0x13c66, 0x13c6c, 0x13c82, 0x13c84, 0x13c90, 0x13c9e, 0x13ca0,\n 0x13cbc, 0x13cc6, 0x13ccc, 0x13cd8, 0x13cee, 0x13d02, 0x13d04, 0x13d08, 0x13d10, 0x13d1e, 0x13d20, 0x13d3c,\n 0x13d40, 0x13d78, 0x13d86, 0x13d8c, 0x13d98, 0x13db0, 0x13dbe, 0x13dce, 0x13ddc, 0x13de4, 0x13de8, 0x13df6,\n 0x13e1a, 0x13e2e, 0x13e32, 0x13e34, 0x13e4e, 0x13e5c, 0x13e62, 0x13e64, 0x13e68, 0x13e76, 0x13e8e, 0x13e9c,\n 0x13eb8, 0x13ec2, 0x13ec4, 0x13ec8, 0x13ed0, 0x13ede, 0x13ee6, 0x13eec, 0x13f26, 0x13f2c, 0x13f3a, 0x13f46,\n 0x13f4c, 0x13f58, 0x13f6e, 0x13f72, 0x13f74, 0x14082, 0x1409e, 0x140a0, 0x140bc, 0x14104, 0x14108, 0x14110,\n 0x1411e, 0x14120, 0x1413c, 0x14140, 0x14178, 0x1418c, 0x14198, 0x141b0, 0x141be, 0x141e2, 0x141e4, 0x141e8,\n 0x14208, 0x14210, 0x1421e, 0x14220, 0x1423c, 0x14240, 0x14278, 0x142f0, 0x14306, 0x1430c, 0x14318, 0x14330,\n 0x1433e, 0x14360, 0x1437c, 0x1438e, 0x143c2, 0x143c4, 0x143c8, 0x143d0, 0x143e6, 0x143ec, 0x14408, 0x14410,\n 0x1441e, 0x14420, 0x1443c, 0x14440, 0x14478, 0x144f0, 0x145e0, 0x1460c, 0x14618, 0x14630, 0x1463e, 0x14660,\n 0x1467c, 0x146c0, 0x146f8, 0x1471c, 0x14738, 0x14770, 0x1477e, 0x14782, 0x14784, 0x14788, 0x14790, 0x147a0,\n 0x147bc, 0x147c6, 0x147cc, 0x147d8, 0x147ee, 0x14810, 0x14820, 0x1483c, 0x14840, 0x14878, 0x148f0, 0x149e0,\n 0x14bc0, 0x14c30, 0x14c3e, 0x14c60, 0x14c7c, 0x14cc0, 0x14cf8, 0x14df0, 0x14e38, 0x14e70, 0x14e7e, 0x14ee0,\n 0x14efc, 0x14f04, 0x14f08, 0x14f10, 0x14f1e, 0x14f20, 0x14f3c, 0x14f40, 0x14f78, 0x14f86, 0x14f8c, 0x14f98,\n 0x14fb0, 0x14fce, 0x14fdc, 0x15020, 0x15040, 0x15078, 0x150f0, 0x151e0, 0x153c0, 0x15860, 0x1587c, 0x158c0,\n 0x158f8, 0x159f0, 0x15be0, 0x15c70, 0x15c7e, 0x15ce0, 0x15cfc, 0x15dc0, 0x15df8, 0x15e08, 0x15e10, 0x15e20,\n 0x15e40, 0x15e78, 0x15ef0, 0x15f0c, 0x15f18, 0x15f30, 0x15f60, 0x15f7c, 0x15f8e, 0x15f9c, 0x15fb8, 0x1604e,\n 0x1605c, 0x1608e, 0x1609c, 0x160b8, 0x160c2, 0x160c4, 0x160c8, 0x160de, 0x1610e, 0x1611c, 0x16138, 0x16170,\n 0x1617e, 0x16184, 0x16188, 0x16190, 0x1619e, 0x161a0, 0x161bc, 0x161c6, 0x161cc, 0x161d8, 0x161f2, 0x161f4,\n 0x1620e, 0x1621c, 0x16238, 0x16270, 0x1627e, 0x162e0, 0x162fc, 0x16304, 0x16308, 0x16310, 0x1631e, 0x16320,\n 0x1633c, 0x16340, 0x16378, 0x16386, 0x1638c, 0x16398, 0x163b0, 0x163be, 0x163ce, 0x163dc, 0x163e2, 0x163e4,\n 0x163e8, 0x163f6, 0x1640e, 0x1641c, 0x16438, 0x16470, 0x1647e, 0x164e0, 0x164fc, 0x165c0, 0x165f8, 0x16610,\n 0x1661e, 0x16620, 0x1663c, 0x16640, 0x16678, 0x166f0, 0x16718, 0x16730, 0x1673e, 0x16760, 0x1677c, 0x1678e,\n 0x1679c, 0x167b8, 0x167c2, 0x167c4, 0x167c8, 0x167d0, 0x167de, 0x167e6, 0x167ec, 0x1681c, 0x16838, 0x16870,\n 0x168e0, 0x168fc, 0x169c0, 0x169f8, 0x16bf0, 0x16c10, 0x16c1e, 0x16c20, 0x16c3c, 0x16c40, 0x16c78, 0x16cf0,\n 0x16de0, 0x16e18, 0x16e30, 0x16e3e, 0x16e60, 0x16e7c, 0x16ec0, 0x16ef8, 0x16f1c, 0x16f38, 0x16f70, 0x16f7e,\n 0x16f84, 0x16f88, 0x16f90, 0x16f9e, 0x16fa0, 0x16fbc, 0x16fc6, 0x16fcc, 0x16fd8, 0x17026, 0x1702c, 0x17046,\n 0x1704c, 0x17058, 0x1706e, 0x17086, 0x1708c, 0x17098, 0x170b0, 0x170be, 0x170ce, 0x170dc, 0x170e8, 0x17106,\n 0x1710c, 0x17118, 0x17130, 0x1713e, 0x17160, 0x1717c, 0x1718e, 0x1719c, 0x171b8, 0x171c2, 0x171c4, 0x171c8,\n 0x171d0, 0x171de, 0x171e6, 0x171ec, 0x171fa, 0x17206, 0x1720c, 0x17218, 0x17230, 0x1723e, 0x17260, 0x1727c,\n 0x172c0, 0x172f8, 0x1730e, 0x1731c, 0x17338, 0x17370, 0x1737e, 0x17388, 0x17390, 0x1739e, 0x173a0, 0x173bc,\n 0x173cc, 0x173d8, 0x173ee, 0x173f2, 0x173f4, 0x1740c, 0x17418, 0x17430, 0x1743e, 0x17460, 0x1747c, 0x174c0,\n 0x174f8, 0x175f0, 0x1760e, 0x1761c, 0x17638, 0x17670, 0x1767e, 0x176e0, 0x176fc, 0x17708, 0x17710, 0x1771e,\n 0x17720, 0x1773c, 0x17740, 0x17778, 0x17798, 0x177b0, 0x177be, 0x177dc, 0x177e2, 0x177e4, 0x177e8, 0x17822,\n 0x17824, 0x17828, 0x17836, 0x17842, 0x17844, 0x17848, 0x17850, 0x1785e, 0x17866, 0x1786c, 0x17882, 0x17884,\n 0x17888, 0x17890, 0x1789e, 0x178a0, 0x178bc, 0x178c6, 0x178cc, 0x178d8, 0x178ee, 0x178f2, 0x178f4, 0x17902,\n 0x17904, 0x17908, 0x17910, 0x1791e, 0x17920, 0x1793c, 0x17940, 0x17978, 0x17986, 0x1798c, 0x17998, 0x179b0,\n 0x179be, 0x179ce, 0x179dc, 0x179e2, 0x179e4, 0x179e8, 0x179f6, 0x17a04, 0x17a08, 0x17a10, 0x17a1e, 0x17a20,\n 0x17a3c, 0x17a40, 0x17a78, 0x17af0, 0x17b06, 0x17b0c, 0x17b18, 0x17b30, 0x17b3e, 0x17b60, 0x17b7c, 0x17b8e,\n 0x17b9c, 0x17bb8, 0x17bc4, 0x17bc8, 0x17bd0, 0x17bde, 0x17be6, 0x17bec, 0x17c2e, 0x17c32, 0x17c34, 0x17c4e,\n 0x17c5c, 0x17c62, 0x17c64, 0x17c68, 0x17c76, 0x17c8e, 0x17c9c, 0x17cb8, 0x17cc2, 0x17cc4, 0x17cc8, 0x17cd0,\n 0x17cde, 0x17ce6, 0x17cec, 0x17d0e, 0x17d1c, 0x17d38, 0x17d70, 0x17d82, 0x17d84, 0x17d88, 0x17d90, 0x17d9e,\n 0x17da0, 0x17dbc, 0x17dc6, 0x17dcc, 0x17dd8, 0x17dee, 0x17e26, 0x17e2c, 0x17e3a, 0x17e46, 0x17e4c, 0x17e58,\n 0x17e6e, 0x17e72, 0x17e74, 0x17e86, 0x17e8c, 0x17e98, 0x17eb0, 0x17ece, 0x17edc, 0x17ee2, 0x17ee4, 0x17ee8,\n 0x17ef6, 0x1813a, 0x18172, 0x18174, 0x18216, 0x18226, 0x1823a, 0x1824c, 0x18258, 0x1826e, 0x18272, 0x18274,\n 0x18298, 0x182be, 0x182e2, 0x182e4, 0x182e8, 0x182f6, 0x1835e, 0x1837a, 0x183ae, 0x183d6, 0x18416, 0x18426,\n 0x1842c, 0x1843a, 0x18446, 0x18458, 0x1846e, 0x18472, 0x18474, 0x18486, 0x184b0, 0x184be, 0x184ce, 0x184dc,\n 0x184e2, 0x184e4, 0x184e8, 0x184f6, 0x18506, 0x1850c, 0x18518, 0x18530, 0x1853e, 0x18560, 0x1857c, 0x1858e,\n 0x1859c, 0x185b8, 0x185c2, 0x185c4, 0x185c8, 0x185d0, 0x185de, 0x185e6, 0x185ec, 0x185fa, 0x18612, 0x18614,\n 0x18622, 0x18628, 0x18636, 0x18642, 0x18650, 0x1865e, 0x1867a, 0x18682, 0x18684, 0x18688, 0x18690, 0x1869e,\n 0x186a0, 0x186bc, 0x186c6, 0x186cc, 0x186d8, 0x186ee, 0x186f2, 0x186f4, 0x1872e, 0x1874e, 0x1875c, 0x18796,\n 0x187a6, 0x187ac, 0x187d2, 0x187d4, 0x18826, 0x1882c, 0x1883a, 0x18846, 0x1884c, 0x18858, 0x1886e, 0x18872,\n 0x18874, 0x18886, 0x18898, 0x188b0, 0x188be, 0x188ce, 0x188dc, 0x188e2, 0x188e4, 0x188e8, 0x188f6, 0x1890c,\n 0x18930, 0x1893e, 0x18960, 0x1897c, 0x1898e, 0x189b8, 0x189c2, 0x189c8, 0x189d0, 0x189de, 0x189e6, 0x189ec,\n 0x189fa, 0x18a18, 0x18a30, 0x18a3e, 0x18a60, 0x18a7c, 0x18ac0, 0x18af8, 0x18b1c, 0x18b38, 0x18b70, 0x18b7e,\n 0x18b82, 0x18b84, 0x18b88, 0x18b90, 0x18b9e, 0x18ba0, 0x18bbc, 0x18bc6, 0x18bcc, 0x18bd8, 0x18bee, 0x18bf2,\n 0x18bf4, 0x18c22, 0x18c24, 0x18c28, 0x18c36, 0x18c42, 0x18c48, 0x18c50, 0x18c5e, 0x18c66, 0x18c7a, 0x18c82,\n 0x18c84, 0x18c90, 0x18c9e, 0x18ca0, 0x18cbc, 0x18ccc, 0x18cf2, 0x18cf4, 0x18d04, 0x18d08, 0x18d10, 0x18d1e,\n 0x18d20, 0x18d3c, 0x18d40, 0x18d78, 0x18d86, 0x18d98, 0x18dce, 0x18de2, 0x18de4, 0x18de8, 0x18e2e, 0x18e32,\n 0x18e34, 0x18e4e, 0x18e5c, 0x18e62, 0x18e64, 0x18e68, 0x18e8e, 0x18e9c, 0x18eb8, 0x18ec2, 0x18ec4, 0x18ec8,\n 0x18ed0, 0x18efa, 0x18f16, 0x18f26, 0x18f2c, 0x18f46, 0x18f4c, 0x18f58, 0x18f6e, 0x18f8a, 0x18f92, 0x18f94,\n 0x18fa2, 0x18fa4, 0x18fa8, 0x18fb6, 0x1902c, 0x1903a, 0x19046, 0x1904c, 0x19058, 0x19072, 0x19074, 0x19086,\n 0x19098, 0x190b0, 0x190be, 0x190ce, 0x190dc, 0x190e2, 0x190e8, 0x190f6, 0x19106, 0x1910c, 0x19130, 0x1913e,\n 0x19160, 0x1917c, 0x1918e, 0x1919c, 0x191b8, 0x191c2, 0x191c8, 0x191d0, 0x191de, 0x191e6, 0x191ec, 0x191fa,\n 0x19218, 0x1923e, 0x19260, 0x1927c, 0x192c0, 0x192f8, 0x19338, 0x19370, 0x1937e, 0x19382, 0x19384, 0x19390,\n 0x1939e, 0x193a0, 0x193bc, 0x193c6, 0x193cc, 0x193d8, 0x193ee, 0x193f2, 0x193f4, 0x19430, 0x1943e, 0x19460,\n 0x1947c, 0x194c0, 0x194f8, 0x195f0, 0x19638, 0x19670, 0x1967e, 0x196e0, 0x196fc, 0x19702, 0x19704, 0x19708,\n 0x19710, 0x19720, 0x1973c, 0x19740, 0x19778, 0x19786, 0x1978c, 0x19798, 0x197b0, 0x197be, 0x197ce, 0x197dc,\n 0x197e2, 0x197e4, 0x197e8, 0x19822, 0x19824, 0x19842, 0x19848, 0x19850, 0x1985e, 0x19866, 0x1987a, 0x19882,\n 0x19884, 0x19890, 0x1989e, 0x198a0, 0x198bc, 0x198cc, 0x198f2, 0x198f4, 0x19902, 0x19908, 0x1991e, 0x19920,\n 0x1993c, 0x19940, 0x19978, 0x19986, 0x19998, 0x199ce, 0x199e2, 0x199e4, 0x199e8, 0x19a08, 0x19a10, 0x19a1e,\n 0x19a20, 0x19a3c, 0x19a40, 0x19a78, 0x19af0, 0x19b18, 0x19b3e, 0x19b60, 0x19b9c, 0x19bc2, 0x19bc4, 0x19bc8,\n 0x19bd0, 0x19be6, 0x19c2e, 0x19c34, 0x19c4e, 0x19c5c, 0x19c62, 0x19c64, 0x19c68, 0x19c8e, 0x19c9c, 0x19cb8,\n 0x19cc2, 0x19cc8, 0x19cd0, 0x19ce6, 0x19cfa, 0x19d0e, 0x19d1c, 0x19d38, 0x19d70, 0x19d7e, 0x19d82, 0x19d84,\n 0x19d88, 0x19d90, 0x19da0, 0x19dcc, 0x19df2, 0x19df4, 0x19e16, 0x19e26, 0x19e2c, 0x19e46, 0x19e4c, 0x19e58,\n 0x19e74, 0x19e86, 0x19e8c, 0x19e98, 0x19eb0, 0x19ebe, 0x19ece, 0x19ee2, 0x19ee4, 0x19ee8, 0x19f0a, 0x19f12,\n 0x19f14, 0x19f22, 0x19f24, 0x19f28, 0x19f42, 0x19f44, 0x19f48, 0x19f50, 0x19f5e, 0x19f6c, 0x19f9a, 0x19fae,\n 0x19fb2, 0x19fb4, 0x1a046, 0x1a04c, 0x1a072, 0x1a074, 0x1a086, 0x1a08c, 0x1a098, 0x1a0b0, 0x1a0be, 0x1a0e2,\n 0x1a0e4, 0x1a0e8, 0x1a0f6, 0x1a106, 0x1a10c, 0x1a118, 0x1a130, 0x1a13e, 0x1a160, 0x1a17c, 0x1a18e, 0x1a19c,\n 0x1a1b8, 0x1a1c2, 0x1a1c4, 0x1a1c8, 0x1a1d0, 0x1a1de, 0x1a1e6, 0x1a1ec, 0x1a218, 0x1a230, 0x1a23e, 0x1a260,\n 0x1a27c, 0x1a2c0, 0x1a2f8, 0x1a31c, 0x1a338, 0x1a370, 0x1a37e, 0x1a382, 0x1a384, 0x1a388, 0x1a390, 0x1a39e,\n 0x1a3a0, 0x1a3bc, 0x1a3c6, 0x1a3cc, 0x1a3d8, 0x1a3ee, 0x1a3f2, 0x1a3f4, 0x1a418, 0x1a430, 0x1a43e, 0x1a460,\n 0x1a47c, 0x1a4c0, 0x1a4f8, 0x1a5f0, 0x1a61c, 0x1a638, 0x1a670, 0x1a67e, 0x1a6e0, 0x1a6fc, 0x1a702, 0x1a704,\n 0x1a708, 0x1a710, 0x1a71e, 0x1a720, 0x1a73c, 0x1a740, 0x1a778, 0x1a786, 0x1a78c, 0x1a798, 0x1a7b0, 0x1a7be,\n 0x1a7ce, 0x1a7dc, 0x1a7e2, 0x1a7e4, 0x1a7e8, 0x1a830, 0x1a860, 0x1a87c, 0x1a8c0, 0x1a8f8, 0x1a9f0, 0x1abe0,\n 0x1ac70, 0x1ac7e, 0x1ace0, 0x1acfc, 0x1adc0, 0x1adf8, 0x1ae04, 0x1ae08, 0x1ae10, 0x1ae20, 0x1ae3c, 0x1ae40,\n 0x1ae78, 0x1aef0, 0x1af06, 0x1af0c, 0x1af18, 0x1af30, 0x1af3e, 0x1af60, 0x1af7c, 0x1af8e, 0x1af9c, 0x1afb8,\n 0x1afc4, 0x1afc8, 0x1afd0, 0x1afde, 0x1b042, 0x1b05e, 0x1b07a, 0x1b082, 0x1b084, 0x1b088, 0x1b090, 0x1b09e,\n 0x1b0a0, 0x1b0bc, 0x1b0cc, 0x1b0f2, 0x1b0f4, 0x1b102, 0x1b104, 0x1b108, 0x1b110, 0x1b11e, 0x1b120, 0x1b13c,\n 0x1b140, 0x1b178, 0x1b186, 0x1b198, 0x1b1ce, 0x1b1e2, 0x1b1e4, 0x1b1e8, 0x1b204, 0x1b208, 0x1b210, 0x1b21e,\n 0x1b220, 0x1b23c, 0x1b240, 0x1b278, 0x1b2f0, 0x1b30c, 0x1b33e, 0x1b360, 0x1b39c, 0x1b3c2, 0x1b3c4, 0x1b3c8,\n 0x1b3d0, 0x1b3e6, 0x1b410, 0x1b41e, 0x1b420, 0x1b43c, 0x1b440, 0x1b478, 0x1b4f0, 0x1b5e0, 0x1b618, 0x1b660,\n 0x1b67c, 0x1b6c0, 0x1b738, 0x1b782, 0x1b784, 0x1b788, 0x1b790, 0x1b79e, 0x1b7a0, 0x1b7cc, 0x1b82e, 0x1b84e,\n 0x1b85c, 0x1b88e, 0x1b89c, 0x1b8b8, 0x1b8c2, 0x1b8c4, 0x1b8c8, 0x1b8d0, 0x1b8e6, 0x1b8fa, 0x1b90e, 0x1b91c,\n 0x1b938, 0x1b970, 0x1b97e, 0x1b982, 0x1b984, 0x1b988, 0x1b990, 0x1b99e, 0x1b9a0, 0x1b9cc, 0x1b9f2, 0x1b9f4,\n 0x1ba0e, 0x1ba1c, 0x1ba38, 0x1ba70, 0x1ba7e, 0x1bae0, 0x1bafc, 0x1bb08, 0x1bb10, 0x1bb20, 0x1bb3c, 0x1bb40,\n 0x1bb98, 0x1bbce, 0x1bbe2, 0x1bbe4, 0x1bbe8, 0x1bc16, 0x1bc26, 0x1bc2c, 0x1bc46, 0x1bc4c, 0x1bc58, 0x1bc72,\n 0x1bc74, 0x1bc86, 0x1bc8c, 0x1bc98, 0x1bcb0, 0x1bcbe, 0x1bcce, 0x1bce2, 0x1bce4, 0x1bce8, 0x1bd06, 0x1bd0c,\n 0x1bd18, 0x1bd30, 0x1bd3e, 0x1bd60, 0x1bd7c, 0x1bd9c, 0x1bdc2, 0x1bdc4, 0x1bdc8, 0x1bdd0, 0x1bde6, 0x1bdfa,\n 0x1be12, 0x1be14, 0x1be22, 0x1be24, 0x1be28, 0x1be42, 0x1be44, 0x1be48, 0x1be50, 0x1be5e, 0x1be66, 0x1be82,\n 0x1be84, 0x1be88, 0x1be90, 0x1be9e, 0x1bea0, 0x1bebc, 0x1becc, 0x1bef4, 0x1bf1a, 0x1bf2e, 0x1bf32, 0x1bf34,\n 0x1bf4e, 0x1bf5c, 0x1bf62, 0x1bf64, 0x1bf68, 0x1c09a, 0x1c0b2, 0x1c0b4, 0x1c11a, 0x1c132, 0x1c134, 0x1c162,\n 0x1c164, 0x1c168, 0x1c176, 0x1c1ba, 0x1c21a, 0x1c232, 0x1c234, 0x1c24e, 0x1c25c, 0x1c262, 0x1c264, 0x1c268,\n 0x1c276, 0x1c28e, 0x1c2c2, 0x1c2c4, 0x1c2c8, 0x1c2d0, 0x1c2de, 0x1c2e6, 0x1c2ec, 0x1c2fa, 0x1c316, 0x1c326,\n 0x1c33a, 0x1c346, 0x1c34c, 0x1c372, 0x1c374, 0x1c41a, 0x1c42e, 0x1c432, 0x1c434, 0x1c44e, 0x1c45c, 0x1c462,\n 0x1c464, 0x1c468, 0x1c476, 0x1c48e, 0x1c49c, 0x1c4b8, 0x1c4c2, 0x1c4c8, 0x1c4d0, 0x1c4de, 0x1c4e6, 0x1c4ec,\n 0x1c4fa, 0x1c51c, 0x1c538, 0x1c570, 0x1c57e, 0x1c582, 0x1c584, 0x1c588, 0x1c590, 0x1c59e, 0x1c5a0, 0x1c5bc,\n 0x1c5c6, 0x1c5cc, 0x1c5d8, 0x1c5ee, 0x1c5f2, 0x1c5f4, 0x1c616, 0x1c626, 0x1c62c, 0x1c63a, 0x1c646, 0x1c64c,\n 0x1c658, 0x1c66e, 0x1c672, 0x1c674, 0x1c686, 0x1c68c, 0x1c698, 0x1c6b0, 0x1c6be, 0x1c6ce, 0x1c6dc, 0x1c6e2,\n 0x1c6e4, 0x1c6e8, 0x1c712, 0x1c714, 0x1c722, 0x1c728, 0x1c736, 0x1c742, 0x1c744, 0x1c748, 0x1c750, 0x1c75e,\n 0x1c766, 0x1c76c, 0x1c77a, 0x1c7ae, 0x1c7d6, 0x1c7ea, 0x1c81a, 0x1c82e, 0x1c832, 0x1c834, 0x1c84e, 0x1c85c,\n 0x1c862, 0x1c864, 0x1c868, 0x1c876, 0x1c88e, 0x1c89c, 0x1c8b8, 0x1c8c2, 0x1c8c8, 0x1c8d0, 0x1c8de, 0x1c8e6,\n 0x1c8ec, 0x1c8fa, 0x1c90e, 0x1c938, 0x1c970, 0x1c97e, 0x1c982, 0x1c984, 0x1c990, 0x1c99e, 0x1c9a0, 0x1c9bc,\n 0x1c9c6, 0x1c9cc, 0x1c9d8, 0x1c9ee, 0x1c9f2, 0x1c9f4, 0x1ca38, 0x1ca70, 0x1ca7e, 0x1cae0, 0x1cafc, 0x1cb02,\n 0x1cb04, 0x1cb08, 0x1cb10, 0x1cb20, 0x1cb3c, 0x1cb40, 0x1cb78, 0x1cb86, 0x1cb8c, 0x1cb98, 0x1cbb0, 0x1cbbe,\n 0x1cbce, 0x1cbdc, 0x1cbe2, 0x1cbe4, 0x1cbe8, 0x1cbf6, 0x1cc16, 0x1cc26, 0x1cc2c, 0x1cc3a, 0x1cc46, 0x1cc58,\n 0x1cc72, 0x1cc74, 0x1cc86, 0x1ccb0, 0x1ccbe, 0x1ccce, 0x1cce2, 0x1cce4, 0x1cce8, 0x1cd06, 0x1cd0c, 0x1cd18,\n 0x1cd30, 0x1cd3e, 0x1cd60, 0x1cd7c, 0x1cd9c, 0x1cdc2, 0x1cdc4, 0x1cdc8, 0x1cdd0, 0x1cdde, 0x1cde6, 0x1cdfa,\n 0x1ce22, 0x1ce28, 0x1ce42, 0x1ce50, 0x1ce5e, 0x1ce66, 0x1ce7a, 0x1ce82, 0x1ce84, 0x1ce88, 0x1ce90, 0x1ce9e,\n 0x1cea0, 0x1cebc, 0x1cecc, 0x1cef2, 0x1cef4, 0x1cf2e, 0x1cf32, 0x1cf34, 0x1cf4e, 0x1cf5c, 0x1cf62, 0x1cf64,\n 0x1cf68, 0x1cf96, 0x1cfa6, 0x1cfac, 0x1cfca, 0x1cfd2, 0x1cfd4, 0x1d02e, 0x1d032, 0x1d034, 0x1d04e, 0x1d05c,\n 0x1d062, 0x1d064, 0x1d068, 0x1d076, 0x1d08e, 0x1d09c, 0x1d0b8, 0x1d0c2, 0x1d0c4, 0x1d0c8, 0x1d0d0, 0x1d0de,\n 0x1d0e6, 0x1d0ec, 0x1d0fa, 0x1d11c, 0x1d138, 0x1d170, 0x1d17e, 0x1d182, 0x1d184, 0x1d188, 0x1d190, 0x1d19e,\n 0x1d1a0, 0x1d1bc, 0x1d1c6, 0x1d1cc, 0x1d1d8, 0x1d1ee, 0x1d1f2, 0x1d1f4, 0x1d21c, 0x1d238, 0x1d270, 0x1d27e,\n 0x1d2e0, 0x1d2fc, 0x1d302, 0x1d304, 0x1d308, 0x1d310, 0x1d31e, 0x1d320, 0x1d33c, 0x1d340, 0x1d378, 0x1d386,\n 0x1d38c, 0x1d398, 0x1d3b0, 0x1d3be, 0x1d3ce, 0x1d3dc, 0x1d3e2, 0x1d3e4, 0x1d3e8, 0x1d3f6, 0x1d470, 0x1d47e,\n 0x1d4e0, 0x1d4fc, 0x1d5c0, 0x1d5f8, 0x1d604, 0x1d608, 0x1d610, 0x1d620, 0x1d640, 0x1d678, 0x1d6f0, 0x1d706,\n 0x1d70c, 0x1d718, 0x1d730, 0x1d73e, 0x1d760, 0x1d77c, 0x1d78e, 0x1d79c, 0x1d7b8, 0x1d7c2, 0x1d7c4, 0x1d7c8,\n 0x1d7d0, 0x1d7de, 0x1d7e6, 0x1d7ec, 0x1d826, 0x1d82c, 0x1d83a, 0x1d846, 0x1d84c, 0x1d858, 0x1d872, 0x1d874,\n 0x1d886, 0x1d88c, 0x1d898, 0x1d8b0, 0x1d8be, 0x1d8ce, 0x1d8e2, 0x1d8e4, 0x1d8e8, 0x1d8f6, 0x1d90c, 0x1d918,\n 0x1d930, 0x1d93e, 0x1d960, 0x1d97c, 0x1d99c, 0x1d9c2, 0x1d9c4, 0x1d9c8, 0x1d9d0, 0x1d9e6, 0x1d9fa, 0x1da0c,\n 0x1da18, 0x1da30, 0x1da3e, 0x1da60, 0x1da7c, 0x1dac0, 0x1daf8, 0x1db38, 0x1db82, 0x1db84, 0x1db88, 0x1db90,\n 0x1db9e, 0x1dba0, 0x1dbcc, 0x1dbf2, 0x1dbf4, 0x1dc22, 0x1dc42, 0x1dc44, 0x1dc48, 0x1dc50, 0x1dc5e, 0x1dc66,\n 0x1dc7a, 0x1dc82, 0x1dc84, 0x1dc88, 0x1dc90, 0x1dc9e, 0x1dca0, 0x1dcbc, 0x1dccc, 0x1dcf2, 0x1dcf4, 0x1dd04,\n 0x1dd08, 0x1dd10, 0x1dd1e, 0x1dd20, 0x1dd3c, 0x1dd40, 0x1dd78, 0x1dd86, 0x1dd98, 0x1ddce, 0x1dde2, 0x1dde4,\n 0x1dde8, 0x1de2e, 0x1de32, 0x1de34, 0x1de4e, 0x1de5c, 0x1de62, 0x1de64, 0x1de68, 0x1de8e, 0x1de9c, 0x1deb8,\n 0x1dec2, 0x1dec4, 0x1dec8, 0x1ded0, 0x1dee6, 0x1defa, 0x1df16, 0x1df26, 0x1df2c, 0x1df46, 0x1df4c, 0x1df58,\n 0x1df72, 0x1df74, 0x1df8a, 0x1df92, 0x1df94, 0x1dfa2, 0x1dfa4, 0x1dfa8, 0x1e08a, 0x1e092, 0x1e094, 0x1e0a2,\n 0x1e0a4, 0x1e0a8, 0x1e0b6, 0x1e0da, 0x1e10a, 0x1e112, 0x1e114, 0x1e122, 0x1e124, 0x1e128, 0x1e136, 0x1e142,\n 0x1e144, 0x1e148, 0x1e150, 0x1e166, 0x1e16c, 0x1e17a, 0x1e19a, 0x1e1b2, 0x1e1b4, 0x1e20a, 0x1e212, 0x1e214,\n 0x1e222, 0x1e224, 0x1e228, 0x1e236, 0x1e242, 0x1e248, 0x1e250, 0x1e25e, 0x1e266, 0x1e26c, 0x1e27a, 0x1e282,\n 0x1e284, 0x1e288, 0x1e290, 0x1e2a0, 0x1e2bc, 0x1e2c6, 0x1e2cc, 0x1e2d8, 0x1e2ee, 0x1e2f2, 0x1e2f4, 0x1e31a,\n 0x1e332, 0x1e334, 0x1e35c, 0x1e362, 0x1e364, 0x1e368, 0x1e3ba, 0x1e40a, 0x1e412, 0x1e414, 0x1e422, 0x1e428,\n 0x1e436, 0x1e442, 0x1e448, 0x1e450, 0x1e45e, 0x1e466, 0x1e46c, 0x1e47a, 0x1e482, 0x1e484, 0x1e490, 0x1e49e,\n 0x1e4a0, 0x1e4bc, 0x1e4c6, 0x1e4cc, 0x1e4d8, 0x1e4ee, 0x1e4f2, 0x1e4f4, 0x1e502, 0x1e504, 0x1e508, 0x1e510,\n 0x1e51e, 0x1e520, 0x1e53c, 0x1e540, 0x1e578, 0x1e586, 0x1e58c, 0x1e598, 0x1e5b0, 0x1e5be, 0x1e5ce, 0x1e5dc,\n 0x1e5e2, 0x1e5e4, 0x1e5e8, 0x1e5f6, 0x1e61a, 0x1e62e, 0x1e632, 0x1e634, 0x1e64e, 0x1e65c, 0x1e662, 0x1e668,\n 0x1e68e, 0x1e69c, 0x1e6b8, 0x1e6c2, 0x1e6c4, 0x1e6c8, 0x1e6d0, 0x1e6e6, 0x1e6fa, 0x1e716, 0x1e726, 0x1e72c,\n 0x1e73a, 0x1e746, 0x1e74c, 0x1e758, 0x1e772, 0x1e774, 0x1e792, 0x1e794, 0x1e7a2, 0x1e7a4, 0x1e7a8, 0x1e7b6,\n 0x1e812, 0x1e814, 0x1e822, 0x1e824, 0x1e828, 0x1e836, 0x1e842, 0x1e844, 0x1e848, 0x1e850, 0x1e85e, 0x1e866,\n 0x1e86c, 0x1e87a, 0x1e882, 0x1e884, 0x1e888, 0x1e890, 0x1e89e, 0x1e8a0, 0x1e8bc, 0x1e8c6, 0x1e8cc, 0x1e8d8,\n 0x1e8ee, 0x1e8f2, 0x1e8f4, 0x1e902, 0x1e904, 0x1e908, 0x1e910, 0x1e920, 0x1e93c, 0x1e940, 0x1e978, 0x1e986,\n 0x1e98c, 0x1e998, 0x1e9b0, 0x1e9be, 0x1e9ce, 0x1e9dc, 0x1e9e2, 0x1e9e4, 0x1e9e8, 0x1e9f6, 0x1ea04, 0x1ea08,\n 0x1ea10, 0x1ea20, 0x1ea40, 0x1ea78, 0x1eaf0, 0x1eb06, 0x1eb0c, 0x1eb18, 0x1eb30, 0x1eb3e, 0x1eb60, 0x1eb7c,\n 0x1eb8e, 0x1eb9c, 0x1ebb8, 0x1ebc2, 0x1ebc4, 0x1ebc8, 0x1ebd0, 0x1ebde, 0x1ebe6, 0x1ebec, 0x1ec1a, 0x1ec2e,\n 0x1ec32, 0x1ec34, 0x1ec4e, 0x1ec5c, 0x1ec62, 0x1ec64, 0x1ec68, 0x1ec8e, 0x1ec9c, 0x1ecb8, 0x1ecc2, 0x1ecc4,\n 0x1ecc8, 0x1ecd0, 0x1ece6, 0x1ecfa, 0x1ed0e, 0x1ed1c, 0x1ed38, 0x1ed70, 0x1ed7e, 0x1ed82, 0x1ed84, 0x1ed88,\n 0x1ed90, 0x1ed9e, 0x1eda0, 0x1edcc, 0x1edf2, 0x1edf4, 0x1ee16, 0x1ee26, 0x1ee2c, 0x1ee3a, 0x1ee46, 0x1ee4c,\n 0x1ee58, 0x1ee6e, 0x1ee72, 0x1ee74, 0x1ee86, 0x1ee8c, 0x1ee98, 0x1eeb0, 0x1eebe, 0x1eece, 0x1eedc, 0x1eee2,\n 0x1eee4, 0x1eee8, 0x1ef12, 0x1ef22, 0x1ef24, 0x1ef28, 0x1ef36, 0x1ef42, 0x1ef44, 0x1ef48, 0x1ef50, 0x1ef5e,\n 0x1ef66, 0x1ef6c, 0x1ef7a, 0x1efae, 0x1efb2, 0x1efb4, 0x1efd6, 0x1f096, 0x1f0a6, 0x1f0ac, 0x1f0ba, 0x1f0ca,\n 0x1f0d2, 0x1f0d4, 0x1f116, 0x1f126, 0x1f12c, 0x1f13a, 0x1f146, 0x1f14c, 0x1f158, 0x1f16e, 0x1f172, 0x1f174,\n 0x1f18a, 0x1f192, 0x1f194, 0x1f1a2, 0x1f1a4, 0x1f1a8, 0x1f1da, 0x1f216, 0x1f226, 0x1f22c, 0x1f23a, 0x1f246,\n 0x1f258, 0x1f26e, 0x1f272, 0x1f274, 0x1f286, 0x1f28c, 0x1f298, 0x1f2b0, 0x1f2be, 0x1f2ce, 0x1f2dc, 0x1f2e2,\n 0x1f2e4, 0x1f2e8, 0x1f2f6, 0x1f30a, 0x1f312, 0x1f314, 0x1f322, 0x1f328, 0x1f342, 0x1f344, 0x1f348, 0x1f350,\n 0x1f35e, 0x1f366, 0x1f37a, 0x1f39a, 0x1f3ae, 0x1f3b2, 0x1f3b4, 0x1f416, 0x1f426, 0x1f42c, 0x1f43a, 0x1f446,\n 0x1f44c, 0x1f458, 0x1f46e, 0x1f472, 0x1f474, 0x1f486, 0x1f48c, 0x1f498, 0x1f4b0, 0x1f4be, 0x1f4ce, 0x1f4dc,\n 0x1f4e2, 0x1f4e4, 0x1f4e8, 0x1f4f6, 0x1f506, 0x1f50c, 0x1f518, 0x1f530, 0x1f53e, 0x1f560, 0x1f57c, 0x1f58e,\n 0x1f59c, 0x1f5b8, 0x1f5c2, 0x1f5c4, 0x1f5c8, 0x1f5d0, 0x1f5de, 0x1f5e6, 0x1f5ec, 0x1f5fa, 0x1f60a, 0x1f612,\n 0x1f614, 0x1f622, 0x1f624, 0x1f628, 0x1f636, 0x1f642, 0x1f644, 0x1f648, 0x1f650, 0x1f65e, 0x1f666, 0x1f67a,\n 0x1f682, 0x1f684, 0x1f688, 0x1f690, 0x1f69e, 0x1f6a0, 0x1f6bc, 0x1f6cc, 0x1f6f2, 0x1f6f4, 0x1f71a, 0x1f72e,\n 0x1f732, 0x1f734, 0x1f74e, 0x1f75c, 0x1f762, 0x1f764, 0x1f768, 0x1f776, 0x1f796, 0x1f7a6, 0x1f7ac, 0x1f7ba,\n 0x1f7d2, 0x1f7d4, 0x1f89a, 0x1f8ae, 0x1f8b2, 0x1f8b4, 0x1f8d6, 0x1f8ea, 0x1f91a, 0x1f92e, 0x1f932, 0x1f934,\n 0x1f94e, 0x1f95c, 0x1f962, 0x1f964, 0x1f968, 0x1f976, 0x1f996, 0x1f9a6, 0x1f9ac, 0x1f9ba, 0x1f9ca, 0x1f9d2,\n 0x1f9d4, 0x1fa1a, 0x1fa2e, 0x1fa32, 0x1fa34, 0x1fa4e, 0x1fa5c, 0x1fa62, 0x1fa64, 0x1fa68, 0x1fa76, 0x1fa8e,\n 0x1fa9c, 0x1fab8, 0x1fac2, 0x1fac4, 0x1fac8, 0x1fad0, 0x1fade, 0x1fae6, 0x1faec, 0x1fb16, 0x1fb26, 0x1fb2c,\n 0x1fb3a, 0x1fb46, 0x1fb4c, 0x1fb58, 0x1fb6e, 0x1fb72, 0x1fb74, 0x1fb8a, 0x1fb92, 0x1fb94, 0x1fba2, 0x1fba4,\n 0x1fba8, 0x1fbb6, 0x1fbda\n ]);\n /**\n * This table contains to codewords for all symbols.\n */\n PDF417Common.CODEWORD_TABLE = Int32Array.from([\n 2627, 1819, 2622, 2621, 1813, 1812, 2729, 2724, 2723, 2779, 2774, 2773, 902, 896, 908, 868, 865, 861, 859, 2511,\n 873, 871, 1780, 835, 2493, 825, 2491, 842, 837, 844, 1764, 1762, 811, 810, 809, 2483, 807, 2482, 806, 2480, 815,\n 814, 813, 812, 2484, 817, 816, 1745, 1744, 1742, 1746, 2655, 2637, 2635, 2626, 2625, 2623, 2628, 1820, 2752,\n 2739, 2737, 2728, 2727, 2725, 2730, 2785, 2783, 2778, 2777, 2775, 2780, 787, 781, 747, 739, 736, 2413, 754, 752,\n 1719, 692, 689, 681, 2371, 678, 2369, 700, 697, 694, 703, 1688, 1686, 642, 638, 2343, 631, 2341, 627, 2338, 651,\n 646, 643, 2345, 654, 652, 1652, 1650, 1647, 1654, 601, 599, 2322, 596, 2321, 594, 2319, 2317, 611, 610, 608, 606,\n 2324, 603, 2323, 615, 614, 612, 1617, 1616, 1614, 1612, 616, 1619, 1618, 2575, 2538, 2536, 905, 901, 898, 909,\n 2509, 2507, 2504, 870, 867, 864, 860, 2512, 875, 872, 1781, 2490, 2489, 2487, 2485, 1748, 836, 834, 832, 830,\n 2494, 827, 2492, 843, 841, 839, 845, 1765, 1763, 2701, 2676, 2674, 2653, 2648, 2656, 2634, 2633, 2631, 2629,\n 1821, 2638, 2636, 2770, 2763, 2761, 2750, 2745, 2753, 2736, 2735, 2733, 2731, 1848, 2740, 2738, 2786, 2784, 591,\n 588, 576, 569, 566, 2296, 1590, 537, 534, 526, 2276, 522, 2274, 545, 542, 539, 548, 1572, 1570, 481, 2245, 466,\n 2242, 462, 2239, 492, 485, 482, 2249, 496, 494, 1534, 1531, 1528, 1538, 413, 2196, 406, 2191, 2188, 425, 419,\n 2202, 415, 2199, 432, 430, 427, 1472, 1467, 1464, 433, 1476, 1474, 368, 367, 2160, 365, 2159, 362, 2157, 2155,\n 2152, 378, 377, 375, 2166, 372, 2165, 369, 2162, 383, 381, 379, 2168, 1419, 1418, 1416, 1414, 385, 1411, 384,\n 1423, 1422, 1420, 1424, 2461, 802, 2441, 2439, 790, 786, 783, 794, 2409, 2406, 2403, 750, 742, 738, 2414, 756,\n 753, 1720, 2367, 2365, 2362, 2359, 1663, 693, 691, 684, 2373, 680, 2370, 702, 699, 696, 704, 1690, 1687, 2337,\n 2336, 2334, 2332, 1624, 2329, 1622, 640, 637, 2344, 634, 2342, 630, 2340, 650, 648, 645, 2346, 655, 653, 1653,\n 1651, 1649, 1655, 2612, 2597, 2595, 2571, 2568, 2565, 2576, 2534, 2529, 2526, 1787, 2540, 2537, 907, 904, 900,\n 910, 2503, 2502, 2500, 2498, 1768, 2495, 1767, 2510, 2508, 2506, 869, 866, 863, 2513, 876, 874, 1782, 2720, 2713,\n 2711, 2697, 2694, 2691, 2702, 2672, 2670, 2664, 1828, 2678, 2675, 2647, 2646, 2644, 2642, 1823, 2639, 1822, 2654,\n 2652, 2650, 2657, 2771, 1855, 2765, 2762, 1850, 1849, 2751, 2749, 2747, 2754, 353, 2148, 344, 342, 336, 2142,\n 332, 2140, 345, 1375, 1373, 306, 2130, 299, 2128, 295, 2125, 319, 314, 311, 2132, 1354, 1352, 1349, 1356, 262,\n 257, 2101, 253, 2096, 2093, 274, 273, 267, 2107, 263, 2104, 280, 278, 275, 1316, 1311, 1308, 1320, 1318, 2052,\n 202, 2050, 2044, 2040, 219, 2063, 212, 2060, 208, 2055, 224, 221, 2066, 1260, 1258, 1252, 231, 1248, 229, 1266,\n 1264, 1261, 1268, 155, 1998, 153, 1996, 1994, 1991, 1988, 165, 164, 2007, 162, 2006, 159, 2003, 2000, 172, 171,\n 169, 2012, 166, 2010, 1186, 1184, 1182, 1179, 175, 1176, 173, 1192, 1191, 1189, 1187, 176, 1194, 1193, 2313,\n 2307, 2305, 592, 589, 2294, 2292, 2289, 578, 572, 568, 2297, 580, 1591, 2272, 2267, 2264, 1547, 538, 536, 529,\n 2278, 525, 2275, 547, 544, 541, 1574, 1571, 2237, 2235, 2229, 1493, 2225, 1489, 478, 2247, 470, 2244, 465, 2241,\n 493, 488, 484, 2250, 498, 495, 1536, 1533, 1530, 1539, 2187, 2186, 2184, 2182, 1432, 2179, 1430, 2176, 1427, 414,\n 412, 2197, 409, 2195, 405, 2193, 2190, 426, 424, 421, 2203, 418, 2201, 431, 429, 1473, 1471, 1469, 1466, 434,\n 1477, 1475, 2478, 2472, 2470, 2459, 2457, 2454, 2462, 803, 2437, 2432, 2429, 1726, 2443, 2440, 792, 789, 785,\n 2401, 2399, 2393, 1702, 2389, 1699, 2411, 2408, 2405, 745, 741, 2415, 758, 755, 1721, 2358, 2357, 2355, 2353,\n 1661, 2350, 1660, 2347, 1657, 2368, 2366, 2364, 2361, 1666, 690, 687, 2374, 683, 2372, 701, 698, 705, 1691, 1689,\n 2619, 2617, 2610, 2608, 2605, 2613, 2593, 2588, 2585, 1803, 2599, 2596, 2563, 2561, 2555, 1797, 2551, 1795, 2573,\n 2570, 2567, 2577, 2525, 2524, 2522, 2520, 1786, 2517, 1785, 2514, 1783, 2535, 2533, 2531, 2528, 1788, 2541, 2539,\n 906, 903, 911, 2721, 1844, 2715, 2712, 1838, 1836, 2699, 2696, 2693, 2703, 1827, 1826, 1824, 2673, 2671, 2669,\n 2666, 1829, 2679, 2677, 1858, 1857, 2772, 1854, 1853, 1851, 1856, 2766, 2764, 143, 1987, 139, 1986, 135, 133,\n 131, 1984, 128, 1983, 125, 1981, 138, 137, 136, 1985, 1133, 1132, 1130, 112, 110, 1974, 107, 1973, 104, 1971,\n 1969, 122, 121, 119, 117, 1977, 114, 1976, 124, 1115, 1114, 1112, 1110, 1117, 1116, 84, 83, 1953, 81, 1952, 78,\n 1950, 1948, 1945, 94, 93, 91, 1959, 88, 1958, 85, 1955, 99, 97, 95, 1961, 1086, 1085, 1083, 1081, 1078, 100,\n 1090, 1089, 1087, 1091, 49, 47, 1917, 44, 1915, 1913, 1910, 1907, 59, 1926, 56, 1925, 53, 1922, 1919, 66, 64,\n 1931, 61, 1929, 1042, 1040, 1038, 71, 1035, 70, 1032, 68, 1048, 1047, 1045, 1043, 1050, 1049, 12, 10, 1869, 1867,\n 1864, 1861, 21, 1880, 19, 1877, 1874, 1871, 28, 1888, 25, 1886, 22, 1883, 982, 980, 977, 974, 32, 30, 991, 989,\n 987, 984, 34, 995, 994, 992, 2151, 2150, 2147, 2146, 2144, 356, 355, 354, 2149, 2139, 2138, 2136, 2134, 1359,\n 343, 341, 338, 2143, 335, 2141, 348, 347, 346, 1376, 1374, 2124, 2123, 2121, 2119, 1326, 2116, 1324, 310, 308,\n 305, 2131, 302, 2129, 298, 2127, 320, 318, 316, 313, 2133, 322, 321, 1355, 1353, 1351, 1357, 2092, 2091, 2089,\n 2087, 1276, 2084, 1274, 2081, 1271, 259, 2102, 256, 2100, 252, 2098, 2095, 272, 269, 2108, 266, 2106, 281, 279,\n 277, 1317, 1315, 1313, 1310, 282, 1321, 1319, 2039, 2037, 2035, 2032, 1203, 2029, 1200, 1197, 207, 2053, 205,\n 2051, 201, 2049, 2046, 2043, 220, 218, 2064, 215, 2062, 211, 2059, 228, 226, 223, 2069, 1259, 1257, 1254, 232,\n 1251, 230, 1267, 1265, 1263, 2316, 2315, 2312, 2311, 2309, 2314, 2304, 2303, 2301, 2299, 1593, 2308, 2306, 590,\n 2288, 2287, 2285, 2283, 1578, 2280, 1577, 2295, 2293, 2291, 579, 577, 574, 571, 2298, 582, 581, 1592, 2263, 2262,\n 2260, 2258, 1545, 2255, 1544, 2252, 1541, 2273, 2271, 2269, 2266, 1550, 535, 532, 2279, 528, 2277, 546, 543, 549,\n 1575, 1573, 2224, 2222, 2220, 1486, 2217, 1485, 2214, 1482, 1479, 2238, 2236, 2234, 2231, 1496, 2228, 1492, 480,\n 477, 2248, 473, 2246, 469, 2243, 490, 487, 2251, 497, 1537, 1535, 1532, 2477, 2476, 2474, 2479, 2469, 2468, 2466,\n 2464, 1730, 2473, 2471, 2453, 2452, 2450, 2448, 1729, 2445, 1728, 2460, 2458, 2456, 2463, 805, 804, 2428, 2427,\n 2425, 2423, 1725, 2420, 1724, 2417, 1722, 2438, 2436, 2434, 2431, 1727, 2444, 2442, 793, 791, 788, 795, 2388,\n 2386, 2384, 1697, 2381, 1696, 2378, 1694, 1692, 2402, 2400, 2398, 2395, 1703, 2392, 1701, 2412, 2410, 2407, 751,\n 748, 744, 2416, 759, 757, 1807, 2620, 2618, 1806, 1805, 2611, 2609, 2607, 2614, 1802, 1801, 1799, 2594, 2592,\n 2590, 2587, 1804, 2600, 2598, 1794, 1793, 1791, 1789, 2564, 2562, 2560, 2557, 1798, 2554, 1796, 2574, 2572, 2569,\n 2578, 1847, 1846, 2722, 1843, 1842, 1840, 1845, 2716, 2714, 1835, 1834, 1832, 1830, 1839, 1837, 2700, 2698, 2695,\n 2704, 1817, 1811, 1810, 897, 862, 1777, 829, 826, 838, 1760, 1758, 808, 2481, 1741, 1740, 1738, 1743, 2624, 1818,\n 2726, 2776, 782, 740, 737, 1715, 686, 679, 695, 1682, 1680, 639, 628, 2339, 647, 644, 1645, 1643, 1640, 1648,\n 602, 600, 597, 595, 2320, 593, 2318, 609, 607, 604, 1611, 1610, 1608, 1606, 613, 1615, 1613, 2328, 926, 924, 892,\n 886, 899, 857, 850, 2505, 1778, 824, 823, 821, 819, 2488, 818, 2486, 833, 831, 828, 840, 1761, 1759, 2649, 2632,\n 2630, 2746, 2734, 2732, 2782, 2781, 570, 567, 1587, 531, 527, 523, 540, 1566, 1564, 476, 467, 463, 2240, 486,\n 483, 1524, 1521, 1518, 1529, 411, 403, 2192, 399, 2189, 423, 416, 1462, 1457, 1454, 428, 1468, 1465, 2210, 366,\n 363, 2158, 360, 2156, 357, 2153, 376, 373, 370, 2163, 1410, 1409, 1407, 1405, 382, 1402, 380, 1417, 1415, 1412,\n 1421, 2175, 2174, 777, 774, 771, 784, 732, 725, 722, 2404, 743, 1716, 676, 674, 668, 2363, 665, 2360, 685, 1684,\n 1681, 626, 624, 622, 2335, 620, 2333, 617, 2330, 641, 635, 649, 1646, 1644, 1642, 2566, 928, 925, 2530, 2527,\n 894, 891, 888, 2501, 2499, 2496, 858, 856, 854, 851, 1779, 2692, 2668, 2665, 2645, 2643, 2640, 2651, 2768, 2759,\n 2757, 2744, 2743, 2741, 2748, 352, 1382, 340, 337, 333, 1371, 1369, 307, 300, 296, 2126, 315, 312, 1347, 1342,\n 1350, 261, 258, 250, 2097, 246, 2094, 271, 268, 264, 1306, 1301, 1298, 276, 1312, 1309, 2115, 203, 2048, 195,\n 2045, 191, 2041, 213, 209, 2056, 1246, 1244, 1238, 225, 1234, 222, 1256, 1253, 1249, 1262, 2080, 2079, 154, 1997,\n 150, 1995, 147, 1992, 1989, 163, 160, 2004, 156, 2001, 1175, 1174, 1172, 1170, 1167, 170, 1164, 167, 1185, 1183,\n 1180, 1177, 174, 1190, 1188, 2025, 2024, 2022, 587, 586, 564, 559, 556, 2290, 573, 1588, 520, 518, 512, 2268,\n 508, 2265, 530, 1568, 1565, 461, 457, 2233, 450, 2230, 446, 2226, 479, 471, 489, 1526, 1523, 1520, 397, 395,\n 2185, 392, 2183, 389, 2180, 2177, 410, 2194, 402, 422, 1463, 1461, 1459, 1456, 1470, 2455, 799, 2433, 2430, 779,\n 776, 773, 2397, 2394, 2390, 734, 728, 724, 746, 1717, 2356, 2354, 2351, 2348, 1658, 677, 675, 673, 670, 667, 688,\n 1685, 1683, 2606, 2589, 2586, 2559, 2556, 2552, 927, 2523, 2521, 2518, 2515, 1784, 2532, 895, 893, 890, 2718,\n 2709, 2707, 2689, 2687, 2684, 2663, 2662, 2660, 2658, 1825, 2667, 2769, 1852, 2760, 2758, 142, 141, 1139, 1138,\n 134, 132, 129, 126, 1982, 1129, 1128, 1126, 1131, 113, 111, 108, 105, 1972, 101, 1970, 120, 118, 115, 1109, 1108,\n 1106, 1104, 123, 1113, 1111, 82, 79, 1951, 75, 1949, 72, 1946, 92, 89, 86, 1956, 1077, 1076, 1074, 1072, 98,\n 1069, 96, 1084, 1082, 1079, 1088, 1968, 1967, 48, 45, 1916, 42, 1914, 39, 1911, 1908, 60, 57, 54, 1923, 50, 1920,\n 1031, 1030, 1028, 1026, 67, 1023, 65, 1020, 62, 1041, 1039, 1036, 1033, 69, 1046, 1044, 1944, 1943, 1941, 11, 9,\n 1868, 7, 1865, 1862, 1859, 20, 1878, 16, 1875, 13, 1872, 970, 968, 966, 963, 29, 960, 26, 23, 983, 981, 978, 975,\n 33, 971, 31, 990, 988, 985, 1906, 1904, 1902, 993, 351, 2145, 1383, 331, 330, 328, 326, 2137, 323, 2135, 339,\n 1372, 1370, 294, 293, 291, 289, 2122, 286, 2120, 283, 2117, 309, 303, 317, 1348, 1346, 1344, 245, 244, 242, 2090,\n 239, 2088, 236, 2085, 2082, 260, 2099, 249, 270, 1307, 1305, 1303, 1300, 1314, 189, 2038, 186, 2036, 183, 2033,\n 2030, 2026, 206, 198, 2047, 194, 216, 1247, 1245, 1243, 1240, 227, 1237, 1255, 2310, 2302, 2300, 2286, 2284,\n 2281, 565, 563, 561, 558, 575, 1589, 2261, 2259, 2256, 2253, 1542, 521, 519, 517, 514, 2270, 511, 533, 1569,\n 1567, 2223, 2221, 2218, 2215, 1483, 2211, 1480, 459, 456, 453, 2232, 449, 474, 491, 1527, 1525, 1522, 2475, 2467,\n 2465, 2451, 2449, 2446, 801, 800, 2426, 2424, 2421, 2418, 1723, 2435, 780, 778, 775, 2387, 2385, 2382, 2379,\n 1695, 2375, 1693, 2396, 735, 733, 730, 727, 749, 1718, 2616, 2615, 2604, 2603, 2601, 2584, 2583, 2581, 2579,\n 1800, 2591, 2550, 2549, 2547, 2545, 1792, 2542, 1790, 2558, 929, 2719, 1841, 2710, 2708, 1833, 1831, 2690, 2688,\n 2686, 1815, 1809, 1808, 1774, 1756, 1754, 1737, 1736, 1734, 1739, 1816, 1711, 1676, 1674, 633, 629, 1638, 1636,\n 1633, 1641, 598, 1605, 1604, 1602, 1600, 605, 1609, 1607, 2327, 887, 853, 1775, 822, 820, 1757, 1755, 1584, 524,\n 1560, 1558, 468, 464, 1514, 1511, 1508, 1519, 408, 404, 400, 1452, 1447, 1444, 417, 1458, 1455, 2208, 364, 361,\n 358, 2154, 1401, 1400, 1398, 1396, 374, 1393, 371, 1408, 1406, 1403, 1413, 2173, 2172, 772, 726, 723, 1712, 672,\n 669, 666, 682, 1678, 1675, 625, 623, 621, 618, 2331, 636, 632, 1639, 1637, 1635, 920, 918, 884, 880, 889, 849,\n 848, 847, 846, 2497, 855, 852, 1776, 2641, 2742, 2787, 1380, 334, 1367, 1365, 301, 297, 1340, 1338, 1335, 1343,\n 255, 251, 247, 1296, 1291, 1288, 265, 1302, 1299, 2113, 204, 196, 192, 2042, 1232, 1230, 1224, 214, 1220, 210,\n 1242, 1239, 1235, 1250, 2077, 2075, 151, 148, 1993, 144, 1990, 1163, 1162, 1160, 1158, 1155, 161, 1152, 157,\n 1173, 1171, 1168, 1165, 168, 1181, 1178, 2021, 2020, 2018, 2023, 585, 560, 557, 1585, 516, 509, 1562, 1559, 458,\n 447, 2227, 472, 1516, 1513, 1510, 398, 396, 393, 390, 2181, 386, 2178, 407, 1453, 1451, 1449, 1446, 420, 1460,\n 2209, 769, 764, 720, 712, 2391, 729, 1713, 664, 663, 661, 659, 2352, 656, 2349, 671, 1679, 1677, 2553, 922, 919,\n 2519, 2516, 885, 883, 881, 2685, 2661, 2659, 2767, 2756, 2755, 140, 1137, 1136, 130, 127, 1125, 1124, 1122, 1127,\n 109, 106, 102, 1103, 1102, 1100, 1098, 116, 1107, 1105, 1980, 80, 76, 73, 1947, 1068, 1067, 1065, 1063, 90, 1060,\n 87, 1075, 1073, 1070, 1080, 1966, 1965, 46, 43, 40, 1912, 36, 1909, 1019, 1018, 1016, 1014, 58, 1011, 55, 1008,\n 51, 1029, 1027, 1024, 1021, 63, 1037, 1034, 1940, 1939, 1937, 1942, 8, 1866, 4, 1863, 1, 1860, 956, 954, 952,\n 949, 946, 17, 14, 969, 967, 964, 961, 27, 957, 24, 979, 976, 972, 1901, 1900, 1898, 1896, 986, 1905, 1903, 350,\n 349, 1381, 329, 327, 324, 1368, 1366, 292, 290, 287, 284, 2118, 304, 1341, 1339, 1337, 1345, 243, 240, 237, 2086,\n 233, 2083, 254, 1297, 1295, 1293, 1290, 1304, 2114, 190, 187, 184, 2034, 180, 2031, 177, 2027, 199, 1233, 1231,\n 1229, 1226, 217, 1223, 1241, 2078, 2076, 584, 555, 554, 552, 550, 2282, 562, 1586, 507, 506, 504, 502, 2257, 499,\n 2254, 515, 1563, 1561, 445, 443, 441, 2219, 438, 2216, 435, 2212, 460, 454, 475, 1517, 1515, 1512, 2447, 798,\n 797, 2422, 2419, 770, 768, 766, 2383, 2380, 2376, 721, 719, 717, 714, 731, 1714, 2602, 2582, 2580, 2548, 2546,\n 2543, 923, 921, 2717, 2706, 2705, 2683, 2682, 2680, 1771, 1752, 1750, 1733, 1732, 1731, 1735, 1814, 1707, 1670,\n 1668, 1631, 1629, 1626, 1634, 1599, 1598, 1596, 1594, 1603, 1601, 2326, 1772, 1753, 1751, 1581, 1554, 1552, 1504,\n 1501, 1498, 1509, 1442, 1437, 1434, 401, 1448, 1445, 2206, 1392, 1391, 1389, 1387, 1384, 359, 1399, 1397, 1394,\n 1404, 2171, 2170, 1708, 1672, 1669, 619, 1632, 1630, 1628, 1773, 1378, 1363, 1361, 1333, 1328, 1336, 1286, 1281,\n 1278, 248, 1292, 1289, 2111, 1218, 1216, 1210, 197, 1206, 193, 1228, 1225, 1221, 1236, 2073, 2071, 1151, 1150,\n 1148, 1146, 152, 1143, 149, 1140, 145, 1161, 1159, 1156, 1153, 158, 1169, 1166, 2017, 2016, 2014, 2019, 1582,\n 510, 1556, 1553, 452, 448, 1506, 1500, 394, 391, 387, 1443, 1441, 1439, 1436, 1450, 2207, 765, 716, 713, 1709,\n 662, 660, 657, 1673, 1671, 916, 914, 879, 878, 877, 882, 1135, 1134, 1121, 1120, 1118, 1123, 1097, 1096, 1094,\n 1092, 103, 1101, 1099, 1979, 1059, 1058, 1056, 1054, 77, 1051, 74, 1066, 1064, 1061, 1071, 1964, 1963, 1007,\n 1006, 1004, 1002, 999, 41, 996, 37, 1017, 1015, 1012, 1009, 52, 1025, 1022, 1936, 1935, 1933, 1938, 942, 940,\n 938, 935, 932, 5, 2, 955, 953, 950, 947, 18, 943, 15, 965, 962, 958, 1895, 1894, 1892, 1890, 973, 1899, 1897,\n 1379, 325, 1364, 1362, 288, 285, 1334, 1332, 1330, 241, 238, 234, 1287, 1285, 1283, 1280, 1294, 2112, 188, 185,\n 181, 178, 2028, 1219, 1217, 1215, 1212, 200, 1209, 1227, 2074, 2072, 583, 553, 551, 1583, 505, 503, 500, 513,\n 1557, 1555, 444, 442, 439, 436, 2213, 455, 451, 1507, 1505, 1502, 796, 763, 762, 760, 767, 711, 710, 708, 706,\n 2377, 718, 715, 1710, 2544, 917, 915, 2681, 1627, 1597, 1595, 2325, 1769, 1749, 1747, 1499, 1438, 1435, 2204,\n 1390, 1388, 1385, 1395, 2169, 2167, 1704, 1665, 1662, 1625, 1623, 1620, 1770, 1329, 1282, 1279, 2109, 1214, 1207,\n 1222, 2068, 2065, 1149, 1147, 1144, 1141, 146, 1157, 1154, 2013, 2011, 2008, 2015, 1579, 1549, 1546, 1495, 1487,\n 1433, 1431, 1428, 1425, 388, 1440, 2205, 1705, 658, 1667, 1664, 1119, 1095, 1093, 1978, 1057, 1055, 1052, 1062,\n 1962, 1960, 1005, 1003, 1000, 997, 38, 1013, 1010, 1932, 1930, 1927, 1934, 941, 939, 936, 933, 6, 930, 3, 951,\n 948, 944, 1889, 1887, 1884, 1881, 959, 1893, 1891, 35, 1377, 1360, 1358, 1327, 1325, 1322, 1331, 1277, 1275,\n 1272, 1269, 235, 1284, 2110, 1205, 1204, 1201, 1198, 182, 1195, 179, 1213, 2070, 2067, 1580, 501, 1551, 1548,\n 440, 437, 1497, 1494, 1490, 1503, 761, 709, 707, 1706, 913, 912, 2198, 1386, 2164, 2161, 1621, 1766, 2103, 1208,\n 2058, 2054, 1145, 1142, 2005, 2002, 1999, 2009, 1488, 1429, 1426, 2200, 1698, 1659, 1656, 1975, 1053, 1957, 1954,\n 1001, 998, 1924, 1921, 1918, 1928, 937, 934, 931, 1879, 1876, 1873, 1870, 945, 1885, 1882, 1323, 1273, 1270,\n 2105, 1202, 1199, 1196, 1211, 2061, 2057, 1576, 1543, 1540, 1484, 1481, 1478, 1491, 1700\n ]);\n\n /*\n * Copyright 2007 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n // import java.util.List;\n /**\n * @author Guenther Grau\n */\n /*public final*/ class PDF417DetectorResult {\n constructor(bits, points) {\n this.bits = bits;\n this.points = points;\n }\n getBits() {\n return this.bits;\n }\n getPoints() {\n return this.points;\n }\n }\n\n /*\n * Copyright 2009 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n // import java.util.ArrayList;\n // import java.util.Arrays;\n // import java.util.List;\n // import java.util.Map;\n /**\n *

Encapsulates logic that can detect a PDF417 Code in an image, even if the\n * PDF417 Code is rotated or skewed, or partially obscured.

\n *\n * @author SITA Lab (kevin.osullivan@sita.aero)\n * @author dswitkin@google.com (Daniel Switkin)\n * @author Guenther Grau\n */\n /*public*/ /*final*/ class Detector$3 {\n /**\n *

Detects a PDF417 Code in an image. Only checks 0 and 180 degree rotations.

\n *\n * @param image barcode image to decode\n * @param hints optional hints to detector\n * @param multiple if true, then the image is searched for multiple codes. If false, then at most one code will\n * be found and returned\n * @return {@link PDF417DetectorResult} encapsulating results of detecting a PDF417 code\n * @throws NotFoundException if no PDF417 Code can be found\n */\n static detectMultiple(image, hints, multiple) {\n // TODO detection improvement, tryHarder could try several different luminance thresholds/blackpoints or even\n // different binarizers\n // boolean tryHarder = hints != null && hints.containsKey(DecodeHintType.TRY_HARDER);\n let bitMatrix = image.getBlackMatrix();\n let barcodeCoordinates = Detector$3.detect(multiple, bitMatrix);\n if (!barcodeCoordinates.length) {\n bitMatrix = bitMatrix.clone();\n bitMatrix.rotate180();\n barcodeCoordinates = Detector$3.detect(multiple, bitMatrix);\n }\n return new PDF417DetectorResult(bitMatrix, barcodeCoordinates);\n }\n /**\n * Detects PDF417 codes in an image. Only checks 0 degree rotation\n * @param multiple if true, then the image is searched for multiple codes. If false, then at most one code will\n * be found and returned\n * @param bitMatrix bit matrix to detect barcodes in\n * @return List of ResultPoint arrays containing the coordinates of found barcodes\n */\n static detect(multiple, bitMatrix) {\n const barcodeCoordinates = new Array();\n let row = 0;\n let column = 0;\n let foundBarcodeInRow = false;\n while (row < bitMatrix.getHeight()) {\n const vertices = Detector$3.findVertices(bitMatrix, row, column);\n if (vertices[0] == null && vertices[3] == null) {\n if (!foundBarcodeInRow) {\n // we didn't find any barcode so that's the end of searching\n break;\n }\n // we didn't find a barcode starting at the given column and row. Try again from the first column and slightly\n // below the lowest barcode we found so far.\n foundBarcodeInRow = false;\n column = 0;\n for (const barcodeCoordinate of barcodeCoordinates) {\n if (barcodeCoordinate[1] != null) {\n row = Math.trunc(Math.max(row, barcodeCoordinate[1].getY()));\n }\n if (barcodeCoordinate[3] != null) {\n row = Math.max(row, Math.trunc(barcodeCoordinate[3].getY()));\n }\n }\n row += Detector$3.ROW_STEP;\n continue;\n }\n foundBarcodeInRow = true;\n barcodeCoordinates.push(vertices);\n if (!multiple) {\n break;\n }\n // if we didn't find a right row indicator column, then continue the search for the next barcode after the\n // start pattern of the barcode just found.\n if (vertices[2] != null) {\n column = Math.trunc(vertices[2].getX());\n row = Math.trunc(vertices[2].getY());\n }\n else {\n column = Math.trunc(vertices[4].getX());\n row = Math.trunc(vertices[4].getY());\n }\n }\n return barcodeCoordinates;\n }\n /**\n * Locate the vertices and the codewords area of a black blob using the Start\n * and Stop patterns as locators.\n *\n * @param matrix the scanned barcode image.\n * @return an array containing the vertices:\n * vertices[0] x, y top left barcode\n * vertices[1] x, y bottom left barcode\n * vertices[2] x, y top right barcode\n * vertices[3] x, y bottom right barcode\n * vertices[4] x, y top left codeword area\n * vertices[5] x, y bottom left codeword area\n * vertices[6] x, y top right codeword area\n * vertices[7] x, y bottom right codeword area\n */\n static findVertices(matrix, startRow, startColumn) {\n const height = matrix.getHeight();\n const width = matrix.getWidth();\n // const result = new ResultPoint[8];\n const result = new Array(8);\n Detector$3.copyToResult(result, Detector$3.findRowsWithPattern(matrix, height, width, startRow, startColumn, Detector$3.START_PATTERN), Detector$3.INDEXES_START_PATTERN);\n if (result[4] != null) {\n startColumn = Math.trunc(result[4].getX());\n startRow = Math.trunc(result[4].getY());\n }\n Detector$3.copyToResult(result, Detector$3.findRowsWithPattern(matrix, height, width, startRow, startColumn, Detector$3.STOP_PATTERN), Detector$3.INDEXES_STOP_PATTERN);\n return result;\n }\n static copyToResult(result, tmpResult, destinationIndexes) {\n for (let i = 0; i < destinationIndexes.length; i++) {\n result[destinationIndexes[i]] = tmpResult[i];\n }\n }\n static findRowsWithPattern(matrix, height, width, startRow, startColumn, pattern) {\n // const result = new ResultPoint[4];\n const result = new Array(4);\n let found = false;\n const counters = new Int32Array(pattern.length);\n for (; startRow < height; startRow += Detector$3.ROW_STEP) {\n let loc = Detector$3.findGuardPattern(matrix, startColumn, startRow, width, false, pattern, counters);\n if (loc != null) {\n while (startRow > 0) {\n const previousRowLoc = Detector$3.findGuardPattern(matrix, startColumn, --startRow, width, false, pattern, counters);\n if (previousRowLoc != null) {\n loc = previousRowLoc;\n }\n else {\n startRow++;\n break;\n }\n }\n result[0] = new ResultPoint(loc[0], startRow);\n result[1] = new ResultPoint(loc[1], startRow);\n found = true;\n break;\n }\n }\n let stopRow = startRow + 1;\n // Last row of the current symbol that contains pattern\n if (found) {\n let skippedRowCount = 0;\n let previousRowLoc = Int32Array.from([Math.trunc(result[0].getX()), Math.trunc(result[1].getX())]);\n for (; stopRow < height; stopRow++) {\n const loc = Detector$3.findGuardPattern(matrix, previousRowLoc[0], stopRow, width, false, pattern, counters);\n // a found pattern is only considered to belong to the same barcode if the start and end positions\n // don't differ too much. Pattern drift should be not bigger than two for consecutive rows. With\n // a higher number of skipped rows drift could be larger. To keep it simple for now, we allow a slightly\n // larger drift and don't check for skipped rows.\n if (loc != null &&\n Math.abs(previousRowLoc[0] - loc[0]) < Detector$3.MAX_PATTERN_DRIFT &&\n Math.abs(previousRowLoc[1] - loc[1]) < Detector$3.MAX_PATTERN_DRIFT) {\n previousRowLoc = loc;\n skippedRowCount = 0;\n }\n else {\n if (skippedRowCount > Detector$3.SKIPPED_ROW_COUNT_MAX) {\n break;\n }\n else {\n skippedRowCount++;\n }\n }\n }\n stopRow -= skippedRowCount + 1;\n result[2] = new ResultPoint(previousRowLoc[0], stopRow);\n result[3] = new ResultPoint(previousRowLoc[1], stopRow);\n }\n if (stopRow - startRow < Detector$3.BARCODE_MIN_HEIGHT) {\n Arrays.fill(result, null);\n }\n return result;\n }\n /**\n * @param matrix row of black/white values to search\n * @param column x position to start search\n * @param row y position to start search\n * @param width the number of pixels to search on this row\n * @param pattern pattern of counts of number of black and white pixels that are\n * being searched for as a pattern\n * @param counters array of counters, as long as pattern, to re-use\n * @return start/end horizontal offset of guard pattern, as an array of two ints.\n */\n static findGuardPattern(matrix, column, row, width, whiteFirst, pattern, counters) {\n Arrays.fillWithin(counters, 0, counters.length, 0);\n let patternStart = column;\n let pixelDrift = 0;\n // if there are black pixels left of the current pixel shift to the left, but only for MAX_PIXEL_DRIFT pixels\n while (matrix.get(patternStart, row) && patternStart > 0 && pixelDrift++ < Detector$3.MAX_PIXEL_DRIFT) {\n patternStart--;\n }\n let x = patternStart;\n let counterPosition = 0;\n let patternLength = pattern.length;\n for (let isWhite = whiteFirst; x < width; x++) {\n let pixel = matrix.get(x, row);\n if (pixel !== isWhite) {\n counters[counterPosition]++;\n }\n else {\n if (counterPosition === patternLength - 1) {\n if (Detector$3.patternMatchVariance(counters, pattern, Detector$3.MAX_INDIVIDUAL_VARIANCE) < Detector$3.MAX_AVG_VARIANCE) {\n return new Int32Array([patternStart, x]);\n }\n patternStart += counters[0] + counters[1];\n System.arraycopy(counters, 2, counters, 0, counterPosition - 1);\n counters[counterPosition - 1] = 0;\n counters[counterPosition] = 0;\n counterPosition--;\n }\n else {\n counterPosition++;\n }\n counters[counterPosition] = 1;\n isWhite = !isWhite;\n }\n }\n if (counterPosition === patternLength - 1 &&\n Detector$3.patternMatchVariance(counters, pattern, Detector$3.MAX_INDIVIDUAL_VARIANCE) < Detector$3.MAX_AVG_VARIANCE) {\n return new Int32Array([patternStart, x - 1]);\n }\n return null;\n }\n /**\n * Determines how closely a set of observed counts of runs of black/white\n * values matches a given target pattern. This is reported as the ratio of\n * the total variance from the expected pattern proportions across all\n * pattern elements, to the length of the pattern.\n *\n * @param counters observed counters\n * @param pattern expected pattern\n * @param maxIndividualVariance The most any counter can differ before we give up\n * @return ratio of total variance between counters and pattern compared to total pattern size\n */\n static patternMatchVariance(counters, pattern, maxIndividualVariance) {\n let numCounters = counters.length;\n let total = 0;\n let patternLength = 0;\n for (let i = 0; i < numCounters; i++) {\n total += counters[i];\n patternLength += pattern[i];\n }\n if (total < patternLength) {\n // If we don't even have one pixel per unit of bar width, assume this\n // is too small to reliably match, so fail:\n return /*Float.POSITIVE_INFINITY*/ Infinity;\n }\n // We're going to fake floating-point math in integers. We just need to use more bits.\n // Scale up patternLength so that intermediate values below like scaledCounter will have\n // more \"significant digits\".\n let unitBarWidth = total / patternLength;\n maxIndividualVariance *= unitBarWidth;\n let totalVariance = 0.0;\n for (let x = 0; x < numCounters; x++) {\n let counter = counters[x];\n let scaledPattern = pattern[x] * unitBarWidth;\n let variance = counter > scaledPattern ? counter - scaledPattern : scaledPattern - counter;\n if (variance > maxIndividualVariance) {\n return /*Float.POSITIVE_INFINITY*/ Infinity;\n }\n totalVariance += variance;\n }\n return totalVariance / total;\n }\n }\n Detector$3.INDEXES_START_PATTERN = Int32Array.from([0, 4, 1, 5]);\n Detector$3.INDEXES_STOP_PATTERN = Int32Array.from([6, 2, 7, 3]);\n Detector$3.MAX_AVG_VARIANCE = 0.42;\n Detector$3.MAX_INDIVIDUAL_VARIANCE = 0.8;\n // B S B S B S B S Bar/Space pattern\n // 11111111 0 1 0 1 0 1 000\n Detector$3.START_PATTERN = Int32Array.from([8, 1, 1, 1, 1, 1, 1, 3]);\n // 1111111 0 1 000 1 0 1 00 1\n Detector$3.STOP_PATTERN = Int32Array.from([7, 1, 1, 3, 1, 1, 1, 2, 1]);\n Detector$3.MAX_PIXEL_DRIFT = 3;\n Detector$3.MAX_PATTERN_DRIFT = 5;\n // if we set the value too low, then we don't detect the correct height of the bar if the start patterns are damaged.\n // if we set the value too high, then we might detect the start pattern from a neighbor barcode.\n Detector$3.SKIPPED_ROW_COUNT_MAX = 25;\n // A PDF471 barcode should have at least 3 rows, with each row being >= 3 times the module width. Therefore it should be at least\n // 9 pixels tall. To be conservative, we use about half the size to ensure we don't miss it.\n Detector$3.ROW_STEP = 5;\n Detector$3.BARCODE_MIN_HEIGHT = 10;\n\n /*\n * Copyright 2012 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n /**\n * @author Sean Owen\n * @see com.google.zxing.common.reedsolomon.GenericGFPoly\n */\n /*final*/ class ModulusPoly {\n constructor(field, coefficients) {\n if (coefficients.length === 0) {\n throw new IllegalArgumentException();\n }\n this.field = field;\n let coefficientsLength = /*int*/ coefficients.length;\n if (coefficientsLength > 1 && coefficients[0] === 0) {\n // Leading term must be non-zero for anything except the constant polynomial \"0\"\n let firstNonZero = /*int*/ 1;\n while (firstNonZero < coefficientsLength && coefficients[firstNonZero] === 0) {\n firstNonZero++;\n }\n if (firstNonZero === coefficientsLength) {\n this.coefficients = new Int32Array([0]);\n }\n else {\n this.coefficients = new Int32Array(coefficientsLength - firstNonZero);\n System.arraycopy(coefficients, firstNonZero, this.coefficients, 0, this.coefficients.length);\n }\n }\n else {\n this.coefficients = coefficients;\n }\n }\n getCoefficients() {\n return this.coefficients;\n }\n /**\n * @return degree of this polynomial\n */\n getDegree() {\n return this.coefficients.length - 1;\n }\n /**\n * @return true iff this polynomial is the monomial \"0\"\n */\n isZero() {\n return this.coefficients[0] === 0;\n }\n /**\n * @return coefficient of x^degree term in this polynomial\n */\n getCoefficient(degree) {\n return this.coefficients[this.coefficients.length - 1 - degree];\n }\n /**\n * @return evaluation of this polynomial at a given point\n */\n evaluateAt(a) {\n if (a === 0) {\n // Just return the x^0 coefficient\n return this.getCoefficient(0);\n }\n if (a === 1) {\n // Just the sum of the coefficients\n let sum = /*int*/ 0;\n for (let coefficient /*int*/ of this.coefficients) {\n sum = this.field.add(sum, coefficient);\n }\n return sum;\n }\n let result = /*int*/ this.coefficients[0];\n let size = /*int*/ this.coefficients.length;\n for (let i /*int*/ = 1; i < size; i++) {\n result = this.field.add(this.field.multiply(a, result), this.coefficients[i]);\n }\n return result;\n }\n add(other) {\n if (!this.field.equals(other.field)) {\n throw new IllegalArgumentException('ModulusPolys do not have same ModulusGF field');\n }\n if (this.isZero()) {\n return other;\n }\n if (other.isZero()) {\n return this;\n }\n let smallerCoefficients = this.coefficients;\n let largerCoefficients = other.coefficients;\n if (smallerCoefficients.length > largerCoefficients.length) {\n let temp = smallerCoefficients;\n smallerCoefficients = largerCoefficients;\n largerCoefficients = temp;\n }\n let sumDiff = new Int32Array(largerCoefficients.length);\n let lengthDiff = /*int*/ largerCoefficients.length - smallerCoefficients.length;\n // Copy high-order terms only found in higher-degree polynomial's coefficients\n System.arraycopy(largerCoefficients, 0, sumDiff, 0, lengthDiff);\n for (let i /*int*/ = lengthDiff; i < largerCoefficients.length; i++) {\n sumDiff[i] = this.field.add(smallerCoefficients[i - lengthDiff], largerCoefficients[i]);\n }\n return new ModulusPoly(this.field, sumDiff);\n }\n subtract(other) {\n if (!this.field.equals(other.field)) {\n throw new IllegalArgumentException('ModulusPolys do not have same ModulusGF field');\n }\n if (other.isZero()) {\n return this;\n }\n return this.add(other.negative());\n }\n multiply(other) {\n if (other instanceof ModulusPoly) {\n return this.multiplyOther(other);\n }\n return this.multiplyScalar(other);\n }\n multiplyOther(other) {\n if (!this.field.equals(other.field)) {\n throw new IllegalArgumentException('ModulusPolys do not have same ModulusGF field');\n }\n if (this.isZero() || other.isZero()) {\n // return this.field.getZero();\n return new ModulusPoly(this.field, new Int32Array([0]));\n }\n let aCoefficients = this.coefficients;\n let aLength = /*int*/ aCoefficients.length;\n let bCoefficients = other.coefficients;\n let bLength = /*int*/ bCoefficients.length;\n let product = new Int32Array(aLength + bLength - 1);\n for (let i /*int*/ = 0; i < aLength; i++) {\n let aCoeff = /*int*/ aCoefficients[i];\n for (let j /*int*/ = 0; j < bLength; j++) {\n product[i + j] = this.field.add(product[i + j], this.field.multiply(aCoeff, bCoefficients[j]));\n }\n }\n return new ModulusPoly(this.field, product);\n }\n negative() {\n let size = /*int*/ this.coefficients.length;\n let negativeCoefficients = new Int32Array(size);\n for (let i /*int*/ = 0; i < size; i++) {\n negativeCoefficients[i] = this.field.subtract(0, this.coefficients[i]);\n }\n return new ModulusPoly(this.field, negativeCoefficients);\n }\n multiplyScalar(scalar) {\n if (scalar === 0) {\n return new ModulusPoly(this.field, new Int32Array([0]));\n }\n if (scalar === 1) {\n return this;\n }\n let size = /*int*/ this.coefficients.length;\n let product = new Int32Array(size);\n for (let i /*int*/ = 0; i < size; i++) {\n product[i] = this.field.multiply(this.coefficients[i], scalar);\n }\n return new ModulusPoly(this.field, product);\n }\n multiplyByMonomial(degree, coefficient) {\n if (degree < 0) {\n throw new IllegalArgumentException();\n }\n if (coefficient === 0) {\n return new ModulusPoly(this.field, new Int32Array([0]));\n }\n let size = /*int*/ this.coefficients.length;\n let product = new Int32Array(size + degree);\n for (let i /*int*/ = 0; i < size; i++) {\n product[i] = this.field.multiply(this.coefficients[i], coefficient);\n }\n return new ModulusPoly(this.field, product);\n }\n /*\n ModulusPoly[] divide(other: ModulusPoly) {\n if (!field.equals(other.field)) {\n throw new IllegalArgumentException(\"ModulusPolys do not have same ModulusGF field\");\n }\n if (other.isZero()) {\n throw new IllegalArgumentException(\"Divide by 0\");\n }\n \n let quotient: ModulusPoly = field.getZero();\n let remainder: ModulusPoly = this;\n \n let denominatorLeadingTerm: /*int/ number = other.getCoefficient(other.getDegree());\n let inverseDenominatorLeadingTerm: /*int/ number = field.inverse(denominatorLeadingTerm);\n \n while (remainder.getDegree() >= other.getDegree() && !remainder.isZero()) {\n let degreeDifference: /*int/ number = remainder.getDegree() - other.getDegree();\n let scale: /*int/ number = field.multiply(remainder.getCoefficient(remainder.getDegree()), inverseDenominatorLeadingTerm);\n let term: ModulusPoly = other.multiplyByMonomial(degreeDifference, scale);\n let iterationQuotient: ModulusPoly = field.buildMonomial(degreeDifference, scale);\n quotient = quotient.add(iterationQuotient);\n remainder = remainder.subtract(term);\n }\n \n return new ModulusPoly[] { quotient, remainder };\n }\n */\n // @Override\n toString() {\n let result = new StringBuilder( /*8 * this.getDegree()*/); // dynamic string size in JS\n for (let degree /*int*/ = this.getDegree(); degree >= 0; degree--) {\n let coefficient = /*int*/ this.getCoefficient(degree);\n if (coefficient !== 0) {\n if (coefficient < 0) {\n result.append(' - ');\n coefficient = -coefficient;\n }\n else {\n if (result.length() > 0) {\n result.append(' + ');\n }\n }\n if (degree === 0 || coefficient !== 1) {\n result.append(coefficient);\n }\n if (degree !== 0) {\n if (degree === 1) {\n result.append('x');\n }\n else {\n result.append('x^');\n result.append(degree);\n }\n }\n }\n }\n return result.toString();\n }\n }\n\n class ModulusBase {\n add(a, b) {\n return (a + b) % this.modulus;\n }\n subtract(a, b) {\n return (this.modulus + a - b) % this.modulus;\n }\n exp(a) {\n return this.expTable[a];\n }\n log(a) {\n if (a === 0) {\n throw new IllegalArgumentException();\n }\n return this.logTable[a];\n }\n inverse(a) {\n if (a === 0) {\n throw new ArithmeticException();\n }\n return this.expTable[this.modulus - this.logTable[a] - 1];\n }\n multiply(a, b) {\n if (a === 0 || b === 0) {\n return 0;\n }\n return this.expTable[(this.logTable[a] + this.logTable[b]) % (this.modulus - 1)];\n }\n getSize() {\n return this.modulus;\n }\n equals(o) {\n return o === this;\n }\n }\n\n /*\n * Copyright 2012 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n /**\n *

A field based on powers of a generator integer, modulo some modulus.

\n *\n * @author Sean Owen\n * @see com.google.zxing.common.reedsolomon.GenericGF\n */\n /*public final*/ class ModulusGF extends ModulusBase {\n // private /*final*/ modulus: /*int*/ number;\n constructor(modulus, generator) {\n super();\n this.modulus = modulus;\n this.expTable = new Int32Array(modulus);\n this.logTable = new Int32Array(modulus);\n let x = /*int*/ 1;\n for (let i /*int*/ = 0; i < modulus; i++) {\n this.expTable[i] = x;\n x = (x * generator) % modulus;\n }\n for (let i /*int*/ = 0; i < modulus - 1; i++) {\n this.logTable[this.expTable[i]] = i;\n }\n // logTable[0] == 0 but this should never be used\n this.zero = new ModulusPoly(this, new Int32Array([0]));\n this.one = new ModulusPoly(this, new Int32Array([1]));\n }\n getZero() {\n return this.zero;\n }\n getOne() {\n return this.one;\n }\n buildMonomial(degree, coefficient) {\n if (degree < 0) {\n throw new IllegalArgumentException();\n }\n if (coefficient === 0) {\n return this.zero;\n }\n let coefficients = new Int32Array(degree + 1);\n coefficients[0] = coefficient;\n return new ModulusPoly(this, coefficients);\n }\n }\n ModulusGF.PDF417_GF = new ModulusGF(PDF417Common.NUMBER_OF_CODEWORDS, 3);\n\n /*\n * Copyright 2012 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n /**\n *

PDF417 error correction implementation.

\n *\n *

This example\n * is quite useful in understanding the algorithm.

\n *\n * @author Sean Owen\n * @see com.google.zxing.common.reedsolomon.ReedSolomonDecoder\n */\n /*public final*/ class ErrorCorrection {\n constructor() {\n this.field = ModulusGF.PDF417_GF;\n }\n /**\n * @param received received codewords\n * @param numECCodewords number of those codewords used for EC\n * @param erasures location of erasures\n * @return number of errors\n * @throws ChecksumException if errors cannot be corrected, maybe because of too many errors\n */\n decode(received, numECCodewords, erasures) {\n let poly = new ModulusPoly(this.field, received);\n let S = new Int32Array(numECCodewords);\n let error = false;\n for (let i /*int*/ = numECCodewords; i > 0; i--) {\n let evaluation = poly.evaluateAt(this.field.exp(i));\n S[numECCodewords - i] = evaluation;\n if (evaluation !== 0) {\n error = true;\n }\n }\n if (!error) {\n return 0;\n }\n let knownErrors = this.field.getOne();\n if (erasures != null) {\n for (const erasure of erasures) {\n let b = this.field.exp(received.length - 1 - erasure);\n // Add (1 - bx) term:\n let term = new ModulusPoly(this.field, new Int32Array([this.field.subtract(0, b), 1]));\n knownErrors = knownErrors.multiply(term);\n }\n }\n let syndrome = new ModulusPoly(this.field, S);\n // syndrome = syndrome.multiply(knownErrors);\n let sigmaOmega = this.runEuclideanAlgorithm(this.field.buildMonomial(numECCodewords, 1), syndrome, numECCodewords);\n let sigma = sigmaOmega[0];\n let omega = sigmaOmega[1];\n // sigma = sigma.multiply(knownErrors);\n let errorLocations = this.findErrorLocations(sigma);\n let errorMagnitudes = this.findErrorMagnitudes(omega, sigma, errorLocations);\n for (let i /*int*/ = 0; i < errorLocations.length; i++) {\n let position = received.length - 1 - this.field.log(errorLocations[i]);\n if (position < 0) {\n throw ChecksumException.getChecksumInstance();\n }\n received[position] = this.field.subtract(received[position], errorMagnitudes[i]);\n }\n return errorLocations.length;\n }\n /**\n *\n * @param ModulusPoly\n * @param a\n * @param ModulusPoly\n * @param b\n * @param int\n * @param R\n * @throws ChecksumException\n */\n runEuclideanAlgorithm(a, b, R) {\n // Assume a's degree is >= b's\n if (a.getDegree() < b.getDegree()) {\n let temp = a;\n a = b;\n b = temp;\n }\n let rLast = a;\n let r = b;\n let tLast = this.field.getZero();\n let t = this.field.getOne();\n // Run Euclidean algorithm until r's degree is less than R/2\n while (r.getDegree() >= Math.round(R / 2)) {\n let rLastLast = rLast;\n let tLastLast = tLast;\n rLast = r;\n tLast = t;\n // Divide rLastLast by rLast, with quotient in q and remainder in r\n if (rLast.isZero()) {\n // Oops, Euclidean algorithm already terminated?\n throw ChecksumException.getChecksumInstance();\n }\n r = rLastLast;\n let q = this.field.getZero();\n let denominatorLeadingTerm = rLast.getCoefficient(rLast.getDegree());\n let dltInverse = this.field.inverse(denominatorLeadingTerm);\n while (r.getDegree() >= rLast.getDegree() && !r.isZero()) {\n let degreeDiff = r.getDegree() - rLast.getDegree();\n let scale = this.field.multiply(r.getCoefficient(r.getDegree()), dltInverse);\n q = q.add(this.field.buildMonomial(degreeDiff, scale));\n r = r.subtract(rLast.multiplyByMonomial(degreeDiff, scale));\n }\n t = q.multiply(tLast).subtract(tLastLast).negative();\n }\n let sigmaTildeAtZero = t.getCoefficient(0);\n if (sigmaTildeAtZero === 0) {\n throw ChecksumException.getChecksumInstance();\n }\n let inverse = this.field.inverse(sigmaTildeAtZero);\n let sigma = t.multiply(inverse);\n let omega = r.multiply(inverse);\n return [sigma, omega];\n }\n /**\n *\n * @param errorLocator\n * @throws ChecksumException\n */\n findErrorLocations(errorLocator) {\n // This is a direct application of Chien's search\n let numErrors = errorLocator.getDegree();\n let result = new Int32Array(numErrors);\n let e = 0;\n for (let i /*int*/ = 1; i < this.field.getSize() && e < numErrors; i++) {\n if (errorLocator.evaluateAt(i) === 0) {\n result[e] = this.field.inverse(i);\n e++;\n }\n }\n if (e !== numErrors) {\n throw ChecksumException.getChecksumInstance();\n }\n return result;\n }\n findErrorMagnitudes(errorEvaluator, errorLocator, errorLocations) {\n let errorLocatorDegree = errorLocator.getDegree();\n let formalDerivativeCoefficients = new Int32Array(errorLocatorDegree);\n for (let i /*int*/ = 1; i <= errorLocatorDegree; i++) {\n formalDerivativeCoefficients[errorLocatorDegree - i] =\n this.field.multiply(i, errorLocator.getCoefficient(i));\n }\n let formalDerivative = new ModulusPoly(this.field, formalDerivativeCoefficients);\n // This is directly applying Forney's Formula\n let s = errorLocations.length;\n let result = new Int32Array(s);\n for (let i /*int*/ = 0; i < s; i++) {\n let xiInverse = this.field.inverse(errorLocations[i]);\n let numerator = this.field.subtract(0, errorEvaluator.evaluateAt(xiInverse));\n let denominator = this.field.inverse(formalDerivative.evaluateAt(xiInverse));\n result[i] = this.field.multiply(numerator, denominator);\n }\n return result;\n }\n }\n\n /*\n * Copyright 2013 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n /**\n * @author Guenther Grau\n */\n /*final*/ class BoundingBox {\n constructor(image, topLeft, bottomLeft, topRight, bottomRight) {\n if (image instanceof BoundingBox) {\n this.constructor_2(image);\n }\n else {\n this.constructor_1(image, topLeft, bottomLeft, topRight, bottomRight);\n }\n }\n /**\n *\n * @param image\n * @param topLeft\n * @param bottomLeft\n * @param topRight\n * @param bottomRight\n *\n * @throws NotFoundException\n */\n constructor_1(image, topLeft, bottomLeft, topRight, bottomRight) {\n const leftUnspecified = topLeft == null || bottomLeft == null;\n const rightUnspecified = topRight == null || bottomRight == null;\n if (leftUnspecified && rightUnspecified) {\n throw new NotFoundException();\n }\n if (leftUnspecified) {\n topLeft = new ResultPoint(0, topRight.getY());\n bottomLeft = new ResultPoint(0, bottomRight.getY());\n }\n else if (rightUnspecified) {\n topRight = new ResultPoint(image.getWidth() - 1, topLeft.getY());\n bottomRight = new ResultPoint(image.getWidth() - 1, bottomLeft.getY());\n }\n this.image = image;\n this.topLeft = topLeft;\n this.bottomLeft = bottomLeft;\n this.topRight = topRight;\n this.bottomRight = bottomRight;\n this.minX = Math.trunc(Math.min(topLeft.getX(), bottomLeft.getX()));\n this.maxX = Math.trunc(Math.max(topRight.getX(), bottomRight.getX()));\n this.minY = Math.trunc(Math.min(topLeft.getY(), topRight.getY()));\n this.maxY = Math.trunc(Math.max(bottomLeft.getY(), bottomRight.getY()));\n }\n constructor_2(boundingBox) {\n this.image = boundingBox.image;\n this.topLeft = boundingBox.getTopLeft();\n this.bottomLeft = boundingBox.getBottomLeft();\n this.topRight = boundingBox.getTopRight();\n this.bottomRight = boundingBox.getBottomRight();\n this.minX = boundingBox.getMinX();\n this.maxX = boundingBox.getMaxX();\n this.minY = boundingBox.getMinY();\n this.maxY = boundingBox.getMaxY();\n }\n /**\n * @throws NotFoundException\n */\n static merge(leftBox, rightBox) {\n if (leftBox == null) {\n return rightBox;\n }\n if (rightBox == null) {\n return leftBox;\n }\n return new BoundingBox(leftBox.image, leftBox.topLeft, leftBox.bottomLeft, rightBox.topRight, rightBox.bottomRight);\n }\n /**\n * @throws NotFoundException\n */\n addMissingRows(missingStartRows, missingEndRows, isLeft) {\n let newTopLeft = this.topLeft;\n let newBottomLeft = this.bottomLeft;\n let newTopRight = this.topRight;\n let newBottomRight = this.bottomRight;\n if (missingStartRows > 0) {\n let top = isLeft ? this.topLeft : this.topRight;\n let newMinY = Math.trunc(top.getY() - missingStartRows);\n if (newMinY < 0) {\n newMinY = 0;\n }\n let newTop = new ResultPoint(top.getX(), newMinY);\n if (isLeft) {\n newTopLeft = newTop;\n }\n else {\n newTopRight = newTop;\n }\n }\n if (missingEndRows > 0) {\n let bottom = isLeft ? this.bottomLeft : this.bottomRight;\n let newMaxY = Math.trunc(bottom.getY() + missingEndRows);\n if (newMaxY >= this.image.getHeight()) {\n newMaxY = this.image.getHeight() - 1;\n }\n let newBottom = new ResultPoint(bottom.getX(), newMaxY);\n if (isLeft) {\n newBottomLeft = newBottom;\n }\n else {\n newBottomRight = newBottom;\n }\n }\n return new BoundingBox(this.image, newTopLeft, newBottomLeft, newTopRight, newBottomRight);\n }\n getMinX() {\n return this.minX;\n }\n getMaxX() {\n return this.maxX;\n }\n getMinY() {\n return this.minY;\n }\n getMaxY() {\n return this.maxY;\n }\n getTopLeft() {\n return this.topLeft;\n }\n getTopRight() {\n return this.topRight;\n }\n getBottomLeft() {\n return this.bottomLeft;\n }\n getBottomRight() {\n return this.bottomRight;\n }\n }\n\n /*\n * Copyright 2013 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n // package com.google.zxing.pdf417.decoder;\n /**\n * @author Guenther Grau\n */\n /*final*/ class BarcodeMetadata {\n constructor(columnCount, rowCountUpperPart, rowCountLowerPart, errorCorrectionLevel) {\n this.columnCount = columnCount;\n this.errorCorrectionLevel = errorCorrectionLevel;\n this.rowCountUpperPart = rowCountUpperPart;\n this.rowCountLowerPart = rowCountLowerPart;\n this.rowCount = rowCountUpperPart + rowCountLowerPart;\n }\n getColumnCount() {\n return this.columnCount;\n }\n getErrorCorrectionLevel() {\n return this.errorCorrectionLevel;\n }\n getRowCount() {\n return this.rowCount;\n }\n getRowCountUpperPart() {\n return this.rowCountUpperPart;\n }\n getRowCountLowerPart() {\n return this.rowCountLowerPart;\n }\n }\n\n /**\n * Java Formatter class polyfill that works in the JS way.\n */\n class Formatter {\n constructor() {\n this.buffer = '';\n }\n /**\n *\n * @see https://stackoverflow.com/a/13439711/4367683\n *\n * @param str\n * @param arr\n */\n static form(str, arr) {\n let i = -1;\n function callback(exp, p0, p1, p2, p3, p4) {\n if (exp === '%%')\n return '%';\n if (arr[++i] === undefined)\n return undefined;\n exp = p2 ? parseInt(p2.substr(1)) : undefined;\n let base = p3 ? parseInt(p3.substr(1)) : undefined;\n let val;\n switch (p4) {\n case 's':\n val = arr[i];\n break;\n case 'c':\n val = arr[i][0];\n break;\n case 'f':\n val = parseFloat(arr[i]).toFixed(exp);\n break;\n case 'p':\n val = parseFloat(arr[i]).toPrecision(exp);\n break;\n case 'e':\n val = parseFloat(arr[i]).toExponential(exp);\n break;\n case 'x':\n val = parseInt(arr[i]).toString(base ? base : 16);\n break;\n case 'd':\n val = parseFloat(parseInt(arr[i], base ? base : 10).toPrecision(exp)).toFixed(0);\n break;\n }\n val = typeof val === 'object' ? JSON.stringify(val) : (+val).toString(base);\n let size = parseInt(p1); /* padding size */\n let ch = p1 && (p1[0] + '') === '0' ? '0' : ' '; /* isnull? */\n while (val.length < size)\n val = p0 !== undefined ? val + ch : ch + val; /* isminus? */\n return val;\n }\n let regex = /%(-)?(0?[0-9]+)?([.][0-9]+)?([#][0-9]+)?([scfpexd%])/g;\n return str.replace(regex, callback);\n }\n /**\n *\n * @param append The new string to append.\n * @param args Argumets values to be formated.\n */\n format(append, ...args) {\n this.buffer += Formatter.form(append, args);\n }\n /**\n * Returns the Formatter string value.\n */\n toString() {\n return this.buffer;\n }\n }\n\n /*\n * Copyright 2013 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n /**\n * @author Guenther Grau\n */\n class DetectionResultColumn {\n constructor(boundingBox) {\n this.boundingBox = new BoundingBox(boundingBox);\n // this.codewords = new Codeword[boundingBox.getMaxY() - boundingBox.getMinY() + 1];\n this.codewords = new Array(boundingBox.getMaxY() - boundingBox.getMinY() + 1);\n }\n /*final*/ getCodewordNearby(imageRow) {\n let codeword = this.getCodeword(imageRow);\n if (codeword != null) {\n return codeword;\n }\n for (let i = 1; i < DetectionResultColumn.MAX_NEARBY_DISTANCE; i++) {\n let nearImageRow = this.imageRowToCodewordIndex(imageRow) - i;\n if (nearImageRow >= 0) {\n codeword = this.codewords[nearImageRow];\n if (codeword != null) {\n return codeword;\n }\n }\n nearImageRow = this.imageRowToCodewordIndex(imageRow) + i;\n if (nearImageRow < this.codewords.length) {\n codeword = this.codewords[nearImageRow];\n if (codeword != null) {\n return codeword;\n }\n }\n }\n return null;\n }\n /*final int*/ imageRowToCodewordIndex(imageRow) {\n return imageRow - this.boundingBox.getMinY();\n }\n /*final void*/ setCodeword(imageRow, codeword) {\n this.codewords[this.imageRowToCodewordIndex(imageRow)] = codeword;\n }\n /*final*/ getCodeword(imageRow) {\n return this.codewords[this.imageRowToCodewordIndex(imageRow)];\n }\n /*final*/ getBoundingBox() {\n return this.boundingBox;\n }\n /*final*/ getCodewords() {\n return this.codewords;\n }\n // @Override\n toString() {\n const formatter = new Formatter();\n let row = 0;\n for (const codeword of this.codewords) {\n if (codeword == null) {\n formatter.format('%3d: | %n', row++);\n continue;\n }\n formatter.format('%3d: %3d|%3d%n', row++, codeword.getRowNumber(), codeword.getValue());\n }\n return formatter.toString();\n }\n }\n DetectionResultColumn.MAX_NEARBY_DISTANCE = 5;\n\n /*\n * Copyright 2013 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n // import java.util.ArrayList;\n // import java.util.Collection;\n // import java.util.HashMap;\n // import java.util.Map;\n // import java.util.Map.Entry;\n /**\n * @author Guenther Grau\n */\n /*final*/ class BarcodeValue {\n constructor() {\n this.values = new Map();\n }\n /**\n * Add an occurrence of a value\n */\n setValue(value) {\n value = Math.trunc(value);\n let confidence = this.values.get(value);\n if (confidence == null) {\n confidence = 0;\n }\n confidence++;\n this.values.set(value, confidence);\n }\n /**\n * Determines the maximum occurrence of a set value and returns all values which were set with this occurrence.\n * @return an array of int, containing the values with the highest occurrence, or null, if no value was set\n */\n getValue() {\n let maxConfidence = -1;\n let result = new Array();\n for (const [key, value] of this.values.entries()) {\n const entry = {\n getKey: () => key,\n getValue: () => value,\n };\n if (entry.getValue() > maxConfidence) {\n maxConfidence = entry.getValue();\n result = [];\n result.push(entry.getKey());\n }\n else if (entry.getValue() === maxConfidence) {\n result.push(entry.getKey());\n }\n }\n return PDF417Common.toIntArray(result);\n }\n getConfidence(value) {\n return this.values.get(value);\n }\n }\n\n /*\n * Copyright 2013 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n /**\n * @author Guenther Grau\n */\n /*final*/ class DetectionResultRowIndicatorColumn extends DetectionResultColumn {\n constructor(boundingBox, isLeft) {\n super(boundingBox);\n this._isLeft = isLeft;\n }\n setRowNumbers() {\n for (let codeword /*Codeword*/ of this.getCodewords()) {\n if (codeword != null) {\n codeword.setRowNumberAsRowIndicatorColumn();\n }\n }\n }\n // TODO implement properly\n // TODO maybe we should add missing codewords to store the correct row number to make\n // finding row numbers for other columns easier\n // use row height count to make detection of invalid row numbers more reliable\n adjustCompleteIndicatorColumnRowNumbers(barcodeMetadata) {\n let codewords = this.getCodewords();\n this.setRowNumbers();\n this.removeIncorrectCodewords(codewords, barcodeMetadata);\n let boundingBox = this.getBoundingBox();\n let top = this._isLeft ? boundingBox.getTopLeft() : boundingBox.getTopRight();\n let bottom = this._isLeft ? boundingBox.getBottomLeft() : boundingBox.getBottomRight();\n let firstRow = this.imageRowToCodewordIndex(Math.trunc(top.getY()));\n let lastRow = this.imageRowToCodewordIndex(Math.trunc(bottom.getY()));\n // We need to be careful using the average row height. Barcode could be skewed so that we have smaller and\n // taller rows\n // float averageRowHeight = (lastRow - firstRow) / /*(float)*/ barcodeMetadata.getRowCount();\n let barcodeRow = -1;\n let maxRowHeight = 1;\n let currentRowHeight = 0;\n for (let codewordsRow /*int*/ = firstRow; codewordsRow < lastRow; codewordsRow++) {\n if (codewords[codewordsRow] == null) {\n continue;\n }\n let codeword = codewords[codewordsRow];\n // float expectedRowNumber = (codewordsRow - firstRow) / averageRowHeight;\n // if (Math.abs(codeword.getRowNumber() - expectedRowNumber) > 2) {\n // SimpleLog.log(LEVEL.WARNING,\n // \"Removing codeword, rowNumberSkew too high, codeword[\" + codewordsRow + \"]: Expected Row: \" +\n // expectedRowNumber + \", RealRow: \" + codeword.getRowNumber() + \", value: \" + codeword.getValue());\n // codewords[codewordsRow] = null;\n // }\n let rowDifference = codeword.getRowNumber() - barcodeRow;\n // TODO improve handling with case where first row indicator doesn't start with 0\n if (rowDifference === 0) {\n currentRowHeight++;\n }\n else if (rowDifference === 1) {\n maxRowHeight = Math.max(maxRowHeight, currentRowHeight);\n currentRowHeight = 1;\n barcodeRow = codeword.getRowNumber();\n }\n else if (rowDifference < 0 ||\n codeword.getRowNumber() >= barcodeMetadata.getRowCount() ||\n rowDifference > codewordsRow) {\n codewords[codewordsRow] = null;\n }\n else {\n let checkedRows;\n if (maxRowHeight > 2) {\n checkedRows = (maxRowHeight - 2) * rowDifference;\n }\n else {\n checkedRows = rowDifference;\n }\n let closePreviousCodewordFound = checkedRows >= codewordsRow;\n for (let i /*int*/ = 1; i <= checkedRows && !closePreviousCodewordFound; i++) {\n // there must be (height * rowDifference) number of codewords missing. For now we assume height = 1.\n // This should hopefully get rid of most problems already.\n closePreviousCodewordFound = codewords[codewordsRow - i] != null;\n }\n if (closePreviousCodewordFound) {\n codewords[codewordsRow] = null;\n }\n else {\n barcodeRow = codeword.getRowNumber();\n currentRowHeight = 1;\n }\n }\n }\n // return (int) (averageRowHeight + 0.5);\n }\n getRowHeights() {\n let barcodeMetadata = this.getBarcodeMetadata();\n if (barcodeMetadata == null) {\n return null;\n }\n this.adjustIncompleteIndicatorColumnRowNumbers(barcodeMetadata);\n let result = new Int32Array(barcodeMetadata.getRowCount());\n for (let codeword /*Codeword*/ of this.getCodewords()) {\n if (codeword != null) {\n let rowNumber = codeword.getRowNumber();\n if (rowNumber >= result.length) {\n // We have more rows than the barcode metadata allows for, ignore them.\n continue;\n }\n result[rowNumber]++;\n } // else throw exception?\n }\n return result;\n }\n // TODO maybe we should add missing codewords to store the correct row number to make\n // finding row numbers for other columns easier\n // use row height count to make detection of invalid row numbers more reliable\n adjustIncompleteIndicatorColumnRowNumbers(barcodeMetadata) {\n let boundingBox = this.getBoundingBox();\n let top = this._isLeft ? boundingBox.getTopLeft() : boundingBox.getTopRight();\n let bottom = this._isLeft ? boundingBox.getBottomLeft() : boundingBox.getBottomRight();\n let firstRow = this.imageRowToCodewordIndex(Math.trunc(top.getY()));\n let lastRow = this.imageRowToCodewordIndex(Math.trunc(bottom.getY()));\n // float averageRowHeight = (lastRow - firstRow) / /*(float)*/ barcodeMetadata.getRowCount();\n let codewords = this.getCodewords();\n let barcodeRow = -1;\n for (let codewordsRow /*int*/ = firstRow; codewordsRow < lastRow; codewordsRow++) {\n if (codewords[codewordsRow] == null) {\n continue;\n }\n let codeword = codewords[codewordsRow];\n codeword.setRowNumberAsRowIndicatorColumn();\n let rowDifference = codeword.getRowNumber() - barcodeRow;\n // TODO improve handling with case where first row indicator doesn't start with 0\n if (rowDifference === 0) ;\n else if (rowDifference === 1) {\n barcodeRow = codeword.getRowNumber();\n }\n else if (codeword.getRowNumber() >= barcodeMetadata.getRowCount()) {\n codewords[codewordsRow] = null;\n }\n else {\n barcodeRow = codeword.getRowNumber();\n }\n }\n // return (int) (averageRowHeight + 0.5);\n }\n getBarcodeMetadata() {\n let codewords = this.getCodewords();\n let barcodeColumnCount = new BarcodeValue();\n let barcodeRowCountUpperPart = new BarcodeValue();\n let barcodeRowCountLowerPart = new BarcodeValue();\n let barcodeECLevel = new BarcodeValue();\n for (let codeword /*Codeword*/ of codewords) {\n if (codeword == null) {\n continue;\n }\n codeword.setRowNumberAsRowIndicatorColumn();\n let rowIndicatorValue = codeword.getValue() % 30;\n let codewordRowNumber = codeword.getRowNumber();\n if (!this._isLeft) {\n codewordRowNumber += 2;\n }\n switch (codewordRowNumber % 3) {\n case 0:\n barcodeRowCountUpperPart.setValue(rowIndicatorValue * 3 + 1);\n break;\n case 1:\n barcodeECLevel.setValue(rowIndicatorValue / 3);\n barcodeRowCountLowerPart.setValue(rowIndicatorValue % 3);\n break;\n case 2:\n barcodeColumnCount.setValue(rowIndicatorValue + 1);\n break;\n }\n }\n // Maybe we should check if we have ambiguous values?\n if ((barcodeColumnCount.getValue().length === 0) ||\n (barcodeRowCountUpperPart.getValue().length === 0) ||\n (barcodeRowCountLowerPart.getValue().length === 0) ||\n (barcodeECLevel.getValue().length === 0) ||\n barcodeColumnCount.getValue()[0] < 1 ||\n barcodeRowCountUpperPart.getValue()[0] + barcodeRowCountLowerPart.getValue()[0] < PDF417Common.MIN_ROWS_IN_BARCODE ||\n barcodeRowCountUpperPart.getValue()[0] + barcodeRowCountLowerPart.getValue()[0] > PDF417Common.MAX_ROWS_IN_BARCODE) {\n return null;\n }\n let barcodeMetadata = new BarcodeMetadata(barcodeColumnCount.getValue()[0], barcodeRowCountUpperPart.getValue()[0], barcodeRowCountLowerPart.getValue()[0], barcodeECLevel.getValue()[0]);\n this.removeIncorrectCodewords(codewords, barcodeMetadata);\n return barcodeMetadata;\n }\n removeIncorrectCodewords(codewords, barcodeMetadata) {\n // Remove codewords which do not match the metadata\n // TODO Maybe we should keep the incorrect codewords for the start and end positions?\n for (let codewordRow /*int*/ = 0; codewordRow < codewords.length; codewordRow++) {\n let codeword = codewords[codewordRow];\n if (codewords[codewordRow] == null) {\n continue;\n }\n let rowIndicatorValue = codeword.getValue() % 30;\n let codewordRowNumber = codeword.getRowNumber();\n if (codewordRowNumber > barcodeMetadata.getRowCount()) {\n codewords[codewordRow] = null;\n continue;\n }\n if (!this._isLeft) {\n codewordRowNumber += 2;\n }\n switch (codewordRowNumber % 3) {\n case 0:\n if (rowIndicatorValue * 3 + 1 !== barcodeMetadata.getRowCountUpperPart()) {\n codewords[codewordRow] = null;\n }\n break;\n case 1:\n if (Math.trunc(rowIndicatorValue / 3) !== barcodeMetadata.getErrorCorrectionLevel() ||\n rowIndicatorValue % 3 !== barcodeMetadata.getRowCountLowerPart()) {\n codewords[codewordRow] = null;\n }\n break;\n case 2:\n if (rowIndicatorValue + 1 !== barcodeMetadata.getColumnCount()) {\n codewords[codewordRow] = null;\n }\n break;\n }\n }\n }\n isLeft() {\n return this._isLeft;\n }\n // @Override\n toString() {\n return 'IsLeft: ' + this._isLeft + '\\n' + super.toString();\n }\n }\n\n /*\n * Copyright 2013 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n /**\n * @author Guenther Grau\n */\n /*final*/ class DetectionResult {\n constructor(barcodeMetadata, boundingBox) {\n /*final*/ this.ADJUST_ROW_NUMBER_SKIP = 2;\n this.barcodeMetadata = barcodeMetadata;\n this.barcodeColumnCount = barcodeMetadata.getColumnCount();\n this.boundingBox = boundingBox;\n // this.detectionResultColumns = new DetectionResultColumn[this.barcodeColumnCount + 2];\n this.detectionResultColumns = new Array(this.barcodeColumnCount + 2);\n }\n getDetectionResultColumns() {\n this.adjustIndicatorColumnRowNumbers(this.detectionResultColumns[0]);\n this.adjustIndicatorColumnRowNumbers(this.detectionResultColumns[this.barcodeColumnCount + 1]);\n let unadjustedCodewordCount = PDF417Common.MAX_CODEWORDS_IN_BARCODE;\n let previousUnadjustedCount;\n do {\n previousUnadjustedCount = unadjustedCodewordCount;\n unadjustedCodewordCount = this.adjustRowNumbersAndGetCount();\n } while (unadjustedCodewordCount > 0 && unadjustedCodewordCount < previousUnadjustedCount);\n return this.detectionResultColumns;\n }\n adjustIndicatorColumnRowNumbers(detectionResultColumn) {\n if (detectionResultColumn != null) {\n detectionResultColumn\n .adjustCompleteIndicatorColumnRowNumbers(this.barcodeMetadata);\n }\n }\n // TODO ensure that no detected codewords with unknown row number are left\n // we should be able to estimate the row height and use it as a hint for the row number\n // we should also fill the rows top to bottom and bottom to top\n /**\n * @return number of codewords which don't have a valid row number. Note that the count is not accurate as codewords\n * will be counted several times. It just serves as an indicator to see when we can stop adjusting row numbers\n */\n adjustRowNumbersAndGetCount() {\n let unadjustedCount = this.adjustRowNumbersByRow();\n if (unadjustedCount === 0) {\n return 0;\n }\n for (let barcodeColumn /*int*/ = 1; barcodeColumn < this.barcodeColumnCount + 1; barcodeColumn++) {\n let codewords = this.detectionResultColumns[barcodeColumn].getCodewords();\n for (let codewordsRow /*int*/ = 0; codewordsRow < codewords.length; codewordsRow++) {\n if (codewords[codewordsRow] == null) {\n continue;\n }\n if (!codewords[codewordsRow].hasValidRowNumber()) {\n this.adjustRowNumbers(barcodeColumn, codewordsRow, codewords);\n }\n }\n }\n return unadjustedCount;\n }\n adjustRowNumbersByRow() {\n this.adjustRowNumbersFromBothRI();\n // TODO we should only do full row adjustments if row numbers of left and right row indicator column match.\n // Maybe it's even better to calculated the height (rows: d) and divide it by the number of barcode\n // rows. This, together with the LRI and RRI row numbers should allow us to get a good estimate where a row\n // number starts and ends.\n let unadjustedCount = this.adjustRowNumbersFromLRI();\n return unadjustedCount + this.adjustRowNumbersFromRRI();\n }\n adjustRowNumbersFromBothRI() {\n if (this.detectionResultColumns[0] == null || this.detectionResultColumns[this.barcodeColumnCount + 1] == null) {\n return;\n }\n let LRIcodewords = this.detectionResultColumns[0].getCodewords();\n let RRIcodewords = this.detectionResultColumns[this.barcodeColumnCount + 1].getCodewords();\n for (let codewordsRow /*int*/ = 0; codewordsRow < LRIcodewords.length; codewordsRow++) {\n if (LRIcodewords[codewordsRow] != null &&\n RRIcodewords[codewordsRow] != null &&\n LRIcodewords[codewordsRow].getRowNumber() === RRIcodewords[codewordsRow].getRowNumber()) {\n for (let barcodeColumn /*int*/ = 1; barcodeColumn <= this.barcodeColumnCount; barcodeColumn++) {\n let codeword = this.detectionResultColumns[barcodeColumn].getCodewords()[codewordsRow];\n if (codeword == null) {\n continue;\n }\n codeword.setRowNumber(LRIcodewords[codewordsRow].getRowNumber());\n if (!codeword.hasValidRowNumber()) {\n this.detectionResultColumns[barcodeColumn].getCodewords()[codewordsRow] = null;\n }\n }\n }\n }\n }\n adjustRowNumbersFromRRI() {\n if (this.detectionResultColumns[this.barcodeColumnCount + 1] == null) {\n return 0;\n }\n let unadjustedCount = 0;\n let codewords = this.detectionResultColumns[this.barcodeColumnCount + 1].getCodewords();\n for (let codewordsRow /*int*/ = 0; codewordsRow < codewords.length; codewordsRow++) {\n if (codewords[codewordsRow] == null) {\n continue;\n }\n let rowIndicatorRowNumber = codewords[codewordsRow].getRowNumber();\n let invalidRowCounts = 0;\n for (let barcodeColumn /*int*/ = this.barcodeColumnCount + 1; barcodeColumn > 0 && invalidRowCounts < this.ADJUST_ROW_NUMBER_SKIP; barcodeColumn--) {\n let codeword = this.detectionResultColumns[barcodeColumn].getCodewords()[codewordsRow];\n if (codeword != null) {\n invalidRowCounts = DetectionResult.adjustRowNumberIfValid(rowIndicatorRowNumber, invalidRowCounts, codeword);\n if (!codeword.hasValidRowNumber()) {\n unadjustedCount++;\n }\n }\n }\n }\n return unadjustedCount;\n }\n adjustRowNumbersFromLRI() {\n if (this.detectionResultColumns[0] == null) {\n return 0;\n }\n let unadjustedCount = 0;\n let codewords = this.detectionResultColumns[0].getCodewords();\n for (let codewordsRow /*int*/ = 0; codewordsRow < codewords.length; codewordsRow++) {\n if (codewords[codewordsRow] == null) {\n continue;\n }\n let rowIndicatorRowNumber = codewords[codewordsRow].getRowNumber();\n let invalidRowCounts = 0;\n for (let barcodeColumn /*int*/ = 1; barcodeColumn < this.barcodeColumnCount + 1 && invalidRowCounts < this.ADJUST_ROW_NUMBER_SKIP; barcodeColumn++) {\n let codeword = this.detectionResultColumns[barcodeColumn].getCodewords()[codewordsRow];\n if (codeword != null) {\n invalidRowCounts = DetectionResult.adjustRowNumberIfValid(rowIndicatorRowNumber, invalidRowCounts, codeword);\n if (!codeword.hasValidRowNumber()) {\n unadjustedCount++;\n }\n }\n }\n }\n return unadjustedCount;\n }\n static adjustRowNumberIfValid(rowIndicatorRowNumber, invalidRowCounts, codeword) {\n if (codeword == null) {\n return invalidRowCounts;\n }\n if (!codeword.hasValidRowNumber()) {\n if (codeword.isValidRowNumber(rowIndicatorRowNumber)) {\n codeword.setRowNumber(rowIndicatorRowNumber);\n invalidRowCounts = 0;\n }\n else {\n ++invalidRowCounts;\n }\n }\n return invalidRowCounts;\n }\n adjustRowNumbers(barcodeColumn, codewordsRow, codewords) {\n if (!this.detectionResultColumns[barcodeColumn - 1]) {\n return;\n }\n let codeword = codewords[codewordsRow];\n let previousColumnCodewords = this.detectionResultColumns[barcodeColumn - 1].getCodewords();\n let nextColumnCodewords = previousColumnCodewords;\n if (this.detectionResultColumns[barcodeColumn + 1] != null) {\n nextColumnCodewords = this.detectionResultColumns[barcodeColumn + 1].getCodewords();\n }\n // let otherCodewords: Codeword[] = new Codeword[14];\n let otherCodewords = new Array(14);\n otherCodewords[2] = previousColumnCodewords[codewordsRow];\n otherCodewords[3] = nextColumnCodewords[codewordsRow];\n if (codewordsRow > 0) {\n otherCodewords[0] = codewords[codewordsRow - 1];\n otherCodewords[4] = previousColumnCodewords[codewordsRow - 1];\n otherCodewords[5] = nextColumnCodewords[codewordsRow - 1];\n }\n if (codewordsRow > 1) {\n otherCodewords[8] = codewords[codewordsRow - 2];\n otherCodewords[10] = previousColumnCodewords[codewordsRow - 2];\n otherCodewords[11] = nextColumnCodewords[codewordsRow - 2];\n }\n if (codewordsRow < codewords.length - 1) {\n otherCodewords[1] = codewords[codewordsRow + 1];\n otherCodewords[6] = previousColumnCodewords[codewordsRow + 1];\n otherCodewords[7] = nextColumnCodewords[codewordsRow + 1];\n }\n if (codewordsRow < codewords.length - 2) {\n otherCodewords[9] = codewords[codewordsRow + 2];\n otherCodewords[12] = previousColumnCodewords[codewordsRow + 2];\n otherCodewords[13] = nextColumnCodewords[codewordsRow + 2];\n }\n for (let otherCodeword of otherCodewords) {\n if (DetectionResult.adjustRowNumber(codeword, otherCodeword)) {\n return;\n }\n }\n }\n /**\n * @return true, if row number was adjusted, false otherwise\n */\n static adjustRowNumber(codeword, otherCodeword) {\n if (otherCodeword == null) {\n return false;\n }\n if (otherCodeword.hasValidRowNumber() && otherCodeword.getBucket() === codeword.getBucket()) {\n codeword.setRowNumber(otherCodeword.getRowNumber());\n return true;\n }\n return false;\n }\n getBarcodeColumnCount() {\n return this.barcodeColumnCount;\n }\n getBarcodeRowCount() {\n return this.barcodeMetadata.getRowCount();\n }\n getBarcodeECLevel() {\n return this.barcodeMetadata.getErrorCorrectionLevel();\n }\n setBoundingBox(boundingBox) {\n this.boundingBox = boundingBox;\n }\n getBoundingBox() {\n return this.boundingBox;\n }\n setDetectionResultColumn(barcodeColumn, detectionResultColumn) {\n this.detectionResultColumns[barcodeColumn] = detectionResultColumn;\n }\n getDetectionResultColumn(barcodeColumn) {\n return this.detectionResultColumns[barcodeColumn];\n }\n // @Override\n toString() {\n let rowIndicatorColumn = this.detectionResultColumns[0];\n if (rowIndicatorColumn == null) {\n rowIndicatorColumn = this.detectionResultColumns[this.barcodeColumnCount + 1];\n }\n // try (\n let formatter = new Formatter();\n // ) {\n for (let codewordsRow /*int*/ = 0; codewordsRow < rowIndicatorColumn.getCodewords().length; codewordsRow++) {\n formatter.format('CW %3d:', codewordsRow);\n for (let barcodeColumn /*int*/ = 0; barcodeColumn < this.barcodeColumnCount + 2; barcodeColumn++) {\n if (this.detectionResultColumns[barcodeColumn] == null) {\n formatter.format(' | ');\n continue;\n }\n let codeword = this.detectionResultColumns[barcodeColumn].getCodewords()[codewordsRow];\n if (codeword == null) {\n formatter.format(' | ');\n continue;\n }\n formatter.format(' %3d|%3d', codeword.getRowNumber(), codeword.getValue());\n }\n formatter.format('%n');\n }\n return formatter.toString();\n // }\n }\n }\n\n /*\n * Copyright 2013 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n // package com.google.zxing.pdf417.decoder;\n /**\n * @author Guenther Grau\n */\n /*final*/ class Codeword {\n constructor(startX, endX, bucket, value) {\n this.rowNumber = Codeword.BARCODE_ROW_UNKNOWN;\n this.startX = Math.trunc(startX);\n this.endX = Math.trunc(endX);\n this.bucket = Math.trunc(bucket);\n this.value = Math.trunc(value);\n }\n hasValidRowNumber() {\n return this.isValidRowNumber(this.rowNumber);\n }\n isValidRowNumber(rowNumber) {\n return rowNumber !== Codeword.BARCODE_ROW_UNKNOWN && this.bucket === (rowNumber % 3) * 3;\n }\n setRowNumberAsRowIndicatorColumn() {\n this.rowNumber = Math.trunc((Math.trunc(this.value / 30)) * 3 + Math.trunc(this.bucket / 3));\n }\n getWidth() {\n return this.endX - this.startX;\n }\n getStartX() {\n return this.startX;\n }\n getEndX() {\n return this.endX;\n }\n getBucket() {\n return this.bucket;\n }\n getValue() {\n return this.value;\n }\n getRowNumber() {\n return this.rowNumber;\n }\n setRowNumber(rowNumber) {\n this.rowNumber = rowNumber;\n }\n // @Override\n toString() {\n return this.rowNumber + '|' + this.value;\n }\n }\n Codeword.BARCODE_ROW_UNKNOWN = -1;\n\n /*\n * Copyright 2013 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n /**\n * @author Guenther Grau\n * @author creatale GmbH (christoph.schulz@creatale.de)\n */\n /*final*/ class PDF417CodewordDecoder {\n /* @note\n * this action have to be performed before first use of class\n * - static constructor\n * working with 32bit float (based from Java logic)\n */\n static initialize() {\n // Pre-computes the symbol ratio table.\n for ( /*int*/let i = 0; i < PDF417Common.SYMBOL_TABLE.length; i++) {\n let currentSymbol = PDF417Common.SYMBOL_TABLE[i];\n let currentBit = currentSymbol & 0x1;\n for ( /*int*/let j = 0; j < PDF417Common.BARS_IN_MODULE; j++) {\n let size = 0.0;\n while ((currentSymbol & 0x1) === currentBit) {\n size += 1.0;\n currentSymbol >>= 1;\n }\n currentBit = currentSymbol & 0x1;\n if (!PDF417CodewordDecoder.RATIOS_TABLE[i]) {\n PDF417CodewordDecoder.RATIOS_TABLE[i] = new Array(PDF417Common.BARS_IN_MODULE);\n }\n PDF417CodewordDecoder.RATIOS_TABLE[i][PDF417Common.BARS_IN_MODULE - j - 1] = Math.fround(size / PDF417Common.MODULES_IN_CODEWORD);\n }\n }\n this.bSymbolTableReady = true;\n }\n static getDecodedValue(moduleBitCount) {\n let decodedValue = PDF417CodewordDecoder.getDecodedCodewordValue(PDF417CodewordDecoder.sampleBitCounts(moduleBitCount));\n if (decodedValue !== -1) {\n return decodedValue;\n }\n return PDF417CodewordDecoder.getClosestDecodedValue(moduleBitCount);\n }\n static sampleBitCounts(moduleBitCount) {\n let bitCountSum = MathUtils.sum(moduleBitCount);\n let result = new Int32Array(PDF417Common.BARS_IN_MODULE);\n let bitCountIndex = 0;\n let sumPreviousBits = 0;\n for ( /*int*/let i = 0; i < PDF417Common.MODULES_IN_CODEWORD; i++) {\n let sampleIndex = bitCountSum / (2 * PDF417Common.MODULES_IN_CODEWORD) +\n (i * bitCountSum) / PDF417Common.MODULES_IN_CODEWORD;\n if (sumPreviousBits + moduleBitCount[bitCountIndex] <= sampleIndex) {\n sumPreviousBits += moduleBitCount[bitCountIndex];\n bitCountIndex++;\n }\n result[bitCountIndex]++;\n }\n return result;\n }\n static getDecodedCodewordValue(moduleBitCount) {\n let decodedValue = PDF417CodewordDecoder.getBitValue(moduleBitCount);\n return PDF417Common.getCodeword(decodedValue) === -1 ? -1 : decodedValue;\n }\n static getBitValue(moduleBitCount) {\n let result = /*long*/ 0;\n for (let /*int*/ i = 0; i < moduleBitCount.length; i++) {\n for ( /*int*/let bit = 0; bit < moduleBitCount[i]; bit++) {\n result = (result << 1) | (i % 2 === 0 ? 1 : 0);\n }\n }\n return Math.trunc(result);\n }\n // working with 32bit float (as in Java)\n static getClosestDecodedValue(moduleBitCount) {\n let bitCountSum = MathUtils.sum(moduleBitCount);\n let bitCountRatios = new Array(PDF417Common.BARS_IN_MODULE);\n if (bitCountSum > 1) {\n for (let /*int*/ i = 0; i < bitCountRatios.length; i++) {\n bitCountRatios[i] = Math.fround(moduleBitCount[i] / bitCountSum);\n }\n }\n let bestMatchError = Float.MAX_VALUE;\n let bestMatch = -1;\n if (!this.bSymbolTableReady) {\n PDF417CodewordDecoder.initialize();\n }\n for ( /*int*/let j = 0; j < PDF417CodewordDecoder.RATIOS_TABLE.length; j++) {\n let error = 0.0;\n let ratioTableRow = PDF417CodewordDecoder.RATIOS_TABLE[j];\n for ( /*int*/let k = 0; k < PDF417Common.BARS_IN_MODULE; k++) {\n let diff = Math.fround(ratioTableRow[k] - bitCountRatios[k]);\n error += Math.fround(diff * diff);\n if (error >= bestMatchError) {\n break;\n }\n }\n if (error < bestMatchError) {\n bestMatchError = error;\n bestMatch = PDF417Common.SYMBOL_TABLE[j];\n }\n }\n return bestMatch;\n }\n }\n // flag that the table is ready for use\n PDF417CodewordDecoder.bSymbolTableReady = false;\n PDF417CodewordDecoder.RATIOS_TABLE = new Array(PDF417Common.SYMBOL_TABLE.length).map(x => x = new Array(PDF417Common.BARS_IN_MODULE));\n\n /*\n * Copyright 2013 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n // package com.google.zxing.pdf417;\n /**\n * @author Guenther Grau\n */\n /*public final*/ class PDF417ResultMetadata {\n constructor() {\n this.segmentCount = -1;\n this.fileSize = -1;\n this.timestamp = -1;\n this.checksum = -1;\n }\n /**\n * The Segment ID represents the segment of the whole file distributed over different symbols.\n *\n * @return File segment index\n */\n getSegmentIndex() {\n return this.segmentIndex;\n }\n setSegmentIndex(segmentIndex) {\n this.segmentIndex = segmentIndex;\n }\n /**\n * Is the same for each related PDF417 symbol\n *\n * @return File ID\n */\n getFileId() {\n return this.fileId;\n }\n setFileId(fileId) {\n this.fileId = fileId;\n }\n /**\n * @return always null\n * @deprecated use dedicated already parsed fields\n */\n // @Deprecated\n getOptionalData() {\n return this.optionalData;\n }\n /**\n * @param optionalData old optional data format as int array\n * @deprecated parse and use new fields\n */\n // @Deprecated\n setOptionalData(optionalData) {\n this.optionalData = optionalData;\n }\n /**\n * @return true if it is the last segment\n */\n isLastSegment() {\n return this.lastSegment;\n }\n setLastSegment(lastSegment) {\n this.lastSegment = lastSegment;\n }\n /**\n * @return count of segments, -1 if not set\n */\n getSegmentCount() {\n return this.segmentCount;\n }\n setSegmentCount(segmentCount /*int*/) {\n this.segmentCount = segmentCount;\n }\n getSender() {\n return this.sender || null;\n }\n setSender(sender) {\n this.sender = sender;\n }\n getAddressee() {\n return this.addressee || null;\n }\n setAddressee(addressee) {\n this.addressee = addressee;\n }\n /**\n * Filename of the encoded file\n *\n * @return filename\n */\n getFileName() {\n return this.fileName;\n }\n setFileName(fileName) {\n this.fileName = fileName;\n }\n /**\n * filesize in bytes of the encoded file\n *\n * @return filesize in bytes, -1 if not set\n */\n getFileSize() {\n return this.fileSize;\n }\n setFileSize(fileSize /*long*/) {\n this.fileSize = fileSize;\n }\n /**\n * 16-bit CRC checksum using CCITT-16\n *\n * @return crc checksum, -1 if not set\n */\n getChecksum() {\n return this.checksum;\n }\n setChecksum(checksum /*int*/) {\n this.checksum = checksum;\n }\n /**\n * unix epock timestamp, elapsed seconds since 1970-01-01\n *\n * @return elapsed seconds, -1 if not set\n */\n getTimestamp() {\n return this.timestamp;\n }\n setTimestamp(timestamp /*long*/) {\n this.timestamp = timestamp;\n }\n }\n\n /**\n * Ponyfill for Java's Long class.\n */\n class Long {\n /**\n * Parses a string to a number, since JS has no really Int64.\n *\n * @param num Numeric string.\n * @param radix Destination radix.\n */\n static parseLong(num, radix = undefined) {\n return parseInt(num, radix);\n }\n }\n\n /**\n * Custom Error class of type Exception.\n */\n class NullPointerException extends Exception {\n }\n NullPointerException.kind = 'NullPointerException';\n\n /*\n * Copyright (c) 1994, 2004, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.\n *\n * This code is free software; you can redistribute it and/or modify it\n * under the terms of the GNU General Public License version 2 only, as\n * published by the Free Software Foundation. Oracle designates this\n * particular file as subject to the \"Classpath\" exception as provided\n * by Oracle in the LICENSE file that accompanied this code.\n *\n * This code is distributed in the hope that it will be useful, but WITHOUT\n * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or\n * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License\n * version 2 for more details (a copy is included in the LICENSE file that\n * accompanied this code).\n *\n * You should have received a copy of the GNU General Public License version\n * 2 along with this work; if not, write to the Free Software Foundation,\n * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.\n *\n * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA\n * or visit www.oracle.com if you need additional information or have any\n * questions.\n */\n // package java.io;\n /**\n * This abstract class is the superclass of all classes representing\n * an output stream of bytes. An output stream accepts output bytes\n * and sends them to some sink.\n *

\n * Applications that need to define a subclass of\n * OutputStream must always provide at least a method\n * that writes one byte of output.\n *\n * @author Arthur van Hoff\n * @see java.io.BufferedOutputStream\n * @see java.io.ByteArrayOutputStream\n * @see java.io.DataOutputStream\n * @see java.io.FilterOutputStream\n * @see java.io.InputStream\n * @see java.io.OutputStream#write(int)\n * @since JDK1.0\n */\n /*public*/ class OutputStream /*implements Closeable, Flushable*/ {\n /**\n * Writes b.length bytes from the specified byte array\n * to this output stream. The general contract for write(b)\n * is that it should have exactly the same effect as the call\n * write(b, 0, b.length).\n *\n * @param b the data.\n * @exception IOException if an I/O error occurs.\n * @see java.io.OutputStream#write(byte[], int, int)\n */\n writeBytes(b) {\n this.writeBytesOffset(b, 0, b.length);\n }\n /**\n * Writes len bytes from the specified byte array\n * starting at offset off to this output stream.\n * The general contract for write(b, off, len) is that\n * some of the bytes in the array b are written to the\n * output stream in order; element b[off] is the first\n * byte written and b[off+len-1] is the last byte written\n * by this operation.\n *

\n * The write method of OutputStream calls\n * the write method of one argument on each of the bytes to be\n * written out. Subclasses are encouraged to override this method and\n * provide a more efficient implementation.\n *

\n * If b is null, a\n * NullPointerException is thrown.\n *

\n * If off is negative, or len is negative, or\n * off+len is greater than the length of the array\n * b, then an IndexOutOfBoundsException is thrown.\n *\n * @param b the data.\n * @param off the start offset in the data.\n * @param len the number of bytes to write.\n * @exception IOException if an I/O error occurs. In particular,\n * an IOException is thrown if the output\n * stream is closed.\n */\n writeBytesOffset(b, off, len) {\n if (b == null) {\n throw new NullPointerException();\n }\n else if ((off < 0) || (off > b.length) || (len < 0) ||\n ((off + len) > b.length) || ((off + len) < 0)) {\n throw new IndexOutOfBoundsException();\n }\n else if (len === 0) {\n return;\n }\n for (let i = 0; i < len; i++) {\n this.write(b[off + i]);\n }\n }\n /**\n * Flushes this output stream and forces any buffered output bytes\n * to be written out. The general contract of flush is\n * that calling it is an indication that, if any bytes previously\n * written have been buffered by the implementation of the output\n * stream, such bytes should immediately be written to their\n * intended destination.\n *

\n * If the intended destination of this stream is an abstraction provided by\n * the underlying operating system, for example a file, then flushing the\n * stream guarantees only that bytes previously written to the stream are\n * passed to the operating system for writing; it does not guarantee that\n * they are actually written to a physical device such as a disk drive.\n *

\n * The flush method of OutputStream does nothing.\n *\n * @exception IOException if an I/O error occurs.\n */\n flush() {\n }\n /**\n * Closes this output stream and releases any system resources\n * associated with this stream. The general contract of close\n * is that it closes the output stream. A closed stream cannot perform\n * output operations and cannot be reopened.\n *

\n * The close method of OutputStream does nothing.\n *\n * @exception IOException if an I/O error occurs.\n */\n close() {\n }\n }\n\n /**\n * Custom Error class of type Exception.\n */\n class OutOfMemoryError extends Exception {\n }\n\n /*\n * Copyright (c) 1994, 2010, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.\n *\n * This code is free software; you can redistribute it and/or modify it\n * under the terms of the GNU General Public License version 2 only, as\n * published by the Free Software Foundation. Oracle designates this\n * particular file as subject to the \"Classpath\" exception as provided\n * by Oracle in the LICENSE file that accompanied this code.\n *\n * This code is distributed in the hope that it will be useful, but WITHOUT\n * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or\n * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License\n * version 2 for more details (a copy is included in the LICENSE file that\n * accompanied this code).\n *\n * You should have received a copy of the GNU General Public License version\n * 2 along with this work; if not, write to the Free Software Foundation,\n * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.\n *\n * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA\n * or visit www.oracle.com if you need additional information or have any\n * questions.\n */\n /**\n * This class implements an output stream in which the data is\n * written into a byte array. The buffer automatically grows as data\n * is written to it.\n * The data can be retrieved using toByteArray() and\n * toString().\n *

\n * Closing a ByteArrayOutputStream has no effect. The methods in\n * this class can be called after the stream has been closed without\n * generating an IOException.\n *\n * @author Arthur van Hoff\n * @since JDK1.0\n */\n /*public*/ class ByteArrayOutputStream extends OutputStream {\n /**\n * Creates a new byte array output stream. The buffer capacity is\n * initially 32 bytes, though its size increases if necessary.\n */\n // public constructor() {\n // this(32);\n // }\n /**\n * Creates a new byte array output stream, with a buffer capacity of\n * the specified size, in bytes.\n *\n * @param size the initial size.\n * @exception IllegalArgumentException if size is negative.\n */\n constructor(size = 32) {\n super();\n /**\n * The number of valid bytes in the buffer.\n */\n this.count = 0;\n if (size < 0) {\n throw new IllegalArgumentException('Negative initial size: '\n + size);\n }\n this.buf = new Uint8Array(size);\n }\n /**\n * Increases the capacity if necessary to ensure that it can hold\n * at least the number of elements specified by the minimum\n * capacity argument.\n *\n * @param minCapacity the desired minimum capacity\n * @throws OutOfMemoryError if {@code minCapacity < 0}. This is\n * interpreted as a request for the unsatisfiably large capacity\n * {@code (long) Integer.MAX_VALUE + (minCapacity - Integer.MAX_VALUE)}.\n */\n ensureCapacity(minCapacity) {\n // overflow-conscious code\n if (minCapacity - this.buf.length > 0)\n this.grow(minCapacity);\n }\n /**\n * Increases the capacity to ensure that it can hold at least the\n * number of elements specified by the minimum capacity argument.\n *\n * @param minCapacity the desired minimum capacity\n */\n grow(minCapacity) {\n // overflow-conscious code\n let oldCapacity = this.buf.length;\n let newCapacity = oldCapacity << 1;\n if (newCapacity - minCapacity < 0)\n newCapacity = minCapacity;\n if (newCapacity < 0) {\n if (minCapacity < 0) // overflow\n throw new OutOfMemoryError();\n newCapacity = Integer.MAX_VALUE;\n }\n this.buf = Arrays.copyOfUint8Array(this.buf, newCapacity);\n }\n /**\n * Writes the specified byte to this byte array output stream.\n *\n * @param b the byte to be written.\n */\n write(b) {\n this.ensureCapacity(this.count + 1);\n this.buf[this.count] = /*(byte)*/ b;\n this.count += 1;\n }\n /**\n * Writes len bytes from the specified byte array\n * starting at offset off to this byte array output stream.\n *\n * @param b the data.\n * @param off the start offset in the data.\n * @param len the number of bytes to write.\n */\n writeBytesOffset(b, off, len) {\n if ((off < 0) || (off > b.length) || (len < 0) ||\n ((off + len) - b.length > 0)) {\n throw new IndexOutOfBoundsException();\n }\n this.ensureCapacity(this.count + len);\n System.arraycopy(b, off, this.buf, this.count, len);\n this.count += len;\n }\n /**\n * Writes the complete contents of this byte array output stream to\n * the specified output stream argument, as if by calling the output\n * stream's write method using out.write(buf, 0, count).\n *\n * @param out the output stream to which to write the data.\n * @exception IOException if an I/O error occurs.\n */\n writeTo(out) {\n out.writeBytesOffset(this.buf, 0, this.count);\n }\n /**\n * Resets the count field of this byte array output\n * stream to zero, so that all currently accumulated output in the\n * output stream is discarded. The output stream can be used again,\n * reusing the already allocated buffer space.\n *\n * @see java.io.ByteArrayInputStream#count\n */\n reset() {\n this.count = 0;\n }\n /**\n * Creates a newly allocated byte array. Its size is the current\n * size of this output stream and the valid contents of the buffer\n * have been copied into it.\n *\n * @return the current contents of this output stream, as a byte array.\n * @see java.io.ByteArrayOutputStream#size()\n */\n toByteArray() {\n return Arrays.copyOfUint8Array(this.buf, this.count);\n }\n /**\n * Returns the current size of the buffer.\n *\n * @return the value of the count field, which is the number\n * of valid bytes in this output stream.\n * @see java.io.ByteArrayOutputStream#count\n */\n size() {\n return this.count;\n }\n toString(param) {\n if (!param) {\n return this.toString_void();\n }\n if (typeof param === 'string') {\n return this.toString_string(param);\n }\n return this.toString_number(param);\n }\n /**\n * Converts the buffer's contents into a string decoding bytes using the\n * platform's default character set. The length of the new String\n * is a function of the character set, and hence may not be equal to the\n * size of the buffer.\n *\n *

This method always replaces malformed-input and unmappable-character\n * sequences with the default replacement string for the platform's\n * default character set. The {@linkplain java.nio.charset.CharsetDecoder}\n * class should be used when more control over the decoding process is\n * required.\n *\n * @return String decoded from the buffer's contents.\n * @since JDK1.1\n */\n toString_void() {\n return new String(this.buf /*, 0, this.count*/).toString();\n }\n /**\n * Converts the buffer's contents into a string by decoding the bytes using\n * the specified {@link java.nio.charset.Charset charsetName}. The length of\n * the new String is a function of the charset, and hence may not be\n * equal to the length of the byte array.\n *\n *

This method always replaces malformed-input and unmappable-character\n * sequences with this charset's default replacement string. The {@link\n * java.nio.charset.CharsetDecoder} class should be used when more control\n * over the decoding process is required.\n *\n * @param charsetName the name of a supported\n * {@linkplain java.nio.charset.Charset charset}\n * @return String decoded from the buffer's contents.\n * @exception UnsupportedEncodingException\n * If the named charset is not supported\n * @since JDK1.1\n */\n toString_string(charsetName) {\n return new String(this.buf /*, 0, this.count, charsetName*/).toString();\n }\n /**\n * Creates a newly allocated string. Its size is the current size of\n * the output stream and the valid contents of the buffer have been\n * copied into it. Each character c in the resulting string is\n * constructed from the corresponding element b in the byte\n * array such that:\n *

\n         *     c == (char)(((hibyte & 0xff) << 8) | (b & 0xff))\n         * 
\n *\n * @deprecated This method does not properly convert bytes into characters.\n * As of JDK 1.1, the preferred way to do this is via the\n * toString(String enc) method, which takes an encoding-name\n * argument, or the toString() method, which uses the\n * platform's default character encoding.\n *\n * @param hibyte the high byte of each resulting Unicode character.\n * @return the current contents of the output stream, as a string.\n * @see java.io.ByteArrayOutputStream#size()\n * @see java.io.ByteArrayOutputStream#toString(String)\n * @see java.io.ByteArrayOutputStream#toString()\n */\n // @Deprecated\n toString_number(hibyte) {\n return new String(this.buf /*, hibyte, 0, this.count*/).toString();\n }\n /**\n * Closing a ByteArrayOutputStream has no effect. The methods in\n * this class can be called after the stream has been closed without\n * generating an IOException.\n *

\n *\n * @throws IOException\n */\n close() {\n }\n }\n\n /*\n * Copyright 2009 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n /*private*/ var Mode$2;\n (function (Mode) {\n Mode[Mode[\"ALPHA\"] = 0] = \"ALPHA\";\n Mode[Mode[\"LOWER\"] = 1] = \"LOWER\";\n Mode[Mode[\"MIXED\"] = 2] = \"MIXED\";\n Mode[Mode[\"PUNCT\"] = 3] = \"PUNCT\";\n Mode[Mode[\"ALPHA_SHIFT\"] = 4] = \"ALPHA_SHIFT\";\n Mode[Mode[\"PUNCT_SHIFT\"] = 5] = \"PUNCT_SHIFT\";\n })(Mode$2 || (Mode$2 = {}));\n /**\n * Indirectly access the global BigInt constructor, it\n * allows browsers that doesn't support BigInt to run\n * the library without breaking due to \"undefined BigInt\"\n * errors.\n */\n function getBigIntConstructor() {\n if (typeof window !== 'undefined') {\n return window['BigInt'] || null;\n }\n if (typeof global !== 'undefined') {\n return global['BigInt'] || null;\n }\n if (typeof self !== 'undefined') {\n return self['BigInt'] || null;\n }\n throw new Error('Can\\'t search globals for BigInt!');\n }\n /**\n * Used to store the BigInt constructor.\n */\n let BigInteger;\n /**\n * This function creates a bigint value. It allows browsers\n * that doesn't support BigInt to run the rest of the library\n * by not directly accessing the BigInt constructor.\n */\n function createBigInt(num) {\n if (typeof BigInteger === 'undefined') {\n BigInteger = getBigIntConstructor();\n }\n if (BigInteger === null) {\n throw new Error('BigInt is not supported!');\n }\n return BigInteger(num);\n }\n function getEXP900() {\n // in Java - array with length = 16\n let EXP900 = [];\n EXP900[0] = createBigInt(1);\n let nineHundred = createBigInt(900);\n EXP900[1] = nineHundred;\n // in Java - array with length = 16\n for (let i /*int*/ = 2; i < 16; i++) {\n EXP900[i] = EXP900[i - 1] * nineHundred;\n }\n return EXP900;\n }\n /**\n *

This class contains the methods for decoding the PDF417 codewords.

\n *\n * @author SITA Lab (kevin.osullivan@sita.aero)\n * @author Guenther Grau\n */\n /*final*/ class DecodedBitStreamParser$2 {\n // private DecodedBitStreamParser() {\n // }\n /**\n *\n * @param codewords\n * @param ecLevel\n *\n * @throws FormatException\n */\n static decode(codewords, ecLevel) {\n // pass encoding to result (will be used for decode symbols in byte mode)\n let result = new StringBuilder('');\n // let encoding: Charset = StandardCharsets.ISO_8859_1;\n let encoding = CharacterSetECI.ISO8859_1;\n /**\n * @note the next command is specific from this TypeScript library\n * because TS can't properly cast some values to char and\n * convert it to string later correctly due to encoding\n * differences from Java version. As reported here:\n * https://github.com/zxing-js/library/pull/264/files#r382831593\n */\n result.enableDecoding(encoding);\n // Get compaction mode\n let codeIndex = 1;\n let code = codewords[codeIndex++];\n let resultMetadata = new PDF417ResultMetadata();\n while (codeIndex < codewords[0]) {\n switch (code) {\n case DecodedBitStreamParser$2.TEXT_COMPACTION_MODE_LATCH:\n codeIndex = DecodedBitStreamParser$2.textCompaction(codewords, codeIndex, result);\n break;\n case DecodedBitStreamParser$2.BYTE_COMPACTION_MODE_LATCH:\n case DecodedBitStreamParser$2.BYTE_COMPACTION_MODE_LATCH_6:\n codeIndex = DecodedBitStreamParser$2.byteCompaction(code, codewords, encoding, codeIndex, result);\n break;\n case DecodedBitStreamParser$2.MODE_SHIFT_TO_BYTE_COMPACTION_MODE:\n result.append(/*(char)*/ codewords[codeIndex++]);\n break;\n case DecodedBitStreamParser$2.NUMERIC_COMPACTION_MODE_LATCH:\n codeIndex = DecodedBitStreamParser$2.numericCompaction(codewords, codeIndex, result);\n break;\n case DecodedBitStreamParser$2.ECI_CHARSET:\n let charsetECI = CharacterSetECI.getCharacterSetECIByValue(codewords[codeIndex++]);\n // encoding = Charset.forName(charsetECI.getName());\n break;\n case DecodedBitStreamParser$2.ECI_GENERAL_PURPOSE:\n // Can't do anything with generic ECI; skip its 2 characters\n codeIndex += 2;\n break;\n case DecodedBitStreamParser$2.ECI_USER_DEFINED:\n // Can't do anything with user ECI; skip its 1 character\n codeIndex++;\n break;\n case DecodedBitStreamParser$2.BEGIN_MACRO_PDF417_CONTROL_BLOCK:\n codeIndex = DecodedBitStreamParser$2.decodeMacroBlock(codewords, codeIndex, resultMetadata);\n break;\n case DecodedBitStreamParser$2.BEGIN_MACRO_PDF417_OPTIONAL_FIELD:\n case DecodedBitStreamParser$2.MACRO_PDF417_TERMINATOR:\n // Should not see these outside a macro block\n throw new FormatException();\n default:\n // Default to text compaction. During testing numerous barcodes\n // appeared to be missing the starting mode. In these cases defaulting\n // to text compaction seems to work.\n codeIndex--;\n codeIndex = DecodedBitStreamParser$2.textCompaction(codewords, codeIndex, result);\n break;\n }\n if (codeIndex < codewords.length) {\n code = codewords[codeIndex++];\n }\n else {\n throw FormatException.getFormatInstance();\n }\n }\n if (result.length() === 0) {\n throw FormatException.getFormatInstance();\n }\n let decoderResult = new DecoderResult(null, result.toString(), null, ecLevel);\n decoderResult.setOther(resultMetadata);\n return decoderResult;\n }\n /**\n *\n * @param int\n * @param param1\n * @param codewords\n * @param int\n * @param codeIndex\n * @param PDF417ResultMetadata\n * @param resultMetadata\n *\n * @throws FormatException\n */\n // @SuppressWarnings(\"deprecation\")\n static decodeMacroBlock(codewords, codeIndex, resultMetadata) {\n if (codeIndex + DecodedBitStreamParser$2.NUMBER_OF_SEQUENCE_CODEWORDS > codewords[0]) {\n // we must have at least two bytes left for the segment index\n throw FormatException.getFormatInstance();\n }\n let segmentIndexArray = new Int32Array(DecodedBitStreamParser$2.NUMBER_OF_SEQUENCE_CODEWORDS);\n for (let i /*int*/ = 0; i < DecodedBitStreamParser$2.NUMBER_OF_SEQUENCE_CODEWORDS; i++, codeIndex++) {\n segmentIndexArray[i] = codewords[codeIndex];\n }\n resultMetadata.setSegmentIndex(Integer.parseInt(DecodedBitStreamParser$2.decodeBase900toBase10(segmentIndexArray, DecodedBitStreamParser$2.NUMBER_OF_SEQUENCE_CODEWORDS)));\n let fileId = new StringBuilder();\n codeIndex = DecodedBitStreamParser$2.textCompaction(codewords, codeIndex, fileId);\n resultMetadata.setFileId(fileId.toString());\n let optionalFieldsStart = -1;\n if (codewords[codeIndex] === DecodedBitStreamParser$2.BEGIN_MACRO_PDF417_OPTIONAL_FIELD) {\n optionalFieldsStart = codeIndex + 1;\n }\n while (codeIndex < codewords[0]) {\n switch (codewords[codeIndex]) {\n case DecodedBitStreamParser$2.BEGIN_MACRO_PDF417_OPTIONAL_FIELD:\n codeIndex++;\n switch (codewords[codeIndex]) {\n case DecodedBitStreamParser$2.MACRO_PDF417_OPTIONAL_FIELD_FILE_NAME:\n let fileName = new StringBuilder();\n codeIndex = DecodedBitStreamParser$2.textCompaction(codewords, codeIndex + 1, fileName);\n resultMetadata.setFileName(fileName.toString());\n break;\n case DecodedBitStreamParser$2.MACRO_PDF417_OPTIONAL_FIELD_SENDER:\n let sender = new StringBuilder();\n codeIndex = DecodedBitStreamParser$2.textCompaction(codewords, codeIndex + 1, sender);\n resultMetadata.setSender(sender.toString());\n break;\n case DecodedBitStreamParser$2.MACRO_PDF417_OPTIONAL_FIELD_ADDRESSEE:\n let addressee = new StringBuilder();\n codeIndex = DecodedBitStreamParser$2.textCompaction(codewords, codeIndex + 1, addressee);\n resultMetadata.setAddressee(addressee.toString());\n break;\n case DecodedBitStreamParser$2.MACRO_PDF417_OPTIONAL_FIELD_SEGMENT_COUNT:\n let segmentCount = new StringBuilder();\n codeIndex = DecodedBitStreamParser$2.numericCompaction(codewords, codeIndex + 1, segmentCount);\n resultMetadata.setSegmentCount(Integer.parseInt(segmentCount.toString()));\n break;\n case DecodedBitStreamParser$2.MACRO_PDF417_OPTIONAL_FIELD_TIME_STAMP:\n let timestamp = new StringBuilder();\n codeIndex = DecodedBitStreamParser$2.numericCompaction(codewords, codeIndex + 1, timestamp);\n resultMetadata.setTimestamp(Long.parseLong(timestamp.toString()));\n break;\n case DecodedBitStreamParser$2.MACRO_PDF417_OPTIONAL_FIELD_CHECKSUM:\n let checksum = new StringBuilder();\n codeIndex = DecodedBitStreamParser$2.numericCompaction(codewords, codeIndex + 1, checksum);\n resultMetadata.setChecksum(Integer.parseInt(checksum.toString()));\n break;\n case DecodedBitStreamParser$2.MACRO_PDF417_OPTIONAL_FIELD_FILE_SIZE:\n let fileSize = new StringBuilder();\n codeIndex = DecodedBitStreamParser$2.numericCompaction(codewords, codeIndex + 1, fileSize);\n resultMetadata.setFileSize(Long.parseLong(fileSize.toString()));\n break;\n default:\n throw FormatException.getFormatInstance();\n }\n break;\n case DecodedBitStreamParser$2.MACRO_PDF417_TERMINATOR:\n codeIndex++;\n resultMetadata.setLastSegment(true);\n break;\n default:\n throw FormatException.getFormatInstance();\n }\n }\n // copy optional fields to additional options\n if (optionalFieldsStart !== -1) {\n let optionalFieldsLength = codeIndex - optionalFieldsStart;\n if (resultMetadata.isLastSegment()) {\n // do not include terminator\n optionalFieldsLength--;\n }\n resultMetadata.setOptionalData(Arrays.copyOfRange(codewords, optionalFieldsStart, optionalFieldsStart + optionalFieldsLength));\n }\n return codeIndex;\n }\n /**\n * Text Compaction mode (see 5.4.1.5) permits all printable ASCII characters to be\n * encoded, i.e. values 32 - 126 inclusive in accordance with ISO/IEC 646 (IRV), as\n * well as selected control characters.\n *\n * @param codewords The array of codewords (data + error)\n * @param codeIndex The current index into the codeword array.\n * @param result The decoded data is appended to the result.\n * @return The next index into the codeword array.\n */\n static textCompaction(codewords, codeIndex, result) {\n // 2 character per codeword\n let textCompactionData = new Int32Array((codewords[0] - codeIndex) * 2);\n // Used to hold the byte compaction value if there is a mode shift\n let byteCompactionData = new Int32Array((codewords[0] - codeIndex) * 2);\n let index = 0;\n let end = false;\n while ((codeIndex < codewords[0]) && !end) {\n let code = codewords[codeIndex++];\n if (code < DecodedBitStreamParser$2.TEXT_COMPACTION_MODE_LATCH) {\n textCompactionData[index] = code / 30;\n textCompactionData[index + 1] = code % 30;\n index += 2;\n }\n else {\n switch (code) {\n case DecodedBitStreamParser$2.TEXT_COMPACTION_MODE_LATCH:\n // reinitialize text compaction mode to alpha sub mode\n textCompactionData[index++] = DecodedBitStreamParser$2.TEXT_COMPACTION_MODE_LATCH;\n break;\n case DecodedBitStreamParser$2.BYTE_COMPACTION_MODE_LATCH:\n case DecodedBitStreamParser$2.BYTE_COMPACTION_MODE_LATCH_6:\n case DecodedBitStreamParser$2.NUMERIC_COMPACTION_MODE_LATCH:\n case DecodedBitStreamParser$2.BEGIN_MACRO_PDF417_CONTROL_BLOCK:\n case DecodedBitStreamParser$2.BEGIN_MACRO_PDF417_OPTIONAL_FIELD:\n case DecodedBitStreamParser$2.MACRO_PDF417_TERMINATOR:\n codeIndex--;\n end = true;\n break;\n case DecodedBitStreamParser$2.MODE_SHIFT_TO_BYTE_COMPACTION_MODE:\n // The Mode Shift codeword 913 shall cause a temporary\n // switch from Text Compaction mode to Byte Compaction mode.\n // This switch shall be in effect for only the next codeword,\n // after which the mode shall revert to the prevailing sub-mode\n // of the Text Compaction mode. Codeword 913 is only available\n // in Text Compaction mode; its use is described in 5.4.2.4.\n textCompactionData[index] = DecodedBitStreamParser$2.MODE_SHIFT_TO_BYTE_COMPACTION_MODE;\n code = codewords[codeIndex++];\n byteCompactionData[index] = code;\n index++;\n break;\n }\n }\n }\n DecodedBitStreamParser$2.decodeTextCompaction(textCompactionData, byteCompactionData, index, result);\n return codeIndex;\n }\n /**\n * The Text Compaction mode includes all the printable ASCII characters\n * (i.e. values from 32 to 126) and three ASCII control characters: HT or tab\n * (9: e), LF or line feed (10: e), and CR or carriage\n * return (13: e). The Text Compaction mode also includes various latch\n * and shift characters which are used exclusively within the mode. The Text\n * Compaction mode encodes up to 2 characters per codeword. The compaction rules\n * for converting data into PDF417 codewords are defined in 5.4.2.2. The sub-mode\n * switches are defined in 5.4.2.3.\n *\n * @param textCompactionData The text compaction data.\n * @param byteCompactionData The byte compaction data if there\n * was a mode shift.\n * @param length The size of the text compaction and byte compaction data.\n * @param result The decoded data is appended to the result.\n */\n static decodeTextCompaction(textCompactionData, byteCompactionData, length, result) {\n // Beginning from an initial state of the Alpha sub-mode\n // The default compaction mode for PDF417 in effect at the start of each symbol shall always be Text\n // Compaction mode Alpha sub-mode (alphabetic: uppercase). A latch codeword from another mode to the Text\n // Compaction mode shall always switch to the Text Compaction Alpha sub-mode.\n let subMode = Mode$2.ALPHA;\n let priorToShiftMode = Mode$2.ALPHA;\n let i = 0;\n while (i < length) {\n let subModeCh = textCompactionData[i];\n let ch = /*char*/ '';\n switch (subMode) {\n case Mode$2.ALPHA:\n // Alpha (alphabetic: uppercase)\n if (subModeCh < 26) {\n // Upper case Alpha Character\n // Note: 65 = 'A' ASCII -> there is byte code of symbol\n ch = /*(char)('A' + subModeCh) */ String.fromCharCode(65 + subModeCh);\n }\n else {\n switch (subModeCh) {\n case 26:\n ch = ' ';\n break;\n case DecodedBitStreamParser$2.LL:\n subMode = Mode$2.LOWER;\n break;\n case DecodedBitStreamParser$2.ML:\n subMode = Mode$2.MIXED;\n break;\n case DecodedBitStreamParser$2.PS:\n // Shift to punctuation\n priorToShiftMode = subMode;\n subMode = Mode$2.PUNCT_SHIFT;\n break;\n case DecodedBitStreamParser$2.MODE_SHIFT_TO_BYTE_COMPACTION_MODE:\n result.append(/*(char)*/ byteCompactionData[i]);\n break;\n case DecodedBitStreamParser$2.TEXT_COMPACTION_MODE_LATCH:\n subMode = Mode$2.ALPHA;\n break;\n }\n }\n break;\n case Mode$2.LOWER:\n // Lower (alphabetic: lowercase)\n if (subModeCh < 26) {\n ch = /*(char)('a' + subModeCh)*/ String.fromCharCode(97 + subModeCh);\n }\n else {\n switch (subModeCh) {\n case 26:\n ch = ' ';\n break;\n case DecodedBitStreamParser$2.AS:\n // Shift to alpha\n priorToShiftMode = subMode;\n subMode = Mode$2.ALPHA_SHIFT;\n break;\n case DecodedBitStreamParser$2.ML:\n subMode = Mode$2.MIXED;\n break;\n case DecodedBitStreamParser$2.PS:\n // Shift to punctuation\n priorToShiftMode = subMode;\n subMode = Mode$2.PUNCT_SHIFT;\n break;\n case DecodedBitStreamParser$2.MODE_SHIFT_TO_BYTE_COMPACTION_MODE:\n // TODO Does this need to use the current character encoding? See other occurrences below\n result.append(/*(char)*/ byteCompactionData[i]);\n break;\n case DecodedBitStreamParser$2.TEXT_COMPACTION_MODE_LATCH:\n subMode = Mode$2.ALPHA;\n break;\n }\n }\n break;\n case Mode$2.MIXED:\n // Mixed (punctuation: e)\n if (subModeCh < DecodedBitStreamParser$2.PL) {\n ch = DecodedBitStreamParser$2.MIXED_CHARS[subModeCh];\n }\n else {\n switch (subModeCh) {\n case DecodedBitStreamParser$2.PL:\n subMode = Mode$2.PUNCT;\n break;\n case 26:\n ch = ' ';\n break;\n case DecodedBitStreamParser$2.LL:\n subMode = Mode$2.LOWER;\n break;\n case DecodedBitStreamParser$2.AL:\n subMode = Mode$2.ALPHA;\n break;\n case DecodedBitStreamParser$2.PS:\n // Shift to punctuation\n priorToShiftMode = subMode;\n subMode = Mode$2.PUNCT_SHIFT;\n break;\n case DecodedBitStreamParser$2.MODE_SHIFT_TO_BYTE_COMPACTION_MODE:\n result.append(/*(char)*/ byteCompactionData[i]);\n break;\n case DecodedBitStreamParser$2.TEXT_COMPACTION_MODE_LATCH:\n subMode = Mode$2.ALPHA;\n break;\n }\n }\n break;\n case Mode$2.PUNCT:\n // Punctuation\n if (subModeCh < DecodedBitStreamParser$2.PAL) {\n ch = DecodedBitStreamParser$2.PUNCT_CHARS[subModeCh];\n }\n else {\n switch (subModeCh) {\n case DecodedBitStreamParser$2.PAL:\n subMode = Mode$2.ALPHA;\n break;\n case DecodedBitStreamParser$2.MODE_SHIFT_TO_BYTE_COMPACTION_MODE:\n result.append(/*(char)*/ byteCompactionData[i]);\n break;\n case DecodedBitStreamParser$2.TEXT_COMPACTION_MODE_LATCH:\n subMode = Mode$2.ALPHA;\n break;\n }\n }\n break;\n case Mode$2.ALPHA_SHIFT:\n // Restore sub-mode\n subMode = priorToShiftMode;\n if (subModeCh < 26) {\n ch = /*(char)('A' + subModeCh)*/ String.fromCharCode(65 + subModeCh);\n }\n else {\n switch (subModeCh) {\n case 26:\n ch = ' ';\n break;\n case DecodedBitStreamParser$2.TEXT_COMPACTION_MODE_LATCH:\n subMode = Mode$2.ALPHA;\n break;\n }\n }\n break;\n case Mode$2.PUNCT_SHIFT:\n // Restore sub-mode\n subMode = priorToShiftMode;\n if (subModeCh < DecodedBitStreamParser$2.PAL) {\n ch = DecodedBitStreamParser$2.PUNCT_CHARS[subModeCh];\n }\n else {\n switch (subModeCh) {\n case DecodedBitStreamParser$2.PAL:\n subMode = Mode$2.ALPHA;\n break;\n case DecodedBitStreamParser$2.MODE_SHIFT_TO_BYTE_COMPACTION_MODE:\n // PS before Shift-to-Byte is used as a padding character,\n // see 5.4.2.4 of the specification\n result.append(/*(char)*/ byteCompactionData[i]);\n break;\n case DecodedBitStreamParser$2.TEXT_COMPACTION_MODE_LATCH:\n subMode = Mode$2.ALPHA;\n break;\n }\n }\n break;\n }\n // if (ch !== 0) {\n if (ch !== '') {\n // Append decoded character to result\n result.append(ch);\n }\n i++;\n }\n }\n /**\n * Byte Compaction mode (see 5.4.3) permits all 256 possible 8-bit byte values to be encoded.\n * This includes all ASCII characters value 0 to 127 inclusive and provides for international\n * character set support.\n *\n * @param mode The byte compaction mode i.e. 901 or 924\n * @param codewords The array of codewords (data + error)\n * @param encoding Currently active character encoding\n * @param codeIndex The current index into the codeword array.\n * @param result The decoded data is appended to the result.\n * @return The next index into the codeword array.\n */\n static /*int*/ byteCompaction(mode, codewords, encoding, codeIndex, result) {\n let decodedBytes = new ByteArrayOutputStream();\n let count = 0;\n let value = /*long*/ 0;\n let end = false;\n switch (mode) {\n case DecodedBitStreamParser$2.BYTE_COMPACTION_MODE_LATCH:\n // Total number of Byte Compaction characters to be encoded\n // is not a multiple of 6\n let byteCompactedCodewords = new Int32Array(6);\n let nextCode = codewords[codeIndex++];\n while ((codeIndex < codewords[0]) && !end) {\n byteCompactedCodewords[count++] = nextCode;\n // Base 900\n value = 900 * value + nextCode;\n nextCode = codewords[codeIndex++];\n // perhaps it should be ok to check only nextCode >= TEXT_COMPACTION_MODE_LATCH\n switch (nextCode) {\n case DecodedBitStreamParser$2.TEXT_COMPACTION_MODE_LATCH:\n case DecodedBitStreamParser$2.BYTE_COMPACTION_MODE_LATCH:\n case DecodedBitStreamParser$2.NUMERIC_COMPACTION_MODE_LATCH:\n case DecodedBitStreamParser$2.BYTE_COMPACTION_MODE_LATCH_6:\n case DecodedBitStreamParser$2.BEGIN_MACRO_PDF417_CONTROL_BLOCK:\n case DecodedBitStreamParser$2.BEGIN_MACRO_PDF417_OPTIONAL_FIELD:\n case DecodedBitStreamParser$2.MACRO_PDF417_TERMINATOR:\n codeIndex--;\n end = true;\n break;\n default:\n if ((count % 5 === 0) && (count > 0)) {\n // Decode every 5 codewords\n // Convert to Base 256\n for (let j /*int*/ = 0; j < 6; ++j) {\n /* @note\n * JavaScript stores numbers as 64 bits floating point numbers, but all bitwise operations are performed on 32 bits binary numbers.\n * So the next bitwise operation could not be done with simple numbers\n */\n decodedBytes.write(/*(byte)*/ Number(createBigInt(value) >> createBigInt(8 * (5 - j))));\n }\n value = 0;\n count = 0;\n }\n break;\n }\n }\n // if the end of all codewords is reached the last codeword needs to be added\n if (codeIndex === codewords[0] && nextCode < DecodedBitStreamParser$2.TEXT_COMPACTION_MODE_LATCH) {\n byteCompactedCodewords[count++] = nextCode;\n }\n // If Byte Compaction mode is invoked with codeword 901,\n // the last group of codewords is interpreted directly\n // as one byte per codeword, without compaction.\n for (let i /*int*/ = 0; i < count; i++) {\n decodedBytes.write(/*(byte)*/ byteCompactedCodewords[i]);\n }\n break;\n case DecodedBitStreamParser$2.BYTE_COMPACTION_MODE_LATCH_6:\n // Total number of Byte Compaction characters to be encoded\n // is an integer multiple of 6\n while (codeIndex < codewords[0] && !end) {\n let code = codewords[codeIndex++];\n if (code < DecodedBitStreamParser$2.TEXT_COMPACTION_MODE_LATCH) {\n count++;\n // Base 900\n value = 900 * value + code;\n }\n else {\n switch (code) {\n case DecodedBitStreamParser$2.TEXT_COMPACTION_MODE_LATCH:\n case DecodedBitStreamParser$2.BYTE_COMPACTION_MODE_LATCH:\n case DecodedBitStreamParser$2.NUMERIC_COMPACTION_MODE_LATCH:\n case DecodedBitStreamParser$2.BYTE_COMPACTION_MODE_LATCH_6:\n case DecodedBitStreamParser$2.BEGIN_MACRO_PDF417_CONTROL_BLOCK:\n case DecodedBitStreamParser$2.BEGIN_MACRO_PDF417_OPTIONAL_FIELD:\n case DecodedBitStreamParser$2.MACRO_PDF417_TERMINATOR:\n codeIndex--;\n end = true;\n break;\n }\n }\n if ((count % 5 === 0) && (count > 0)) {\n // Decode every 5 codewords\n // Convert to Base 256\n /* @note\n * JavaScript stores numbers as 64 bits floating point numbers, but all bitwise operations are performed on 32 bits binary numbers.\n * So the next bitwise operation could not be done with simple numbers\n */\n for (let j /*int*/ = 0; j < 6; ++j) {\n decodedBytes.write(/*(byte)*/ Number(createBigInt(value) >> createBigInt(8 * (5 - j))));\n }\n value = 0;\n count = 0;\n }\n }\n break;\n }\n result.append(StringEncoding.decode(decodedBytes.toByteArray(), encoding));\n return codeIndex;\n }\n /**\n * Numeric Compaction mode (see 5.4.4) permits efficient encoding of numeric data strings.\n *\n * @param codewords The array of codewords (data + error)\n * @param codeIndex The current index into the codeword array.\n * @param result The decoded data is appended to the result.\n * @return The next index into the codeword array.\n *\n * @throws FormatException\n */\n static numericCompaction(codewords, codeIndex /*int*/, result) {\n let count = 0;\n let end = false;\n let numericCodewords = new Int32Array(DecodedBitStreamParser$2.MAX_NUMERIC_CODEWORDS);\n while (codeIndex < codewords[0] && !end) {\n let code = codewords[codeIndex++];\n if (codeIndex === codewords[0]) {\n end = true;\n }\n if (code < DecodedBitStreamParser$2.TEXT_COMPACTION_MODE_LATCH) {\n numericCodewords[count] = code;\n count++;\n }\n else {\n switch (code) {\n case DecodedBitStreamParser$2.TEXT_COMPACTION_MODE_LATCH:\n case DecodedBitStreamParser$2.BYTE_COMPACTION_MODE_LATCH:\n case DecodedBitStreamParser$2.BYTE_COMPACTION_MODE_LATCH_6:\n case DecodedBitStreamParser$2.BEGIN_MACRO_PDF417_CONTROL_BLOCK:\n case DecodedBitStreamParser$2.BEGIN_MACRO_PDF417_OPTIONAL_FIELD:\n case DecodedBitStreamParser$2.MACRO_PDF417_TERMINATOR:\n codeIndex--;\n end = true;\n break;\n }\n }\n if ((count % DecodedBitStreamParser$2.MAX_NUMERIC_CODEWORDS === 0 || code === DecodedBitStreamParser$2.NUMERIC_COMPACTION_MODE_LATCH || end) && count > 0) {\n // Re-invoking Numeric Compaction mode (by using codeword 902\n // while in Numeric Compaction mode) serves to terminate the\n // current Numeric Compaction mode grouping as described in 5.4.4.2,\n // and then to start a new one grouping.\n result.append(DecodedBitStreamParser$2.decodeBase900toBase10(numericCodewords, count));\n count = 0;\n }\n }\n return codeIndex;\n }\n /**\n * Convert a list of Numeric Compacted codewords from Base 900 to Base 10.\n *\n * @param codewords The array of codewords\n * @param count The number of codewords\n * @return The decoded string representing the Numeric data.\n *\n * EXAMPLE\n * Encode the fifteen digit numeric string 000213298174000\n * Prefix the numeric string with a 1 and set the initial value of\n * t = 1 000 213 298 174 000\n * Calculate codeword 0\n * d0 = 1 000 213 298 174 000 mod 900 = 200\n *\n * t = 1 000 213 298 174 000 div 900 = 1 111 348 109 082\n * Calculate codeword 1\n * d1 = 1 111 348 109 082 mod 900 = 282\n *\n * t = 1 111 348 109 082 div 900 = 1 234 831 232\n * Calculate codeword 2\n * d2 = 1 234 831 232 mod 900 = 632\n *\n * t = 1 234 831 232 div 900 = 1 372 034\n * Calculate codeword 3\n * d3 = 1 372 034 mod 900 = 434\n *\n * t = 1 372 034 div 900 = 1 524\n * Calculate codeword 4\n * d4 = 1 524 mod 900 = 624\n *\n * t = 1 524 div 900 = 1\n * Calculate codeword 5\n * d5 = 1 mod 900 = 1\n * t = 1 div 900 = 0\n * Codeword sequence is: 1, 624, 434, 632, 282, 200\n *\n * Decode the above codewords involves\n * 1 x 900 power of 5 + 624 x 900 power of 4 + 434 x 900 power of 3 +\n * 632 x 900 power of 2 + 282 x 900 power of 1 + 200 x 900 power of 0 = 1000213298174000\n *\n * Remove leading 1 => Result is 000213298174000\n *\n * @throws FormatException\n */\n static decodeBase900toBase10(codewords, count) {\n let result = createBigInt(0);\n for (let i /*int*/ = 0; i < count; i++) {\n result += DecodedBitStreamParser$2.EXP900[count - i - 1] * createBigInt(codewords[i]);\n }\n let resultString = result.toString();\n if (resultString.charAt(0) !== '1') {\n throw new FormatException();\n }\n return resultString.substring(1);\n }\n }\n DecodedBitStreamParser$2.TEXT_COMPACTION_MODE_LATCH = 900;\n DecodedBitStreamParser$2.BYTE_COMPACTION_MODE_LATCH = 901;\n DecodedBitStreamParser$2.NUMERIC_COMPACTION_MODE_LATCH = 902;\n DecodedBitStreamParser$2.BYTE_COMPACTION_MODE_LATCH_6 = 924;\n DecodedBitStreamParser$2.ECI_USER_DEFINED = 925;\n DecodedBitStreamParser$2.ECI_GENERAL_PURPOSE = 926;\n DecodedBitStreamParser$2.ECI_CHARSET = 927;\n DecodedBitStreamParser$2.BEGIN_MACRO_PDF417_CONTROL_BLOCK = 928;\n DecodedBitStreamParser$2.BEGIN_MACRO_PDF417_OPTIONAL_FIELD = 923;\n DecodedBitStreamParser$2.MACRO_PDF417_TERMINATOR = 922;\n DecodedBitStreamParser$2.MODE_SHIFT_TO_BYTE_COMPACTION_MODE = 913;\n DecodedBitStreamParser$2.MAX_NUMERIC_CODEWORDS = 15;\n DecodedBitStreamParser$2.MACRO_PDF417_OPTIONAL_FIELD_FILE_NAME = 0;\n DecodedBitStreamParser$2.MACRO_PDF417_OPTIONAL_FIELD_SEGMENT_COUNT = 1;\n DecodedBitStreamParser$2.MACRO_PDF417_OPTIONAL_FIELD_TIME_STAMP = 2;\n DecodedBitStreamParser$2.MACRO_PDF417_OPTIONAL_FIELD_SENDER = 3;\n DecodedBitStreamParser$2.MACRO_PDF417_OPTIONAL_FIELD_ADDRESSEE = 4;\n DecodedBitStreamParser$2.MACRO_PDF417_OPTIONAL_FIELD_FILE_SIZE = 5;\n DecodedBitStreamParser$2.MACRO_PDF417_OPTIONAL_FIELD_CHECKSUM = 6;\n DecodedBitStreamParser$2.PL = 25;\n DecodedBitStreamParser$2.LL = 27;\n DecodedBitStreamParser$2.AS = 27;\n DecodedBitStreamParser$2.ML = 28;\n DecodedBitStreamParser$2.AL = 28;\n DecodedBitStreamParser$2.PS = 29;\n DecodedBitStreamParser$2.PAL = 29;\n DecodedBitStreamParser$2.PUNCT_CHARS = ';<>@[\\\\]_`~!\\r\\t,:\\n-.$/\"|*()?{}\\'';\n DecodedBitStreamParser$2.MIXED_CHARS = '0123456789&\\r\\t,:#-.$/+%*=^';\n /**\n * Table containing values for the exponent of 900.\n * This is used in the numeric compaction decode algorithm.\n */\n DecodedBitStreamParser$2.EXP900 = getBigIntConstructor() ? getEXP900() : [];\n DecodedBitStreamParser$2.NUMBER_OF_SEQUENCE_CODEWORDS = 2;\n\n /*\n * Copyright 2013 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n // import java.util.ArrayList;\n // import java.util.Collection;\n // import java.util.Formatter;\n // import java.util.List;\n /**\n * @author Guenther Grau\n */\n /*public final*/ class PDF417ScanningDecoder {\n constructor() { }\n /**\n * @TODO don't pass in minCodewordWidth and maxCodewordWidth, pass in barcode columns for start and stop pattern\n *\n * columns. That way width can be deducted from the pattern column.\n * This approach also allows to detect more details about the barcode, e.g. if a bar type (white or black) is wider\n * than it should be. This can happen if the scanner used a bad blackpoint.\n *\n * @param BitMatrix\n * @param image\n * @param ResultPoint\n * @param imageTopLeft\n * @param ResultPoint\n * @param imageBottomLeft\n * @param ResultPoint\n * @param imageTopRight\n * @param ResultPoint\n * @param imageBottomRight\n * @param int\n * @param minCodewordWidth\n * @param int\n * @param maxCodewordWidth\n *\n * @throws NotFoundException\n * @throws FormatException\n * @throws ChecksumException\n */\n static decode(image, imageTopLeft, imageBottomLeft, imageTopRight, imageBottomRight, minCodewordWidth, maxCodewordWidth) {\n let boundingBox = new BoundingBox(image, imageTopLeft, imageBottomLeft, imageTopRight, imageBottomRight);\n let leftRowIndicatorColumn = null;\n let rightRowIndicatorColumn = null;\n let detectionResult;\n for (let firstPass /*boolean*/ = true;; firstPass = false) {\n if (imageTopLeft != null) {\n leftRowIndicatorColumn = PDF417ScanningDecoder.getRowIndicatorColumn(image, boundingBox, imageTopLeft, true, minCodewordWidth, maxCodewordWidth);\n }\n if (imageTopRight != null) {\n rightRowIndicatorColumn = PDF417ScanningDecoder.getRowIndicatorColumn(image, boundingBox, imageTopRight, false, minCodewordWidth, maxCodewordWidth);\n }\n detectionResult = PDF417ScanningDecoder.merge(leftRowIndicatorColumn, rightRowIndicatorColumn);\n if (detectionResult == null) {\n throw NotFoundException.getNotFoundInstance();\n }\n let resultBox = detectionResult.getBoundingBox();\n if (firstPass && resultBox != null &&\n (resultBox.getMinY() < boundingBox.getMinY() || resultBox.getMaxY() > boundingBox.getMaxY())) {\n boundingBox = resultBox;\n }\n else {\n break;\n }\n }\n detectionResult.setBoundingBox(boundingBox);\n let maxBarcodeColumn = detectionResult.getBarcodeColumnCount() + 1;\n detectionResult.setDetectionResultColumn(0, leftRowIndicatorColumn);\n detectionResult.setDetectionResultColumn(maxBarcodeColumn, rightRowIndicatorColumn);\n let leftToRight = leftRowIndicatorColumn != null;\n for (let barcodeColumnCount /*int*/ = 1; barcodeColumnCount <= maxBarcodeColumn; barcodeColumnCount++) {\n let barcodeColumn = leftToRight ? barcodeColumnCount : maxBarcodeColumn - barcodeColumnCount;\n if (detectionResult.getDetectionResultColumn(barcodeColumn) !== /* null */ undefined) {\n // This will be the case for the opposite row indicator column, which doesn't need to be decoded again.\n continue;\n }\n let detectionResultColumn;\n if (barcodeColumn === 0 || barcodeColumn === maxBarcodeColumn) {\n detectionResultColumn = new DetectionResultRowIndicatorColumn(boundingBox, barcodeColumn === 0);\n }\n else {\n detectionResultColumn = new DetectionResultColumn(boundingBox);\n }\n detectionResult.setDetectionResultColumn(barcodeColumn, detectionResultColumn);\n let startColumn = -1;\n let previousStartColumn = startColumn;\n // TODO start at a row for which we know the start position, then detect upwards and downwards from there.\n for (let imageRow /*int*/ = boundingBox.getMinY(); imageRow <= boundingBox.getMaxY(); imageRow++) {\n startColumn = PDF417ScanningDecoder.getStartColumn(detectionResult, barcodeColumn, imageRow, leftToRight);\n if (startColumn < 0 || startColumn > boundingBox.getMaxX()) {\n if (previousStartColumn === -1) {\n continue;\n }\n startColumn = previousStartColumn;\n }\n let codeword = PDF417ScanningDecoder.detectCodeword(image, boundingBox.getMinX(), boundingBox.getMaxX(), leftToRight, startColumn, imageRow, minCodewordWidth, maxCodewordWidth);\n if (codeword != null) {\n detectionResultColumn.setCodeword(imageRow, codeword);\n previousStartColumn = startColumn;\n minCodewordWidth = Math.min(minCodewordWidth, codeword.getWidth());\n maxCodewordWidth = Math.max(maxCodewordWidth, codeword.getWidth());\n }\n }\n }\n return PDF417ScanningDecoder.createDecoderResult(detectionResult);\n }\n /**\n *\n * @param leftRowIndicatorColumn\n * @param rightRowIndicatorColumn\n *\n * @throws NotFoundException\n */\n static merge(leftRowIndicatorColumn, rightRowIndicatorColumn) {\n if (leftRowIndicatorColumn == null && rightRowIndicatorColumn == null) {\n return null;\n }\n let barcodeMetadata = PDF417ScanningDecoder.getBarcodeMetadata(leftRowIndicatorColumn, rightRowIndicatorColumn);\n if (barcodeMetadata == null) {\n return null;\n }\n let boundingBox = BoundingBox.merge(PDF417ScanningDecoder.adjustBoundingBox(leftRowIndicatorColumn), PDF417ScanningDecoder.adjustBoundingBox(rightRowIndicatorColumn));\n return new DetectionResult(barcodeMetadata, boundingBox);\n }\n /**\n *\n * @param rowIndicatorColumn\n *\n * @throws NotFoundException\n */\n static adjustBoundingBox(rowIndicatorColumn) {\n if (rowIndicatorColumn == null) {\n return null;\n }\n let rowHeights = rowIndicatorColumn.getRowHeights();\n if (rowHeights == null) {\n return null;\n }\n let maxRowHeight = PDF417ScanningDecoder.getMax(rowHeights);\n let missingStartRows = 0;\n for (let rowHeight /*int*/ of rowHeights) {\n missingStartRows += maxRowHeight - rowHeight;\n if (rowHeight > 0) {\n break;\n }\n }\n let codewords = rowIndicatorColumn.getCodewords();\n for (let row /*int*/ = 0; missingStartRows > 0 && codewords[row] == null; row++) {\n missingStartRows--;\n }\n let missingEndRows = 0;\n for (let row /*int*/ = rowHeights.length - 1; row >= 0; row--) {\n missingEndRows += maxRowHeight - rowHeights[row];\n if (rowHeights[row] > 0) {\n break;\n }\n }\n for (let row /*int*/ = codewords.length - 1; missingEndRows > 0 && codewords[row] == null; row--) {\n missingEndRows--;\n }\n return rowIndicatorColumn.getBoundingBox().addMissingRows(missingStartRows, missingEndRows, rowIndicatorColumn.isLeft());\n }\n static getMax(values) {\n let maxValue = -1;\n for (let value /*int*/ of values) {\n maxValue = Math.max(maxValue, value);\n }\n return maxValue;\n }\n static getBarcodeMetadata(leftRowIndicatorColumn, rightRowIndicatorColumn) {\n let leftBarcodeMetadata;\n if (leftRowIndicatorColumn == null ||\n (leftBarcodeMetadata = leftRowIndicatorColumn.getBarcodeMetadata()) == null) {\n return rightRowIndicatorColumn == null ? null : rightRowIndicatorColumn.getBarcodeMetadata();\n }\n let rightBarcodeMetadata;\n if (rightRowIndicatorColumn == null ||\n (rightBarcodeMetadata = rightRowIndicatorColumn.getBarcodeMetadata()) == null) {\n return leftBarcodeMetadata;\n }\n if (leftBarcodeMetadata.getColumnCount() !== rightBarcodeMetadata.getColumnCount() &&\n leftBarcodeMetadata.getErrorCorrectionLevel() !== rightBarcodeMetadata.getErrorCorrectionLevel() &&\n leftBarcodeMetadata.getRowCount() !== rightBarcodeMetadata.getRowCount()) {\n return null;\n }\n return leftBarcodeMetadata;\n }\n static getRowIndicatorColumn(image, boundingBox, startPoint, leftToRight, minCodewordWidth, maxCodewordWidth) {\n let rowIndicatorColumn = new DetectionResultRowIndicatorColumn(boundingBox, leftToRight);\n for (let i /*int*/ = 0; i < 2; i++) {\n let increment = i === 0 ? 1 : -1;\n let startColumn = Math.trunc(Math.trunc(startPoint.getX()));\n for (let imageRow /*int*/ = Math.trunc(Math.trunc(startPoint.getY())); imageRow <= boundingBox.getMaxY() &&\n imageRow >= boundingBox.getMinY(); imageRow += increment) {\n let codeword = PDF417ScanningDecoder.detectCodeword(image, 0, image.getWidth(), leftToRight, startColumn, imageRow, minCodewordWidth, maxCodewordWidth);\n if (codeword != null) {\n rowIndicatorColumn.setCodeword(imageRow, codeword);\n if (leftToRight) {\n startColumn = codeword.getStartX();\n }\n else {\n startColumn = codeword.getEndX();\n }\n }\n }\n }\n return rowIndicatorColumn;\n }\n /**\n *\n * @param detectionResult\n * @param BarcodeValue\n * @param param2\n * @param param3\n * @param barcodeMatrix\n *\n * @throws NotFoundException\n */\n static adjustCodewordCount(detectionResult, barcodeMatrix) {\n let barcodeMatrix01 = barcodeMatrix[0][1];\n let numberOfCodewords = barcodeMatrix01.getValue();\n let calculatedNumberOfCodewords = detectionResult.getBarcodeColumnCount() *\n detectionResult.getBarcodeRowCount() -\n PDF417ScanningDecoder.getNumberOfECCodeWords(detectionResult.getBarcodeECLevel());\n if (numberOfCodewords.length === 0) {\n if (calculatedNumberOfCodewords < 1 || calculatedNumberOfCodewords > PDF417Common.MAX_CODEWORDS_IN_BARCODE) {\n throw NotFoundException.getNotFoundInstance();\n }\n barcodeMatrix01.setValue(calculatedNumberOfCodewords);\n }\n else if (numberOfCodewords[0] !== calculatedNumberOfCodewords) {\n // The calculated one is more reliable as it is derived from the row indicator columns\n barcodeMatrix01.setValue(calculatedNumberOfCodewords);\n }\n }\n /**\n *\n * @param detectionResult\n *\n * @throws FormatException\n * @throws ChecksumException\n * @throws NotFoundException\n */\n static createDecoderResult(detectionResult) {\n let barcodeMatrix = PDF417ScanningDecoder.createBarcodeMatrix(detectionResult);\n PDF417ScanningDecoder.adjustCodewordCount(detectionResult, barcodeMatrix);\n let erasures /*Collection*/ = new Array();\n let codewords = new Int32Array(detectionResult.getBarcodeRowCount() * detectionResult.getBarcodeColumnCount());\n let ambiguousIndexValuesList = /*List*/ [];\n let ambiguousIndexesList = /*Collection*/ new Array();\n for (let row /*int*/ = 0; row < detectionResult.getBarcodeRowCount(); row++) {\n for (let column /*int*/ = 0; column < detectionResult.getBarcodeColumnCount(); column++) {\n let values = barcodeMatrix[row][column + 1].getValue();\n let codewordIndex = row * detectionResult.getBarcodeColumnCount() + column;\n if (values.length === 0) {\n erasures.push(codewordIndex);\n }\n else if (values.length === 1) {\n codewords[codewordIndex] = values[0];\n }\n else {\n ambiguousIndexesList.push(codewordIndex);\n ambiguousIndexValuesList.push(values);\n }\n }\n }\n let ambiguousIndexValues = new Array(ambiguousIndexValuesList.length);\n for (let i /*int*/ = 0; i < ambiguousIndexValues.length; i++) {\n ambiguousIndexValues[i] = ambiguousIndexValuesList[i];\n }\n return PDF417ScanningDecoder.createDecoderResultFromAmbiguousValues(detectionResult.getBarcodeECLevel(), codewords, PDF417Common.toIntArray(erasures), PDF417Common.toIntArray(ambiguousIndexesList), ambiguousIndexValues);\n }\n /**\n * This method deals with the fact, that the decoding process doesn't always yield a single most likely value. The\n * current error correction implementation doesn't deal with erasures very well, so it's better to provide a value\n * for these ambiguous codewords instead of treating it as an erasure. The problem is that we don't know which of\n * the ambiguous values to choose. We try decode using the first value, and if that fails, we use another of the\n * ambiguous values and try to decode again. This usually only happens on very hard to read and decode barcodes,\n * so decoding the normal barcodes is not affected by this.\n *\n * @param erasureArray contains the indexes of erasures\n * @param ambiguousIndexes array with the indexes that have more than one most likely value\n * @param ambiguousIndexValues two dimensional array that contains the ambiguous values. The first dimension must\n * be the same length as the ambiguousIndexes array\n *\n * @throws FormatException\n * @throws ChecksumException\n */\n static createDecoderResultFromAmbiguousValues(ecLevel, codewords, erasureArray, ambiguousIndexes, ambiguousIndexValues) {\n let ambiguousIndexCount = new Int32Array(ambiguousIndexes.length);\n let tries = 100;\n while (tries-- > 0) {\n for (let i /*int*/ = 0; i < ambiguousIndexCount.length; i++) {\n codewords[ambiguousIndexes[i]] = ambiguousIndexValues[i][ambiguousIndexCount[i]];\n }\n try {\n return PDF417ScanningDecoder.decodeCodewords(codewords, ecLevel, erasureArray);\n }\n catch (err) {\n let ignored = err instanceof ChecksumException;\n if (!ignored) {\n throw err;\n }\n }\n if (ambiguousIndexCount.length === 0) {\n throw ChecksumException.getChecksumInstance();\n }\n for (let i /*int*/ = 0; i < ambiguousIndexCount.length; i++) {\n if (ambiguousIndexCount[i] < ambiguousIndexValues[i].length - 1) {\n ambiguousIndexCount[i]++;\n break;\n }\n else {\n ambiguousIndexCount[i] = 0;\n if (i === ambiguousIndexCount.length - 1) {\n throw ChecksumException.getChecksumInstance();\n }\n }\n }\n }\n throw ChecksumException.getChecksumInstance();\n }\n static createBarcodeMatrix(detectionResult) {\n // let barcodeMatrix: BarcodeValue[][] =\n // new BarcodeValue[detectionResult.getBarcodeRowCount()][detectionResult.getBarcodeColumnCount() + 2];\n let barcodeMatrix = Array.from({ length: detectionResult.getBarcodeRowCount() }, () => new Array(detectionResult.getBarcodeColumnCount() + 2));\n for (let row /*int*/ = 0; row < barcodeMatrix.length; row++) {\n for (let column /*int*/ = 0; column < barcodeMatrix[row].length; column++) {\n barcodeMatrix[row][column] = new BarcodeValue();\n }\n }\n let column = 0;\n for (let detectionResultColumn /*DetectionResultColumn*/ of detectionResult.getDetectionResultColumns()) {\n if (detectionResultColumn != null) {\n for (let codeword /*Codeword*/ of detectionResultColumn.getCodewords()) {\n if (codeword != null) {\n let rowNumber = codeword.getRowNumber();\n if (rowNumber >= 0) {\n if (rowNumber >= barcodeMatrix.length) {\n // We have more rows than the barcode metadata allows for, ignore them.\n continue;\n }\n barcodeMatrix[rowNumber][column].setValue(codeword.getValue());\n }\n }\n }\n }\n column++;\n }\n return barcodeMatrix;\n }\n static isValidBarcodeColumn(detectionResult, barcodeColumn) {\n return barcodeColumn >= 0 && barcodeColumn <= detectionResult.getBarcodeColumnCount() + 1;\n }\n static getStartColumn(detectionResult, barcodeColumn, imageRow, leftToRight) {\n let offset = leftToRight ? 1 : -1;\n let codeword = null;\n if (PDF417ScanningDecoder.isValidBarcodeColumn(detectionResult, barcodeColumn - offset)) {\n codeword = detectionResult.getDetectionResultColumn(barcodeColumn - offset).getCodeword(imageRow);\n }\n if (codeword != null) {\n return leftToRight ? codeword.getEndX() : codeword.getStartX();\n }\n codeword = detectionResult.getDetectionResultColumn(barcodeColumn).getCodewordNearby(imageRow);\n if (codeword != null) {\n return leftToRight ? codeword.getStartX() : codeword.getEndX();\n }\n if (PDF417ScanningDecoder.isValidBarcodeColumn(detectionResult, barcodeColumn - offset)) {\n codeword = detectionResult.getDetectionResultColumn(barcodeColumn - offset).getCodewordNearby(imageRow);\n }\n if (codeword != null) {\n return leftToRight ? codeword.getEndX() : codeword.getStartX();\n }\n let skippedColumns = 0;\n while (PDF417ScanningDecoder.isValidBarcodeColumn(detectionResult, barcodeColumn - offset)) {\n barcodeColumn -= offset;\n for (let previousRowCodeword /*Codeword*/ of detectionResult.getDetectionResultColumn(barcodeColumn).getCodewords()) {\n if (previousRowCodeword != null) {\n return (leftToRight ? previousRowCodeword.getEndX() : previousRowCodeword.getStartX()) +\n offset *\n skippedColumns *\n (previousRowCodeword.getEndX() - previousRowCodeword.getStartX());\n }\n }\n skippedColumns++;\n }\n return leftToRight ? detectionResult.getBoundingBox().getMinX() : detectionResult.getBoundingBox().getMaxX();\n }\n static detectCodeword(image, minColumn, maxColumn, leftToRight, startColumn, imageRow, minCodewordWidth, maxCodewordWidth) {\n startColumn = PDF417ScanningDecoder.adjustCodewordStartColumn(image, minColumn, maxColumn, leftToRight, startColumn, imageRow);\n // we usually know fairly exact now how long a codeword is. We should provide minimum and maximum expected length\n // and try to adjust the read pixels, e.g. remove single pixel errors or try to cut off exceeding pixels.\n // min and maxCodewordWidth should not be used as they are calculated for the whole barcode an can be inaccurate\n // for the current position\n let moduleBitCount = PDF417ScanningDecoder.getModuleBitCount(image, minColumn, maxColumn, leftToRight, startColumn, imageRow);\n if (moduleBitCount == null) {\n return null;\n }\n let endColumn;\n let codewordBitCount = MathUtils.sum(moduleBitCount);\n if (leftToRight) {\n endColumn = startColumn + codewordBitCount;\n }\n else {\n for (let i /*int*/ = 0; i < moduleBitCount.length / 2; i++) {\n let tmpCount = moduleBitCount[i];\n moduleBitCount[i] = moduleBitCount[moduleBitCount.length - 1 - i];\n moduleBitCount[moduleBitCount.length - 1 - i] = tmpCount;\n }\n endColumn = startColumn;\n startColumn = endColumn - codewordBitCount;\n }\n // TODO implement check for width and correction of black and white bars\n // use start (and maybe stop pattern) to determine if black bars are wider than white bars. If so, adjust.\n // should probably done only for codewords with a lot more than 17 bits.\n // The following fixes 10-1.png, which has wide black bars and small white bars\n // for (let i /*int*/ = 0; i < moduleBitCount.length; i++) {\n // if (i % 2 === 0) {\n // moduleBitCount[i]--;\n // } else {\n // moduleBitCount[i]++;\n // }\n // }\n // We could also use the width of surrounding codewords for more accurate results, but this seems\n // sufficient for now\n if (!PDF417ScanningDecoder.checkCodewordSkew(codewordBitCount, minCodewordWidth, maxCodewordWidth)) {\n // We could try to use the startX and endX position of the codeword in the same column in the previous row,\n // create the bit count from it and normalize it to 8. This would help with single pixel errors.\n return null;\n }\n let decodedValue = PDF417CodewordDecoder.getDecodedValue(moduleBitCount);\n let codeword = PDF417Common.getCodeword(decodedValue);\n if (codeword === -1) {\n return null;\n }\n return new Codeword(startColumn, endColumn, PDF417ScanningDecoder.getCodewordBucketNumber(decodedValue), codeword);\n }\n static getModuleBitCount(image, minColumn, maxColumn, leftToRight, startColumn, imageRow) {\n let imageColumn = startColumn;\n let moduleBitCount = new Int32Array(8);\n let moduleNumber = 0;\n let increment = leftToRight ? 1 : -1;\n let previousPixelValue = leftToRight;\n while ((leftToRight ? imageColumn < maxColumn : imageColumn >= minColumn) &&\n moduleNumber < moduleBitCount.length) {\n if (image.get(imageColumn, imageRow) === previousPixelValue) {\n moduleBitCount[moduleNumber]++;\n imageColumn += increment;\n }\n else {\n moduleNumber++;\n previousPixelValue = !previousPixelValue;\n }\n }\n if (moduleNumber === moduleBitCount.length ||\n ((imageColumn === (leftToRight ? maxColumn : minColumn)) &&\n moduleNumber === moduleBitCount.length - 1)) {\n return moduleBitCount;\n }\n return null;\n }\n static getNumberOfECCodeWords(barcodeECLevel) {\n return 2 << barcodeECLevel;\n }\n static adjustCodewordStartColumn(image, minColumn, maxColumn, leftToRight, codewordStartColumn, imageRow) {\n let correctedStartColumn = codewordStartColumn;\n let increment = leftToRight ? -1 : 1;\n // there should be no black pixels before the start column. If there are, then we need to start earlier.\n for (let i /*int*/ = 0; i < 2; i++) {\n while ((leftToRight ? correctedStartColumn >= minColumn : correctedStartColumn < maxColumn) &&\n leftToRight === image.get(correctedStartColumn, imageRow)) {\n if (Math.abs(codewordStartColumn - correctedStartColumn) > PDF417ScanningDecoder.CODEWORD_SKEW_SIZE) {\n return codewordStartColumn;\n }\n correctedStartColumn += increment;\n }\n increment = -increment;\n leftToRight = !leftToRight;\n }\n return correctedStartColumn;\n }\n static checkCodewordSkew(codewordSize, minCodewordWidth, maxCodewordWidth) {\n return minCodewordWidth - PDF417ScanningDecoder.CODEWORD_SKEW_SIZE <= codewordSize &&\n codewordSize <= maxCodewordWidth + PDF417ScanningDecoder.CODEWORD_SKEW_SIZE;\n }\n /**\n * @throws FormatException,\n * @throws ChecksumException\n */\n static decodeCodewords(codewords, ecLevel, erasures) {\n if (codewords.length === 0) {\n throw FormatException.getFormatInstance();\n }\n let numECCodewords = 1 << (ecLevel + 1);\n let correctedErrorsCount = PDF417ScanningDecoder.correctErrors(codewords, erasures, numECCodewords);\n PDF417ScanningDecoder.verifyCodewordCount(codewords, numECCodewords);\n // Decode the codewords\n let decoderResult = DecodedBitStreamParser$2.decode(codewords, '' + ecLevel);\n decoderResult.setErrorsCorrected(correctedErrorsCount);\n decoderResult.setErasures(erasures.length);\n return decoderResult;\n }\n /**\n *

Given data and error-correction codewords received, possibly corrupted by errors, attempts to\n * correct the errors in-place.

\n *\n * @param codewords data and error correction codewords\n * @param erasures positions of any known erasures\n * @param numECCodewords number of error correction codewords that are available in codewords\n * @throws ChecksumException if error correction fails\n */\n static correctErrors(codewords, erasures, numECCodewords) {\n if (erasures != null &&\n erasures.length > numECCodewords / 2 + PDF417ScanningDecoder.MAX_ERRORS ||\n numECCodewords < 0 ||\n numECCodewords > PDF417ScanningDecoder.MAX_EC_CODEWORDS) {\n // Too many errors or EC Codewords is corrupted\n throw ChecksumException.getChecksumInstance();\n }\n return PDF417ScanningDecoder.errorCorrection.decode(codewords, numECCodewords, erasures);\n }\n /**\n * Verify that all is OK with the codeword array.\n * @throws FormatException\n */\n static verifyCodewordCount(codewords, numECCodewords) {\n if (codewords.length < 4) {\n // Codeword array size should be at least 4 allowing for\n // Count CW, At least one Data CW, Error Correction CW, Error Correction CW\n throw FormatException.getFormatInstance();\n }\n // The first codeword, the Symbol Length Descriptor, shall always encode the total number of data\n // codewords in the symbol, including the Symbol Length Descriptor itself, data codewords and pad\n // codewords, but excluding the number of error correction codewords.\n let numberOfCodewords = codewords[0];\n if (numberOfCodewords > codewords.length) {\n throw FormatException.getFormatInstance();\n }\n if (numberOfCodewords === 0) {\n // Reset to the length of the array - 8 (Allow for at least level 3 Error Correction (8 Error Codewords)\n if (numECCodewords < codewords.length) {\n codewords[0] = codewords.length - numECCodewords;\n }\n else {\n throw FormatException.getFormatInstance();\n }\n }\n }\n static getBitCountForCodeword(codeword) {\n let result = new Int32Array(8);\n let previousValue = 0;\n let i = result.length - 1;\n while (true) {\n if ((codeword & 0x1) !== previousValue) {\n previousValue = codeword & 0x1;\n i--;\n if (i < 0) {\n break;\n }\n }\n result[i]++;\n codeword >>= 1;\n }\n return result;\n }\n static getCodewordBucketNumber(codeword) {\n if (codeword instanceof Int32Array) {\n return this.getCodewordBucketNumber_Int32Array(codeword);\n }\n return this.getCodewordBucketNumber_number(codeword);\n }\n static getCodewordBucketNumber_number(codeword) {\n return PDF417ScanningDecoder.getCodewordBucketNumber(PDF417ScanningDecoder.getBitCountForCodeword(codeword));\n }\n static getCodewordBucketNumber_Int32Array(moduleBitCount) {\n return (moduleBitCount[0] - moduleBitCount[2] + moduleBitCount[4] - moduleBitCount[6] + 9) % 9;\n }\n static toString(barcodeMatrix) {\n let formatter = new Formatter();\n // try (let formatter = new Formatter()) {\n for (let row /*int*/ = 0; row < barcodeMatrix.length; row++) {\n formatter.format('Row %2d: ', row);\n for (let column /*int*/ = 0; column < barcodeMatrix[row].length; column++) {\n let barcodeValue = barcodeMatrix[row][column];\n if (barcodeValue.getValue().length === 0) {\n formatter.format(' ', null);\n }\n else {\n formatter.format('%4d(%2d)', barcodeValue.getValue()[0], barcodeValue.getConfidence(barcodeValue.getValue()[0]));\n }\n }\n formatter.format('%n');\n }\n return formatter.toString();\n // }\n }\n }\n /*final*/ PDF417ScanningDecoder.CODEWORD_SKEW_SIZE = 2;\n /*final*/ PDF417ScanningDecoder.MAX_ERRORS = 3;\n /*final*/ PDF417ScanningDecoder.MAX_EC_CODEWORDS = 512;\n /*final*/ PDF417ScanningDecoder.errorCorrection = new ErrorCorrection();\n\n /*\n * Copyright 2009 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n // import java.util.ArrayList;\n // import java.util.List;\n // import java.util.Map;\n /**\n * This implementation can detect and decode PDF417 codes in an image.\n *\n * @author Guenther Grau\n */\n /*public final*/ class PDF417Reader {\n // private static /*final Result[]*/ EMPTY_RESULT_ARRAY: Result[] = new Result([0]);\n /**\n * Locates and decodes a PDF417 code in an image.\n *\n * @return a String representing the content encoded by the PDF417 code\n * @throws NotFoundException if a PDF417 code cannot be found,\n * @throws FormatException if a PDF417 cannot be decoded\n * @throws ChecksumException\n */\n // @Override\n decode(image, hints = null) {\n let result = PDF417Reader.decode(image, hints, false);\n if (result == null || result.length === 0 || result[0] == null) {\n throw NotFoundException.getNotFoundInstance();\n }\n return result[0];\n }\n /**\n *\n * @param BinaryBitmap\n * @param image\n * @throws NotFoundException\n */\n // @Override\n decodeMultiple(image, hints = null) {\n try {\n return PDF417Reader.decode(image, hints, true);\n }\n catch (ignored) {\n if (ignored instanceof FormatException || ignored instanceof ChecksumException) {\n throw NotFoundException.getNotFoundInstance();\n }\n throw ignored;\n }\n }\n /**\n *\n * @param image\n * @param hints\n * @param multiple\n *\n * @throws NotFoundException\n * @throws FormatException\u00DF\n * @throws ChecksumException\n */\n static decode(image, hints, multiple) {\n const results = new Array();\n const detectorResult = Detector$3.detectMultiple(image, hints, multiple);\n for (const points of detectorResult.getPoints()) {\n const decoderResult = PDF417ScanningDecoder.decode(detectorResult.getBits(), points[4], points[5], points[6], points[7], PDF417Reader.getMinCodewordWidth(points), PDF417Reader.getMaxCodewordWidth(points));\n const result = new Result(decoderResult.getText(), decoderResult.getRawBytes(), undefined, points, BarcodeFormat$1.PDF_417);\n result.putMetadata(ResultMetadataType$1.ERROR_CORRECTION_LEVEL, decoderResult.getECLevel());\n const pdf417ResultMetadata = decoderResult.getOther();\n if (pdf417ResultMetadata != null) {\n result.putMetadata(ResultMetadataType$1.PDF417_EXTRA_METADATA, pdf417ResultMetadata);\n }\n results.push(result);\n }\n return results.map(x => x);\n }\n static getMaxWidth(p1, p2) {\n if (p1 == null || p2 == null) {\n return 0;\n }\n return Math.trunc(Math.abs(p1.getX() - p2.getX()));\n }\n static getMinWidth(p1, p2) {\n if (p1 == null || p2 == null) {\n return Integer.MAX_VALUE;\n }\n return Math.trunc(Math.abs(p1.getX() - p2.getX()));\n }\n static getMaxCodewordWidth(p) {\n return Math.floor(Math.max(Math.max(PDF417Reader.getMaxWidth(p[0], p[4]), PDF417Reader.getMaxWidth(p[6], p[2]) * PDF417Common.MODULES_IN_CODEWORD /\n PDF417Common.MODULES_IN_STOP_PATTERN), Math.max(PDF417Reader.getMaxWidth(p[1], p[5]), PDF417Reader.getMaxWidth(p[7], p[3]) * PDF417Common.MODULES_IN_CODEWORD /\n PDF417Common.MODULES_IN_STOP_PATTERN)));\n }\n static getMinCodewordWidth(p) {\n return Math.floor(Math.min(Math.min(PDF417Reader.getMinWidth(p[0], p[4]), PDF417Reader.getMinWidth(p[6], p[2]) * PDF417Common.MODULES_IN_CODEWORD /\n PDF417Common.MODULES_IN_STOP_PATTERN), Math.min(PDF417Reader.getMinWidth(p[1], p[5]), PDF417Reader.getMinWidth(p[7], p[3]) * PDF417Common.MODULES_IN_CODEWORD /\n PDF417Common.MODULES_IN_STOP_PATTERN)));\n }\n // @Override\n reset() {\n // nothing needs to be reset\n }\n }\n\n /**\n * Custom Error class of type Exception.\n */\n class ReaderException extends Exception {\n }\n ReaderException.kind = 'ReaderException';\n\n /*\n * Copyright 2009 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n /*namespace com.google.zxing {*/\n /**\n * MultiFormatReader is a convenience class and the main entry point into the library for most uses.\n * By default it attempts to decode all barcode formats that the library supports. Optionally, you\n * can provide a hints object to request different behavior, for example only decoding QR codes.\n *\n * @author Sean Owen\n * @author dswitkin@google.com (Daniel Switkin)\n */\n class MultiFormatReader {\n /**\n * Creates an instance of this class\n * \n * @param {Boolean} verbose if 'true' logs will be dumped to console, otherwise hidden.\n * @param hints The hints to use, clearing the previous state.\n */\n constructor(verbose, hints) {\n this.verbose = (verbose === true);\n if (hints) {\n this.setHints(hints);\n }\n }\n /**\n * This version of decode honors the intent of Reader.decode(BinaryBitmap) in that it\n * passes null as a hint to the decoders. However, that makes it inefficient to call repeatedly.\n * Use setHints() followed by decodeWithState() for continuous scan applications.\n *\n * @param image The pixel data to decode\n * @return The contents of the image\n *\n * @throws NotFoundException Any errors which occurred\n */\n /*@Override*/\n // public decode(image: BinaryBitmap): Result {\n // setHints(null)\n // return decodeInternal(image)\n // }\n /**\n * Decode an image using the hints provided. Does not honor existing state.\n *\n * @param image The pixel data to decode\n * @param hints The hints to use, clearing the previous state.\n * @return The contents of the image\n *\n * @throws NotFoundException Any errors which occurred\n */\n /*@Override*/\n decode(image, hints) {\n if (hints) {\n this.setHints(hints);\n }\n return this.decodeInternal(image);\n }\n /**\n * Decode an image using the state set up by calling setHints() previously. Continuous scan\n * clients will get a large speed increase by using this instead of decode().\n *\n * @param image The pixel data to decode\n * @return The contents of the image\n *\n * @throws NotFoundException Any errors which occurred\n */\n decodeWithState(image) {\n // Make sure to set up the default state so we don't crash\n if (this.readers === null || this.readers === undefined) {\n this.setHints(null);\n }\n return this.decodeInternal(image);\n }\n /**\n * This method adds state to the MultiFormatReader. By setting the hints once, subsequent calls\n * to decodeWithState(image) can reuse the same set of readers without reallocating memory. This\n * is important for performance in continuous scan clients.\n *\n * @param hints The set of hints to use for subsequent calls to decode(image)\n */\n setHints(hints) {\n this.hints = hints;\n const tryHarder = !isNullOrUndefined(hints)\n && hints.get(DecodeHintType$1.TRY_HARDER) === true;\n const formats = isNullOrUndefined(hints) ? null : hints.get(DecodeHintType$1.POSSIBLE_FORMATS);\n const readers = new Array();\n if (!isNullOrUndefined(formats)) {\n const addOneDReader = formats.some(f => {\n return (\n f === BarcodeFormat$1.UPC_A ||\n f === BarcodeFormat$1.UPC_E ||\n f === BarcodeFormat$1.EAN_13 ||\n f === BarcodeFormat$1.EAN_8 ||\n f === BarcodeFormat$1.CODABAR ||\n f === BarcodeFormat$1.CODE_39 ||\n f === BarcodeFormat$1.CODE_93 ||\n f === BarcodeFormat$1.CODE_128 ||\n f === BarcodeFormat$1.ITF ||\n f === BarcodeFormat$1.RSS_14 ||\n f === BarcodeFormat$1.RSS_EXPANDED);\n });\n // Put 1D readers upfront in \"normal\" mode\n if (addOneDReader && !tryHarder) {\n readers.push(new MultiFormatOneDReader(hints, this.verbose));\n }\n if (formats.includes(BarcodeFormat$1.QR_CODE)) {\n readers.push(new QRCodeReader());\n }\n if (formats.includes(BarcodeFormat$1.DATA_MATRIX)) {\n readers.push(new DataMatrixReader());\n }\n if (formats.includes(BarcodeFormat$1.AZTEC)) {\n readers.push(new AztecReader());\n }\n if (formats.includes(BarcodeFormat$1.PDF_417)) {\n readers.push(new PDF417Reader());\n }\n // if (formats.includes(BarcodeFormat.MAXICODE)) {\n // readers.push(new MaxiCodeReader())\n // }\n // At end in \"try harder\" mode\n if (addOneDReader && tryHarder) {\n readers.push(new MultiFormatOneDReader(hints, this.verbose));\n }\n }\n if (readers.length === 0) {\n if (!tryHarder) {\n readers.push(new MultiFormatOneDReader(hints, this.verbose));\n }\n readers.push(new QRCodeReader());\n readers.push(new DataMatrixReader());\n readers.push(new AztecReader());\n readers.push(new PDF417Reader());\n // readers.push(new MaxiCodeReader())\n if (tryHarder) {\n readers.push(new MultiFormatOneDReader(hints, this.verbose));\n }\n }\n this.readers = readers; // .toArray(new Reader[readers.size()])\n }\n /*@Override*/\n reset() {\n if (this.readers !== null) {\n for (const reader of this.readers) {\n reader.reset();\n }\n }\n }\n /**\n * @throws NotFoundException\n */\n decodeInternal(image) {\n if (this.readers === null) {\n throw new ReaderException('No readers where selected, nothing can be read.');\n }\n for (const reader of this.readers) {\n // Trying to decode with ${reader} reader.\n try {\n return reader.decode(image, this.hints);\n }\n catch (ex) {\n if (ex instanceof ReaderException) {\n continue;\n }\n // Bad Exception.\n }\n }\n throw new NotFoundException('No MultiFormat Readers were able to detect the code.');\n }\n }\n\n class BrowserMultiFormatReader extends BrowserCodeReader {\n constructor(hints = null, timeBetweenScansMillis = 500) {\n const reader = new MultiFormatReader();\n reader.setHints(hints);\n super(reader, timeBetweenScansMillis);\n }\n /**\n * Overwrite decodeBitmap to call decodeWithState, which will pay\n * attention to the hints set in the constructor function\n */\n decodeBitmap(binaryBitmap) {\n return this.reader.decodeWithState(binaryBitmap);\n }\n }\n\n /**\n * @deprecated Moving to @zxing/browser\n *\n * QR Code reader to use from browser.\n */\n class BrowserPDF417Reader extends BrowserCodeReader {\n /**\n * Creates an instance of BrowserPDF417Reader.\n * @param {number} [timeBetweenScansMillis=500] the time delay between subsequent decode tries\n */\n constructor(timeBetweenScansMillis = 500) {\n super(new PDF417Reader(), timeBetweenScansMillis);\n }\n }\n\n /**\n * @deprecated Moving to @zxing/browser\n *\n * QR Code reader to use from browser.\n */\n class BrowserQRCodeReader extends BrowserCodeReader {\n /**\n * Creates an instance of BrowserQRCodeReader.\n * @param {number} [timeBetweenScansMillis=500] the time delay between subsequent decode tries\n */\n constructor(timeBetweenScansMillis = 500) {\n super(new QRCodeReader(), timeBetweenScansMillis);\n }\n }\n\n /*\n * Copyright 2009 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n /*namespace com.google.zxing {*/\n /**\n * These are a set of hints that you may pass to Writers to specify their behavior.\n *\n * @author dswitkin@google.com (Daniel Switkin)\n */\n var EncodeHintType;\n (function (EncodeHintType) {\n /**\n * Specifies what degree of error correction to use, for example in QR Codes.\n * Type depends on the encoder. For example for QR codes it's type\n * {@link com.google.zxing.qrcode.decoder.ErrorCorrectionLevel ErrorCorrectionLevel}.\n * For Aztec it is of type {@link Integer}, representing the minimal percentage of error correction words.\n * For PDF417 it is of type {@link Integer}, valid values being 0 to 8.\n * In all cases, it can also be a {@link String} representation of the desired value as well.\n * Note: an Aztec symbol should have a minimum of 25% EC words.\n */\n EncodeHintType[EncodeHintType[\"ERROR_CORRECTION\"] = 0] = \"ERROR_CORRECTION\";\n /**\n * Specifies what character encoding to use where applicable (type {@link String})\n */\n EncodeHintType[EncodeHintType[\"CHARACTER_SET\"] = 1] = \"CHARACTER_SET\";\n /**\n * Specifies the matrix shape for Data Matrix (type {@link com.google.zxing.datamatrix.encoder.SymbolShapeHint})\n */\n EncodeHintType[EncodeHintType[\"DATA_MATRIX_SHAPE\"] = 2] = \"DATA_MATRIX_SHAPE\";\n /**\n * Specifies a minimum barcode size (type {@link Dimension}). Only applicable to Data Matrix now.\n *\n * @deprecated use width/height params in\n * {@link com.google.zxing.datamatrix.DataMatrixWriter#encode(String, BarcodeFormat, int, int)}\n */\n /*@Deprecated*/\n EncodeHintType[EncodeHintType[\"MIN_SIZE\"] = 3] = \"MIN_SIZE\";\n /**\n * Specifies a maximum barcode size (type {@link Dimension}). Only applicable to Data Matrix now.\n *\n * @deprecated without replacement\n */\n /*@Deprecated*/\n EncodeHintType[EncodeHintType[\"MAX_SIZE\"] = 4] = \"MAX_SIZE\";\n /**\n * Specifies margin, in pixels, to use when generating the barcode. The meaning can vary\n * by format; for example it controls margin before and after the barcode horizontally for\n * most 1D formats. (Type {@link Integer}, or {@link String} representation of the integer value).\n */\n EncodeHintType[EncodeHintType[\"MARGIN\"] = 5] = \"MARGIN\";\n /**\n * Specifies whether to use compact mode for PDF417 (type {@link Boolean}, or \"true\" or \"false\"\n * {@link String} value).\n */\n EncodeHintType[EncodeHintType[\"PDF417_COMPACT\"] = 6] = \"PDF417_COMPACT\";\n /**\n * Specifies what compaction mode to use for PDF417 (type\n * {@link com.google.zxing.pdf417.encoder.Compaction Compaction} or {@link String} value of one of its\n * enum values).\n */\n EncodeHintType[EncodeHintType[\"PDF417_COMPACTION\"] = 7] = \"PDF417_COMPACTION\";\n /**\n * Specifies the minimum and maximum number of rows and columns for PDF417 (type\n * {@link com.google.zxing.pdf417.encoder.Dimensions Dimensions}).\n */\n EncodeHintType[EncodeHintType[\"PDF417_DIMENSIONS\"] = 8] = \"PDF417_DIMENSIONS\";\n /**\n * Specifies the required number of layers for an Aztec code.\n * A negative number (-1, -2, -3, -4) specifies a compact Aztec code.\n * 0 indicates to use the minimum number of layers (the default).\n * A positive number (1, 2, .. 32) specifies a normal (non-compact) Aztec code.\n * (Type {@link Integer}, or {@link String} representation of the integer value).\n */\n EncodeHintType[EncodeHintType[\"AZTEC_LAYERS\"] = 9] = \"AZTEC_LAYERS\";\n /**\n * Specifies the exact version of QR code to be encoded.\n * (Type {@link Integer}, or {@link String} representation of the integer value).\n */\n EncodeHintType[EncodeHintType[\"QR_VERSION\"] = 10] = \"QR_VERSION\";\n })(EncodeHintType || (EncodeHintType = {}));\n var EncodeHintType$1 = EncodeHintType;\n\n /**\n *

Implements Reed-Solomon encoding, as the name implies.

\n *\n * @author Sean Owen\n * @author William Rucklidge\n */\n class ReedSolomonEncoder {\n /**\n * A reed solomon error-correcting encoding constructor is created by\n * passing as Galois Field with of size equal to the number of code\n * words (symbols) in the alphabet (the number of values in each\n * element of arrays that are encoded/decoded).\n * @param field A galois field with a number of elements equal to the size\n * of the alphabet of symbols to encode.\n */\n constructor(field) {\n this.field = field;\n this.cachedGenerators = [];\n this.cachedGenerators.push(new GenericGFPoly(field, Int32Array.from([1])));\n }\n buildGenerator(degree /*int*/) {\n const cachedGenerators = this.cachedGenerators;\n if (degree >= cachedGenerators.length) {\n let lastGenerator = cachedGenerators[cachedGenerators.length - 1];\n const field = this.field;\n for (let d = cachedGenerators.length; d <= degree; d++) {\n const nextGenerator = lastGenerator.multiply(new GenericGFPoly(field, Int32Array.from([1, field.exp(d - 1 + field.getGeneratorBase())])));\n cachedGenerators.push(nextGenerator);\n lastGenerator = nextGenerator;\n }\n }\n return cachedGenerators[degree];\n }\n /**\n *

Encode a sequence of code words (symbols) using Reed-Solomon to allow decoders\n * to detect and correct errors that may have been introduced when the resulting\n * data is stored or transmitted.

\n *\n * @param toEncode array used for both and output. Caller initializes the array with\n * the code words (symbols) to be encoded followed by empty elements allocated to make\n * space for error-correction code words in the encoded output. The array contains\n * the encdoded output when encode returns. Code words are encoded as numbers from\n * 0 to n-1, where n is the number of possible code words (symbols), as determined\n * by the size of the Galois Field passed in the constructor of this object.\n * @param ecBytes the number of elements reserved in the array (first parameter)\n * to store error-correction code words. Thus, the number of code words (symbols)\n * to encode in the first parameter is thus toEncode.length - ecBytes.\n * Note, the use of \"bytes\" in the name of this parameter is misleading, as there may\n * be more or fewer than 256 symbols being encoded, as determined by the number of\n * elements in the Galois Field passed as a constructor to this object.\n * @throws IllegalArgumentException thrown in response to validation errros.\n */\n encode(toEncode, ecBytes /*int*/) {\n if (ecBytes === 0) {\n throw new IllegalArgumentException('No error correction bytes');\n }\n const dataBytes = toEncode.length - ecBytes;\n if (dataBytes <= 0) {\n throw new IllegalArgumentException('No data bytes provided');\n }\n const generator = this.buildGenerator(ecBytes);\n const infoCoefficients = new Int32Array(dataBytes);\n System.arraycopy(toEncode, 0, infoCoefficients, 0, dataBytes);\n let info = new GenericGFPoly(this.field, infoCoefficients);\n info = info.multiplyByMonomial(ecBytes, 1);\n const remainder = info.divide(generator)[1];\n const coefficients = remainder.getCoefficients();\n const numZeroCoefficients = ecBytes - coefficients.length;\n for (let i = 0; i < numZeroCoefficients; i++) {\n toEncode[dataBytes + i] = 0;\n }\n System.arraycopy(coefficients, 0, toEncode, dataBytes + numZeroCoefficients, coefficients.length);\n }\n }\n\n /**\n * @author Satoru Takabayashi\n * @author Daniel Switkin\n * @author Sean Owen\n */\n class MaskUtil {\n constructor() {\n // do nothing\n }\n /**\n * Apply mask penalty rule 1 and return the penalty. Find repetitive cells with the same color and\n * give penalty to them. Example: 00000 or 11111.\n */\n static applyMaskPenaltyRule1(matrix) {\n return MaskUtil.applyMaskPenaltyRule1Internal(matrix, true) + MaskUtil.applyMaskPenaltyRule1Internal(matrix, false);\n }\n /**\n * Apply mask penalty rule 2 and return the penalty. Find 2x2 blocks with the same color and give\n * penalty to them. This is actually equivalent to the spec's rule, which is to find MxN blocks and give a\n * penalty proportional to (M-1)x(N-1), because this is the number of 2x2 blocks inside such a block.\n */\n static applyMaskPenaltyRule2(matrix) {\n let penalty = 0;\n const array = matrix.getArray();\n const width = matrix.getWidth();\n const height = matrix.getHeight();\n for (let y = 0; y < height - 1; y++) {\n const arrayY = array[y];\n for (let x = 0; x < width - 1; x++) {\n const value = arrayY[x];\n if (value === arrayY[x + 1] && value === array[y + 1][x] && value === array[y + 1][x + 1]) {\n penalty++;\n }\n }\n }\n return MaskUtil.N2 * penalty;\n }\n /**\n * Apply mask penalty rule 3 and return the penalty. Find consecutive runs of 1:1:3:1:1:4\n * starting with black, or 4:1:1:3:1:1 starting with white, and give penalty to them. If we\n * find patterns like 000010111010000, we give penalty once.\n */\n static applyMaskPenaltyRule3(matrix) {\n let numPenalties = 0;\n const array = matrix.getArray();\n const width = matrix.getWidth();\n const height = matrix.getHeight();\n for (let y = 0; y < height; y++) {\n for (let x = 0; x < width; x++) {\n const arrayY = array[y]; // We can at least optimize this access\n if (x + 6 < width &&\n arrayY[x] === 1 &&\n arrayY[x + 1] === 0 &&\n arrayY[x + 2] === 1 &&\n arrayY[x + 3] === 1 &&\n arrayY[x + 4] === 1 &&\n arrayY[x + 5] === 0 &&\n arrayY[x + 6] === 1 &&\n (MaskUtil.isWhiteHorizontal(arrayY, x - 4, x) || MaskUtil.isWhiteHorizontal(arrayY, x + 7, x + 11))) {\n numPenalties++;\n }\n if (y + 6 < height &&\n array[y][x] === 1 &&\n array[y + 1][x] === 0 &&\n array[y + 2][x] === 1 &&\n array[y + 3][x] === 1 &&\n array[y + 4][x] === 1 &&\n array[y + 5][x] === 0 &&\n array[y + 6][x] === 1 &&\n (MaskUtil.isWhiteVertical(array, x, y - 4, y) || MaskUtil.isWhiteVertical(array, x, y + 7, y + 11))) {\n numPenalties++;\n }\n }\n }\n return numPenalties * MaskUtil.N3;\n }\n static isWhiteHorizontal(rowArray, from /*int*/, to /*int*/) {\n from = Math.max(from, 0);\n to = Math.min(to, rowArray.length);\n for (let i = from; i < to; i++) {\n if (rowArray[i] === 1) {\n return false;\n }\n }\n return true;\n }\n static isWhiteVertical(array, col /*int*/, from /*int*/, to /*int*/) {\n from = Math.max(from, 0);\n to = Math.min(to, array.length);\n for (let i = from; i < to; i++) {\n if (array[i][col] === 1) {\n return false;\n }\n }\n return true;\n }\n /**\n * Apply mask penalty rule 4 and return the penalty. Calculate the ratio of dark cells and give\n * penalty if the ratio is far from 50%. It gives 10 penalty for 5% distance.\n */\n static applyMaskPenaltyRule4(matrix) {\n let numDarkCells = 0;\n const array = matrix.getArray();\n const width = matrix.getWidth();\n const height = matrix.getHeight();\n for (let y = 0; y < height; y++) {\n const arrayY = array[y];\n for (let x = 0; x < width; x++) {\n if (arrayY[x] === 1) {\n numDarkCells++;\n }\n }\n }\n const numTotalCells = matrix.getHeight() * matrix.getWidth();\n const fivePercentVariances = Math.floor(Math.abs(numDarkCells * 2 - numTotalCells) * 10 / numTotalCells);\n return fivePercentVariances * MaskUtil.N4;\n }\n /**\n * Return the mask bit for \"getMaskPattern\" at \"x\" and \"y\". See 8.8 of JISX0510:2004 for mask\n * pattern conditions.\n */\n static getDataMaskBit(maskPattern /*int*/, x /*int*/, y /*int*/) {\n let intermediate; /*int*/\n let temp; /*int*/\n switch (maskPattern) {\n case 0:\n intermediate = (y + x) & 0x1;\n break;\n case 1:\n intermediate = y & 0x1;\n break;\n case 2:\n intermediate = x % 3;\n break;\n case 3:\n intermediate = (y + x) % 3;\n break;\n case 4:\n intermediate = (Math.floor(y / 2) + Math.floor(x / 3)) & 0x1;\n break;\n case 5:\n temp = y * x;\n intermediate = (temp & 0x1) + (temp % 3);\n break;\n case 6:\n temp = y * x;\n intermediate = ((temp & 0x1) + (temp % 3)) & 0x1;\n break;\n case 7:\n temp = y * x;\n intermediate = ((temp % 3) + ((y + x) & 0x1)) & 0x1;\n break;\n default:\n throw new IllegalArgumentException('Invalid mask pattern: ' + maskPattern);\n }\n return intermediate === 0;\n }\n /**\n * Helper function for applyMaskPenaltyRule1. We need this for doing this calculation in both\n * vertical and horizontal orders respectively.\n */\n static applyMaskPenaltyRule1Internal(matrix, isHorizontal) {\n let penalty = 0;\n const iLimit = isHorizontal ? matrix.getHeight() : matrix.getWidth();\n const jLimit = isHorizontal ? matrix.getWidth() : matrix.getHeight();\n const array = matrix.getArray();\n for (let i = 0; i < iLimit; i++) {\n let numSameBitCells = 0;\n let prevBit = -1;\n for (let j = 0; j < jLimit; j++) {\n const bit = isHorizontal ? array[i][j] : array[j][i];\n if (bit === prevBit) {\n numSameBitCells++;\n }\n else {\n if (numSameBitCells >= 5) {\n penalty += MaskUtil.N1 + (numSameBitCells - 5);\n }\n numSameBitCells = 1; // Include the cell itself.\n prevBit = bit;\n }\n }\n if (numSameBitCells >= 5) {\n penalty += MaskUtil.N1 + (numSameBitCells - 5);\n }\n }\n return penalty;\n }\n }\n // Penalty weights from section 6.8.2.1\n MaskUtil.N1 = 3;\n MaskUtil.N2 = 3;\n MaskUtil.N3 = 40;\n MaskUtil.N4 = 10;\n\n /**\n * JAVAPORT: The original code was a 2D array of ints, but since it only ever gets assigned\n * -1, 0, and 1, I'm going to use less memory and go with bytes.\n *\n * @author dswitkin@google.com (Daniel Switkin)\n */\n class ByteMatrix {\n constructor(width /*int*/, height /*int*/) {\n this.width = width;\n this.height = height;\n const bytes = new Array(height); // [height][width]\n for (let i = 0; i !== height; i++) {\n bytes[i] = new Uint8Array(width);\n }\n this.bytes = bytes;\n }\n getHeight() {\n return this.height;\n }\n getWidth() {\n return this.width;\n }\n get(x /*int*/, y /*int*/) {\n return this.bytes[y][x];\n }\n /**\n * @return an internal representation as bytes, in row-major order. array[y][x] represents point (x,y)\n */\n getArray() {\n return this.bytes;\n }\n // TYPESCRIPTPORT: preffer to let two methods instead of override to avoid type comparison inside\n setNumber(x /*int*/, y /*int*/, value /*byte|int*/) {\n this.bytes[y][x] = value;\n }\n // public set(x: number /*int*/, y: number /*int*/, value: number /*int*/): void {\n // bytes[y][x] = (byte) value\n // }\n setBoolean(x /*int*/, y /*int*/, value) {\n this.bytes[y][x] = /*(byte) */ (value ? 1 : 0);\n }\n clear(value /*byte*/) {\n for (const aByte of this.bytes) {\n Arrays.fill(aByte, value);\n }\n }\n equals(o) {\n if (!(o instanceof ByteMatrix)) {\n return false;\n }\n const other = o;\n if (this.width !== other.width) {\n return false;\n }\n if (this.height !== other.height) {\n return false;\n }\n for (let y = 0, height = this.height; y < height; ++y) {\n const bytesY = this.bytes[y];\n const otherBytesY = other.bytes[y];\n for (let x = 0, width = this.width; x < width; ++x) {\n if (bytesY[x] !== otherBytesY[x]) {\n return false;\n }\n }\n }\n return true;\n }\n /*@Override*/\n toString() {\n const result = new StringBuilder(); // (2 * width * height + 2)\n for (let y = 0, height = this.height; y < height; ++y) {\n const bytesY = this.bytes[y];\n for (let x = 0, width = this.width; x < width; ++x) {\n switch (bytesY[x]) {\n case 0:\n result.append(' 0');\n break;\n case 1:\n result.append(' 1');\n break;\n default:\n result.append(' ');\n break;\n }\n }\n result.append('\\n');\n }\n return result.toString();\n }\n }\n\n /**\n * @author satorux@google.com (Satoru Takabayashi) - creator\n * @author dswitkin@google.com (Daniel Switkin) - ported from C++\n */\n class QRCode {\n constructor() {\n this.maskPattern = -1;\n }\n getMode() {\n return this.mode;\n }\n getECLevel() {\n return this.ecLevel;\n }\n getVersion() {\n return this.version;\n }\n getMaskPattern() {\n return this.maskPattern;\n }\n getMatrix() {\n return this.matrix;\n }\n /*@Override*/\n toString() {\n const result = new StringBuilder(); // (200)\n result.append('<<\\n');\n result.append(' mode: ');\n result.append(this.mode ? this.mode.toString() : 'null');\n result.append('\\n ecLevel: ');\n result.append(this.ecLevel ? this.ecLevel.toString() : 'null');\n result.append('\\n version: ');\n result.append(this.version ? this.version.toString() : 'null');\n result.append('\\n maskPattern: ');\n result.append(this.maskPattern.toString());\n if (this.matrix) {\n result.append('\\n matrix:\\n');\n result.append(this.matrix.toString());\n }\n else {\n result.append('\\n matrix: null\\n');\n }\n result.append('>>\\n');\n return result.toString();\n }\n setMode(value) {\n this.mode = value;\n }\n setECLevel(value) {\n this.ecLevel = value;\n }\n setVersion(version) {\n this.version = version;\n }\n setMaskPattern(value /*int*/) {\n this.maskPattern = value;\n }\n setMatrix(value) {\n this.matrix = value;\n }\n // Check if \"mask_pattern\" is valid.\n static isValidMaskPattern(maskPattern /*int*/) {\n return maskPattern >= 0 && maskPattern < QRCode.NUM_MASK_PATTERNS;\n }\n }\n QRCode.NUM_MASK_PATTERNS = 8;\n\n /**\n * Custom Error class of type Exception.\n */\n class WriterException extends Exception {\n }\n WriterException.kind = 'WriterException';\n\n /**\n * @author satorux@google.com (Satoru Takabayashi) - creator\n * @author dswitkin@google.com (Daniel Switkin) - ported from C++\n */\n class MatrixUtil {\n constructor() {\n // do nothing\n }\n // Set all cells to -1 (TYPESCRIPTPORT: 255). -1 (TYPESCRIPTPORT: 255) means that the cell is empty (not set yet).\n //\n // JAVAPORT: We shouldn't need to do this at all. The code should be rewritten to begin encoding\n // with the ByteMatrix initialized all to zero.\n static clearMatrix(matrix) {\n // TYPESCRIPTPORT: we use UintArray se changed here from -1 to 255\n matrix.clear(/*(byte) */ /*-1*/ 255);\n }\n // Build 2D matrix of QR Code from \"dataBits\" with \"ecLevel\", \"version\" and \"getMaskPattern\". On\n // success, store the result in \"matrix\" and return true.\n static buildMatrix(dataBits, ecLevel, version, maskPattern /*int*/, matrix) {\n MatrixUtil.clearMatrix(matrix);\n MatrixUtil.embedBasicPatterns(version, matrix);\n // Type information appear with any version.\n MatrixUtil.embedTypeInfo(ecLevel, maskPattern, matrix);\n // Version info appear if version >= 7.\n MatrixUtil.maybeEmbedVersionInfo(version, matrix);\n // Data should be embedded at end.\n MatrixUtil.embedDataBits(dataBits, maskPattern, matrix);\n }\n // Embed basic patterns. On success, modify the matrix and return true.\n // The basic patterns are:\n // - Position detection patterns\n // - Timing patterns\n // - Dark dot at the left bottom corner\n // - Position adjustment patterns, if need be\n static embedBasicPatterns(version, matrix) {\n // Let's get started with embedding big squares at corners.\n MatrixUtil.embedPositionDetectionPatternsAndSeparators(matrix);\n // Then, embed the dark dot at the left bottom corner.\n MatrixUtil.embedDarkDotAtLeftBottomCorner(matrix);\n // Position adjustment patterns appear if version >= 2.\n MatrixUtil.maybeEmbedPositionAdjustmentPatterns(version, matrix);\n // Timing patterns should be embedded after position adj. patterns.\n MatrixUtil.embedTimingPatterns(matrix);\n }\n // Embed type information. On success, modify the matrix.\n static embedTypeInfo(ecLevel, maskPattern /*int*/, matrix) {\n const typeInfoBits = new BitArray();\n MatrixUtil.makeTypeInfoBits(ecLevel, maskPattern, typeInfoBits);\n for (let i = 0, size = typeInfoBits.getSize(); i < size; ++i) {\n // Place bits in LSB to MSB order. LSB (least significant bit) is the last value in\n // \"typeInfoBits\".\n const bit = typeInfoBits.get(typeInfoBits.getSize() - 1 - i);\n // Type info bits at the left top corner. See 8.9 of JISX0510:2004 (p.46).\n const coordinates = MatrixUtil.TYPE_INFO_COORDINATES[i];\n const x1 = coordinates[0];\n const y1 = coordinates[1];\n matrix.setBoolean(x1, y1, bit);\n if (i < 8) {\n // Right top corner.\n const x2 = matrix.getWidth() - i - 1;\n const y2 = 8;\n matrix.setBoolean(x2, y2, bit);\n }\n else {\n // Left bottom corner.\n const x2 = 8;\n const y2 = matrix.getHeight() - 7 + (i - 8);\n matrix.setBoolean(x2, y2, bit);\n }\n }\n }\n // Embed version information if need be. On success, modify the matrix and return true.\n // See 8.10 of JISX0510:2004 (p.47) for how to embed version information.\n static maybeEmbedVersionInfo(version, matrix) {\n if (version.getVersionNumber() < 7) { // Version info is necessary if version >= 7.\n return; // Don't need version info.\n }\n const versionInfoBits = new BitArray();\n MatrixUtil.makeVersionInfoBits(version, versionInfoBits);\n let bitIndex = 6 * 3 - 1; // It will decrease from 17 to 0.\n for (let i = 0; i < 6; ++i) {\n for (let j = 0; j < 3; ++j) {\n // Place bits in LSB (least significant bit) to MSB order.\n const bit = versionInfoBits.get(bitIndex);\n bitIndex--;\n // Left bottom corner.\n matrix.setBoolean(i, matrix.getHeight() - 11 + j, bit);\n // Right bottom corner.\n matrix.setBoolean(matrix.getHeight() - 11 + j, i, bit);\n }\n }\n }\n // Embed \"dataBits\" using \"getMaskPattern\". On success, modify the matrix and return true.\n // For debugging purposes, it skips masking process if \"getMaskPattern\" is -1(TYPESCRIPTPORT: 255).\n // See 8.7 of JISX0510:2004 (p.38) for how to embed data bits.\n static embedDataBits(dataBits, maskPattern /*int*/, matrix) {\n let bitIndex = 0;\n let direction = -1;\n // Start from the right bottom cell.\n let x = matrix.getWidth() - 1;\n let y = matrix.getHeight() - 1;\n while (x > 0) {\n // Skip the vertical timing pattern.\n if (x === 6) {\n x -= 1;\n }\n while (y >= 0 && y < matrix.getHeight()) {\n for (let i = 0; i < 2; ++i) {\n const xx = x - i;\n // Skip the cell if it's not empty.\n if (!MatrixUtil.isEmpty(matrix.get(xx, y))) {\n continue;\n }\n let bit;\n if (bitIndex < dataBits.getSize()) {\n bit = dataBits.get(bitIndex);\n ++bitIndex;\n }\n else {\n // Padding bit. If there is no bit left, we'll fill the left cells with 0, as described\n // in 8.4.9 of JISX0510:2004 (p. 24).\n bit = false;\n }\n // Skip masking if mask_pattern is -1 (TYPESCRIPTPORT: 255).\n if (maskPattern !== 255 && MaskUtil.getDataMaskBit(maskPattern, xx, y)) {\n bit = !bit;\n }\n matrix.setBoolean(xx, y, bit);\n }\n y += direction;\n }\n direction = -direction; // Reverse the direction.\n y += direction;\n x -= 2; // Move to the left.\n }\n // All bits should be consumed.\n if (bitIndex !== dataBits.getSize()) {\n throw new WriterException('Not all bits consumed: ' + bitIndex + '/' + dataBits.getSize());\n }\n }\n // Return the position of the most significant bit set (one: to) in the \"value\". The most\n // significant bit is position 32. If there is no bit set, return 0. Examples:\n // - findMSBSet(0) => 0\n // - findMSBSet(1) => 1\n // - findMSBSet(255) => 8\n static findMSBSet(value /*int*/) {\n return 32 - Integer.numberOfLeadingZeros(value);\n }\n // Calculate BCH (Bose-Chaudhuri-Hocquenghem) code for \"value\" using polynomial \"poly\". The BCH\n // code is used for encoding type information and version information.\n // Example: Calculation of version information of 7.\n // f(x) is created from 7.\n // - 7 = 000111 in 6 bits\n // - f(x) = x^2 + x^1 + x^0\n // g(x) is given by the standard (p. 67)\n // - g(x) = x^12 + x^11 + x^10 + x^9 + x^8 + x^5 + x^2 + 1\n // Multiply f(x) by x^(18 - 6)\n // - f'(x) = f(x) * x^(18 - 6)\n // - f'(x) = x^14 + x^13 + x^12\n // Calculate the remainder of f'(x) / g(x)\n // x^2\n // __________________________________________________\n // g(x) )x^14 + x^13 + x^12\n // x^14 + x^13 + x^12 + x^11 + x^10 + x^7 + x^4 + x^2\n // --------------------------------------------------\n // x^11 + x^10 + x^7 + x^4 + x^2\n //\n // The remainder is x^11 + x^10 + x^7 + x^4 + x^2\n // Encode it in binary: 110010010100\n // The return value is 0xc94 (1100 1001 0100)\n //\n // Since all coefficients in the polynomials are 1 or 0, we can do the calculation by bit\n // operations. We don't care if coefficients are positive or negative.\n static calculateBCHCode(value /*int*/, poly /*int*/) {\n if (poly === 0) {\n throw new IllegalArgumentException('0 polynomial');\n }\n // If poly is \"1 1111 0010 0101\" (version info poly), msbSetInPoly is 13. We'll subtract 1\n // from 13 to make it 12.\n const msbSetInPoly = MatrixUtil.findMSBSet(poly);\n value <<= msbSetInPoly - 1;\n // Do the division business using exclusive-or operations.\n while (MatrixUtil.findMSBSet(value) >= msbSetInPoly) {\n value ^= poly << (MatrixUtil.findMSBSet(value) - msbSetInPoly);\n }\n // Now the \"value\" is the remainder (i.e. the BCH code)\n return value;\n }\n // Make bit vector of type information. On success, store the result in \"bits\" and return true.\n // Encode error correction level and mask pattern. See 8.9 of\n // JISX0510:2004 (p.45) for details.\n static makeTypeInfoBits(ecLevel, maskPattern /*int*/, bits) {\n if (!QRCode.isValidMaskPattern(maskPattern)) {\n throw new WriterException('Invalid mask pattern');\n }\n const typeInfo = (ecLevel.getBits() << 3) | maskPattern;\n bits.appendBits(typeInfo, 5);\n const bchCode = MatrixUtil.calculateBCHCode(typeInfo, MatrixUtil.TYPE_INFO_POLY);\n bits.appendBits(bchCode, 10);\n const maskBits = new BitArray();\n maskBits.appendBits(MatrixUtil.TYPE_INFO_MASK_PATTERN, 15);\n bits.xor(maskBits);\n if (bits.getSize() !== 15) { // Just in case.\n throw new WriterException('should not happen but we got: ' + bits.getSize());\n }\n }\n // Make bit vector of version information. On success, store the result in \"bits\" and return true.\n // See 8.10 of JISX0510:2004 (p.45) for details.\n static makeVersionInfoBits(version, bits) {\n bits.appendBits(version.getVersionNumber(), 6);\n const bchCode = MatrixUtil.calculateBCHCode(version.getVersionNumber(), MatrixUtil.VERSION_INFO_POLY);\n bits.appendBits(bchCode, 12);\n if (bits.getSize() !== 18) { // Just in case.\n throw new WriterException('should not happen but we got: ' + bits.getSize());\n }\n }\n // Check if \"value\" is empty.\n static isEmpty(value /*int*/) {\n return value === 255; // -1\n }\n static embedTimingPatterns(matrix) {\n // -8 is for skipping position detection patterns (7: size), and two horizontal/vertical\n // separation patterns (1: size). Thus, 8 = 7 + 1.\n for (let i = 8; i < matrix.getWidth() - 8; ++i) {\n const bit = (i + 1) % 2;\n // Horizontal line.\n if (MatrixUtil.isEmpty(matrix.get(i, 6))) {\n matrix.setNumber(i, 6, bit);\n }\n // Vertical line.\n if (MatrixUtil.isEmpty(matrix.get(6, i))) {\n matrix.setNumber(6, i, bit);\n }\n }\n }\n // Embed the lonely dark dot at left bottom corner. JISX0510:2004 (p.46)\n static embedDarkDotAtLeftBottomCorner(matrix) {\n if (matrix.get(8, matrix.getHeight() - 8) === 0) {\n throw new WriterException();\n }\n matrix.setNumber(8, matrix.getHeight() - 8, 1);\n }\n static embedHorizontalSeparationPattern(xStart /*int*/, yStart /*int*/, matrix) {\n for (let x = 0; x < 8; ++x) {\n if (!MatrixUtil.isEmpty(matrix.get(xStart + x, yStart))) {\n throw new WriterException();\n }\n matrix.setNumber(xStart + x, yStart, 0);\n }\n }\n static embedVerticalSeparationPattern(xStart /*int*/, yStart /*int*/, matrix) {\n for (let y = 0; y < 7; ++y) {\n if (!MatrixUtil.isEmpty(matrix.get(xStart, yStart + y))) {\n throw new WriterException();\n }\n matrix.setNumber(xStart, yStart + y, 0);\n }\n }\n static embedPositionAdjustmentPattern(xStart /*int*/, yStart /*int*/, matrix) {\n for (let y = 0; y < 5; ++y) {\n const patternY = MatrixUtil.POSITION_ADJUSTMENT_PATTERN[y];\n for (let x = 0; x < 5; ++x) {\n matrix.setNumber(xStart + x, yStart + y, patternY[x]);\n }\n }\n }\n static embedPositionDetectionPattern(xStart /*int*/, yStart /*int*/, matrix) {\n for (let y = 0; y < 7; ++y) {\n const patternY = MatrixUtil.POSITION_DETECTION_PATTERN[y];\n for (let x = 0; x < 7; ++x) {\n matrix.setNumber(xStart + x, yStart + y, patternY[x]);\n }\n }\n }\n // Embed position detection patterns and surrounding vertical/horizontal separators.\n static embedPositionDetectionPatternsAndSeparators(matrix) {\n // Embed three big squares at corners.\n const pdpWidth = MatrixUtil.POSITION_DETECTION_PATTERN[0].length;\n // Left top corner.\n MatrixUtil.embedPositionDetectionPattern(0, 0, matrix);\n // Right top corner.\n MatrixUtil.embedPositionDetectionPattern(matrix.getWidth() - pdpWidth, 0, matrix);\n // Left bottom corner.\n MatrixUtil.embedPositionDetectionPattern(0, matrix.getWidth() - pdpWidth, matrix);\n // Embed horizontal separation patterns around the squares.\n const hspWidth = 8;\n // Left top corner.\n MatrixUtil.embedHorizontalSeparationPattern(0, hspWidth - 1, matrix);\n // Right top corner.\n MatrixUtil.embedHorizontalSeparationPattern(matrix.getWidth() - hspWidth, hspWidth - 1, matrix);\n // Left bottom corner.\n MatrixUtil.embedHorizontalSeparationPattern(0, matrix.getWidth() - hspWidth, matrix);\n // Embed vertical separation patterns around the squares.\n const vspSize = 7;\n // Left top corner.\n MatrixUtil.embedVerticalSeparationPattern(vspSize, 0, matrix);\n // Right top corner.\n MatrixUtil.embedVerticalSeparationPattern(matrix.getHeight() - vspSize - 1, 0, matrix);\n // Left bottom corner.\n MatrixUtil.embedVerticalSeparationPattern(vspSize, matrix.getHeight() - vspSize, matrix);\n }\n // Embed position adjustment patterns if need be.\n static maybeEmbedPositionAdjustmentPatterns(version, matrix) {\n if (version.getVersionNumber() < 2) { // The patterns appear if version >= 2\n return;\n }\n const index = version.getVersionNumber() - 1;\n const coordinates = MatrixUtil.POSITION_ADJUSTMENT_PATTERN_COORDINATE_TABLE[index];\n for (let i = 0, length = coordinates.length; i !== length; i++) {\n const y = coordinates[i];\n if (y >= 0) {\n for (let j = 0; j !== length; j++) {\n const x = coordinates[j];\n if (x >= 0 && MatrixUtil.isEmpty(matrix.get(x, y))) {\n // If the cell is unset, we embed the position adjustment pattern here.\n // -2 is necessary since the x/y coordinates point to the center of the pattern, not the\n // left top corner.\n MatrixUtil.embedPositionAdjustmentPattern(x - 2, y - 2, matrix);\n }\n }\n }\n }\n }\n }\n MatrixUtil.POSITION_DETECTION_PATTERN = Array.from([\n Int32Array.from([1, 1, 1, 1, 1, 1, 1]),\n Int32Array.from([1, 0, 0, 0, 0, 0, 1]),\n Int32Array.from([1, 0, 1, 1, 1, 0, 1]),\n Int32Array.from([1, 0, 1, 1, 1, 0, 1]),\n Int32Array.from([1, 0, 1, 1, 1, 0, 1]),\n Int32Array.from([1, 0, 0, 0, 0, 0, 1]),\n Int32Array.from([1, 1, 1, 1, 1, 1, 1]),\n ]);\n MatrixUtil.POSITION_ADJUSTMENT_PATTERN = Array.from([\n Int32Array.from([1, 1, 1, 1, 1]),\n Int32Array.from([1, 0, 0, 0, 1]),\n Int32Array.from([1, 0, 1, 0, 1]),\n Int32Array.from([1, 0, 0, 0, 1]),\n Int32Array.from([1, 1, 1, 1, 1]),\n ]);\n // From Appendix E. Table 1, JIS0510X:2004 (71: p). The table was double-checked by komatsu.\n MatrixUtil.POSITION_ADJUSTMENT_PATTERN_COORDINATE_TABLE = Array.from([\n Int32Array.from([-1, -1, -1, -1, -1, -1, -1]),\n Int32Array.from([6, 18, -1, -1, -1, -1, -1]),\n Int32Array.from([6, 22, -1, -1, -1, -1, -1]),\n Int32Array.from([6, 26, -1, -1, -1, -1, -1]),\n Int32Array.from([6, 30, -1, -1, -1, -1, -1]),\n Int32Array.from([6, 34, -1, -1, -1, -1, -1]),\n Int32Array.from([6, 22, 38, -1, -1, -1, -1]),\n Int32Array.from([6, 24, 42, -1, -1, -1, -1]),\n Int32Array.from([6, 26, 46, -1, -1, -1, -1]),\n Int32Array.from([6, 28, 50, -1, -1, -1, -1]),\n Int32Array.from([6, 30, 54, -1, -1, -1, -1]),\n Int32Array.from([6, 32, 58, -1, -1, -1, -1]),\n Int32Array.from([6, 34, 62, -1, -1, -1, -1]),\n Int32Array.from([6, 26, 46, 66, -1, -1, -1]),\n Int32Array.from([6, 26, 48, 70, -1, -1, -1]),\n Int32Array.from([6, 26, 50, 74, -1, -1, -1]),\n Int32Array.from([6, 30, 54, 78, -1, -1, -1]),\n Int32Array.from([6, 30, 56, 82, -1, -1, -1]),\n Int32Array.from([6, 30, 58, 86, -1, -1, -1]),\n Int32Array.from([6, 34, 62, 90, -1, -1, -1]),\n Int32Array.from([6, 28, 50, 72, 94, -1, -1]),\n Int32Array.from([6, 26, 50, 74, 98, -1, -1]),\n Int32Array.from([6, 30, 54, 78, 102, -1, -1]),\n Int32Array.from([6, 28, 54, 80, 106, -1, -1]),\n Int32Array.from([6, 32, 58, 84, 110, -1, -1]),\n Int32Array.from([6, 30, 58, 86, 114, -1, -1]),\n Int32Array.from([6, 34, 62, 90, 118, -1, -1]),\n Int32Array.from([6, 26, 50, 74, 98, 122, -1]),\n Int32Array.from([6, 30, 54, 78, 102, 126, -1]),\n Int32Array.from([6, 26, 52, 78, 104, 130, -1]),\n Int32Array.from([6, 30, 56, 82, 108, 134, -1]),\n Int32Array.from([6, 34, 60, 86, 112, 138, -1]),\n Int32Array.from([6, 30, 58, 86, 114, 142, -1]),\n Int32Array.from([6, 34, 62, 90, 118, 146, -1]),\n Int32Array.from([6, 30, 54, 78, 102, 126, 150]),\n Int32Array.from([6, 24, 50, 76, 102, 128, 154]),\n Int32Array.from([6, 28, 54, 80, 106, 132, 158]),\n Int32Array.from([6, 32, 58, 84, 110, 136, 162]),\n Int32Array.from([6, 26, 54, 82, 110, 138, 166]),\n Int32Array.from([6, 30, 58, 86, 114, 142, 170]),\n ]);\n // Type info cells at the left top corner.\n MatrixUtil.TYPE_INFO_COORDINATES = Array.from([\n Int32Array.from([8, 0]),\n Int32Array.from([8, 1]),\n Int32Array.from([8, 2]),\n Int32Array.from([8, 3]),\n Int32Array.from([8, 4]),\n Int32Array.from([8, 5]),\n Int32Array.from([8, 7]),\n Int32Array.from([8, 8]),\n Int32Array.from([7, 8]),\n Int32Array.from([5, 8]),\n Int32Array.from([4, 8]),\n Int32Array.from([3, 8]),\n Int32Array.from([2, 8]),\n Int32Array.from([1, 8]),\n Int32Array.from([0, 8]),\n ]);\n // From Appendix D in JISX0510:2004 (p. 67)\n MatrixUtil.VERSION_INFO_POLY = 0x1f25; // 1 1111 0010 0101\n // From Appendix C in JISX0510:2004 (p.65).\n MatrixUtil.TYPE_INFO_POLY = 0x537;\n MatrixUtil.TYPE_INFO_MASK_PATTERN = 0x5412;\n\n /*namespace com.google.zxing.qrcode.encoder {*/\n class BlockPair {\n constructor(dataBytes, errorCorrectionBytes) {\n this.dataBytes = dataBytes;\n this.errorCorrectionBytes = errorCorrectionBytes;\n }\n getDataBytes() {\n return this.dataBytes;\n }\n getErrorCorrectionBytes() {\n return this.errorCorrectionBytes;\n }\n }\n\n /*import java.io.UnsupportedEncodingException;*/\n /*import java.util.ArrayList;*/\n /*import java.util.Collection;*/\n /*import java.util.Map;*/\n /**\n * @author satorux@google.com (Satoru Takabayashi) - creator\n * @author dswitkin@google.com (Daniel Switkin) - ported from C++\n */\n class Encoder {\n // TYPESCRIPTPORT: changed to UTF8, the default for js\n constructor() { }\n // The mask penalty calculation is complicated. See Table 21 of JISX0510:2004 (p.45) for details.\n // Basically it applies four rules and summate all penalties.\n static calculateMaskPenalty(matrix) {\n return MaskUtil.applyMaskPenaltyRule1(matrix)\n + MaskUtil.applyMaskPenaltyRule2(matrix)\n + MaskUtil.applyMaskPenaltyRule3(matrix)\n + MaskUtil.applyMaskPenaltyRule4(matrix);\n }\n /**\n * @param content text to encode\n * @param ecLevel error correction level to use\n * @return {@link QRCode} representing the encoded QR code\n * @throws WriterException if encoding can't succeed, because of for example invalid content\n * or configuration\n */\n // public static encode(content: string, ecLevel: ErrorCorrectionLevel): QRCode /*throws WriterException*/ {\n // return encode(content, ecLevel, null)\n // }\n static encode(content, ecLevel, hints = null) {\n // Determine what character encoding has been specified by the caller, if any\n let encoding = Encoder.DEFAULT_BYTE_MODE_ENCODING;\n const hasEncodingHint = hints !== null && undefined !== hints.get(EncodeHintType$1.CHARACTER_SET);\n if (hasEncodingHint) {\n encoding = hints.get(EncodeHintType$1.CHARACTER_SET).toString();\n }\n // Pick an encoding mode appropriate for the content. Note that this will not attempt to use\n // multiple modes / segments even if that were more efficient. Twould be nice.\n const mode = this.chooseMode(content, encoding);\n // This will store the header information, like mode and\n // length, as well as \"header\" segments like an ECI segment.\n const headerBits = new BitArray();\n // Append ECI segment if applicable\n if (mode === Mode$1.BYTE && (hasEncodingHint || Encoder.DEFAULT_BYTE_MODE_ENCODING !== encoding)) {\n const eci = CharacterSetECI.getCharacterSetECIByName(encoding);\n if (eci !== undefined) {\n this.appendECI(eci, headerBits);\n }\n }\n // (With ECI in place,) Write the mode marker\n this.appendModeInfo(mode, headerBits);\n // Collect data within the main segment, separately, to count its size if needed. Don't add it to\n // main payload yet.\n const dataBits = new BitArray();\n this.appendBytes(content, mode, dataBits, encoding);\n let version;\n if (hints !== null && undefined !== hints.get(EncodeHintType$1.QR_VERSION)) {\n const versionNumber = Number.parseInt(hints.get(EncodeHintType$1.QR_VERSION).toString(), 10);\n version = Version$1.getVersionForNumber(versionNumber);\n const bitsNeeded = this.calculateBitsNeeded(mode, headerBits, dataBits, version);\n if (!this.willFit(bitsNeeded, version, ecLevel)) {\n throw new WriterException('Data too big for requested version');\n }\n }\n else {\n version = this.recommendVersion(ecLevel, mode, headerBits, dataBits);\n }\n const headerAndDataBits = new BitArray();\n headerAndDataBits.appendBitArray(headerBits);\n // Find \"length\" of main segment and write it\n const numLetters = mode === Mode$1.BYTE ? dataBits.getSizeInBytes() : content.length;\n this.appendLengthInfo(numLetters, version, mode, headerAndDataBits);\n // Put data together into the overall payload\n headerAndDataBits.appendBitArray(dataBits);\n const ecBlocks = version.getECBlocksForLevel(ecLevel);\n const numDataBytes = version.getTotalCodewords() - ecBlocks.getTotalECCodewords();\n // Terminate the bits properly.\n this.terminateBits(numDataBytes, headerAndDataBits);\n // Interleave data bits with error correction code.\n const finalBits = this.interleaveWithECBytes(headerAndDataBits, version.getTotalCodewords(), numDataBytes, ecBlocks.getNumBlocks());\n const qrCode = new QRCode();\n qrCode.setECLevel(ecLevel);\n qrCode.setMode(mode);\n qrCode.setVersion(version);\n // Choose the mask pattern and set to \"qrCode\".\n const dimension = version.getDimensionForVersion();\n const matrix = new ByteMatrix(dimension, dimension);\n const maskPattern = this.chooseMaskPattern(finalBits, ecLevel, version, matrix);\n qrCode.setMaskPattern(maskPattern);\n // Build the matrix and set it to \"qrCode\".\n MatrixUtil.buildMatrix(finalBits, ecLevel, version, maskPattern, matrix);\n qrCode.setMatrix(matrix);\n return qrCode;\n }\n /**\n * Decides the smallest version of QR code that will contain all of the provided data.\n *\n * @throws WriterException if the data cannot fit in any version\n */\n static recommendVersion(ecLevel, mode, headerBits, dataBits) {\n // Hard part: need to know version to know how many bits length takes. But need to know how many\n // bits it takes to know version. First we take a guess at version by assuming version will be\n // the minimum, 1:\n const provisionalBitsNeeded = this.calculateBitsNeeded(mode, headerBits, dataBits, Version$1.getVersionForNumber(1));\n const provisionalVersion = this.chooseVersion(provisionalBitsNeeded, ecLevel);\n // Use that guess to calculate the right version. I am still not sure this works in 100% of cases.\n const bitsNeeded = this.calculateBitsNeeded(mode, headerBits, dataBits, provisionalVersion);\n return this.chooseVersion(bitsNeeded, ecLevel);\n }\n static calculateBitsNeeded(mode, headerBits, dataBits, version) {\n return headerBits.getSize() + mode.getCharacterCountBits(version) + dataBits.getSize();\n }\n /**\n * @return the code point of the table used in alphanumeric mode or\n * -1 if there is no corresponding code in the table.\n */\n static getAlphanumericCode(code /*int*/) {\n if (code < Encoder.ALPHANUMERIC_TABLE.length) {\n return Encoder.ALPHANUMERIC_TABLE[code];\n }\n return -1;\n }\n // public static chooseMode(content: string): Mode {\n // return chooseMode(content, null);\n // }\n /**\n * Choose the best mode by examining the content. Note that 'encoding' is used as a hint;\n * if it is Shift_JIS, and the input is only double-byte Kanji, then we return {@link Mode#KANJI}.\n */\n static chooseMode(content, encoding = null) {\n if (CharacterSetECI.SJIS.getName() === encoding && this.isOnlyDoubleByteKanji(content)) {\n // Choose Kanji mode if all input are double-byte characters\n return Mode$1.KANJI;\n }\n let hasNumeric = false;\n let hasAlphanumeric = false;\n for (let i = 0, length = content.length; i < length; ++i) {\n const c = content.charAt(i);\n if (Encoder.isDigit(c)) {\n hasNumeric = true;\n }\n else if (this.getAlphanumericCode(c.charCodeAt(0)) !== -1) {\n hasAlphanumeric = true;\n }\n else {\n return Mode$1.BYTE;\n }\n }\n if (hasAlphanumeric) {\n return Mode$1.ALPHANUMERIC;\n }\n if (hasNumeric) {\n return Mode$1.NUMERIC;\n }\n return Mode$1.BYTE;\n }\n static isOnlyDoubleByteKanji(content) {\n let bytes;\n try {\n bytes = StringEncoding.encode(content, CharacterSetECI.SJIS); // content.getBytes(\"Shift_JIS\"))\n }\n catch (ignored /*: UnsupportedEncodingException*/) {\n return false;\n }\n const length = bytes.length;\n if (length % 2 !== 0) {\n return false;\n }\n for (let i = 0; i < length; i += 2) {\n const byte1 = bytes[i] & 0xFF;\n if ((byte1 < 0x81 || byte1 > 0x9F) && (byte1 < 0xE0 || byte1 > 0xEB)) {\n return false;\n }\n }\n return true;\n }\n static chooseMaskPattern(bits, ecLevel, version, matrix) {\n let minPenalty = Number.MAX_SAFE_INTEGER; // Lower penalty is better.\n let bestMaskPattern = -1;\n // We try all mask patterns to choose the best one.\n for (let maskPattern = 0; maskPattern < QRCode.NUM_MASK_PATTERNS; maskPattern++) {\n MatrixUtil.buildMatrix(bits, ecLevel, version, maskPattern, matrix);\n let penalty = this.calculateMaskPenalty(matrix);\n if (penalty < minPenalty) {\n minPenalty = penalty;\n bestMaskPattern = maskPattern;\n }\n }\n return bestMaskPattern;\n }\n static chooseVersion(numInputBits /*int*/, ecLevel) {\n for (let versionNum = 1; versionNum <= 40; versionNum++) {\n const version = Version$1.getVersionForNumber(versionNum);\n if (Encoder.willFit(numInputBits, version, ecLevel)) {\n return version;\n }\n }\n throw new WriterException('Data too big');\n }\n /**\n * @return true if the number of input bits will fit in a code with the specified version and\n * error correction level.\n */\n static willFit(numInputBits /*int*/, version, ecLevel) {\n // In the following comments, we use numbers of Version 7-H.\n // numBytes = 196\n const numBytes = version.getTotalCodewords();\n // getNumECBytes = 130\n const ecBlocks = version.getECBlocksForLevel(ecLevel);\n const numEcBytes = ecBlocks.getTotalECCodewords();\n // getNumDataBytes = 196 - 130 = 66\n const numDataBytes = numBytes - numEcBytes;\n const totalInputBytes = (numInputBits + 7) / 8;\n return numDataBytes >= totalInputBytes;\n }\n /**\n * Terminate bits as described in 8.4.8 and 8.4.9 of JISX0510:2004 (p.24).\n */\n static terminateBits(numDataBytes /*int*/, bits) {\n const capacity = numDataBytes * 8;\n if (bits.getSize() > capacity) {\n throw new WriterException('data bits cannot fit in the QR Code' + bits.getSize() + ' > ' +\n capacity);\n }\n for (let i = 0; i < 4 && bits.getSize() < capacity; ++i) {\n bits.appendBit(false);\n }\n // Append termination bits. See 8.4.8 of JISX0510:2004 (p.24) for details.\n // If the last byte isn't 8-bit aligned, we'll add padding bits.\n const numBitsInLastByte = bits.getSize() & 0x07;\n if (numBitsInLastByte > 0) {\n for (let i = numBitsInLastByte; i < 8; i++) {\n bits.appendBit(false);\n }\n }\n // If we have more space, we'll fill the space with padding patterns defined in 8.4.9 (p.24).\n const numPaddingBytes = numDataBytes - bits.getSizeInBytes();\n for (let i = 0; i < numPaddingBytes; ++i) {\n bits.appendBits((i & 0x01) === 0 ? 0xEC : 0x11, 8);\n }\n if (bits.getSize() !== capacity) {\n throw new WriterException('Bits size does not equal capacity');\n }\n }\n /**\n * Get number of data bytes and number of error correction bytes for block id \"blockID\". Store\n * the result in \"numDataBytesInBlock\", and \"numECBytesInBlock\". See table 12 in 8.5.1 of\n * JISX0510:2004 (p.30)\n */\n static getNumDataBytesAndNumECBytesForBlockID(numTotalBytes /*int*/, numDataBytes /*int*/, numRSBlocks /*int*/, blockID /*int*/, numDataBytesInBlock, numECBytesInBlock) {\n if (blockID >= numRSBlocks) {\n throw new WriterException('Block ID too large');\n }\n // numRsBlocksInGroup2 = 196 % 5 = 1\n const numRsBlocksInGroup2 = numTotalBytes % numRSBlocks;\n // numRsBlocksInGroup1 = 5 - 1 = 4\n const numRsBlocksInGroup1 = numRSBlocks - numRsBlocksInGroup2;\n // numTotalBytesInGroup1 = 196 / 5 = 39\n const numTotalBytesInGroup1 = Math.floor(numTotalBytes / numRSBlocks);\n // numTotalBytesInGroup2 = 39 + 1 = 40\n const numTotalBytesInGroup2 = numTotalBytesInGroup1 + 1;\n // numDataBytesInGroup1 = 66 / 5 = 13\n const numDataBytesInGroup1 = Math.floor(numDataBytes / numRSBlocks);\n // numDataBytesInGroup2 = 13 + 1 = 14\n const numDataBytesInGroup2 = numDataBytesInGroup1 + 1;\n // numEcBytesInGroup1 = 39 - 13 = 26\n const numEcBytesInGroup1 = numTotalBytesInGroup1 - numDataBytesInGroup1;\n // numEcBytesInGroup2 = 40 - 14 = 26\n const numEcBytesInGroup2 = numTotalBytesInGroup2 - numDataBytesInGroup2;\n // Sanity checks.\n // 26 = 26\n if (numEcBytesInGroup1 !== numEcBytesInGroup2) {\n throw new WriterException('EC bytes mismatch');\n }\n // 5 = 4 + 1.\n if (numRSBlocks !== numRsBlocksInGroup1 + numRsBlocksInGroup2) {\n throw new WriterException('RS blocks mismatch');\n }\n // 196 = (13 + 26) * 4 + (14 + 26) * 1\n if (numTotalBytes !==\n ((numDataBytesInGroup1 + numEcBytesInGroup1) *\n numRsBlocksInGroup1) +\n ((numDataBytesInGroup2 + numEcBytesInGroup2) *\n numRsBlocksInGroup2)) {\n throw new WriterException('Total bytes mismatch');\n }\n if (blockID < numRsBlocksInGroup1) {\n numDataBytesInBlock[0] = numDataBytesInGroup1;\n numECBytesInBlock[0] = numEcBytesInGroup1;\n }\n else {\n numDataBytesInBlock[0] = numDataBytesInGroup2;\n numECBytesInBlock[0] = numEcBytesInGroup2;\n }\n }\n /**\n * Interleave \"bits\" with corresponding error correction bytes. On success, store the result in\n * \"result\". The interleave rule is complicated. See 8.6 of JISX0510:2004 (p.37) for details.\n */\n static interleaveWithECBytes(bits, numTotalBytes /*int*/, numDataBytes /*int*/, numRSBlocks /*int*/) {\n // \"bits\" must have \"getNumDataBytes\" bytes of data.\n if (bits.getSizeInBytes() !== numDataBytes) {\n throw new WriterException('Number of bits and data bytes does not match');\n }\n // Step 1. Divide data bytes into blocks and generate error correction bytes for them. We'll\n // store the divided data bytes blocks and error correction bytes blocks into \"blocks\".\n let dataBytesOffset = 0;\n let maxNumDataBytes = 0;\n let maxNumEcBytes = 0;\n // Since, we know the number of reedsolmon blocks, we can initialize the vector with the number.\n const blocks = new Array(); // new Array(numRSBlocks)\n for (let i = 0; i < numRSBlocks; ++i) {\n const numDataBytesInBlock = new Int32Array(1);\n const numEcBytesInBlock = new Int32Array(1);\n Encoder.getNumDataBytesAndNumECBytesForBlockID(numTotalBytes, numDataBytes, numRSBlocks, i, numDataBytesInBlock, numEcBytesInBlock);\n const size = numDataBytesInBlock[0];\n const dataBytes = new Uint8Array(size);\n bits.toBytes(8 * dataBytesOffset, dataBytes, 0, size);\n const ecBytes = Encoder.generateECBytes(dataBytes, numEcBytesInBlock[0]);\n blocks.push(new BlockPair(dataBytes, ecBytes));\n maxNumDataBytes = Math.max(maxNumDataBytes, size);\n maxNumEcBytes = Math.max(maxNumEcBytes, ecBytes.length);\n dataBytesOffset += numDataBytesInBlock[0];\n }\n if (numDataBytes !== dataBytesOffset) {\n throw new WriterException('Data bytes does not match offset');\n }\n const result = new BitArray();\n // First, place data blocks.\n for (let i = 0; i < maxNumDataBytes; ++i) {\n for (const block of blocks) {\n const dataBytes = block.getDataBytes();\n if (i < dataBytes.length) {\n result.appendBits(dataBytes[i], 8);\n }\n }\n }\n // Then, place error correction blocks.\n for (let i = 0; i < maxNumEcBytes; ++i) {\n for (const block of blocks) {\n const ecBytes = block.getErrorCorrectionBytes();\n if (i < ecBytes.length) {\n result.appendBits(ecBytes[i], 8);\n }\n }\n }\n if (numTotalBytes !== result.getSizeInBytes()) { // Should be same.\n throw new WriterException('Interleaving error: ' + numTotalBytes + ' and ' +\n result.getSizeInBytes() + ' differ.');\n }\n return result;\n }\n static generateECBytes(dataBytes, numEcBytesInBlock /*int*/) {\n const numDataBytes = dataBytes.length;\n const toEncode = new Int32Array(numDataBytes + numEcBytesInBlock); // int[numDataBytes + numEcBytesInBlock]\n for (let i = 0; i < numDataBytes; i++) {\n toEncode[i] = dataBytes[i] & 0xFF;\n }\n new ReedSolomonEncoder(GenericGF.QR_CODE_FIELD_256).encode(toEncode, numEcBytesInBlock);\n const ecBytes = new Uint8Array(numEcBytesInBlock);\n for (let i = 0; i < numEcBytesInBlock; i++) {\n ecBytes[i] = /*(byte) */ toEncode[numDataBytes + i];\n }\n return ecBytes;\n }\n /**\n * Append mode info. On success, store the result in \"bits\".\n */\n static appendModeInfo(mode, bits) {\n bits.appendBits(mode.getBits(), 4);\n }\n /**\n * Append length info. On success, store the result in \"bits\".\n */\n static appendLengthInfo(numLetters /*int*/, version, mode, bits) {\n const numBits = mode.getCharacterCountBits(version);\n if (numLetters >= (1 << numBits)) {\n throw new WriterException(numLetters + ' is bigger than ' + ((1 << numBits) - 1));\n }\n bits.appendBits(numLetters, numBits);\n }\n /**\n * Append \"bytes\" in \"mode\" mode (encoding) into \"bits\". On success, store the result in \"bits\".\n */\n static appendBytes(content, mode, bits, encoding) {\n switch (mode) {\n case Mode$1.NUMERIC:\n Encoder.appendNumericBytes(content, bits);\n break;\n case Mode$1.ALPHANUMERIC:\n Encoder.appendAlphanumericBytes(content, bits);\n break;\n case Mode$1.BYTE:\n Encoder.append8BitBytes(content, bits, encoding);\n break;\n case Mode$1.KANJI:\n Encoder.appendKanjiBytes(content, bits);\n break;\n default:\n throw new WriterException('Invalid mode: ' + mode);\n }\n }\n static getDigit(singleCharacter) {\n return singleCharacter.charCodeAt(0) - 48;\n }\n static isDigit(singleCharacter) {\n const cn = Encoder.getDigit(singleCharacter);\n return cn >= 0 && cn <= 9;\n }\n static appendNumericBytes(content, bits) {\n const length = content.length;\n let i = 0;\n while (i < length) {\n const num1 = Encoder.getDigit(content.charAt(i));\n if (i + 2 < length) {\n // Encode three numeric letters in ten bits.\n const num2 = Encoder.getDigit(content.charAt(i + 1));\n const num3 = Encoder.getDigit(content.charAt(i + 2));\n bits.appendBits(num1 * 100 + num2 * 10 + num3, 10);\n i += 3;\n }\n else if (i + 1 < length) {\n // Encode two numeric letters in seven bits.\n const num2 = Encoder.getDigit(content.charAt(i + 1));\n bits.appendBits(num1 * 10 + num2, 7);\n i += 2;\n }\n else {\n // Encode one numeric letter in four bits.\n bits.appendBits(num1, 4);\n i++;\n }\n }\n }\n static appendAlphanumericBytes(content, bits) {\n const length = content.length;\n let i = 0;\n while (i < length) {\n const code1 = Encoder.getAlphanumericCode(content.charCodeAt(i));\n if (code1 === -1) {\n throw new WriterException();\n }\n if (i + 1 < length) {\n const code2 = Encoder.getAlphanumericCode(content.charCodeAt(i + 1));\n if (code2 === -1) {\n throw new WriterException();\n }\n // Encode two alphanumeric letters in 11 bits.\n bits.appendBits(code1 * 45 + code2, 11);\n i += 2;\n }\n else {\n // Encode one alphanumeric letter in six bits.\n bits.appendBits(code1, 6);\n i++;\n }\n }\n }\n static append8BitBytes(content, bits, encoding) {\n let bytes;\n try {\n bytes = StringEncoding.encode(content, encoding);\n }\n catch (uee /*: UnsupportedEncodingException*/) {\n throw new WriterException(uee);\n }\n for (let i = 0, length = bytes.length; i !== length; i++) {\n const b = bytes[i];\n bits.appendBits(b, 8);\n }\n }\n /**\n * @throws WriterException\n */\n static appendKanjiBytes(content, bits) {\n let bytes;\n try {\n bytes = StringEncoding.encode(content, CharacterSetECI.SJIS);\n }\n catch (uee /*: UnsupportedEncodingException*/) {\n throw new WriterException(uee);\n }\n const length = bytes.length;\n for (let i = 0; i < length; i += 2) {\n const byte1 = bytes[i] & 0xFF;\n const byte2 = bytes[i + 1] & 0xFF;\n const code = ((byte1 << 8) & 0xFFFFFFFF) | byte2;\n let subtracted = -1;\n if (code >= 0x8140 && code <= 0x9ffc) {\n subtracted = code - 0x8140;\n }\n else if (code >= 0xe040 && code <= 0xebbf) {\n subtracted = code - 0xc140;\n }\n if (subtracted === -1) {\n throw new WriterException('Invalid byte sequence');\n }\n const encoded = ((subtracted >> 8) * 0xc0) + (subtracted & 0xff);\n bits.appendBits(encoded, 13);\n }\n }\n static appendECI(eci, bits) {\n bits.appendBits(Mode$1.ECI.getBits(), 4);\n // This is correct for values up to 127, which is all we need now.\n bits.appendBits(eci.getValue(), 8);\n }\n }\n // The original table is defined in the table 5 of JISX0510:2004 (p.19).\n Encoder.ALPHANUMERIC_TABLE = Int32Array.from([\n -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n 36, -1, -1, -1, 37, 38, -1, -1, -1, -1, 39, 40, -1, 41, 42, 43,\n 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 44, -1, -1, -1, -1, -1,\n -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,\n 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1,\n ]);\n Encoder.DEFAULT_BYTE_MODE_ENCODING = CharacterSetECI.UTF8.getName(); // \"ISO-8859-1\"\n\n /**\n * @deprecated Moving to @zxing/browser\n */\n class BrowserQRCodeSvgWriter {\n /**\n * Writes and renders a QRCode SVG element.\n *\n * @param contents\n * @param width\n * @param height\n * @param hints\n */\n write(contents, width, height, hints = null) {\n if (contents.length === 0) {\n throw new IllegalArgumentException('Found empty contents');\n }\n // if (format != BarcodeFormat.QR_CODE) {\n // throw new IllegalArgumentException(\"Can only encode QR_CODE, but got \" + format)\n // }\n if (width < 0 || height < 0) {\n throw new IllegalArgumentException('Requested dimensions are too small: ' + width + 'x' + height);\n }\n let errorCorrectionLevel = ErrorCorrectionLevel.L;\n let quietZone = BrowserQRCodeSvgWriter.QUIET_ZONE_SIZE;\n if (hints !== null) {\n if (undefined !== hints.get(EncodeHintType$1.ERROR_CORRECTION)) {\n errorCorrectionLevel = ErrorCorrectionLevel.fromString(hints.get(EncodeHintType$1.ERROR_CORRECTION).toString());\n }\n if (undefined !== hints.get(EncodeHintType$1.MARGIN)) {\n quietZone = Number.parseInt(hints.get(EncodeHintType$1.MARGIN).toString(), 10);\n }\n }\n const code = Encoder.encode(contents, errorCorrectionLevel, hints);\n return this.renderResult(code, width, height, quietZone);\n }\n /**\n * Renders the result and then appends it to the DOM.\n */\n writeToDom(containerElement, contents, width, height, hints = null) {\n if (typeof containerElement === 'string') {\n containerElement = document.querySelector(containerElement);\n }\n const svgElement = this.write(contents, width, height, hints);\n if (containerElement)\n containerElement.appendChild(svgElement);\n }\n /**\n * Note that the input matrix uses 0 == white, 1 == black.\n * The output matrix uses 0 == black, 255 == white (i.e. an 8 bit greyscale bitmap).\n */\n renderResult(code, width /*int*/, height /*int*/, quietZone /*int*/) {\n const input = code.getMatrix();\n if (input === null) {\n throw new IllegalStateException();\n }\n const inputWidth = input.getWidth();\n const inputHeight = input.getHeight();\n const qrWidth = inputWidth + (quietZone * 2);\n const qrHeight = inputHeight + (quietZone * 2);\n const outputWidth = Math.max(width, qrWidth);\n const outputHeight = Math.max(height, qrHeight);\n const multiple = Math.min(Math.floor(outputWidth / qrWidth), Math.floor(outputHeight / qrHeight));\n // Padding includes both the quiet zone and the extra white pixels to accommodate the requested\n // dimensions. For example, if input is 25x25 the QR will be 33x33 including the quiet zone.\n // If the requested size is 200x160, the multiple will be 4, for a QR of 132x132. These will\n // handle all the padding from 100x100 (the actual QR) up to 200x160.\n const leftPadding = Math.floor((outputWidth - (inputWidth * multiple)) / 2);\n const topPadding = Math.floor((outputHeight - (inputHeight * multiple)) / 2);\n const svgElement = this.createSVGElement(outputWidth, outputHeight);\n for (let inputY = 0, outputY = topPadding; inputY < inputHeight; inputY++, outputY += multiple) {\n // Write the contents of this row of the barcode\n for (let inputX = 0, outputX = leftPadding; inputX < inputWidth; inputX++, outputX += multiple) {\n if (input.get(inputX, inputY) === 1) {\n const svgRectElement = this.createSvgRectElement(outputX, outputY, multiple, multiple);\n svgElement.appendChild(svgRectElement);\n }\n }\n }\n return svgElement;\n }\n /**\n * Creates a SVG element.\n *\n * @param w SVG's width attribute\n * @param h SVG's height attribute\n */\n createSVGElement(w, h) {\n const svgElement = document.createElementNS(BrowserQRCodeSvgWriter.SVG_NS, 'svg');\n svgElement.setAttributeNS(null, 'height', w.toString());\n svgElement.setAttributeNS(null, 'width', h.toString());\n return svgElement;\n }\n /**\n * Creates a SVG rect element.\n *\n * @param x Element's x coordinate\n * @param y Element's y coordinate\n * @param w Element's width attribute\n * @param h Element's height attribute\n */\n createSvgRectElement(x, y, w, h) {\n const rect = document.createElementNS(BrowserQRCodeSvgWriter.SVG_NS, 'rect');\n rect.setAttributeNS(null, 'x', x.toString());\n rect.setAttributeNS(null, 'y', y.toString());\n rect.setAttributeNS(null, 'height', w.toString());\n rect.setAttributeNS(null, 'width', h.toString());\n rect.setAttributeNS(null, 'fill', '#000000');\n return rect;\n }\n }\n BrowserQRCodeSvgWriter.QUIET_ZONE_SIZE = 4;\n /**\n * SVG markup NameSpace\n */\n BrowserQRCodeSvgWriter.SVG_NS = 'http://www.w3.org/2000/svg';\n\n /*import java.util.Map;*/\n /**\n * This object renders a QR Code as a BitMatrix 2D array of greyscale values.\n *\n * @author dswitkin@google.com (Daniel Switkin)\n */\n class QRCodeWriter {\n /*@Override*/\n // public encode(contents: string, format: BarcodeFormat, width: number /*int*/, height: number /*int*/): BitMatrix\n // /*throws WriterException */ {\n // return encode(contents, format, width, height, null)\n // }\n /*@Override*/\n encode(contents, format, width /*int*/, height /*int*/, hints) {\n if (contents.length === 0) {\n throw new IllegalArgumentException('Found empty contents');\n }\n if (format !== BarcodeFormat$1.QR_CODE) {\n throw new IllegalArgumentException('Can only encode QR_CODE, but got ' + format);\n }\n if (width < 0 || height < 0) {\n throw new IllegalArgumentException(`Requested dimensions are too small: ${width}x${height}`);\n }\n let errorCorrectionLevel = ErrorCorrectionLevel.L;\n let quietZone = QRCodeWriter.QUIET_ZONE_SIZE;\n if (hints !== null) {\n if (undefined !== hints.get(EncodeHintType$1.ERROR_CORRECTION)) {\n errorCorrectionLevel = ErrorCorrectionLevel.fromString(hints.get(EncodeHintType$1.ERROR_CORRECTION).toString());\n }\n if (undefined !== hints.get(EncodeHintType$1.MARGIN)) {\n quietZone = Number.parseInt(hints.get(EncodeHintType$1.MARGIN).toString(), 10);\n }\n }\n const code = Encoder.encode(contents, errorCorrectionLevel, hints);\n return QRCodeWriter.renderResult(code, width, height, quietZone);\n }\n // Note that the input matrix uses 0 == white, 1 == black, while the output matrix uses\n // 0 == black, 255 == white (i.e. an 8 bit greyscale bitmap).\n static renderResult(code, width /*int*/, height /*int*/, quietZone /*int*/) {\n const input = code.getMatrix();\n if (input === null) {\n throw new IllegalStateException();\n }\n const inputWidth = input.getWidth();\n const inputHeight = input.getHeight();\n const qrWidth = inputWidth + (quietZone * 2);\n const qrHeight = inputHeight + (quietZone * 2);\n const outputWidth = Math.max(width, qrWidth);\n const outputHeight = Math.max(height, qrHeight);\n const multiple = Math.min(Math.floor(outputWidth / qrWidth), Math.floor(outputHeight / qrHeight));\n // Padding includes both the quiet zone and the extra white pixels to accommodate the requested\n // dimensions. For example, if input is 25x25 the QR will be 33x33 including the quiet zone.\n // If the requested size is 200x160, the multiple will be 4, for a QR of 132x132. These will\n // handle all the padding from 100x100 (the actual QR) up to 200x160.\n const leftPadding = Math.floor((outputWidth - (inputWidth * multiple)) / 2);\n const topPadding = Math.floor((outputHeight - (inputHeight * multiple)) / 2);\n const output = new BitMatrix(outputWidth, outputHeight);\n for (let inputY = 0, outputY = topPadding; inputY < inputHeight; inputY++, outputY += multiple) {\n // Write the contents of this row of the barcode\n for (let inputX = 0, outputX = leftPadding; inputX < inputWidth; inputX++, outputX += multiple) {\n if (input.get(inputX, inputY) === 1) {\n output.setRegion(outputX, outputY, multiple, multiple);\n }\n }\n }\n return output;\n }\n }\n QRCodeWriter.QUIET_ZONE_SIZE = 4;\n\n /*import java.util.Map;*/\n /**\n * This is a factory class which finds the appropriate Writer subclass for the BarcodeFormat\n * requested and encodes the barcode with the supplied contents.\n *\n * @author dswitkin@google.com (Daniel Switkin)\n */\n class MultiFormatWriter {\n /*@Override*/\n // public encode(contents: string,\n // format: BarcodeFormat,\n // width: number /*int*/,\n // height: number /*int*/): BitMatrix /*throws WriterException */ {\n // return encode(contents, format, width, height, null)\n // }\n /*@Override*/\n encode(contents, format, width /*int*/, height /*int*/, hints) {\n let writer;\n switch (format) {\n // case BarcodeFormat.EAN_8:\n // writer = new EAN8Writer()\n // break\n // case BarcodeFormat.UPC_E:\n // writer = new UPCEWriter()\n // break\n // case BarcodeFormat.EAN_13:\n // writer = new EAN13Writer()\n // break\n // case BarcodeFormat.UPC_A:\n // writer = new UPCAWriter()\n // break\n case BarcodeFormat$1.QR_CODE:\n writer = new QRCodeWriter();\n break;\n // case BarcodeFormat.CODE_39:\n // writer = new Code39Writer()\n // break\n // case BarcodeFormat.CODE_93:\n // writer = new Code93Writer()\n // break\n // case BarcodeFormat.CODE_128:\n // writer = new Code128Writer()\n // break\n // case BarcodeFormat.ITF:\n // writer = new ITFWriter()\n // break\n // case BarcodeFormat.PDF_417:\n // writer = new PDF417Writer()\n // break\n // case BarcodeFormat.CODABAR:\n // writer = new CodaBarWriter()\n // break\n // case BarcodeFormat.DATA_MATRIX:\n // writer = new DataMatrixWriter()\n // break\n // case BarcodeFormat.AZTEC:\n // writer = new AztecWriter()\n // break\n default:\n throw new IllegalArgumentException('No encoder available for format ' + format);\n }\n return writer.encode(contents, format, width, height, hints);\n }\n }\n\n /*\n * Copyright 2009 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n /**\n * This object extends LuminanceSource around an array of YUV data returned from the camera driver,\n * with the option to crop to a rectangle within the full data. This can be used to exclude\n * superfluous pixels around the perimeter and speed up decoding.\n *\n * It works for any pixel format where the Y channel is planar and appears first, including\n * YCbCr_420_SP and YCbCr_422_SP.\n *\n * @author dswitkin@google.com (Daniel Switkin)\n */\n class PlanarYUVLuminanceSource extends LuminanceSource {\n constructor(yuvData, dataWidth /*int*/, dataHeight /*int*/, left /*int*/, top /*int*/, width /*int*/, height /*int*/, reverseHorizontal) {\n super(width, height);\n this.yuvData = yuvData;\n this.dataWidth = dataWidth;\n this.dataHeight = dataHeight;\n this.left = left;\n this.top = top;\n if (left + width > dataWidth || top + height > dataHeight) {\n throw new IllegalArgumentException('Crop rectangle does not fit within image data.');\n }\n if (reverseHorizontal) {\n this.reverseHorizontal(width, height);\n }\n }\n /*@Override*/\n getRow(y /*int*/, row) {\n if (y < 0 || y >= this.getHeight()) {\n throw new IllegalArgumentException('Requested row is outside the image: ' + y);\n }\n const width = this.getWidth();\n if (row === null || row === undefined || row.length < width) {\n row = new Uint8ClampedArray(width);\n }\n const offset = (y + this.top) * this.dataWidth + this.left;\n System.arraycopy(this.yuvData, offset, row, 0, width);\n return row;\n }\n /*@Override*/\n getMatrix() {\n const width = this.getWidth();\n const height = this.getHeight();\n // If the caller asks for the entire underlying image, save the copy and give them the\n // original data. The docs specifically warn that result.length must be ignored.\n if (width === this.dataWidth && height === this.dataHeight) {\n return this.yuvData;\n }\n const area = width * height;\n const matrix = new Uint8ClampedArray(area);\n let inputOffset = this.top * this.dataWidth + this.left;\n // If the width matches the full width of the underlying data, perform a single copy.\n if (width === this.dataWidth) {\n System.arraycopy(this.yuvData, inputOffset, matrix, 0, area);\n return matrix;\n }\n // Otherwise copy one cropped row at a time.\n for (let y = 0; y < height; y++) {\n const outputOffset = y * width;\n System.arraycopy(this.yuvData, inputOffset, matrix, outputOffset, width);\n inputOffset += this.dataWidth;\n }\n return matrix;\n }\n /*@Override*/\n isCropSupported() {\n return true;\n }\n /*@Override*/\n crop(left /*int*/, top /*int*/, width /*int*/, height /*int*/) {\n return new PlanarYUVLuminanceSource(this.yuvData, this.dataWidth, this.dataHeight, this.left + left, this.top + top, width, height, false);\n }\n renderThumbnail() {\n const width = this.getWidth() / PlanarYUVLuminanceSource.THUMBNAIL_SCALE_FACTOR;\n const height = this.getHeight() / PlanarYUVLuminanceSource.THUMBNAIL_SCALE_FACTOR;\n const pixels = new Int32Array(width * height);\n const yuv = this.yuvData;\n let inputOffset = this.top * this.dataWidth + this.left;\n for (let y = 0; y < height; y++) {\n const outputOffset = y * width;\n for (let x = 0; x < width; x++) {\n const grey = yuv[inputOffset + x * PlanarYUVLuminanceSource.THUMBNAIL_SCALE_FACTOR] & 0xff;\n pixels[outputOffset + x] = 0xFF000000 | (grey * 0x00010101);\n }\n inputOffset += this.dataWidth * PlanarYUVLuminanceSource.THUMBNAIL_SCALE_FACTOR;\n }\n return pixels;\n }\n /**\n * @return width of image from {@link #renderThumbnail()}\n */\n getThumbnailWidth() {\n return this.getWidth() / PlanarYUVLuminanceSource.THUMBNAIL_SCALE_FACTOR;\n }\n /**\n * @return height of image from {@link #renderThumbnail()}\n */\n getThumbnailHeight() {\n return this.getHeight() / PlanarYUVLuminanceSource.THUMBNAIL_SCALE_FACTOR;\n }\n reverseHorizontal(width /*int*/, height /*int*/) {\n const yuvData = this.yuvData;\n for (let y = 0, rowStart = this.top * this.dataWidth + this.left; y < height; y++, rowStart += this.dataWidth) {\n const middle = rowStart + width / 2;\n for (let x1 = rowStart, x2 = rowStart + width - 1; x1 < middle; x1++, x2--) {\n const temp = yuvData[x1];\n yuvData[x1] = yuvData[x2];\n yuvData[x2] = temp;\n }\n }\n }\n invert() {\n return new InvertedLuminanceSource(this);\n }\n }\n PlanarYUVLuminanceSource.THUMBNAIL_SCALE_FACTOR = 2;\n\n /*\n * Copyright 2009 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n /**\n * This class is used to help decode images from files which arrive as RGB data from\n * an ARGB pixel array. It does not support rotation.\n *\n * @author dswitkin@google.com (Daniel Switkin)\n * @author Betaminos\n */\n class RGBLuminanceSource extends LuminanceSource {\n constructor(luminances, width /*int*/, height /*int*/, dataWidth /*int*/, dataHeight /*int*/, left /*int*/, top /*int*/) {\n super(width, height);\n this.dataWidth = dataWidth;\n this.dataHeight = dataHeight;\n this.left = left;\n this.top = top;\n if (luminances.BYTES_PER_ELEMENT === 4) { // Int32Array\n const size = width * height;\n const luminancesUint8Array = new Uint8ClampedArray(size);\n for (let offset = 0; offset < size; offset++) {\n const pixel = luminances[offset];\n const r = (pixel >> 16) & 0xff; // red\n const g2 = (pixel >> 7) & 0x1fe; // 2 * green\n const b = pixel & 0xff; // blue\n // Calculate green-favouring average cheaply\n luminancesUint8Array[offset] = /*(byte) */ ((r + g2 + b) / 4) & 0xFF;\n }\n this.luminances = luminancesUint8Array;\n }\n else {\n this.luminances = luminances;\n }\n if (undefined === dataWidth) {\n this.dataWidth = width;\n }\n if (undefined === dataHeight) {\n this.dataHeight = height;\n }\n if (undefined === left) {\n this.left = 0;\n }\n if (undefined === top) {\n this.top = 0;\n }\n if (this.left + width > this.dataWidth || this.top + height > this.dataHeight) {\n throw new IllegalArgumentException('Crop rectangle does not fit within image data.');\n }\n }\n /*@Override*/\n getRow(y /*int*/, row) {\n if (y < 0 || y >= this.getHeight()) {\n throw new IllegalArgumentException('Requested row is outside the image: ' + y);\n }\n const width = this.getWidth();\n if (row === null || row === undefined || row.length < width) {\n row = new Uint8ClampedArray(width);\n }\n const offset = (y + this.top) * this.dataWidth + this.left;\n System.arraycopy(this.luminances, offset, row, 0, width);\n return row;\n }\n /*@Override*/\n getMatrix() {\n const width = this.getWidth();\n const height = this.getHeight();\n // If the caller asks for the entire underlying image, save the copy and give them the\n // original data. The docs specifically warn that result.length must be ignored.\n if (width === this.dataWidth && height === this.dataHeight) {\n return this.luminances;\n }\n const area = width * height;\n const matrix = new Uint8ClampedArray(area);\n let inputOffset = this.top * this.dataWidth + this.left;\n // If the width matches the full width of the underlying data, perform a single copy.\n if (width === this.dataWidth) {\n System.arraycopy(this.luminances, inputOffset, matrix, 0, area);\n return matrix;\n }\n // Otherwise copy one cropped row at a time.\n for (let y = 0; y < height; y++) {\n const outputOffset = y * width;\n System.arraycopy(this.luminances, inputOffset, matrix, outputOffset, width);\n inputOffset += this.dataWidth;\n }\n return matrix;\n }\n /*@Override*/\n isCropSupported() {\n return true;\n }\n /*@Override*/\n crop(left /*int*/, top /*int*/, width /*int*/, height /*int*/) {\n return new RGBLuminanceSource(this.luminances, width, height, this.dataWidth, this.dataHeight, this.left + left, this.top + top);\n }\n invert() {\n return new InvertedLuminanceSource(this);\n }\n }\n\n /**\n * Just to make a shortcut between Java code and TS code.\n */\n class Charset extends CharacterSetECI {\n static forName(name) {\n return this.getCharacterSetECIByName(name);\n }\n }\n\n /**\n * Just to make a shortcut between Java code and TS code.\n */\n class StandardCharsets {\n }\n StandardCharsets.ISO_8859_1 = CharacterSetECI.ISO8859_1;\n\n /*\n * Copyright 2013 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n /**\n * Aztec 2D code representation\n *\n * @author Rustam Abdullaev\n */\n /*public final*/ class AztecCode {\n /**\n * @return {@code true} if compact instead of full mode\n */\n isCompact() {\n return this.compact;\n }\n setCompact(compact) {\n this.compact = compact;\n }\n /**\n * @return size in pixels (width and height)\n */\n getSize() {\n return this.size;\n }\n setSize(size) {\n this.size = size;\n }\n /**\n * @return number of levels\n */\n getLayers() {\n return this.layers;\n }\n setLayers(layers) {\n this.layers = layers;\n }\n /**\n * @return number of data codewords\n */\n getCodeWords() {\n return this.codeWords;\n }\n setCodeWords(codeWords) {\n this.codeWords = codeWords;\n }\n /**\n * @return the symbol image\n */\n getMatrix() {\n return this.matrix;\n }\n setMatrix(matrix) {\n this.matrix = matrix;\n }\n }\n\n class Collections {\n /**\n * The singletonList(T) method is used to return an immutable list containing only the specified object.\n */\n static singletonList(item) {\n return [item];\n }\n /**\n * The min(Collection, Comparator) method is used to return the minimum element of the given collection, according to the order induced by the specified comparator.\n */\n static min(collection, comparator) {\n return collection.sort(comparator)[0];\n }\n }\n\n /*\n * Copyright 2013 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n class Token {\n constructor(previous) {\n this.previous = previous;\n }\n getPrevious() {\n return this.previous;\n }\n }\n\n /*\n * Copyright 2013 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n /*final*/ class SimpleToken extends Token {\n constructor(previous, value, bitCount) {\n super(previous);\n this.value = value;\n this.bitCount = bitCount;\n }\n /**\n * @Override\n */\n appendTo(bitArray, text) {\n bitArray.appendBits(this.value, this.bitCount);\n }\n add(value, bitCount) {\n return new SimpleToken(this, value, bitCount);\n }\n addBinaryShift(start, byteCount) {\n // no-op can't binary shift a simple token\n console.warn('addBinaryShift on SimpleToken, this simply returns a copy of this token');\n return new SimpleToken(this, start, byteCount);\n }\n /**\n * @Override\n */\n toString() {\n let value = this.value & ((1 << this.bitCount) - 1);\n value |= 1 << this.bitCount;\n return '<' + Integer.toBinaryString(value | (1 << this.bitCount)).substring(1) + '>';\n }\n }\n\n /*\n * Copyright 2013 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n /*final*/ class BinaryShiftToken extends SimpleToken {\n constructor(previous, binaryShiftStart, binaryShiftByteCount) {\n super(previous, 0, 0);\n this.binaryShiftStart = binaryShiftStart;\n this.binaryShiftByteCount = binaryShiftByteCount;\n }\n /**\n * @Override\n */\n appendTo(bitArray, text) {\n for (let i = 0; i < this.binaryShiftByteCount; i++) {\n if (i === 0 || (i === 31 && this.binaryShiftByteCount <= 62)) {\n // We need a header before the first character, and before\n // character 31 when the total byte code is <= 62\n bitArray.appendBits(31, 5); // BINARY_SHIFT\n if (this.binaryShiftByteCount > 62) {\n bitArray.appendBits(this.binaryShiftByteCount - 31, 16);\n }\n else if (i === 0) {\n // 1 <= binaryShiftByteCode <= 62\n bitArray.appendBits(Math.min(this.binaryShiftByteCount, 31), 5);\n }\n else {\n // 32 <= binaryShiftCount <= 62 and i == 31\n bitArray.appendBits(this.binaryShiftByteCount - 31, 5);\n }\n }\n bitArray.appendBits(text[this.binaryShiftStart + i], 8);\n }\n }\n addBinaryShift(start, byteCount) {\n // int bitCount = (byteCount * 8) + (byteCount <= 31 ? 10 : byteCount <= 62 ? 20 : 21);\n return new BinaryShiftToken(this, start, byteCount);\n }\n /**\n * @Override\n */\n toString() {\n return '<' + this.binaryShiftStart + '::' + (this.binaryShiftStart + this.binaryShiftByteCount - 1) + '>';\n }\n }\n\n function addBinaryShift(token, start, byteCount) {\n // int bitCount = (byteCount * 8) + (byteCount <= 31 ? 10 : byteCount <= 62 ? 20 : 21);\n return new BinaryShiftToken(token, start, byteCount);\n }\n function add(token, value, bitCount) {\n return new SimpleToken(token, value, bitCount);\n }\n\n const /*final*/ MODE_NAMES = [\n 'UPPER',\n 'LOWER',\n 'DIGIT',\n 'MIXED',\n 'PUNCT'\n ];\n const /*final*/ MODE_UPPER = 0; // 5 bits\n const /*final*/ MODE_LOWER = 1; // 5 bits\n const /*final*/ MODE_DIGIT = 2; // 4 bits\n const /*final*/ MODE_MIXED = 3; // 5 bits\n const /*final*/ MODE_PUNCT = 4; // 5 bits\n const EMPTY_TOKEN = new SimpleToken(null, 0, 0);\n\n // The Latch Table shows, for each pair of Modes, the optimal method for\n // getting from one mode to another. In the worst possible case, this can\n // be up to 14 bits. In the best possible case, we are already there!\n // The high half-word of each entry gives the number of bits.\n // The low half-word of each entry are the actual bits necessary to change\n const LATCH_TABLE = [\n Int32Array.from([\n 0,\n (5 << 16) + 28,\n (5 << 16) + 30,\n (5 << 16) + 29,\n (10 << 16) + (29 << 5) + 30 // UPPER -> MIXED -> PUNCT\n ]),\n Int32Array.from([\n (9 << 16) + (30 << 4) + 14,\n 0,\n (5 << 16) + 30,\n (5 << 16) + 29,\n (10 << 16) + (29 << 5) + 30 // LOWER -> MIXED -> PUNCT\n ]),\n Int32Array.from([\n (4 << 16) + 14,\n (9 << 16) + (14 << 5) + 28,\n 0,\n (9 << 16) + (14 << 5) + 29,\n (14 << 16) + (14 << 10) + (29 << 5) + 30\n // DIGIT -> UPPER -> MIXED -> PUNCT\n ]),\n Int32Array.from([\n (5 << 16) + 29,\n (5 << 16) + 28,\n (10 << 16) + (29 << 5) + 30,\n 0,\n (5 << 16) + 30 // MIXED -> PUNCT\n ]),\n Int32Array.from([\n (5 << 16) + 31,\n (10 << 16) + (31 << 5) + 28,\n (10 << 16) + (31 << 5) + 30,\n (10 << 16) + (31 << 5) + 29,\n 0\n ])\n ];\n\n function static_SHIFT_TABLE(SHIFT_TABLE) {\n for (let table /*Int32Array*/ of SHIFT_TABLE) {\n Arrays.fill(table, -1);\n }\n SHIFT_TABLE[MODE_UPPER][MODE_PUNCT] = 0;\n SHIFT_TABLE[MODE_LOWER][MODE_PUNCT] = 0;\n SHIFT_TABLE[MODE_LOWER][MODE_UPPER] = 28;\n SHIFT_TABLE[MODE_MIXED][MODE_PUNCT] = 0;\n SHIFT_TABLE[MODE_DIGIT][MODE_PUNCT] = 0;\n SHIFT_TABLE[MODE_DIGIT][MODE_UPPER] = 15;\n return SHIFT_TABLE;\n }\n const /*final*/ SHIFT_TABLE = static_SHIFT_TABLE(Arrays.createInt32Array(6, 6)); // mode shift codes, per table\n\n /*\n * Copyright 2013 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n /**\n * State represents all information about a sequence necessary to generate the current output.\n * Note that a state is immutable.\n */\n /*final*/ class State {\n constructor(token, mode, binaryBytes, bitCount) {\n this.token = token;\n this.mode = mode;\n this.binaryShiftByteCount = binaryBytes;\n this.bitCount = bitCount;\n // Make sure we match the token\n // int binaryShiftBitCount = (binaryShiftByteCount * 8) +\n // (binaryShiftByteCount === 0 ? 0 :\n // binaryShiftByteCount <= 31 ? 10 :\n // binaryShiftByteCount <= 62 ? 20 : 21);\n // assert this.bitCount === token.getTotalBitCount() + binaryShiftBitCount;\n }\n getMode() {\n return this.mode;\n }\n getToken() {\n return this.token;\n }\n getBinaryShiftByteCount() {\n return this.binaryShiftByteCount;\n }\n getBitCount() {\n return this.bitCount;\n }\n // Create a new state representing this state with a latch to a (not\n // necessary different) mode, and then a code.\n latchAndAppend(mode, value) {\n // assert binaryShiftByteCount === 0;\n let bitCount = this.bitCount;\n let token = this.token;\n if (mode !== this.mode) {\n let latch = LATCH_TABLE[this.mode][mode];\n token = add(token, latch & 0xffff, latch >> 16);\n bitCount += latch >> 16;\n }\n let latchModeBitCount = mode === MODE_DIGIT ? 4 : 5;\n token = add(token, value, latchModeBitCount);\n return new State(token, mode, 0, bitCount + latchModeBitCount);\n }\n // Create a new state representing this state, with a temporary shift\n // to a different mode to output a single value.\n shiftAndAppend(mode, value) {\n // assert binaryShiftByteCount === 0 && this.mode !== mode;\n let token = this.token;\n let thisModeBitCount = this.mode === MODE_DIGIT ? 4 : 5;\n // Shifts exist only to UPPER and PUNCT, both with tokens size 5.\n token = add(token, SHIFT_TABLE[this.mode][mode], thisModeBitCount);\n token = add(token, value, 5);\n return new State(token, this.mode, 0, this.bitCount + thisModeBitCount + 5);\n }\n // Create a new state representing this state, but an additional character\n // output in Binary Shift mode.\n addBinaryShiftChar(index) {\n let token = this.token;\n let mode = this.mode;\n let bitCount = this.bitCount;\n if (this.mode === MODE_PUNCT || this.mode === MODE_DIGIT) {\n // assert binaryShiftByteCount === 0;\n let latch = LATCH_TABLE[mode][MODE_UPPER];\n token = add(token, latch & 0xffff, latch >> 16);\n bitCount += latch >> 16;\n mode = MODE_UPPER;\n }\n let deltaBitCount = this.binaryShiftByteCount === 0 || this.binaryShiftByteCount === 31\n ? 18\n : this.binaryShiftByteCount === 62\n ? 9\n : 8;\n let result = new State(token, mode, this.binaryShiftByteCount + 1, bitCount + deltaBitCount);\n if (result.binaryShiftByteCount === 2047 + 31) {\n // The string is as long as it's allowed to be. We should end it.\n result = result.endBinaryShift(index + 1);\n }\n return result;\n }\n // Create the state identical to this one, but we are no longer in\n // Binary Shift mode.\n endBinaryShift(index) {\n if (this.binaryShiftByteCount === 0) {\n return this;\n }\n let token = this.token;\n token = addBinaryShift(token, index - this.binaryShiftByteCount, this.binaryShiftByteCount);\n // assert token.getTotalBitCount() === this.bitCount;\n return new State(token, this.mode, 0, this.bitCount);\n }\n // Returns true if \"this\" state is better (equal: or) to be in than \"that\"\n // state under all possible circumstances.\n isBetterThanOrEqualTo(other) {\n let newModeBitCount = this.bitCount + (LATCH_TABLE[this.mode][other.mode] >> 16);\n if (this.binaryShiftByteCount < other.binaryShiftByteCount) {\n // add additional B/S encoding cost of other, if any\n newModeBitCount +=\n State.calculateBinaryShiftCost(other) -\n State.calculateBinaryShiftCost(this);\n }\n else if (this.binaryShiftByteCount > other.binaryShiftByteCount &&\n other.binaryShiftByteCount > 0) {\n // maximum possible additional cost (it: h)\n newModeBitCount += 10;\n }\n return newModeBitCount <= other.bitCount;\n }\n toBitArray(text) {\n // Reverse the tokens, so that they are in the order that they should\n // be output\n let symbols = [];\n for (let token = this.endBinaryShift(text.length).token; token !== null; token = token.getPrevious()) {\n symbols.unshift(token);\n }\n let bitArray = new BitArray();\n // Add each token to the result.\n for (const symbol of symbols) {\n symbol.appendTo(bitArray, text);\n }\n // assert bitArray.getSize() === this.bitCount;\n return bitArray;\n }\n /**\n * @Override\n */\n toString() {\n return StringUtils.format('%s bits=%d bytes=%d', MODE_NAMES[this.mode], this.bitCount, this.binaryShiftByteCount);\n }\n static calculateBinaryShiftCost(state) {\n if (state.binaryShiftByteCount > 62) {\n return 21; // B/S with extended length\n }\n if (state.binaryShiftByteCount > 31) {\n return 20; // two B/S\n }\n if (state.binaryShiftByteCount > 0) {\n return 10; // one B/S\n }\n return 0;\n }\n }\n State.INITIAL_STATE = new State(EMPTY_TOKEN, MODE_UPPER, 0, 0);\n\n function static_CHAR_MAP(CHAR_MAP) {\n const spaceCharCode = StringUtils.getCharCode(' ');\n const pointCharCode = StringUtils.getCharCode('.');\n const commaCharCode = StringUtils.getCharCode(',');\n CHAR_MAP[MODE_UPPER][spaceCharCode] = 1;\n const zUpperCharCode = StringUtils.getCharCode('Z');\n const aUpperCharCode = StringUtils.getCharCode('A');\n for (let c = aUpperCharCode; c <= zUpperCharCode; c++) {\n CHAR_MAP[MODE_UPPER][c] = c - aUpperCharCode + 2;\n }\n CHAR_MAP[MODE_LOWER][spaceCharCode] = 1;\n const zLowerCharCode = StringUtils.getCharCode('z');\n const aLowerCharCode = StringUtils.getCharCode('a');\n for (let c = aLowerCharCode; c <= zLowerCharCode; c++) {\n CHAR_MAP[MODE_LOWER][c] = c - aLowerCharCode + 2;\n }\n CHAR_MAP[MODE_DIGIT][spaceCharCode] = 1;\n const nineCharCode = StringUtils.getCharCode('9');\n const zeroCharCode = StringUtils.getCharCode('0');\n for (let c = zeroCharCode; c <= nineCharCode; c++) {\n CHAR_MAP[MODE_DIGIT][c] = c - zeroCharCode + 2;\n }\n CHAR_MAP[MODE_DIGIT][commaCharCode] = 12;\n CHAR_MAP[MODE_DIGIT][pointCharCode] = 13;\n const mixedTable = [\n '\\x00',\n ' ',\n '\\x01',\n '\\x02',\n '\\x03',\n '\\x04',\n '\\x05',\n '\\x06',\n '\\x07',\n '\\b',\n '\\t',\n '\\n',\n '\\x0b',\n '\\f',\n '\\r',\n '\\x1b',\n '\\x1c',\n '\\x1d',\n '\\x1e',\n '\\x1f',\n '@',\n '\\\\',\n '^',\n '_',\n '`',\n '|',\n '~',\n '\\x7f'\n ];\n for (let i = 0; i < mixedTable.length; i++) {\n CHAR_MAP[MODE_MIXED][StringUtils.getCharCode(mixedTable[i])] = i;\n }\n const punctTable = [\n '\\x00',\n '\\r',\n '\\x00',\n '\\x00',\n '\\x00',\n '\\x00',\n '!',\n '\\'',\n '#',\n '$',\n '%',\n '&',\n '\\'',\n '(',\n ')',\n '*',\n '+',\n ',',\n '-',\n '.',\n '/',\n ':',\n ';',\n '<',\n '=',\n '>',\n '?',\n '[',\n ']',\n '{',\n '}'\n ];\n for (let i = 0; i < punctTable.length; i++) {\n if (StringUtils.getCharCode(punctTable[i]) > 0) {\n CHAR_MAP[MODE_PUNCT][StringUtils.getCharCode(punctTable[i])] = i;\n }\n }\n return CHAR_MAP;\n }\n const CHAR_MAP = static_CHAR_MAP(Arrays.createInt32Array(5, 256));\n\n /*\n * Copyright 2013 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n /**\n * This produces nearly optimal encodings of text into the first-level of\n * encoding used by Aztec code.\n *\n * It uses a dynamic algorithm. For each prefix of the string, it determines\n * a set of encodings that could lead to this prefix. We repeatedly add a\n * character and generate a new set of optimal encodings until we have read\n * through the entire input.\n *\n * @author Frank Yellin\n * @author Rustam Abdullaev\n */\n /*public final*/ class HighLevelEncoder {\n constructor(text) {\n this.text = text;\n }\n /**\n * @return text represented by this encoder encoded as a {@link BitArray}\n */\n encode() {\n const spaceCharCode = StringUtils.getCharCode(' ');\n const lineBreakCharCode = StringUtils.getCharCode('\\n');\n let states = Collections.singletonList(State.INITIAL_STATE);\n for (let index = 0; index < this.text.length; index++) {\n let pairCode;\n let nextChar = index + 1 < this.text.length ? this.text[index + 1] : 0;\n switch (this.text[index]) {\n case StringUtils.getCharCode('\\r'):\n pairCode = nextChar === lineBreakCharCode ? 2 : 0;\n break;\n case StringUtils.getCharCode('.'):\n pairCode = nextChar === spaceCharCode ? 3 : 0;\n break;\n case StringUtils.getCharCode(','):\n pairCode = nextChar === spaceCharCode ? 4 : 0;\n break;\n case StringUtils.getCharCode(':'):\n pairCode = nextChar === spaceCharCode ? 5 : 0;\n break;\n default:\n pairCode = 0;\n }\n if (pairCode > 0) {\n // We have one of the four special PUNCT pairs. Treat them specially.\n // Get a new set of states for the two new characters.\n states = HighLevelEncoder.updateStateListForPair(states, index, pairCode);\n index++;\n }\n else {\n // Get a new set of states for the new character.\n states = this.updateStateListForChar(states, index);\n }\n }\n // We are left with a set of states. Find the shortest one.\n const minState = Collections.min(states, (a, b) => {\n return a.getBitCount() - b.getBitCount();\n });\n // Convert it to a bit array, and return.\n return minState.toBitArray(this.text);\n }\n // We update a set of states for a new character by updating each state\n // for the new character, merging the results, and then removing the\n // non-optimal states.\n updateStateListForChar(states, index) {\n const result = [];\n for (let state /*State*/ of states) {\n this.updateStateForChar(state, index, result);\n }\n return HighLevelEncoder.simplifyStates(result);\n }\n // Return a set of states that represent the possible ways of updating this\n // state for the next character. The resulting set of states are added to\n // the \"result\" list.\n updateStateForChar(state, index, result) {\n let ch = (this.text[index] & 0xff);\n let charInCurrentTable = CHAR_MAP[state.getMode()][ch] > 0;\n let stateNoBinary = null;\n for (let mode /*int*/ = 0; mode <= MODE_PUNCT; mode++) {\n let charInMode = CHAR_MAP[mode][ch];\n if (charInMode > 0) {\n if (stateNoBinary == null) {\n // Only create stateNoBinary the first time it's required.\n stateNoBinary = state.endBinaryShift(index);\n }\n // Try generating the character by latching to its mode\n if (!charInCurrentTable ||\n mode === state.getMode() ||\n mode === MODE_DIGIT) {\n // If the character is in the current table, we don't want to latch to\n // any other mode except possibly digit (which uses only 4 bits). Any\n // other latch would be equally successful *after* this character, and\n // so wouldn't save any bits.\n const latchState = stateNoBinary.latchAndAppend(mode, charInMode);\n result.push(latchState);\n }\n // Try generating the character by switching to its mode.\n if (!charInCurrentTable &&\n SHIFT_TABLE[state.getMode()][mode] >= 0) {\n // It never makes sense to temporarily shift to another mode if the\n // character exists in the current mode. That can never save bits.\n const shiftState = stateNoBinary.shiftAndAppend(mode, charInMode);\n result.push(shiftState);\n }\n }\n }\n if (state.getBinaryShiftByteCount() > 0 ||\n CHAR_MAP[state.getMode()][ch] === 0) {\n // It's never worthwhile to go into binary shift mode if you're not already\n // in binary shift mode, and the character exists in your current mode.\n // That can never save bits over just outputting the char in the current mode.\n let binaryState = state.addBinaryShiftChar(index);\n result.push(binaryState);\n }\n }\n static updateStateListForPair(states, index, pairCode) {\n const result = [];\n for (let state /*State*/ of states) {\n this.updateStateForPair(state, index, pairCode, result);\n }\n return this.simplifyStates(result);\n }\n static updateStateForPair(state, index, pairCode, result) {\n let stateNoBinary = state.endBinaryShift(index);\n // Possibility 1. Latch to C.MODE_PUNCT, and then append this code\n result.push(stateNoBinary.latchAndAppend(MODE_PUNCT, pairCode));\n if (state.getMode() !== MODE_PUNCT) {\n // Possibility 2. Shift to C.MODE_PUNCT, and then append this code.\n // Every state except C.MODE_PUNCT (handled above) can shift\n result.push(stateNoBinary.shiftAndAppend(MODE_PUNCT, pairCode));\n }\n if (pairCode === 3 || pairCode === 4) {\n // both characters are in DIGITS. Sometimes better to just add two digits\n let digitState = stateNoBinary\n .latchAndAppend(MODE_DIGIT, 16 - pairCode) // period or comma in DIGIT\n .latchAndAppend(MODE_DIGIT, 1); // space in DIGIT\n result.push(digitState);\n }\n if (state.getBinaryShiftByteCount() > 0) {\n // It only makes sense to do the characters as binary if we're already\n // in binary mode.\n let binaryState = state\n .addBinaryShiftChar(index)\n .addBinaryShiftChar(index + 1);\n result.push(binaryState);\n }\n }\n static simplifyStates(states) {\n let result = [];\n for (const newState of states) {\n let add = true;\n for (const oldState of result) {\n if (oldState.isBetterThanOrEqualTo(newState)) {\n add = false;\n break;\n }\n if (newState.isBetterThanOrEqualTo(oldState)) {\n // iterator.remove();\n result = result.filter(x => x !== oldState); // remove old state\n }\n }\n if (add) {\n result.push(newState);\n }\n }\n return result;\n }\n }\n\n /*\n * Copyright 2013 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n // package com.google.zxing.aztec.encoder;\n // import com.google.zxing.common.BitArray;\n // import com.google.zxing.common.BitMatrix;\n // import com.google.zxing.common.reedsolomon.GenericGF;\n // import com.google.zxing.common.reedsolomon.ReedSolomonEncoder;\n /**\n * Generates Aztec 2D barcodes.\n *\n * @author Rustam Abdullaev\n */\n /*public final*/ class Encoder$1 {\n constructor() {\n }\n /**\n * Encodes the given binary content as an Aztec symbol\n *\n * @param data input data string\n * @return Aztec symbol matrix with metadata\n */\n static encodeBytes(data) {\n return Encoder$1.encode(data, Encoder$1.DEFAULT_EC_PERCENT, Encoder$1.DEFAULT_AZTEC_LAYERS);\n }\n /**\n * Encodes the given binary content as an Aztec symbol\n *\n * @param data input data string\n * @param minECCPercent minimal percentage of error check words (According to ISO/IEC 24778:2008,\n * a minimum of 23% + 3 words is recommended)\n * @param userSpecifiedLayers if non-zero, a user-specified value for the number of layers\n * @return Aztec symbol matrix with metadata\n */\n static encode(data, minECCPercent, userSpecifiedLayers) {\n // High-level encode\n let bits = new HighLevelEncoder(data).encode();\n // stuff bits and choose symbol size\n let eccBits = Integer.truncDivision((bits.getSize() * minECCPercent), 100) + 11;\n let totalSizeBits = bits.getSize() + eccBits;\n let compact;\n let layers;\n let totalBitsInLayer;\n let wordSize;\n let stuffedBits;\n if (userSpecifiedLayers !== Encoder$1.DEFAULT_AZTEC_LAYERS) {\n compact = userSpecifiedLayers < 0;\n layers = Math.abs(userSpecifiedLayers);\n if (layers > (compact ? Encoder$1.MAX_NB_BITS_COMPACT : Encoder$1.MAX_NB_BITS)) {\n throw new IllegalArgumentException(StringUtils.format('Illegal value %s for layers', userSpecifiedLayers));\n }\n totalBitsInLayer = Encoder$1.totalBitsInLayer(layers, compact);\n wordSize = Encoder$1.WORD_SIZE[layers];\n let usableBitsInLayers = totalBitsInLayer - (totalBitsInLayer % wordSize);\n stuffedBits = Encoder$1.stuffBits(bits, wordSize);\n if (stuffedBits.getSize() + eccBits > usableBitsInLayers) {\n throw new IllegalArgumentException('Data to large for user specified layer');\n }\n if (compact && stuffedBits.getSize() > wordSize * 64) {\n // Compact format only allows 64 data words, though C4 can hold more words than that\n throw new IllegalArgumentException('Data to large for user specified layer');\n }\n }\n else {\n wordSize = 0;\n stuffedBits = null;\n // We look at the possible table sizes in the order Compact1, Compact2, Compact3,\n // Compact4, Normal4,... Normal(i) for i < 4 isn't typically used since Compact(i+1)\n // is the same size, but has more data.\n for (let i /*int*/ = 0;; i++) {\n if (i > Encoder$1.MAX_NB_BITS) {\n throw new IllegalArgumentException('Data too large for an Aztec code');\n }\n compact = i <= 3;\n layers = compact ? i + 1 : i;\n totalBitsInLayer = Encoder$1.totalBitsInLayer(layers, compact);\n if (totalSizeBits > totalBitsInLayer) {\n continue;\n }\n // [Re]stuff the bits if this is the first opportunity, or if the\n // wordSize has changed\n if (stuffedBits == null || wordSize !== Encoder$1.WORD_SIZE[layers]) {\n wordSize = Encoder$1.WORD_SIZE[layers];\n stuffedBits = Encoder$1.stuffBits(bits, wordSize);\n }\n let usableBitsInLayers = totalBitsInLayer - (totalBitsInLayer % wordSize);\n if (compact && stuffedBits.getSize() > wordSize * 64) {\n // Compact format only allows 64 data words, though C4 can hold more words than that\n continue;\n }\n if (stuffedBits.getSize() + eccBits <= usableBitsInLayers) {\n break;\n }\n }\n }\n let messageBits = Encoder$1.generateCheckWords(stuffedBits, totalBitsInLayer, wordSize);\n // generate mode message\n let messageSizeInWords = stuffedBits.getSize() / wordSize;\n let modeMessage = Encoder$1.generateModeMessage(compact, layers, messageSizeInWords);\n // allocate symbol\n let baseMatrixSize = (compact ? 11 : 14) + layers * 4; // not including alignment lines\n let alignmentMap = new Int32Array(baseMatrixSize);\n let matrixSize;\n if (compact) {\n // no alignment marks in compact mode, alignmentMap is a no-op\n matrixSize = baseMatrixSize;\n for (let i /*int*/ = 0; i < alignmentMap.length; i++) {\n alignmentMap[i] = i;\n }\n }\n else {\n matrixSize = baseMatrixSize + 1 + 2 * Integer.truncDivision((Integer.truncDivision(baseMatrixSize, 2) - 1), 15);\n let origCenter = Integer.truncDivision(baseMatrixSize, 2);\n let center = Integer.truncDivision(matrixSize, 2);\n for (let i /*int*/ = 0; i < origCenter; i++) {\n let newOffset = i + Integer.truncDivision(i, 15);\n alignmentMap[origCenter - i - 1] = center - newOffset - 1;\n alignmentMap[origCenter + i] = center + newOffset + 1;\n }\n }\n let matrix = new BitMatrix(matrixSize);\n // draw data bits\n for (let i /*int*/ = 0, rowOffset = 0; i < layers; i++) {\n let rowSize = (layers - i) * 4 + (compact ? 9 : 12);\n for (let j /*int*/ = 0; j < rowSize; j++) {\n let columnOffset = j * 2;\n for (let k /*int*/ = 0; k < 2; k++) {\n if (messageBits.get(rowOffset + columnOffset + k)) {\n matrix.set(alignmentMap[i * 2 + k], alignmentMap[i * 2 + j]);\n }\n if (messageBits.get(rowOffset + rowSize * 2 + columnOffset + k)) {\n matrix.set(alignmentMap[i * 2 + j], alignmentMap[baseMatrixSize - 1 - i * 2 - k]);\n }\n if (messageBits.get(rowOffset + rowSize * 4 + columnOffset + k)) {\n matrix.set(alignmentMap[baseMatrixSize - 1 - i * 2 - k], alignmentMap[baseMatrixSize - 1 - i * 2 - j]);\n }\n if (messageBits.get(rowOffset + rowSize * 6 + columnOffset + k)) {\n matrix.set(alignmentMap[baseMatrixSize - 1 - i * 2 - j], alignmentMap[i * 2 + k]);\n }\n }\n }\n rowOffset += rowSize * 8;\n }\n // draw mode message\n Encoder$1.drawModeMessage(matrix, compact, matrixSize, modeMessage);\n // draw alignment marks\n if (compact) {\n Encoder$1.drawBullsEye(matrix, Integer.truncDivision(matrixSize, 2), 5);\n }\n else {\n Encoder$1.drawBullsEye(matrix, Integer.truncDivision(matrixSize, 2), 7);\n for (let i /*int*/ = 0, j = 0; i < Integer.truncDivision(baseMatrixSize, 2) - 1; i += 15, j += 16) {\n for (let k /*int*/ = Integer.truncDivision(matrixSize, 2) & 1; k < matrixSize; k += 2) {\n matrix.set(Integer.truncDivision(matrixSize, 2) - j, k);\n matrix.set(Integer.truncDivision(matrixSize, 2) + j, k);\n matrix.set(k, Integer.truncDivision(matrixSize, 2) - j);\n matrix.set(k, Integer.truncDivision(matrixSize, 2) + j);\n }\n }\n }\n let aztec = new AztecCode();\n aztec.setCompact(compact);\n aztec.setSize(matrixSize);\n aztec.setLayers(layers);\n aztec.setCodeWords(messageSizeInWords);\n aztec.setMatrix(matrix);\n return aztec;\n }\n static drawBullsEye(matrix, center, size) {\n for (let i /*int*/ = 0; i < size; i += 2) {\n for (let j /*int*/ = center - i; j <= center + i; j++) {\n matrix.set(j, center - i);\n matrix.set(j, center + i);\n matrix.set(center - i, j);\n matrix.set(center + i, j);\n }\n }\n matrix.set(center - size, center - size);\n matrix.set(center - size + 1, center - size);\n matrix.set(center - size, center - size + 1);\n matrix.set(center + size, center - size);\n matrix.set(center + size, center - size + 1);\n matrix.set(center + size, center + size - 1);\n }\n static generateModeMessage(compact, layers, messageSizeInWords) {\n let modeMessage = new BitArray();\n if (compact) {\n modeMessage.appendBits(layers - 1, 2);\n modeMessage.appendBits(messageSizeInWords - 1, 6);\n modeMessage = Encoder$1.generateCheckWords(modeMessage, 28, 4);\n }\n else {\n modeMessage.appendBits(layers - 1, 5);\n modeMessage.appendBits(messageSizeInWords - 1, 11);\n modeMessage = Encoder$1.generateCheckWords(modeMessage, 40, 4);\n }\n return modeMessage;\n }\n static drawModeMessage(matrix, compact, matrixSize, modeMessage) {\n let center = Integer.truncDivision(matrixSize, 2);\n if (compact) {\n for (let i /*int*/ = 0; i < 7; i++) {\n let offset = center - 3 + i;\n if (modeMessage.get(i)) {\n matrix.set(offset, center - 5);\n }\n if (modeMessage.get(i + 7)) {\n matrix.set(center + 5, offset);\n }\n if (modeMessage.get(20 - i)) {\n matrix.set(offset, center + 5);\n }\n if (modeMessage.get(27 - i)) {\n matrix.set(center - 5, offset);\n }\n }\n }\n else {\n for (let i /*int*/ = 0; i < 10; i++) {\n let offset = center - 5 + i + Integer.truncDivision(i, 5);\n if (modeMessage.get(i)) {\n matrix.set(offset, center - 7);\n }\n if (modeMessage.get(i + 10)) {\n matrix.set(center + 7, offset);\n }\n if (modeMessage.get(29 - i)) {\n matrix.set(offset, center + 7);\n }\n if (modeMessage.get(39 - i)) {\n matrix.set(center - 7, offset);\n }\n }\n }\n }\n static generateCheckWords(bitArray, totalBits, wordSize) {\n // bitArray is guaranteed to be a multiple of the wordSize, so no padding needed\n let messageSizeInWords = bitArray.getSize() / wordSize;\n let rs = new ReedSolomonEncoder(Encoder$1.getGF(wordSize));\n let totalWords = Integer.truncDivision(totalBits, wordSize);\n let messageWords = Encoder$1.bitsToWords(bitArray, wordSize, totalWords);\n rs.encode(messageWords, totalWords - messageSizeInWords);\n let startPad = totalBits % wordSize;\n let messageBits = new BitArray();\n messageBits.appendBits(0, startPad);\n for (const messageWord /*: int*/ of Array.from(messageWords)) {\n messageBits.appendBits(messageWord, wordSize);\n }\n return messageBits;\n }\n static bitsToWords(stuffedBits, wordSize, totalWords) {\n let message = new Int32Array(totalWords);\n let i;\n let n;\n for (i = 0, n = stuffedBits.getSize() / wordSize; i < n; i++) {\n let value = 0;\n for (let j /*int*/ = 0; j < wordSize; j++) {\n value |= stuffedBits.get(i * wordSize + j) ? (1 << wordSize - j - 1) : 0;\n }\n message[i] = value;\n }\n return message;\n }\n static getGF(wordSize) {\n switch (wordSize) {\n case 4:\n return GenericGF.AZTEC_PARAM;\n case 6:\n return GenericGF.AZTEC_DATA_6;\n case 8:\n return GenericGF.AZTEC_DATA_8;\n case 10:\n return GenericGF.AZTEC_DATA_10;\n case 12:\n return GenericGF.AZTEC_DATA_12;\n default:\n throw new IllegalArgumentException('Unsupported word size ' + wordSize);\n }\n }\n static stuffBits(bits, wordSize) {\n let out = new BitArray();\n let n = bits.getSize();\n let mask = (1 << wordSize) - 2;\n for (let i /*int*/ = 0; i < n; i += wordSize) {\n let word = 0;\n for (let j /*int*/ = 0; j < wordSize; j++) {\n if (i + j >= n || bits.get(i + j)) {\n word |= 1 << (wordSize - 1 - j);\n }\n }\n if ((word & mask) === mask) {\n out.appendBits(word & mask, wordSize);\n i--;\n }\n else if ((word & mask) === 0) {\n out.appendBits(word | 1, wordSize);\n i--;\n }\n else {\n out.appendBits(word, wordSize);\n }\n }\n return out;\n }\n static totalBitsInLayer(layers, compact) {\n return ((compact ? 88 : 112) + 16 * layers) * layers;\n }\n }\n Encoder$1.DEFAULT_EC_PERCENT = 33; // default minimal percentage of error check words\n Encoder$1.DEFAULT_AZTEC_LAYERS = 0;\n Encoder$1.MAX_NB_BITS = 32;\n Encoder$1.MAX_NB_BITS_COMPACT = 4;\n Encoder$1.WORD_SIZE = Int32Array.from([\n 4, 6, 6, 8, 8, 8, 8, 8, 8, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,\n 12, 12, 12, 12, 12, 12, 12, 12, 12, 12\n ]);\n\n /*\n * Copyright 2013 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n /**\n * Renders an Aztec code as a {@link BitMatrix}.\n */\n /*public final*/ class AztecWriter {\n // @Override\n encode(contents, format, width, height) {\n return this.encodeWithHints(contents, format, width, height, null);\n }\n // @Override\n encodeWithHints(contents, format, width, height, hints) {\n let charset = StandardCharsets.ISO_8859_1;\n let eccPercent = Encoder$1.DEFAULT_EC_PERCENT;\n let layers = Encoder$1.DEFAULT_AZTEC_LAYERS;\n if (hints != null) {\n if (hints.has(EncodeHintType$1.CHARACTER_SET)) {\n charset = Charset.forName(hints.get(EncodeHintType$1.CHARACTER_SET).toString());\n }\n if (hints.has(EncodeHintType$1.ERROR_CORRECTION)) {\n eccPercent = Integer.parseInt(hints.get(EncodeHintType$1.ERROR_CORRECTION).toString());\n }\n if (hints.has(EncodeHintType$1.AZTEC_LAYERS)) {\n layers = Integer.parseInt(hints.get(EncodeHintType$1.AZTEC_LAYERS).toString());\n }\n }\n return AztecWriter.encodeLayers(contents, format, width, height, charset, eccPercent, layers);\n }\n static encodeLayers(contents, format, width, height, charset, eccPercent, layers) {\n if (format !== BarcodeFormat$1.AZTEC) {\n throw new IllegalArgumentException('Can only encode AZTEC, but got ' + format);\n }\n let aztec = Encoder$1.encode(StringUtils.getBytes(contents, charset), eccPercent, layers);\n return AztecWriter.renderResult(aztec, width, height);\n }\n static renderResult(code, width, height) {\n let input = code.getMatrix();\n if (input == null) {\n throw new IllegalStateException();\n }\n let inputWidth = input.getWidth();\n let inputHeight = input.getHeight();\n let outputWidth = Math.max(width, inputWidth);\n let outputHeight = Math.max(height, inputHeight);\n let multiple = Math.min(outputWidth / inputWidth, outputHeight / inputHeight);\n let leftPadding = (outputWidth - (inputWidth * multiple)) / 2;\n let topPadding = (outputHeight - (inputHeight * multiple)) / 2;\n let output = new BitMatrix(outputWidth, outputHeight);\n for (let inputY /*int*/ = 0, outputY = topPadding; inputY < inputHeight; inputY++, outputY += multiple) {\n // Write the contents of this row of the barcode\n for (let inputX /*int*/ = 0, outputX = leftPadding; inputX < inputWidth; inputX++, outputX += multiple) {\n if (input.get(inputX, inputY)) {\n output.setRegion(outputX, outputY, multiple, multiple);\n }\n }\n }\n return output;\n }\n }\n\n exports.AbstractExpandedDecoder = AbstractExpandedDecoder;\n exports.ArgumentException = ArgumentException;\n exports.ArithmeticException = ArithmeticException;\n exports.AztecCode = AztecCode;\n exports.AztecCodeReader = AztecReader;\n exports.AztecCodeWriter = AztecWriter;\n exports.AztecDecoder = Decoder;\n exports.AztecDetector = Detector;\n exports.AztecDetectorResult = AztecDetectorResult;\n exports.AztecEncoder = Encoder$1;\n exports.AztecHighLevelEncoder = HighLevelEncoder;\n exports.AztecPoint = Point;\n exports.BarcodeFormat = BarcodeFormat$1;\n exports.Binarizer = Binarizer;\n exports.BinaryBitmap = BinaryBitmap;\n exports.BitArray = BitArray;\n exports.BitMatrix = BitMatrix;\n exports.BitSource = BitSource;\n exports.BrowserAztecCodeReader = BrowserAztecCodeReader;\n exports.BrowserBarcodeReader = BrowserBarcodeReader;\n exports.BrowserCodeReader = BrowserCodeReader;\n exports.BrowserDatamatrixCodeReader = BrowserDatamatrixCodeReader;\n exports.BrowserMultiFormatReader = BrowserMultiFormatReader;\n exports.BrowserPDF417Reader = BrowserPDF417Reader;\n exports.BrowserQRCodeReader = BrowserQRCodeReader;\n exports.BrowserQRCodeSvgWriter = BrowserQRCodeSvgWriter;\n exports.CharacterSetECI = CharacterSetECI;\n exports.ChecksumException = ChecksumException;\n exports.Code128Reader = Code128Reader;\n exports.Code39Reader = Code39Reader;\n exports.DataMatrixDecodedBitStreamParser = DecodedBitStreamParser;\n exports.DataMatrixReader = DataMatrixReader;\n exports.DecodeHintType = DecodeHintType$1;\n exports.DecoderResult = DecoderResult;\n exports.DefaultGridSampler = DefaultGridSampler;\n exports.DetectorResult = DetectorResult;\n exports.EAN13Reader = EAN13Reader;\n exports.EncodeHintType = EncodeHintType$1;\n exports.Exception = Exception;\n exports.FormatException = FormatException;\n exports.GenericGF = GenericGF;\n exports.GenericGFPoly = GenericGFPoly;\n exports.GlobalHistogramBinarizer = GlobalHistogramBinarizer;\n exports.GridSampler = GridSampler;\n exports.GridSamplerInstance = GridSamplerInstance;\n exports.HTMLCanvasElementLuminanceSource = HTMLCanvasElementLuminanceSource;\n exports.HybridBinarizer = HybridBinarizer;\n exports.ITFReader = ITFReader;\n exports.IllegalArgumentException = IllegalArgumentException;\n exports.IllegalStateException = IllegalStateException;\n exports.InvertedLuminanceSource = InvertedLuminanceSource;\n exports.LuminanceSource = LuminanceSource;\n exports.MathUtils = MathUtils;\n exports.MultiFormatOneDReader = MultiFormatOneDReader;\n exports.MultiFormatReader = MultiFormatReader;\n exports.MultiFormatWriter = MultiFormatWriter;\n exports.NotFoundException = NotFoundException;\n exports.OneDReader = OneDReader;\n exports.PDF417DecodedBitStreamParser = DecodedBitStreamParser$2;\n exports.PDF417DecoderErrorCorrection = ErrorCorrection;\n exports.PDF417Reader = PDF417Reader;\n exports.PDF417ResultMetadata = PDF417ResultMetadata;\n exports.PerspectiveTransform = PerspectiveTransform;\n exports.PlanarYUVLuminanceSource = PlanarYUVLuminanceSource;\n exports.QRCodeByteMatrix = ByteMatrix;\n exports.QRCodeDataMask = DataMask;\n exports.QRCodeDecodedBitStreamParser = DecodedBitStreamParser$1;\n exports.QRCodeDecoderErrorCorrectionLevel = ErrorCorrectionLevel;\n exports.QRCodeDecoderFormatInformation = FormatInformation;\n exports.QRCodeEncoder = Encoder;\n exports.QRCodeEncoderQRCode = QRCode;\n exports.QRCodeMaskUtil = MaskUtil;\n exports.QRCodeMatrixUtil = MatrixUtil;\n exports.QRCodeMode = Mode$1;\n exports.QRCodeReader = QRCodeReader;\n exports.QRCodeVersion = Version$1;\n exports.QRCodeWriter = QRCodeWriter;\n exports.RGBLuminanceSource = RGBLuminanceSource;\n exports.RSS14Reader = RSS14Reader;\n exports.RSSExpandedReader = RSSExpandedReader;\n exports.ReaderException = ReaderException;\n exports.ReedSolomonDecoder = ReedSolomonDecoder;\n exports.ReedSolomonEncoder = ReedSolomonEncoder;\n exports.ReedSolomonException = ReedSolomonException;\n exports.Result = Result;\n exports.ResultMetadataType = ResultMetadataType$1;\n exports.ResultPoint = ResultPoint;\n exports.StringUtils = StringUtils;\n exports.UnsupportedOperationException = UnsupportedOperationException;\n exports.VideoInputDevice = VideoInputDevice;\n exports.WhiteRectangleDetector = WhiteRectangleDetector;\n exports.WriterException = WriterException;\n exports.ZXingArrays = Arrays;\n exports.ZXingCharset = Charset;\n exports.ZXingInteger = Integer;\n exports.ZXingStandardCharsets = StandardCharsets;\n exports.ZXingStringBuilder = StringBuilder;\n exports.ZXingStringEncoding = StringEncoding;\n exports.ZXingSystem = System;\n exports.createAbstractExpandedDecoder = createDecoder;\n\n Object.defineProperty(exports, '__esModule', { value: true });\n\n})));\n", "/*\r\n * The MIT License (MIT)\r\n *\r\n * Copyright (c) 2014 Patrick Gansterer \r\n *\r\n * Permission is hereby granted, free of charge, to any person obtaining a copy\r\n * of this software and associated documentation files (the \"Software\"), to deal\r\n * in the Software without restriction, including without limitation the rights\r\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n * copies of the Software, and to permit persons to whom the Software is\r\n * furnished to do so, subject to the following conditions:\r\n *\r\n * The above copyright notice and this permission notice shall be included in all\r\n * copies or substantial portions of the Software.\r\n *\r\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r\n * SOFTWARE.\r\n */\r\n\r\n(function(global, undefined) { \"use strict\";\r\nvar POW_2_24 = Math.pow(2, -24),\r\n POW_2_32 = Math.pow(2, 32),\r\n POW_2_53 = Math.pow(2, 53);\r\n\r\nfunction encode(value) {\r\n var data = new ArrayBuffer(256);\r\n var dataView = new DataView(data);\r\n var lastLength;\r\n var offset = 0;\r\n\r\n function ensureSpace(length) {\r\n var newByteLength = data.byteLength;\r\n var requiredLength = offset + length;\r\n while (newByteLength < requiredLength)\r\n newByteLength *= 2;\r\n if (newByteLength !== data.byteLength) {\r\n var oldDataView = dataView;\r\n data = new ArrayBuffer(newByteLength);\r\n dataView = new DataView(data);\r\n var uint32count = (offset + 3) >> 2;\r\n for (var i = 0; i < uint32count; ++i)\r\n dataView.setUint32(i * 4, oldDataView.getUint32(i * 4));\r\n }\r\n\r\n lastLength = length;\r\n return dataView;\r\n }\r\n function write() {\r\n offset += lastLength;\r\n }\r\n function writeFloat64(value) {\r\n write(ensureSpace(8).setFloat64(offset, value));\r\n }\r\n function writeUint8(value) {\r\n write(ensureSpace(1).setUint8(offset, value));\r\n }\r\n function writeUint8Array(value) {\r\n var dataView = ensureSpace(value.length);\r\n for (var i = 0; i < value.length; ++i)\r\n dataView.setUint8(offset + i, value[i]);\r\n write();\r\n }\r\n function writeUint16(value) {\r\n write(ensureSpace(2).setUint16(offset, value));\r\n }\r\n function writeUint32(value) {\r\n write(ensureSpace(4).setUint32(offset, value));\r\n }\r\n function writeUint64(value) {\r\n var low = value % POW_2_32;\r\n var high = (value - low) / POW_2_32;\r\n var dataView = ensureSpace(8);\r\n dataView.setUint32(offset, high);\r\n dataView.setUint32(offset + 4, low);\r\n write();\r\n }\r\n function writeTypeAndLength(type, length) {\r\n if (length < 24) {\r\n writeUint8(type << 5 | length);\r\n } else if (length < 0x100) {\r\n writeUint8(type << 5 | 24);\r\n writeUint8(length);\r\n } else if (length < 0x10000) {\r\n writeUint8(type << 5 | 25);\r\n writeUint16(length);\r\n } else if (length < 0x100000000) {\r\n writeUint8(type << 5 | 26);\r\n writeUint32(length);\r\n } else {\r\n writeUint8(type << 5 | 27);\r\n writeUint64(length);\r\n }\r\n }\r\n \r\n function encodeItem(value) {\r\n var i;\r\n\r\n if (value === false)\r\n return writeUint8(0xf4);\r\n if (value === true)\r\n return writeUint8(0xf5);\r\n if (value === null)\r\n return writeUint8(0xf6);\r\n if (value === undefined)\r\n return writeUint8(0xf7);\r\n \r\n switch (typeof value) {\r\n case \"number\":\r\n if (Math.floor(value) === value) {\r\n if (0 <= value && value <= POW_2_53)\r\n return writeTypeAndLength(0, value);\r\n if (-POW_2_53 <= value && value < 0)\r\n return writeTypeAndLength(1, -(value + 1));\r\n }\r\n writeUint8(0xfb);\r\n return writeFloat64(value);\r\n\r\n case \"string\":\r\n var utf8data = [];\r\n for (i = 0; i < value.length; ++i) {\r\n var charCode = value.charCodeAt(i);\r\n if (charCode < 0x80) {\r\n utf8data.push(charCode);\r\n } else if (charCode < 0x800) {\r\n utf8data.push(0xc0 | charCode >> 6);\r\n utf8data.push(0x80 | charCode & 0x3f);\r\n } else if (charCode < 0xd800) {\r\n utf8data.push(0xe0 | charCode >> 12);\r\n utf8data.push(0x80 | (charCode >> 6) & 0x3f);\r\n utf8data.push(0x80 | charCode & 0x3f);\r\n } else {\r\n charCode = (charCode & 0x3ff) << 10;\r\n charCode |= value.charCodeAt(++i) & 0x3ff;\r\n charCode += 0x10000;\r\n\r\n utf8data.push(0xf0 | charCode >> 18);\r\n utf8data.push(0x80 | (charCode >> 12) & 0x3f);\r\n utf8data.push(0x80 | (charCode >> 6) & 0x3f);\r\n utf8data.push(0x80 | charCode & 0x3f);\r\n }\r\n }\r\n\r\n writeTypeAndLength(3, utf8data.length);\r\n return writeUint8Array(utf8data);\r\n\r\n default:\r\n var length;\r\n if (Array.isArray(value)) {\r\n length = value.length;\r\n writeTypeAndLength(4, length);\r\n for (i = 0; i < length; ++i)\r\n encodeItem(value[i]);\r\n } else if (value instanceof Uint8Array) {\r\n writeTypeAndLength(2, value.length);\r\n writeUint8Array(value);\r\n } else {\r\n var keys = Object.keys(value);\r\n length = keys.length;\r\n writeTypeAndLength(5, length);\r\n for (i = 0; i < length; ++i) {\r\n var key = keys[i];\r\n encodeItem(key);\r\n encodeItem(value[key]);\r\n }\r\n }\r\n }\r\n }\r\n \r\n encodeItem(value);\r\n\r\n if (\"slice\" in data)\r\n return data.slice(0, offset);\r\n \r\n var ret = new ArrayBuffer(offset);\r\n var retView = new DataView(ret);\r\n for (var i = 0; i < offset; ++i)\r\n retView.setUint8(i, dataView.getUint8(i));\r\n return ret;\r\n}\r\n\r\nfunction decode(data, tagger, simpleValue) {\r\n var dataView = new DataView(data);\r\n var offset = 0;\r\n \r\n if (typeof tagger !== \"function\")\r\n tagger = function(value) { return value; };\r\n if (typeof simpleValue !== \"function\")\r\n simpleValue = function() { return undefined; };\r\n\r\n function read(value, length) {\r\n offset += length;\r\n return value;\r\n }\r\n function readArrayBuffer(length) {\r\n return read(new Uint8Array(data, offset, length), length);\r\n }\r\n function readFloat16() {\r\n var tempArrayBuffer = new ArrayBuffer(4);\r\n var tempDataView = new DataView(tempArrayBuffer);\r\n var value = readUint16();\r\n\r\n var sign = value & 0x8000;\r\n var exponent = value & 0x7c00;\r\n var fraction = value & 0x03ff;\r\n \r\n if (exponent === 0x7c00)\r\n exponent = 0xff << 10;\r\n else if (exponent !== 0)\r\n exponent += (127 - 15) << 10;\r\n else if (fraction !== 0)\r\n return fraction * POW_2_24;\r\n \r\n tempDataView.setUint32(0, sign << 16 | exponent << 13 | fraction << 13);\r\n return tempDataView.getFloat32(0);\r\n }\r\n function readFloat32() {\r\n return read(dataView.getFloat32(offset), 4);\r\n }\r\n function readFloat64() {\r\n return read(dataView.getFloat64(offset), 8);\r\n }\r\n function readUint8() {\r\n return read(dataView.getUint8(offset), 1);\r\n }\r\n function readUint16() {\r\n return read(dataView.getUint16(offset), 2);\r\n }\r\n function readUint32() {\r\n return read(dataView.getUint32(offset), 4);\r\n }\r\n function readUint64() {\r\n return readUint32() * POW_2_32 + readUint32();\r\n }\r\n function readBreak() {\r\n if (dataView.getUint8(offset) !== 0xff)\r\n return false;\r\n offset += 1;\r\n return true;\r\n }\r\n function readLength(additionalInformation) {\r\n if (additionalInformation < 24)\r\n return additionalInformation;\r\n if (additionalInformation === 24)\r\n return readUint8();\r\n if (additionalInformation === 25)\r\n return readUint16();\r\n if (additionalInformation === 26)\r\n return readUint32();\r\n if (additionalInformation === 27)\r\n return readUint64();\r\n if (additionalInformation === 31)\r\n return -1;\r\n throw \"Invalid length encoding\";\r\n }\r\n function readIndefiniteStringLength(majorType) {\r\n var initialByte = readUint8();\r\n if (initialByte === 0xff)\r\n return -1;\r\n var length = readLength(initialByte & 0x1f);\r\n if (length < 0 || (initialByte >> 5) !== majorType)\r\n throw \"Invalid indefinite length element\";\r\n return length;\r\n }\r\n\r\n function appendUtf16data(utf16data, length) {\r\n for (var i = 0; i < length; ++i) {\r\n var value = readUint8();\r\n if (value & 0x80) {\r\n if (value < 0xe0) {\r\n value = (value & 0x1f) << 6\r\n | (readUint8() & 0x3f);\r\n length -= 1;\r\n } else if (value < 0xf0) {\r\n value = (value & 0x0f) << 12\r\n | (readUint8() & 0x3f) << 6\r\n | (readUint8() & 0x3f);\r\n length -= 2;\r\n } else {\r\n value = (value & 0x0f) << 18\r\n | (readUint8() & 0x3f) << 12\r\n | (readUint8() & 0x3f) << 6\r\n | (readUint8() & 0x3f);\r\n length -= 3;\r\n }\r\n }\r\n\r\n if (value < 0x10000) {\r\n utf16data.push(value);\r\n } else {\r\n value -= 0x10000;\r\n utf16data.push(0xd800 | (value >> 10));\r\n utf16data.push(0xdc00 | (value & 0x3ff));\r\n }\r\n }\r\n }\r\n\r\n function decodeItem() {\r\n var initialByte = readUint8();\r\n var majorType = initialByte >> 5;\r\n var additionalInformation = initialByte & 0x1f;\r\n var i;\r\n var length;\r\n\r\n if (majorType === 7) {\r\n switch (additionalInformation) {\r\n case 25:\r\n return readFloat16();\r\n case 26:\r\n return readFloat32();\r\n case 27:\r\n return readFloat64();\r\n }\r\n }\r\n\r\n length = readLength(additionalInformation);\r\n if (length < 0 && (majorType < 2 || 6 < majorType))\r\n throw \"Invalid length\";\r\n\r\n switch (majorType) {\r\n case 0:\r\n return length;\r\n case 1:\r\n return -1 - length;\r\n case 2:\r\n if (length < 0) {\r\n var elements = [];\r\n var fullArrayLength = 0;\r\n while ((length = readIndefiniteStringLength(majorType)) >= 0) {\r\n fullArrayLength += length;\r\n elements.push(readArrayBuffer(length));\r\n }\r\n var fullArray = new Uint8Array(fullArrayLength);\r\n var fullArrayOffset = 0;\r\n for (i = 0; i < elements.length; ++i) {\r\n fullArray.set(elements[i], fullArrayOffset);\r\n fullArrayOffset += elements[i].length;\r\n }\r\n return fullArray;\r\n }\r\n return readArrayBuffer(length);\r\n case 3:\r\n var utf16data = [];\r\n if (length < 0) {\r\n while ((length = readIndefiniteStringLength(majorType)) >= 0)\r\n appendUtf16data(utf16data, length);\r\n } else\r\n appendUtf16data(utf16data, length);\r\n return String.fromCharCode.apply(null, utf16data);\r\n case 4:\r\n var retArray;\r\n if (length < 0) {\r\n retArray = [];\r\n while (!readBreak())\r\n retArray.push(decodeItem());\r\n } else {\r\n retArray = new Array(length);\r\n for (i = 0; i < length; ++i)\r\n retArray[i] = decodeItem();\r\n }\r\n return retArray;\r\n case 5:\r\n var retObject = {};\r\n for (i = 0; i < length || length < 0 && !readBreak(); ++i) {\r\n var key = decodeItem();\r\n retObject[key] = decodeItem();\r\n }\r\n return retObject;\r\n case 6:\r\n return tagger(decodeItem(), length);\r\n case 7:\r\n switch (length) {\r\n case 20:\r\n return false;\r\n case 21:\r\n return true;\r\n case 22:\r\n return null;\r\n case 23:\r\n return undefined;\r\n default:\r\n return simpleValue(length);\r\n }\r\n }\r\n }\r\n\r\n var ret = decodeItem();\r\n if (offset !== data.byteLength)\r\n throw \"Remaining bytes\";\r\n return ret;\r\n}\r\n\r\nvar obj = { encode: encode, decode: decode };\r\n\r\nif (typeof define === \"function\" && define.amd)\r\n define(\"cbor/cbor\", obj);\r\nelse if (typeof module !== 'undefined' && module.exports)\r\n module.exports = obj;\r\nelse if (!global.CBOR)\r\n global.CBOR = obj;\r\n\r\n})(this);\r\n", "'use strict'\n\nexports.byteLength = byteLength\nexports.toByteArray = toByteArray\nexports.fromByteArray = fromByteArray\n\nvar lookup = []\nvar revLookup = []\nvar Arr = typeof Uint8Array !== 'undefined' ? Uint8Array : Array\n\nvar code = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'\nfor (var i = 0, len = code.length; i < len; ++i) {\n lookup[i] = code[i]\n revLookup[code.charCodeAt(i)] = i\n}\n\n// Support decoding URL-safe base64 strings, as Node.js does.\n// See: https://en.wikipedia.org/wiki/Base64#URL_applications\nrevLookup['-'.charCodeAt(0)] = 62\nrevLookup['_'.charCodeAt(0)] = 63\n\nfunction getLens (b64) {\n var len = b64.length\n\n if (len % 4 > 0) {\n throw new Error('Invalid string. Length must be a multiple of 4')\n }\n\n // Trim off extra bytes after placeholder bytes are found\n // See: https://github.com/beatgammit/base64-js/issues/42\n var validLen = b64.indexOf('=')\n if (validLen === -1) validLen = len\n\n var placeHoldersLen = validLen === len\n ? 0\n : 4 - (validLen % 4)\n\n return [validLen, placeHoldersLen]\n}\n\n// base64 is 4/3 + up to two characters of the original data\nfunction byteLength (b64) {\n var lens = getLens(b64)\n var validLen = lens[0]\n var placeHoldersLen = lens[1]\n return ((validLen + placeHoldersLen) * 3 / 4) - placeHoldersLen\n}\n\nfunction _byteLength (b64, validLen, placeHoldersLen) {\n return ((validLen + placeHoldersLen) * 3 / 4) - placeHoldersLen\n}\n\nfunction toByteArray (b64) {\n var tmp\n var lens = getLens(b64)\n var validLen = lens[0]\n var placeHoldersLen = lens[1]\n\n var arr = new Arr(_byteLength(b64, validLen, placeHoldersLen))\n\n var curByte = 0\n\n // if there are placeholders, only get up to the last complete 4 chars\n var len = placeHoldersLen > 0\n ? validLen - 4\n : validLen\n\n var i\n for (i = 0; i < len; i += 4) {\n tmp =\n (revLookup[b64.charCodeAt(i)] << 18) |\n (revLookup[b64.charCodeAt(i + 1)] << 12) |\n (revLookup[b64.charCodeAt(i + 2)] << 6) |\n revLookup[b64.charCodeAt(i + 3)]\n arr[curByte++] = (tmp >> 16) & 0xFF\n arr[curByte++] = (tmp >> 8) & 0xFF\n arr[curByte++] = tmp & 0xFF\n }\n\n if (placeHoldersLen === 2) {\n tmp =\n (revLookup[b64.charCodeAt(i)] << 2) |\n (revLookup[b64.charCodeAt(i + 1)] >> 4)\n arr[curByte++] = tmp & 0xFF\n }\n\n if (placeHoldersLen === 1) {\n tmp =\n (revLookup[b64.charCodeAt(i)] << 10) |\n (revLookup[b64.charCodeAt(i + 1)] << 4) |\n (revLookup[b64.charCodeAt(i + 2)] >> 2)\n arr[curByte++] = (tmp >> 8) & 0xFF\n arr[curByte++] = tmp & 0xFF\n }\n\n return arr\n}\n\nfunction tripletToBase64 (num) {\n return lookup[num >> 18 & 0x3F] +\n lookup[num >> 12 & 0x3F] +\n lookup[num >> 6 & 0x3F] +\n lookup[num & 0x3F]\n}\n\nfunction encodeChunk (uint8, start, end) {\n var tmp\n var output = []\n for (var i = start; i < end; i += 3) {\n tmp =\n ((uint8[i] << 16) & 0xFF0000) +\n ((uint8[i + 1] << 8) & 0xFF00) +\n (uint8[i + 2] & 0xFF)\n output.push(tripletToBase64(tmp))\n }\n return output.join('')\n}\n\nfunction fromByteArray (uint8) {\n var tmp\n var len = uint8.length\n var extraBytes = len % 3 // if we have 1 byte left, pad 2 bytes\n var parts = []\n var maxChunkLength = 16383 // must be multiple of 3\n\n // go through the array every three bytes, we'll deal with trailing stuff later\n for (var i = 0, len2 = len - extraBytes; i < len2; i += maxChunkLength) {\n parts.push(encodeChunk(uint8, i, (i + maxChunkLength) > len2 ? len2 : (i + maxChunkLength)))\n }\n\n // pad the end with zeros, but make sure to not forget the extra bytes\n if (extraBytes === 1) {\n tmp = uint8[len - 1]\n parts.push(\n lookup[tmp >> 2] +\n lookup[(tmp << 4) & 0x3F] +\n '=='\n )\n } else if (extraBytes === 2) {\n tmp = (uint8[len - 2] << 8) + uint8[len - 1]\n parts.push(\n lookup[tmp >> 10] +\n lookup[(tmp >> 4) & 0x3F] +\n lookup[(tmp << 2) & 0x3F] +\n '='\n )\n }\n\n return parts.join('')\n}\n", "// Local QR generator and scanner with COSE compression (no external CDNs)\n// Exposes: \n// - window.generateQRCode(text, { size?: number, margin?: number, errorCorrectionLevel?: 'L'|'M'|'Q'|'H' })\n// - window.generateCOSEQRCode(data, senderKey?, recipientKey?) - COSE-based compression\n// - window.Html5Qrcode (for scanning QR codes)\n// - window.packSecurePayload, window.receiveAndProcess (COSE functions)\n\nimport * as QRCode from 'qrcode';\nimport { Html5Qrcode } from 'html5-qrcode';\nimport { gzip, ungzip, deflate, inflate } from 'pako';\nimport * as cbor from 'cbor-js';\nimport { packSecurePayload, receiveAndProcess } from '../crypto/cose-qr.js';\n\n// Compact payload prefix to signal gzip+base64 content\nconst COMPRESSION_PREFIX = 'SB1:gz:';\nconst BINARY_PREFIX = 'SB1:bin:'; // CBOR + deflate + base64url\n\nfunction uint8ToBase64(bytes) {\n let binary = '';\n const chunkSize = 0x8000;\n for (let i = 0; i < bytes.length; i += chunkSize) {\n const chunk = bytes.subarray(i, i + chunkSize);\n binary += String.fromCharCode.apply(null, chunk);\n }\n return btoa(binary);\n}\n\nfunction base64ToUint8(b64) {\n const binary = atob(b64);\n const len = binary.length;\n const bytes = new Uint8Array(len);\n for (let i = 0; i < len; i++) bytes[i] = binary.charCodeAt(i);\n return bytes;\n}\n\nfunction compressStringToBase64Gzip(text) {\n const utf8 = new TextEncoder().encode(text);\n const gz = gzip(utf8);\n return uint8ToBase64(gz);\n}\n\nfunction decompressBase64GzipToString(b64) {\n const gz = base64ToUint8(b64);\n const out = ungzip(gz);\n return new TextDecoder().decode(out);\n}\n\nasync function generateQRCode(text, opts = {}) {\n const size = opts.size || 512;\n const margin = opts.margin ?? 2;\n const errorCorrectionLevel = opts.errorCorrectionLevel || 'M';\n return await QRCode.toDataURL(text, { width: size, margin, errorCorrectionLevel });\n}\n\n// Generate QR with gzip+base64 payload and recognizable prefix for scanners\nasync function generateCompressedQRCode(text, opts = {}) {\n try {\n const compressedB64 = compressStringToBase64Gzip(text);\n const payload = COMPRESSION_PREFIX + compressedB64;\n return await generateQRCode(payload, opts);\n } catch (e) {\n console.warn('generateCompressedQRCode failed, falling back to plain:', e?.message || e);\n return await generateQRCode(text, opts);\n }\n}\n\n// ---- Binary (CBOR) encode/decode helpers ----\nfunction base64ToBase64Url(b64) {\n return b64.replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=+$/g, '');\n}\nfunction base64UrlToBase64(b64url) {\n let b64 = b64url.replace(/-/g, '+').replace(/_/g, '/');\n const pad = b64.length % 4;\n if (pad) b64 += '='.repeat(4 - pad);\n return b64;\n}\n\nfunction encodeObjectToBinaryBase64Url(obj) {\n const cborBytes = cbor.encode(obj);\n const compressed = deflate(new Uint8Array(cborBytes));\n const b64 = uint8ToBase64(compressed);\n return base64ToBase64Url(b64);\n}\n\nfunction decodeBinaryBase64UrlToObject(b64url) {\n const b64 = base64UrlToBase64(b64url);\n const compressed = base64ToUint8(b64);\n const decompressed = inflate(compressed);\n const ab = decompressed.buffer.slice(decompressed.byteOffset, decompressed.byteOffset + decompressed.byteLength);\n return cbor.decode(ab);\n}\n\nasync function generateBinaryQRCodeFromObject(obj, opts = {}) {\n try {\n const b64url = encodeObjectToBinaryBase64Url(obj);\n const payload = BINARY_PREFIX + b64url;\n return await generateQRCode(payload, opts);\n } catch (e) {\n console.warn('generateBinaryQRCodeFromObject failed, falling back to JSON compressed:', e?.message || e);\n const text = JSON.stringify(obj);\n return await generateCompressedQRCode(text, opts);\n }\n}\n\n// COSE-based QR generation for large data\nasync function generateCOSEQRCode(data, senderKey = null, recipientKey = null) {\n try {\n console.log('\uD83D\uDD10 Generating COSE-based QR code...');\n \n // Pack data using COSE\n const chunks = await packSecurePayload(data, senderKey, recipientKey);\n \n if (chunks.length === 1) {\n // Single QR code\n return await generateQRCode(chunks[0]);\n } else {\n // Enforce single-QR policy: let caller fallback to template/reference\n console.warn(`\uD83D\uDCCA COSE packing produced ${chunks.length} chunks; falling back to non-COSE strategy`);\n throw new Error('COSE QR would require multiple chunks');\n }\n } catch (error) {\n console.error('Error generating COSE QR code:', error);\n throw error;\n }\n}\n\n// Expose functions to global scope\nwindow.generateQRCode = generateQRCode;\nwindow.generateCompressedQRCode = generateCompressedQRCode;\nwindow.generateBinaryQRCodeFromObject = generateBinaryQRCodeFromObject;\nwindow.generateCOSEQRCode = generateCOSEQRCode;\nwindow.Html5Qrcode = Html5Qrcode;\nwindow.packSecurePayload = packSecurePayload;\nwindow.receiveAndProcess = receiveAndProcess;\n\n// Expose helper to transparently decompress scanner payloads\nwindow.decompressIfNeeded = function (scannedText) {\n try {\n if (typeof scannedText === 'string' && scannedText.startsWith(COMPRESSION_PREFIX)) {\n const b64 = scannedText.slice(COMPRESSION_PREFIX.length);\n return decompressBase64GzipToString(b64);\n }\n } catch (e) {\n console.warn('decompressIfNeeded failed:', e?.message || e);\n }\n return scannedText;\n};\n\n// Expose helper to get compressed string with prefix for copy/paste flows\nwindow.compressToPrefixedGzip = function (text) {\n try {\n const payload = String(text || '');\n const compressedB64 = compressStringToBase64Gzip(payload);\n return COMPRESSION_PREFIX + compressedB64;\n } catch (e) {\n console.warn('compressToPrefixedGzip failed:', e?.message || e);\n return String(text || '');\n }\n};\n\n// Expose helpers for binary payloads in copy/paste\nwindow.encodeBinaryToPrefixed = function (objOrJson) {\n try {\n const obj = typeof objOrJson === 'string' ? JSON.parse(objOrJson) : objOrJson;\n const b64url = encodeObjectToBinaryBase64Url(obj);\n return BINARY_PREFIX + b64url;\n } catch (e) {\n console.warn('encodeBinaryToPrefixed failed:', e?.message || e);\n return typeof objOrJson === 'string' ? objOrJson : JSON.stringify(objOrJson);\n }\n};\n\nwindow.decodeAnyPayload = function (scannedText) {\n try {\n if (typeof scannedText === 'string') {\n if (scannedText.startsWith(BINARY_PREFIX)) {\n const b64url = scannedText.slice(BINARY_PREFIX.length);\n return decodeBinaryBase64UrlToObject(b64url); // returns object\n }\n if (scannedText.startsWith(COMPRESSION_PREFIX)) {\n const s = window.decompressIfNeeded(scannedText);\n return s; // returns JSON string\n }\n // Not prefixed: return as-is\n return scannedText;\n }\n } catch (e) {\n console.warn('decodeAnyPayload failed:', e?.message || e);\n }\n return scannedText;\n};\n\nconsole.log('QR libraries loaded: generateQRCode, generateCompressedQRCode, generateBinaryQRCodeFromObject, Html5Qrcode, COSE functions');", null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, "\n/*! pako 2.1.0 https://github.com/nodeca/pako @license (MIT AND Zlib) */\n// (C) 1995-2013 Jean-loup Gailly and Mark Adler\n// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin\n//\n// This software is provided 'as-is', without any express or implied\n// warranty. In no event will the authors be held liable for any damages\n// arising from the use of this software.\n//\n// Permission is granted to anyone to use this software for any purpose,\n// including commercial applications, and to alter it and redistribute it\n// freely, subject to the following restrictions:\n//\n// 1. The origin of this software must not be misrepresented; you must not\n// claim that you wrote the original software. If you use this software\n// in a product, an acknowledgment in the product documentation would be\n// appreciated but is not required.\n// 2. Altered source versions must be plainly marked as such, and must not be\n// misrepresented as being the original software.\n// 3. This notice may not be removed or altered from any source distribution.\n\n/* eslint-disable space-unary-ops */\n\n/* Public constants ==========================================================*/\n/* ===========================================================================*/\n\n\n//const Z_FILTERED = 1;\n//const Z_HUFFMAN_ONLY = 2;\n//const Z_RLE = 3;\nconst Z_FIXED$1 = 4;\n//const Z_DEFAULT_STRATEGY = 0;\n\n/* Possible values of the data_type field (though see inflate()) */\nconst Z_BINARY = 0;\nconst Z_TEXT = 1;\n//const Z_ASCII = 1; // = Z_TEXT\nconst Z_UNKNOWN$1 = 2;\n\n/*============================================================================*/\n\n\nfunction zero$1(buf) { let len = buf.length; while (--len >= 0) { buf[len] = 0; } }\n\n// From zutil.h\n\nconst STORED_BLOCK = 0;\nconst STATIC_TREES = 1;\nconst DYN_TREES = 2;\n/* The three kinds of block type */\n\nconst MIN_MATCH$1 = 3;\nconst MAX_MATCH$1 = 258;\n/* The minimum and maximum match lengths */\n\n// From deflate.h\n/* ===========================================================================\n * Internal compression state.\n */\n\nconst LENGTH_CODES$1 = 29;\n/* number of length codes, not counting the special END_BLOCK code */\n\nconst LITERALS$1 = 256;\n/* number of literal bytes 0..255 */\n\nconst L_CODES$1 = LITERALS$1 + 1 + LENGTH_CODES$1;\n/* number of Literal or Length codes, including the END_BLOCK code */\n\nconst D_CODES$1 = 30;\n/* number of distance codes */\n\nconst BL_CODES$1 = 19;\n/* number of codes used to transfer the bit lengths */\n\nconst HEAP_SIZE$1 = 2 * L_CODES$1 + 1;\n/* maximum heap size */\n\nconst MAX_BITS$1 = 15;\n/* All codes must not exceed MAX_BITS bits */\n\nconst Buf_size = 16;\n/* size of bit buffer in bi_buf */\n\n\n/* ===========================================================================\n * Constants\n */\n\nconst MAX_BL_BITS = 7;\n/* Bit length codes must not exceed MAX_BL_BITS bits */\n\nconst END_BLOCK = 256;\n/* end of block literal code */\n\nconst REP_3_6 = 16;\n/* repeat previous bit length 3-6 times (2 bits of repeat count) */\n\nconst REPZ_3_10 = 17;\n/* repeat a zero length 3-10 times (3 bits of repeat count) */\n\nconst REPZ_11_138 = 18;\n/* repeat a zero length 11-138 times (7 bits of repeat count) */\n\n/* eslint-disable comma-spacing,array-bracket-spacing */\nconst extra_lbits = /* extra bits for each length code */\n new Uint8Array([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]);\n\nconst extra_dbits = /* extra bits for each distance code */\n new Uint8Array([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]);\n\nconst extra_blbits = /* extra bits for each bit length code */\n new Uint8Array([0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7]);\n\nconst bl_order =\n new Uint8Array([16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15]);\n/* eslint-enable comma-spacing,array-bracket-spacing */\n\n/* The lengths of the bit length codes are sent in order of decreasing\n * probability, to avoid transmitting the lengths for unused bit length codes.\n */\n\n/* ===========================================================================\n * Local data. These are initialized only once.\n */\n\n// We pre-fill arrays with 0 to avoid uninitialized gaps\n\nconst DIST_CODE_LEN = 512; /* see definition of array dist_code below */\n\n// !!!! Use flat array instead of structure, Freq = i*2, Len = i*2+1\nconst static_ltree = new Array((L_CODES$1 + 2) * 2);\nzero$1(static_ltree);\n/* The static literal tree. Since the bit lengths are imposed, there is no\n * need for the L_CODES extra codes used during heap construction. However\n * The codes 286 and 287 are needed to build a canonical tree (see _tr_init\n * below).\n */\n\nconst static_dtree = new Array(D_CODES$1 * 2);\nzero$1(static_dtree);\n/* The static distance tree. (Actually a trivial tree since all codes use\n * 5 bits.)\n */\n\nconst _dist_code = new Array(DIST_CODE_LEN);\nzero$1(_dist_code);\n/* Distance codes. The first 256 values correspond to the distances\n * 3 .. 258, the last 256 values correspond to the top 8 bits of\n * the 15 bit distances.\n */\n\nconst _length_code = new Array(MAX_MATCH$1 - MIN_MATCH$1 + 1);\nzero$1(_length_code);\n/* length code for each normalized match length (0 == MIN_MATCH) */\n\nconst base_length = new Array(LENGTH_CODES$1);\nzero$1(base_length);\n/* First normalized length for each code (0 = MIN_MATCH) */\n\nconst base_dist = new Array(D_CODES$1);\nzero$1(base_dist);\n/* First normalized distance for each code (0 = distance of 1) */\n\n\nfunction StaticTreeDesc(static_tree, extra_bits, extra_base, elems, max_length) {\n\n this.static_tree = static_tree; /* static tree or NULL */\n this.extra_bits = extra_bits; /* extra bits for each code or NULL */\n this.extra_base = extra_base; /* base index for extra_bits */\n this.elems = elems; /* max number of elements in the tree */\n this.max_length = max_length; /* max bit length for the codes */\n\n // show if `static_tree` has data or dummy - needed for monomorphic objects\n this.has_stree = static_tree && static_tree.length;\n}\n\n\nlet static_l_desc;\nlet static_d_desc;\nlet static_bl_desc;\n\n\nfunction TreeDesc(dyn_tree, stat_desc) {\n this.dyn_tree = dyn_tree; /* the dynamic tree */\n this.max_code = 0; /* largest code with non zero frequency */\n this.stat_desc = stat_desc; /* the corresponding static tree */\n}\n\n\n\nconst d_code = (dist) => {\n\n return dist < 256 ? _dist_code[dist] : _dist_code[256 + (dist >>> 7)];\n};\n\n\n/* ===========================================================================\n * Output a short LSB first on the stream.\n * IN assertion: there is enough room in pendingBuf.\n */\nconst put_short = (s, w) => {\n// put_byte(s, (uch)((w) & 0xff));\n// put_byte(s, (uch)((ush)(w) >> 8));\n s.pending_buf[s.pending++] = (w) & 0xff;\n s.pending_buf[s.pending++] = (w >>> 8) & 0xff;\n};\n\n\n/* ===========================================================================\n * Send a value on a given number of bits.\n * IN assertion: length <= 16 and value fits in length bits.\n */\nconst send_bits = (s, value, length) => {\n\n if (s.bi_valid > (Buf_size - length)) {\n s.bi_buf |= (value << s.bi_valid) & 0xffff;\n put_short(s, s.bi_buf);\n s.bi_buf = value >> (Buf_size - s.bi_valid);\n s.bi_valid += length - Buf_size;\n } else {\n s.bi_buf |= (value << s.bi_valid) & 0xffff;\n s.bi_valid += length;\n }\n};\n\n\nconst send_code = (s, c, tree) => {\n\n send_bits(s, tree[c * 2]/*.Code*/, tree[c * 2 + 1]/*.Len*/);\n};\n\n\n/* ===========================================================================\n * Reverse the first len bits of a code, using straightforward code (a faster\n * method would use a table)\n * IN assertion: 1 <= len <= 15\n */\nconst bi_reverse = (code, len) => {\n\n let res = 0;\n do {\n res |= code & 1;\n code >>>= 1;\n res <<= 1;\n } while (--len > 0);\n return res >>> 1;\n};\n\n\n/* ===========================================================================\n * Flush the bit buffer, keeping at most 7 bits in it.\n */\nconst bi_flush = (s) => {\n\n if (s.bi_valid === 16) {\n put_short(s, s.bi_buf);\n s.bi_buf = 0;\n s.bi_valid = 0;\n\n } else if (s.bi_valid >= 8) {\n s.pending_buf[s.pending++] = s.bi_buf & 0xff;\n s.bi_buf >>= 8;\n s.bi_valid -= 8;\n }\n};\n\n\n/* ===========================================================================\n * Compute the optimal bit lengths for a tree and update the total bit length\n * for the current block.\n * IN assertion: the fields freq and dad are set, heap[heap_max] and\n * above are the tree nodes sorted by increasing frequency.\n * OUT assertions: the field len is set to the optimal bit length, the\n * array bl_count contains the frequencies for each bit length.\n * The length opt_len is updated; static_len is also updated if stree is\n * not null.\n */\nconst gen_bitlen = (s, desc) => {\n// deflate_state *s;\n// tree_desc *desc; /* the tree descriptor */\n\n const tree = desc.dyn_tree;\n const max_code = desc.max_code;\n const stree = desc.stat_desc.static_tree;\n const has_stree = desc.stat_desc.has_stree;\n const extra = desc.stat_desc.extra_bits;\n const base = desc.stat_desc.extra_base;\n const max_length = desc.stat_desc.max_length;\n let h; /* heap index */\n let n, m; /* iterate over the tree elements */\n let bits; /* bit length */\n let xbits; /* extra bits */\n let f; /* frequency */\n let overflow = 0; /* number of elements with bit length too large */\n\n for (bits = 0; bits <= MAX_BITS$1; bits++) {\n s.bl_count[bits] = 0;\n }\n\n /* In a first pass, compute the optimal bit lengths (which may\n * overflow in the case of the bit length tree).\n */\n tree[s.heap[s.heap_max] * 2 + 1]/*.Len*/ = 0; /* root of the heap */\n\n for (h = s.heap_max + 1; h < HEAP_SIZE$1; h++) {\n n = s.heap[h];\n bits = tree[tree[n * 2 + 1]/*.Dad*/ * 2 + 1]/*.Len*/ + 1;\n if (bits > max_length) {\n bits = max_length;\n overflow++;\n }\n tree[n * 2 + 1]/*.Len*/ = bits;\n /* We overwrite tree[n].Dad which is no longer needed */\n\n if (n > max_code) { continue; } /* not a leaf node */\n\n s.bl_count[bits]++;\n xbits = 0;\n if (n >= base) {\n xbits = extra[n - base];\n }\n f = tree[n * 2]/*.Freq*/;\n s.opt_len += f * (bits + xbits);\n if (has_stree) {\n s.static_len += f * (stree[n * 2 + 1]/*.Len*/ + xbits);\n }\n }\n if (overflow === 0) { return; }\n\n // Tracev((stderr,\"\\nbit length overflow\\n\"));\n /* This happens for example on obj2 and pic of the Calgary corpus */\n\n /* Find the first bit length which could increase: */\n do {\n bits = max_length - 1;\n while (s.bl_count[bits] === 0) { bits--; }\n s.bl_count[bits]--; /* move one leaf down the tree */\n s.bl_count[bits + 1] += 2; /* move one overflow item as its brother */\n s.bl_count[max_length]--;\n /* The brother of the overflow item also moves one step up,\n * but this does not affect bl_count[max_length]\n */\n overflow -= 2;\n } while (overflow > 0);\n\n /* Now recompute all bit lengths, scanning in increasing frequency.\n * h is still equal to HEAP_SIZE. (It is simpler to reconstruct all\n * lengths instead of fixing only the wrong ones. This idea is taken\n * from 'ar' written by Haruhiko Okumura.)\n */\n for (bits = max_length; bits !== 0; bits--) {\n n = s.bl_count[bits];\n while (n !== 0) {\n m = s.heap[--h];\n if (m > max_code) { continue; }\n if (tree[m * 2 + 1]/*.Len*/ !== bits) {\n // Tracev((stderr,\"code %d bits %d->%d\\n\", m, tree[m].Len, bits));\n s.opt_len += (bits - tree[m * 2 + 1]/*.Len*/) * tree[m * 2]/*.Freq*/;\n tree[m * 2 + 1]/*.Len*/ = bits;\n }\n n--;\n }\n }\n};\n\n\n/* ===========================================================================\n * Generate the codes for a given tree and bit counts (which need not be\n * optimal).\n * IN assertion: the array bl_count contains the bit length statistics for\n * the given tree and the field len is set for all tree elements.\n * OUT assertion: the field code is set for all tree elements of non\n * zero code length.\n */\nconst gen_codes = (tree, max_code, bl_count) => {\n// ct_data *tree; /* the tree to decorate */\n// int max_code; /* largest code with non zero frequency */\n// ushf *bl_count; /* number of codes at each bit length */\n\n const next_code = new Array(MAX_BITS$1 + 1); /* next code value for each bit length */\n let code = 0; /* running code value */\n let bits; /* bit index */\n let n; /* code index */\n\n /* The distribution counts are first used to generate the code values\n * without bit reversal.\n */\n for (bits = 1; bits <= MAX_BITS$1; bits++) {\n code = (code + bl_count[bits - 1]) << 1;\n next_code[bits] = code;\n }\n /* Check that the bit counts in bl_count are consistent. The last code\n * must be all ones.\n */\n //Assert (code + bl_count[MAX_BITS]-1 == (1< {\n\n let n; /* iterates over tree elements */\n let bits; /* bit counter */\n let length; /* length value */\n let code; /* code value */\n let dist; /* distance index */\n const bl_count = new Array(MAX_BITS$1 + 1);\n /* number of codes at each bit length for an optimal tree */\n\n // do check in _tr_init()\n //if (static_init_done) return;\n\n /* For some embedded targets, global variables are not initialized: */\n/*#ifdef NO_INIT_GLOBAL_POINTERS\n static_l_desc.static_tree = static_ltree;\n static_l_desc.extra_bits = extra_lbits;\n static_d_desc.static_tree = static_dtree;\n static_d_desc.extra_bits = extra_dbits;\n static_bl_desc.extra_bits = extra_blbits;\n#endif*/\n\n /* Initialize the mapping length (0..255) -> length code (0..28) */\n length = 0;\n for (code = 0; code < LENGTH_CODES$1 - 1; code++) {\n base_length[code] = length;\n for (n = 0; n < (1 << extra_lbits[code]); n++) {\n _length_code[length++] = code;\n }\n }\n //Assert (length == 256, \"tr_static_init: length != 256\");\n /* Note that the length 255 (match length 258) can be represented\n * in two different ways: code 284 + 5 bits or code 285, so we\n * overwrite length_code[255] to use the best encoding:\n */\n _length_code[length - 1] = code;\n\n /* Initialize the mapping dist (0..32K) -> dist code (0..29) */\n dist = 0;\n for (code = 0; code < 16; code++) {\n base_dist[code] = dist;\n for (n = 0; n < (1 << extra_dbits[code]); n++) {\n _dist_code[dist++] = code;\n }\n }\n //Assert (dist == 256, \"tr_static_init: dist != 256\");\n dist >>= 7; /* from now on, all distances are divided by 128 */\n for (; code < D_CODES$1; code++) {\n base_dist[code] = dist << 7;\n for (n = 0; n < (1 << (extra_dbits[code] - 7)); n++) {\n _dist_code[256 + dist++] = code;\n }\n }\n //Assert (dist == 256, \"tr_static_init: 256+dist != 512\");\n\n /* Construct the codes of the static literal tree */\n for (bits = 0; bits <= MAX_BITS$1; bits++) {\n bl_count[bits] = 0;\n }\n\n n = 0;\n while (n <= 143) {\n static_ltree[n * 2 + 1]/*.Len*/ = 8;\n n++;\n bl_count[8]++;\n }\n while (n <= 255) {\n static_ltree[n * 2 + 1]/*.Len*/ = 9;\n n++;\n bl_count[9]++;\n }\n while (n <= 279) {\n static_ltree[n * 2 + 1]/*.Len*/ = 7;\n n++;\n bl_count[7]++;\n }\n while (n <= 287) {\n static_ltree[n * 2 + 1]/*.Len*/ = 8;\n n++;\n bl_count[8]++;\n }\n /* Codes 286 and 287 do not exist, but we must include them in the\n * tree construction to get a canonical Huffman tree (longest code\n * all ones)\n */\n gen_codes(static_ltree, L_CODES$1 + 1, bl_count);\n\n /* The static distance tree is trivial: */\n for (n = 0; n < D_CODES$1; n++) {\n static_dtree[n * 2 + 1]/*.Len*/ = 5;\n static_dtree[n * 2]/*.Code*/ = bi_reverse(n, 5);\n }\n\n // Now data ready and we can init static trees\n static_l_desc = new StaticTreeDesc(static_ltree, extra_lbits, LITERALS$1 + 1, L_CODES$1, MAX_BITS$1);\n static_d_desc = new StaticTreeDesc(static_dtree, extra_dbits, 0, D_CODES$1, MAX_BITS$1);\n static_bl_desc = new StaticTreeDesc(new Array(0), extra_blbits, 0, BL_CODES$1, MAX_BL_BITS);\n\n //static_init_done = true;\n};\n\n\n/* ===========================================================================\n * Initialize a new block.\n */\nconst init_block = (s) => {\n\n let n; /* iterates over tree elements */\n\n /* Initialize the trees. */\n for (n = 0; n < L_CODES$1; n++) { s.dyn_ltree[n * 2]/*.Freq*/ = 0; }\n for (n = 0; n < D_CODES$1; n++) { s.dyn_dtree[n * 2]/*.Freq*/ = 0; }\n for (n = 0; n < BL_CODES$1; n++) { s.bl_tree[n * 2]/*.Freq*/ = 0; }\n\n s.dyn_ltree[END_BLOCK * 2]/*.Freq*/ = 1;\n s.opt_len = s.static_len = 0;\n s.sym_next = s.matches = 0;\n};\n\n\n/* ===========================================================================\n * Flush the bit buffer and align the output on a byte boundary\n */\nconst bi_windup = (s) =>\n{\n if (s.bi_valid > 8) {\n put_short(s, s.bi_buf);\n } else if (s.bi_valid > 0) {\n //put_byte(s, (Byte)s->bi_buf);\n s.pending_buf[s.pending++] = s.bi_buf;\n }\n s.bi_buf = 0;\n s.bi_valid = 0;\n};\n\n/* ===========================================================================\n * Compares to subtrees, using the tree depth as tie breaker when\n * the subtrees have equal frequency. This minimizes the worst case length.\n */\nconst smaller = (tree, n, m, depth) => {\n\n const _n2 = n * 2;\n const _m2 = m * 2;\n return (tree[_n2]/*.Freq*/ < tree[_m2]/*.Freq*/ ||\n (tree[_n2]/*.Freq*/ === tree[_m2]/*.Freq*/ && depth[n] <= depth[m]));\n};\n\n/* ===========================================================================\n * Restore the heap property by moving down the tree starting at node k,\n * exchanging a node with the smallest of its two sons if necessary, stopping\n * when the heap property is re-established (each father smaller than its\n * two sons).\n */\nconst pqdownheap = (s, tree, k) => {\n// deflate_state *s;\n// ct_data *tree; /* the tree to restore */\n// int k; /* node to move down */\n\n const v = s.heap[k];\n let j = k << 1; /* left son of k */\n while (j <= s.heap_len) {\n /* Set j to the smallest of the two sons: */\n if (j < s.heap_len &&\n smaller(tree, s.heap[j + 1], s.heap[j], s.depth)) {\n j++;\n }\n /* Exit if v is smaller than both sons */\n if (smaller(tree, v, s.heap[j], s.depth)) { break; }\n\n /* Exchange v with the smallest son */\n s.heap[k] = s.heap[j];\n k = j;\n\n /* And continue down the tree, setting j to the left son of k */\n j <<= 1;\n }\n s.heap[k] = v;\n};\n\n\n// inlined manually\n// const SMALLEST = 1;\n\n/* ===========================================================================\n * Send the block data compressed using the given Huffman trees\n */\nconst compress_block = (s, ltree, dtree) => {\n// deflate_state *s;\n// const ct_data *ltree; /* literal tree */\n// const ct_data *dtree; /* distance tree */\n\n let dist; /* distance of matched string */\n let lc; /* match length or unmatched char (if dist == 0) */\n let sx = 0; /* running index in sym_buf */\n let code; /* the code to send */\n let extra; /* number of extra bits to send */\n\n if (s.sym_next !== 0) {\n do {\n dist = s.pending_buf[s.sym_buf + sx++] & 0xff;\n dist += (s.pending_buf[s.sym_buf + sx++] & 0xff) << 8;\n lc = s.pending_buf[s.sym_buf + sx++];\n if (dist === 0) {\n send_code(s, lc, ltree); /* send a literal byte */\n //Tracecv(isgraph(lc), (stderr,\" '%c' \", lc));\n } else {\n /* Here, lc is the match length - MIN_MATCH */\n code = _length_code[lc];\n send_code(s, code + LITERALS$1 + 1, ltree); /* send the length code */\n extra = extra_lbits[code];\n if (extra !== 0) {\n lc -= base_length[code];\n send_bits(s, lc, extra); /* send the extra length bits */\n }\n dist--; /* dist is now the match distance - 1 */\n code = d_code(dist);\n //Assert (code < D_CODES, \"bad d_code\");\n\n send_code(s, code, dtree); /* send the distance code */\n extra = extra_dbits[code];\n if (extra !== 0) {\n dist -= base_dist[code];\n send_bits(s, dist, extra); /* send the extra distance bits */\n }\n } /* literal or match pair ? */\n\n /* Check that the overlay between pending_buf and sym_buf is ok: */\n //Assert(s->pending < s->lit_bufsize + sx, \"pendingBuf overflow\");\n\n } while (sx < s.sym_next);\n }\n\n send_code(s, END_BLOCK, ltree);\n};\n\n\n/* ===========================================================================\n * Construct one Huffman tree and assigns the code bit strings and lengths.\n * Update the total bit length for the current block.\n * IN assertion: the field freq is set for all tree elements.\n * OUT assertions: the fields len and code are set to the optimal bit length\n * and corresponding code. The length opt_len is updated; static_len is\n * also updated if stree is not null. The field max_code is set.\n */\nconst build_tree = (s, desc) => {\n// deflate_state *s;\n// tree_desc *desc; /* the tree descriptor */\n\n const tree = desc.dyn_tree;\n const stree = desc.stat_desc.static_tree;\n const has_stree = desc.stat_desc.has_stree;\n const elems = desc.stat_desc.elems;\n let n, m; /* iterate over heap elements */\n let max_code = -1; /* largest code with non zero frequency */\n let node; /* new node being created */\n\n /* Construct the initial heap, with least frequent element in\n * heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n+1].\n * heap[0] is not used.\n */\n s.heap_len = 0;\n s.heap_max = HEAP_SIZE$1;\n\n for (n = 0; n < elems; n++) {\n if (tree[n * 2]/*.Freq*/ !== 0) {\n s.heap[++s.heap_len] = max_code = n;\n s.depth[n] = 0;\n\n } else {\n tree[n * 2 + 1]/*.Len*/ = 0;\n }\n }\n\n /* The pkzip format requires that at least one distance code exists,\n * and that at least one bit should be sent even if there is only one\n * possible code. So to avoid special checks later on we force at least\n * two codes of non zero frequency.\n */\n while (s.heap_len < 2) {\n node = s.heap[++s.heap_len] = (max_code < 2 ? ++max_code : 0);\n tree[node * 2]/*.Freq*/ = 1;\n s.depth[node] = 0;\n s.opt_len--;\n\n if (has_stree) {\n s.static_len -= stree[node * 2 + 1]/*.Len*/;\n }\n /* node is 0 or 1 so it does not have extra bits */\n }\n desc.max_code = max_code;\n\n /* The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree,\n * establish sub-heaps of increasing lengths:\n */\n for (n = (s.heap_len >> 1/*int /2*/); n >= 1; n--) { pqdownheap(s, tree, n); }\n\n /* Construct the Huffman tree by repeatedly combining the least two\n * frequent nodes.\n */\n node = elems; /* next internal node of the tree */\n do {\n //pqremove(s, tree, n); /* n = node of least frequency */\n /*** pqremove ***/\n n = s.heap[1/*SMALLEST*/];\n s.heap[1/*SMALLEST*/] = s.heap[s.heap_len--];\n pqdownheap(s, tree, 1/*SMALLEST*/);\n /***/\n\n m = s.heap[1/*SMALLEST*/]; /* m = node of next least frequency */\n\n s.heap[--s.heap_max] = n; /* keep the nodes sorted by frequency */\n s.heap[--s.heap_max] = m;\n\n /* Create a new node father of n and m */\n tree[node * 2]/*.Freq*/ = tree[n * 2]/*.Freq*/ + tree[m * 2]/*.Freq*/;\n s.depth[node] = (s.depth[n] >= s.depth[m] ? s.depth[n] : s.depth[m]) + 1;\n tree[n * 2 + 1]/*.Dad*/ = tree[m * 2 + 1]/*.Dad*/ = node;\n\n /* and insert the new node in the heap */\n s.heap[1/*SMALLEST*/] = node++;\n pqdownheap(s, tree, 1/*SMALLEST*/);\n\n } while (s.heap_len >= 2);\n\n s.heap[--s.heap_max] = s.heap[1/*SMALLEST*/];\n\n /* At this point, the fields freq and dad are set. We can now\n * generate the bit lengths.\n */\n gen_bitlen(s, desc);\n\n /* The field len is now set, we can generate the bit codes */\n gen_codes(tree, max_code, s.bl_count);\n};\n\n\n/* ===========================================================================\n * Scan a literal or distance tree to determine the frequencies of the codes\n * in the bit length tree.\n */\nconst scan_tree = (s, tree, max_code) => {\n// deflate_state *s;\n// ct_data *tree; /* the tree to be scanned */\n// int max_code; /* and its largest code of non zero frequency */\n\n let n; /* iterates over all tree elements */\n let prevlen = -1; /* last emitted length */\n let curlen; /* length of current code */\n\n let nextlen = tree[0 * 2 + 1]/*.Len*/; /* length of next code */\n\n let count = 0; /* repeat count of the current code */\n let max_count = 7; /* max repeat count */\n let min_count = 4; /* min repeat count */\n\n if (nextlen === 0) {\n max_count = 138;\n min_count = 3;\n }\n tree[(max_code + 1) * 2 + 1]/*.Len*/ = 0xffff; /* guard */\n\n for (n = 0; n <= max_code; n++) {\n curlen = nextlen;\n nextlen = tree[(n + 1) * 2 + 1]/*.Len*/;\n\n if (++count < max_count && curlen === nextlen) {\n continue;\n\n } else if (count < min_count) {\n s.bl_tree[curlen * 2]/*.Freq*/ += count;\n\n } else if (curlen !== 0) {\n\n if (curlen !== prevlen) { s.bl_tree[curlen * 2]/*.Freq*/++; }\n s.bl_tree[REP_3_6 * 2]/*.Freq*/++;\n\n } else if (count <= 10) {\n s.bl_tree[REPZ_3_10 * 2]/*.Freq*/++;\n\n } else {\n s.bl_tree[REPZ_11_138 * 2]/*.Freq*/++;\n }\n\n count = 0;\n prevlen = curlen;\n\n if (nextlen === 0) {\n max_count = 138;\n min_count = 3;\n\n } else if (curlen === nextlen) {\n max_count = 6;\n min_count = 3;\n\n } else {\n max_count = 7;\n min_count = 4;\n }\n }\n};\n\n\n/* ===========================================================================\n * Send a literal or distance tree in compressed form, using the codes in\n * bl_tree.\n */\nconst send_tree = (s, tree, max_code) => {\n// deflate_state *s;\n// ct_data *tree; /* the tree to be scanned */\n// int max_code; /* and its largest code of non zero frequency */\n\n let n; /* iterates over all tree elements */\n let prevlen = -1; /* last emitted length */\n let curlen; /* length of current code */\n\n let nextlen = tree[0 * 2 + 1]/*.Len*/; /* length of next code */\n\n let count = 0; /* repeat count of the current code */\n let max_count = 7; /* max repeat count */\n let min_count = 4; /* min repeat count */\n\n /* tree[max_code+1].Len = -1; */ /* guard already set */\n if (nextlen === 0) {\n max_count = 138;\n min_count = 3;\n }\n\n for (n = 0; n <= max_code; n++) {\n curlen = nextlen;\n nextlen = tree[(n + 1) * 2 + 1]/*.Len*/;\n\n if (++count < max_count && curlen === nextlen) {\n continue;\n\n } else if (count < min_count) {\n do { send_code(s, curlen, s.bl_tree); } while (--count !== 0);\n\n } else if (curlen !== 0) {\n if (curlen !== prevlen) {\n send_code(s, curlen, s.bl_tree);\n count--;\n }\n //Assert(count >= 3 && count <= 6, \" 3_6?\");\n send_code(s, REP_3_6, s.bl_tree);\n send_bits(s, count - 3, 2);\n\n } else if (count <= 10) {\n send_code(s, REPZ_3_10, s.bl_tree);\n send_bits(s, count - 3, 3);\n\n } else {\n send_code(s, REPZ_11_138, s.bl_tree);\n send_bits(s, count - 11, 7);\n }\n\n count = 0;\n prevlen = curlen;\n if (nextlen === 0) {\n max_count = 138;\n min_count = 3;\n\n } else if (curlen === nextlen) {\n max_count = 6;\n min_count = 3;\n\n } else {\n max_count = 7;\n min_count = 4;\n }\n }\n};\n\n\n/* ===========================================================================\n * Construct the Huffman tree for the bit lengths and return the index in\n * bl_order of the last bit length code to send.\n */\nconst build_bl_tree = (s) => {\n\n let max_blindex; /* index of last bit length code of non zero freq */\n\n /* Determine the bit length frequencies for literal and distance trees */\n scan_tree(s, s.dyn_ltree, s.l_desc.max_code);\n scan_tree(s, s.dyn_dtree, s.d_desc.max_code);\n\n /* Build the bit length tree: */\n build_tree(s, s.bl_desc);\n /* opt_len now includes the length of the tree representations, except\n * the lengths of the bit lengths codes and the 5+5+4 bits for the counts.\n */\n\n /* Determine the number of bit length codes to send. The pkzip format\n * requires that at least 4 bit length codes be sent. (appnote.txt says\n * 3 but the actual value used is 4.)\n */\n for (max_blindex = BL_CODES$1 - 1; max_blindex >= 3; max_blindex--) {\n if (s.bl_tree[bl_order[max_blindex] * 2 + 1]/*.Len*/ !== 0) {\n break;\n }\n }\n /* Update opt_len to include the bit length tree and counts */\n s.opt_len += 3 * (max_blindex + 1) + 5 + 5 + 4;\n //Tracev((stderr, \"\\ndyn trees: dyn %ld, stat %ld\",\n // s->opt_len, s->static_len));\n\n return max_blindex;\n};\n\n\n/* ===========================================================================\n * Send the header for a block using dynamic Huffman trees: the counts, the\n * lengths of the bit length codes, the literal tree and the distance tree.\n * IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4.\n */\nconst send_all_trees = (s, lcodes, dcodes, blcodes) => {\n// deflate_state *s;\n// int lcodes, dcodes, blcodes; /* number of codes for each tree */\n\n let rank; /* index in bl_order */\n\n //Assert (lcodes >= 257 && dcodes >= 1 && blcodes >= 4, \"not enough codes\");\n //Assert (lcodes <= L_CODES && dcodes <= D_CODES && blcodes <= BL_CODES,\n // \"too many codes\");\n //Tracev((stderr, \"\\nbl counts: \"));\n send_bits(s, lcodes - 257, 5); /* not +255 as stated in appnote.txt */\n send_bits(s, dcodes - 1, 5);\n send_bits(s, blcodes - 4, 4); /* not -3 as stated in appnote.txt */\n for (rank = 0; rank < blcodes; rank++) {\n //Tracev((stderr, \"\\nbl code %2d \", bl_order[rank]));\n send_bits(s, s.bl_tree[bl_order[rank] * 2 + 1]/*.Len*/, 3);\n }\n //Tracev((stderr, \"\\nbl tree: sent %ld\", s->bits_sent));\n\n send_tree(s, s.dyn_ltree, lcodes - 1); /* literal tree */\n //Tracev((stderr, \"\\nlit tree: sent %ld\", s->bits_sent));\n\n send_tree(s, s.dyn_dtree, dcodes - 1); /* distance tree */\n //Tracev((stderr, \"\\ndist tree: sent %ld\", s->bits_sent));\n};\n\n\n/* ===========================================================================\n * Check if the data type is TEXT or BINARY, using the following algorithm:\n * - TEXT if the two conditions below are satisfied:\n * a) There are no non-portable control characters belonging to the\n * \"block list\" (0..6, 14..25, 28..31).\n * b) There is at least one printable character belonging to the\n * \"allow list\" (9 {TAB}, 10 {LF}, 13 {CR}, 32..255).\n * - BINARY otherwise.\n * - The following partially-portable control characters form a\n * \"gray list\" that is ignored in this detection algorithm:\n * (7 {BEL}, 8 {BS}, 11 {VT}, 12 {FF}, 26 {SUB}, 27 {ESC}).\n * IN assertion: the fields Freq of dyn_ltree are set.\n */\nconst detect_data_type = (s) => {\n /* block_mask is the bit mask of block-listed bytes\n * set bits 0..6, 14..25, and 28..31\n * 0xf3ffc07f = binary 11110011111111111100000001111111\n */\n let block_mask = 0xf3ffc07f;\n let n;\n\n /* Check for non-textual (\"block-listed\") bytes. */\n for (n = 0; n <= 31; n++, block_mask >>>= 1) {\n if ((block_mask & 1) && (s.dyn_ltree[n * 2]/*.Freq*/ !== 0)) {\n return Z_BINARY;\n }\n }\n\n /* Check for textual (\"allow-listed\") bytes. */\n if (s.dyn_ltree[9 * 2]/*.Freq*/ !== 0 || s.dyn_ltree[10 * 2]/*.Freq*/ !== 0 ||\n s.dyn_ltree[13 * 2]/*.Freq*/ !== 0) {\n return Z_TEXT;\n }\n for (n = 32; n < LITERALS$1; n++) {\n if (s.dyn_ltree[n * 2]/*.Freq*/ !== 0) {\n return Z_TEXT;\n }\n }\n\n /* There are no \"block-listed\" or \"allow-listed\" bytes:\n * this stream either is empty or has tolerated (\"gray-listed\") bytes only.\n */\n return Z_BINARY;\n};\n\n\nlet static_init_done = false;\n\n/* ===========================================================================\n * Initialize the tree data structures for a new zlib stream.\n */\nconst _tr_init$1 = (s) =>\n{\n\n if (!static_init_done) {\n tr_static_init();\n static_init_done = true;\n }\n\n s.l_desc = new TreeDesc(s.dyn_ltree, static_l_desc);\n s.d_desc = new TreeDesc(s.dyn_dtree, static_d_desc);\n s.bl_desc = new TreeDesc(s.bl_tree, static_bl_desc);\n\n s.bi_buf = 0;\n s.bi_valid = 0;\n\n /* Initialize the first block of the first file: */\n init_block(s);\n};\n\n\n/* ===========================================================================\n * Send a stored block\n */\nconst _tr_stored_block$1 = (s, buf, stored_len, last) => {\n//DeflateState *s;\n//charf *buf; /* input block */\n//ulg stored_len; /* length of input block */\n//int last; /* one if this is the last block for a file */\n\n send_bits(s, (STORED_BLOCK << 1) + (last ? 1 : 0), 3); /* send block type */\n bi_windup(s); /* align on byte boundary */\n put_short(s, stored_len);\n put_short(s, ~stored_len);\n if (stored_len) {\n s.pending_buf.set(s.window.subarray(buf, buf + stored_len), s.pending);\n }\n s.pending += stored_len;\n};\n\n\n/* ===========================================================================\n * Send one empty static block to give enough lookahead for inflate.\n * This takes 10 bits, of which 7 may remain in the bit buffer.\n */\nconst _tr_align$1 = (s) => {\n send_bits(s, STATIC_TREES << 1, 3);\n send_code(s, END_BLOCK, static_ltree);\n bi_flush(s);\n};\n\n\n/* ===========================================================================\n * Determine the best encoding for the current block: dynamic trees, static\n * trees or store, and write out the encoded block.\n */\nconst _tr_flush_block$1 = (s, buf, stored_len, last) => {\n//DeflateState *s;\n//charf *buf; /* input block, or NULL if too old */\n//ulg stored_len; /* length of input block */\n//int last; /* one if this is the last block for a file */\n\n let opt_lenb, static_lenb; /* opt_len and static_len in bytes */\n let max_blindex = 0; /* index of last bit length code of non zero freq */\n\n /* Build the Huffman trees unless a stored block is forced */\n if (s.level > 0) {\n\n /* Check if the file is binary or text */\n if (s.strm.data_type === Z_UNKNOWN$1) {\n s.strm.data_type = detect_data_type(s);\n }\n\n /* Construct the literal and distance trees */\n build_tree(s, s.l_desc);\n // Tracev((stderr, \"\\nlit data: dyn %ld, stat %ld\", s->opt_len,\n // s->static_len));\n\n build_tree(s, s.d_desc);\n // Tracev((stderr, \"\\ndist data: dyn %ld, stat %ld\", s->opt_len,\n // s->static_len));\n /* At this point, opt_len and static_len are the total bit lengths of\n * the compressed block data, excluding the tree representations.\n */\n\n /* Build the bit length tree for the above two trees, and get the index\n * in bl_order of the last bit length code to send.\n */\n max_blindex = build_bl_tree(s);\n\n /* Determine the best encoding. Compute the block lengths in bytes. */\n opt_lenb = (s.opt_len + 3 + 7) >>> 3;\n static_lenb = (s.static_len + 3 + 7) >>> 3;\n\n // Tracev((stderr, \"\\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u \",\n // opt_lenb, s->opt_len, static_lenb, s->static_len, stored_len,\n // s->sym_next / 3));\n\n if (static_lenb <= opt_lenb) { opt_lenb = static_lenb; }\n\n } else {\n // Assert(buf != (char*)0, \"lost buf\");\n opt_lenb = static_lenb = stored_len + 5; /* force a stored block */\n }\n\n if ((stored_len + 4 <= opt_lenb) && (buf !== -1)) {\n /* 4: two words for the lengths */\n\n /* The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE.\n * Otherwise we can't have processed more than WSIZE input bytes since\n * the last block flush, because compression would have been\n * successful. If LIT_BUFSIZE <= WSIZE, it is never too late to\n * transform a block into a stored block.\n */\n _tr_stored_block$1(s, buf, stored_len, last);\n\n } else if (s.strategy === Z_FIXED$1 || static_lenb === opt_lenb) {\n\n send_bits(s, (STATIC_TREES << 1) + (last ? 1 : 0), 3);\n compress_block(s, static_ltree, static_dtree);\n\n } else {\n send_bits(s, (DYN_TREES << 1) + (last ? 1 : 0), 3);\n send_all_trees(s, s.l_desc.max_code + 1, s.d_desc.max_code + 1, max_blindex + 1);\n compress_block(s, s.dyn_ltree, s.dyn_dtree);\n }\n // Assert (s->compressed_len == s->bits_sent, \"bad compressed size\");\n /* The above check is made mod 2^32, for files larger than 512 MB\n * and uLong implemented on 32 bits.\n */\n init_block(s);\n\n if (last) {\n bi_windup(s);\n }\n // Tracev((stderr,\"\\ncomprlen %lu(%lu) \", s->compressed_len>>3,\n // s->compressed_len-7*last));\n};\n\n/* ===========================================================================\n * Save the match info and tally the frequency counts. Return true if\n * the current block must be flushed.\n */\nconst _tr_tally$1 = (s, dist, lc) => {\n// deflate_state *s;\n// unsigned dist; /* distance of matched string */\n// unsigned lc; /* match length-MIN_MATCH or unmatched char (if dist==0) */\n\n s.pending_buf[s.sym_buf + s.sym_next++] = dist;\n s.pending_buf[s.sym_buf + s.sym_next++] = dist >> 8;\n s.pending_buf[s.sym_buf + s.sym_next++] = lc;\n if (dist === 0) {\n /* lc is the unmatched char */\n s.dyn_ltree[lc * 2]/*.Freq*/++;\n } else {\n s.matches++;\n /* Here, lc is the match length - MIN_MATCH */\n dist--; /* dist = match distance - 1 */\n //Assert((ush)dist < (ush)MAX_DIST(s) &&\n // (ush)lc <= (ush)(MAX_MATCH-MIN_MATCH) &&\n // (ush)d_code(dist) < (ush)D_CODES, \"_tr_tally: bad match\");\n\n s.dyn_ltree[(_length_code[lc] + LITERALS$1 + 1) * 2]/*.Freq*/++;\n s.dyn_dtree[d_code(dist) * 2]/*.Freq*/++;\n }\n\n return (s.sym_next === s.sym_end);\n};\n\nvar _tr_init_1 = _tr_init$1;\nvar _tr_stored_block_1 = _tr_stored_block$1;\nvar _tr_flush_block_1 = _tr_flush_block$1;\nvar _tr_tally_1 = _tr_tally$1;\nvar _tr_align_1 = _tr_align$1;\n\nvar trees = {\n\t_tr_init: _tr_init_1,\n\t_tr_stored_block: _tr_stored_block_1,\n\t_tr_flush_block: _tr_flush_block_1,\n\t_tr_tally: _tr_tally_1,\n\t_tr_align: _tr_align_1\n};\n\n// Note: adler32 takes 12% for level 0 and 2% for level 6.\n// It isn't worth it to make additional optimizations as in original.\n// Small size is preferable.\n\n// (C) 1995-2013 Jean-loup Gailly and Mark Adler\n// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin\n//\n// This software is provided 'as-is', without any express or implied\n// warranty. In no event will the authors be held liable for any damages\n// arising from the use of this software.\n//\n// Permission is granted to anyone to use this software for any purpose,\n// including commercial applications, and to alter it and redistribute it\n// freely, subject to the following restrictions:\n//\n// 1. The origin of this software must not be misrepresented; you must not\n// claim that you wrote the original software. If you use this software\n// in a product, an acknowledgment in the product documentation would be\n// appreciated but is not required.\n// 2. Altered source versions must be plainly marked as such, and must not be\n// misrepresented as being the original software.\n// 3. This notice may not be removed or altered from any source distribution.\n\nconst adler32 = (adler, buf, len, pos) => {\n let s1 = (adler & 0xffff) |0,\n s2 = ((adler >>> 16) & 0xffff) |0,\n n = 0;\n\n while (len !== 0) {\n // Set limit ~ twice less than 5552, to keep\n // s2 in 31-bits, because we force signed ints.\n // in other case %= will fail.\n n = len > 2000 ? 2000 : len;\n len -= n;\n\n do {\n s1 = (s1 + buf[pos++]) |0;\n s2 = (s2 + s1) |0;\n } while (--n);\n\n s1 %= 65521;\n s2 %= 65521;\n }\n\n return (s1 | (s2 << 16)) |0;\n};\n\n\nvar adler32_1 = adler32;\n\n// Note: we can't get significant speed boost here.\n// So write code to minimize size - no pregenerated tables\n// and array tools dependencies.\n\n// (C) 1995-2013 Jean-loup Gailly and Mark Adler\n// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin\n//\n// This software is provided 'as-is', without any express or implied\n// warranty. In no event will the authors be held liable for any damages\n// arising from the use of this software.\n//\n// Permission is granted to anyone to use this software for any purpose,\n// including commercial applications, and to alter it and redistribute it\n// freely, subject to the following restrictions:\n//\n// 1. The origin of this software must not be misrepresented; you must not\n// claim that you wrote the original software. If you use this software\n// in a product, an acknowledgment in the product documentation would be\n// appreciated but is not required.\n// 2. Altered source versions must be plainly marked as such, and must not be\n// misrepresented as being the original software.\n// 3. This notice may not be removed or altered from any source distribution.\n\n// Use ordinary array, since untyped makes no boost here\nconst makeTable = () => {\n let c, table = [];\n\n for (var n = 0; n < 256; n++) {\n c = n;\n for (var k = 0; k < 8; k++) {\n c = ((c & 1) ? (0xEDB88320 ^ (c >>> 1)) : (c >>> 1));\n }\n table[n] = c;\n }\n\n return table;\n};\n\n// Create table on load. Just 255 signed longs. Not a problem.\nconst crcTable = new Uint32Array(makeTable());\n\n\nconst crc32 = (crc, buf, len, pos) => {\n const t = crcTable;\n const end = pos + len;\n\n crc ^= -1;\n\n for (let i = pos; i < end; i++) {\n crc = (crc >>> 8) ^ t[(crc ^ buf[i]) & 0xFF];\n }\n\n return (crc ^ (-1)); // >>> 0;\n};\n\n\nvar crc32_1 = crc32;\n\n// (C) 1995-2013 Jean-loup Gailly and Mark Adler\n// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin\n//\n// This software is provided 'as-is', without any express or implied\n// warranty. In no event will the authors be held liable for any damages\n// arising from the use of this software.\n//\n// Permission is granted to anyone to use this software for any purpose,\n// including commercial applications, and to alter it and redistribute it\n// freely, subject to the following restrictions:\n//\n// 1. The origin of this software must not be misrepresented; you must not\n// claim that you wrote the original software. If you use this software\n// in a product, an acknowledgment in the product documentation would be\n// appreciated but is not required.\n// 2. Altered source versions must be plainly marked as such, and must not be\n// misrepresented as being the original software.\n// 3. This notice may not be removed or altered from any source distribution.\n\nvar messages = {\n 2: 'need dictionary', /* Z_NEED_DICT 2 */\n 1: 'stream end', /* Z_STREAM_END 1 */\n 0: '', /* Z_OK 0 */\n '-1': 'file error', /* Z_ERRNO (-1) */\n '-2': 'stream error', /* Z_STREAM_ERROR (-2) */\n '-3': 'data error', /* Z_DATA_ERROR (-3) */\n '-4': 'insufficient memory', /* Z_MEM_ERROR (-4) */\n '-5': 'buffer error', /* Z_BUF_ERROR (-5) */\n '-6': 'incompatible version' /* Z_VERSION_ERROR (-6) */\n};\n\n// (C) 1995-2013 Jean-loup Gailly and Mark Adler\n// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin\n//\n// This software is provided 'as-is', without any express or implied\n// warranty. In no event will the authors be held liable for any damages\n// arising from the use of this software.\n//\n// Permission is granted to anyone to use this software for any purpose,\n// including commercial applications, and to alter it and redistribute it\n// freely, subject to the following restrictions:\n//\n// 1. The origin of this software must not be misrepresented; you must not\n// claim that you wrote the original software. If you use this software\n// in a product, an acknowledgment in the product documentation would be\n// appreciated but is not required.\n// 2. Altered source versions must be plainly marked as such, and must not be\n// misrepresented as being the original software.\n// 3. This notice may not be removed or altered from any source distribution.\n\nvar constants$2 = {\n\n /* Allowed flush values; see deflate() and inflate() below for details */\n Z_NO_FLUSH: 0,\n Z_PARTIAL_FLUSH: 1,\n Z_SYNC_FLUSH: 2,\n Z_FULL_FLUSH: 3,\n Z_FINISH: 4,\n Z_BLOCK: 5,\n Z_TREES: 6,\n\n /* Return codes for the compression/decompression functions. Negative values\n * are errors, positive values are used for special but normal events.\n */\n Z_OK: 0,\n Z_STREAM_END: 1,\n Z_NEED_DICT: 2,\n Z_ERRNO: -1,\n Z_STREAM_ERROR: -2,\n Z_DATA_ERROR: -3,\n Z_MEM_ERROR: -4,\n Z_BUF_ERROR: -5,\n //Z_VERSION_ERROR: -6,\n\n /* compression levels */\n Z_NO_COMPRESSION: 0,\n Z_BEST_SPEED: 1,\n Z_BEST_COMPRESSION: 9,\n Z_DEFAULT_COMPRESSION: -1,\n\n\n Z_FILTERED: 1,\n Z_HUFFMAN_ONLY: 2,\n Z_RLE: 3,\n Z_FIXED: 4,\n Z_DEFAULT_STRATEGY: 0,\n\n /* Possible values of the data_type field (though see inflate()) */\n Z_BINARY: 0,\n Z_TEXT: 1,\n //Z_ASCII: 1, // = Z_TEXT (deprecated)\n Z_UNKNOWN: 2,\n\n /* The deflate compression method */\n Z_DEFLATED: 8\n //Z_NULL: null // Use -1 or null inline, depending on var type\n};\n\n// (C) 1995-2013 Jean-loup Gailly and Mark Adler\n// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin\n//\n// This software is provided 'as-is', without any express or implied\n// warranty. In no event will the authors be held liable for any damages\n// arising from the use of this software.\n//\n// Permission is granted to anyone to use this software for any purpose,\n// including commercial applications, and to alter it and redistribute it\n// freely, subject to the following restrictions:\n//\n// 1. The origin of this software must not be misrepresented; you must not\n// claim that you wrote the original software. If you use this software\n// in a product, an acknowledgment in the product documentation would be\n// appreciated but is not required.\n// 2. Altered source versions must be plainly marked as such, and must not be\n// misrepresented as being the original software.\n// 3. This notice may not be removed or altered from any source distribution.\n\nconst { _tr_init, _tr_stored_block, _tr_flush_block, _tr_tally, _tr_align } = trees;\n\n\n\n\n/* Public constants ==========================================================*/\n/* ===========================================================================*/\n\nconst {\n Z_NO_FLUSH: Z_NO_FLUSH$2, Z_PARTIAL_FLUSH, Z_FULL_FLUSH: Z_FULL_FLUSH$1, Z_FINISH: Z_FINISH$3, Z_BLOCK: Z_BLOCK$1,\n Z_OK: Z_OK$3, Z_STREAM_END: Z_STREAM_END$3, Z_STREAM_ERROR: Z_STREAM_ERROR$2, Z_DATA_ERROR: Z_DATA_ERROR$2, Z_BUF_ERROR: Z_BUF_ERROR$1,\n Z_DEFAULT_COMPRESSION: Z_DEFAULT_COMPRESSION$1,\n Z_FILTERED, Z_HUFFMAN_ONLY, Z_RLE, Z_FIXED, Z_DEFAULT_STRATEGY: Z_DEFAULT_STRATEGY$1,\n Z_UNKNOWN,\n Z_DEFLATED: Z_DEFLATED$2\n} = constants$2;\n\n/*============================================================================*/\n\n\nconst MAX_MEM_LEVEL = 9;\n/* Maximum value for memLevel in deflateInit2 */\nconst MAX_WBITS$1 = 15;\n/* 32K LZ77 window */\nconst DEF_MEM_LEVEL = 8;\n\n\nconst LENGTH_CODES = 29;\n/* number of length codes, not counting the special END_BLOCK code */\nconst LITERALS = 256;\n/* number of literal bytes 0..255 */\nconst L_CODES = LITERALS + 1 + LENGTH_CODES;\n/* number of Literal or Length codes, including the END_BLOCK code */\nconst D_CODES = 30;\n/* number of distance codes */\nconst BL_CODES = 19;\n/* number of codes used to transfer the bit lengths */\nconst HEAP_SIZE = 2 * L_CODES + 1;\n/* maximum heap size */\nconst MAX_BITS = 15;\n/* All codes must not exceed MAX_BITS bits */\n\nconst MIN_MATCH = 3;\nconst MAX_MATCH = 258;\nconst MIN_LOOKAHEAD = (MAX_MATCH + MIN_MATCH + 1);\n\nconst PRESET_DICT = 0x20;\n\nconst INIT_STATE = 42; /* zlib header -> BUSY_STATE */\n//#ifdef GZIP\nconst GZIP_STATE = 57; /* gzip header -> BUSY_STATE | EXTRA_STATE */\n//#endif\nconst EXTRA_STATE = 69; /* gzip extra block -> NAME_STATE */\nconst NAME_STATE = 73; /* gzip file name -> COMMENT_STATE */\nconst COMMENT_STATE = 91; /* gzip comment -> HCRC_STATE */\nconst HCRC_STATE = 103; /* gzip header CRC -> BUSY_STATE */\nconst BUSY_STATE = 113; /* deflate -> FINISH_STATE */\nconst FINISH_STATE = 666; /* stream complete */\n\nconst BS_NEED_MORE = 1; /* block not completed, need more input or more output */\nconst BS_BLOCK_DONE = 2; /* block flush performed */\nconst BS_FINISH_STARTED = 3; /* finish started, need only more output at next deflate */\nconst BS_FINISH_DONE = 4; /* finish done, accept no more input or output */\n\nconst OS_CODE = 0x03; // Unix :) . Don't detect, use this default.\n\nconst err = (strm, errorCode) => {\n strm.msg = messages[errorCode];\n return errorCode;\n};\n\nconst rank = (f) => {\n return ((f) * 2) - ((f) > 4 ? 9 : 0);\n};\n\nconst zero = (buf) => {\n let len = buf.length; while (--len >= 0) { buf[len] = 0; }\n};\n\n/* ===========================================================================\n * Slide the hash table when sliding the window down (could be avoided with 32\n * bit values at the expense of memory usage). We slide even when level == 0 to\n * keep the hash table consistent if we switch back to level > 0 later.\n */\nconst slide_hash = (s) => {\n let n, m;\n let p;\n let wsize = s.w_size;\n\n n = s.hash_size;\n p = n;\n do {\n m = s.head[--p];\n s.head[p] = (m >= wsize ? m - wsize : 0);\n } while (--n);\n n = wsize;\n//#ifndef FASTEST\n p = n;\n do {\n m = s.prev[--p];\n s.prev[p] = (m >= wsize ? m - wsize : 0);\n /* If n is not on any hash chain, prev[n] is garbage but\n * its value will never be used.\n */\n } while (--n);\n//#endif\n};\n\n/* eslint-disable new-cap */\nlet HASH_ZLIB = (s, prev, data) => ((prev << s.hash_shift) ^ data) & s.hash_mask;\n// This hash causes less collisions, https://github.com/nodeca/pako/issues/135\n// But breaks binary compatibility\n//let HASH_FAST = (s, prev, data) => ((prev << 8) + (prev >> 8) + (data << 4)) & s.hash_mask;\nlet HASH = HASH_ZLIB;\n\n\n/* =========================================================================\n * Flush as much pending output as possible. All deflate() output, except for\n * some deflate_stored() output, goes through this function so some\n * applications may wish to modify it to avoid allocating a large\n * strm->next_out buffer and copying into it. (See also read_buf()).\n */\nconst flush_pending = (strm) => {\n const s = strm.state;\n\n //_tr_flush_bits(s);\n let len = s.pending;\n if (len > strm.avail_out) {\n len = strm.avail_out;\n }\n if (len === 0) { return; }\n\n strm.output.set(s.pending_buf.subarray(s.pending_out, s.pending_out + len), strm.next_out);\n strm.next_out += len;\n s.pending_out += len;\n strm.total_out += len;\n strm.avail_out -= len;\n s.pending -= len;\n if (s.pending === 0) {\n s.pending_out = 0;\n }\n};\n\n\nconst flush_block_only = (s, last) => {\n _tr_flush_block(s, (s.block_start >= 0 ? s.block_start : -1), s.strstart - s.block_start, last);\n s.block_start = s.strstart;\n flush_pending(s.strm);\n};\n\n\nconst put_byte = (s, b) => {\n s.pending_buf[s.pending++] = b;\n};\n\n\n/* =========================================================================\n * Put a short in the pending buffer. The 16-bit value is put in MSB order.\n * IN assertion: the stream state is correct and there is enough room in\n * pending_buf.\n */\nconst putShortMSB = (s, b) => {\n\n // put_byte(s, (Byte)(b >> 8));\n// put_byte(s, (Byte)(b & 0xff));\n s.pending_buf[s.pending++] = (b >>> 8) & 0xff;\n s.pending_buf[s.pending++] = b & 0xff;\n};\n\n\n/* ===========================================================================\n * Read a new buffer from the current input stream, update the adler32\n * and total number of bytes read. All deflate() input goes through\n * this function so some applications may wish to modify it to avoid\n * allocating a large strm->input buffer and copying from it.\n * (See also flush_pending()).\n */\nconst read_buf = (strm, buf, start, size) => {\n\n let len = strm.avail_in;\n\n if (len > size) { len = size; }\n if (len === 0) { return 0; }\n\n strm.avail_in -= len;\n\n // zmemcpy(buf, strm->next_in, len);\n buf.set(strm.input.subarray(strm.next_in, strm.next_in + len), start);\n if (strm.state.wrap === 1) {\n strm.adler = adler32_1(strm.adler, buf, len, start);\n }\n\n else if (strm.state.wrap === 2) {\n strm.adler = crc32_1(strm.adler, buf, len, start);\n }\n\n strm.next_in += len;\n strm.total_in += len;\n\n return len;\n};\n\n\n/* ===========================================================================\n * Set match_start to the longest match starting at the given string and\n * return its length. Matches shorter or equal to prev_length are discarded,\n * in which case the result is equal to prev_length and match_start is\n * garbage.\n * IN assertions: cur_match is the head of the hash chain for the current\n * string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1\n * OUT assertion: the match length is not greater than s->lookahead.\n */\nconst longest_match = (s, cur_match) => {\n\n let chain_length = s.max_chain_length; /* max hash chain length */\n let scan = s.strstart; /* current string */\n let match; /* matched string */\n let len; /* length of current match */\n let best_len = s.prev_length; /* best match length so far */\n let nice_match = s.nice_match; /* stop if match long enough */\n const limit = (s.strstart > (s.w_size - MIN_LOOKAHEAD)) ?\n s.strstart - (s.w_size - MIN_LOOKAHEAD) : 0/*NIL*/;\n\n const _win = s.window; // shortcut\n\n const wmask = s.w_mask;\n const prev = s.prev;\n\n /* Stop when cur_match becomes <= limit. To simplify the code,\n * we prevent matches with the string of window index 0.\n */\n\n const strend = s.strstart + MAX_MATCH;\n let scan_end1 = _win[scan + best_len - 1];\n let scan_end = _win[scan + best_len];\n\n /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16.\n * It is easy to get rid of this optimization if necessary.\n */\n // Assert(s->hash_bits >= 8 && MAX_MATCH == 258, \"Code too clever\");\n\n /* Do not waste too much time if we already have a good match: */\n if (s.prev_length >= s.good_match) {\n chain_length >>= 2;\n }\n /* Do not look for matches beyond the end of the input. This is necessary\n * to make deflate deterministic.\n */\n if (nice_match > s.lookahead) { nice_match = s.lookahead; }\n\n // Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, \"need lookahead\");\n\n do {\n // Assert(cur_match < s->strstart, \"no future\");\n match = cur_match;\n\n /* Skip to next match if the match length cannot increase\n * or if the match length is less than 2. Note that the checks below\n * for insufficient lookahead only occur occasionally for performance\n * reasons. Therefore uninitialized memory will be accessed, and\n * conditional jumps will be made that depend on those values.\n * However the length of the match is limited to the lookahead, so\n * the output of deflate is not affected by the uninitialized values.\n */\n\n if (_win[match + best_len] !== scan_end ||\n _win[match + best_len - 1] !== scan_end1 ||\n _win[match] !== _win[scan] ||\n _win[++match] !== _win[scan + 1]) {\n continue;\n }\n\n /* The check at best_len-1 can be removed because it will be made\n * again later. (This heuristic is not always a win.)\n * It is not necessary to compare scan[2] and match[2] since they\n * are always equal when the other bytes match, given that\n * the hash keys are equal and that HASH_BITS >= 8.\n */\n scan += 2;\n match++;\n // Assert(*scan == *match, \"match[2]?\");\n\n /* We check for insufficient lookahead only every 8th comparison;\n * the 256th check will be made at strstart+258.\n */\n do {\n /*jshint noempty:false*/\n } while (_win[++scan] === _win[++match] && _win[++scan] === _win[++match] &&\n _win[++scan] === _win[++match] && _win[++scan] === _win[++match] &&\n _win[++scan] === _win[++match] && _win[++scan] === _win[++match] &&\n _win[++scan] === _win[++match] && _win[++scan] === _win[++match] &&\n scan < strend);\n\n // Assert(scan <= s->window+(unsigned)(s->window_size-1), \"wild scan\");\n\n len = MAX_MATCH - (strend - scan);\n scan = strend - MAX_MATCH;\n\n if (len > best_len) {\n s.match_start = cur_match;\n best_len = len;\n if (len >= nice_match) {\n break;\n }\n scan_end1 = _win[scan + best_len - 1];\n scan_end = _win[scan + best_len];\n }\n } while ((cur_match = prev[cur_match & wmask]) > limit && --chain_length !== 0);\n\n if (best_len <= s.lookahead) {\n return best_len;\n }\n return s.lookahead;\n};\n\n\n/* ===========================================================================\n * Fill the window when the lookahead becomes insufficient.\n * Updates strstart and lookahead.\n *\n * IN assertion: lookahead < MIN_LOOKAHEAD\n * OUT assertions: strstart <= window_size-MIN_LOOKAHEAD\n * At least one byte has been read, or avail_in == 0; reads are\n * performed for at least two bytes (required for the zip translate_eol\n * option -- not supported here).\n */\nconst fill_window = (s) => {\n\n const _w_size = s.w_size;\n let n, more, str;\n\n //Assert(s->lookahead < MIN_LOOKAHEAD, \"already enough lookahead\");\n\n do {\n more = s.window_size - s.lookahead - s.strstart;\n\n // JS ints have 32 bit, block below not needed\n /* Deal with !@#$% 64K limit: */\n //if (sizeof(int) <= 2) {\n // if (more == 0 && s->strstart == 0 && s->lookahead == 0) {\n // more = wsize;\n //\n // } else if (more == (unsigned)(-1)) {\n // /* Very unlikely, but possible on 16 bit machine if\n // * strstart == 0 && lookahead == 1 (input done a byte at time)\n // */\n // more--;\n // }\n //}\n\n\n /* If the window is almost full and there is insufficient lookahead,\n * move the upper half to the lower one to make room in the upper half.\n */\n if (s.strstart >= _w_size + (_w_size - MIN_LOOKAHEAD)) {\n\n s.window.set(s.window.subarray(_w_size, _w_size + _w_size - more), 0);\n s.match_start -= _w_size;\n s.strstart -= _w_size;\n /* we now have strstart >= MAX_DIST */\n s.block_start -= _w_size;\n if (s.insert > s.strstart) {\n s.insert = s.strstart;\n }\n slide_hash(s);\n more += _w_size;\n }\n if (s.strm.avail_in === 0) {\n break;\n }\n\n /* If there was no sliding:\n * strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 &&\n * more == window_size - lookahead - strstart\n * => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1)\n * => more >= window_size - 2*WSIZE + 2\n * In the BIG_MEM or MMAP case (not yet supported),\n * window_size == input_size + MIN_LOOKAHEAD &&\n * strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD.\n * Otherwise, window_size == 2*WSIZE so more >= 2.\n * If there was sliding, more >= WSIZE. So in all cases, more >= 2.\n */\n //Assert(more >= 2, \"more < 2\");\n n = read_buf(s.strm, s.window, s.strstart + s.lookahead, more);\n s.lookahead += n;\n\n /* Initialize the hash value now that we have some input: */\n if (s.lookahead + s.insert >= MIN_MATCH) {\n str = s.strstart - s.insert;\n s.ins_h = s.window[str];\n\n /* UPDATE_HASH(s, s->ins_h, s->window[str + 1]); */\n s.ins_h = HASH(s, s.ins_h, s.window[str + 1]);\n//#if MIN_MATCH != 3\n// Call update_hash() MIN_MATCH-3 more times\n//#endif\n while (s.insert) {\n /* UPDATE_HASH(s, s->ins_h, s->window[str + MIN_MATCH-1]); */\n s.ins_h = HASH(s, s.ins_h, s.window[str + MIN_MATCH - 1]);\n\n s.prev[str & s.w_mask] = s.head[s.ins_h];\n s.head[s.ins_h] = str;\n str++;\n s.insert--;\n if (s.lookahead + s.insert < MIN_MATCH) {\n break;\n }\n }\n }\n /* If the whole input has less than MIN_MATCH bytes, ins_h is garbage,\n * but this is not important since only literal bytes will be emitted.\n */\n\n } while (s.lookahead < MIN_LOOKAHEAD && s.strm.avail_in !== 0);\n\n /* If the WIN_INIT bytes after the end of the current data have never been\n * written, then zero those bytes in order to avoid memory check reports of\n * the use of uninitialized (or uninitialised as Julian writes) bytes by\n * the longest match routines. Update the high water mark for the next\n * time through here. WIN_INIT is set to MAX_MATCH since the longest match\n * routines allow scanning to strstart + MAX_MATCH, ignoring lookahead.\n */\n// if (s.high_water < s.window_size) {\n// const curr = s.strstart + s.lookahead;\n// let init = 0;\n//\n// if (s.high_water < curr) {\n// /* Previous high water mark below current data -- zero WIN_INIT\n// * bytes or up to end of window, whichever is less.\n// */\n// init = s.window_size - curr;\n// if (init > WIN_INIT)\n// init = WIN_INIT;\n// zmemzero(s->window + curr, (unsigned)init);\n// s->high_water = curr + init;\n// }\n// else if (s->high_water < (ulg)curr + WIN_INIT) {\n// /* High water mark at or above current data, but below current data\n// * plus WIN_INIT -- zero out to current data plus WIN_INIT, or up\n// * to end of window, whichever is less.\n// */\n// init = (ulg)curr + WIN_INIT - s->high_water;\n// if (init > s->window_size - s->high_water)\n// init = s->window_size - s->high_water;\n// zmemzero(s->window + s->high_water, (unsigned)init);\n// s->high_water += init;\n// }\n// }\n//\n// Assert((ulg)s->strstart <= s->window_size - MIN_LOOKAHEAD,\n// \"not enough room for search\");\n};\n\n/* ===========================================================================\n * Copy without compression as much as possible from the input stream, return\n * the current block state.\n *\n * In case deflateParams() is used to later switch to a non-zero compression\n * level, s->matches (otherwise unused when storing) keeps track of the number\n * of hash table slides to perform. If s->matches is 1, then one hash table\n * slide will be done when switching. If s->matches is 2, the maximum value\n * allowed here, then the hash table will be cleared, since two or more slides\n * is the same as a clear.\n *\n * deflate_stored() is written to minimize the number of times an input byte is\n * copied. It is most efficient with large input and output buffers, which\n * maximizes the opportunites to have a single copy from next_in to next_out.\n */\nconst deflate_stored = (s, flush) => {\n\n /* Smallest worthy block size when not flushing or finishing. By default\n * this is 32K. This can be as small as 507 bytes for memLevel == 1. For\n * large input and output buffers, the stored block size will be larger.\n */\n let min_block = s.pending_buf_size - 5 > s.w_size ? s.w_size : s.pending_buf_size - 5;\n\n /* Copy as many min_block or larger stored blocks directly to next_out as\n * possible. If flushing, copy the remaining available input to next_out as\n * stored blocks, if there is enough space.\n */\n let len, left, have, last = 0;\n let used = s.strm.avail_in;\n do {\n /* Set len to the maximum size block that we can copy directly with the\n * available input data and output space. Set left to how much of that\n * would be copied from what's left in the window.\n */\n len = 65535/* MAX_STORED */; /* maximum deflate stored block length */\n have = (s.bi_valid + 42) >> 3; /* number of header bytes */\n if (s.strm.avail_out < have) { /* need room for header */\n break;\n }\n /* maximum stored block length that will fit in avail_out: */\n have = s.strm.avail_out - have;\n left = s.strstart - s.block_start; /* bytes left in window */\n if (len > left + s.strm.avail_in) {\n len = left + s.strm.avail_in; /* limit len to the input */\n }\n if (len > have) {\n len = have; /* limit len to the output */\n }\n\n /* If the stored block would be less than min_block in length, or if\n * unable to copy all of the available input when flushing, then try\n * copying to the window and the pending buffer instead. Also don't\n * write an empty block when flushing -- deflate() does that.\n */\n if (len < min_block && ((len === 0 && flush !== Z_FINISH$3) ||\n flush === Z_NO_FLUSH$2 ||\n len !== left + s.strm.avail_in)) {\n break;\n }\n\n /* Make a dummy stored block in pending to get the header bytes,\n * including any pending bits. This also updates the debugging counts.\n */\n last = flush === Z_FINISH$3 && len === left + s.strm.avail_in ? 1 : 0;\n _tr_stored_block(s, 0, 0, last);\n\n /* Replace the lengths in the dummy stored block with len. */\n s.pending_buf[s.pending - 4] = len;\n s.pending_buf[s.pending - 3] = len >> 8;\n s.pending_buf[s.pending - 2] = ~len;\n s.pending_buf[s.pending - 1] = ~len >> 8;\n\n /* Write the stored block header bytes. */\n flush_pending(s.strm);\n\n//#ifdef ZLIB_DEBUG\n// /* Update debugging counts for the data about to be copied. */\n// s->compressed_len += len << 3;\n// s->bits_sent += len << 3;\n//#endif\n\n /* Copy uncompressed bytes from the window to next_out. */\n if (left) {\n if (left > len) {\n left = len;\n }\n //zmemcpy(s->strm->next_out, s->window + s->block_start, left);\n s.strm.output.set(s.window.subarray(s.block_start, s.block_start + left), s.strm.next_out);\n s.strm.next_out += left;\n s.strm.avail_out -= left;\n s.strm.total_out += left;\n s.block_start += left;\n len -= left;\n }\n\n /* Copy uncompressed bytes directly from next_in to next_out, updating\n * the check value.\n */\n if (len) {\n read_buf(s.strm, s.strm.output, s.strm.next_out, len);\n s.strm.next_out += len;\n s.strm.avail_out -= len;\n s.strm.total_out += len;\n }\n } while (last === 0);\n\n /* Update the sliding window with the last s->w_size bytes of the copied\n * data, or append all of the copied data to the existing window if less\n * than s->w_size bytes were copied. Also update the number of bytes to\n * insert in the hash tables, in the event that deflateParams() switches to\n * a non-zero compression level.\n */\n used -= s.strm.avail_in; /* number of input bytes directly copied */\n if (used) {\n /* If any input was used, then no unused input remains in the window,\n * therefore s->block_start == s->strstart.\n */\n if (used >= s.w_size) { /* supplant the previous history */\n s.matches = 2; /* clear hash */\n //zmemcpy(s->window, s->strm->next_in - s->w_size, s->w_size);\n s.window.set(s.strm.input.subarray(s.strm.next_in - s.w_size, s.strm.next_in), 0);\n s.strstart = s.w_size;\n s.insert = s.strstart;\n }\n else {\n if (s.window_size - s.strstart <= used) {\n /* Slide the window down. */\n s.strstart -= s.w_size;\n //zmemcpy(s->window, s->window + s->w_size, s->strstart);\n s.window.set(s.window.subarray(s.w_size, s.w_size + s.strstart), 0);\n if (s.matches < 2) {\n s.matches++; /* add a pending slide_hash() */\n }\n if (s.insert > s.strstart) {\n s.insert = s.strstart;\n }\n }\n //zmemcpy(s->window + s->strstart, s->strm->next_in - used, used);\n s.window.set(s.strm.input.subarray(s.strm.next_in - used, s.strm.next_in), s.strstart);\n s.strstart += used;\n s.insert += used > s.w_size - s.insert ? s.w_size - s.insert : used;\n }\n s.block_start = s.strstart;\n }\n if (s.high_water < s.strstart) {\n s.high_water = s.strstart;\n }\n\n /* If the last block was written to next_out, then done. */\n if (last) {\n return BS_FINISH_DONE;\n }\n\n /* If flushing and all input has been consumed, then done. */\n if (flush !== Z_NO_FLUSH$2 && flush !== Z_FINISH$3 &&\n s.strm.avail_in === 0 && s.strstart === s.block_start) {\n return BS_BLOCK_DONE;\n }\n\n /* Fill the window with any remaining input. */\n have = s.window_size - s.strstart;\n if (s.strm.avail_in > have && s.block_start >= s.w_size) {\n /* Slide the window down. */\n s.block_start -= s.w_size;\n s.strstart -= s.w_size;\n //zmemcpy(s->window, s->window + s->w_size, s->strstart);\n s.window.set(s.window.subarray(s.w_size, s.w_size + s.strstart), 0);\n if (s.matches < 2) {\n s.matches++; /* add a pending slide_hash() */\n }\n have += s.w_size; /* more space now */\n if (s.insert > s.strstart) {\n s.insert = s.strstart;\n }\n }\n if (have > s.strm.avail_in) {\n have = s.strm.avail_in;\n }\n if (have) {\n read_buf(s.strm, s.window, s.strstart, have);\n s.strstart += have;\n s.insert += have > s.w_size - s.insert ? s.w_size - s.insert : have;\n }\n if (s.high_water < s.strstart) {\n s.high_water = s.strstart;\n }\n\n /* There was not enough avail_out to write a complete worthy or flushed\n * stored block to next_out. Write a stored block to pending instead, if we\n * have enough input for a worthy block, or if flushing and there is enough\n * room for the remaining input as a stored block in the pending buffer.\n */\n have = (s.bi_valid + 42) >> 3; /* number of header bytes */\n /* maximum stored block length that will fit in pending: */\n have = s.pending_buf_size - have > 65535/* MAX_STORED */ ? 65535/* MAX_STORED */ : s.pending_buf_size - have;\n min_block = have > s.w_size ? s.w_size : have;\n left = s.strstart - s.block_start;\n if (left >= min_block ||\n ((left || flush === Z_FINISH$3) && flush !== Z_NO_FLUSH$2 &&\n s.strm.avail_in === 0 && left <= have)) {\n len = left > have ? have : left;\n last = flush === Z_FINISH$3 && s.strm.avail_in === 0 &&\n len === left ? 1 : 0;\n _tr_stored_block(s, s.block_start, len, last);\n s.block_start += len;\n flush_pending(s.strm);\n }\n\n /* We've done all we can with the available input and output. */\n return last ? BS_FINISH_STARTED : BS_NEED_MORE;\n};\n\n\n/* ===========================================================================\n * Compress as much as possible from the input stream, return the current\n * block state.\n * This function does not perform lazy evaluation of matches and inserts\n * new strings in the dictionary only for unmatched strings or for short\n * matches. It is used only for the fast compression options.\n */\nconst deflate_fast = (s, flush) => {\n\n let hash_head; /* head of the hash chain */\n let bflush; /* set if current block must be flushed */\n\n for (;;) {\n /* Make sure that we always have enough lookahead, except\n * at the end of the input file. We need MAX_MATCH bytes\n * for the next match, plus MIN_MATCH bytes to insert the\n * string following the next match.\n */\n if (s.lookahead < MIN_LOOKAHEAD) {\n fill_window(s);\n if (s.lookahead < MIN_LOOKAHEAD && flush === Z_NO_FLUSH$2) {\n return BS_NEED_MORE;\n }\n if (s.lookahead === 0) {\n break; /* flush the current block */\n }\n }\n\n /* Insert the string window[strstart .. strstart+2] in the\n * dictionary, and set hash_head to the head of the hash chain:\n */\n hash_head = 0/*NIL*/;\n if (s.lookahead >= MIN_MATCH) {\n /*** INSERT_STRING(s, s.strstart, hash_head); ***/\n s.ins_h = HASH(s, s.ins_h, s.window[s.strstart + MIN_MATCH - 1]);\n hash_head = s.prev[s.strstart & s.w_mask] = s.head[s.ins_h];\n s.head[s.ins_h] = s.strstart;\n /***/\n }\n\n /* Find the longest match, discarding those <= prev_length.\n * At this point we have always match_length < MIN_MATCH\n */\n if (hash_head !== 0/*NIL*/ && ((s.strstart - hash_head) <= (s.w_size - MIN_LOOKAHEAD))) {\n /* To simplify the code, we prevent matches with the string\n * of window index 0 (in particular we have to avoid a match\n * of the string with itself at the start of the input file).\n */\n s.match_length = longest_match(s, hash_head);\n /* longest_match() sets match_start */\n }\n if (s.match_length >= MIN_MATCH) {\n // check_match(s, s.strstart, s.match_start, s.match_length); // for debug only\n\n /*** _tr_tally_dist(s, s.strstart - s.match_start,\n s.match_length - MIN_MATCH, bflush); ***/\n bflush = _tr_tally(s, s.strstart - s.match_start, s.match_length - MIN_MATCH);\n\n s.lookahead -= s.match_length;\n\n /* Insert new strings in the hash table only if the match length\n * is not too large. This saves time but degrades compression.\n */\n if (s.match_length <= s.max_lazy_match/*max_insert_length*/ && s.lookahead >= MIN_MATCH) {\n s.match_length--; /* string at strstart already in table */\n do {\n s.strstart++;\n /*** INSERT_STRING(s, s.strstart, hash_head); ***/\n s.ins_h = HASH(s, s.ins_h, s.window[s.strstart + MIN_MATCH - 1]);\n hash_head = s.prev[s.strstart & s.w_mask] = s.head[s.ins_h];\n s.head[s.ins_h] = s.strstart;\n /***/\n /* strstart never exceeds WSIZE-MAX_MATCH, so there are\n * always MIN_MATCH bytes ahead.\n */\n } while (--s.match_length !== 0);\n s.strstart++;\n } else\n {\n s.strstart += s.match_length;\n s.match_length = 0;\n s.ins_h = s.window[s.strstart];\n /* UPDATE_HASH(s, s.ins_h, s.window[s.strstart+1]); */\n s.ins_h = HASH(s, s.ins_h, s.window[s.strstart + 1]);\n\n//#if MIN_MATCH != 3\n// Call UPDATE_HASH() MIN_MATCH-3 more times\n//#endif\n /* If lookahead < MIN_MATCH, ins_h is garbage, but it does not\n * matter since it will be recomputed at next deflate call.\n */\n }\n } else {\n /* No match, output a literal byte */\n //Tracevv((stderr,\"%c\", s.window[s.strstart]));\n /*** _tr_tally_lit(s, s.window[s.strstart], bflush); ***/\n bflush = _tr_tally(s, 0, s.window[s.strstart]);\n\n s.lookahead--;\n s.strstart++;\n }\n if (bflush) {\n /*** FLUSH_BLOCK(s, 0); ***/\n flush_block_only(s, false);\n if (s.strm.avail_out === 0) {\n return BS_NEED_MORE;\n }\n /***/\n }\n }\n s.insert = ((s.strstart < (MIN_MATCH - 1)) ? s.strstart : MIN_MATCH - 1);\n if (flush === Z_FINISH$3) {\n /*** FLUSH_BLOCK(s, 1); ***/\n flush_block_only(s, true);\n if (s.strm.avail_out === 0) {\n return BS_FINISH_STARTED;\n }\n /***/\n return BS_FINISH_DONE;\n }\n if (s.sym_next) {\n /*** FLUSH_BLOCK(s, 0); ***/\n flush_block_only(s, false);\n if (s.strm.avail_out === 0) {\n return BS_NEED_MORE;\n }\n /***/\n }\n return BS_BLOCK_DONE;\n};\n\n/* ===========================================================================\n * Same as above, but achieves better compression. We use a lazy\n * evaluation for matches: a match is finally adopted only if there is\n * no better match at the next window position.\n */\nconst deflate_slow = (s, flush) => {\n\n let hash_head; /* head of hash chain */\n let bflush; /* set if current block must be flushed */\n\n let max_insert;\n\n /* Process the input block. */\n for (;;) {\n /* Make sure that we always have enough lookahead, except\n * at the end of the input file. We need MAX_MATCH bytes\n * for the next match, plus MIN_MATCH bytes to insert the\n * string following the next match.\n */\n if (s.lookahead < MIN_LOOKAHEAD) {\n fill_window(s);\n if (s.lookahead < MIN_LOOKAHEAD && flush === Z_NO_FLUSH$2) {\n return BS_NEED_MORE;\n }\n if (s.lookahead === 0) { break; } /* flush the current block */\n }\n\n /* Insert the string window[strstart .. strstart+2] in the\n * dictionary, and set hash_head to the head of the hash chain:\n */\n hash_head = 0/*NIL*/;\n if (s.lookahead >= MIN_MATCH) {\n /*** INSERT_STRING(s, s.strstart, hash_head); ***/\n s.ins_h = HASH(s, s.ins_h, s.window[s.strstart + MIN_MATCH - 1]);\n hash_head = s.prev[s.strstart & s.w_mask] = s.head[s.ins_h];\n s.head[s.ins_h] = s.strstart;\n /***/\n }\n\n /* Find the longest match, discarding those <= prev_length.\n */\n s.prev_length = s.match_length;\n s.prev_match = s.match_start;\n s.match_length = MIN_MATCH - 1;\n\n if (hash_head !== 0/*NIL*/ && s.prev_length < s.max_lazy_match &&\n s.strstart - hash_head <= (s.w_size - MIN_LOOKAHEAD)/*MAX_DIST(s)*/) {\n /* To simplify the code, we prevent matches with the string\n * of window index 0 (in particular we have to avoid a match\n * of the string with itself at the start of the input file).\n */\n s.match_length = longest_match(s, hash_head);\n /* longest_match() sets match_start */\n\n if (s.match_length <= 5 &&\n (s.strategy === Z_FILTERED || (s.match_length === MIN_MATCH && s.strstart - s.match_start > 4096/*TOO_FAR*/))) {\n\n /* If prev_match is also MIN_MATCH, match_start is garbage\n * but we will ignore the current match anyway.\n */\n s.match_length = MIN_MATCH - 1;\n }\n }\n /* If there was a match at the previous step and the current\n * match is not better, output the previous match:\n */\n if (s.prev_length >= MIN_MATCH && s.match_length <= s.prev_length) {\n max_insert = s.strstart + s.lookahead - MIN_MATCH;\n /* Do not insert strings in hash table beyond this. */\n\n //check_match(s, s.strstart-1, s.prev_match, s.prev_length);\n\n /***_tr_tally_dist(s, s.strstart - 1 - s.prev_match,\n s.prev_length - MIN_MATCH, bflush);***/\n bflush = _tr_tally(s, s.strstart - 1 - s.prev_match, s.prev_length - MIN_MATCH);\n /* Insert in hash table all strings up to the end of the match.\n * strstart-1 and strstart are already inserted. If there is not\n * enough lookahead, the last two strings are not inserted in\n * the hash table.\n */\n s.lookahead -= s.prev_length - 1;\n s.prev_length -= 2;\n do {\n if (++s.strstart <= max_insert) {\n /*** INSERT_STRING(s, s.strstart, hash_head); ***/\n s.ins_h = HASH(s, s.ins_h, s.window[s.strstart + MIN_MATCH - 1]);\n hash_head = s.prev[s.strstart & s.w_mask] = s.head[s.ins_h];\n s.head[s.ins_h] = s.strstart;\n /***/\n }\n } while (--s.prev_length !== 0);\n s.match_available = 0;\n s.match_length = MIN_MATCH - 1;\n s.strstart++;\n\n if (bflush) {\n /*** FLUSH_BLOCK(s, 0); ***/\n flush_block_only(s, false);\n if (s.strm.avail_out === 0) {\n return BS_NEED_MORE;\n }\n /***/\n }\n\n } else if (s.match_available) {\n /* If there was no match at the previous position, output a\n * single literal. If there was a match but the current match\n * is longer, truncate the previous match to a single literal.\n */\n //Tracevv((stderr,\"%c\", s->window[s->strstart-1]));\n /*** _tr_tally_lit(s, s.window[s.strstart-1], bflush); ***/\n bflush = _tr_tally(s, 0, s.window[s.strstart - 1]);\n\n if (bflush) {\n /*** FLUSH_BLOCK_ONLY(s, 0) ***/\n flush_block_only(s, false);\n /***/\n }\n s.strstart++;\n s.lookahead--;\n if (s.strm.avail_out === 0) {\n return BS_NEED_MORE;\n }\n } else {\n /* There is no previous match to compare with, wait for\n * the next step to decide.\n */\n s.match_available = 1;\n s.strstart++;\n s.lookahead--;\n }\n }\n //Assert (flush != Z_NO_FLUSH, \"no flush?\");\n if (s.match_available) {\n //Tracevv((stderr,\"%c\", s->window[s->strstart-1]));\n /*** _tr_tally_lit(s, s.window[s.strstart-1], bflush); ***/\n bflush = _tr_tally(s, 0, s.window[s.strstart - 1]);\n\n s.match_available = 0;\n }\n s.insert = s.strstart < MIN_MATCH - 1 ? s.strstart : MIN_MATCH - 1;\n if (flush === Z_FINISH$3) {\n /*** FLUSH_BLOCK(s, 1); ***/\n flush_block_only(s, true);\n if (s.strm.avail_out === 0) {\n return BS_FINISH_STARTED;\n }\n /***/\n return BS_FINISH_DONE;\n }\n if (s.sym_next) {\n /*** FLUSH_BLOCK(s, 0); ***/\n flush_block_only(s, false);\n if (s.strm.avail_out === 0) {\n return BS_NEED_MORE;\n }\n /***/\n }\n\n return BS_BLOCK_DONE;\n};\n\n\n/* ===========================================================================\n * For Z_RLE, simply look for runs of bytes, generate matches only of distance\n * one. Do not maintain a hash table. (It will be regenerated if this run of\n * deflate switches away from Z_RLE.)\n */\nconst deflate_rle = (s, flush) => {\n\n let bflush; /* set if current block must be flushed */\n let prev; /* byte at distance one to match */\n let scan, strend; /* scan goes up to strend for length of run */\n\n const _win = s.window;\n\n for (;;) {\n /* Make sure that we always have enough lookahead, except\n * at the end of the input file. We need MAX_MATCH bytes\n * for the longest run, plus one for the unrolled loop.\n */\n if (s.lookahead <= MAX_MATCH) {\n fill_window(s);\n if (s.lookahead <= MAX_MATCH && flush === Z_NO_FLUSH$2) {\n return BS_NEED_MORE;\n }\n if (s.lookahead === 0) { break; } /* flush the current block */\n }\n\n /* See how many times the previous byte repeats */\n s.match_length = 0;\n if (s.lookahead >= MIN_MATCH && s.strstart > 0) {\n scan = s.strstart - 1;\n prev = _win[scan];\n if (prev === _win[++scan] && prev === _win[++scan] && prev === _win[++scan]) {\n strend = s.strstart + MAX_MATCH;\n do {\n /*jshint noempty:false*/\n } while (prev === _win[++scan] && prev === _win[++scan] &&\n prev === _win[++scan] && prev === _win[++scan] &&\n prev === _win[++scan] && prev === _win[++scan] &&\n prev === _win[++scan] && prev === _win[++scan] &&\n scan < strend);\n s.match_length = MAX_MATCH - (strend - scan);\n if (s.match_length > s.lookahead) {\n s.match_length = s.lookahead;\n }\n }\n //Assert(scan <= s->window+(uInt)(s->window_size-1), \"wild scan\");\n }\n\n /* Emit match if have run of MIN_MATCH or longer, else emit literal */\n if (s.match_length >= MIN_MATCH) {\n //check_match(s, s.strstart, s.strstart - 1, s.match_length);\n\n /*** _tr_tally_dist(s, 1, s.match_length - MIN_MATCH, bflush); ***/\n bflush = _tr_tally(s, 1, s.match_length - MIN_MATCH);\n\n s.lookahead -= s.match_length;\n s.strstart += s.match_length;\n s.match_length = 0;\n } else {\n /* No match, output a literal byte */\n //Tracevv((stderr,\"%c\", s->window[s->strstart]));\n /*** _tr_tally_lit(s, s.window[s.strstart], bflush); ***/\n bflush = _tr_tally(s, 0, s.window[s.strstart]);\n\n s.lookahead--;\n s.strstart++;\n }\n if (bflush) {\n /*** FLUSH_BLOCK(s, 0); ***/\n flush_block_only(s, false);\n if (s.strm.avail_out === 0) {\n return BS_NEED_MORE;\n }\n /***/\n }\n }\n s.insert = 0;\n if (flush === Z_FINISH$3) {\n /*** FLUSH_BLOCK(s, 1); ***/\n flush_block_only(s, true);\n if (s.strm.avail_out === 0) {\n return BS_FINISH_STARTED;\n }\n /***/\n return BS_FINISH_DONE;\n }\n if (s.sym_next) {\n /*** FLUSH_BLOCK(s, 0); ***/\n flush_block_only(s, false);\n if (s.strm.avail_out === 0) {\n return BS_NEED_MORE;\n }\n /***/\n }\n return BS_BLOCK_DONE;\n};\n\n/* ===========================================================================\n * For Z_HUFFMAN_ONLY, do not look for matches. Do not maintain a hash table.\n * (It will be regenerated if this run of deflate switches away from Huffman.)\n */\nconst deflate_huff = (s, flush) => {\n\n let bflush; /* set if current block must be flushed */\n\n for (;;) {\n /* Make sure that we have a literal to write. */\n if (s.lookahead === 0) {\n fill_window(s);\n if (s.lookahead === 0) {\n if (flush === Z_NO_FLUSH$2) {\n return BS_NEED_MORE;\n }\n break; /* flush the current block */\n }\n }\n\n /* Output a literal byte */\n s.match_length = 0;\n //Tracevv((stderr,\"%c\", s->window[s->strstart]));\n /*** _tr_tally_lit(s, s.window[s.strstart], bflush); ***/\n bflush = _tr_tally(s, 0, s.window[s.strstart]);\n s.lookahead--;\n s.strstart++;\n if (bflush) {\n /*** FLUSH_BLOCK(s, 0); ***/\n flush_block_only(s, false);\n if (s.strm.avail_out === 0) {\n return BS_NEED_MORE;\n }\n /***/\n }\n }\n s.insert = 0;\n if (flush === Z_FINISH$3) {\n /*** FLUSH_BLOCK(s, 1); ***/\n flush_block_only(s, true);\n if (s.strm.avail_out === 0) {\n return BS_FINISH_STARTED;\n }\n /***/\n return BS_FINISH_DONE;\n }\n if (s.sym_next) {\n /*** FLUSH_BLOCK(s, 0); ***/\n flush_block_only(s, false);\n if (s.strm.avail_out === 0) {\n return BS_NEED_MORE;\n }\n /***/\n }\n return BS_BLOCK_DONE;\n};\n\n/* Values for max_lazy_match, good_match and max_chain_length, depending on\n * the desired pack level (0..9). The values given below have been tuned to\n * exclude worst case performance for pathological files. Better values may be\n * found for specific files.\n */\nfunction Config(good_length, max_lazy, nice_length, max_chain, func) {\n\n this.good_length = good_length;\n this.max_lazy = max_lazy;\n this.nice_length = nice_length;\n this.max_chain = max_chain;\n this.func = func;\n}\n\nconst configuration_table = [\n /* good lazy nice chain */\n new Config(0, 0, 0, 0, deflate_stored), /* 0 store only */\n new Config(4, 4, 8, 4, deflate_fast), /* 1 max speed, no lazy matches */\n new Config(4, 5, 16, 8, deflate_fast), /* 2 */\n new Config(4, 6, 32, 32, deflate_fast), /* 3 */\n\n new Config(4, 4, 16, 16, deflate_slow), /* 4 lazy matches */\n new Config(8, 16, 32, 32, deflate_slow), /* 5 */\n new Config(8, 16, 128, 128, deflate_slow), /* 6 */\n new Config(8, 32, 128, 256, deflate_slow), /* 7 */\n new Config(32, 128, 258, 1024, deflate_slow), /* 8 */\n new Config(32, 258, 258, 4096, deflate_slow) /* 9 max compression */\n];\n\n\n/* ===========================================================================\n * Initialize the \"longest match\" routines for a new zlib stream\n */\nconst lm_init = (s) => {\n\n s.window_size = 2 * s.w_size;\n\n /*** CLEAR_HASH(s); ***/\n zero(s.head); // Fill with NIL (= 0);\n\n /* Set the default configuration parameters:\n */\n s.max_lazy_match = configuration_table[s.level].max_lazy;\n s.good_match = configuration_table[s.level].good_length;\n s.nice_match = configuration_table[s.level].nice_length;\n s.max_chain_length = configuration_table[s.level].max_chain;\n\n s.strstart = 0;\n s.block_start = 0;\n s.lookahead = 0;\n s.insert = 0;\n s.match_length = s.prev_length = MIN_MATCH - 1;\n s.match_available = 0;\n s.ins_h = 0;\n};\n\n\nfunction DeflateState() {\n this.strm = null; /* pointer back to this zlib stream */\n this.status = 0; /* as the name implies */\n this.pending_buf = null; /* output still pending */\n this.pending_buf_size = 0; /* size of pending_buf */\n this.pending_out = 0; /* next pending byte to output to the stream */\n this.pending = 0; /* nb of bytes in the pending buffer */\n this.wrap = 0; /* bit 0 true for zlib, bit 1 true for gzip */\n this.gzhead = null; /* gzip header information to write */\n this.gzindex = 0; /* where in extra, name, or comment */\n this.method = Z_DEFLATED$2; /* can only be DEFLATED */\n this.last_flush = -1; /* value of flush param for previous deflate call */\n\n this.w_size = 0; /* LZ77 window size (32K by default) */\n this.w_bits = 0; /* log2(w_size) (8..16) */\n this.w_mask = 0; /* w_size - 1 */\n\n this.window = null;\n /* Sliding window. Input bytes are read into the second half of the window,\n * and move to the first half later to keep a dictionary of at least wSize\n * bytes. With this organization, matches are limited to a distance of\n * wSize-MAX_MATCH bytes, but this ensures that IO is always\n * performed with a length multiple of the block size.\n */\n\n this.window_size = 0;\n /* Actual size of window: 2*wSize, except when the user input buffer\n * is directly used as sliding window.\n */\n\n this.prev = null;\n /* Link to older string with same hash index. To limit the size of this\n * array to 64K, this link is maintained only for the last 32K strings.\n * An index in this array is thus a window index modulo 32K.\n */\n\n this.head = null; /* Heads of the hash chains or NIL. */\n\n this.ins_h = 0; /* hash index of string to be inserted */\n this.hash_size = 0; /* number of elements in hash table */\n this.hash_bits = 0; /* log2(hash_size) */\n this.hash_mask = 0; /* hash_size-1 */\n\n this.hash_shift = 0;\n /* Number of bits by which ins_h must be shifted at each input\n * step. It must be such that after MIN_MATCH steps, the oldest\n * byte no longer takes part in the hash key, that is:\n * hash_shift * MIN_MATCH >= hash_bits\n */\n\n this.block_start = 0;\n /* Window position at the beginning of the current output block. Gets\n * negative when the window is moved backwards.\n */\n\n this.match_length = 0; /* length of best match */\n this.prev_match = 0; /* previous match */\n this.match_available = 0; /* set if previous match exists */\n this.strstart = 0; /* start of string to insert */\n this.match_start = 0; /* start of matching string */\n this.lookahead = 0; /* number of valid bytes ahead in window */\n\n this.prev_length = 0;\n /* Length of the best match at previous step. Matches not greater than this\n * are discarded. This is used in the lazy match evaluation.\n */\n\n this.max_chain_length = 0;\n /* To speed up deflation, hash chains are never searched beyond this\n * length. A higher limit improves compression ratio but degrades the\n * speed.\n */\n\n this.max_lazy_match = 0;\n /* Attempt to find a better match only when the current match is strictly\n * smaller than this value. This mechanism is used only for compression\n * levels >= 4.\n */\n // That's alias to max_lazy_match, don't use directly\n //this.max_insert_length = 0;\n /* Insert new strings in the hash table only if the match length is not\n * greater than this length. This saves time but degrades compression.\n * max_insert_length is used only for compression levels <= 3.\n */\n\n this.level = 0; /* compression level (1..9) */\n this.strategy = 0; /* favor or force Huffman coding*/\n\n this.good_match = 0;\n /* Use a faster search when the previous match is longer than this */\n\n this.nice_match = 0; /* Stop searching when current match exceeds this */\n\n /* used by trees.c: */\n\n /* Didn't use ct_data typedef below to suppress compiler warning */\n\n // struct ct_data_s dyn_ltree[HEAP_SIZE]; /* literal and length tree */\n // struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */\n // struct ct_data_s bl_tree[2*BL_CODES+1]; /* Huffman tree for bit lengths */\n\n // Use flat array of DOUBLE size, with interleaved fata,\n // because JS does not support effective\n this.dyn_ltree = new Uint16Array(HEAP_SIZE * 2);\n this.dyn_dtree = new Uint16Array((2 * D_CODES + 1) * 2);\n this.bl_tree = new Uint16Array((2 * BL_CODES + 1) * 2);\n zero(this.dyn_ltree);\n zero(this.dyn_dtree);\n zero(this.bl_tree);\n\n this.l_desc = null; /* desc. for literal tree */\n this.d_desc = null; /* desc. for distance tree */\n this.bl_desc = null; /* desc. for bit length tree */\n\n //ush bl_count[MAX_BITS+1];\n this.bl_count = new Uint16Array(MAX_BITS + 1);\n /* number of codes at each bit length for an optimal tree */\n\n //int heap[2*L_CODES+1]; /* heap used to build the Huffman trees */\n this.heap = new Uint16Array(2 * L_CODES + 1); /* heap used to build the Huffman trees */\n zero(this.heap);\n\n this.heap_len = 0; /* number of elements in the heap */\n this.heap_max = 0; /* element of largest frequency */\n /* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used.\n * The same heap array is used to build all trees.\n */\n\n this.depth = new Uint16Array(2 * L_CODES + 1); //uch depth[2*L_CODES+1];\n zero(this.depth);\n /* Depth of each subtree used as tie breaker for trees of equal frequency\n */\n\n this.sym_buf = 0; /* buffer for distances and literals/lengths */\n\n this.lit_bufsize = 0;\n /* Size of match buffer for literals/lengths. There are 4 reasons for\n * limiting lit_bufsize to 64K:\n * - frequencies can be kept in 16 bit counters\n * - if compression is not successful for the first block, all input\n * data is still in the window so we can still emit a stored block even\n * when input comes from standard input. (This can also be done for\n * all blocks if lit_bufsize is not greater than 32K.)\n * - if compression is not successful for a file smaller than 64K, we can\n * even emit a stored file instead of a stored block (saving 5 bytes).\n * This is applicable only for zip (not gzip or zlib).\n * - creating new Huffman trees less frequently may not provide fast\n * adaptation to changes in the input data statistics. (Take for\n * example a binary file with poorly compressible code followed by\n * a highly compressible string table.) Smaller buffer sizes give\n * fast adaptation but have of course the overhead of transmitting\n * trees more frequently.\n * - I can't count above 4\n */\n\n this.sym_next = 0; /* running index in sym_buf */\n this.sym_end = 0; /* symbol table full when sym_next reaches this */\n\n this.opt_len = 0; /* bit length of current block with optimal trees */\n this.static_len = 0; /* bit length of current block with static trees */\n this.matches = 0; /* number of string matches in current block */\n this.insert = 0; /* bytes at end of window left to insert */\n\n\n this.bi_buf = 0;\n /* Output buffer. bits are inserted starting at the bottom (least\n * significant bits).\n */\n this.bi_valid = 0;\n /* Number of valid bits in bi_buf. All bits above the last valid bit\n * are always zero.\n */\n\n // Used for window memory init. We safely ignore it for JS. That makes\n // sense only for pointers and memory check tools.\n //this.high_water = 0;\n /* High water mark offset in window for initialized bytes -- bytes above\n * this are set to zero in order to avoid memory check warnings when\n * longest match routines access bytes past the input. This is then\n * updated to the new high water mark.\n */\n}\n\n\n/* =========================================================================\n * Check for a valid deflate stream state. Return 0 if ok, 1 if not.\n */\nconst deflateStateCheck = (strm) => {\n\n if (!strm) {\n return 1;\n }\n const s = strm.state;\n if (!s || s.strm !== strm || (s.status !== INIT_STATE &&\n//#ifdef GZIP\n s.status !== GZIP_STATE &&\n//#endif\n s.status !== EXTRA_STATE &&\n s.status !== NAME_STATE &&\n s.status !== COMMENT_STATE &&\n s.status !== HCRC_STATE &&\n s.status !== BUSY_STATE &&\n s.status !== FINISH_STATE)) {\n return 1;\n }\n return 0;\n};\n\n\nconst deflateResetKeep = (strm) => {\n\n if (deflateStateCheck(strm)) {\n return err(strm, Z_STREAM_ERROR$2);\n }\n\n strm.total_in = strm.total_out = 0;\n strm.data_type = Z_UNKNOWN;\n\n const s = strm.state;\n s.pending = 0;\n s.pending_out = 0;\n\n if (s.wrap < 0) {\n s.wrap = -s.wrap;\n /* was made negative by deflate(..., Z_FINISH); */\n }\n s.status =\n//#ifdef GZIP\n s.wrap === 2 ? GZIP_STATE :\n//#endif\n s.wrap ? INIT_STATE : BUSY_STATE;\n strm.adler = (s.wrap === 2) ?\n 0 // crc32(0, Z_NULL, 0)\n :\n 1; // adler32(0, Z_NULL, 0)\n s.last_flush = -2;\n _tr_init(s);\n return Z_OK$3;\n};\n\n\nconst deflateReset = (strm) => {\n\n const ret = deflateResetKeep(strm);\n if (ret === Z_OK$3) {\n lm_init(strm.state);\n }\n return ret;\n};\n\n\nconst deflateSetHeader = (strm, head) => {\n\n if (deflateStateCheck(strm) || strm.state.wrap !== 2) {\n return Z_STREAM_ERROR$2;\n }\n strm.state.gzhead = head;\n return Z_OK$3;\n};\n\n\nconst deflateInit2 = (strm, level, method, windowBits, memLevel, strategy) => {\n\n if (!strm) { // === Z_NULL\n return Z_STREAM_ERROR$2;\n }\n let wrap = 1;\n\n if (level === Z_DEFAULT_COMPRESSION$1) {\n level = 6;\n }\n\n if (windowBits < 0) { /* suppress zlib wrapper */\n wrap = 0;\n windowBits = -windowBits;\n }\n\n else if (windowBits > 15) {\n wrap = 2; /* write gzip wrapper instead */\n windowBits -= 16;\n }\n\n\n if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || method !== Z_DEFLATED$2 ||\n windowBits < 8 || windowBits > 15 || level < 0 || level > 9 ||\n strategy < 0 || strategy > Z_FIXED || (windowBits === 8 && wrap !== 1)) {\n return err(strm, Z_STREAM_ERROR$2);\n }\n\n\n if (windowBits === 8) {\n windowBits = 9;\n }\n /* until 256-byte window bug fixed */\n\n const s = new DeflateState();\n\n strm.state = s;\n s.strm = strm;\n s.status = INIT_STATE; /* to pass state test in deflateReset() */\n\n s.wrap = wrap;\n s.gzhead = null;\n s.w_bits = windowBits;\n s.w_size = 1 << s.w_bits;\n s.w_mask = s.w_size - 1;\n\n s.hash_bits = memLevel + 7;\n s.hash_size = 1 << s.hash_bits;\n s.hash_mask = s.hash_size - 1;\n s.hash_shift = ~~((s.hash_bits + MIN_MATCH - 1) / MIN_MATCH);\n\n s.window = new Uint8Array(s.w_size * 2);\n s.head = new Uint16Array(s.hash_size);\n s.prev = new Uint16Array(s.w_size);\n\n // Don't need mem init magic for JS.\n //s.high_water = 0; /* nothing written to s->window yet */\n\n s.lit_bufsize = 1 << (memLevel + 6); /* 16K elements by default */\n\n /* We overlay pending_buf and sym_buf. This works since the average size\n * for length/distance pairs over any compressed block is assured to be 31\n * bits or less.\n *\n * Analysis: The longest fixed codes are a length code of 8 bits plus 5\n * extra bits, for lengths 131 to 257. The longest fixed distance codes are\n * 5 bits plus 13 extra bits, for distances 16385 to 32768. The longest\n * possible fixed-codes length/distance pair is then 31 bits total.\n *\n * sym_buf starts one-fourth of the way into pending_buf. So there are\n * three bytes in sym_buf for every four bytes in pending_buf. Each symbol\n * in sym_buf is three bytes -- two for the distance and one for the\n * literal/length. As each symbol is consumed, the pointer to the next\n * sym_buf value to read moves forward three bytes. From that symbol, up to\n * 31 bits are written to pending_buf. The closest the written pending_buf\n * bits gets to the next sym_buf symbol to read is just before the last\n * code is written. At that time, 31*(n-2) bits have been written, just\n * after 24*(n-2) bits have been consumed from sym_buf. sym_buf starts at\n * 8*n bits into pending_buf. (Note that the symbol buffer fills when n-1\n * symbols are written.) The closest the writing gets to what is unread is\n * then n+14 bits. Here n is lit_bufsize, which is 16384 by default, and\n * can range from 128 to 32768.\n *\n * Therefore, at a minimum, there are 142 bits of space between what is\n * written and what is read in the overlain buffers, so the symbols cannot\n * be overwritten by the compressed data. That space is actually 139 bits,\n * due to the three-bit fixed-code block header.\n *\n * That covers the case where either Z_FIXED is specified, forcing fixed\n * codes, or when the use of fixed codes is chosen, because that choice\n * results in a smaller compressed block than dynamic codes. That latter\n * condition then assures that the above analysis also covers all dynamic\n * blocks. A dynamic-code block will only be chosen to be emitted if it has\n * fewer bits than a fixed-code block would for the same set of symbols.\n * Therefore its average symbol length is assured to be less than 31. So\n * the compressed data for a dynamic block also cannot overwrite the\n * symbols from which it is being constructed.\n */\n\n s.pending_buf_size = s.lit_bufsize * 4;\n s.pending_buf = new Uint8Array(s.pending_buf_size);\n\n // It is offset from `s.pending_buf` (size is `s.lit_bufsize * 2`)\n //s->sym_buf = s->pending_buf + s->lit_bufsize;\n s.sym_buf = s.lit_bufsize;\n\n //s->sym_end = (s->lit_bufsize - 1) * 3;\n s.sym_end = (s.lit_bufsize - 1) * 3;\n /* We avoid equality with lit_bufsize*3 because of wraparound at 64K\n * on 16 bit machines and because stored blocks are restricted to\n * 64K-1 bytes.\n */\n\n s.level = level;\n s.strategy = strategy;\n s.method = method;\n\n return deflateReset(strm);\n};\n\nconst deflateInit = (strm, level) => {\n\n return deflateInit2(strm, level, Z_DEFLATED$2, MAX_WBITS$1, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY$1);\n};\n\n\n/* ========================================================================= */\nconst deflate$2 = (strm, flush) => {\n\n if (deflateStateCheck(strm) || flush > Z_BLOCK$1 || flush < 0) {\n return strm ? err(strm, Z_STREAM_ERROR$2) : Z_STREAM_ERROR$2;\n }\n\n const s = strm.state;\n\n if (!strm.output ||\n (strm.avail_in !== 0 && !strm.input) ||\n (s.status === FINISH_STATE && flush !== Z_FINISH$3)) {\n return err(strm, (strm.avail_out === 0) ? Z_BUF_ERROR$1 : Z_STREAM_ERROR$2);\n }\n\n const old_flush = s.last_flush;\n s.last_flush = flush;\n\n /* Flush as much pending output as possible */\n if (s.pending !== 0) {\n flush_pending(strm);\n if (strm.avail_out === 0) {\n /* Since avail_out is 0, deflate will be called again with\n * more output space, but possibly with both pending and\n * avail_in equal to zero. There won't be anything to do,\n * but this is not an error situation so make sure we\n * return OK instead of BUF_ERROR at next call of deflate:\n */\n s.last_flush = -1;\n return Z_OK$3;\n }\n\n /* Make sure there is something to do and avoid duplicate consecutive\n * flushes. For repeated and useless calls with Z_FINISH, we keep\n * returning Z_STREAM_END instead of Z_BUF_ERROR.\n */\n } else if (strm.avail_in === 0 && rank(flush) <= rank(old_flush) &&\n flush !== Z_FINISH$3) {\n return err(strm, Z_BUF_ERROR$1);\n }\n\n /* User must not provide more input after the first FINISH: */\n if (s.status === FINISH_STATE && strm.avail_in !== 0) {\n return err(strm, Z_BUF_ERROR$1);\n }\n\n /* Write the header */\n if (s.status === INIT_STATE && s.wrap === 0) {\n s.status = BUSY_STATE;\n }\n if (s.status === INIT_STATE) {\n /* zlib header */\n let header = (Z_DEFLATED$2 + ((s.w_bits - 8) << 4)) << 8;\n let level_flags = -1;\n\n if (s.strategy >= Z_HUFFMAN_ONLY || s.level < 2) {\n level_flags = 0;\n } else if (s.level < 6) {\n level_flags = 1;\n } else if (s.level === 6) {\n level_flags = 2;\n } else {\n level_flags = 3;\n }\n header |= (level_flags << 6);\n if (s.strstart !== 0) { header |= PRESET_DICT; }\n header += 31 - (header % 31);\n\n putShortMSB(s, header);\n\n /* Save the adler32 of the preset dictionary: */\n if (s.strstart !== 0) {\n putShortMSB(s, strm.adler >>> 16);\n putShortMSB(s, strm.adler & 0xffff);\n }\n strm.adler = 1; // adler32(0L, Z_NULL, 0);\n s.status = BUSY_STATE;\n\n /* Compression must start with an empty pending buffer */\n flush_pending(strm);\n if (s.pending !== 0) {\n s.last_flush = -1;\n return Z_OK$3;\n }\n }\n//#ifdef GZIP\n if (s.status === GZIP_STATE) {\n /* gzip header */\n strm.adler = 0; //crc32(0L, Z_NULL, 0);\n put_byte(s, 31);\n put_byte(s, 139);\n put_byte(s, 8);\n if (!s.gzhead) { // s->gzhead == Z_NULL\n put_byte(s, 0);\n put_byte(s, 0);\n put_byte(s, 0);\n put_byte(s, 0);\n put_byte(s, 0);\n put_byte(s, s.level === 9 ? 2 :\n (s.strategy >= Z_HUFFMAN_ONLY || s.level < 2 ?\n 4 : 0));\n put_byte(s, OS_CODE);\n s.status = BUSY_STATE;\n\n /* Compression must start with an empty pending buffer */\n flush_pending(strm);\n if (s.pending !== 0) {\n s.last_flush = -1;\n return Z_OK$3;\n }\n }\n else {\n put_byte(s, (s.gzhead.text ? 1 : 0) +\n (s.gzhead.hcrc ? 2 : 0) +\n (!s.gzhead.extra ? 0 : 4) +\n (!s.gzhead.name ? 0 : 8) +\n (!s.gzhead.comment ? 0 : 16)\n );\n put_byte(s, s.gzhead.time & 0xff);\n put_byte(s, (s.gzhead.time >> 8) & 0xff);\n put_byte(s, (s.gzhead.time >> 16) & 0xff);\n put_byte(s, (s.gzhead.time >> 24) & 0xff);\n put_byte(s, s.level === 9 ? 2 :\n (s.strategy >= Z_HUFFMAN_ONLY || s.level < 2 ?\n 4 : 0));\n put_byte(s, s.gzhead.os & 0xff);\n if (s.gzhead.extra && s.gzhead.extra.length) {\n put_byte(s, s.gzhead.extra.length & 0xff);\n put_byte(s, (s.gzhead.extra.length >> 8) & 0xff);\n }\n if (s.gzhead.hcrc) {\n strm.adler = crc32_1(strm.adler, s.pending_buf, s.pending, 0);\n }\n s.gzindex = 0;\n s.status = EXTRA_STATE;\n }\n }\n if (s.status === EXTRA_STATE) {\n if (s.gzhead.extra/* != Z_NULL*/) {\n let beg = s.pending; /* start of bytes to update crc */\n let left = (s.gzhead.extra.length & 0xffff) - s.gzindex;\n while (s.pending + left > s.pending_buf_size) {\n let copy = s.pending_buf_size - s.pending;\n // zmemcpy(s.pending_buf + s.pending,\n // s.gzhead.extra + s.gzindex, copy);\n s.pending_buf.set(s.gzhead.extra.subarray(s.gzindex, s.gzindex + copy), s.pending);\n s.pending = s.pending_buf_size;\n //--- HCRC_UPDATE(beg) ---//\n if (s.gzhead.hcrc && s.pending > beg) {\n strm.adler = crc32_1(strm.adler, s.pending_buf, s.pending - beg, beg);\n }\n //---//\n s.gzindex += copy;\n flush_pending(strm);\n if (s.pending !== 0) {\n s.last_flush = -1;\n return Z_OK$3;\n }\n beg = 0;\n left -= copy;\n }\n // JS specific: s.gzhead.extra may be TypedArray or Array for backward compatibility\n // TypedArray.slice and TypedArray.from don't exist in IE10-IE11\n let gzhead_extra = new Uint8Array(s.gzhead.extra);\n // zmemcpy(s->pending_buf + s->pending,\n // s->gzhead->extra + s->gzindex, left);\n s.pending_buf.set(gzhead_extra.subarray(s.gzindex, s.gzindex + left), s.pending);\n s.pending += left;\n //--- HCRC_UPDATE(beg) ---//\n if (s.gzhead.hcrc && s.pending > beg) {\n strm.adler = crc32_1(strm.adler, s.pending_buf, s.pending - beg, beg);\n }\n //---//\n s.gzindex = 0;\n }\n s.status = NAME_STATE;\n }\n if (s.status === NAME_STATE) {\n if (s.gzhead.name/* != Z_NULL*/) {\n let beg = s.pending; /* start of bytes to update crc */\n let val;\n do {\n if (s.pending === s.pending_buf_size) {\n //--- HCRC_UPDATE(beg) ---//\n if (s.gzhead.hcrc && s.pending > beg) {\n strm.adler = crc32_1(strm.adler, s.pending_buf, s.pending - beg, beg);\n }\n //---//\n flush_pending(strm);\n if (s.pending !== 0) {\n s.last_flush = -1;\n return Z_OK$3;\n }\n beg = 0;\n }\n // JS specific: little magic to add zero terminator to end of string\n if (s.gzindex < s.gzhead.name.length) {\n val = s.gzhead.name.charCodeAt(s.gzindex++) & 0xff;\n } else {\n val = 0;\n }\n put_byte(s, val);\n } while (val !== 0);\n //--- HCRC_UPDATE(beg) ---//\n if (s.gzhead.hcrc && s.pending > beg) {\n strm.adler = crc32_1(strm.adler, s.pending_buf, s.pending - beg, beg);\n }\n //---//\n s.gzindex = 0;\n }\n s.status = COMMENT_STATE;\n }\n if (s.status === COMMENT_STATE) {\n if (s.gzhead.comment/* != Z_NULL*/) {\n let beg = s.pending; /* start of bytes to update crc */\n let val;\n do {\n if (s.pending === s.pending_buf_size) {\n //--- HCRC_UPDATE(beg) ---//\n if (s.gzhead.hcrc && s.pending > beg) {\n strm.adler = crc32_1(strm.adler, s.pending_buf, s.pending - beg, beg);\n }\n //---//\n flush_pending(strm);\n if (s.pending !== 0) {\n s.last_flush = -1;\n return Z_OK$3;\n }\n beg = 0;\n }\n // JS specific: little magic to add zero terminator to end of string\n if (s.gzindex < s.gzhead.comment.length) {\n val = s.gzhead.comment.charCodeAt(s.gzindex++) & 0xff;\n } else {\n val = 0;\n }\n put_byte(s, val);\n } while (val !== 0);\n //--- HCRC_UPDATE(beg) ---//\n if (s.gzhead.hcrc && s.pending > beg) {\n strm.adler = crc32_1(strm.adler, s.pending_buf, s.pending - beg, beg);\n }\n //---//\n }\n s.status = HCRC_STATE;\n }\n if (s.status === HCRC_STATE) {\n if (s.gzhead.hcrc) {\n if (s.pending + 2 > s.pending_buf_size) {\n flush_pending(strm);\n if (s.pending !== 0) {\n s.last_flush = -1;\n return Z_OK$3;\n }\n }\n put_byte(s, strm.adler & 0xff);\n put_byte(s, (strm.adler >> 8) & 0xff);\n strm.adler = 0; //crc32(0L, Z_NULL, 0);\n }\n s.status = BUSY_STATE;\n\n /* Compression must start with an empty pending buffer */\n flush_pending(strm);\n if (s.pending !== 0) {\n s.last_flush = -1;\n return Z_OK$3;\n }\n }\n//#endif\n\n /* Start a new block or continue the current one.\n */\n if (strm.avail_in !== 0 || s.lookahead !== 0 ||\n (flush !== Z_NO_FLUSH$2 && s.status !== FINISH_STATE)) {\n let bstate = s.level === 0 ? deflate_stored(s, flush) :\n s.strategy === Z_HUFFMAN_ONLY ? deflate_huff(s, flush) :\n s.strategy === Z_RLE ? deflate_rle(s, flush) :\n configuration_table[s.level].func(s, flush);\n\n if (bstate === BS_FINISH_STARTED || bstate === BS_FINISH_DONE) {\n s.status = FINISH_STATE;\n }\n if (bstate === BS_NEED_MORE || bstate === BS_FINISH_STARTED) {\n if (strm.avail_out === 0) {\n s.last_flush = -1;\n /* avoid BUF_ERROR next call, see above */\n }\n return Z_OK$3;\n /* If flush != Z_NO_FLUSH && avail_out == 0, the next call\n * of deflate should use the same flush parameter to make sure\n * that the flush is complete. So we don't have to output an\n * empty block here, this will be done at next call. This also\n * ensures that for a very small output buffer, we emit at most\n * one empty block.\n */\n }\n if (bstate === BS_BLOCK_DONE) {\n if (flush === Z_PARTIAL_FLUSH) {\n _tr_align(s);\n }\n else if (flush !== Z_BLOCK$1) { /* FULL_FLUSH or SYNC_FLUSH */\n\n _tr_stored_block(s, 0, 0, false);\n /* For a full flush, this empty block will be recognized\n * as a special marker by inflate_sync().\n */\n if (flush === Z_FULL_FLUSH$1) {\n /*** CLEAR_HASH(s); ***/ /* forget history */\n zero(s.head); // Fill with NIL (= 0);\n\n if (s.lookahead === 0) {\n s.strstart = 0;\n s.block_start = 0;\n s.insert = 0;\n }\n }\n }\n flush_pending(strm);\n if (strm.avail_out === 0) {\n s.last_flush = -1; /* avoid BUF_ERROR at next call, see above */\n return Z_OK$3;\n }\n }\n }\n\n if (flush !== Z_FINISH$3) { return Z_OK$3; }\n if (s.wrap <= 0) { return Z_STREAM_END$3; }\n\n /* Write the trailer */\n if (s.wrap === 2) {\n put_byte(s, strm.adler & 0xff);\n put_byte(s, (strm.adler >> 8) & 0xff);\n put_byte(s, (strm.adler >> 16) & 0xff);\n put_byte(s, (strm.adler >> 24) & 0xff);\n put_byte(s, strm.total_in & 0xff);\n put_byte(s, (strm.total_in >> 8) & 0xff);\n put_byte(s, (strm.total_in >> 16) & 0xff);\n put_byte(s, (strm.total_in >> 24) & 0xff);\n }\n else\n {\n putShortMSB(s, strm.adler >>> 16);\n putShortMSB(s, strm.adler & 0xffff);\n }\n\n flush_pending(strm);\n /* If avail_out is zero, the application will call deflate again\n * to flush the rest.\n */\n if (s.wrap > 0) { s.wrap = -s.wrap; }\n /* write the trailer only once! */\n return s.pending !== 0 ? Z_OK$3 : Z_STREAM_END$3;\n};\n\n\nconst deflateEnd = (strm) => {\n\n if (deflateStateCheck(strm)) {\n return Z_STREAM_ERROR$2;\n }\n\n const status = strm.state.status;\n\n strm.state = null;\n\n return status === BUSY_STATE ? err(strm, Z_DATA_ERROR$2) : Z_OK$3;\n};\n\n\n/* =========================================================================\n * Initializes the compression dictionary from the given byte\n * sequence without producing any compressed output.\n */\nconst deflateSetDictionary = (strm, dictionary) => {\n\n let dictLength = dictionary.length;\n\n if (deflateStateCheck(strm)) {\n return Z_STREAM_ERROR$2;\n }\n\n const s = strm.state;\n const wrap = s.wrap;\n\n if (wrap === 2 || (wrap === 1 && s.status !== INIT_STATE) || s.lookahead) {\n return Z_STREAM_ERROR$2;\n }\n\n /* when using zlib wrappers, compute Adler-32 for provided dictionary */\n if (wrap === 1) {\n /* adler32(strm->adler, dictionary, dictLength); */\n strm.adler = adler32_1(strm.adler, dictionary, dictLength, 0);\n }\n\n s.wrap = 0; /* avoid computing Adler-32 in read_buf */\n\n /* if dictionary would fill window, just replace the history */\n if (dictLength >= s.w_size) {\n if (wrap === 0) { /* already empty otherwise */\n /*** CLEAR_HASH(s); ***/\n zero(s.head); // Fill with NIL (= 0);\n s.strstart = 0;\n s.block_start = 0;\n s.insert = 0;\n }\n /* use the tail */\n // dictionary = dictionary.slice(dictLength - s.w_size);\n let tmpDict = new Uint8Array(s.w_size);\n tmpDict.set(dictionary.subarray(dictLength - s.w_size, dictLength), 0);\n dictionary = tmpDict;\n dictLength = s.w_size;\n }\n /* insert dictionary into window and hash */\n const avail = strm.avail_in;\n const next = strm.next_in;\n const input = strm.input;\n strm.avail_in = dictLength;\n strm.next_in = 0;\n strm.input = dictionary;\n fill_window(s);\n while (s.lookahead >= MIN_MATCH) {\n let str = s.strstart;\n let n = s.lookahead - (MIN_MATCH - 1);\n do {\n /* UPDATE_HASH(s, s->ins_h, s->window[str + MIN_MATCH-1]); */\n s.ins_h = HASH(s, s.ins_h, s.window[str + MIN_MATCH - 1]);\n\n s.prev[str & s.w_mask] = s.head[s.ins_h];\n\n s.head[s.ins_h] = str;\n str++;\n } while (--n);\n s.strstart = str;\n s.lookahead = MIN_MATCH - 1;\n fill_window(s);\n }\n s.strstart += s.lookahead;\n s.block_start = s.strstart;\n s.insert = s.lookahead;\n s.lookahead = 0;\n s.match_length = s.prev_length = MIN_MATCH - 1;\n s.match_available = 0;\n strm.next_in = next;\n strm.input = input;\n strm.avail_in = avail;\n s.wrap = wrap;\n return Z_OK$3;\n};\n\n\nvar deflateInit_1 = deflateInit;\nvar deflateInit2_1 = deflateInit2;\nvar deflateReset_1 = deflateReset;\nvar deflateResetKeep_1 = deflateResetKeep;\nvar deflateSetHeader_1 = deflateSetHeader;\nvar deflate_2$1 = deflate$2;\nvar deflateEnd_1 = deflateEnd;\nvar deflateSetDictionary_1 = deflateSetDictionary;\nvar deflateInfo = 'pako deflate (from Nodeca project)';\n\n/* Not implemented\nmodule.exports.deflateBound = deflateBound;\nmodule.exports.deflateCopy = deflateCopy;\nmodule.exports.deflateGetDictionary = deflateGetDictionary;\nmodule.exports.deflateParams = deflateParams;\nmodule.exports.deflatePending = deflatePending;\nmodule.exports.deflatePrime = deflatePrime;\nmodule.exports.deflateTune = deflateTune;\n*/\n\nvar deflate_1$2 = {\n\tdeflateInit: deflateInit_1,\n\tdeflateInit2: deflateInit2_1,\n\tdeflateReset: deflateReset_1,\n\tdeflateResetKeep: deflateResetKeep_1,\n\tdeflateSetHeader: deflateSetHeader_1,\n\tdeflate: deflate_2$1,\n\tdeflateEnd: deflateEnd_1,\n\tdeflateSetDictionary: deflateSetDictionary_1,\n\tdeflateInfo: deflateInfo\n};\n\nconst _has = (obj, key) => {\n return Object.prototype.hasOwnProperty.call(obj, key);\n};\n\nvar assign = function (obj /*from1, from2, from3, ...*/) {\n const sources = Array.prototype.slice.call(arguments, 1);\n while (sources.length) {\n const source = sources.shift();\n if (!source) { continue; }\n\n if (typeof source !== 'object') {\n throw new TypeError(source + 'must be non-object');\n }\n\n for (const p in source) {\n if (_has(source, p)) {\n obj[p] = source[p];\n }\n }\n }\n\n return obj;\n};\n\n\n// Join array of chunks to single array.\nvar flattenChunks = (chunks) => {\n // calculate data length\n let len = 0;\n\n for (let i = 0, l = chunks.length; i < l; i++) {\n len += chunks[i].length;\n }\n\n // join chunks\n const result = new Uint8Array(len);\n\n for (let i = 0, pos = 0, l = chunks.length; i < l; i++) {\n let chunk = chunks[i];\n result.set(chunk, pos);\n pos += chunk.length;\n }\n\n return result;\n};\n\nvar common = {\n\tassign: assign,\n\tflattenChunks: flattenChunks\n};\n\n// String encode/decode helpers\n\n\n// Quick check if we can use fast array to bin string conversion\n//\n// - apply(Array) can fail on Android 2.2\n// - apply(Uint8Array) can fail on iOS 5.1 Safari\n//\nlet STR_APPLY_UIA_OK = true;\n\ntry { String.fromCharCode.apply(null, new Uint8Array(1)); } catch (__) { STR_APPLY_UIA_OK = false; }\n\n\n// Table with utf8 lengths (calculated by first byte of sequence)\n// Note, that 5 & 6-byte values and some 4-byte values can not be represented in JS,\n// because max possible codepoint is 0x10ffff\nconst _utf8len = new Uint8Array(256);\nfor (let q = 0; q < 256; q++) {\n _utf8len[q] = (q >= 252 ? 6 : q >= 248 ? 5 : q >= 240 ? 4 : q >= 224 ? 3 : q >= 192 ? 2 : 1);\n}\n_utf8len[254] = _utf8len[254] = 1; // Invalid sequence start\n\n\n// convert string to array (typed, when possible)\nvar string2buf = (str) => {\n if (typeof TextEncoder === 'function' && TextEncoder.prototype.encode) {\n return new TextEncoder().encode(str);\n }\n\n let buf, c, c2, m_pos, i, str_len = str.length, buf_len = 0;\n\n // count binary size\n for (m_pos = 0; m_pos < str_len; m_pos++) {\n c = str.charCodeAt(m_pos);\n if ((c & 0xfc00) === 0xd800 && (m_pos + 1 < str_len)) {\n c2 = str.charCodeAt(m_pos + 1);\n if ((c2 & 0xfc00) === 0xdc00) {\n c = 0x10000 + ((c - 0xd800) << 10) + (c2 - 0xdc00);\n m_pos++;\n }\n }\n buf_len += c < 0x80 ? 1 : c < 0x800 ? 2 : c < 0x10000 ? 3 : 4;\n }\n\n // allocate buffer\n buf = new Uint8Array(buf_len);\n\n // convert\n for (i = 0, m_pos = 0; i < buf_len; m_pos++) {\n c = str.charCodeAt(m_pos);\n if ((c & 0xfc00) === 0xd800 && (m_pos + 1 < str_len)) {\n c2 = str.charCodeAt(m_pos + 1);\n if ((c2 & 0xfc00) === 0xdc00) {\n c = 0x10000 + ((c - 0xd800) << 10) + (c2 - 0xdc00);\n m_pos++;\n }\n }\n if (c < 0x80) {\n /* one byte */\n buf[i++] = c;\n } else if (c < 0x800) {\n /* two bytes */\n buf[i++] = 0xC0 | (c >>> 6);\n buf[i++] = 0x80 | (c & 0x3f);\n } else if (c < 0x10000) {\n /* three bytes */\n buf[i++] = 0xE0 | (c >>> 12);\n buf[i++] = 0x80 | (c >>> 6 & 0x3f);\n buf[i++] = 0x80 | (c & 0x3f);\n } else {\n /* four bytes */\n buf[i++] = 0xf0 | (c >>> 18);\n buf[i++] = 0x80 | (c >>> 12 & 0x3f);\n buf[i++] = 0x80 | (c >>> 6 & 0x3f);\n buf[i++] = 0x80 | (c & 0x3f);\n }\n }\n\n return buf;\n};\n\n// Helper\nconst buf2binstring = (buf, len) => {\n // On Chrome, the arguments in a function call that are allowed is `65534`.\n // If the length of the buffer is smaller than that, we can use this optimization,\n // otherwise we will take a slower path.\n if (len < 65534) {\n if (buf.subarray && STR_APPLY_UIA_OK) {\n return String.fromCharCode.apply(null, buf.length === len ? buf : buf.subarray(0, len));\n }\n }\n\n let result = '';\n for (let i = 0; i < len; i++) {\n result += String.fromCharCode(buf[i]);\n }\n return result;\n};\n\n\n// convert array to string\nvar buf2string = (buf, max) => {\n const len = max || buf.length;\n\n if (typeof TextDecoder === 'function' && TextDecoder.prototype.decode) {\n return new TextDecoder().decode(buf.subarray(0, max));\n }\n\n let i, out;\n\n // Reserve max possible length (2 words per char)\n // NB: by unknown reasons, Array is significantly faster for\n // String.fromCharCode.apply than Uint16Array.\n const utf16buf = new Array(len * 2);\n\n for (out = 0, i = 0; i < len;) {\n let c = buf[i++];\n // quick process ascii\n if (c < 0x80) { utf16buf[out++] = c; continue; }\n\n let c_len = _utf8len[c];\n // skip 5 & 6 byte codes\n if (c_len > 4) { utf16buf[out++] = 0xfffd; i += c_len - 1; continue; }\n\n // apply mask on first byte\n c &= c_len === 2 ? 0x1f : c_len === 3 ? 0x0f : 0x07;\n // join the rest\n while (c_len > 1 && i < len) {\n c = (c << 6) | (buf[i++] & 0x3f);\n c_len--;\n }\n\n // terminated by end of string?\n if (c_len > 1) { utf16buf[out++] = 0xfffd; continue; }\n\n if (c < 0x10000) {\n utf16buf[out++] = c;\n } else {\n c -= 0x10000;\n utf16buf[out++] = 0xd800 | ((c >> 10) & 0x3ff);\n utf16buf[out++] = 0xdc00 | (c & 0x3ff);\n }\n }\n\n return buf2binstring(utf16buf, out);\n};\n\n\n// Calculate max possible position in utf8 buffer,\n// that will not break sequence. If that's not possible\n// - (very small limits) return max size as is.\n//\n// buf[] - utf8 bytes array\n// max - length limit (mandatory);\nvar utf8border = (buf, max) => {\n\n max = max || buf.length;\n if (max > buf.length) { max = buf.length; }\n\n // go back from last position, until start of sequence found\n let pos = max - 1;\n while (pos >= 0 && (buf[pos] & 0xC0) === 0x80) { pos--; }\n\n // Very small and broken sequence,\n // return max, because we should return something anyway.\n if (pos < 0) { return max; }\n\n // If we came to start of buffer - that means buffer is too small,\n // return max too.\n if (pos === 0) { return max; }\n\n return (pos + _utf8len[buf[pos]] > max) ? pos : max;\n};\n\nvar strings = {\n\tstring2buf: string2buf,\n\tbuf2string: buf2string,\n\tutf8border: utf8border\n};\n\n// (C) 1995-2013 Jean-loup Gailly and Mark Adler\n// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin\n//\n// This software is provided 'as-is', without any express or implied\n// warranty. In no event will the authors be held liable for any damages\n// arising from the use of this software.\n//\n// Permission is granted to anyone to use this software for any purpose,\n// including commercial applications, and to alter it and redistribute it\n// freely, subject to the following restrictions:\n//\n// 1. The origin of this software must not be misrepresented; you must not\n// claim that you wrote the original software. If you use this software\n// in a product, an acknowledgment in the product documentation would be\n// appreciated but is not required.\n// 2. Altered source versions must be plainly marked as such, and must not be\n// misrepresented as being the original software.\n// 3. This notice may not be removed or altered from any source distribution.\n\nfunction ZStream() {\n /* next input byte */\n this.input = null; // JS specific, because we have no pointers\n this.next_in = 0;\n /* number of bytes available at input */\n this.avail_in = 0;\n /* total number of input bytes read so far */\n this.total_in = 0;\n /* next output byte should be put there */\n this.output = null; // JS specific, because we have no pointers\n this.next_out = 0;\n /* remaining free space at output */\n this.avail_out = 0;\n /* total number of bytes output so far */\n this.total_out = 0;\n /* last error message, NULL if no error */\n this.msg = ''/*Z_NULL*/;\n /* not visible by applications */\n this.state = null;\n /* best guess about the data type: binary or text */\n this.data_type = 2/*Z_UNKNOWN*/;\n /* adler32 value of the uncompressed data */\n this.adler = 0;\n}\n\nvar zstream = ZStream;\n\nconst toString$1 = Object.prototype.toString;\n\n/* Public constants ==========================================================*/\n/* ===========================================================================*/\n\nconst {\n Z_NO_FLUSH: Z_NO_FLUSH$1, Z_SYNC_FLUSH, Z_FULL_FLUSH, Z_FINISH: Z_FINISH$2,\n Z_OK: Z_OK$2, Z_STREAM_END: Z_STREAM_END$2,\n Z_DEFAULT_COMPRESSION,\n Z_DEFAULT_STRATEGY,\n Z_DEFLATED: Z_DEFLATED$1\n} = constants$2;\n\n/* ===========================================================================*/\n\n\n/**\n * class Deflate\n *\n * Generic JS-style wrapper for zlib calls. If you don't need\n * streaming behaviour - use more simple functions: [[deflate]],\n * [[deflateRaw]] and [[gzip]].\n **/\n\n/* internal\n * Deflate.chunks -> Array\n *\n * Chunks of output data, if [[Deflate#onData]] not overridden.\n **/\n\n/**\n * Deflate.result -> Uint8Array\n *\n * Compressed result, generated by default [[Deflate#onData]]\n * and [[Deflate#onEnd]] handlers. Filled after you push last chunk\n * (call [[Deflate#push]] with `Z_FINISH` / `true` param).\n **/\n\n/**\n * Deflate.err -> Number\n *\n * Error code after deflate finished. 0 (Z_OK) on success.\n * You will not need it in real life, because deflate errors\n * are possible only on wrong options or bad `onData` / `onEnd`\n * custom handlers.\n **/\n\n/**\n * Deflate.msg -> String\n *\n * Error message, if [[Deflate.err]] != 0\n **/\n\n\n/**\n * new Deflate(options)\n * - options (Object): zlib deflate options.\n *\n * Creates new deflator instance with specified params. Throws exception\n * on bad params. Supported options:\n *\n * - `level`\n * - `windowBits`\n * - `memLevel`\n * - `strategy`\n * - `dictionary`\n *\n * [http://zlib.net/manual.html#Advanced](http://zlib.net/manual.html#Advanced)\n * for more information on these.\n *\n * Additional options, for internal needs:\n *\n * - `chunkSize` - size of generated data chunks (16K by default)\n * - `raw` (Boolean) - do raw deflate\n * - `gzip` (Boolean) - create gzip wrapper\n * - `header` (Object) - custom header for gzip\n * - `text` (Boolean) - true if compressed data believed to be text\n * - `time` (Number) - modification time, unix timestamp\n * - `os` (Number) - operation system code\n * - `extra` (Array) - array of bytes with extra data (max 65536)\n * - `name` (String) - file name (binary string)\n * - `comment` (String) - comment (binary string)\n * - `hcrc` (Boolean) - true if header crc should be added\n *\n * ##### Example:\n *\n * ```javascript\n * const pako = require('pako')\n * , chunk1 = new Uint8Array([1,2,3,4,5,6,7,8,9])\n * , chunk2 = new Uint8Array([10,11,12,13,14,15,16,17,18,19]);\n *\n * const deflate = new pako.Deflate({ level: 3});\n *\n * deflate.push(chunk1, false);\n * deflate.push(chunk2, true); // true -> last chunk\n *\n * if (deflate.err) { throw new Error(deflate.err); }\n *\n * console.log(deflate.result);\n * ```\n **/\nfunction Deflate$1(options) {\n this.options = common.assign({\n level: Z_DEFAULT_COMPRESSION,\n method: Z_DEFLATED$1,\n chunkSize: 16384,\n windowBits: 15,\n memLevel: 8,\n strategy: Z_DEFAULT_STRATEGY\n }, options || {});\n\n let opt = this.options;\n\n if (opt.raw && (opt.windowBits > 0)) {\n opt.windowBits = -opt.windowBits;\n }\n\n else if (opt.gzip && (opt.windowBits > 0) && (opt.windowBits < 16)) {\n opt.windowBits += 16;\n }\n\n this.err = 0; // error code, if happens (0 = Z_OK)\n this.msg = ''; // error message\n this.ended = false; // used to avoid multiple onEnd() calls\n this.chunks = []; // chunks of compressed data\n\n this.strm = new zstream();\n this.strm.avail_out = 0;\n\n let status = deflate_1$2.deflateInit2(\n this.strm,\n opt.level,\n opt.method,\n opt.windowBits,\n opt.memLevel,\n opt.strategy\n );\n\n if (status !== Z_OK$2) {\n throw new Error(messages[status]);\n }\n\n if (opt.header) {\n deflate_1$2.deflateSetHeader(this.strm, opt.header);\n }\n\n if (opt.dictionary) {\n let dict;\n // Convert data if needed\n if (typeof opt.dictionary === 'string') {\n // If we need to compress text, change encoding to utf8.\n dict = strings.string2buf(opt.dictionary);\n } else if (toString$1.call(opt.dictionary) === '[object ArrayBuffer]') {\n dict = new Uint8Array(opt.dictionary);\n } else {\n dict = opt.dictionary;\n }\n\n status = deflate_1$2.deflateSetDictionary(this.strm, dict);\n\n if (status !== Z_OK$2) {\n throw new Error(messages[status]);\n }\n\n this._dict_set = true;\n }\n}\n\n/**\n * Deflate#push(data[, flush_mode]) -> Boolean\n * - data (Uint8Array|ArrayBuffer|String): input data. Strings will be\n * converted to utf8 byte sequence.\n * - flush_mode (Number|Boolean): 0..6 for corresponding Z_NO_FLUSH..Z_TREE modes.\n * See constants. Skipped or `false` means Z_NO_FLUSH, `true` means Z_FINISH.\n *\n * Sends input data to deflate pipe, generating [[Deflate#onData]] calls with\n * new compressed chunks. Returns `true` on success. The last data block must\n * have `flush_mode` Z_FINISH (or `true`). That will flush internal pending\n * buffers and call [[Deflate#onEnd]].\n *\n * On fail call [[Deflate#onEnd]] with error code and return false.\n *\n * ##### Example\n *\n * ```javascript\n * push(chunk, false); // push one of data chunks\n * ...\n * push(chunk, true); // push last chunk\n * ```\n **/\nDeflate$1.prototype.push = function (data, flush_mode) {\n const strm = this.strm;\n const chunkSize = this.options.chunkSize;\n let status, _flush_mode;\n\n if (this.ended) { return false; }\n\n if (flush_mode === ~~flush_mode) _flush_mode = flush_mode;\n else _flush_mode = flush_mode === true ? Z_FINISH$2 : Z_NO_FLUSH$1;\n\n // Convert data if needed\n if (typeof data === 'string') {\n // If we need to compress text, change encoding to utf8.\n strm.input = strings.string2buf(data);\n } else if (toString$1.call(data) === '[object ArrayBuffer]') {\n strm.input = new Uint8Array(data);\n } else {\n strm.input = data;\n }\n\n strm.next_in = 0;\n strm.avail_in = strm.input.length;\n\n for (;;) {\n if (strm.avail_out === 0) {\n strm.output = new Uint8Array(chunkSize);\n strm.next_out = 0;\n strm.avail_out = chunkSize;\n }\n\n // Make sure avail_out > 6 to avoid repeating markers\n if ((_flush_mode === Z_SYNC_FLUSH || _flush_mode === Z_FULL_FLUSH) && strm.avail_out <= 6) {\n this.onData(strm.output.subarray(0, strm.next_out));\n strm.avail_out = 0;\n continue;\n }\n\n status = deflate_1$2.deflate(strm, _flush_mode);\n\n // Ended => flush and finish\n if (status === Z_STREAM_END$2) {\n if (strm.next_out > 0) {\n this.onData(strm.output.subarray(0, strm.next_out));\n }\n status = deflate_1$2.deflateEnd(this.strm);\n this.onEnd(status);\n this.ended = true;\n return status === Z_OK$2;\n }\n\n // Flush if out buffer full\n if (strm.avail_out === 0) {\n this.onData(strm.output);\n continue;\n }\n\n // Flush if requested and has data\n if (_flush_mode > 0 && strm.next_out > 0) {\n this.onData(strm.output.subarray(0, strm.next_out));\n strm.avail_out = 0;\n continue;\n }\n\n if (strm.avail_in === 0) break;\n }\n\n return true;\n};\n\n\n/**\n * Deflate#onData(chunk) -> Void\n * - chunk (Uint8Array): output data.\n *\n * By default, stores data blocks in `chunks[]` property and glue\n * those in `onEnd`. Override this handler, if you need another behaviour.\n **/\nDeflate$1.prototype.onData = function (chunk) {\n this.chunks.push(chunk);\n};\n\n\n/**\n * Deflate#onEnd(status) -> Void\n * - status (Number): deflate status. 0 (Z_OK) on success,\n * other if not.\n *\n * Called once after you tell deflate that the input stream is\n * complete (Z_FINISH). By default - join collected chunks,\n * free memory and fill `results` / `err` properties.\n **/\nDeflate$1.prototype.onEnd = function (status) {\n // On success - join\n if (status === Z_OK$2) {\n this.result = common.flattenChunks(this.chunks);\n }\n this.chunks = [];\n this.err = status;\n this.msg = this.strm.msg;\n};\n\n\n/**\n * deflate(data[, options]) -> Uint8Array\n * - data (Uint8Array|ArrayBuffer|String): input data to compress.\n * - options (Object): zlib deflate options.\n *\n * Compress `data` with deflate algorithm and `options`.\n *\n * Supported options are:\n *\n * - level\n * - windowBits\n * - memLevel\n * - strategy\n * - dictionary\n *\n * [http://zlib.net/manual.html#Advanced](http://zlib.net/manual.html#Advanced)\n * for more information on these.\n *\n * Sugar (options):\n *\n * - `raw` (Boolean) - say that we work with raw stream, if you don't wish to specify\n * negative windowBits implicitly.\n *\n * ##### Example:\n *\n * ```javascript\n * const pako = require('pako')\n * const data = new Uint8Array([1,2,3,4,5,6,7,8,9]);\n *\n * console.log(pako.deflate(data));\n * ```\n **/\nfunction deflate$1(input, options) {\n const deflator = new Deflate$1(options);\n\n deflator.push(input, true);\n\n // That will never happens, if you don't cheat with options :)\n if (deflator.err) { throw deflator.msg || messages[deflator.err]; }\n\n return deflator.result;\n}\n\n\n/**\n * deflateRaw(data[, options]) -> Uint8Array\n * - data (Uint8Array|ArrayBuffer|String): input data to compress.\n * - options (Object): zlib deflate options.\n *\n * The same as [[deflate]], but creates raw data, without wrapper\n * (header and adler32 crc).\n **/\nfunction deflateRaw$1(input, options) {\n options = options || {};\n options.raw = true;\n return deflate$1(input, options);\n}\n\n\n/**\n * gzip(data[, options]) -> Uint8Array\n * - data (Uint8Array|ArrayBuffer|String): input data to compress.\n * - options (Object): zlib deflate options.\n *\n * The same as [[deflate]], but create gzip wrapper instead of\n * deflate one.\n **/\nfunction gzip$1(input, options) {\n options = options || {};\n options.gzip = true;\n return deflate$1(input, options);\n}\n\n\nvar Deflate_1$1 = Deflate$1;\nvar deflate_2 = deflate$1;\nvar deflateRaw_1$1 = deflateRaw$1;\nvar gzip_1$1 = gzip$1;\nvar constants$1 = constants$2;\n\nvar deflate_1$1 = {\n\tDeflate: Deflate_1$1,\n\tdeflate: deflate_2,\n\tdeflateRaw: deflateRaw_1$1,\n\tgzip: gzip_1$1,\n\tconstants: constants$1\n};\n\n// (C) 1995-2013 Jean-loup Gailly and Mark Adler\n// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin\n//\n// This software is provided 'as-is', without any express or implied\n// warranty. In no event will the authors be held liable for any damages\n// arising from the use of this software.\n//\n// Permission is granted to anyone to use this software for any purpose,\n// including commercial applications, and to alter it and redistribute it\n// freely, subject to the following restrictions:\n//\n// 1. The origin of this software must not be misrepresented; you must not\n// claim that you wrote the original software. If you use this software\n// in a product, an acknowledgment in the product documentation would be\n// appreciated but is not required.\n// 2. Altered source versions must be plainly marked as such, and must not be\n// misrepresented as being the original software.\n// 3. This notice may not be removed or altered from any source distribution.\n\n// See state defs from inflate.js\nconst BAD$1 = 16209; /* got a data error -- remain here until reset */\nconst TYPE$1 = 16191; /* i: waiting for type bits, including last-flag bit */\n\n/*\n Decode literal, length, and distance codes and write out the resulting\n literal and match bytes until either not enough input or output is\n available, an end-of-block is encountered, or a data error is encountered.\n When large enough input and output buffers are supplied to inflate(), for\n example, a 16K input buffer and a 64K output buffer, more than 95% of the\n inflate execution time is spent in this routine.\n\n Entry assumptions:\n\n state.mode === LEN\n strm.avail_in >= 6\n strm.avail_out >= 258\n start >= strm.avail_out\n state.bits < 8\n\n On return, state.mode is one of:\n\n LEN -- ran out of enough output space or enough available input\n TYPE -- reached end of block code, inflate() to interpret next block\n BAD -- error in block data\n\n Notes:\n\n - The maximum input bits used by a length/distance pair is 15 bits for the\n length code, 5 bits for the length extra, 15 bits for the distance code,\n and 13 bits for the distance extra. This totals 48 bits, or six bytes.\n Therefore if strm.avail_in >= 6, then there is enough input to avoid\n checking for available input while decoding.\n\n - The maximum bytes that a single length/distance pair can output is 258\n bytes, which is the maximum length that can be coded. inflate_fast()\n requires strm.avail_out >= 258 for each loop to avoid checking for\n output space.\n */\nvar inffast = function inflate_fast(strm, start) {\n let _in; /* local strm.input */\n let last; /* have enough input while in < last */\n let _out; /* local strm.output */\n let beg; /* inflate()'s initial strm.output */\n let end; /* while out < end, enough space available */\n//#ifdef INFLATE_STRICT\n let dmax; /* maximum distance from zlib header */\n//#endif\n let wsize; /* window size or zero if not using window */\n let whave; /* valid bytes in the window */\n let wnext; /* window write index */\n // Use `s_window` instead `window`, avoid conflict with instrumentation tools\n let s_window; /* allocated sliding window, if wsize != 0 */\n let hold; /* local strm.hold */\n let bits; /* local strm.bits */\n let lcode; /* local strm.lencode */\n let dcode; /* local strm.distcode */\n let lmask; /* mask for first level of length codes */\n let dmask; /* mask for first level of distance codes */\n let here; /* retrieved table entry */\n let op; /* code bits, operation, extra bits, or */\n /* window position, window bytes to copy */\n let len; /* match length, unused bytes */\n let dist; /* match distance */\n let from; /* where to copy match from */\n let from_source;\n\n\n let input, output; // JS specific, because we have no pointers\n\n /* copy state to local variables */\n const state = strm.state;\n //here = state.here;\n _in = strm.next_in;\n input = strm.input;\n last = _in + (strm.avail_in - 5);\n _out = strm.next_out;\n output = strm.output;\n beg = _out - (start - strm.avail_out);\n end = _out + (strm.avail_out - 257);\n//#ifdef INFLATE_STRICT\n dmax = state.dmax;\n//#endif\n wsize = state.wsize;\n whave = state.whave;\n wnext = state.wnext;\n s_window = state.window;\n hold = state.hold;\n bits = state.bits;\n lcode = state.lencode;\n dcode = state.distcode;\n lmask = (1 << state.lenbits) - 1;\n dmask = (1 << state.distbits) - 1;\n\n\n /* decode literals and length/distances until end-of-block or not enough\n input data or output space */\n\n top:\n do {\n if (bits < 15) {\n hold += input[_in++] << bits;\n bits += 8;\n hold += input[_in++] << bits;\n bits += 8;\n }\n\n here = lcode[hold & lmask];\n\n dolen:\n for (;;) { // Goto emulation\n op = here >>> 24/*here.bits*/;\n hold >>>= op;\n bits -= op;\n op = (here >>> 16) & 0xff/*here.op*/;\n if (op === 0) { /* literal */\n //Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ?\n // \"inflate: literal '%c'\\n\" :\n // \"inflate: literal 0x%02x\\n\", here.val));\n output[_out++] = here & 0xffff/*here.val*/;\n }\n else if (op & 16) { /* length base */\n len = here & 0xffff/*here.val*/;\n op &= 15; /* number of extra bits */\n if (op) {\n if (bits < op) {\n hold += input[_in++] << bits;\n bits += 8;\n }\n len += hold & ((1 << op) - 1);\n hold >>>= op;\n bits -= op;\n }\n //Tracevv((stderr, \"inflate: length %u\\n\", len));\n if (bits < 15) {\n hold += input[_in++] << bits;\n bits += 8;\n hold += input[_in++] << bits;\n bits += 8;\n }\n here = dcode[hold & dmask];\n\n dodist:\n for (;;) { // goto emulation\n op = here >>> 24/*here.bits*/;\n hold >>>= op;\n bits -= op;\n op = (here >>> 16) & 0xff/*here.op*/;\n\n if (op & 16) { /* distance base */\n dist = here & 0xffff/*here.val*/;\n op &= 15; /* number of extra bits */\n if (bits < op) {\n hold += input[_in++] << bits;\n bits += 8;\n if (bits < op) {\n hold += input[_in++] << bits;\n bits += 8;\n }\n }\n dist += hold & ((1 << op) - 1);\n//#ifdef INFLATE_STRICT\n if (dist > dmax) {\n strm.msg = 'invalid distance too far back';\n state.mode = BAD$1;\n break top;\n }\n//#endif\n hold >>>= op;\n bits -= op;\n //Tracevv((stderr, \"inflate: distance %u\\n\", dist));\n op = _out - beg; /* max distance in output */\n if (dist > op) { /* see if copy from window */\n op = dist - op; /* distance back in window */\n if (op > whave) {\n if (state.sane) {\n strm.msg = 'invalid distance too far back';\n state.mode = BAD$1;\n break top;\n }\n\n// (!) This block is disabled in zlib defaults,\n// don't enable it for binary compatibility\n//#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR\n// if (len <= op - whave) {\n// do {\n// output[_out++] = 0;\n// } while (--len);\n// continue top;\n// }\n// len -= op - whave;\n// do {\n// output[_out++] = 0;\n// } while (--op > whave);\n// if (op === 0) {\n// from = _out - dist;\n// do {\n// output[_out++] = output[from++];\n// } while (--len);\n// continue top;\n// }\n//#endif\n }\n from = 0; // window index\n from_source = s_window;\n if (wnext === 0) { /* very common case */\n from += wsize - op;\n if (op < len) { /* some from window */\n len -= op;\n do {\n output[_out++] = s_window[from++];\n } while (--op);\n from = _out - dist; /* rest from output */\n from_source = output;\n }\n }\n else if (wnext < op) { /* wrap around window */\n from += wsize + wnext - op;\n op -= wnext;\n if (op < len) { /* some from end of window */\n len -= op;\n do {\n output[_out++] = s_window[from++];\n } while (--op);\n from = 0;\n if (wnext < len) { /* some from start of window */\n op = wnext;\n len -= op;\n do {\n output[_out++] = s_window[from++];\n } while (--op);\n from = _out - dist; /* rest from output */\n from_source = output;\n }\n }\n }\n else { /* contiguous in window */\n from += wnext - op;\n if (op < len) { /* some from window */\n len -= op;\n do {\n output[_out++] = s_window[from++];\n } while (--op);\n from = _out - dist; /* rest from output */\n from_source = output;\n }\n }\n while (len > 2) {\n output[_out++] = from_source[from++];\n output[_out++] = from_source[from++];\n output[_out++] = from_source[from++];\n len -= 3;\n }\n if (len) {\n output[_out++] = from_source[from++];\n if (len > 1) {\n output[_out++] = from_source[from++];\n }\n }\n }\n else {\n from = _out - dist; /* copy direct from output */\n do { /* minimum length is three */\n output[_out++] = output[from++];\n output[_out++] = output[from++];\n output[_out++] = output[from++];\n len -= 3;\n } while (len > 2);\n if (len) {\n output[_out++] = output[from++];\n if (len > 1) {\n output[_out++] = output[from++];\n }\n }\n }\n }\n else if ((op & 64) === 0) { /* 2nd level distance code */\n here = dcode[(here & 0xffff)/*here.val*/ + (hold & ((1 << op) - 1))];\n continue dodist;\n }\n else {\n strm.msg = 'invalid distance code';\n state.mode = BAD$1;\n break top;\n }\n\n break; // need to emulate goto via \"continue\"\n }\n }\n else if ((op & 64) === 0) { /* 2nd level length code */\n here = lcode[(here & 0xffff)/*here.val*/ + (hold & ((1 << op) - 1))];\n continue dolen;\n }\n else if (op & 32) { /* end-of-block */\n //Tracevv((stderr, \"inflate: end of block\\n\"));\n state.mode = TYPE$1;\n break top;\n }\n else {\n strm.msg = 'invalid literal/length code';\n state.mode = BAD$1;\n break top;\n }\n\n break; // need to emulate goto via \"continue\"\n }\n } while (_in < last && _out < end);\n\n /* return unused bytes (on entry, bits < 8, so in won't go too far back) */\n len = bits >> 3;\n _in -= len;\n bits -= len << 3;\n hold &= (1 << bits) - 1;\n\n /* update state and return */\n strm.next_in = _in;\n strm.next_out = _out;\n strm.avail_in = (_in < last ? 5 + (last - _in) : 5 - (_in - last));\n strm.avail_out = (_out < end ? 257 + (end - _out) : 257 - (_out - end));\n state.hold = hold;\n state.bits = bits;\n return;\n};\n\n// (C) 1995-2013 Jean-loup Gailly and Mark Adler\n// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin\n//\n// This software is provided 'as-is', without any express or implied\n// warranty. In no event will the authors be held liable for any damages\n// arising from the use of this software.\n//\n// Permission is granted to anyone to use this software for any purpose,\n// including commercial applications, and to alter it and redistribute it\n// freely, subject to the following restrictions:\n//\n// 1. The origin of this software must not be misrepresented; you must not\n// claim that you wrote the original software. If you use this software\n// in a product, an acknowledgment in the product documentation would be\n// appreciated but is not required.\n// 2. Altered source versions must be plainly marked as such, and must not be\n// misrepresented as being the original software.\n// 3. This notice may not be removed or altered from any source distribution.\n\nconst MAXBITS = 15;\nconst ENOUGH_LENS$1 = 852;\nconst ENOUGH_DISTS$1 = 592;\n//const ENOUGH = (ENOUGH_LENS+ENOUGH_DISTS);\n\nconst CODES$1 = 0;\nconst LENS$1 = 1;\nconst DISTS$1 = 2;\n\nconst lbase = new Uint16Array([ /* Length codes 257..285 base */\n 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,\n 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0\n]);\n\nconst lext = new Uint8Array([ /* Length codes 257..285 extra */\n 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18,\n 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 72, 78\n]);\n\nconst dbase = new Uint16Array([ /* Distance codes 0..29 base */\n 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,\n 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,\n 8193, 12289, 16385, 24577, 0, 0\n]);\n\nconst dext = new Uint8Array([ /* Distance codes 0..29 extra */\n 16, 16, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22,\n 23, 23, 24, 24, 25, 25, 26, 26, 27, 27,\n 28, 28, 29, 29, 64, 64\n]);\n\nconst inflate_table = (type, lens, lens_index, codes, table, table_index, work, opts) =>\n{\n const bits = opts.bits;\n //here = opts.here; /* table entry for duplication */\n\n let len = 0; /* a code's length in bits */\n let sym = 0; /* index of code symbols */\n let min = 0, max = 0; /* minimum and maximum code lengths */\n let root = 0; /* number of index bits for root table */\n let curr = 0; /* number of index bits for current table */\n let drop = 0; /* code bits to drop for sub-table */\n let left = 0; /* number of prefix codes available */\n let used = 0; /* code entries in table used */\n let huff = 0; /* Huffman code */\n let incr; /* for incrementing code, index */\n let fill; /* index for replicating entries */\n let low; /* low bits for current root entry */\n let mask; /* mask for low root bits */\n let next; /* next available space in table */\n let base = null; /* base value table to use */\n// let shoextra; /* extra bits table to use */\n let match; /* use base and extra for symbol >= match */\n const count = new Uint16Array(MAXBITS + 1); //[MAXBITS+1]; /* number of codes of each length */\n const offs = new Uint16Array(MAXBITS + 1); //[MAXBITS+1]; /* offsets in table for each length */\n let extra = null;\n\n let here_bits, here_op, here_val;\n\n /*\n Process a set of code lengths to create a canonical Huffman code. The\n code lengths are lens[0..codes-1]. Each length corresponds to the\n symbols 0..codes-1. The Huffman code is generated by first sorting the\n symbols by length from short to long, and retaining the symbol order\n for codes with equal lengths. Then the code starts with all zero bits\n for the first code of the shortest length, and the codes are integer\n increments for the same length, and zeros are appended as the length\n increases. For the deflate format, these bits are stored backwards\n from their more natural integer increment ordering, and so when the\n decoding tables are built in the large loop below, the integer codes\n are incremented backwards.\n\n This routine assumes, but does not check, that all of the entries in\n lens[] are in the range 0..MAXBITS. The caller must assure this.\n 1..MAXBITS is interpreted as that code length. zero means that that\n symbol does not occur in this code.\n\n The codes are sorted by computing a count of codes for each length,\n creating from that a table of starting indices for each length in the\n sorted table, and then entering the symbols in order in the sorted\n table. The sorted table is work[], with that space being provided by\n the caller.\n\n The length counts are used for other purposes as well, i.e. finding\n the minimum and maximum length codes, determining if there are any\n codes at all, checking for a valid set of lengths, and looking ahead\n at length counts to determine sub-table sizes when building the\n decoding tables.\n */\n\n /* accumulate lengths for codes (assumes lens[] all in 0..MAXBITS) */\n for (len = 0; len <= MAXBITS; len++) {\n count[len] = 0;\n }\n for (sym = 0; sym < codes; sym++) {\n count[lens[lens_index + sym]]++;\n }\n\n /* bound code lengths, force root to be within code lengths */\n root = bits;\n for (max = MAXBITS; max >= 1; max--) {\n if (count[max] !== 0) { break; }\n }\n if (root > max) {\n root = max;\n }\n if (max === 0) { /* no symbols to code at all */\n //table.op[opts.table_index] = 64; //here.op = (var char)64; /* invalid code marker */\n //table.bits[opts.table_index] = 1; //here.bits = (var char)1;\n //table.val[opts.table_index++] = 0; //here.val = (var short)0;\n table[table_index++] = (1 << 24) | (64 << 16) | 0;\n\n\n //table.op[opts.table_index] = 64;\n //table.bits[opts.table_index] = 1;\n //table.val[opts.table_index++] = 0;\n table[table_index++] = (1 << 24) | (64 << 16) | 0;\n\n opts.bits = 1;\n return 0; /* no symbols, but wait for decoding to report error */\n }\n for (min = 1; min < max; min++) {\n if (count[min] !== 0) { break; }\n }\n if (root < min) {\n root = min;\n }\n\n /* check for an over-subscribed or incomplete set of lengths */\n left = 1;\n for (len = 1; len <= MAXBITS; len++) {\n left <<= 1;\n left -= count[len];\n if (left < 0) {\n return -1;\n } /* over-subscribed */\n }\n if (left > 0 && (type === CODES$1 || max !== 1)) {\n return -1; /* incomplete set */\n }\n\n /* generate offsets into symbol table for each length for sorting */\n offs[1] = 0;\n for (len = 1; len < MAXBITS; len++) {\n offs[len + 1] = offs[len] + count[len];\n }\n\n /* sort symbols by length, by symbol order within each length */\n for (sym = 0; sym < codes; sym++) {\n if (lens[lens_index + sym] !== 0) {\n work[offs[lens[lens_index + sym]]++] = sym;\n }\n }\n\n /*\n Create and fill in decoding tables. In this loop, the table being\n filled is at next and has curr index bits. The code being used is huff\n with length len. That code is converted to an index by dropping drop\n bits off of the bottom. For codes where len is less than drop + curr,\n those top drop + curr - len bits are incremented through all values to\n fill the table with replicated entries.\n\n root is the number of index bits for the root table. When len exceeds\n root, sub-tables are created pointed to by the root entry with an index\n of the low root bits of huff. This is saved in low to check for when a\n new sub-table should be started. drop is zero when the root table is\n being filled, and drop is root when sub-tables are being filled.\n\n When a new sub-table is needed, it is necessary to look ahead in the\n code lengths to determine what size sub-table is needed. The length\n counts are used for this, and so count[] is decremented as codes are\n entered in the tables.\n\n used keeps track of how many table entries have been allocated from the\n provided *table space. It is checked for LENS and DIST tables against\n the constants ENOUGH_LENS and ENOUGH_DISTS to guard against changes in\n the initial root table size constants. See the comments in inftrees.h\n for more information.\n\n sym increments through all symbols, and the loop terminates when\n all codes of length max, i.e. all codes, have been processed. This\n routine permits incomplete codes, so another loop after this one fills\n in the rest of the decoding tables with invalid code markers.\n */\n\n /* set up for code type */\n // poor man optimization - use if-else instead of switch,\n // to avoid deopts in old v8\n if (type === CODES$1) {\n base = extra = work; /* dummy value--not used */\n match = 20;\n\n } else if (type === LENS$1) {\n base = lbase;\n extra = lext;\n match = 257;\n\n } else { /* DISTS */\n base = dbase;\n extra = dext;\n match = 0;\n }\n\n /* initialize opts for loop */\n huff = 0; /* starting code */\n sym = 0; /* starting code symbol */\n len = min; /* starting code length */\n next = table_index; /* current table to fill in */\n curr = root; /* current table index bits */\n drop = 0; /* current bits to drop from code for index */\n low = -1; /* trigger new sub-table when len > root */\n used = 1 << root; /* use root table entries */\n mask = used - 1; /* mask for comparing low */\n\n /* check available table space */\n if ((type === LENS$1 && used > ENOUGH_LENS$1) ||\n (type === DISTS$1 && used > ENOUGH_DISTS$1)) {\n return 1;\n }\n\n /* process all codes and make table entries */\n for (;;) {\n /* create table entry */\n here_bits = len - drop;\n if (work[sym] + 1 < match) {\n here_op = 0;\n here_val = work[sym];\n }\n else if (work[sym] >= match) {\n here_op = extra[work[sym] - match];\n here_val = base[work[sym] - match];\n }\n else {\n here_op = 32 + 64; /* end of block */\n here_val = 0;\n }\n\n /* replicate for those indices with low len bits equal to huff */\n incr = 1 << (len - drop);\n fill = 1 << curr;\n min = fill; /* save offset to next table */\n do {\n fill -= incr;\n table[next + (huff >> drop) + fill] = (here_bits << 24) | (here_op << 16) | here_val |0;\n } while (fill !== 0);\n\n /* backwards increment the len-bit code huff */\n incr = 1 << (len - 1);\n while (huff & incr) {\n incr >>= 1;\n }\n if (incr !== 0) {\n huff &= incr - 1;\n huff += incr;\n } else {\n huff = 0;\n }\n\n /* go to next symbol, update count, len */\n sym++;\n if (--count[len] === 0) {\n if (len === max) { break; }\n len = lens[lens_index + work[sym]];\n }\n\n /* create new sub-table if needed */\n if (len > root && (huff & mask) !== low) {\n /* if first time, transition to sub-tables */\n if (drop === 0) {\n drop = root;\n }\n\n /* increment past last table */\n next += min; /* here min is 1 << curr */\n\n /* determine length of next table */\n curr = len - drop;\n left = 1 << curr;\n while (curr + drop < max) {\n left -= count[curr + drop];\n if (left <= 0) { break; }\n curr++;\n left <<= 1;\n }\n\n /* check for enough space */\n used += 1 << curr;\n if ((type === LENS$1 && used > ENOUGH_LENS$1) ||\n (type === DISTS$1 && used > ENOUGH_DISTS$1)) {\n return 1;\n }\n\n /* point entry in root table to sub-table */\n low = huff & mask;\n /*table.op[low] = curr;\n table.bits[low] = root;\n table.val[low] = next - opts.table_index;*/\n table[low] = (root << 24) | (curr << 16) | (next - table_index) |0;\n }\n }\n\n /* fill in remaining table entry if code is incomplete (guaranteed to have\n at most one remaining entry, since if the code is incomplete, the\n maximum code length that was allowed to get this far is one bit) */\n if (huff !== 0) {\n //table.op[next + huff] = 64; /* invalid code marker */\n //table.bits[next + huff] = len - drop;\n //table.val[next + huff] = 0;\n table[next + huff] = ((len - drop) << 24) | (64 << 16) |0;\n }\n\n /* set return parameters */\n //opts.table_index += used;\n opts.bits = root;\n return 0;\n};\n\n\nvar inftrees = inflate_table;\n\n// (C) 1995-2013 Jean-loup Gailly and Mark Adler\n// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin\n//\n// This software is provided 'as-is', without any express or implied\n// warranty. In no event will the authors be held liable for any damages\n// arising from the use of this software.\n//\n// Permission is granted to anyone to use this software for any purpose,\n// including commercial applications, and to alter it and redistribute it\n// freely, subject to the following restrictions:\n//\n// 1. The origin of this software must not be misrepresented; you must not\n// claim that you wrote the original software. If you use this software\n// in a product, an acknowledgment in the product documentation would be\n// appreciated but is not required.\n// 2. Altered source versions must be plainly marked as such, and must not be\n// misrepresented as being the original software.\n// 3. This notice may not be removed or altered from any source distribution.\n\n\n\n\n\n\nconst CODES = 0;\nconst LENS = 1;\nconst DISTS = 2;\n\n/* Public constants ==========================================================*/\n/* ===========================================================================*/\n\nconst {\n Z_FINISH: Z_FINISH$1, Z_BLOCK, Z_TREES,\n Z_OK: Z_OK$1, Z_STREAM_END: Z_STREAM_END$1, Z_NEED_DICT: Z_NEED_DICT$1, Z_STREAM_ERROR: Z_STREAM_ERROR$1, Z_DATA_ERROR: Z_DATA_ERROR$1, Z_MEM_ERROR: Z_MEM_ERROR$1, Z_BUF_ERROR,\n Z_DEFLATED\n} = constants$2;\n\n\n/* STATES ====================================================================*/\n/* ===========================================================================*/\n\n\nconst HEAD = 16180; /* i: waiting for magic header */\nconst FLAGS = 16181; /* i: waiting for method and flags (gzip) */\nconst TIME = 16182; /* i: waiting for modification time (gzip) */\nconst OS = 16183; /* i: waiting for extra flags and operating system (gzip) */\nconst EXLEN = 16184; /* i: waiting for extra length (gzip) */\nconst EXTRA = 16185; /* i: waiting for extra bytes (gzip) */\nconst NAME = 16186; /* i: waiting for end of file name (gzip) */\nconst COMMENT = 16187; /* i: waiting for end of comment (gzip) */\nconst HCRC = 16188; /* i: waiting for header crc (gzip) */\nconst DICTID = 16189; /* i: waiting for dictionary check value */\nconst DICT = 16190; /* waiting for inflateSetDictionary() call */\nconst TYPE = 16191; /* i: waiting for type bits, including last-flag bit */\nconst TYPEDO = 16192; /* i: same, but skip check to exit inflate on new block */\nconst STORED = 16193; /* i: waiting for stored size (length and complement) */\nconst COPY_ = 16194; /* i/o: same as COPY below, but only first time in */\nconst COPY = 16195; /* i/o: waiting for input or output to copy stored block */\nconst TABLE = 16196; /* i: waiting for dynamic block table lengths */\nconst LENLENS = 16197; /* i: waiting for code length code lengths */\nconst CODELENS = 16198; /* i: waiting for length/lit and distance code lengths */\nconst LEN_ = 16199; /* i: same as LEN below, but only first time in */\nconst LEN = 16200; /* i: waiting for length/lit/eob code */\nconst LENEXT = 16201; /* i: waiting for length extra bits */\nconst DIST = 16202; /* i: waiting for distance code */\nconst DISTEXT = 16203; /* i: waiting for distance extra bits */\nconst MATCH = 16204; /* o: waiting for output space to copy string */\nconst LIT = 16205; /* o: waiting for output space to write literal */\nconst CHECK = 16206; /* i: waiting for 32-bit check value */\nconst LENGTH = 16207; /* i: waiting for 32-bit length (gzip) */\nconst DONE = 16208; /* finished check, done -- remain here until reset */\nconst BAD = 16209; /* got a data error -- remain here until reset */\nconst MEM = 16210; /* got an inflate() memory error -- remain here until reset */\nconst SYNC = 16211; /* looking for synchronization bytes to restart inflate() */\n\n/* ===========================================================================*/\n\n\n\nconst ENOUGH_LENS = 852;\nconst ENOUGH_DISTS = 592;\n//const ENOUGH = (ENOUGH_LENS+ENOUGH_DISTS);\n\nconst MAX_WBITS = 15;\n/* 32K LZ77 window */\nconst DEF_WBITS = MAX_WBITS;\n\n\nconst zswap32 = (q) => {\n\n return (((q >>> 24) & 0xff) +\n ((q >>> 8) & 0xff00) +\n ((q & 0xff00) << 8) +\n ((q & 0xff) << 24));\n};\n\n\nfunction InflateState() {\n this.strm = null; /* pointer back to this zlib stream */\n this.mode = 0; /* current inflate mode */\n this.last = false; /* true if processing last block */\n this.wrap = 0; /* bit 0 true for zlib, bit 1 true for gzip,\n bit 2 true to validate check value */\n this.havedict = false; /* true if dictionary provided */\n this.flags = 0; /* gzip header method and flags (0 if zlib), or\n -1 if raw or no header yet */\n this.dmax = 0; /* zlib header max distance (INFLATE_STRICT) */\n this.check = 0; /* protected copy of check value */\n this.total = 0; /* protected copy of output count */\n // TODO: may be {}\n this.head = null; /* where to save gzip header information */\n\n /* sliding window */\n this.wbits = 0; /* log base 2 of requested window size */\n this.wsize = 0; /* window size or zero if not using window */\n this.whave = 0; /* valid bytes in the window */\n this.wnext = 0; /* window write index */\n this.window = null; /* allocated sliding window, if needed */\n\n /* bit accumulator */\n this.hold = 0; /* input bit accumulator */\n this.bits = 0; /* number of bits in \"in\" */\n\n /* for string and stored block copying */\n this.length = 0; /* literal or length of data to copy */\n this.offset = 0; /* distance back to copy string from */\n\n /* for table and code decoding */\n this.extra = 0; /* extra bits needed */\n\n /* fixed and dynamic code tables */\n this.lencode = null; /* starting table for length/literal codes */\n this.distcode = null; /* starting table for distance codes */\n this.lenbits = 0; /* index bits for lencode */\n this.distbits = 0; /* index bits for distcode */\n\n /* dynamic table building */\n this.ncode = 0; /* number of code length code lengths */\n this.nlen = 0; /* number of length code lengths */\n this.ndist = 0; /* number of distance code lengths */\n this.have = 0; /* number of code lengths in lens[] */\n this.next = null; /* next available space in codes[] */\n\n this.lens = new Uint16Array(320); /* temporary storage for code lengths */\n this.work = new Uint16Array(288); /* work area for code table building */\n\n /*\n because we don't have pointers in js, we use lencode and distcode directly\n as buffers so we don't need codes\n */\n //this.codes = new Int32Array(ENOUGH); /* space for code tables */\n this.lendyn = null; /* dynamic table for length/literal codes (JS specific) */\n this.distdyn = null; /* dynamic table for distance codes (JS specific) */\n this.sane = 0; /* if false, allow invalid distance too far */\n this.back = 0; /* bits back of last unprocessed length/lit */\n this.was = 0; /* initial length of match */\n}\n\n\nconst inflateStateCheck = (strm) => {\n\n if (!strm) {\n return 1;\n }\n const state = strm.state;\n if (!state || state.strm !== strm ||\n state.mode < HEAD || state.mode > SYNC) {\n return 1;\n }\n return 0;\n};\n\n\nconst inflateResetKeep = (strm) => {\n\n if (inflateStateCheck(strm)) { return Z_STREAM_ERROR$1; }\n const state = strm.state;\n strm.total_in = strm.total_out = state.total = 0;\n strm.msg = ''; /*Z_NULL*/\n if (state.wrap) { /* to support ill-conceived Java test suite */\n strm.adler = state.wrap & 1;\n }\n state.mode = HEAD;\n state.last = 0;\n state.havedict = 0;\n state.flags = -1;\n state.dmax = 32768;\n state.head = null/*Z_NULL*/;\n state.hold = 0;\n state.bits = 0;\n //state.lencode = state.distcode = state.next = state.codes;\n state.lencode = state.lendyn = new Int32Array(ENOUGH_LENS);\n state.distcode = state.distdyn = new Int32Array(ENOUGH_DISTS);\n\n state.sane = 1;\n state.back = -1;\n //Tracev((stderr, \"inflate: reset\\n\"));\n return Z_OK$1;\n};\n\n\nconst inflateReset = (strm) => {\n\n if (inflateStateCheck(strm)) { return Z_STREAM_ERROR$1; }\n const state = strm.state;\n state.wsize = 0;\n state.whave = 0;\n state.wnext = 0;\n return inflateResetKeep(strm);\n\n};\n\n\nconst inflateReset2 = (strm, windowBits) => {\n let wrap;\n\n /* get the state */\n if (inflateStateCheck(strm)) { return Z_STREAM_ERROR$1; }\n const state = strm.state;\n\n /* extract wrap request from windowBits parameter */\n if (windowBits < 0) {\n wrap = 0;\n windowBits = -windowBits;\n }\n else {\n wrap = (windowBits >> 4) + 5;\n if (windowBits < 48) {\n windowBits &= 15;\n }\n }\n\n /* set number of window bits, free window if different */\n if (windowBits && (windowBits < 8 || windowBits > 15)) {\n return Z_STREAM_ERROR$1;\n }\n if (state.window !== null && state.wbits !== windowBits) {\n state.window = null;\n }\n\n /* update state and reset the rest of it */\n state.wrap = wrap;\n state.wbits = windowBits;\n return inflateReset(strm);\n};\n\n\nconst inflateInit2 = (strm, windowBits) => {\n\n if (!strm) { return Z_STREAM_ERROR$1; }\n //strm.msg = Z_NULL; /* in case we return an error */\n\n const state = new InflateState();\n\n //if (state === Z_NULL) return Z_MEM_ERROR;\n //Tracev((stderr, \"inflate: allocated\\n\"));\n strm.state = state;\n state.strm = strm;\n state.window = null/*Z_NULL*/;\n state.mode = HEAD; /* to pass state test in inflateReset2() */\n const ret = inflateReset2(strm, windowBits);\n if (ret !== Z_OK$1) {\n strm.state = null/*Z_NULL*/;\n }\n return ret;\n};\n\n\nconst inflateInit = (strm) => {\n\n return inflateInit2(strm, DEF_WBITS);\n};\n\n\n/*\n Return state with length and distance decoding tables and index sizes set to\n fixed code decoding. Normally this returns fixed tables from inffixed.h.\n If BUILDFIXED is defined, then instead this routine builds the tables the\n first time it's called, and returns those tables the first time and\n thereafter. This reduces the size of the code by about 2K bytes, in\n exchange for a little execution time. However, BUILDFIXED should not be\n used for threaded applications, since the rewriting of the tables and virgin\n may not be thread-safe.\n */\nlet virgin = true;\n\nlet lenfix, distfix; // We have no pointers in JS, so keep tables separate\n\n\nconst fixedtables = (state) => {\n\n /* build fixed huffman tables if first call (may not be thread safe) */\n if (virgin) {\n lenfix = new Int32Array(512);\n distfix = new Int32Array(32);\n\n /* literal/length table */\n let sym = 0;\n while (sym < 144) { state.lens[sym++] = 8; }\n while (sym < 256) { state.lens[sym++] = 9; }\n while (sym < 280) { state.lens[sym++] = 7; }\n while (sym < 288) { state.lens[sym++] = 8; }\n\n inftrees(LENS, state.lens, 0, 288, lenfix, 0, state.work, { bits: 9 });\n\n /* distance table */\n sym = 0;\n while (sym < 32) { state.lens[sym++] = 5; }\n\n inftrees(DISTS, state.lens, 0, 32, distfix, 0, state.work, { bits: 5 });\n\n /* do this just once */\n virgin = false;\n }\n\n state.lencode = lenfix;\n state.lenbits = 9;\n state.distcode = distfix;\n state.distbits = 5;\n};\n\n\n/*\n Update the window with the last wsize (normally 32K) bytes written before\n returning. If window does not exist yet, create it. This is only called\n when a window is already in use, or when output has been written during this\n inflate call, but the end of the deflate stream has not been reached yet.\n It is also called to create a window for dictionary data when a dictionary\n is loaded.\n\n Providing output buffers larger than 32K to inflate() should provide a speed\n advantage, since only the last 32K of output is copied to the sliding window\n upon return from inflate(), and since all distances after the first 32K of\n output will fall in the output data, making match copies simpler and faster.\n The advantage may be dependent on the size of the processor's data caches.\n */\nconst updatewindow = (strm, src, end, copy) => {\n\n let dist;\n const state = strm.state;\n\n /* if it hasn't been done already, allocate space for the window */\n if (state.window === null) {\n state.wsize = 1 << state.wbits;\n state.wnext = 0;\n state.whave = 0;\n\n state.window = new Uint8Array(state.wsize);\n }\n\n /* copy state->wsize or less output bytes into the circular window */\n if (copy >= state.wsize) {\n state.window.set(src.subarray(end - state.wsize, end), 0);\n state.wnext = 0;\n state.whave = state.wsize;\n }\n else {\n dist = state.wsize - state.wnext;\n if (dist > copy) {\n dist = copy;\n }\n //zmemcpy(state->window + state->wnext, end - copy, dist);\n state.window.set(src.subarray(end - copy, end - copy + dist), state.wnext);\n copy -= dist;\n if (copy) {\n //zmemcpy(state->window, end - copy, copy);\n state.window.set(src.subarray(end - copy, end), 0);\n state.wnext = copy;\n state.whave = state.wsize;\n }\n else {\n state.wnext += dist;\n if (state.wnext === state.wsize) { state.wnext = 0; }\n if (state.whave < state.wsize) { state.whave += dist; }\n }\n }\n return 0;\n};\n\n\nconst inflate$2 = (strm, flush) => {\n\n let state;\n let input, output; // input/output buffers\n let next; /* next input INDEX */\n let put; /* next output INDEX */\n let have, left; /* available input and output */\n let hold; /* bit buffer */\n let bits; /* bits in bit buffer */\n let _in, _out; /* save starting available input and output */\n let copy; /* number of stored or match bytes to copy */\n let from; /* where to copy match bytes from */\n let from_source;\n let here = 0; /* current decoding table entry */\n let here_bits, here_op, here_val; // paked \"here\" denormalized (JS specific)\n //let last; /* parent table entry */\n let last_bits, last_op, last_val; // paked \"last\" denormalized (JS specific)\n let len; /* length to copy for repeats, bits to drop */\n let ret; /* return code */\n const hbuf = new Uint8Array(4); /* buffer for gzip header crc calculation */\n let opts;\n\n let n; // temporary variable for NEED_BITS\n\n const order = /* permutation of code lengths */\n new Uint8Array([ 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 ]);\n\n\n if (inflateStateCheck(strm) || !strm.output ||\n (!strm.input && strm.avail_in !== 0)) {\n return Z_STREAM_ERROR$1;\n }\n\n state = strm.state;\n if (state.mode === TYPE) { state.mode = TYPEDO; } /* skip check */\n\n\n //--- LOAD() ---\n put = strm.next_out;\n output = strm.output;\n left = strm.avail_out;\n next = strm.next_in;\n input = strm.input;\n have = strm.avail_in;\n hold = state.hold;\n bits = state.bits;\n //---\n\n _in = have;\n _out = left;\n ret = Z_OK$1;\n\n inf_leave: // goto emulation\n for (;;) {\n switch (state.mode) {\n case HEAD:\n if (state.wrap === 0) {\n state.mode = TYPEDO;\n break;\n }\n //=== NEEDBITS(16);\n while (bits < 16) {\n if (have === 0) { break inf_leave; }\n have--;\n hold += input[next++] << bits;\n bits += 8;\n }\n //===//\n if ((state.wrap & 2) && hold === 0x8b1f) { /* gzip header */\n if (state.wbits === 0) {\n state.wbits = 15;\n }\n state.check = 0/*crc32(0L, Z_NULL, 0)*/;\n //=== CRC2(state.check, hold);\n hbuf[0] = hold & 0xff;\n hbuf[1] = (hold >>> 8) & 0xff;\n state.check = crc32_1(state.check, hbuf, 2, 0);\n //===//\n\n //=== INITBITS();\n hold = 0;\n bits = 0;\n //===//\n state.mode = FLAGS;\n break;\n }\n if (state.head) {\n state.head.done = false;\n }\n if (!(state.wrap & 1) || /* check if zlib header allowed */\n (((hold & 0xff)/*BITS(8)*/ << 8) + (hold >> 8)) % 31) {\n strm.msg = 'incorrect header check';\n state.mode = BAD;\n break;\n }\n if ((hold & 0x0f)/*BITS(4)*/ !== Z_DEFLATED) {\n strm.msg = 'unknown compression method';\n state.mode = BAD;\n break;\n }\n //--- DROPBITS(4) ---//\n hold >>>= 4;\n bits -= 4;\n //---//\n len = (hold & 0x0f)/*BITS(4)*/ + 8;\n if (state.wbits === 0) {\n state.wbits = len;\n }\n if (len > 15 || len > state.wbits) {\n strm.msg = 'invalid window size';\n state.mode = BAD;\n break;\n }\n\n // !!! pako patch. Force use `options.windowBits` if passed.\n // Required to always use max window size by default.\n state.dmax = 1 << state.wbits;\n //state.dmax = 1 << len;\n\n state.flags = 0; /* indicate zlib header */\n //Tracev((stderr, \"inflate: zlib header ok\\n\"));\n strm.adler = state.check = 1/*adler32(0L, Z_NULL, 0)*/;\n state.mode = hold & 0x200 ? DICTID : TYPE;\n //=== INITBITS();\n hold = 0;\n bits = 0;\n //===//\n break;\n case FLAGS:\n //=== NEEDBITS(16); */\n while (bits < 16) {\n if (have === 0) { break inf_leave; }\n have--;\n hold += input[next++] << bits;\n bits += 8;\n }\n //===//\n state.flags = hold;\n if ((state.flags & 0xff) !== Z_DEFLATED) {\n strm.msg = 'unknown compression method';\n state.mode = BAD;\n break;\n }\n if (state.flags & 0xe000) {\n strm.msg = 'unknown header flags set';\n state.mode = BAD;\n break;\n }\n if (state.head) {\n state.head.text = ((hold >> 8) & 1);\n }\n if ((state.flags & 0x0200) && (state.wrap & 4)) {\n //=== CRC2(state.check, hold);\n hbuf[0] = hold & 0xff;\n hbuf[1] = (hold >>> 8) & 0xff;\n state.check = crc32_1(state.check, hbuf, 2, 0);\n //===//\n }\n //=== INITBITS();\n hold = 0;\n bits = 0;\n //===//\n state.mode = TIME;\n /* falls through */\n case TIME:\n //=== NEEDBITS(32); */\n while (bits < 32) {\n if (have === 0) { break inf_leave; }\n have--;\n hold += input[next++] << bits;\n bits += 8;\n }\n //===//\n if (state.head) {\n state.head.time = hold;\n }\n if ((state.flags & 0x0200) && (state.wrap & 4)) {\n //=== CRC4(state.check, hold)\n hbuf[0] = hold & 0xff;\n hbuf[1] = (hold >>> 8) & 0xff;\n hbuf[2] = (hold >>> 16) & 0xff;\n hbuf[3] = (hold >>> 24) & 0xff;\n state.check = crc32_1(state.check, hbuf, 4, 0);\n //===\n }\n //=== INITBITS();\n hold = 0;\n bits = 0;\n //===//\n state.mode = OS;\n /* falls through */\n case OS:\n //=== NEEDBITS(16); */\n while (bits < 16) {\n if (have === 0) { break inf_leave; }\n have--;\n hold += input[next++] << bits;\n bits += 8;\n }\n //===//\n if (state.head) {\n state.head.xflags = (hold & 0xff);\n state.head.os = (hold >> 8);\n }\n if ((state.flags & 0x0200) && (state.wrap & 4)) {\n //=== CRC2(state.check, hold);\n hbuf[0] = hold & 0xff;\n hbuf[1] = (hold >>> 8) & 0xff;\n state.check = crc32_1(state.check, hbuf, 2, 0);\n //===//\n }\n //=== INITBITS();\n hold = 0;\n bits = 0;\n //===//\n state.mode = EXLEN;\n /* falls through */\n case EXLEN:\n if (state.flags & 0x0400) {\n //=== NEEDBITS(16); */\n while (bits < 16) {\n if (have === 0) { break inf_leave; }\n have--;\n hold += input[next++] << bits;\n bits += 8;\n }\n //===//\n state.length = hold;\n if (state.head) {\n state.head.extra_len = hold;\n }\n if ((state.flags & 0x0200) && (state.wrap & 4)) {\n //=== CRC2(state.check, hold);\n hbuf[0] = hold & 0xff;\n hbuf[1] = (hold >>> 8) & 0xff;\n state.check = crc32_1(state.check, hbuf, 2, 0);\n //===//\n }\n //=== INITBITS();\n hold = 0;\n bits = 0;\n //===//\n }\n else if (state.head) {\n state.head.extra = null/*Z_NULL*/;\n }\n state.mode = EXTRA;\n /* falls through */\n case EXTRA:\n if (state.flags & 0x0400) {\n copy = state.length;\n if (copy > have) { copy = have; }\n if (copy) {\n if (state.head) {\n len = state.head.extra_len - state.length;\n if (!state.head.extra) {\n // Use untyped array for more convenient processing later\n state.head.extra = new Uint8Array(state.head.extra_len);\n }\n state.head.extra.set(\n input.subarray(\n next,\n // extra field is limited to 65536 bytes\n // - no need for additional size check\n next + copy\n ),\n /*len + copy > state.head.extra_max - len ? state.head.extra_max : copy,*/\n len\n );\n //zmemcpy(state.head.extra + len, next,\n // len + copy > state.head.extra_max ?\n // state.head.extra_max - len : copy);\n }\n if ((state.flags & 0x0200) && (state.wrap & 4)) {\n state.check = crc32_1(state.check, input, copy, next);\n }\n have -= copy;\n next += copy;\n state.length -= copy;\n }\n if (state.length) { break inf_leave; }\n }\n state.length = 0;\n state.mode = NAME;\n /* falls through */\n case NAME:\n if (state.flags & 0x0800) {\n if (have === 0) { break inf_leave; }\n copy = 0;\n do {\n // TODO: 2 or 1 bytes?\n len = input[next + copy++];\n /* use constant limit because in js we should not preallocate memory */\n if (state.head && len &&\n (state.length < 65536 /*state.head.name_max*/)) {\n state.head.name += String.fromCharCode(len);\n }\n } while (len && copy < have);\n\n if ((state.flags & 0x0200) && (state.wrap & 4)) {\n state.check = crc32_1(state.check, input, copy, next);\n }\n have -= copy;\n next += copy;\n if (len) { break inf_leave; }\n }\n else if (state.head) {\n state.head.name = null;\n }\n state.length = 0;\n state.mode = COMMENT;\n /* falls through */\n case COMMENT:\n if (state.flags & 0x1000) {\n if (have === 0) { break inf_leave; }\n copy = 0;\n do {\n len = input[next + copy++];\n /* use constant limit because in js we should not preallocate memory */\n if (state.head && len &&\n (state.length < 65536 /*state.head.comm_max*/)) {\n state.head.comment += String.fromCharCode(len);\n }\n } while (len && copy < have);\n if ((state.flags & 0x0200) && (state.wrap & 4)) {\n state.check = crc32_1(state.check, input, copy, next);\n }\n have -= copy;\n next += copy;\n if (len) { break inf_leave; }\n }\n else if (state.head) {\n state.head.comment = null;\n }\n state.mode = HCRC;\n /* falls through */\n case HCRC:\n if (state.flags & 0x0200) {\n //=== NEEDBITS(16); */\n while (bits < 16) {\n if (have === 0) { break inf_leave; }\n have--;\n hold += input[next++] << bits;\n bits += 8;\n }\n //===//\n if ((state.wrap & 4) && hold !== (state.check & 0xffff)) {\n strm.msg = 'header crc mismatch';\n state.mode = BAD;\n break;\n }\n //=== INITBITS();\n hold = 0;\n bits = 0;\n //===//\n }\n if (state.head) {\n state.head.hcrc = ((state.flags >> 9) & 1);\n state.head.done = true;\n }\n strm.adler = state.check = 0;\n state.mode = TYPE;\n break;\n case DICTID:\n //=== NEEDBITS(32); */\n while (bits < 32) {\n if (have === 0) { break inf_leave; }\n have--;\n hold += input[next++] << bits;\n bits += 8;\n }\n //===//\n strm.adler = state.check = zswap32(hold);\n //=== INITBITS();\n hold = 0;\n bits = 0;\n //===//\n state.mode = DICT;\n /* falls through */\n case DICT:\n if (state.havedict === 0) {\n //--- RESTORE() ---\n strm.next_out = put;\n strm.avail_out = left;\n strm.next_in = next;\n strm.avail_in = have;\n state.hold = hold;\n state.bits = bits;\n //---\n return Z_NEED_DICT$1;\n }\n strm.adler = state.check = 1/*adler32(0L, Z_NULL, 0)*/;\n state.mode = TYPE;\n /* falls through */\n case TYPE:\n if (flush === Z_BLOCK || flush === Z_TREES) { break inf_leave; }\n /* falls through */\n case TYPEDO:\n if (state.last) {\n //--- BYTEBITS() ---//\n hold >>>= bits & 7;\n bits -= bits & 7;\n //---//\n state.mode = CHECK;\n break;\n }\n //=== NEEDBITS(3); */\n while (bits < 3) {\n if (have === 0) { break inf_leave; }\n have--;\n hold += input[next++] << bits;\n bits += 8;\n }\n //===//\n state.last = (hold & 0x01)/*BITS(1)*/;\n //--- DROPBITS(1) ---//\n hold >>>= 1;\n bits -= 1;\n //---//\n\n switch ((hold & 0x03)/*BITS(2)*/) {\n case 0: /* stored block */\n //Tracev((stderr, \"inflate: stored block%s\\n\",\n // state.last ? \" (last)\" : \"\"));\n state.mode = STORED;\n break;\n case 1: /* fixed block */\n fixedtables(state);\n //Tracev((stderr, \"inflate: fixed codes block%s\\n\",\n // state.last ? \" (last)\" : \"\"));\n state.mode = LEN_; /* decode codes */\n if (flush === Z_TREES) {\n //--- DROPBITS(2) ---//\n hold >>>= 2;\n bits -= 2;\n //---//\n break inf_leave;\n }\n break;\n case 2: /* dynamic block */\n //Tracev((stderr, \"inflate: dynamic codes block%s\\n\",\n // state.last ? \" (last)\" : \"\"));\n state.mode = TABLE;\n break;\n case 3:\n strm.msg = 'invalid block type';\n state.mode = BAD;\n }\n //--- DROPBITS(2) ---//\n hold >>>= 2;\n bits -= 2;\n //---//\n break;\n case STORED:\n //--- BYTEBITS() ---// /* go to byte boundary */\n hold >>>= bits & 7;\n bits -= bits & 7;\n //---//\n //=== NEEDBITS(32); */\n while (bits < 32) {\n if (have === 0) { break inf_leave; }\n have--;\n hold += input[next++] << bits;\n bits += 8;\n }\n //===//\n if ((hold & 0xffff) !== ((hold >>> 16) ^ 0xffff)) {\n strm.msg = 'invalid stored block lengths';\n state.mode = BAD;\n break;\n }\n state.length = hold & 0xffff;\n //Tracev((stderr, \"inflate: stored length %u\\n\",\n // state.length));\n //=== INITBITS();\n hold = 0;\n bits = 0;\n //===//\n state.mode = COPY_;\n if (flush === Z_TREES) { break inf_leave; }\n /* falls through */\n case COPY_:\n state.mode = COPY;\n /* falls through */\n case COPY:\n copy = state.length;\n if (copy) {\n if (copy > have) { copy = have; }\n if (copy > left) { copy = left; }\n if (copy === 0) { break inf_leave; }\n //--- zmemcpy(put, next, copy); ---\n output.set(input.subarray(next, next + copy), put);\n //---//\n have -= copy;\n next += copy;\n left -= copy;\n put += copy;\n state.length -= copy;\n break;\n }\n //Tracev((stderr, \"inflate: stored end\\n\"));\n state.mode = TYPE;\n break;\n case TABLE:\n //=== NEEDBITS(14); */\n while (bits < 14) {\n if (have === 0) { break inf_leave; }\n have--;\n hold += input[next++] << bits;\n bits += 8;\n }\n //===//\n state.nlen = (hold & 0x1f)/*BITS(5)*/ + 257;\n //--- DROPBITS(5) ---//\n hold >>>= 5;\n bits -= 5;\n //---//\n state.ndist = (hold & 0x1f)/*BITS(5)*/ + 1;\n //--- DROPBITS(5) ---//\n hold >>>= 5;\n bits -= 5;\n //---//\n state.ncode = (hold & 0x0f)/*BITS(4)*/ + 4;\n //--- DROPBITS(4) ---//\n hold >>>= 4;\n bits -= 4;\n //---//\n//#ifndef PKZIP_BUG_WORKAROUND\n if (state.nlen > 286 || state.ndist > 30) {\n strm.msg = 'too many length or distance symbols';\n state.mode = BAD;\n break;\n }\n//#endif\n //Tracev((stderr, \"inflate: table sizes ok\\n\"));\n state.have = 0;\n state.mode = LENLENS;\n /* falls through */\n case LENLENS:\n while (state.have < state.ncode) {\n //=== NEEDBITS(3);\n while (bits < 3) {\n if (have === 0) { break inf_leave; }\n have--;\n hold += input[next++] << bits;\n bits += 8;\n }\n //===//\n state.lens[order[state.have++]] = (hold & 0x07);//BITS(3);\n //--- DROPBITS(3) ---//\n hold >>>= 3;\n bits -= 3;\n //---//\n }\n while (state.have < 19) {\n state.lens[order[state.have++]] = 0;\n }\n // We have separate tables & no pointers. 2 commented lines below not needed.\n //state.next = state.codes;\n //state.lencode = state.next;\n // Switch to use dynamic table\n state.lencode = state.lendyn;\n state.lenbits = 7;\n\n opts = { bits: state.lenbits };\n ret = inftrees(CODES, state.lens, 0, 19, state.lencode, 0, state.work, opts);\n state.lenbits = opts.bits;\n\n if (ret) {\n strm.msg = 'invalid code lengths set';\n state.mode = BAD;\n break;\n }\n //Tracev((stderr, \"inflate: code lengths ok\\n\"));\n state.have = 0;\n state.mode = CODELENS;\n /* falls through */\n case CODELENS:\n while (state.have < state.nlen + state.ndist) {\n for (;;) {\n here = state.lencode[hold & ((1 << state.lenbits) - 1)];/*BITS(state.lenbits)*/\n here_bits = here >>> 24;\n here_op = (here >>> 16) & 0xff;\n here_val = here & 0xffff;\n\n if ((here_bits) <= bits) { break; }\n //--- PULLBYTE() ---//\n if (have === 0) { break inf_leave; }\n have--;\n hold += input[next++] << bits;\n bits += 8;\n //---//\n }\n if (here_val < 16) {\n //--- DROPBITS(here.bits) ---//\n hold >>>= here_bits;\n bits -= here_bits;\n //---//\n state.lens[state.have++] = here_val;\n }\n else {\n if (here_val === 16) {\n //=== NEEDBITS(here.bits + 2);\n n = here_bits + 2;\n while (bits < n) {\n if (have === 0) { break inf_leave; }\n have--;\n hold += input[next++] << bits;\n bits += 8;\n }\n //===//\n //--- DROPBITS(here.bits) ---//\n hold >>>= here_bits;\n bits -= here_bits;\n //---//\n if (state.have === 0) {\n strm.msg = 'invalid bit length repeat';\n state.mode = BAD;\n break;\n }\n len = state.lens[state.have - 1];\n copy = 3 + (hold & 0x03);//BITS(2);\n //--- DROPBITS(2) ---//\n hold >>>= 2;\n bits -= 2;\n //---//\n }\n else if (here_val === 17) {\n //=== NEEDBITS(here.bits + 3);\n n = here_bits + 3;\n while (bits < n) {\n if (have === 0) { break inf_leave; }\n have--;\n hold += input[next++] << bits;\n bits += 8;\n }\n //===//\n //--- DROPBITS(here.bits) ---//\n hold >>>= here_bits;\n bits -= here_bits;\n //---//\n len = 0;\n copy = 3 + (hold & 0x07);//BITS(3);\n //--- DROPBITS(3) ---//\n hold >>>= 3;\n bits -= 3;\n //---//\n }\n else {\n //=== NEEDBITS(here.bits + 7);\n n = here_bits + 7;\n while (bits < n) {\n if (have === 0) { break inf_leave; }\n have--;\n hold += input[next++] << bits;\n bits += 8;\n }\n //===//\n //--- DROPBITS(here.bits) ---//\n hold >>>= here_bits;\n bits -= here_bits;\n //---//\n len = 0;\n copy = 11 + (hold & 0x7f);//BITS(7);\n //--- DROPBITS(7) ---//\n hold >>>= 7;\n bits -= 7;\n //---//\n }\n if (state.have + copy > state.nlen + state.ndist) {\n strm.msg = 'invalid bit length repeat';\n state.mode = BAD;\n break;\n }\n while (copy--) {\n state.lens[state.have++] = len;\n }\n }\n }\n\n /* handle error breaks in while */\n if (state.mode === BAD) { break; }\n\n /* check for end-of-block code (better have one) */\n if (state.lens[256] === 0) {\n strm.msg = 'invalid code -- missing end-of-block';\n state.mode = BAD;\n break;\n }\n\n /* build code tables -- note: do not change the lenbits or distbits\n values here (9 and 6) without reading the comments in inftrees.h\n concerning the ENOUGH constants, which depend on those values */\n state.lenbits = 9;\n\n opts = { bits: state.lenbits };\n ret = inftrees(LENS, state.lens, 0, state.nlen, state.lencode, 0, state.work, opts);\n // We have separate tables & no pointers. 2 commented lines below not needed.\n // state.next_index = opts.table_index;\n state.lenbits = opts.bits;\n // state.lencode = state.next;\n\n if (ret) {\n strm.msg = 'invalid literal/lengths set';\n state.mode = BAD;\n break;\n }\n\n state.distbits = 6;\n //state.distcode.copy(state.codes);\n // Switch to use dynamic table\n state.distcode = state.distdyn;\n opts = { bits: state.distbits };\n ret = inftrees(DISTS, state.lens, state.nlen, state.ndist, state.distcode, 0, state.work, opts);\n // We have separate tables & no pointers. 2 commented lines below not needed.\n // state.next_index = opts.table_index;\n state.distbits = opts.bits;\n // state.distcode = state.next;\n\n if (ret) {\n strm.msg = 'invalid distances set';\n state.mode = BAD;\n break;\n }\n //Tracev((stderr, 'inflate: codes ok\\n'));\n state.mode = LEN_;\n if (flush === Z_TREES) { break inf_leave; }\n /* falls through */\n case LEN_:\n state.mode = LEN;\n /* falls through */\n case LEN:\n if (have >= 6 && left >= 258) {\n //--- RESTORE() ---\n strm.next_out = put;\n strm.avail_out = left;\n strm.next_in = next;\n strm.avail_in = have;\n state.hold = hold;\n state.bits = bits;\n //---\n inffast(strm, _out);\n //--- LOAD() ---\n put = strm.next_out;\n output = strm.output;\n left = strm.avail_out;\n next = strm.next_in;\n input = strm.input;\n have = strm.avail_in;\n hold = state.hold;\n bits = state.bits;\n //---\n\n if (state.mode === TYPE) {\n state.back = -1;\n }\n break;\n }\n state.back = 0;\n for (;;) {\n here = state.lencode[hold & ((1 << state.lenbits) - 1)]; /*BITS(state.lenbits)*/\n here_bits = here >>> 24;\n here_op = (here >>> 16) & 0xff;\n here_val = here & 0xffff;\n\n if (here_bits <= bits) { break; }\n //--- PULLBYTE() ---//\n if (have === 0) { break inf_leave; }\n have--;\n hold += input[next++] << bits;\n bits += 8;\n //---//\n }\n if (here_op && (here_op & 0xf0) === 0) {\n last_bits = here_bits;\n last_op = here_op;\n last_val = here_val;\n for (;;) {\n here = state.lencode[last_val +\n ((hold & ((1 << (last_bits + last_op)) - 1))/*BITS(last.bits + last.op)*/ >> last_bits)];\n here_bits = here >>> 24;\n here_op = (here >>> 16) & 0xff;\n here_val = here & 0xffff;\n\n if ((last_bits + here_bits) <= bits) { break; }\n //--- PULLBYTE() ---//\n if (have === 0) { break inf_leave; }\n have--;\n hold += input[next++] << bits;\n bits += 8;\n //---//\n }\n //--- DROPBITS(last.bits) ---//\n hold >>>= last_bits;\n bits -= last_bits;\n //---//\n state.back += last_bits;\n }\n //--- DROPBITS(here.bits) ---//\n hold >>>= here_bits;\n bits -= here_bits;\n //---//\n state.back += here_bits;\n state.length = here_val;\n if (here_op === 0) {\n //Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ?\n // \"inflate: literal '%c'\\n\" :\n // \"inflate: literal 0x%02x\\n\", here.val));\n state.mode = LIT;\n break;\n }\n if (here_op & 32) {\n //Tracevv((stderr, \"inflate: end of block\\n\"));\n state.back = -1;\n state.mode = TYPE;\n break;\n }\n if (here_op & 64) {\n strm.msg = 'invalid literal/length code';\n state.mode = BAD;\n break;\n }\n state.extra = here_op & 15;\n state.mode = LENEXT;\n /* falls through */\n case LENEXT:\n if (state.extra) {\n //=== NEEDBITS(state.extra);\n n = state.extra;\n while (bits < n) {\n if (have === 0) { break inf_leave; }\n have--;\n hold += input[next++] << bits;\n bits += 8;\n }\n //===//\n state.length += hold & ((1 << state.extra) - 1)/*BITS(state.extra)*/;\n //--- DROPBITS(state.extra) ---//\n hold >>>= state.extra;\n bits -= state.extra;\n //---//\n state.back += state.extra;\n }\n //Tracevv((stderr, \"inflate: length %u\\n\", state.length));\n state.was = state.length;\n state.mode = DIST;\n /* falls through */\n case DIST:\n for (;;) {\n here = state.distcode[hold & ((1 << state.distbits) - 1)];/*BITS(state.distbits)*/\n here_bits = here >>> 24;\n here_op = (here >>> 16) & 0xff;\n here_val = here & 0xffff;\n\n if ((here_bits) <= bits) { break; }\n //--- PULLBYTE() ---//\n if (have === 0) { break inf_leave; }\n have--;\n hold += input[next++] << bits;\n bits += 8;\n //---//\n }\n if ((here_op & 0xf0) === 0) {\n last_bits = here_bits;\n last_op = here_op;\n last_val = here_val;\n for (;;) {\n here = state.distcode[last_val +\n ((hold & ((1 << (last_bits + last_op)) - 1))/*BITS(last.bits + last.op)*/ >> last_bits)];\n here_bits = here >>> 24;\n here_op = (here >>> 16) & 0xff;\n here_val = here & 0xffff;\n\n if ((last_bits + here_bits) <= bits) { break; }\n //--- PULLBYTE() ---//\n if (have === 0) { break inf_leave; }\n have--;\n hold += input[next++] << bits;\n bits += 8;\n //---//\n }\n //--- DROPBITS(last.bits) ---//\n hold >>>= last_bits;\n bits -= last_bits;\n //---//\n state.back += last_bits;\n }\n //--- DROPBITS(here.bits) ---//\n hold >>>= here_bits;\n bits -= here_bits;\n //---//\n state.back += here_bits;\n if (here_op & 64) {\n strm.msg = 'invalid distance code';\n state.mode = BAD;\n break;\n }\n state.offset = here_val;\n state.extra = (here_op) & 15;\n state.mode = DISTEXT;\n /* falls through */\n case DISTEXT:\n if (state.extra) {\n //=== NEEDBITS(state.extra);\n n = state.extra;\n while (bits < n) {\n if (have === 0) { break inf_leave; }\n have--;\n hold += input[next++] << bits;\n bits += 8;\n }\n //===//\n state.offset += hold & ((1 << state.extra) - 1)/*BITS(state.extra)*/;\n //--- DROPBITS(state.extra) ---//\n hold >>>= state.extra;\n bits -= state.extra;\n //---//\n state.back += state.extra;\n }\n//#ifdef INFLATE_STRICT\n if (state.offset > state.dmax) {\n strm.msg = 'invalid distance too far back';\n state.mode = BAD;\n break;\n }\n//#endif\n //Tracevv((stderr, \"inflate: distance %u\\n\", state.offset));\n state.mode = MATCH;\n /* falls through */\n case MATCH:\n if (left === 0) { break inf_leave; }\n copy = _out - left;\n if (state.offset > copy) { /* copy from window */\n copy = state.offset - copy;\n if (copy > state.whave) {\n if (state.sane) {\n strm.msg = 'invalid distance too far back';\n state.mode = BAD;\n break;\n }\n// (!) This block is disabled in zlib defaults,\n// don't enable it for binary compatibility\n//#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR\n// Trace((stderr, \"inflate.c too far\\n\"));\n// copy -= state.whave;\n// if (copy > state.length) { copy = state.length; }\n// if (copy > left) { copy = left; }\n// left -= copy;\n// state.length -= copy;\n// do {\n// output[put++] = 0;\n// } while (--copy);\n// if (state.length === 0) { state.mode = LEN; }\n// break;\n//#endif\n }\n if (copy > state.wnext) {\n copy -= state.wnext;\n from = state.wsize - copy;\n }\n else {\n from = state.wnext - copy;\n }\n if (copy > state.length) { copy = state.length; }\n from_source = state.window;\n }\n else { /* copy from output */\n from_source = output;\n from = put - state.offset;\n copy = state.length;\n }\n if (copy > left) { copy = left; }\n left -= copy;\n state.length -= copy;\n do {\n output[put++] = from_source[from++];\n } while (--copy);\n if (state.length === 0) { state.mode = LEN; }\n break;\n case LIT:\n if (left === 0) { break inf_leave; }\n output[put++] = state.length;\n left--;\n state.mode = LEN;\n break;\n case CHECK:\n if (state.wrap) {\n //=== NEEDBITS(32);\n while (bits < 32) {\n if (have === 0) { break inf_leave; }\n have--;\n // Use '|' instead of '+' to make sure that result is signed\n hold |= input[next++] << bits;\n bits += 8;\n }\n //===//\n _out -= left;\n strm.total_out += _out;\n state.total += _out;\n if ((state.wrap & 4) && _out) {\n strm.adler = state.check =\n /*UPDATE_CHECK(state.check, put - _out, _out);*/\n (state.flags ? crc32_1(state.check, output, _out, put - _out) : adler32_1(state.check, output, _out, put - _out));\n\n }\n _out = left;\n // NB: crc32 stored as signed 32-bit int, zswap32 returns signed too\n if ((state.wrap & 4) && (state.flags ? hold : zswap32(hold)) !== state.check) {\n strm.msg = 'incorrect data check';\n state.mode = BAD;\n break;\n }\n //=== INITBITS();\n hold = 0;\n bits = 0;\n //===//\n //Tracev((stderr, \"inflate: check matches trailer\\n\"));\n }\n state.mode = LENGTH;\n /* falls through */\n case LENGTH:\n if (state.wrap && state.flags) {\n //=== NEEDBITS(32);\n while (bits < 32) {\n if (have === 0) { break inf_leave; }\n have--;\n hold += input[next++] << bits;\n bits += 8;\n }\n //===//\n if ((state.wrap & 4) && hold !== (state.total & 0xffffffff)) {\n strm.msg = 'incorrect length check';\n state.mode = BAD;\n break;\n }\n //=== INITBITS();\n hold = 0;\n bits = 0;\n //===//\n //Tracev((stderr, \"inflate: length matches trailer\\n\"));\n }\n state.mode = DONE;\n /* falls through */\n case DONE:\n ret = Z_STREAM_END$1;\n break inf_leave;\n case BAD:\n ret = Z_DATA_ERROR$1;\n break inf_leave;\n case MEM:\n return Z_MEM_ERROR$1;\n case SYNC:\n /* falls through */\n default:\n return Z_STREAM_ERROR$1;\n }\n }\n\n // inf_leave <- here is real place for \"goto inf_leave\", emulated via \"break inf_leave\"\n\n /*\n Return from inflate(), updating the total counts and the check value.\n If there was no progress during the inflate() call, return a buffer\n error. Call updatewindow() to create and/or update the window state.\n Note: a memory error from inflate() is non-recoverable.\n */\n\n //--- RESTORE() ---\n strm.next_out = put;\n strm.avail_out = left;\n strm.next_in = next;\n strm.avail_in = have;\n state.hold = hold;\n state.bits = bits;\n //---\n\n if (state.wsize || (_out !== strm.avail_out && state.mode < BAD &&\n (state.mode < CHECK || flush !== Z_FINISH$1))) {\n if (updatewindow(strm, strm.output, strm.next_out, _out - strm.avail_out)) ;\n }\n _in -= strm.avail_in;\n _out -= strm.avail_out;\n strm.total_in += _in;\n strm.total_out += _out;\n state.total += _out;\n if ((state.wrap & 4) && _out) {\n strm.adler = state.check = /*UPDATE_CHECK(state.check, strm.next_out - _out, _out);*/\n (state.flags ? crc32_1(state.check, output, _out, strm.next_out - _out) : adler32_1(state.check, output, _out, strm.next_out - _out));\n }\n strm.data_type = state.bits + (state.last ? 64 : 0) +\n (state.mode === TYPE ? 128 : 0) +\n (state.mode === LEN_ || state.mode === COPY_ ? 256 : 0);\n if (((_in === 0 && _out === 0) || flush === Z_FINISH$1) && ret === Z_OK$1) {\n ret = Z_BUF_ERROR;\n }\n return ret;\n};\n\n\nconst inflateEnd = (strm) => {\n\n if (inflateStateCheck(strm)) {\n return Z_STREAM_ERROR$1;\n }\n\n let state = strm.state;\n if (state.window) {\n state.window = null;\n }\n strm.state = null;\n return Z_OK$1;\n};\n\n\nconst inflateGetHeader = (strm, head) => {\n\n /* check state */\n if (inflateStateCheck(strm)) { return Z_STREAM_ERROR$1; }\n const state = strm.state;\n if ((state.wrap & 2) === 0) { return Z_STREAM_ERROR$1; }\n\n /* save header structure */\n state.head = head;\n head.done = false;\n return Z_OK$1;\n};\n\n\nconst inflateSetDictionary = (strm, dictionary) => {\n const dictLength = dictionary.length;\n\n let state;\n let dictid;\n let ret;\n\n /* check state */\n if (inflateStateCheck(strm)) { return Z_STREAM_ERROR$1; }\n state = strm.state;\n\n if (state.wrap !== 0 && state.mode !== DICT) {\n return Z_STREAM_ERROR$1;\n }\n\n /* check for correct dictionary identifier */\n if (state.mode === DICT) {\n dictid = 1; /* adler32(0, null, 0)*/\n /* dictid = adler32(dictid, dictionary, dictLength); */\n dictid = adler32_1(dictid, dictionary, dictLength, 0);\n if (dictid !== state.check) {\n return Z_DATA_ERROR$1;\n }\n }\n /* copy dictionary to window using updatewindow(), which will amend the\n existing dictionary if appropriate */\n ret = updatewindow(strm, dictionary, dictLength, dictLength);\n if (ret) {\n state.mode = MEM;\n return Z_MEM_ERROR$1;\n }\n state.havedict = 1;\n // Tracev((stderr, \"inflate: dictionary set\\n\"));\n return Z_OK$1;\n};\n\n\nvar inflateReset_1 = inflateReset;\nvar inflateReset2_1 = inflateReset2;\nvar inflateResetKeep_1 = inflateResetKeep;\nvar inflateInit_1 = inflateInit;\nvar inflateInit2_1 = inflateInit2;\nvar inflate_2$1 = inflate$2;\nvar inflateEnd_1 = inflateEnd;\nvar inflateGetHeader_1 = inflateGetHeader;\nvar inflateSetDictionary_1 = inflateSetDictionary;\nvar inflateInfo = 'pako inflate (from Nodeca project)';\n\n/* Not implemented\nmodule.exports.inflateCodesUsed = inflateCodesUsed;\nmodule.exports.inflateCopy = inflateCopy;\nmodule.exports.inflateGetDictionary = inflateGetDictionary;\nmodule.exports.inflateMark = inflateMark;\nmodule.exports.inflatePrime = inflatePrime;\nmodule.exports.inflateSync = inflateSync;\nmodule.exports.inflateSyncPoint = inflateSyncPoint;\nmodule.exports.inflateUndermine = inflateUndermine;\nmodule.exports.inflateValidate = inflateValidate;\n*/\n\nvar inflate_1$2 = {\n\tinflateReset: inflateReset_1,\n\tinflateReset2: inflateReset2_1,\n\tinflateResetKeep: inflateResetKeep_1,\n\tinflateInit: inflateInit_1,\n\tinflateInit2: inflateInit2_1,\n\tinflate: inflate_2$1,\n\tinflateEnd: inflateEnd_1,\n\tinflateGetHeader: inflateGetHeader_1,\n\tinflateSetDictionary: inflateSetDictionary_1,\n\tinflateInfo: inflateInfo\n};\n\n// (C) 1995-2013 Jean-loup Gailly and Mark Adler\n// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin\n//\n// This software is provided 'as-is', without any express or implied\n// warranty. In no event will the authors be held liable for any damages\n// arising from the use of this software.\n//\n// Permission is granted to anyone to use this software for any purpose,\n// including commercial applications, and to alter it and redistribute it\n// freely, subject to the following restrictions:\n//\n// 1. The origin of this software must not be misrepresented; you must not\n// claim that you wrote the original software. If you use this software\n// in a product, an acknowledgment in the product documentation would be\n// appreciated but is not required.\n// 2. Altered source versions must be plainly marked as such, and must not be\n// misrepresented as being the original software.\n// 3. This notice may not be removed or altered from any source distribution.\n\nfunction GZheader() {\n /* true if compressed data believed to be text */\n this.text = 0;\n /* modification time */\n this.time = 0;\n /* extra flags (not used when writing a gzip file) */\n this.xflags = 0;\n /* operating system */\n this.os = 0;\n /* pointer to extra field or Z_NULL if none */\n this.extra = null;\n /* extra field length (valid if extra != Z_NULL) */\n this.extra_len = 0; // Actually, we don't need it in JS,\n // but leave for few code modifications\n\n //\n // Setup limits is not necessary because in js we should not preallocate memory\n // for inflate use constant limit in 65536 bytes\n //\n\n /* space at extra (only when reading header) */\n // this.extra_max = 0;\n /* pointer to zero-terminated file name or Z_NULL */\n this.name = '';\n /* space at name (only when reading header) */\n // this.name_max = 0;\n /* pointer to zero-terminated comment or Z_NULL */\n this.comment = '';\n /* space at comment (only when reading header) */\n // this.comm_max = 0;\n /* true if there was or will be a header crc */\n this.hcrc = 0;\n /* true when done reading gzip header (not used when writing a gzip file) */\n this.done = false;\n}\n\nvar gzheader = GZheader;\n\nconst toString = Object.prototype.toString;\n\n/* Public constants ==========================================================*/\n/* ===========================================================================*/\n\nconst {\n Z_NO_FLUSH, Z_FINISH,\n Z_OK, Z_STREAM_END, Z_NEED_DICT, Z_STREAM_ERROR, Z_DATA_ERROR, Z_MEM_ERROR\n} = constants$2;\n\n/* ===========================================================================*/\n\n\n/**\n * class Inflate\n *\n * Generic JS-style wrapper for zlib calls. If you don't need\n * streaming behaviour - use more simple functions: [[inflate]]\n * and [[inflateRaw]].\n **/\n\n/* internal\n * inflate.chunks -> Array\n *\n * Chunks of output data, if [[Inflate#onData]] not overridden.\n **/\n\n/**\n * Inflate.result -> Uint8Array|String\n *\n * Uncompressed result, generated by default [[Inflate#onData]]\n * and [[Inflate#onEnd]] handlers. Filled after you push last chunk\n * (call [[Inflate#push]] with `Z_FINISH` / `true` param).\n **/\n\n/**\n * Inflate.err -> Number\n *\n * Error code after inflate finished. 0 (Z_OK) on success.\n * Should be checked if broken data possible.\n **/\n\n/**\n * Inflate.msg -> String\n *\n * Error message, if [[Inflate.err]] != 0\n **/\n\n\n/**\n * new Inflate(options)\n * - options (Object): zlib inflate options.\n *\n * Creates new inflator instance with specified params. Throws exception\n * on bad params. Supported options:\n *\n * - `windowBits`\n * - `dictionary`\n *\n * [http://zlib.net/manual.html#Advanced](http://zlib.net/manual.html#Advanced)\n * for more information on these.\n *\n * Additional options, for internal needs:\n *\n * - `chunkSize` - size of generated data chunks (16K by default)\n * - `raw` (Boolean) - do raw inflate\n * - `to` (String) - if equal to 'string', then result will be converted\n * from utf8 to utf16 (javascript) string. When string output requested,\n * chunk length can differ from `chunkSize`, depending on content.\n *\n * By default, when no options set, autodetect deflate/gzip data format via\n * wrapper header.\n *\n * ##### Example:\n *\n * ```javascript\n * const pako = require('pako')\n * const chunk1 = new Uint8Array([1,2,3,4,5,6,7,8,9])\n * const chunk2 = new Uint8Array([10,11,12,13,14,15,16,17,18,19]);\n *\n * const inflate = new pako.Inflate({ level: 3});\n *\n * inflate.push(chunk1, false);\n * inflate.push(chunk2, true); // true -> last chunk\n *\n * if (inflate.err) { throw new Error(inflate.err); }\n *\n * console.log(inflate.result);\n * ```\n **/\nfunction Inflate$1(options) {\n this.options = common.assign({\n chunkSize: 1024 * 64,\n windowBits: 15,\n to: ''\n }, options || {});\n\n const opt = this.options;\n\n // Force window size for `raw` data, if not set directly,\n // because we have no header for autodetect.\n if (opt.raw && (opt.windowBits >= 0) && (opt.windowBits < 16)) {\n opt.windowBits = -opt.windowBits;\n if (opt.windowBits === 0) { opt.windowBits = -15; }\n }\n\n // If `windowBits` not defined (and mode not raw) - set autodetect flag for gzip/deflate\n if ((opt.windowBits >= 0) && (opt.windowBits < 16) &&\n !(options && options.windowBits)) {\n opt.windowBits += 32;\n }\n\n // Gzip header has no info about windows size, we can do autodetect only\n // for deflate. So, if window size not set, force it to max when gzip possible\n if ((opt.windowBits > 15) && (opt.windowBits < 48)) {\n // bit 3 (16) -> gzipped data\n // bit 4 (32) -> autodetect gzip/deflate\n if ((opt.windowBits & 15) === 0) {\n opt.windowBits |= 15;\n }\n }\n\n this.err = 0; // error code, if happens (0 = Z_OK)\n this.msg = ''; // error message\n this.ended = false; // used to avoid multiple onEnd() calls\n this.chunks = []; // chunks of compressed data\n\n this.strm = new zstream();\n this.strm.avail_out = 0;\n\n let status = inflate_1$2.inflateInit2(\n this.strm,\n opt.windowBits\n );\n\n if (status !== Z_OK) {\n throw new Error(messages[status]);\n }\n\n this.header = new gzheader();\n\n inflate_1$2.inflateGetHeader(this.strm, this.header);\n\n // Setup dictionary\n if (opt.dictionary) {\n // Convert data if needed\n if (typeof opt.dictionary === 'string') {\n opt.dictionary = strings.string2buf(opt.dictionary);\n } else if (toString.call(opt.dictionary) === '[object ArrayBuffer]') {\n opt.dictionary = new Uint8Array(opt.dictionary);\n }\n if (opt.raw) { //In raw mode we need to set the dictionary early\n status = inflate_1$2.inflateSetDictionary(this.strm, opt.dictionary);\n if (status !== Z_OK) {\n throw new Error(messages[status]);\n }\n }\n }\n}\n\n/**\n * Inflate#push(data[, flush_mode]) -> Boolean\n * - data (Uint8Array|ArrayBuffer): input data\n * - flush_mode (Number|Boolean): 0..6 for corresponding Z_NO_FLUSH..Z_TREE\n * flush modes. See constants. Skipped or `false` means Z_NO_FLUSH,\n * `true` means Z_FINISH.\n *\n * Sends input data to inflate pipe, generating [[Inflate#onData]] calls with\n * new output chunks. Returns `true` on success. If end of stream detected,\n * [[Inflate#onEnd]] will be called.\n *\n * `flush_mode` is not needed for normal operation, because end of stream\n * detected automatically. You may try to use it for advanced things, but\n * this functionality was not tested.\n *\n * On fail call [[Inflate#onEnd]] with error code and return false.\n *\n * ##### Example\n *\n * ```javascript\n * push(chunk, false); // push one of data chunks\n * ...\n * push(chunk, true); // push last chunk\n * ```\n **/\nInflate$1.prototype.push = function (data, flush_mode) {\n const strm = this.strm;\n const chunkSize = this.options.chunkSize;\n const dictionary = this.options.dictionary;\n let status, _flush_mode, last_avail_out;\n\n if (this.ended) return false;\n\n if (flush_mode === ~~flush_mode) _flush_mode = flush_mode;\n else _flush_mode = flush_mode === true ? Z_FINISH : Z_NO_FLUSH;\n\n // Convert data if needed\n if (toString.call(data) === '[object ArrayBuffer]') {\n strm.input = new Uint8Array(data);\n } else {\n strm.input = data;\n }\n\n strm.next_in = 0;\n strm.avail_in = strm.input.length;\n\n for (;;) {\n if (strm.avail_out === 0) {\n strm.output = new Uint8Array(chunkSize);\n strm.next_out = 0;\n strm.avail_out = chunkSize;\n }\n\n status = inflate_1$2.inflate(strm, _flush_mode);\n\n if (status === Z_NEED_DICT && dictionary) {\n status = inflate_1$2.inflateSetDictionary(strm, dictionary);\n\n if (status === Z_OK) {\n status = inflate_1$2.inflate(strm, _flush_mode);\n } else if (status === Z_DATA_ERROR) {\n // Replace code with more verbose\n status = Z_NEED_DICT;\n }\n }\n\n // Skip snyc markers if more data follows and not raw mode\n while (strm.avail_in > 0 &&\n status === Z_STREAM_END &&\n strm.state.wrap > 0 &&\n data[strm.next_in] !== 0)\n {\n inflate_1$2.inflateReset(strm);\n status = inflate_1$2.inflate(strm, _flush_mode);\n }\n\n switch (status) {\n case Z_STREAM_ERROR:\n case Z_DATA_ERROR:\n case Z_NEED_DICT:\n case Z_MEM_ERROR:\n this.onEnd(status);\n this.ended = true;\n return false;\n }\n\n // Remember real `avail_out` value, because we may patch out buffer content\n // to align utf8 strings boundaries.\n last_avail_out = strm.avail_out;\n\n if (strm.next_out) {\n if (strm.avail_out === 0 || status === Z_STREAM_END) {\n\n if (this.options.to === 'string') {\n\n let next_out_utf8 = strings.utf8border(strm.output, strm.next_out);\n\n let tail = strm.next_out - next_out_utf8;\n let utf8str = strings.buf2string(strm.output, next_out_utf8);\n\n // move tail & realign counters\n strm.next_out = tail;\n strm.avail_out = chunkSize - tail;\n if (tail) strm.output.set(strm.output.subarray(next_out_utf8, next_out_utf8 + tail), 0);\n\n this.onData(utf8str);\n\n } else {\n this.onData(strm.output.length === strm.next_out ? strm.output : strm.output.subarray(0, strm.next_out));\n }\n }\n }\n\n // Must repeat iteration if out buffer is full\n if (status === Z_OK && last_avail_out === 0) continue;\n\n // Finalize if end of stream reached.\n if (status === Z_STREAM_END) {\n status = inflate_1$2.inflateEnd(this.strm);\n this.onEnd(status);\n this.ended = true;\n return true;\n }\n\n if (strm.avail_in === 0) break;\n }\n\n return true;\n};\n\n\n/**\n * Inflate#onData(chunk) -> Void\n * - chunk (Uint8Array|String): output data. When string output requested,\n * each chunk will be string.\n *\n * By default, stores data blocks in `chunks[]` property and glue\n * those in `onEnd`. Override this handler, if you need another behaviour.\n **/\nInflate$1.prototype.onData = function (chunk) {\n this.chunks.push(chunk);\n};\n\n\n/**\n * Inflate#onEnd(status) -> Void\n * - status (Number): inflate status. 0 (Z_OK) on success,\n * other if not.\n *\n * Called either after you tell inflate that the input stream is\n * complete (Z_FINISH). By default - join collected chunks,\n * free memory and fill `results` / `err` properties.\n **/\nInflate$1.prototype.onEnd = function (status) {\n // On success - join\n if (status === Z_OK) {\n if (this.options.to === 'string') {\n this.result = this.chunks.join('');\n } else {\n this.result = common.flattenChunks(this.chunks);\n }\n }\n this.chunks = [];\n this.err = status;\n this.msg = this.strm.msg;\n};\n\n\n/**\n * inflate(data[, options]) -> Uint8Array|String\n * - data (Uint8Array|ArrayBuffer): input data to decompress.\n * - options (Object): zlib inflate options.\n *\n * Decompress `data` with inflate/ungzip and `options`. Autodetect\n * format via wrapper header by default. That's why we don't provide\n * separate `ungzip` method.\n *\n * Supported options are:\n *\n * - windowBits\n *\n * [http://zlib.net/manual.html#Advanced](http://zlib.net/manual.html#Advanced)\n * for more information.\n *\n * Sugar (options):\n *\n * - `raw` (Boolean) - say that we work with raw stream, if you don't wish to specify\n * negative windowBits implicitly.\n * - `to` (String) - if equal to 'string', then result will be converted\n * from utf8 to utf16 (javascript) string. When string output requested,\n * chunk length can differ from `chunkSize`, depending on content.\n *\n *\n * ##### Example:\n *\n * ```javascript\n * const pako = require('pako');\n * const input = pako.deflate(new Uint8Array([1,2,3,4,5,6,7,8,9]));\n * let output;\n *\n * try {\n * output = pako.inflate(input);\n * } catch (err) {\n * console.log(err);\n * }\n * ```\n **/\nfunction inflate$1(input, options) {\n const inflator = new Inflate$1(options);\n\n inflator.push(input);\n\n // That will never happens, if you don't cheat with options :)\n if (inflator.err) throw inflator.msg || messages[inflator.err];\n\n return inflator.result;\n}\n\n\n/**\n * inflateRaw(data[, options]) -> Uint8Array|String\n * - data (Uint8Array|ArrayBuffer): input data to decompress.\n * - options (Object): zlib inflate options.\n *\n * The same as [[inflate]], but creates raw data, without wrapper\n * (header and adler32 crc).\n **/\nfunction inflateRaw$1(input, options) {\n options = options || {};\n options.raw = true;\n return inflate$1(input, options);\n}\n\n\n/**\n * ungzip(data[, options]) -> Uint8Array|String\n * - data (Uint8Array|ArrayBuffer): input data to decompress.\n * - options (Object): zlib inflate options.\n *\n * Just shortcut to [[inflate]], because it autodetects format\n * by header.content. Done for convenience.\n **/\n\n\nvar Inflate_1$1 = Inflate$1;\nvar inflate_2 = inflate$1;\nvar inflateRaw_1$1 = inflateRaw$1;\nvar ungzip$1 = inflate$1;\nvar constants = constants$2;\n\nvar inflate_1$1 = {\n\tInflate: Inflate_1$1,\n\tinflate: inflate_2,\n\tinflateRaw: inflateRaw_1$1,\n\tungzip: ungzip$1,\n\tconstants: constants\n};\n\nconst { Deflate, deflate, deflateRaw, gzip } = deflate_1$1;\n\nconst { Inflate, inflate, inflateRaw, ungzip } = inflate_1$1;\n\n\n\nvar Deflate_1 = Deflate;\nvar deflate_1 = deflate;\nvar deflateRaw_1 = deflateRaw;\nvar gzip_1 = gzip;\nvar Inflate_1 = Inflate;\nvar inflate_1 = inflate;\nvar inflateRaw_1 = inflateRaw;\nvar ungzip_1 = ungzip;\nvar constants_1 = constants$2;\n\nvar pako = {\n\tDeflate: Deflate_1,\n\tdeflate: deflate_1,\n\tdeflateRaw: deflateRaw_1,\n\tgzip: gzip_1,\n\tInflate: Inflate_1,\n\tinflate: inflate_1,\n\tinflateRaw: inflateRaw_1,\n\tungzip: ungzip_1,\n\tconstants: constants_1\n};\n\nexport { Deflate_1 as Deflate, Inflate_1 as Inflate, constants_1 as constants, pako as default, deflate_1 as deflate, deflateRaw_1 as deflateRaw, gzip_1 as gzip, inflate_1 as inflate, inflateRaw_1 as inflateRaw, ungzip_1 as ungzip };\n", "/**\n * COSE-based QR Code Compression and Encryption\n * Implements secure payload packing with CBOR, compression, and chunking\n */\n\nimport * as cbor from 'cbor-js';\nimport * as pako from 'pako';\nimport * as base64 from 'base64-js';\n\n// Base64URL encoding/decoding helpers\nfunction toBase64Url(uint8) {\n let b64 = base64.fromByteArray(uint8);\n return b64.replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=+$/, '');\n}\n\nfunction fromBase64Url(str) {\n str = str.replace(/-/g, '+').replace(/_/g, '/');\n while (str.length % 4) str += '=';\n return base64.toByteArray(str);\n}\n\n// Generate UUID for chunking\nfunction generateUUID() {\n return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, c => {\n const r = Math.random() * 16 | 0;\n const v = c === 'x' ? r : (r & 0x3 | 0x8);\n return v.toString(16);\n });\n}\n\n/**\n * Pack secure payload using COSE-like structure with compression\n * @param {Object} payloadObj - The data to pack\n * @param {CryptoKey} senderEcdsaPrivKey - Sender's signing key (optional)\n * @param {CryptoKey} recipientEcdhPubKey - Recipient's ECDH key (optional, null for broadcast)\n * @returns {Array} Array of QR code strings (chunks)\n */\nexport async function packSecurePayload(payloadObj, senderEcdsaPrivKey = null, recipientEcdhPubKey = null) {\n try {\n console.log('\uD83D\uDD10 Starting COSE packing...');\n \n // 1. Canonicalize payload (minified JSON)\n const payloadJson = JSON.stringify(payloadObj);\n console.log(`\uD83D\uDCCA Original payload size: ${payloadJson.length} characters`);\n \n // 2. Create ephemeral ECDH keypair (P-384) for encryption\n let ciphertextCose;\n let ephemeralRaw = null;\n \n if (recipientEcdhPubKey) {\n console.log('\uD83D\uDD10 Encrypting for specific recipient...');\n \n // Generate ephemeral ECDH keypair\n const ecdhPair = await crypto.subtle.generateKey(\n { name: \"ECDH\", namedCurve: \"P-384\" },\n true,\n [\"deriveKey\", \"deriveBits\"]\n );\n \n // Export ephemeral public key as raw bytes\n ephemeralRaw = new Uint8Array(await crypto.subtle.exportKey('raw', ecdhPair.publicKey));\n \n // Derive shared secret\n const sharedBits = await crypto.subtle.deriveBits(\n { name: \"ECDH\", public: recipientEcdhPubKey },\n ecdhPair.privateKey,\n 384\n );\n \n // HKDF-SHA384: derive AES-256-GCM key\n const hkdfKey = await crypto.subtle.importKey('raw', sharedBits, 'HKDF', false, ['deriveKey']);\n const cek = await crypto.subtle.deriveKey(\n {\n name: 'HKDF',\n hash: 'SHA-384',\n salt: new Uint8Array(0),\n info: new TextEncoder().encode('SecureBit QR ECDH AES key')\n },\n hkdfKey,\n { name: 'AES-GCM', length: 256 },\n true,\n ['encrypt', 'decrypt']\n );\n \n // AES-GCM encrypt payload\n const iv = crypto.getRandomValues(new Uint8Array(12));\n const enc = await crypto.subtle.encrypt(\n { name: 'AES-GCM', iv },\n cek,\n new TextEncoder().encode(payloadJson)\n );\n \n // Build COSE_Encrypt-like structure\n ciphertextCose = {\n protected: { alg: 'A256GCM' },\n unprotected: { epk: ephemeralRaw },\n ciphertext: new Uint8Array(enc),\n iv: iv\n };\n } else {\n console.log('\uD83D\uDD10 Using broadcast mode (no encryption)...');\n // Broadcast mode: not encrypted, include ephemeral key for future use\n ephemeralRaw = crypto.getRandomValues(new Uint8Array(97)); // P-384 uncompressed point size\n ciphertextCose = {\n plaintext: new TextEncoder().encode(payloadJson),\n epk: ephemeralRaw\n };\n }\n \n // 3. Wrap in COSE_Sign1 structure (sign if key provided)\n let coseSign1;\n const toSign = cbor.encode(ciphertextCose);\n \n if (senderEcdsaPrivKey) {\n console.log('\uD83D\uDD10 Signing payload...');\n // Sign using ECDSA P-384 SHA-384\n const signature = new Uint8Array(await crypto.subtle.sign(\n { name: 'ECDSA', hash: 'SHA-384' },\n senderEcdsaPrivKey,\n toSign\n ));\n \n // COSE_Sign1 as array: [protected, unprotected, payload, signature]\n const protectedHeader = cbor.encode({ alg: 'ES384' });\n const unprotectedHeader = { kid: 'securebit-sender' };\n coseSign1 = [protectedHeader, unprotectedHeader, toSign, signature];\n } else {\n console.log('\uD83D\uDD10 No signing key provided, using unsigned structure...');\n // COSE_Sign1 as array: [protected, unprotected, payload, signature]\n const protectedHeader = cbor.encode({ alg: 'none' });\n const unprotectedHeader = {};\n coseSign1 = [protectedHeader, unprotectedHeader, toSign, new Uint8Array(0)];\n }\n \n // 4. Final encode: CBOR -> deflate -> base64url\n const cborFinal = cbor.encode(coseSign1);\n const compressed = pako.deflate(cborFinal);\n const encoded = toBase64Url(compressed);\n \n console.log(`\uD83D\uDCCA Compressed size: ${encoded.length} characters (${Math.round((1 - encoded.length/payloadJson.length) * 100)}% reduction)`);\n \n // 5. Chunking for QR codes - \u0443\u043B\u0443\u0447\u0448\u0435\u043D\u043D\u043E\u0435 \u0440\u0430\u0437\u0431\u0438\u0435\u043D\u0438\u0435 \u0434\u043B\u044F \u043B\u0443\u0447\u0448\u0435\u0433\u043E \u0441\u043A\u0430\u043D\u0438\u0440\u043E\u0432\u0430\u043D\u0438\u044F\n const TARGET_CHUNKS = 10; // \u0426\u0435\u043B\u0435\u0432\u043E\u0435 \u043A\u043E\u043B\u0438\u0447\u0435\u0441\u0442\u0432\u043E \u0447\u0430\u0441\u0442\u0435\u0439\n const QR_MAX = Math.max(200, Math.floor(encoded.length / TARGET_CHUNKS)); // \u0414\u0438\u043D\u0430\u043C\u0438\u0447\u0435\u0441\u043A\u0438\u0439 \u0440\u0430\u0437\u043C\u0435\u0440 \u0447\u0430\u0441\u0442\u0438\n const chunks = [];\n \n if (encoded.length <= QR_MAX) {\n // Single chunk\n chunks.push(JSON.stringify({\n hdr: { v: 1, id: generateUUID(), seq: 1, total: 1 },\n body: encoded\n }));\n } else {\n // Multiple chunks - \u0440\u0430\u0437\u0431\u0438\u0432\u0430\u0435\u043C \u043D\u0430 \u0431\u043E\u043B\u044C\u0448\u0435 \u0447\u0430\u0441\u0442\u0435\u0439 \u0434\u043B\u044F \u043B\u0443\u0447\u0448\u0435\u0433\u043E \u0441\u043A\u0430\u043D\u0438\u0440\u043E\u0432\u0430\u043D\u0438\u044F\n const id = generateUUID();\n const totalChunks = Math.ceil(encoded.length / QR_MAX);\n \n console.log(`\uD83D\uDCCA COSE: Splitting ${encoded.length} chars into ${totalChunks} chunks (max ${QR_MAX} chars per chunk)`);\n \n for (let i = 0, seq = 1; i < encoded.length; i += QR_MAX, seq++) {\n const part = encoded.slice(i, i + QR_MAX);\n chunks.push(JSON.stringify({\n hdr: { v: 1, id, seq, total: totalChunks },\n body: part\n }));\n }\n }\n \n console.log(`\uD83D\uDCCA Generated ${chunks.length} QR chunk(s)`);\n return chunks;\n \n } catch (error) {\n console.error('\u274C Error in packSecurePayload:', error);\n throw error;\n }\n}\n\n/**\n * Receive and process COSE-packed QR data\n * @param {Array} qrStrings - Array of QR code strings\n * @param {CryptoKey} recipientEcdhPrivKey - Recipient's ECDH private key (optional)\n * @param {CryptoKey} trustedSenderPubKey - Trusted sender's public key (optional)\n * @returns {Array} Array of processed payloads\n */\nexport async function receiveAndProcess(qrStrings, recipientEcdhPrivKey = null, trustedSenderPubKey = null) {\n try {\n console.log('\uD83D\uDD13 Starting COSE processing...');\n \n // 1. Assemble chunks by ID\n console.log(`\uD83D\uDCCA Processing ${qrStrings.length} QR string(s)`);\n const assembled = await assembleFromQrStrings(qrStrings);\n if (!assembled.length) {\n console.error('\u274C No complete packets found after assembly');\n throw new Error('No complete packets found');\n }\n \n console.log(`\uD83D\uDCCA Assembled ${assembled.length} complete packet(s)`);\n console.log('\uD83D\uDCCA First assembled packet:', assembled[0]);\n \n const results = [];\n \n for (const pack of assembled) {\n try {\n const encoded = pack.jsonObj;\n \n // 2. Decode: base64url -> decompress -> CBOR decode\n const compressed = fromBase64Url(encoded.body || encoded);\n const cborBytes = pako.inflate(compressed);\n console.log('\uD83D\uDD13 Decompressed CBOR bytes length:', cborBytes.length);\n console.log('\uD83D\uDD13 CBOR bytes type:', typeof cborBytes, cborBytes.constructor.name);\n \n // Convert Uint8Array to ArrayBuffer for cbor-js\n const cborArrayBuffer = cborBytes.buffer.slice(cborBytes.byteOffset, cborBytes.byteOffset + cborBytes.byteLength);\n console.log('\uD83D\uDD13 Converted to ArrayBuffer, length:', cborArrayBuffer.byteLength);\n \n const coseSign1 = cbor.decode(cborArrayBuffer);\n \n console.log('\uD83D\uDD13 Decoded COSE structure');\n \n // Handle both array and object formats\n let protectedHeader, unprotectedHeader, payload, signature;\n if (Array.isArray(coseSign1)) {\n // Array format: [protected, unprotected, payload, signature]\n [protectedHeader, unprotectedHeader, payload, signature] = coseSign1;\n console.log('\uD83D\uDD13 COSE structure is array format');\n } else {\n // Object format (legacy)\n protectedHeader = coseSign1.protected;\n unprotectedHeader = coseSign1.unprotected;\n payload = coseSign1.payload;\n signature = coseSign1.signature;\n console.log('\uD83D\uDD13 COSE structure is object format (legacy)');\n }\n \n // 3. Verify signature (if key provided)\n if (trustedSenderPubKey && signature && signature.length > 0) {\n const toVerify = cbor.encode([protectedHeader, unprotectedHeader, payload]);\n const isValid = await crypto.subtle.verify(\n { name: 'ECDSA', hash: 'SHA-384' },\n trustedSenderPubKey,\n signature,\n toVerify\n );\n \n if (!isValid) {\n console.warn('\u26A0\uFE0F Signature verification failed');\n continue;\n }\n console.log('\u2705 Signature verified');\n }\n \n // 4. Decrypt payload\n let inner;\n if (payload instanceof Uint8Array) {\n // Payload is still encoded\n const innerArrayBuffer = payload.buffer.slice(payload.byteOffset, payload.byteOffset + payload.byteLength);\n inner = cbor.decode(innerArrayBuffer);\n } else {\n // Payload is already decoded\n inner = payload;\n }\n console.log('\uD83D\uDD13 Inner payload type:', typeof inner, inner.constructor.name);\n console.log('\uD83D\uDD13 Inner payload keys:', Object.keys(inner));\n console.log('\uD83D\uDD13 Inner payload full object:', inner);\n \n let payloadObj;\n \n if (inner.ciphertext && recipientEcdhPrivKey) {\n console.log('\uD83D\uDD13 Decrypting encrypted payload...');\n \n // Get ephemeral public key\n const epkRaw = inner.unprotected?.epk || inner.epk;\n \n // Import ephemeral public key\n const ephemeralPub = await crypto.subtle.importKey(\n 'raw',\n epkRaw,\n { name: 'ECDH', namedCurve: 'P-384' },\n true,\n []\n );\n \n // Derive shared secret\n const sharedBits = await crypto.subtle.deriveBits(\n { name: 'ECDH', public: ephemeralPub },\n recipientEcdhPrivKey,\n 384\n );\n \n // HKDF-SHA384 -> AES key\n const hkdfKey = await crypto.subtle.importKey('raw', sharedBits, 'HKDF', false, ['deriveKey']);\n const cek = await crypto.subtle.deriveKey(\n {\n name: 'HKDF',\n hash: 'SHA-384',\n salt: new Uint8Array(0),\n info: new TextEncoder().encode('SecureBit QR ECDH AES key')\n },\n hkdfKey,\n { name: 'AES-GCM', length: 256 },\n true,\n ['decrypt']\n );\n \n // Decrypt\n const plaintext = await crypto.subtle.decrypt(\n { name: 'AES-GCM', iv: inner.iv },\n cek,\n inner.ciphertext\n );\n \n const payloadJson = new TextDecoder().decode(plaintext);\n payloadObj = JSON.parse(payloadJson);\n \n } else if (inner.plaintext) {\n console.log('\uD83D\uDD13 Processing plaintext payload...');\n // Broadcast mode\n payloadObj = JSON.parse(new TextDecoder().decode(inner.plaintext));\n } else if (Object.keys(inner).length === 0) {\n console.log('\uD83D\uDD13 Empty inner payload, using alternative approach...');\n \n // Alternative: try to use the original assembled body\n try {\n const originalBody = encoded.body || encoded;\n console.log('\uD83D\uDD13 Trying to decode original body:', originalBody.substring(0, 50) + '...');\n \n // Decode base64url -> decompress -> CBOR decode -> extract JSON\n const compressed = fromBase64Url(originalBody);\n const decompressed = pako.inflate(compressed);\n console.log('\uD83D\uDD13 Decompressed length:', decompressed.length);\n \n // Convert to ArrayBuffer for CBOR decoding\n const decompressedArrayBuffer = decompressed.buffer.slice(decompressed.byteOffset, decompressed.byteOffset + decompressed.byteLength);\n const cborDecoded = cbor.decode(decompressedArrayBuffer);\n console.log('\uD83D\uDD13 CBOR decoded structure:', cborDecoded);\n \n // Handle both array and object formats\n let payload;\n if (Array.isArray(cborDecoded)) {\n // Array format: [protected, unprotected, payload, signature]\n console.log('\uD83D\uDD13 Alternative: COSE structure is array format');\n console.log('\uD83D\uDD13 Array length:', cborDecoded.length);\n console.log('\uD83D\uDD13 Array elements:', cborDecoded.map((el, i) => `${i}: ${typeof el} ${el.constructor.name}`));\n \n // Payload is at index 2\n payload = cborDecoded[2];\n console.log('\uD83D\uDD13 Payload at index 2:', payload);\n } else {\n // Object format (legacy)\n payload = cborDecoded.payload;\n console.log('\uD83D\uDD13 Alternative: COSE structure is object format (legacy)');\n }\n \n // Extract the actual payload from CBOR structure\n if (payload && payload instanceof Uint8Array) {\n const payloadArrayBuffer = payload.buffer.slice(payload.byteOffset, payload.byteOffset + payload.byteLength);\n const innerCbor = cbor.decode(payloadArrayBuffer);\n console.log('\uD83D\uDD13 Inner CBOR structure:', innerCbor);\n \n if (innerCbor.plaintext) {\n const jsonString = new TextDecoder().decode(innerCbor.plaintext);\n payloadObj = JSON.parse(jsonString);\n console.log('\uD83D\uDD13 Successfully decoded via alternative approach');\n console.log('\uD83D\uDD13 Alternative payloadObj:', payloadObj);\n } else {\n console.error('\u274C No plaintext found in inner CBOR structure');\n continue;\n }\n } else if (payload && typeof payload === 'object' && Object.keys(payload).length > 0) {\n // Payload is already a decoded object\n console.log('\uD83D\uDD13 Payload is already decoded object:', payload);\n if (payload.plaintext) {\n const jsonString = new TextDecoder().decode(payload.plaintext);\n payloadObj = JSON.parse(jsonString);\n console.log('\uD83D\uDD13 Successfully decoded from payload object');\n console.log('\uD83D\uDD13 Alternative payloadObj:', payloadObj);\n } else {\n console.error('\u274C No plaintext found in payload object');\n continue;\n }\n } else {\n console.error('\u274C No payload found in CBOR structure');\n console.log('\uD83D\uDD13 CBOR structure keys:', Object.keys(cborDecoded));\n console.log('\uD83D\uDD13 Payload type:', typeof payload);\n console.log('\uD83D\uDD13 Payload value:', payload);\n continue;\n }\n } catch (altError) {\n console.error('\u274C Alternative approach failed:', altError);\n continue;\n }\n } else {\n console.warn('\u26A0\uFE0F Unknown payload format:', inner);\n continue;\n }\n \n results.push({\n payloadObj,\n senderVerified: !!trustedSenderPubKey,\n encrypted: !!inner.ciphertext\n });\n \n } catch (packError) {\n console.error('\u274C Error processing packet:', packError);\n continue;\n }\n }\n \n console.log(`\u2705 Successfully processed ${results.length} payload(s)`);\n return results;\n \n } catch (error) {\n console.error('\u274C Error in receiveAndProcess:', error);\n throw error;\n }\n}\n\n/**\n * Assemble QR chunks into complete packets\n * @param {Array} qrStrings - Array of QR code strings\n * @returns {Array} Array of assembled packets\n */\nasync function assembleFromQrStrings(qrStrings) {\n const packets = new Map();\n \n console.log('\uD83D\uDD27 Starting assembly of QR strings...');\n \n for (const qrString of qrStrings) {\n try {\n console.log('\uD83D\uDD27 Parsing QR string:', qrString.substring(0, 100) + '...');\n const parsed = JSON.parse(qrString);\n console.log('\uD83D\uDD27 Parsed structure:', parsed);\n \n if (parsed.hdr && parsed.body) {\n const id = parsed.hdr.id;\n console.log(`\uD83D\uDD27 Processing packet ID: ${id}, seq: ${parsed.hdr.seq}, total: ${parsed.hdr.total}`);\n \n if (!packets.has(id)) {\n packets.set(id, {\n id: id,\n chunks: new Map(),\n total: parsed.hdr.total\n });\n console.log(`\uD83D\uDD27 Created new packet for ID: ${id}`);\n }\n \n const packet = packets.get(id);\n packet.chunks.set(parsed.hdr.seq, parsed.body);\n console.log(`\uD83D\uDD27 Added chunk ${parsed.hdr.seq} to packet ${id}. Current chunks: ${packet.chunks.size}/${packet.total}`);\n \n // Check if complete\n if (packet.chunks.size === packet.total) {\n console.log(`\uD83D\uDD27 Packet ${id} is complete! Assembling body...`);\n // Assemble body\n let assembledBody = '';\n for (let i = 1; i <= packet.total; i++) {\n assembledBody += packet.chunks.get(i);\n }\n \n packet.jsonObj = { body: assembledBody };\n packet.complete = true;\n console.log(`\uD83D\uDD27 Assembled body length: ${assembledBody.length} characters`);\n }\n } else {\n console.warn('\u26A0\uFE0F QR string missing hdr or body:', parsed);\n }\n } catch (error) {\n console.warn('\u26A0\uFE0F Failed to parse QR string:', error);\n continue;\n }\n }\n \n // Return only complete packets\n const completePackets = Array.from(packets.values()).filter(p => p.complete);\n console.log(`\uD83D\uDD27 Assembly complete. Found ${completePackets.length} complete packets`);\n return completePackets;\n}\n\n// Export for global use\nwindow.packSecurePayload = packSecurePayload;\nwindow.receiveAndProcess = receiveAndProcess;\n"], + "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')\n\nconst EC_BLOCKS_TABLE = [\n// L M Q H\n 1, 1, 1, 1,\n 1, 1, 1, 1,\n 1, 1, 2, 2,\n 1, 2, 2, 4,\n 1, 2, 4, 4,\n 2, 4, 4, 4,\n 2, 4, 6, 5,\n 2, 4, 6, 6,\n 2, 5, 8, 8,\n 4, 5, 8, 8,\n 4, 5, 8, 11,\n 4, 8, 10, 11,\n 4, 9, 12, 16,\n 4, 9, 16, 16,\n 6, 10, 12, 18,\n 6, 10, 17, 16,\n 6, 11, 16, 19,\n 6, 13, 18, 21,\n 7, 14, 21, 25,\n 8, 16, 20, 25,\n 8, 17, 23, 25,\n 9, 17, 23, 34,\n 9, 18, 25, 30,\n 10, 20, 27, 32,\n 12, 21, 29, 35,\n 12, 23, 34, 37,\n 12, 25, 34, 40,\n 13, 26, 35, 42,\n 14, 28, 38, 45,\n 15, 29, 40, 48,\n 16, 31, 43, 51,\n 17, 33, 45, 54,\n 18, 35, 48, 57,\n 19, 37, 51, 60,\n 19, 38, 53, 63,\n 20, 40, 56, 66,\n 21, 43, 59, 70,\n 22, 45, 62, 74,\n 24, 47, 65, 77,\n 25, 49, 68, 81\n]\n\nconst EC_CODEWORDS_TABLE = [\n// L M Q H\n 7, 10, 13, 17,\n 10, 16, 22, 28,\n 15, 26, 36, 44,\n 20, 36, 52, 64,\n 26, 48, 72, 88,\n 36, 64, 96, 112,\n 40, 72, 108, 130,\n 48, 88, 132, 156,\n 60, 110, 160, 192,\n 72, 130, 192, 224,\n 80, 150, 224, 264,\n 96, 176, 260, 308,\n 104, 198, 288, 352,\n 120, 216, 320, 384,\n 132, 240, 360, 432,\n 144, 280, 408, 480,\n 168, 308, 448, 532,\n 180, 338, 504, 588,\n 196, 364, 546, 650,\n 224, 416, 600, 700,\n 224, 442, 644, 750,\n 252, 476, 690, 816,\n 270, 504, 750, 900,\n 300, 560, 810, 960,\n 312, 588, 870, 1050,\n 336, 644, 952, 1110,\n 360, 700, 1020, 1200,\n 390, 728, 1050, 1260,\n 420, 784, 1140, 1350,\n 450, 812, 1200, 1440,\n 480, 868, 1290, 1530,\n 510, 924, 1350, 1620,\n 540, 980, 1440, 1710,\n 570, 1036, 1530, 1800,\n 570, 1064, 1590, 1890,\n 600, 1120, 1680, 1980,\n 630, 1204, 1770, 2100,\n 660, 1260, 1860, 2220,\n 720, 1316, 1950, 2310,\n 750, 1372, 2040, 2430\n]\n\n/**\n * Returns the number of error correction block that the QR Code should contain\n * for the specified version and error correction level.\n *\n * @param {Number} version QR Code version\n * @param {Number} errorCorrectionLevel Error correction level\n * @return {Number} Number of error correction blocks\n */\nexports.getBlocksCount = function getBlocksCount (version, errorCorrectionLevel) {\n switch (errorCorrectionLevel) {\n case ECLevel.L:\n return EC_BLOCKS_TABLE[(version - 1) * 4 + 0]\n case ECLevel.M:\n return EC_BLOCKS_TABLE[(version - 1) * 4 + 1]\n case ECLevel.Q:\n return EC_BLOCKS_TABLE[(version - 1) * 4 + 2]\n case ECLevel.H:\n return EC_BLOCKS_TABLE[(version - 1) * 4 + 3]\n default:\n return undefined\n }\n}\n\n/**\n * Returns the number of error correction codewords to use for the specified\n * version and error correction level.\n *\n * @param {Number} version QR Code version\n * @param {Number} errorCorrectionLevel Error correction level\n * @return {Number} Number of error correction codewords\n */\nexports.getTotalCodewordsCount = function getTotalCodewordsCount (version, errorCorrectionLevel) {\n switch (errorCorrectionLevel) {\n case ECLevel.L:\n return EC_CODEWORDS_TABLE[(version - 1) * 4 + 0]\n case ECLevel.M:\n return EC_CODEWORDS_TABLE[(version - 1) * 4 + 1]\n case ECLevel.Q:\n return EC_CODEWORDS_TABLE[(version - 1) * 4 + 2]\n case ECLevel.H:\n return EC_CODEWORDS_TABLE[(version - 1) * 4 + 3]\n default:\n return undefined\n }\n}\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", "(function (global, factory) {\n typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :\n typeof define === 'function' && define.amd ? define(['exports'], factory) :\n (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.ZXing = {}));\n}(this, (function (exports) { 'use strict';\n\n function isNullOrUndefined(obj) {\n return obj === null || obj === undefined;\n }\n\n /*\n * Copyright 2008 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n /* global Reflect, Promise */\n\n var extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n\n function __extends(d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n }\n\n function fixProto(target, prototype) {\n var setPrototypeOf = Object.setPrototypeOf;\n setPrototypeOf ? setPrototypeOf(target, prototype) : (target.__proto__ = prototype);\n }\n\n function fixStack(target, fn) {\n if (fn === void 0) {\n fn = target.constructor;\n }\n var captureStackTrace = Error.captureStackTrace;\n captureStackTrace && captureStackTrace(target, fn);\n }\n\n var CustomError = (function (_super) {\n __extends(CustomError, _super);\n function CustomError(message) {\n var _newTarget = this.constructor;\n var _this = _super.call(this, message) || this;\n Object.defineProperty(_this, 'name', {\n value: _newTarget.name,\n enumerable: false\n });\n fixProto(_this, _newTarget.prototype);\n fixStack(_this);\n return _this;\n }\n \n return CustomError;\n })(Error);\n\n /**\n * Custom Error class of type Exception.\n */\n class Exception extends CustomError {\n /**\n * Allows Exception to be constructed directly\n * with some message and prototype definition.\n */\n constructor(message = undefined) {\n super(message);\n this.message = message;\n }\n getKind() {\n const ex = this.constructor;\n return ex.kind;\n }\n }\n /**\n * It's typed as string so it can be extended and overriden.\n */\n Exception.kind = 'Exception';\n\n /**\n * Custom Error class of type Exception.\n */\n class ArgumentException extends Exception {\n }\n ArgumentException.kind = 'ArgumentException';\n\n /**\n * Custom Error class of type Exception.\n */\n class IllegalArgumentException extends Exception {\n }\n IllegalArgumentException.kind = 'IllegalArgumentException';\n\n /*\n * Copyright 2009 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n class BinaryBitmap {\n constructor(binarizer) {\n this.binarizer = binarizer;\n if (binarizer === null) {\n throw new IllegalArgumentException('Binarizer must be non-null.');\n }\n }\n /**\n * @return The width of the bitmap.\n */\n getWidth() {\n return this.binarizer.getWidth();\n }\n /**\n * @return The height of the bitmap.\n */\n getHeight() {\n return this.binarizer.getHeight();\n }\n /**\n * Converts one row of luminance data to 1 bit data. May actually do the conversion, or return\n * cached data. Callers should assume this method is expensive and call it as seldom as possible.\n * This method is intended for decoding 1D barcodes and may choose to apply sharpening.\n *\n * @param y The row to fetch, which must be in [0, bitmap height)\n * @param row An optional preallocated array. If null or too small, it will be ignored.\n * If used, the Binarizer will call BitArray.clear(). Always use the returned object.\n * @return The array of bits for this row (true means black).\n * @throws NotFoundException if row can't be binarized\n */\n getBlackRow(y /*int*/, row) {\n return this.binarizer.getBlackRow(y, row);\n }\n /**\n * Converts a 2D array of luminance data to 1 bit. As above, assume this method is expensive\n * and do not call it repeatedly. This method is intended for decoding 2D barcodes and may or\n * may not apply sharpening. Therefore, a row from this matrix may not be identical to one\n * fetched using getBlackRow(), so don't mix and match between them.\n *\n * @return The 2D array of bits for the image (true means black).\n * @throws NotFoundException if image can't be binarized to make a matrix\n */\n getBlackMatrix() {\n // The matrix is created on demand the first time it is requested, then cached. There are two\n // reasons for this:\n // 1. This work will never be done if the caller only installs 1D Reader objects, or if a\n // 1D Reader finds a barcode before the 2D Readers run.\n // 2. This work will only be done once even if the caller installs multiple 2D Readers.\n if (this.matrix === null || this.matrix === undefined) {\n this.matrix = this.binarizer.getBlackMatrix();\n }\n return this.matrix;\n }\n /**\n * @return Whether this bitmap can be cropped.\n */\n isCropSupported() {\n return this.binarizer.getLuminanceSource().isCropSupported();\n }\n /**\n * Returns a new object with cropped image data. Implementations may keep a reference to the\n * original data rather than a copy. Only callable if isCropSupported() is true.\n *\n * @param left The left coordinate, which must be in [0,getWidth())\n * @param top The top coordinate, which must be in [0,getHeight())\n * @param width The width of the rectangle to crop.\n * @param height The height of the rectangle to crop.\n * @return A cropped version of this object.\n */\n crop(left /*int*/, top /*int*/, width /*int*/, height /*int*/) {\n const newSource = this.binarizer.getLuminanceSource().crop(left, top, width, height);\n return new BinaryBitmap(this.binarizer.createBinarizer(newSource));\n }\n /**\n * @return Whether this bitmap supports counter-clockwise rotation.\n */\n isRotateSupported() {\n return this.binarizer.getLuminanceSource().isRotateSupported();\n }\n /**\n * Returns a new object with rotated image data by 90 degrees counterclockwise.\n * Only callable if {@link #isRotateSupported()} is true.\n *\n * @return A rotated version of this object.\n */\n rotateCounterClockwise() {\n const newSource = this.binarizer.getLuminanceSource().rotateCounterClockwise();\n return new BinaryBitmap(this.binarizer.createBinarizer(newSource));\n }\n /**\n * Returns a new object with rotated image data by 45 degrees counterclockwise.\n * Only callable if {@link #isRotateSupported()} is true.\n *\n * @return A rotated version of this object.\n */\n rotateCounterClockwise45() {\n const newSource = this.binarizer.getLuminanceSource().rotateCounterClockwise45();\n return new BinaryBitmap(this.binarizer.createBinarizer(newSource));\n }\n /*@Override*/\n toString() {\n try {\n return this.getBlackMatrix().toString();\n }\n catch (e /*: NotFoundException*/) {\n return '';\n }\n }\n }\n\n /**\n * Custom Error class of type Exception.\n */\n class ChecksumException extends Exception {\n static getChecksumInstance() {\n return new ChecksumException();\n }\n }\n ChecksumException.kind = 'ChecksumException';\n\n /*\n * Copyright 2009 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n /**\n * This class hierarchy provides a set of methods to convert luminance data to 1 bit data.\n * It allows the algorithm to vary polymorphically, for example allowing a very expensive\n * thresholding technique for servers and a fast one for mobile. It also permits the implementation\n * to vary, e.g. a JNI version for Android and a Java fallback version for other platforms.\n *\n * @author dswitkin@google.com (Daniel Switkin)\n */\n class Binarizer {\n constructor(source) {\n this.source = source;\n }\n getLuminanceSource() {\n return this.source;\n }\n getWidth() {\n return this.source.getWidth();\n }\n getHeight() {\n return this.source.getHeight();\n }\n }\n\n class System {\n // public static void arraycopy(Object src, int srcPos, Object dest, int destPos, int length)\n /**\n * Makes a copy of a array.\n */\n static arraycopy(src, srcPos, dest, destPos, length) {\n // TODO: better use split or set?\n while (length--) {\n dest[destPos++] = src[srcPos++];\n }\n }\n /**\n * Returns the current time in milliseconds.\n */\n static currentTimeMillis() {\n return Date.now();\n }\n }\n\n /**\n * Custom Error class of type Exception.\n */\n class IndexOutOfBoundsException extends Exception {\n }\n IndexOutOfBoundsException.kind = 'IndexOutOfBoundsException';\n\n /**\n * Custom Error class of type Exception.\n */\n class ArrayIndexOutOfBoundsException extends IndexOutOfBoundsException {\n constructor(index = undefined, message = undefined) {\n super(message);\n this.index = index;\n this.message = message;\n }\n }\n ArrayIndexOutOfBoundsException.kind = 'ArrayIndexOutOfBoundsException';\n\n class Arrays {\n /**\n * Assigns the specified int value to each element of the specified array\n * of ints.\n *\n * @param a the array to be filled\n * @param val the value to be stored in all elements of the array\n */\n static fill(a, val) {\n for (let i = 0, len = a.length; i < len; i++)\n a[i] = val;\n }\n /**\n * Assigns the specified int value to each element of the specified\n * range of the specified array of ints. The range to be filled\n * extends from index {@code fromIndex}, inclusive, to index\n * {@code toIndex}, exclusive. (If {@code fromIndex==toIndex}, the\n * range to be filled is empty.)\n *\n * @param a the array to be filled\n * @param fromIndex the index of the first element (inclusive) to be\n * filled with the specified value\n * @param toIndex the index of the last element (exclusive) to be\n * filled with the specified value\n * @param val the value to be stored in all elements of the array\n * @throws IllegalArgumentException if {@code fromIndex > toIndex}\n * @throws ArrayIndexOutOfBoundsException if {@code fromIndex < 0} or\n * {@code toIndex > a.length}\n */\n static fillWithin(a, fromIndex, toIndex, val) {\n Arrays.rangeCheck(a.length, fromIndex, toIndex);\n for (let i = fromIndex; i < toIndex; i++)\n a[i] = val;\n }\n /**\n * Checks that {@code fromIndex} and {@code toIndex} are in\n * the range and throws an exception if they aren't.\n */\n static rangeCheck(arrayLength, fromIndex, toIndex) {\n if (fromIndex > toIndex) {\n throw new IllegalArgumentException('fromIndex(' + fromIndex + ') > toIndex(' + toIndex + ')');\n }\n if (fromIndex < 0) {\n throw new ArrayIndexOutOfBoundsException(fromIndex);\n }\n if (toIndex > arrayLength) {\n throw new ArrayIndexOutOfBoundsException(toIndex);\n }\n }\n static asList(...args) {\n return args;\n }\n static create(rows, cols, value) {\n let arr = Array.from({ length: rows });\n return arr.map(x => Array.from({ length: cols }).fill(value));\n }\n static createInt32Array(rows, cols, value) {\n let arr = Array.from({ length: rows });\n return arr.map(x => Int32Array.from({ length: cols }).fill(value));\n }\n static equals(first, second) {\n if (!first) {\n return false;\n }\n if (!second) {\n return false;\n }\n if (!first.length) {\n return false;\n }\n if (!second.length) {\n return false;\n }\n if (first.length !== second.length) {\n return false;\n }\n for (let i = 0, length = first.length; i < length; i++) {\n if (first[i] !== second[i]) {\n return false;\n }\n }\n return true;\n }\n static hashCode(a) {\n if (a === null) {\n return 0;\n }\n let result = 1;\n for (const element of a) {\n result = 31 * result + element;\n }\n return result;\n }\n static fillUint8Array(a, value) {\n for (let i = 0; i !== a.length; i++) {\n a[i] = value;\n }\n }\n static copyOf(original, newLength) {\n return original.slice(0, newLength);\n }\n static copyOfUint8Array(original, newLength) {\n if (original.length <= newLength) {\n const newArray = new Uint8Array(newLength);\n newArray.set(original);\n return newArray;\n }\n return original.slice(0, newLength);\n }\n static copyOfRange(original, from, to) {\n const newLength = to - from;\n const copy = new Int32Array(newLength);\n System.arraycopy(original, from, copy, 0, newLength);\n return copy;\n }\n /*\n * Returns the index of of the element in a sorted array or (-n-1) where n is the insertion point\n * for the new element.\n * Parameters:\n * ar - A sorted array\n * el - An element to search for\n * comparator - A comparator function. The function takes two arguments: (a, b) and returns:\n * a negative number if a is less than b;\n * 0 if a is equal to b;\n * a positive number of a is greater than b.\n * The array may contain duplicate elements. If there are more than one equal elements in the array,\n * the returned value can be the index of any one of the equal elements.\n *\n * http://jsfiddle.net/aryzhov/pkfst550/\n */\n static binarySearch(ar, el, comparator) {\n if (undefined === comparator) {\n comparator = Arrays.numberComparator;\n }\n let m = 0;\n let n = ar.length - 1;\n while (m <= n) {\n const k = (n + m) >> 1;\n const cmp = comparator(el, ar[k]);\n if (cmp > 0) {\n m = k + 1;\n }\n else if (cmp < 0) {\n n = k - 1;\n }\n else {\n return k;\n }\n }\n return -m - 1;\n }\n static numberComparator(a, b) {\n return a - b;\n }\n }\n\n /**\n * Ponyfill for Java's Integer class.\n */\n class Integer {\n static numberOfTrailingZeros(i) {\n let y;\n if (i === 0)\n return 32;\n let n = 31;\n y = i << 16;\n if (y !== 0) {\n n -= 16;\n i = y;\n }\n y = i << 8;\n if (y !== 0) {\n n -= 8;\n i = y;\n }\n y = i << 4;\n if (y !== 0) {\n n -= 4;\n i = y;\n }\n y = i << 2;\n if (y !== 0) {\n n -= 2;\n i = y;\n }\n return n - ((i << 1) >>> 31);\n }\n static numberOfLeadingZeros(i) {\n // HD, Figure 5-6\n if (i === 0) {\n return 32;\n }\n let n = 1;\n if (i >>> 16 === 0) {\n n += 16;\n i <<= 16;\n }\n if (i >>> 24 === 0) {\n n += 8;\n i <<= 8;\n }\n if (i >>> 28 === 0) {\n n += 4;\n i <<= 4;\n }\n if (i >>> 30 === 0) {\n n += 2;\n i <<= 2;\n }\n n -= i >>> 31;\n return n;\n }\n static toHexString(i) {\n return i.toString(16);\n }\n static toBinaryString(intNumber) {\n return String(parseInt(String(intNumber), 2));\n }\n // Returns the number of one-bits in the two's complement binary representation of the specified int value. This function is sometimes referred to as the population count.\n // Returns:\n // the number of one-bits in the two's complement binary representation of the specified int value.\n static bitCount(i) {\n // HD, Figure 5-2\n i = i - ((i >>> 1) & 0x55555555);\n i = (i & 0x33333333) + ((i >>> 2) & 0x33333333);\n i = (i + (i >>> 4)) & 0x0f0f0f0f;\n i = i + (i >>> 8);\n i = i + (i >>> 16);\n return i & 0x3f;\n }\n static truncDivision(dividend, divisor) {\n return Math.trunc(dividend / divisor);\n }\n /**\n * Converts A string to an integer.\n * @param s A string to convert into a number.\n * @param radix A value between 2 and 36 that specifies the base of the number in numString. If this argument is not supplied, strings with a prefix of '0x' are considered hexadecimal. All other strings are considered decimal.\n */\n static parseInt(num, radix = undefined) {\n return parseInt(num, radix);\n }\n }\n Integer.MIN_VALUE_32_BITS = -2147483648;\n Integer.MAX_VALUE = Number.MAX_SAFE_INTEGER;\n\n /**\n *

A simple, fast array of bits, represented compactly by an array of ints internally.

\n *\n * @author Sean Owen\n */\n class BitArray /*implements Cloneable*/ {\n // For testing only\n constructor(size /*int*/, bits) {\n if (undefined === size) {\n this.size = 0;\n this.bits = new Int32Array(1);\n }\n else {\n this.size = size;\n if (undefined === bits || null === bits) {\n this.bits = BitArray.makeArray(size);\n }\n else {\n this.bits = bits;\n }\n }\n }\n getSize() {\n return this.size;\n }\n getSizeInBytes() {\n return Math.floor((this.size + 7) / 8);\n }\n ensureCapacity(size /*int*/) {\n if (size > this.bits.length * 32) {\n const newBits = BitArray.makeArray(size);\n System.arraycopy(this.bits, 0, newBits, 0, this.bits.length);\n this.bits = newBits;\n }\n }\n /**\n * @param i bit to get\n * @return true iff bit i is set\n */\n get(i /*int*/) {\n return (this.bits[Math.floor(i / 32)] & (1 << (i & 0x1F))) !== 0;\n }\n /**\n * Sets bit i.\n *\n * @param i bit to set\n */\n set(i /*int*/) {\n this.bits[Math.floor(i / 32)] |= 1 << (i & 0x1F);\n }\n /**\n * Flips bit i.\n *\n * @param i bit to set\n */\n flip(i /*int*/) {\n this.bits[Math.floor(i / 32)] ^= 1 << (i & 0x1F);\n }\n /**\n * @param from first bit to check\n * @return index of first bit that is set, starting from the given index, or size if none are set\n * at or beyond this given index\n * @see #getNextUnset(int)\n */\n getNextSet(from /*int*/) {\n const size = this.size;\n if (from >= size) {\n return size;\n }\n const bits = this.bits;\n let bitsOffset = Math.floor(from / 32);\n let currentBits = bits[bitsOffset];\n // mask off lesser bits first\n currentBits &= ~((1 << (from & 0x1F)) - 1);\n const length = bits.length;\n while (currentBits === 0) {\n if (++bitsOffset === length) {\n return size;\n }\n currentBits = bits[bitsOffset];\n }\n const result = (bitsOffset * 32) + Integer.numberOfTrailingZeros(currentBits);\n return result > size ? size : result;\n }\n /**\n * @param from index to start looking for unset bit\n * @return index of next unset bit, or {@code size} if none are unset until the end\n * @see #getNextSet(int)\n */\n getNextUnset(from /*int*/) {\n const size = this.size;\n if (from >= size) {\n return size;\n }\n const bits = this.bits;\n let bitsOffset = Math.floor(from / 32);\n let currentBits = ~bits[bitsOffset];\n // mask off lesser bits first\n currentBits &= ~((1 << (from & 0x1F)) - 1);\n const length = bits.length;\n while (currentBits === 0) {\n if (++bitsOffset === length) {\n return size;\n }\n currentBits = ~bits[bitsOffset];\n }\n const result = (bitsOffset * 32) + Integer.numberOfTrailingZeros(currentBits);\n return result > size ? size : result;\n }\n /**\n * Sets a block of 32 bits, starting at bit i.\n *\n * @param i first bit to set\n * @param newBits the new value of the next 32 bits. Note again that the least-significant bit\n * corresponds to bit i, the next-least-significant to i+1, and so on.\n */\n setBulk(i /*int*/, newBits /*int*/) {\n this.bits[Math.floor(i / 32)] = newBits;\n }\n /**\n * Sets a range of bits.\n *\n * @param start start of range, inclusive.\n * @param end end of range, exclusive\n */\n setRange(start /*int*/, end /*int*/) {\n if (end < start || start < 0 || end > this.size) {\n throw new IllegalArgumentException();\n }\n if (end === start) {\n return;\n }\n end--; // will be easier to treat this as the last actually set bit -- inclusive\n const firstInt = Math.floor(start / 32);\n const lastInt = Math.floor(end / 32);\n const bits = this.bits;\n for (let i = firstInt; i <= lastInt; i++) {\n const firstBit = i > firstInt ? 0 : start & 0x1F;\n const lastBit = i < lastInt ? 31 : end & 0x1F;\n // Ones from firstBit to lastBit, inclusive\n const mask = (2 << lastBit) - (1 << firstBit);\n bits[i] |= mask;\n }\n }\n /**\n * Clears all bits (sets to false).\n */\n clear() {\n const max = this.bits.length;\n const bits = this.bits;\n for (let i = 0; i < max; i++) {\n bits[i] = 0;\n }\n }\n /**\n * Efficient method to check if a range of bits is set, or not set.\n *\n * @param start start of range, inclusive.\n * @param end end of range, exclusive\n * @param value if true, checks that bits in range are set, otherwise checks that they are not set\n * \n * @return true iff all bits are set or not set in range, according to value argument\n * @throws IllegalArgumentException if end is less than start or the range is not contained in the array\n */\n isRange(start /*int*/, end /*int*/, value) {\n if (end < start || start < 0 || end > this.size) {\n throw new IllegalArgumentException();\n }\n if (end === start) {\n return true; // empty range matches\n }\n end--; // will be easier to treat this as the last actually set bit -- inclusive\n const firstInt = Math.floor(start / 32);\n const lastInt = Math.floor(end / 32);\n const bits = this.bits;\n for (let i = firstInt; i <= lastInt; i++) {\n const firstBit = i > firstInt ? 0 : start & 0x1F;\n const lastBit = i < lastInt ? 31 : end & 0x1F;\n // Ones from firstBit to lastBit, inclusive\n const mask = (2 << lastBit) - (1 << firstBit) & 0xFFFFFFFF;\n // TYPESCRIPTPORT: & 0xFFFFFFFF added to discard anything after 32 bits, as ES has 53 bits\n // Return false if we're looking for 1s and the masked bits[i] isn't all 1s (is: that,\n // equals the mask, or we're looking for 0s and the masked portion is not all 0s\n if ((bits[i] & mask) !== (value ? mask : 0)) {\n return false;\n }\n }\n return true;\n }\n appendBit(bit) {\n this.ensureCapacity(this.size + 1);\n if (bit) {\n this.bits[Math.floor(this.size / 32)] |= 1 << (this.size & 0x1F);\n }\n this.size++;\n }\n /**\n * Appends the least-significant bits, from value, in order from most-significant to\n * least-significant. For example, appending 6 bits from 0x000001E will append the bits\n * 0, 1, 1, 1, 1, 0 in that order.\n *\n * @param value {@code int} containing bits to append\n * @param numBits bits from value to append\n */\n appendBits(value /*int*/, numBits /*int*/) {\n if (numBits < 0 || numBits > 32) {\n throw new IllegalArgumentException('Num bits must be between 0 and 32');\n }\n this.ensureCapacity(this.size + numBits);\n // const appendBit = this.appendBit;\n for (let numBitsLeft = numBits; numBitsLeft > 0; numBitsLeft--) {\n this.appendBit(((value >> (numBitsLeft - 1)) & 0x01) === 1);\n }\n }\n appendBitArray(other) {\n const otherSize = other.size;\n this.ensureCapacity(this.size + otherSize);\n // const appendBit = this.appendBit;\n for (let i = 0; i < otherSize; i++) {\n this.appendBit(other.get(i));\n }\n }\n xor(other) {\n if (this.size !== other.size) {\n throw new IllegalArgumentException('Sizes don\\'t match');\n }\n const bits = this.bits;\n for (let i = 0, length = bits.length; i < length; i++) {\n // The last int could be incomplete (i.e. not have 32 bits in\n // it) but there is no problem since 0 XOR 0 == 0.\n bits[i] ^= other.bits[i];\n }\n }\n /**\n *\n * @param bitOffset first bit to start writing\n * @param array array to write into. Bytes are written most-significant byte first. This is the opposite\n * of the internal representation, which is exposed by {@link #getBitArray()}\n * @param offset position in array to start writing\n * @param numBytes how many bytes to write\n */\n toBytes(bitOffset /*int*/, array, offset /*int*/, numBytes /*int*/) {\n for (let i = 0; i < numBytes; i++) {\n let theByte = 0;\n for (let j = 0; j < 8; j++) {\n if (this.get(bitOffset)) {\n theByte |= 1 << (7 - j);\n }\n bitOffset++;\n }\n array[offset + i] = /*(byte)*/ theByte;\n }\n }\n /**\n * @return underlying array of ints. The first element holds the first 32 bits, and the least\n * significant bit is bit 0.\n */\n getBitArray() {\n return this.bits;\n }\n /**\n * Reverses all bits in the array.\n */\n reverse() {\n const newBits = new Int32Array(this.bits.length);\n // reverse all int's first\n const len = Math.floor((this.size - 1) / 32);\n const oldBitsLen = len + 1;\n const bits = this.bits;\n for (let i = 0; i < oldBitsLen; i++) {\n let x = bits[i];\n x = ((x >> 1) & 0x55555555) | ((x & 0x55555555) << 1);\n x = ((x >> 2) & 0x33333333) | ((x & 0x33333333) << 2);\n x = ((x >> 4) & 0x0f0f0f0f) | ((x & 0x0f0f0f0f) << 4);\n x = ((x >> 8) & 0x00ff00ff) | ((x & 0x00ff00ff) << 8);\n x = ((x >> 16) & 0x0000ffff) | ((x & 0x0000ffff) << 16);\n newBits[len - i] = /*(int)*/ x;\n }\n // now correct the int's if the bit size isn't a multiple of 32\n if (this.size !== oldBitsLen * 32) {\n const leftOffset = oldBitsLen * 32 - this.size;\n let currentInt = newBits[0] >>> leftOffset;\n for (let i = 1; i < oldBitsLen; i++) {\n const nextInt = newBits[i];\n currentInt |= nextInt << (32 - leftOffset);\n newBits[i - 1] = currentInt;\n currentInt = nextInt >>> leftOffset;\n }\n newBits[oldBitsLen - 1] = currentInt;\n }\n this.bits = newBits;\n }\n static makeArray(size /*int*/) {\n return new Int32Array(Math.floor((size + 31) / 32));\n }\n /*@Override*/\n equals(o) {\n if (!(o instanceof BitArray)) {\n return false;\n }\n const other = o;\n return this.size === other.size && Arrays.equals(this.bits, other.bits);\n }\n /*@Override*/\n hashCode() {\n return 31 * this.size + Arrays.hashCode(this.bits);\n }\n /*@Override*/\n toString() {\n let result = '';\n for (let i = 0, size = this.size; i < size; i++) {\n if ((i & 0x07) === 0) {\n result += ' ';\n }\n result += this.get(i) ? 'X' : '.';\n }\n return result;\n }\n /*@Override*/\n clone() {\n return new BitArray(this.size, this.bits.slice());\n }\n }\n\n /*\n * Copyright 2009 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n /*namespace com.google.zxing {*/\n /**\n * Encapsulates a type of hint that a caller may pass to a barcode reader to help it\n * more quickly or accurately decode it. It is up to implementations to decide what,\n * if anything, to do with the information that is supplied.\n *\n * @author Sean Owen\n * @author dswitkin@google.com (Daniel Switkin)\n * @see Reader#decode(BinaryBitmap,java.util.Map)\n */\n var DecodeHintType;\n (function (DecodeHintType) {\n /**\n * Unspecified, application-specific hint. Maps to an unspecified {@link Object}.\n */\n DecodeHintType[DecodeHintType[\"OTHER\"] = 0] = \"OTHER\"; /*(Object.class)*/\n /**\n * Image is a pure monochrome image of a barcode. Doesn't matter what it maps to;\n * use {@link Boolean#TRUE}.\n */\n DecodeHintType[DecodeHintType[\"PURE_BARCODE\"] = 1] = \"PURE_BARCODE\"; /*(Void.class)*/\n /**\n * Image is known to be of one of a few possible formats.\n * Maps to a {@link List} of {@link BarcodeFormat}s.\n */\n DecodeHintType[DecodeHintType[\"POSSIBLE_FORMATS\"] = 2] = \"POSSIBLE_FORMATS\"; /*(List.class)*/\n /**\n * Spend more time to try to find a barcode; optimize for accuracy, not speed.\n * Doesn't matter what it maps to; use {@link Boolean#TRUE}.\n */\n DecodeHintType[DecodeHintType[\"TRY_HARDER\"] = 3] = \"TRY_HARDER\"; /*(Void.class)*/\n /**\n * Specifies what character encoding to use when decoding, where applicable (type String)\n */\n DecodeHintType[DecodeHintType[\"CHARACTER_SET\"] = 4] = \"CHARACTER_SET\"; /*(String.class)*/\n /**\n * Allowed lengths of encoded data -- reject anything else. Maps to an {@code Int32Array}.\n */\n DecodeHintType[DecodeHintType[\"ALLOWED_LENGTHS\"] = 5] = \"ALLOWED_LENGTHS\"; /*(Int32Array.class)*/\n /**\n * Assume Code 39 codes employ a check digit. Doesn't matter what it maps to;\n * use {@link Boolean#TRUE}.\n */\n DecodeHintType[DecodeHintType[\"ASSUME_CODE_39_CHECK_DIGIT\"] = 6] = \"ASSUME_CODE_39_CHECK_DIGIT\"; /*(Void.class)*/\n /**\n * Assume the barcode is being processed as a GS1 barcode, and modify behavior as needed.\n * For example this affects FNC1 handling for Code 128 (aka GS1-128). Doesn't matter what it maps to;\n * use {@link Boolean#TRUE}.\n */\n DecodeHintType[DecodeHintType[\"ASSUME_GS1\"] = 7] = \"ASSUME_GS1\"; /*(Void.class)*/\n /**\n * If true, return the start and end digits in a Codabar barcode instead of stripping them. They\n * are alpha, whereas the rest are numeric. By default, they are stripped, but this causes them\n * to not be. Doesn't matter what it maps to; use {@link Boolean#TRUE}.\n */\n DecodeHintType[DecodeHintType[\"RETURN_CODABAR_START_END\"] = 8] = \"RETURN_CODABAR_START_END\"; /*(Void.class)*/\n /**\n * The caller needs to be notified via callback when a possible {@link ResultPoint}\n * is found. Maps to a {@link ResultPointCallback}.\n */\n DecodeHintType[DecodeHintType[\"NEED_RESULT_POINT_CALLBACK\"] = 9] = \"NEED_RESULT_POINT_CALLBACK\"; /*(ResultPointCallback.class)*/\n /**\n * Allowed extension lengths for EAN or UPC barcodes. Other formats will ignore this.\n * Maps to an {@code Int32Array} of the allowed extension lengths, for example [2], [5], or [2, 5].\n * If it is optional to have an extension, do not set this hint. If this is set,\n * and a UPC or EAN barcode is found but an extension is not, then no result will be returned\n * at all.\n */\n DecodeHintType[DecodeHintType[\"ALLOWED_EAN_EXTENSIONS\"] = 10] = \"ALLOWED_EAN_EXTENSIONS\"; /*(Int32Array.class)*/\n // End of enumeration values.\n /**\n * Data type the hint is expecting.\n * Among the possible values the {@link Void} stands out as being used for\n * hints that do not expect a value to be supplied (flag hints). Such hints\n * will possibly have their value ignored, or replaced by a\n * {@link Boolean#TRUE}. Hint suppliers should probably use\n * {@link Boolean#TRUE} as directed by the actual hint documentation.\n */\n // private valueType: Class\n // DecodeHintType(valueType: Class) {\n // this.valueType = valueType\n // }\n // public getValueType(): Class {\n // return valueType\n // }\n })(DecodeHintType || (DecodeHintType = {}));\n var DecodeHintType$1 = DecodeHintType;\n\n /**\n * Custom Error class of type Exception.\n */\n class FormatException extends Exception {\n static getFormatInstance() {\n return new FormatException();\n }\n }\n FormatException.kind = 'FormatException';\n\n /*import java.util.HashMap;*/\n /*import java.util.Map;*/\n var CharacterSetValueIdentifiers;\n (function (CharacterSetValueIdentifiers) {\n CharacterSetValueIdentifiers[CharacterSetValueIdentifiers[\"Cp437\"] = 0] = \"Cp437\";\n CharacterSetValueIdentifiers[CharacterSetValueIdentifiers[\"ISO8859_1\"] = 1] = \"ISO8859_1\";\n CharacterSetValueIdentifiers[CharacterSetValueIdentifiers[\"ISO8859_2\"] = 2] = \"ISO8859_2\";\n CharacterSetValueIdentifiers[CharacterSetValueIdentifiers[\"ISO8859_3\"] = 3] = \"ISO8859_3\";\n CharacterSetValueIdentifiers[CharacterSetValueIdentifiers[\"ISO8859_4\"] = 4] = \"ISO8859_4\";\n CharacterSetValueIdentifiers[CharacterSetValueIdentifiers[\"ISO8859_5\"] = 5] = \"ISO8859_5\";\n CharacterSetValueIdentifiers[CharacterSetValueIdentifiers[\"ISO8859_6\"] = 6] = \"ISO8859_6\";\n CharacterSetValueIdentifiers[CharacterSetValueIdentifiers[\"ISO8859_7\"] = 7] = \"ISO8859_7\";\n CharacterSetValueIdentifiers[CharacterSetValueIdentifiers[\"ISO8859_8\"] = 8] = \"ISO8859_8\";\n CharacterSetValueIdentifiers[CharacterSetValueIdentifiers[\"ISO8859_9\"] = 9] = \"ISO8859_9\";\n CharacterSetValueIdentifiers[CharacterSetValueIdentifiers[\"ISO8859_10\"] = 10] = \"ISO8859_10\";\n CharacterSetValueIdentifiers[CharacterSetValueIdentifiers[\"ISO8859_11\"] = 11] = \"ISO8859_11\";\n CharacterSetValueIdentifiers[CharacterSetValueIdentifiers[\"ISO8859_13\"] = 12] = \"ISO8859_13\";\n CharacterSetValueIdentifiers[CharacterSetValueIdentifiers[\"ISO8859_14\"] = 13] = \"ISO8859_14\";\n CharacterSetValueIdentifiers[CharacterSetValueIdentifiers[\"ISO8859_15\"] = 14] = \"ISO8859_15\";\n CharacterSetValueIdentifiers[CharacterSetValueIdentifiers[\"ISO8859_16\"] = 15] = \"ISO8859_16\";\n CharacterSetValueIdentifiers[CharacterSetValueIdentifiers[\"SJIS\"] = 16] = \"SJIS\";\n CharacterSetValueIdentifiers[CharacterSetValueIdentifiers[\"Cp1250\"] = 17] = \"Cp1250\";\n CharacterSetValueIdentifiers[CharacterSetValueIdentifiers[\"Cp1251\"] = 18] = \"Cp1251\";\n CharacterSetValueIdentifiers[CharacterSetValueIdentifiers[\"Cp1252\"] = 19] = \"Cp1252\";\n CharacterSetValueIdentifiers[CharacterSetValueIdentifiers[\"Cp1256\"] = 20] = \"Cp1256\";\n CharacterSetValueIdentifiers[CharacterSetValueIdentifiers[\"UnicodeBigUnmarked\"] = 21] = \"UnicodeBigUnmarked\";\n CharacterSetValueIdentifiers[CharacterSetValueIdentifiers[\"UTF8\"] = 22] = \"UTF8\";\n CharacterSetValueIdentifiers[CharacterSetValueIdentifiers[\"ASCII\"] = 23] = \"ASCII\";\n CharacterSetValueIdentifiers[CharacterSetValueIdentifiers[\"Big5\"] = 24] = \"Big5\";\n CharacterSetValueIdentifiers[CharacterSetValueIdentifiers[\"GB18030\"] = 25] = \"GB18030\";\n CharacterSetValueIdentifiers[CharacterSetValueIdentifiers[\"EUC_KR\"] = 26] = \"EUC_KR\";\n })(CharacterSetValueIdentifiers || (CharacterSetValueIdentifiers = {}));\n /**\n * Encapsulates a Character Set ECI, according to \"Extended Channel Interpretations\" 5.3.1.1\n * of ISO 18004.\n *\n * @author Sean Owen\n */\n class CharacterSetECI {\n constructor(valueIdentifier, valuesParam, name, ...otherEncodingNames) {\n this.valueIdentifier = valueIdentifier;\n this.name = name;\n if (typeof valuesParam === 'number') {\n this.values = Int32Array.from([valuesParam]);\n }\n else {\n this.values = valuesParam;\n }\n this.otherEncodingNames = otherEncodingNames;\n CharacterSetECI.VALUE_IDENTIFIER_TO_ECI.set(valueIdentifier, this);\n CharacterSetECI.NAME_TO_ECI.set(name, this);\n const values = this.values;\n for (let i = 0, length = values.length; i !== length; i++) {\n const v = values[i];\n CharacterSetECI.VALUES_TO_ECI.set(v, this);\n }\n for (const otherName of otherEncodingNames) {\n CharacterSetECI.NAME_TO_ECI.set(otherName, this);\n }\n }\n // CharacterSetECI(value: number /*int*/) {\n // this(new Int32Array {value})\n // }\n // CharacterSetECI(value: number /*int*/, String... otherEncodingNames) {\n // this.values = new Int32Array {value}\n // this.otherEncodingNames = otherEncodingNames\n // }\n // CharacterSetECI(values: Int32Array, String... otherEncodingNames) {\n // this.values = values\n // this.otherEncodingNames = otherEncodingNames\n // }\n getValueIdentifier() {\n return this.valueIdentifier;\n }\n getName() {\n return this.name;\n }\n getValue() {\n return this.values[0];\n }\n /**\n * @param value character set ECI value\n * @return {@code CharacterSetECI} representing ECI of given value, or null if it is legal but\n * unsupported\n * @throws FormatException if ECI value is invalid\n */\n static getCharacterSetECIByValue(value /*int*/) {\n if (value < 0 || value >= 900) {\n throw new FormatException('incorect value');\n }\n const characterSet = CharacterSetECI.VALUES_TO_ECI.get(value);\n if (undefined === characterSet) {\n throw new FormatException('incorect value');\n }\n return characterSet;\n }\n /**\n * @param name character set ECI encoding name\n * @return CharacterSetECI representing ECI for character encoding, or null if it is legal\n * but unsupported\n */\n static getCharacterSetECIByName(name) {\n const characterSet = CharacterSetECI.NAME_TO_ECI.get(name);\n if (undefined === characterSet) {\n throw new FormatException('incorect value');\n }\n return characterSet;\n }\n equals(o) {\n if (!(o instanceof CharacterSetECI)) {\n return false;\n }\n const other = o;\n return this.getName() === other.getName();\n }\n }\n CharacterSetECI.VALUE_IDENTIFIER_TO_ECI = new Map();\n CharacterSetECI.VALUES_TO_ECI = new Map();\n CharacterSetECI.NAME_TO_ECI = new Map();\n // Enum name is a Java encoding valid for java.lang and java.io\n // TYPESCRIPTPORT: changed the main label for ISO as the TextEncoder did not recognized them in the form from java\n // (eg ISO8859_1 must be ISO88591 or ISO8859-1 or ISO-8859-1)\n // later on: well, except 16 wich does not work with ISO885916 so used ISO-8859-1 form for default\n CharacterSetECI.Cp437 = new CharacterSetECI(CharacterSetValueIdentifiers.Cp437, Int32Array.from([0, 2]), 'Cp437');\n CharacterSetECI.ISO8859_1 = new CharacterSetECI(CharacterSetValueIdentifiers.ISO8859_1, Int32Array.from([1, 3]), 'ISO-8859-1', 'ISO88591', 'ISO8859_1');\n CharacterSetECI.ISO8859_2 = new CharacterSetECI(CharacterSetValueIdentifiers.ISO8859_2, 4, 'ISO-8859-2', 'ISO88592', 'ISO8859_2');\n CharacterSetECI.ISO8859_3 = new CharacterSetECI(CharacterSetValueIdentifiers.ISO8859_3, 5, 'ISO-8859-3', 'ISO88593', 'ISO8859_3');\n CharacterSetECI.ISO8859_4 = new CharacterSetECI(CharacterSetValueIdentifiers.ISO8859_4, 6, 'ISO-8859-4', 'ISO88594', 'ISO8859_4');\n CharacterSetECI.ISO8859_5 = new CharacterSetECI(CharacterSetValueIdentifiers.ISO8859_5, 7, 'ISO-8859-5', 'ISO88595', 'ISO8859_5');\n CharacterSetECI.ISO8859_6 = new CharacterSetECI(CharacterSetValueIdentifiers.ISO8859_6, 8, 'ISO-8859-6', 'ISO88596', 'ISO8859_6');\n CharacterSetECI.ISO8859_7 = new CharacterSetECI(CharacterSetValueIdentifiers.ISO8859_7, 9, 'ISO-8859-7', 'ISO88597', 'ISO8859_7');\n CharacterSetECI.ISO8859_8 = new CharacterSetECI(CharacterSetValueIdentifiers.ISO8859_8, 10, 'ISO-8859-8', 'ISO88598', 'ISO8859_8');\n CharacterSetECI.ISO8859_9 = new CharacterSetECI(CharacterSetValueIdentifiers.ISO8859_9, 11, 'ISO-8859-9', 'ISO88599', 'ISO8859_9');\n CharacterSetECI.ISO8859_10 = new CharacterSetECI(CharacterSetValueIdentifiers.ISO8859_10, 12, 'ISO-8859-10', 'ISO885910', 'ISO8859_10');\n CharacterSetECI.ISO8859_11 = new CharacterSetECI(CharacterSetValueIdentifiers.ISO8859_11, 13, 'ISO-8859-11', 'ISO885911', 'ISO8859_11');\n CharacterSetECI.ISO8859_13 = new CharacterSetECI(CharacterSetValueIdentifiers.ISO8859_13, 15, 'ISO-8859-13', 'ISO885913', 'ISO8859_13');\n CharacterSetECI.ISO8859_14 = new CharacterSetECI(CharacterSetValueIdentifiers.ISO8859_14, 16, 'ISO-8859-14', 'ISO885914', 'ISO8859_14');\n CharacterSetECI.ISO8859_15 = new CharacterSetECI(CharacterSetValueIdentifiers.ISO8859_15, 17, 'ISO-8859-15', 'ISO885915', 'ISO8859_15');\n CharacterSetECI.ISO8859_16 = new CharacterSetECI(CharacterSetValueIdentifiers.ISO8859_16, 18, 'ISO-8859-16', 'ISO885916', 'ISO8859_16');\n CharacterSetECI.SJIS = new CharacterSetECI(CharacterSetValueIdentifiers.SJIS, 20, 'SJIS', 'Shift_JIS');\n CharacterSetECI.Cp1250 = new CharacterSetECI(CharacterSetValueIdentifiers.Cp1250, 21, 'Cp1250', 'windows-1250');\n CharacterSetECI.Cp1251 = new CharacterSetECI(CharacterSetValueIdentifiers.Cp1251, 22, 'Cp1251', 'windows-1251');\n CharacterSetECI.Cp1252 = new CharacterSetECI(CharacterSetValueIdentifiers.Cp1252, 23, 'Cp1252', 'windows-1252');\n CharacterSetECI.Cp1256 = new CharacterSetECI(CharacterSetValueIdentifiers.Cp1256, 24, 'Cp1256', 'windows-1256');\n CharacterSetECI.UnicodeBigUnmarked = new CharacterSetECI(CharacterSetValueIdentifiers.UnicodeBigUnmarked, 25, 'UnicodeBigUnmarked', 'UTF-16BE', 'UnicodeBig');\n CharacterSetECI.UTF8 = new CharacterSetECI(CharacterSetValueIdentifiers.UTF8, 26, 'UTF8', 'UTF-8');\n CharacterSetECI.ASCII = new CharacterSetECI(CharacterSetValueIdentifiers.ASCII, Int32Array.from([27, 170]), 'ASCII', 'US-ASCII');\n CharacterSetECI.Big5 = new CharacterSetECI(CharacterSetValueIdentifiers.Big5, 28, 'Big5');\n CharacterSetECI.GB18030 = new CharacterSetECI(CharacterSetValueIdentifiers.GB18030, 29, 'GB18030', 'GB2312', 'EUC_CN', 'GBK');\n CharacterSetECI.EUC_KR = new CharacterSetECI(CharacterSetValueIdentifiers.EUC_KR, 30, 'EUC_KR', 'EUC-KR');\n\n /**\n * Custom Error class of type Exception.\n */\n class UnsupportedOperationException extends Exception {\n }\n UnsupportedOperationException.kind = 'UnsupportedOperationException';\n\n /**\n * Responsible for en/decoding strings.\n */\n class StringEncoding {\n /**\n * Decodes some Uint8Array to a string format.\n */\n static decode(bytes, encoding) {\n const encodingName = this.encodingName(encoding);\n if (this.customDecoder) {\n return this.customDecoder(bytes, encodingName);\n }\n // Increases browser support.\n if (typeof TextDecoder === 'undefined' || this.shouldDecodeOnFallback(encodingName)) {\n return this.decodeFallback(bytes, encodingName);\n }\n return new TextDecoder(encodingName).decode(bytes);\n }\n /**\n * Checks if the decoding method should use the fallback for decoding\n * once Node TextDecoder doesn't support all encoding formats.\n *\n * @param encodingName\n */\n static shouldDecodeOnFallback(encodingName) {\n return !StringEncoding.isBrowser() && encodingName === 'ISO-8859-1';\n }\n /**\n * Encodes some string into a Uint8Array.\n */\n static encode(s, encoding) {\n const encodingName = this.encodingName(encoding);\n if (this.customEncoder) {\n return this.customEncoder(s, encodingName);\n }\n // Increases browser support.\n if (typeof TextEncoder === 'undefined') {\n return this.encodeFallback(s);\n }\n // TextEncoder only encodes to UTF8 by default as specified by encoding.spec.whatwg.org\n return new TextEncoder().encode(s);\n }\n static isBrowser() {\n return (typeof window !== 'undefined' && {}.toString.call(window) === '[object Window]');\n }\n /**\n * Returns the string value from some encoding character set.\n */\n static encodingName(encoding) {\n return typeof encoding === 'string'\n ? encoding\n : encoding.getName();\n }\n /**\n * Returns character set from some encoding character set.\n */\n static encodingCharacterSet(encoding) {\n if (encoding instanceof CharacterSetECI) {\n return encoding;\n }\n return CharacterSetECI.getCharacterSetECIByName(encoding);\n }\n /**\n * Runs a fallback for the native decoding funcion.\n */\n static decodeFallback(bytes, encoding) {\n const characterSet = this.encodingCharacterSet(encoding);\n if (StringEncoding.isDecodeFallbackSupported(characterSet)) {\n let s = '';\n for (let i = 0, length = bytes.length; i < length; i++) {\n let h = bytes[i].toString(16);\n if (h.length < 2) {\n h = '0' + h;\n }\n s += '%' + h;\n }\n return decodeURIComponent(s);\n }\n if (characterSet.equals(CharacterSetECI.UnicodeBigUnmarked)) {\n return String.fromCharCode.apply(null, new Uint16Array(bytes.buffer));\n }\n throw new UnsupportedOperationException(`Encoding ${this.encodingName(encoding)} not supported by fallback.`);\n }\n static isDecodeFallbackSupported(characterSet) {\n return characterSet.equals(CharacterSetECI.UTF8) ||\n characterSet.equals(CharacterSetECI.ISO8859_1) ||\n characterSet.equals(CharacterSetECI.ASCII);\n }\n /**\n * Runs a fallback for the native encoding funcion.\n *\n * @see https://stackoverflow.com/a/17192845/4367683\n */\n static encodeFallback(s) {\n const encodedURIstring = btoa(unescape(encodeURIComponent(s)));\n const charList = encodedURIstring.split('');\n const uintArray = [];\n for (let i = 0; i < charList.length; i++) {\n uintArray.push(charList[i].charCodeAt(0));\n }\n return new Uint8Array(uintArray);\n }\n }\n\n /*\n * Copyright (C) 2010 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n /**\n * Common string-related functions.\n *\n * @author Sean Owen\n * @author Alex Dupre\n */\n class StringUtils {\n // SHIFT_JIS.equalsIgnoreCase(PLATFORM_DEFAULT_ENCODING) ||\n // EUC_JP.equalsIgnoreCase(PLATFORM_DEFAULT_ENCODING);\n static castAsNonUtf8Char(code, encoding = null) {\n // ISO 8859-1 is the Java default as UTF-8 is JavaScripts\n // you can see this method as a Java version of String.fromCharCode\n const e = encoding ? encoding.getName() : this.ISO88591;\n // use passed format (fromCharCode will return UTF8 encoding)\n return StringEncoding.decode(new Uint8Array([code]), e);\n }\n /**\n * @param bytes bytes encoding a string, whose encoding should be guessed\n * @param hints decode hints if applicable\n * @return name of guessed encoding; at the moment will only guess one of:\n * {@link #SHIFT_JIS}, {@link #UTF8}, {@link #ISO88591}, or the platform\n * default encoding if none of these can possibly be correct\n */\n static guessEncoding(bytes, hints) {\n if (hints !== null && hints !== undefined && undefined !== hints.get(DecodeHintType$1.CHARACTER_SET)) {\n return hints.get(DecodeHintType$1.CHARACTER_SET).toString();\n }\n // For now, merely tries to distinguish ISO-8859-1, UTF-8 and Shift_JIS,\n // which should be by far the most common encodings.\n const length = bytes.length;\n let canBeISO88591 = true;\n let canBeShiftJIS = true;\n let canBeUTF8 = true;\n let utf8BytesLeft = 0;\n // int utf8LowChars = 0\n let utf2BytesChars = 0;\n let utf3BytesChars = 0;\n let utf4BytesChars = 0;\n let sjisBytesLeft = 0;\n // int sjisLowChars = 0\n let sjisKatakanaChars = 0;\n // int sjisDoubleBytesChars = 0\n let sjisCurKatakanaWordLength = 0;\n let sjisCurDoubleBytesWordLength = 0;\n let sjisMaxKatakanaWordLength = 0;\n let sjisMaxDoubleBytesWordLength = 0;\n // int isoLowChars = 0\n // int isoHighChars = 0\n let isoHighOther = 0;\n const utf8bom = bytes.length > 3 &&\n bytes[0] === /*(byte) */ 0xEF &&\n bytes[1] === /*(byte) */ 0xBB &&\n bytes[2] === /*(byte) */ 0xBF;\n for (let i = 0; i < length && (canBeISO88591 || canBeShiftJIS || canBeUTF8); i++) {\n const value = bytes[i] & 0xFF;\n // UTF-8 stuff\n if (canBeUTF8) {\n if (utf8BytesLeft > 0) {\n if ((value & 0x80) === 0) {\n canBeUTF8 = false;\n }\n else {\n utf8BytesLeft--;\n }\n }\n else if ((value & 0x80) !== 0) {\n if ((value & 0x40) === 0) {\n canBeUTF8 = false;\n }\n else {\n utf8BytesLeft++;\n if ((value & 0x20) === 0) {\n utf2BytesChars++;\n }\n else {\n utf8BytesLeft++;\n if ((value & 0x10) === 0) {\n utf3BytesChars++;\n }\n else {\n utf8BytesLeft++;\n if ((value & 0x08) === 0) {\n utf4BytesChars++;\n }\n else {\n canBeUTF8 = false;\n }\n }\n }\n }\n } // else {\n // utf8LowChars++\n // }\n }\n // ISO-8859-1 stuff\n if (canBeISO88591) {\n if (value > 0x7F && value < 0xA0) {\n canBeISO88591 = false;\n }\n else if (value > 0x9F) {\n if (value < 0xC0 || value === 0xD7 || value === 0xF7) {\n isoHighOther++;\n } // else {\n // isoHighChars++\n // }\n } // else {\n // isoLowChars++\n // }\n }\n // Shift_JIS stuff\n if (canBeShiftJIS) {\n if (sjisBytesLeft > 0) {\n if (value < 0x40 || value === 0x7F || value > 0xFC) {\n canBeShiftJIS = false;\n }\n else {\n sjisBytesLeft--;\n }\n }\n else if (value === 0x80 || value === 0xA0 || value > 0xEF) {\n canBeShiftJIS = false;\n }\n else if (value > 0xA0 && value < 0xE0) {\n sjisKatakanaChars++;\n sjisCurDoubleBytesWordLength = 0;\n sjisCurKatakanaWordLength++;\n if (sjisCurKatakanaWordLength > sjisMaxKatakanaWordLength) {\n sjisMaxKatakanaWordLength = sjisCurKatakanaWordLength;\n }\n }\n else if (value > 0x7F) {\n sjisBytesLeft++;\n // sjisDoubleBytesChars++\n sjisCurKatakanaWordLength = 0;\n sjisCurDoubleBytesWordLength++;\n if (sjisCurDoubleBytesWordLength > sjisMaxDoubleBytesWordLength) {\n sjisMaxDoubleBytesWordLength = sjisCurDoubleBytesWordLength;\n }\n }\n else {\n // sjisLowChars++\n sjisCurKatakanaWordLength = 0;\n sjisCurDoubleBytesWordLength = 0;\n }\n }\n }\n if (canBeUTF8 && utf8BytesLeft > 0) {\n canBeUTF8 = false;\n }\n if (canBeShiftJIS && sjisBytesLeft > 0) {\n canBeShiftJIS = false;\n }\n // Easy -- if there is BOM or at least 1 valid not-single byte character (and no evidence it can't be UTF-8), done\n if (canBeUTF8 && (utf8bom || utf2BytesChars + utf3BytesChars + utf4BytesChars > 0)) {\n return StringUtils.UTF8;\n }\n // Easy -- if assuming Shift_JIS or at least 3 valid consecutive not-ascii characters (and no evidence it can't be), done\n if (canBeShiftJIS && (StringUtils.ASSUME_SHIFT_JIS || sjisMaxKatakanaWordLength >= 3 || sjisMaxDoubleBytesWordLength >= 3)) {\n return StringUtils.SHIFT_JIS;\n }\n // Distinguishing Shift_JIS and ISO-8859-1 can be a little tough for short words. The crude heuristic is:\n // - If we saw\n // - only two consecutive katakana chars in the whole text, or\n // - at least 10% of bytes that could be \"upper\" not-alphanumeric Latin1,\n // - then we conclude Shift_JIS, else ISO-8859-1\n if (canBeISO88591 && canBeShiftJIS) {\n return (sjisMaxKatakanaWordLength === 2 && sjisKatakanaChars === 2) || isoHighOther * 10 >= length\n ? StringUtils.SHIFT_JIS : StringUtils.ISO88591;\n }\n // Otherwise, try in order ISO-8859-1, Shift JIS, UTF-8 and fall back to default platform encoding\n if (canBeISO88591) {\n return StringUtils.ISO88591;\n }\n if (canBeShiftJIS) {\n return StringUtils.SHIFT_JIS;\n }\n if (canBeUTF8) {\n return StringUtils.UTF8;\n }\n // Otherwise, we take a wild guess with platform encoding\n return StringUtils.PLATFORM_DEFAULT_ENCODING;\n }\n /**\n *\n * @see https://stackoverflow.com/a/13439711/4367683\n *\n * @param append The new string to append.\n * @param args Argumets values to be formated.\n */\n static format(append, ...args) {\n let i = -1;\n function callback(exp, p0, p1, p2, p3, p4) {\n if (exp === '%%')\n return '%';\n if (args[++i] === undefined)\n return undefined;\n exp = p2 ? parseInt(p2.substr(1)) : undefined;\n let base = p3 ? parseInt(p3.substr(1)) : undefined;\n let val;\n switch (p4) {\n case 's':\n val = args[i];\n break;\n case 'c':\n val = args[i][0];\n break;\n case 'f':\n val = parseFloat(args[i]).toFixed(exp);\n break;\n case 'p':\n val = parseFloat(args[i]).toPrecision(exp);\n break;\n case 'e':\n val = parseFloat(args[i]).toExponential(exp);\n break;\n case 'x':\n val = parseInt(args[i]).toString(base ? base : 16);\n break;\n case 'd':\n val = parseFloat(parseInt(args[i], base ? base : 10).toPrecision(exp)).toFixed(0);\n break;\n }\n val = typeof val === 'object' ? JSON.stringify(val) : (+val).toString(base);\n let size = parseInt(p1); /* padding size */\n let ch = p1 && (p1[0] + '') === '0' ? '0' : ' '; /* isnull? */\n while (val.length < size)\n val = p0 !== undefined ? val + ch : ch + val; /* isminus? */\n return val;\n }\n let regex = /%(-)?(0?[0-9]+)?([.][0-9]+)?([#][0-9]+)?([scfpexd%])/g;\n return append.replace(regex, callback);\n }\n /**\n *\n */\n static getBytes(str, encoding) {\n return StringEncoding.encode(str, encoding);\n }\n /**\n * Returns the charcode at the specified index or at index zero.\n */\n static getCharCode(str, index = 0) {\n return str.charCodeAt(index);\n }\n /**\n * Returns char for given charcode\n */\n static getCharAt(charCode) {\n return String.fromCharCode(charCode);\n }\n }\n StringUtils.SHIFT_JIS = CharacterSetECI.SJIS.getName(); // \"SJIS\"\n StringUtils.GB2312 = 'GB2312';\n StringUtils.ISO88591 = CharacterSetECI.ISO8859_1.getName(); // \"ISO8859_1\"\n StringUtils.EUC_JP = 'EUC_JP';\n StringUtils.UTF8 = CharacterSetECI.UTF8.getName(); // \"UTF8\"\n StringUtils.PLATFORM_DEFAULT_ENCODING = StringUtils.UTF8; // \"UTF8\"//Charset.defaultCharset().name()\n StringUtils.ASSUME_SHIFT_JIS = false;\n\n class StringBuilder {\n constructor(value = '') {\n this.value = value;\n }\n enableDecoding(encoding) {\n this.encoding = encoding;\n return this;\n }\n append(s) {\n if (typeof s === 'string') {\n this.value += s.toString();\n }\n else if (this.encoding) {\n // use passed format (fromCharCode will return UTF8 encoding)\n this.value += StringUtils.castAsNonUtf8Char(s, this.encoding);\n }\n else {\n // correctly converts from UTF-8, but not other encodings\n this.value += String.fromCharCode(s);\n }\n return this;\n }\n appendChars(str, offset, len) {\n for (let i = offset; offset < offset + len; i++) {\n this.append(str[i]);\n }\n return this;\n }\n length() {\n return this.value.length;\n }\n charAt(n) {\n return this.value.charAt(n);\n }\n deleteCharAt(n) {\n this.value = this.value.substr(0, n) + this.value.substring(n + 1);\n }\n setCharAt(n, c) {\n this.value = this.value.substr(0, n) + c + this.value.substr(n + 1);\n }\n substring(start, end) {\n return this.value.substring(start, end);\n }\n /**\n * @note helper method for RSS Expanded\n */\n setLengthToZero() {\n this.value = '';\n }\n toString() {\n return this.value;\n }\n insert(n, c) {\n this.value = this.value.substr(0, n) + c + this.value.substr(n + c.length);\n }\n }\n\n /*\n * Copyright 2007 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n /**\n *

Represents a 2D matrix of bits. In function arguments below, and throughout the common\n * module, x is the column position, and y is the row position. The ordering is always x, y.\n * The origin is at the top-left.

\n *\n *

Internally the bits are represented in a 1-D array of 32-bit ints. However, each row begins\n * with a new int. This is done intentionally so that we can copy out a row into a BitArray very\n * efficiently.

\n *\n *

The ordering of bits is row-major. Within each int, the least significant bits are used first,\n * meaning they represent lower x values. This is compatible with BitArray's implementation.

\n *\n * @author Sean Owen\n * @author dswitkin@google.com (Daniel Switkin)\n */\n class BitMatrix /*implements Cloneable*/ {\n /**\n * Creates an empty square {@link BitMatrix}.\n *\n * @param dimension height and width\n */\n // public constructor(dimension: number /*int*/) {\n // this(dimension, dimension)\n // }\n /**\n * Creates an empty {@link BitMatrix}.\n *\n * @param width bit matrix width\n * @param height bit matrix height\n */\n // public constructor(width: number /*int*/, height: number /*int*/) {\n // if (width < 1 || height < 1) {\n // throw new IllegalArgumentException(\"Both dimensions must be greater than 0\")\n // }\n // this.width = width\n // this.height = height\n // this.rowSize = (width + 31) / 32\n // bits = new int[rowSize * height];\n // }\n constructor(width /*int*/, height /*int*/, rowSize /*int*/, bits) {\n this.width = width;\n this.height = height;\n this.rowSize = rowSize;\n this.bits = bits;\n if (undefined === height || null === height) {\n height = width;\n }\n this.height = height;\n if (width < 1 || height < 1) {\n throw new IllegalArgumentException('Both dimensions must be greater than 0');\n }\n if (undefined === rowSize || null === rowSize) {\n rowSize = Math.floor((width + 31) / 32);\n }\n this.rowSize = rowSize;\n if (undefined === bits || null === bits) {\n this.bits = new Int32Array(this.rowSize * this.height);\n }\n }\n /**\n * Interprets a 2D array of booleans as a {@link BitMatrix}, where \"true\" means an \"on\" bit.\n *\n * @function parse\n * @param image bits of the image, as a row-major 2D array. Elements are arrays representing rows\n * @return {@link BitMatrix} representation of image\n */\n static parseFromBooleanArray(image) {\n const height = image.length;\n const width = image[0].length;\n const bits = new BitMatrix(width, height);\n for (let i = 0; i < height; i++) {\n const imageI = image[i];\n for (let j = 0; j < width; j++) {\n if (imageI[j]) {\n bits.set(j, i);\n }\n }\n }\n return bits;\n }\n /**\n *\n * @function parse\n * @param stringRepresentation\n * @param setString\n * @param unsetString\n */\n static parseFromString(stringRepresentation, setString, unsetString) {\n if (stringRepresentation === null) {\n throw new IllegalArgumentException('stringRepresentation cannot be null');\n }\n const bits = new Array(stringRepresentation.length);\n let bitsPos = 0;\n let rowStartPos = 0;\n let rowLength = -1;\n let nRows = 0;\n let pos = 0;\n while (pos < stringRepresentation.length) {\n if (stringRepresentation.charAt(pos) === '\\n' ||\n stringRepresentation.charAt(pos) === '\\r') {\n if (bitsPos > rowStartPos) {\n if (rowLength === -1) {\n rowLength = bitsPos - rowStartPos;\n }\n else if (bitsPos - rowStartPos !== rowLength) {\n throw new IllegalArgumentException('row lengths do not match');\n }\n rowStartPos = bitsPos;\n nRows++;\n }\n pos++;\n }\n else if (stringRepresentation.substring(pos, pos + setString.length) === setString) {\n pos += setString.length;\n bits[bitsPos] = true;\n bitsPos++;\n }\n else if (stringRepresentation.substring(pos, pos + unsetString.length) === unsetString) {\n pos += unsetString.length;\n bits[bitsPos] = false;\n bitsPos++;\n }\n else {\n throw new IllegalArgumentException('illegal character encountered: ' + stringRepresentation.substring(pos));\n }\n }\n // no EOL at end?\n if (bitsPos > rowStartPos) {\n if (rowLength === -1) {\n rowLength = bitsPos - rowStartPos;\n }\n else if (bitsPos - rowStartPos !== rowLength) {\n throw new IllegalArgumentException('row lengths do not match');\n }\n nRows++;\n }\n const matrix = new BitMatrix(rowLength, nRows);\n for (let i = 0; i < bitsPos; i++) {\n if (bits[i]) {\n matrix.set(Math.floor(i % rowLength), Math.floor(i / rowLength));\n }\n }\n return matrix;\n }\n /**\n *

Gets the requested bit, where true means black.

\n *\n * @param x The horizontal component (i.e. which column)\n * @param y The vertical component (i.e. which row)\n * @return value of given bit in matrix\n */\n get(x /*int*/, y /*int*/) {\n const offset = y * this.rowSize + Math.floor(x / 32);\n return ((this.bits[offset] >>> (x & 0x1f)) & 1) !== 0;\n }\n /**\n *

Sets the given bit to true.

\n *\n * @param x The horizontal component (i.e. which column)\n * @param y The vertical component (i.e. which row)\n */\n set(x /*int*/, y /*int*/) {\n const offset = y * this.rowSize + Math.floor(x / 32);\n this.bits[offset] |= (1 << (x & 0x1f)) & 0xFFFFFFFF;\n }\n unset(x /*int*/, y /*int*/) {\n const offset = y * this.rowSize + Math.floor(x / 32);\n this.bits[offset] &= ~((1 << (x & 0x1f)) & 0xFFFFFFFF);\n }\n /**\n *

Flips the given bit.

\n *\n * @param x The horizontal component (i.e. which column)\n * @param y The vertical component (i.e. which row)\n */\n flip(x /*int*/, y /*int*/) {\n const offset = y * this.rowSize + Math.floor(x / 32);\n this.bits[offset] ^= ((1 << (x & 0x1f)) & 0xFFFFFFFF);\n }\n /**\n * Exclusive-or (XOR): Flip the bit in this {@code BitMatrix} if the corresponding\n * mask bit is set.\n *\n * @param mask XOR mask\n */\n xor(mask) {\n if (this.width !== mask.getWidth() || this.height !== mask.getHeight()\n || this.rowSize !== mask.getRowSize()) {\n throw new IllegalArgumentException('input matrix dimensions do not match');\n }\n const rowArray = new BitArray(Math.floor(this.width / 32) + 1);\n const rowSize = this.rowSize;\n const bits = this.bits;\n for (let y = 0, height = this.height; y < height; y++) {\n const offset = y * rowSize;\n const row = mask.getRow(y, rowArray).getBitArray();\n for (let x = 0; x < rowSize; x++) {\n bits[offset + x] ^= row[x];\n }\n }\n }\n /**\n * Clears all bits (sets to false).\n */\n clear() {\n const bits = this.bits;\n const max = bits.length;\n for (let i = 0; i < max; i++) {\n bits[i] = 0;\n }\n }\n /**\n *

Sets a square region of the bit matrix to true.

\n *\n * @param left The horizontal position to begin at (inclusive)\n * @param top The vertical position to begin at (inclusive)\n * @param width The width of the region\n * @param height The height of the region\n */\n setRegion(left /*int*/, top /*int*/, width /*int*/, height /*int*/) {\n if (top < 0 || left < 0) {\n throw new IllegalArgumentException('Left and top must be nonnegative');\n }\n if (height < 1 || width < 1) {\n throw new IllegalArgumentException('Height and width must be at least 1');\n }\n const right = left + width;\n const bottom = top + height;\n if (bottom > this.height || right > this.width) {\n throw new IllegalArgumentException('The region must fit inside the matrix');\n }\n const rowSize = this.rowSize;\n const bits = this.bits;\n for (let y = top; y < bottom; y++) {\n const offset = y * rowSize;\n for (let x = left; x < right; x++) {\n bits[offset + Math.floor(x / 32)] |= ((1 << (x & 0x1f)) & 0xFFFFFFFF);\n }\n }\n }\n /**\n * A fast method to retrieve one row of data from the matrix as a BitArray.\n *\n * @param y The row to retrieve\n * @param row An optional caller-allocated BitArray, will be allocated if null or too small\n * @return The resulting BitArray - this reference should always be used even when passing\n * your own row\n */\n getRow(y /*int*/, row) {\n if (row === null || row === undefined || row.getSize() < this.width) {\n row = new BitArray(this.width);\n }\n else {\n row.clear();\n }\n const rowSize = this.rowSize;\n const bits = this.bits;\n const offset = y * rowSize;\n for (let x = 0; x < rowSize; x++) {\n row.setBulk(x * 32, bits[offset + x]);\n }\n return row;\n }\n /**\n * @param y row to set\n * @param row {@link BitArray} to copy from\n */\n setRow(y /*int*/, row) {\n System.arraycopy(row.getBitArray(), 0, this.bits, y * this.rowSize, this.rowSize);\n }\n /**\n * Modifies this {@code BitMatrix} to represent the same but rotated 180 degrees\n */\n rotate180() {\n const width = this.getWidth();\n const height = this.getHeight();\n let topRow = new BitArray(width);\n let bottomRow = new BitArray(width);\n for (let i = 0, length = Math.floor((height + 1) / 2); i < length; i++) {\n topRow = this.getRow(i, topRow);\n bottomRow = this.getRow(height - 1 - i, bottomRow);\n topRow.reverse();\n bottomRow.reverse();\n this.setRow(i, bottomRow);\n this.setRow(height - 1 - i, topRow);\n }\n }\n /**\n * This is useful in detecting the enclosing rectangle of a 'pure' barcode.\n *\n * @return {@code left,top,width,height} enclosing rectangle of all 1 bits, or null if it is all white\n */\n getEnclosingRectangle() {\n const width = this.width;\n const height = this.height;\n const rowSize = this.rowSize;\n const bits = this.bits;\n let left = width;\n let top = height;\n let right = -1;\n let bottom = -1;\n for (let y = 0; y < height; y++) {\n for (let x32 = 0; x32 < rowSize; x32++) {\n const theBits = bits[y * rowSize + x32];\n if (theBits !== 0) {\n if (y < top) {\n top = y;\n }\n if (y > bottom) {\n bottom = y;\n }\n if (x32 * 32 < left) {\n let bit = 0;\n while (((theBits << (31 - bit)) & 0xFFFFFFFF) === 0) {\n bit++;\n }\n if ((x32 * 32 + bit) < left) {\n left = x32 * 32 + bit;\n }\n }\n if (x32 * 32 + 31 > right) {\n let bit = 31;\n while ((theBits >>> bit) === 0) {\n bit--;\n }\n if ((x32 * 32 + bit) > right) {\n right = x32 * 32 + bit;\n }\n }\n }\n }\n }\n if (right < left || bottom < top) {\n return null;\n }\n return Int32Array.from([left, top, right - left + 1, bottom - top + 1]);\n }\n /**\n * This is useful in detecting a corner of a 'pure' barcode.\n *\n * @return {@code x,y} coordinate of top-left-most 1 bit, or null if it is all white\n */\n getTopLeftOnBit() {\n const rowSize = this.rowSize;\n const bits = this.bits;\n let bitsOffset = 0;\n while (bitsOffset < bits.length && bits[bitsOffset] === 0) {\n bitsOffset++;\n }\n if (bitsOffset === bits.length) {\n return null;\n }\n const y = bitsOffset / rowSize;\n let x = (bitsOffset % rowSize) * 32;\n const theBits = bits[bitsOffset];\n let bit = 0;\n while (((theBits << (31 - bit)) & 0xFFFFFFFF) === 0) {\n bit++;\n }\n x += bit;\n return Int32Array.from([x, y]);\n }\n getBottomRightOnBit() {\n const rowSize = this.rowSize;\n const bits = this.bits;\n let bitsOffset = bits.length - 1;\n while (bitsOffset >= 0 && bits[bitsOffset] === 0) {\n bitsOffset--;\n }\n if (bitsOffset < 0) {\n return null;\n }\n const y = Math.floor(bitsOffset / rowSize);\n let x = Math.floor(bitsOffset % rowSize) * 32;\n const theBits = bits[bitsOffset];\n let bit = 31;\n while ((theBits >>> bit) === 0) {\n bit--;\n }\n x += bit;\n return Int32Array.from([x, y]);\n }\n /**\n * @return The width of the matrix\n */\n getWidth() {\n return this.width;\n }\n /**\n * @return The height of the matrix\n */\n getHeight() {\n return this.height;\n }\n /**\n * @return The row size of the matrix\n */\n getRowSize() {\n return this.rowSize;\n }\n /*@Override*/\n equals(o) {\n if (!(o instanceof BitMatrix)) {\n return false;\n }\n const other = o;\n return this.width === other.width && this.height === other.height && this.rowSize === other.rowSize &&\n Arrays.equals(this.bits, other.bits);\n }\n /*@Override*/\n hashCode() {\n let hash = this.width;\n hash = 31 * hash + this.width;\n hash = 31 * hash + this.height;\n hash = 31 * hash + this.rowSize;\n hash = 31 * hash + Arrays.hashCode(this.bits);\n return hash;\n }\n /**\n * @return string representation using \"X\" for set and \" \" for unset bits\n */\n /*@Override*/\n // public toString(): string {\n // return toString(\": \"X, \" \")\n // }\n /**\n * @param setString representation of a set bit\n * @param unsetString representation of an unset bit\n * @return string representation of entire matrix utilizing given strings\n */\n // public toString(setString: string = \"X \", unsetString: string = \" \"): string {\n // return this.buildToString(setString, unsetString, \"\\n\")\n // }\n /**\n * @param setString representation of a set bit\n * @param unsetString representation of an unset bit\n * @param lineSeparator newline character in string representation\n * @return string representation of entire matrix utilizing given strings and line separator\n * @deprecated call {@link #toString(String,String)} only, which uses \\n line separator always\n */\n // @Deprecated\n toString(setString = 'X ', unsetString = ' ', lineSeparator = '\\n') {\n return this.buildToString(setString, unsetString, lineSeparator);\n }\n buildToString(setString, unsetString, lineSeparator) {\n let result = new StringBuilder();\n // result.append(lineSeparator);\n for (let y = 0, height = this.height; y < height; y++) {\n for (let x = 0, width = this.width; x < width; x++) {\n result.append(this.get(x, y) ? setString : unsetString);\n }\n result.append(lineSeparator);\n }\n return result.toString();\n }\n /*@Override*/\n clone() {\n return new BitMatrix(this.width, this.height, this.rowSize, this.bits.slice());\n }\n }\n\n /**\n * Custom Error class of type Exception.\n */\n class NotFoundException extends Exception {\n static getNotFoundInstance() {\n return new NotFoundException();\n }\n }\n NotFoundException.kind = 'NotFoundException';\n\n /*\n * Copyright 2009 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n /**\n * This Binarizer implementation uses the old ZXing global histogram approach. It is suitable\n * for low-end mobile devices which don't have enough CPU or memory to use a local thresholding\n * algorithm. However, because it picks a global black point, it cannot handle difficult shadows\n * and gradients.\n *\n * Faster mobile devices and all desktop applications should probably use HybridBinarizer instead.\n *\n * @author dswitkin@google.com (Daniel Switkin)\n * @author Sean Owen\n */\n class GlobalHistogramBinarizer extends Binarizer {\n constructor(source) {\n super(source);\n this.luminances = GlobalHistogramBinarizer.EMPTY;\n this.buckets = new Int32Array(GlobalHistogramBinarizer.LUMINANCE_BUCKETS);\n }\n // Applies simple sharpening to the row data to improve performance of the 1D Readers.\n /*@Override*/\n getBlackRow(y /*int*/, row) {\n const source = this.getLuminanceSource();\n const width = source.getWidth();\n if (row === undefined || row === null || row.getSize() < width) {\n row = new BitArray(width);\n }\n else {\n row.clear();\n }\n this.initArrays(width);\n const localLuminances = source.getRow(y, this.luminances);\n const localBuckets = this.buckets;\n for (let x = 0; x < width; x++) {\n localBuckets[(localLuminances[x] & 0xff) >> GlobalHistogramBinarizer.LUMINANCE_SHIFT]++;\n }\n const blackPoint = GlobalHistogramBinarizer.estimateBlackPoint(localBuckets);\n if (width < 3) {\n // Special case for very small images\n for (let x = 0; x < width; x++) {\n if ((localLuminances[x] & 0xff) < blackPoint) {\n row.set(x);\n }\n }\n }\n else {\n let left = localLuminances[0] & 0xff;\n let center = localLuminances[1] & 0xff;\n for (let x = 1; x < width - 1; x++) {\n const right = localLuminances[x + 1] & 0xff;\n // A simple -1 4 -1 box filter with a weight of 2.\n if (((center * 4) - left - right) / 2 < blackPoint) {\n row.set(x);\n }\n left = center;\n center = right;\n }\n }\n return row;\n }\n // Does not sharpen the data, as this call is intended to only be used by 2D Readers.\n /*@Override*/\n getBlackMatrix() {\n const source = this.getLuminanceSource();\n const width = source.getWidth();\n const height = source.getHeight();\n const matrix = new BitMatrix(width, height);\n // Quickly calculates the histogram by sampling four rows from the image. This proved to be\n // more robust on the blackbox tests than sampling a diagonal as we used to do.\n this.initArrays(width);\n const localBuckets = this.buckets;\n for (let y = 1; y < 5; y++) {\n const row = Math.floor((height * y) / 5);\n const localLuminances = source.getRow(row, this.luminances);\n const right = Math.floor((width * 4) / 5);\n for (let x = Math.floor(width / 5); x < right; x++) {\n const pixel = localLuminances[x] & 0xff;\n localBuckets[pixel >> GlobalHistogramBinarizer.LUMINANCE_SHIFT]++;\n }\n }\n const blackPoint = GlobalHistogramBinarizer.estimateBlackPoint(localBuckets);\n // We delay reading the entire image luminance until the black point estimation succeeds.\n // Although we end up reading four rows twice, it is consistent with our motto of\n // \"fail quickly\" which is necessary for continuous scanning.\n const localLuminances = source.getMatrix();\n for (let y = 0; y < height; y++) {\n const offset = y * width;\n for (let x = 0; x < width; x++) {\n const pixel = localLuminances[offset + x] & 0xff;\n if (pixel < blackPoint) {\n matrix.set(x, y);\n }\n }\n }\n return matrix;\n }\n /*@Override*/\n createBinarizer(source) {\n return new GlobalHistogramBinarizer(source);\n }\n initArrays(luminanceSize /*int*/) {\n if (this.luminances.length < luminanceSize) {\n this.luminances = new Uint8ClampedArray(luminanceSize);\n }\n const buckets = this.buckets;\n for (let x = 0; x < GlobalHistogramBinarizer.LUMINANCE_BUCKETS; x++) {\n buckets[x] = 0;\n }\n }\n static estimateBlackPoint(buckets) {\n // Find the tallest peak in the histogram.\n const numBuckets = buckets.length;\n let maxBucketCount = 0;\n let firstPeak = 0;\n let firstPeakSize = 0;\n for (let x = 0; x < numBuckets; x++) {\n if (buckets[x] > firstPeakSize) {\n firstPeak = x;\n firstPeakSize = buckets[x];\n }\n if (buckets[x] > maxBucketCount) {\n maxBucketCount = buckets[x];\n }\n }\n // Find the second-tallest peak which is somewhat far from the tallest peak.\n let secondPeak = 0;\n let secondPeakScore = 0;\n for (let x = 0; x < numBuckets; x++) {\n const distanceToBiggest = x - firstPeak;\n // Encourage more distant second peaks by multiplying by square of distance.\n const score = buckets[x] * distanceToBiggest * distanceToBiggest;\n if (score > secondPeakScore) {\n secondPeak = x;\n secondPeakScore = score;\n }\n }\n // Make sure firstPeak corresponds to the black peak.\n if (firstPeak > secondPeak) {\n const temp = firstPeak;\n firstPeak = secondPeak;\n secondPeak = temp;\n }\n // If there is too little contrast in the image to pick a meaningful black point, throw rather\n // than waste time trying to decode the image, and risk false positives.\n if (secondPeak - firstPeak <= numBuckets / 16) {\n throw new NotFoundException();\n }\n // Find a valley between them that is low and closer to the white peak.\n let bestValley = secondPeak - 1;\n let bestValleyScore = -1;\n for (let x = secondPeak - 1; x > firstPeak; x--) {\n const fromFirst = x - firstPeak;\n const score = fromFirst * fromFirst * (secondPeak - x) * (maxBucketCount - buckets[x]);\n if (score > bestValleyScore) {\n bestValley = x;\n bestValleyScore = score;\n }\n }\n return bestValley << GlobalHistogramBinarizer.LUMINANCE_SHIFT;\n }\n }\n GlobalHistogramBinarizer.LUMINANCE_BITS = 5;\n GlobalHistogramBinarizer.LUMINANCE_SHIFT = 8 - GlobalHistogramBinarizer.LUMINANCE_BITS;\n GlobalHistogramBinarizer.LUMINANCE_BUCKETS = 1 << GlobalHistogramBinarizer.LUMINANCE_BITS;\n GlobalHistogramBinarizer.EMPTY = Uint8ClampedArray.from([0]);\n\n /*\n * Copyright 2009 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n /**\n * This class implements a local thresholding algorithm, which while slower than the\n * GlobalHistogramBinarizer, is fairly efficient for what it does. It is designed for\n * high frequency images of barcodes with black data on white backgrounds. For this application,\n * it does a much better job than a global blackpoint with severe shadows and gradients.\n * However it tends to produce artifacts on lower frequency images and is therefore not\n * a good general purpose binarizer for uses outside ZXing.\n *\n * This class extends GlobalHistogramBinarizer, using the older histogram approach for 1D readers,\n * and the newer local approach for 2D readers. 1D decoding using a per-row histogram is already\n * inherently local, and only fails for horizontal gradients. We can revisit that problem later,\n * but for now it was not a win to use local blocks for 1D.\n *\n * This Binarizer is the default for the unit tests and the recommended class for library users.\n *\n * @author dswitkin@google.com (Daniel Switkin)\n */\n class HybridBinarizer extends GlobalHistogramBinarizer {\n constructor(source) {\n super(source);\n this.matrix = null;\n }\n /**\n * Calculates the final BitMatrix once for all requests. This could be called once from the\n * constructor instead, but there are some advantages to doing it lazily, such as making\n * profiling easier, and not doing heavy lifting when callers don't expect it.\n */\n /*@Override*/\n getBlackMatrix() {\n if (this.matrix !== null) {\n return this.matrix;\n }\n const source = this.getLuminanceSource();\n const width = source.getWidth();\n const height = source.getHeight();\n if (width >= HybridBinarizer.MINIMUM_DIMENSION && height >= HybridBinarizer.MINIMUM_DIMENSION) {\n const luminances = source.getMatrix();\n let subWidth = width >> HybridBinarizer.BLOCK_SIZE_POWER;\n if ((width & HybridBinarizer.BLOCK_SIZE_MASK) !== 0) {\n subWidth++;\n }\n let subHeight = height >> HybridBinarizer.BLOCK_SIZE_POWER;\n if ((height & HybridBinarizer.BLOCK_SIZE_MASK) !== 0) {\n subHeight++;\n }\n const blackPoints = HybridBinarizer.calculateBlackPoints(luminances, subWidth, subHeight, width, height);\n const newMatrix = new BitMatrix(width, height);\n HybridBinarizer.calculateThresholdForBlock(luminances, subWidth, subHeight, width, height, blackPoints, newMatrix);\n this.matrix = newMatrix;\n }\n else {\n // If the image is too small, fall back to the global histogram approach.\n this.matrix = super.getBlackMatrix();\n }\n return this.matrix;\n }\n /*@Override*/\n createBinarizer(source) {\n return new HybridBinarizer(source);\n }\n /**\n * For each block in the image, calculate the average black point using a 5x5 grid\n * of the blocks around it. Also handles the corner cases (fractional blocks are computed based\n * on the last pixels in the row/column which are also used in the previous block).\n */\n static calculateThresholdForBlock(luminances, subWidth /*int*/, subHeight /*int*/, width /*int*/, height /*int*/, blackPoints, matrix) {\n const maxYOffset = height - HybridBinarizer.BLOCK_SIZE;\n const maxXOffset = width - HybridBinarizer.BLOCK_SIZE;\n for (let y = 0; y < subHeight; y++) {\n let yoffset = y << HybridBinarizer.BLOCK_SIZE_POWER;\n if (yoffset > maxYOffset) {\n yoffset = maxYOffset;\n }\n const top = HybridBinarizer.cap(y, 2, subHeight - 3);\n for (let x = 0; x < subWidth; x++) {\n let xoffset = x << HybridBinarizer.BLOCK_SIZE_POWER;\n if (xoffset > maxXOffset) {\n xoffset = maxXOffset;\n }\n const left = HybridBinarizer.cap(x, 2, subWidth - 3);\n let sum = 0;\n for (let z = -2; z <= 2; z++) {\n const blackRow = blackPoints[top + z];\n sum += blackRow[left - 2] + blackRow[left - 1] + blackRow[left] + blackRow[left + 1] + blackRow[left + 2];\n }\n const average = sum / 25;\n HybridBinarizer.thresholdBlock(luminances, xoffset, yoffset, average, width, matrix);\n }\n }\n }\n static cap(value /*int*/, min /*int*/, max /*int*/) {\n return value < min ? min : value > max ? max : value;\n }\n /**\n * Applies a single threshold to a block of pixels.\n */\n static thresholdBlock(luminances, xoffset /*int*/, yoffset /*int*/, threshold /*int*/, stride /*int*/, matrix) {\n for (let y = 0, offset = yoffset * stride + xoffset; y < HybridBinarizer.BLOCK_SIZE; y++, offset += stride) {\n for (let x = 0; x < HybridBinarizer.BLOCK_SIZE; x++) {\n // Comparison needs to be <= so that black == 0 pixels are black even if the threshold is 0.\n if ((luminances[offset + x] & 0xFF) <= threshold) {\n matrix.set(xoffset + x, yoffset + y);\n }\n }\n }\n }\n /**\n * Calculates a single black point for each block of pixels and saves it away.\n * See the following thread for a discussion of this algorithm:\n * http://groups.google.com/group/zxing/browse_thread/thread/d06efa2c35a7ddc0\n */\n static calculateBlackPoints(luminances, subWidth /*int*/, subHeight /*int*/, width /*int*/, height /*int*/) {\n const maxYOffset = height - HybridBinarizer.BLOCK_SIZE;\n const maxXOffset = width - HybridBinarizer.BLOCK_SIZE;\n // tslint:disable-next-line:whitespace\n const blackPoints = new Array(subHeight); // subWidth\n for (let y = 0; y < subHeight; y++) {\n blackPoints[y] = new Int32Array(subWidth);\n let yoffset = y << HybridBinarizer.BLOCK_SIZE_POWER;\n if (yoffset > maxYOffset) {\n yoffset = maxYOffset;\n }\n for (let x = 0; x < subWidth; x++) {\n let xoffset = x << HybridBinarizer.BLOCK_SIZE_POWER;\n if (xoffset > maxXOffset) {\n xoffset = maxXOffset;\n }\n let sum = 0;\n let min = 0xFF;\n let max = 0;\n for (let yy = 0, offset = yoffset * width + xoffset; yy < HybridBinarizer.BLOCK_SIZE; yy++, offset += width) {\n for (let xx = 0; xx < HybridBinarizer.BLOCK_SIZE; xx++) {\n const pixel = luminances[offset + xx] & 0xFF;\n sum += pixel;\n // still looking for good contrast\n if (pixel < min) {\n min = pixel;\n }\n if (pixel > max) {\n max = pixel;\n }\n }\n // short-circuit min/max tests once dynamic range is met\n if (max - min > HybridBinarizer.MIN_DYNAMIC_RANGE) {\n // finish the rest of the rows quickly\n for (yy++, offset += width; yy < HybridBinarizer.BLOCK_SIZE; yy++, offset += width) {\n for (let xx = 0; xx < HybridBinarizer.BLOCK_SIZE; xx++) {\n sum += luminances[offset + xx] & 0xFF;\n }\n }\n }\n }\n // The default estimate is the average of the values in the block.\n let average = sum >> (HybridBinarizer.BLOCK_SIZE_POWER * 2);\n if (max - min <= HybridBinarizer.MIN_DYNAMIC_RANGE) {\n // If variation within the block is low, assume this is a block with only light or only\n // dark pixels. In that case we do not want to use the average, as it would divide this\n // low contrast area into black and white pixels, essentially creating data out of noise.\n //\n // The default assumption is that the block is light/background. Since no estimate for\n // the level of dark pixels exists locally, use half the min for the block.\n average = min / 2;\n if (y > 0 && x > 0) {\n // Correct the \"white background\" assumption for blocks that have neighbors by comparing\n // the pixels in this block to the previously calculated black points. This is based on\n // the fact that dark barcode symbology is always surrounded by some amount of light\n // background for which reasonable black point estimates were made. The bp estimated at\n // the boundaries is used for the interior.\n // The (min < bp) is arbitrary but works better than other heuristics that were tried.\n const averageNeighborBlackPoint = (blackPoints[y - 1][x] + (2 * blackPoints[y][x - 1]) + blackPoints[y - 1][x - 1]) / 4;\n if (min < averageNeighborBlackPoint) {\n average = averageNeighborBlackPoint;\n }\n }\n }\n blackPoints[y][x] = average;\n }\n }\n return blackPoints;\n }\n }\n // This class uses 5x5 blocks to compute local luminance, where each block is 8x8 pixels.\n // So this is the smallest dimension in each axis we can accept.\n HybridBinarizer.BLOCK_SIZE_POWER = 3;\n HybridBinarizer.BLOCK_SIZE = 1 << HybridBinarizer.BLOCK_SIZE_POWER; // ...0100...00\n HybridBinarizer.BLOCK_SIZE_MASK = HybridBinarizer.BLOCK_SIZE - 1; // ...0011...11\n HybridBinarizer.MINIMUM_DIMENSION = HybridBinarizer.BLOCK_SIZE * 5;\n HybridBinarizer.MIN_DYNAMIC_RANGE = 24;\n\n /*\n * Copyright 2009 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n /*namespace com.google.zxing {*/\n /**\n * The purpose of this class hierarchy is to abstract different bitmap implementations across\n * platforms into a standard interface for requesting greyscale luminance values. The interface\n * only provides immutable methods; therefore crop and rotation create copies. This is to ensure\n * that one Reader does not modify the original luminance source and leave it in an unknown state\n * for other Readers in the chain.\n *\n * @author dswitkin@google.com (Daniel Switkin)\n */\n class LuminanceSource {\n constructor(width /*int*/, height /*int*/) {\n this.width = width;\n this.height = height;\n }\n /**\n * @return The width of the bitmap.\n */\n getWidth() {\n return this.width;\n }\n /**\n * @return The height of the bitmap.\n */\n getHeight() {\n return this.height;\n }\n /**\n * @return Whether this subclass supports cropping.\n */\n isCropSupported() {\n return false;\n }\n /**\n * Returns a new object with cropped image data. Implementations may keep a reference to the\n * original data rather than a copy. Only callable if isCropSupported() is true.\n *\n * @param left The left coordinate, which must be in [0,getWidth())\n * @param top The top coordinate, which must be in [0,getHeight())\n * @param width The width of the rectangle to crop.\n * @param height The height of the rectangle to crop.\n * @return A cropped version of this object.\n */\n crop(left /*int*/, top /*int*/, width /*int*/, height /*int*/) {\n throw new UnsupportedOperationException('This luminance source does not support cropping.');\n }\n /**\n * @return Whether this subclass supports counter-clockwise rotation.\n */\n isRotateSupported() {\n return false;\n }\n /**\n * Returns a new object with rotated image data by 90 degrees counterclockwise.\n * Only callable if {@link #isRotateSupported()} is true.\n *\n * @return A rotated version of this object.\n */\n rotateCounterClockwise() {\n throw new UnsupportedOperationException('This luminance source does not support rotation by 90 degrees.');\n }\n /**\n * Returns a new object with rotated image data by 45 degrees counterclockwise.\n * Only callable if {@link #isRotateSupported()} is true.\n *\n * @return A rotated version of this object.\n */\n rotateCounterClockwise45() {\n throw new UnsupportedOperationException('This luminance source does not support rotation by 45 degrees.');\n }\n /*@Override*/\n toString() {\n const row = new Uint8ClampedArray(this.width);\n let result = new StringBuilder();\n for (let y = 0; y < this.height; y++) {\n const sourceRow = this.getRow(y, row);\n for (let x = 0; x < this.width; x++) {\n const luminance = sourceRow[x] & 0xFF;\n let c;\n if (luminance < 0x40) {\n c = '#';\n }\n else if (luminance < 0x80) {\n c = '+';\n }\n else if (luminance < 0xC0) {\n c = '.';\n }\n else {\n c = ' ';\n }\n result.append(c);\n }\n result.append('\\n');\n }\n return result.toString();\n }\n }\n\n /*\n * Copyright 2009 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n /*namespace com.google.zxing {*/\n /**\n * A wrapper implementation of {@link LuminanceSource} which inverts the luminances it returns -- black becomes\n * white and vice versa, and each value becomes (255-value).\n *\n * @author Sean Owen\n */\n class InvertedLuminanceSource extends LuminanceSource {\n constructor(delegate) {\n super(delegate.getWidth(), delegate.getHeight());\n this.delegate = delegate;\n }\n /*@Override*/\n getRow(y /*int*/, row) {\n const sourceRow = this.delegate.getRow(y, row);\n const width = this.getWidth();\n for (let i = 0; i < width; i++) {\n sourceRow[i] = /*(byte)*/ (255 - (sourceRow[i] & 0xFF));\n }\n return sourceRow;\n }\n /*@Override*/\n getMatrix() {\n const matrix = this.delegate.getMatrix();\n const length = this.getWidth() * this.getHeight();\n const invertedMatrix = new Uint8ClampedArray(length);\n for (let i = 0; i < length; i++) {\n invertedMatrix[i] = /*(byte)*/ (255 - (matrix[i] & 0xFF));\n }\n return invertedMatrix;\n }\n /*@Override*/\n isCropSupported() {\n return this.delegate.isCropSupported();\n }\n /*@Override*/\n crop(left /*int*/, top /*int*/, width /*int*/, height /*int*/) {\n return new InvertedLuminanceSource(this.delegate.crop(left, top, width, height));\n }\n /*@Override*/\n isRotateSupported() {\n return this.delegate.isRotateSupported();\n }\n /**\n * @return original delegate {@link LuminanceSource} since invert undoes itself\n */\n /*@Override*/\n invert() {\n return this.delegate;\n }\n /*@Override*/\n rotateCounterClockwise() {\n return new InvertedLuminanceSource(this.delegate.rotateCounterClockwise());\n }\n /*@Override*/\n rotateCounterClockwise45() {\n return new InvertedLuminanceSource(this.delegate.rotateCounterClockwise45());\n }\n }\n\n /**\n * @deprecated Moving to @zxing/browser\n */\n class HTMLCanvasElementLuminanceSource extends LuminanceSource {\n constructor(canvas) {\n super(canvas.width, canvas.height);\n this.canvas = canvas;\n this.tempCanvasElement = null;\n this.buffer = HTMLCanvasElementLuminanceSource.makeBufferFromCanvasImageData(canvas);\n }\n static makeBufferFromCanvasImageData(canvas) {\n const imageData = canvas.getContext('2d').getImageData(0, 0, canvas.width, canvas.height);\n return HTMLCanvasElementLuminanceSource.toGrayscaleBuffer(imageData.data, canvas.width, canvas.height);\n }\n static toGrayscaleBuffer(imageBuffer, width, height) {\n const grayscaleBuffer = new Uint8ClampedArray(width * height);\n for (let i = 0, j = 0, length = imageBuffer.length; i < length; i += 4, j++) {\n let gray;\n const alpha = imageBuffer[i + 3];\n // The color of fully-transparent pixels is irrelevant. They are often, technically, fully-transparent\n // black (0 alpha, and then 0 RGB). They are often used, of course as the \"white\" area in a\n // barcode image. Force any such pixel to be white:\n if (alpha === 0) {\n gray = 0xFF;\n }\n else {\n const pixelR = imageBuffer[i];\n const pixelG = imageBuffer[i + 1];\n const pixelB = imageBuffer[i + 2];\n // .299R + 0.587G + 0.114B (YUV/YIQ for PAL and NTSC),\n // (306*R) >> 10 is approximately equal to R*0.299, and so on.\n // 0x200 >> 10 is 0.5, it implements rounding.\n gray = (306 * pixelR +\n 601 * pixelG +\n 117 * pixelB +\n 0x200) >> 10;\n }\n grayscaleBuffer[j] = gray;\n }\n return grayscaleBuffer;\n }\n getRow(y /*int*/, row) {\n if (y < 0 || y >= this.getHeight()) {\n throw new IllegalArgumentException('Requested row is outside the image: ' + y);\n }\n const width = this.getWidth();\n const start = y * width;\n if (row === null) {\n row = this.buffer.slice(start, start + width);\n }\n else {\n if (row.length < width) {\n row = new Uint8ClampedArray(width);\n }\n // The underlying raster of image consists of bytes with the luminance values\n // TODO: can avoid set/slice?\n row.set(this.buffer.slice(start, start + width));\n }\n return row;\n }\n getMatrix() {\n return this.buffer;\n }\n isCropSupported() {\n return true;\n }\n crop(left /*int*/, top /*int*/, width /*int*/, height /*int*/) {\n super.crop(left, top, width, height);\n return this;\n }\n /**\n * This is always true, since the image is a gray-scale image.\n *\n * @return true\n */\n isRotateSupported() {\n return true;\n }\n rotateCounterClockwise() {\n this.rotate(-90);\n return this;\n }\n rotateCounterClockwise45() {\n this.rotate(-45);\n return this;\n }\n getTempCanvasElement() {\n if (null === this.tempCanvasElement) {\n const tempCanvasElement = this.canvas.ownerDocument.createElement('canvas');\n tempCanvasElement.width = this.canvas.width;\n tempCanvasElement.height = this.canvas.height;\n this.tempCanvasElement = tempCanvasElement;\n }\n return this.tempCanvasElement;\n }\n rotate(angle) {\n const tempCanvasElement = this.getTempCanvasElement();\n const tempContext = tempCanvasElement.getContext('2d');\n const angleRadians = angle * HTMLCanvasElementLuminanceSource.DEGREE_TO_RADIANS;\n // Calculate and set new dimensions for temp canvas\n const width = this.canvas.width;\n const height = this.canvas.height;\n const newWidth = Math.ceil(Math.abs(Math.cos(angleRadians)) * width + Math.abs(Math.sin(angleRadians)) * height);\n const newHeight = Math.ceil(Math.abs(Math.sin(angleRadians)) * width + Math.abs(Math.cos(angleRadians)) * height);\n tempCanvasElement.width = newWidth;\n tempCanvasElement.height = newHeight;\n // Draw at center of temp canvas to prevent clipping of image data\n tempContext.translate(newWidth / 2, newHeight / 2);\n tempContext.rotate(angleRadians);\n tempContext.drawImage(this.canvas, width / -2, height / -2);\n this.buffer = HTMLCanvasElementLuminanceSource.makeBufferFromCanvasImageData(tempCanvasElement);\n return this;\n }\n invert() {\n return new InvertedLuminanceSource(this);\n }\n }\n HTMLCanvasElementLuminanceSource.DEGREE_TO_RADIANS = Math.PI / 180;\n\n /**\n * @deprecated Moving to @zxing/browser\n *\n * Video input device metadata containing the id and label of the device if available.\n */\n class VideoInputDevice {\n /**\n * Creates an instance of VideoInputDevice.\n *\n * @param {string} deviceId the video input device id\n * @param {string} label the label of the device if available\n */\n constructor(deviceId, label, groupId) {\n this.deviceId = deviceId;\n this.label = label;\n /** @inheritdoc */\n this.kind = 'videoinput';\n this.groupId = groupId || undefined;\n }\n /** @inheritdoc */\n toJSON() {\n return {\n kind: this.kind,\n groupId: this.groupId,\n deviceId: this.deviceId,\n label: this.label,\n };\n }\n }\n\n var __awaiter = ((globalThis || global || self || window || undefined) && (globalThis || global || self || window || undefined).__awaiter) || function (thisArg, _arguments, P, generator) {\n function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }\n return new (P || (P = Promise))(function (resolve, reject) {\n function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\n function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\n function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }\n step((generator = generator.apply(thisArg, _arguments || [])).next());\n });\n };\n /**\n * @deprecated Moving to @zxing/browser\n *\n * Base class for browser code reader.\n */\n class BrowserCodeReader {\n /**\n * Creates an instance of BrowserCodeReader.\n * @param {Reader} reader The reader instance to decode the barcode\n * @param {number} [timeBetweenScansMillis=500] the time delay between subsequent successful decode tries\n *\n * @memberOf BrowserCodeReader\n */\n constructor(reader, timeBetweenScansMillis = 500, _hints) {\n this.reader = reader;\n this.timeBetweenScansMillis = timeBetweenScansMillis;\n this._hints = _hints;\n /**\n * This will break the loop.\n */\n this._stopContinuousDecode = false;\n /**\n * This will break the loop.\n */\n this._stopAsyncDecode = false;\n /**\n * Delay time between decode attempts made by the scanner.\n */\n this._timeBetweenDecodingAttempts = 0;\n }\n /**\n * If navigator is present.\n */\n get hasNavigator() {\n return typeof navigator !== 'undefined';\n }\n /**\n * If mediaDevices under navigator is supported.\n */\n get isMediaDevicesSuported() {\n return this.hasNavigator && !!navigator.mediaDevices;\n }\n /**\n * If enumerateDevices under navigator is supported.\n */\n get canEnumerateDevices() {\n return !!(this.isMediaDevicesSuported && navigator.mediaDevices.enumerateDevices);\n }\n /** Time between two decoding tries in milli seconds. */\n get timeBetweenDecodingAttempts() {\n return this._timeBetweenDecodingAttempts;\n }\n /**\n * Change the time span the decoder waits between two decoding tries.\n *\n * @param {number} millis Time between two decoding tries in milli seconds.\n */\n set timeBetweenDecodingAttempts(millis) {\n this._timeBetweenDecodingAttempts = millis < 0 ? 0 : millis;\n }\n /**\n * Sets the hints.\n */\n set hints(hints) {\n this._hints = hints || null;\n }\n /**\n * Sets the hints.\n */\n get hints() {\n return this._hints;\n }\n /**\n * Lists all the available video input devices.\n */\n listVideoInputDevices() {\n return __awaiter(this, void 0, void 0, function* () {\n if (!this.hasNavigator) {\n throw new Error('Can\\'t enumerate devices, navigator is not present.');\n }\n if (!this.canEnumerateDevices) {\n throw new Error('Can\\'t enumerate devices, method not supported.');\n }\n const devices = yield navigator.mediaDevices.enumerateDevices();\n const videoDevices = [];\n for (const device of devices) {\n const kind = device.kind === 'video' ? 'videoinput' : device.kind;\n if (kind !== 'videoinput') {\n continue;\n }\n const deviceId = device.deviceId || device.id;\n const label = device.label || `Video device ${videoDevices.length + 1}`;\n const groupId = device.groupId;\n const videoDevice = { deviceId, label, kind, groupId };\n videoDevices.push(videoDevice);\n }\n return videoDevices;\n });\n }\n /**\n * Obtain the list of available devices with type 'videoinput'.\n *\n * @returns {Promise} an array of available video input devices\n *\n * @memberOf BrowserCodeReader\n *\n * @deprecated Use `listVideoInputDevices` instead.\n */\n getVideoInputDevices() {\n return __awaiter(this, void 0, void 0, function* () {\n const devices = yield this.listVideoInputDevices();\n return devices.map(d => new VideoInputDevice(d.deviceId, d.label));\n });\n }\n /**\n * Let's you find a device using it's Id.\n */\n findDeviceById(deviceId) {\n return __awaiter(this, void 0, void 0, function* () {\n const devices = yield this.listVideoInputDevices();\n if (!devices) {\n return null;\n }\n return devices.find(x => x.deviceId === deviceId);\n });\n }\n /**\n * Decodes the barcode from the device specified by deviceId while showing the video in the specified video element.\n *\n * @param deviceId the id of one of the devices obtained after calling getVideoInputDevices. Can be undefined, in this case it will decode from one of the available devices, preffering the main camera (environment facing) if available.\n * @param video the video element in page where to show the video while decoding. Can be either an element id or directly an HTMLVideoElement. Can be undefined, in which case no video will be shown.\n * @returns The decoding result.\n *\n * @memberOf BrowserCodeReader\n *\n * @deprecated Use `decodeOnceFromVideoDevice` instead.\n */\n decodeFromInputVideoDevice(deviceId, videoSource) {\n return __awaiter(this, void 0, void 0, function* () {\n return yield this.decodeOnceFromVideoDevice(deviceId, videoSource);\n });\n }\n /**\n * In one attempt, tries to decode the barcode from the device specified by deviceId while showing the video in the specified video element.\n *\n * @param deviceId the id of one of the devices obtained after calling getVideoInputDevices. Can be undefined, in this case it will decode from one of the available devices, preffering the main camera (environment facing) if available.\n * @param video the video element in page where to show the video while decoding. Can be either an element id or directly an HTMLVideoElement. Can be undefined, in which case no video will be shown.\n * @returns The decoding result.\n *\n * @memberOf BrowserCodeReader\n */\n decodeOnceFromVideoDevice(deviceId, videoSource) {\n return __awaiter(this, void 0, void 0, function* () {\n this.reset();\n let videoConstraints;\n if (!deviceId) {\n videoConstraints = { facingMode: 'environment' };\n }\n else {\n videoConstraints = { deviceId: { exact: deviceId } };\n }\n const constraints = { video: videoConstraints };\n return yield this.decodeOnceFromConstraints(constraints, videoSource);\n });\n }\n /**\n * In one attempt, tries to decode the barcode from a stream obtained from the given constraints while showing the video in the specified video element.\n *\n * @param constraints the media stream constraints to get s valid media stream to decode from\n * @param video the video element in page where to show the video while decoding. Can be either an element id or directly an HTMLVideoElement. Can be undefined, in which case no video will be shown.\n * @returns The decoding result.\n *\n * @memberOf BrowserCodeReader\n */\n decodeOnceFromConstraints(constraints, videoSource) {\n return __awaiter(this, void 0, void 0, function* () {\n const stream = yield navigator.mediaDevices.getUserMedia(constraints);\n return yield this.decodeOnceFromStream(stream, videoSource);\n });\n }\n /**\n * In one attempt, tries to decode the barcode from a stream obtained from the given constraints while showing the video in the specified video element.\n *\n * @param {MediaStream} [constraints] the media stream constraints to get s valid media stream to decode from\n * @param {string|HTMLVideoElement} [video] the video element in page where to show the video while decoding. Can be either an element id or directly an HTMLVideoElement. Can be undefined, in which case no video will be shown.\n * @returns {Promise} The decoding result.\n *\n * @memberOf BrowserCodeReader\n */\n decodeOnceFromStream(stream, videoSource) {\n return __awaiter(this, void 0, void 0, function* () {\n this.reset();\n const video = yield this.attachStreamToVideo(stream, videoSource);\n const result = yield this.decodeOnce(video);\n return result;\n });\n }\n /**\n * Continuously decodes the barcode from the device specified by device while showing the video in the specified video element.\n *\n * @param {string|null} [deviceId] the id of one of the devices obtained after calling getVideoInputDevices. Can be undefined, in this case it will decode from one of the available devices, preffering the main camera (environment facing) if available.\n * @param {string|HTMLVideoElement|null} [video] the video element in page where to show the video while decoding. Can be either an element id or directly an HTMLVideoElement. Can be undefined, in which case no video will be shown.\n * @returns {Promise}\n *\n * @memberOf BrowserCodeReader\n *\n * @deprecated Use `decodeFromVideoDevice` instead.\n */\n decodeFromInputVideoDeviceContinuously(deviceId, videoSource, callbackFn) {\n return __awaiter(this, void 0, void 0, function* () {\n return yield this.decodeFromVideoDevice(deviceId, videoSource, callbackFn);\n });\n }\n /**\n * Continuously tries to decode the barcode from the device specified by device while showing the video in the specified video element.\n *\n * @param {string|null} [deviceId] the id of one of the devices obtained after calling getVideoInputDevices. Can be undefined, in this case it will decode from one of the available devices, preffering the main camera (environment facing) if available.\n * @param {string|HTMLVideoElement|null} [video] the video element in page where to show the video while decoding. Can be either an element id or directly an HTMLVideoElement. Can be undefined, in which case no video will be shown.\n * @returns {Promise}\n *\n * @memberOf BrowserCodeReader\n */\n decodeFromVideoDevice(deviceId, videoSource, callbackFn) {\n return __awaiter(this, void 0, void 0, function* () {\n let videoConstraints;\n if (!deviceId) {\n videoConstraints = { facingMode: 'environment' };\n }\n else {\n videoConstraints = { deviceId: { exact: deviceId } };\n }\n const constraints = { video: videoConstraints };\n return yield this.decodeFromConstraints(constraints, videoSource, callbackFn);\n });\n }\n /**\n * Continuously tries to decode the barcode from a stream obtained from the given constraints while showing the video in the specified video element.\n *\n * @param {MediaStream} [constraints] the media stream constraints to get s valid media stream to decode from\n * @param {string|HTMLVideoElement} [video] the video element in page where to show the video while decoding. Can be either an element id or directly an HTMLVideoElement. Can be undefined, in which case no video will be shown.\n * @returns {Promise} The decoding result.\n *\n * @memberOf BrowserCodeReader\n */\n decodeFromConstraints(constraints, videoSource, callbackFn) {\n return __awaiter(this, void 0, void 0, function* () {\n const stream = yield navigator.mediaDevices.getUserMedia(constraints);\n return yield this.decodeFromStream(stream, videoSource, callbackFn);\n });\n }\n /**\n * In one attempt, tries to decode the barcode from a stream obtained from the given constraints while showing the video in the specified video element.\n *\n * @param {MediaStream} [constraints] the media stream constraints to get s valid media stream to decode from\n * @param {string|HTMLVideoElement} [video] the video element in page where to show the video while decoding. Can be either an element id or directly an HTMLVideoElement. Can be undefined, in which case no video will be shown.\n * @returns {Promise} The decoding result.\n *\n * @memberOf BrowserCodeReader\n */\n decodeFromStream(stream, videoSource, callbackFn) {\n return __awaiter(this, void 0, void 0, function* () {\n this.reset();\n const video = yield this.attachStreamToVideo(stream, videoSource);\n return yield this.decodeContinuously(video, callbackFn);\n });\n }\n /**\n * Breaks the decoding loop.\n */\n stopAsyncDecode() {\n this._stopAsyncDecode = true;\n }\n /**\n * Breaks the decoding loop.\n */\n stopContinuousDecode() {\n this._stopContinuousDecode = true;\n }\n /**\n * Sets the new stream and request a new decoding-with-delay.\n *\n * @param stream The stream to be shown in the video element.\n * @param decodeFn A callback for the decode method.\n */\n attachStreamToVideo(stream, videoSource) {\n return __awaiter(this, void 0, void 0, function* () {\n const videoElement = this.prepareVideoElement(videoSource);\n this.addVideoSource(videoElement, stream);\n this.videoElement = videoElement;\n this.stream = stream;\n yield this.playVideoOnLoadAsync(videoElement);\n return videoElement;\n });\n }\n /**\n *\n * @param videoElement\n */\n playVideoOnLoadAsync(videoElement) {\n return new Promise((resolve, reject) => this.playVideoOnLoad(videoElement, () => resolve()));\n }\n /**\n * Binds listeners and callbacks to the videoElement.\n *\n * @param element\n * @param callbackFn\n */\n playVideoOnLoad(element, callbackFn) {\n this.videoEndedListener = () => this.stopStreams();\n this.videoCanPlayListener = () => this.tryPlayVideo(element);\n element.addEventListener('ended', this.videoEndedListener);\n element.addEventListener('canplay', this.videoCanPlayListener);\n element.addEventListener('playing', callbackFn);\n // if canplay was already fired, we won't know when to play, so just give it a try\n this.tryPlayVideo(element);\n }\n /**\n * Checks if the given video element is currently playing.\n */\n isVideoPlaying(video) {\n return video.currentTime > 0 && !video.paused && !video.ended && video.readyState > 2;\n }\n /**\n * Just tries to play the video and logs any errors.\n * The play call is only made is the video is not already playing.\n */\n tryPlayVideo(videoElement) {\n return __awaiter(this, void 0, void 0, function* () {\n if (this.isVideoPlaying(videoElement)) {\n console.warn('Trying to play video that is already playing.');\n return;\n }\n try {\n yield videoElement.play();\n }\n catch (_a) {\n console.warn('It was not possible to play the video.');\n }\n });\n }\n /**\n * Searches and validates a media element.\n */\n getMediaElement(mediaElementId, type) {\n const mediaElement = document.getElementById(mediaElementId);\n if (!mediaElement) {\n throw new ArgumentException(`element with id '${mediaElementId}' not found`);\n }\n if (mediaElement.nodeName.toLowerCase() !== type.toLowerCase()) {\n throw new ArgumentException(`element with id '${mediaElementId}' must be an ${type} element`);\n }\n return mediaElement;\n }\n /**\n * Decodes the barcode from an image.\n *\n * @param {(string|HTMLImageElement)} [source] The image element that can be either an element id or the element itself. Can be undefined in which case the decoding will be done from the imageUrl parameter.\n * @param {string} [url]\n * @returns {Promise} The decoding result.\n *\n * @memberOf BrowserCodeReader\n */\n decodeFromImage(source, url) {\n if (!source && !url) {\n throw new ArgumentException('either imageElement with a src set or an url must be provided');\n }\n if (url && !source) {\n return this.decodeFromImageUrl(url);\n }\n return this.decodeFromImageElement(source);\n }\n /**\n * Decodes the barcode from a video.\n *\n * @param {(string|HTMLImageElement)} [source] The image element that can be either an element id or the element itself. Can be undefined in which case the decoding will be done from the imageUrl parameter.\n * @param {string} [url]\n * @returns {Promise} The decoding result.\n *\n * @memberOf BrowserCodeReader\n */\n decodeFromVideo(source, url) {\n if (!source && !url) {\n throw new ArgumentException('Either an element with a src set or an URL must be provided');\n }\n if (url && !source) {\n return this.decodeFromVideoUrl(url);\n }\n return this.decodeFromVideoElement(source);\n }\n /**\n * Decodes continuously the barcode from a video.\n *\n * @param {(string|HTMLImageElement)} [source] The image element that can be either an element id or the element itself. Can be undefined in which case the decoding will be done from the imageUrl parameter.\n * @param {string} [url]\n * @returns {Promise} The decoding result.\n *\n * @memberOf BrowserCodeReader\n *\n * @experimental\n */\n decodeFromVideoContinuously(source, url, callbackFn) {\n if (undefined === source && undefined === url) {\n throw new ArgumentException('Either an element with a src set or an URL must be provided');\n }\n if (url && !source) {\n return this.decodeFromVideoUrlContinuously(url, callbackFn);\n }\n return this.decodeFromVideoElementContinuously(source, callbackFn);\n }\n /**\n * Decodes something from an image HTML element.\n */\n decodeFromImageElement(source) {\n if (!source) {\n throw new ArgumentException('An image element must be provided.');\n }\n this.reset();\n const element = this.prepareImageElement(source);\n this.imageElement = element;\n let task;\n if (this.isImageLoaded(element)) {\n task = this.decodeOnce(element, false, true);\n }\n else {\n task = this._decodeOnLoadImage(element);\n }\n return task;\n }\n /**\n * Decodes something from an image HTML element.\n */\n decodeFromVideoElement(source) {\n const element = this._decodeFromVideoElementSetup(source);\n return this._decodeOnLoadVideo(element);\n }\n /**\n * Decodes something from an image HTML element.\n */\n decodeFromVideoElementContinuously(source, callbackFn) {\n const element = this._decodeFromVideoElementSetup(source);\n return this._decodeOnLoadVideoContinuously(element, callbackFn);\n }\n /**\n * Sets up the video source so it can be decoded when loaded.\n *\n * @param source The video source element.\n */\n _decodeFromVideoElementSetup(source) {\n if (!source) {\n throw new ArgumentException('A video element must be provided.');\n }\n this.reset();\n const element = this.prepareVideoElement(source);\n // defines the video element before starts decoding\n this.videoElement = element;\n return element;\n }\n /**\n * Decodes an image from a URL.\n */\n decodeFromImageUrl(url) {\n if (!url) {\n throw new ArgumentException('An URL must be provided.');\n }\n this.reset();\n const element = this.prepareImageElement();\n this.imageElement = element;\n const decodeTask = this._decodeOnLoadImage(element);\n element.src = url;\n return decodeTask;\n }\n /**\n * Decodes an image from a URL.\n */\n decodeFromVideoUrl(url) {\n if (!url) {\n throw new ArgumentException('An URL must be provided.');\n }\n this.reset();\n // creates a new element\n const element = this.prepareVideoElement();\n const decodeTask = this.decodeFromVideoElement(element);\n element.src = url;\n return decodeTask;\n }\n /**\n * Decodes an image from a URL.\n *\n * @experimental\n */\n decodeFromVideoUrlContinuously(url, callbackFn) {\n if (!url) {\n throw new ArgumentException('An URL must be provided.');\n }\n this.reset();\n // creates a new element\n const element = this.prepareVideoElement();\n const decodeTask = this.decodeFromVideoElementContinuously(element, callbackFn);\n element.src = url;\n return decodeTask;\n }\n _decodeOnLoadImage(element) {\n return new Promise((resolve, reject) => {\n this.imageLoadedListener = () => this.decodeOnce(element, false, true).then(resolve, reject);\n element.addEventListener('load', this.imageLoadedListener);\n });\n }\n _decodeOnLoadVideo(videoElement) {\n return __awaiter(this, void 0, void 0, function* () {\n // plays the video\n yield this.playVideoOnLoadAsync(videoElement);\n // starts decoding after played the video\n return yield this.decodeOnce(videoElement);\n });\n }\n _decodeOnLoadVideoContinuously(videoElement, callbackFn) {\n return __awaiter(this, void 0, void 0, function* () {\n // plays the video\n yield this.playVideoOnLoadAsync(videoElement);\n // starts decoding after played the video\n this.decodeContinuously(videoElement, callbackFn);\n });\n }\n isImageLoaded(img) {\n // During the onload event, IE correctly identifies any images that\n // weren\u2019t downloaded as not complete. Others should too. Gecko-based\n // browsers act like NS4 in that they report this incorrectly.\n if (!img.complete) {\n return false;\n }\n // However, they do have two very useful properties: naturalWidth and\n // naturalHeight. These give the true size of the image. If it failed\n // to load, either of these should be zero.\n if (img.naturalWidth === 0) {\n return false;\n }\n // No other way of checking: assume it\u2019s ok.\n return true;\n }\n prepareImageElement(imageSource) {\n let imageElement;\n if (typeof imageSource === 'undefined') {\n imageElement = document.createElement('img');\n imageElement.width = 200;\n imageElement.height = 200;\n }\n if (typeof imageSource === 'string') {\n imageElement = this.getMediaElement(imageSource, 'img');\n }\n if (imageSource instanceof HTMLImageElement) {\n imageElement = imageSource;\n }\n return imageElement;\n }\n /**\n * Sets a HTMLVideoElement for scanning or creates a new one.\n *\n * @param videoSource The HTMLVideoElement to be set.\n */\n prepareVideoElement(videoSource) {\n let videoElement;\n if (!videoSource && typeof document !== 'undefined') {\n videoElement = document.createElement('video');\n videoElement.width = 200;\n videoElement.height = 200;\n }\n if (typeof videoSource === 'string') {\n videoElement = this.getMediaElement(videoSource, 'video');\n }\n if (videoSource instanceof HTMLVideoElement) {\n videoElement = videoSource;\n }\n // Needed for iOS 11\n videoElement.setAttribute('autoplay', 'true');\n videoElement.setAttribute('muted', 'true');\n videoElement.setAttribute('playsinline', 'true');\n return videoElement;\n }\n /**\n * Tries to decode from the video input until it finds some value.\n */\n decodeOnce(element, retryIfNotFound = true, retryIfChecksumOrFormatError = true) {\n this._stopAsyncDecode = false;\n const loop = (resolve, reject) => {\n if (this._stopAsyncDecode) {\n reject(new NotFoundException('Video stream has ended before any code could be detected.'));\n this._stopAsyncDecode = undefined;\n return;\n }\n try {\n const result = this.decode(element);\n resolve(result);\n }\n catch (e) {\n const ifNotFound = retryIfNotFound && e instanceof NotFoundException;\n const isChecksumOrFormatError = e instanceof ChecksumException || e instanceof FormatException;\n const ifChecksumOrFormat = isChecksumOrFormatError && retryIfChecksumOrFormatError;\n if (ifNotFound || ifChecksumOrFormat) {\n // trying again\n return setTimeout(loop, this._timeBetweenDecodingAttempts, resolve, reject);\n }\n reject(e);\n }\n };\n return new Promise((resolve, reject) => loop(resolve, reject));\n }\n /**\n * Continuously decodes from video input.\n */\n decodeContinuously(element, callbackFn) {\n this._stopContinuousDecode = false;\n const loop = () => {\n if (this._stopContinuousDecode) {\n this._stopContinuousDecode = undefined;\n return;\n }\n try {\n const result = this.decode(element);\n callbackFn(result, null);\n setTimeout(loop, this.timeBetweenScansMillis);\n }\n catch (e) {\n callbackFn(null, e);\n const isChecksumOrFormatError = e instanceof ChecksumException || e instanceof FormatException;\n const isNotFound = e instanceof NotFoundException;\n if (isChecksumOrFormatError || isNotFound) {\n // trying again\n setTimeout(loop, this._timeBetweenDecodingAttempts);\n }\n }\n };\n loop();\n }\n /**\n * Gets the BinaryBitmap for ya! (and decodes it)\n */\n decode(element) {\n // get binary bitmap for decode function\n const binaryBitmap = this.createBinaryBitmap(element);\n return this.decodeBitmap(binaryBitmap);\n }\n /**\n * Returns true if media element is indeed a {@link HtmlVideoElement}.\n */\n _isHTMLVideoElement(mediaElement) {\n const potentialVideo = mediaElement;\n return potentialVideo.videoWidth !== 0;\n }\n /**\n * Overwriting this allows you to manipulate the next frame in anyway\n * you want before decode.\n */\n drawFrameOnCanvas(\n srcElement, dimensions, canvasElementContext) {\n if (!dimensions) {\n dimensions = {\n sx: 0,\n sy: 0,\n sWidth: srcElement.videoWidth,\n sHeight: srcElement.videoHeight,\n dx: 0,\n dy: 0,\n dWidth: srcElement.videoWidth,\n dHeight: srcElement.videoHeight};\n }\n if (!canvasElementContext) {\n canvasElementContext = this.captureCanvasContext;\n }\n canvasElementContext.drawImage(\n srcElement,\n dimensions.sx,\n dimensions.sy,\n dimensions.sWidth,\n dimensions.sHeight,\n dimensions.dx,\n dimensions.dy,\n dimensions.dWidth,\n dimensions.dHeight);\n }\n /**\n * Ovewriting this allows you to manipulate the snapshot image in anyway\n * you want before decode.\n */\n drawImageOnCanvas(\n srcElement,\n dimensions,\n canvasElementContext = this.captureCanvasContext) {\n if (!dimensions) {\n dimensions = {\n sx: 0,\n sy: 0,\n sWidth: srcElement.naturalWidth,\n sHeight: srcElement.naturalHeight,\n dx: 0,\n dy: 0,\n dWidth: srcElement.naturalWidth,\n dHeight: srcElement.naturalHeight\n };\n }\n if (!canvasElementContext) {\n canvasElementContext = this.captureCanvasContext;\n }\n canvasElementContext.drawImage(\n srcElement,\n dimensions.sx,\n dimensions.sy,\n dimensions.sWidth,\n dimensions.sHeight,\n dimensions.dx,\n dimensions.dy,\n dimensions.dWidth,\n dimensions.dHeight);\n }\n /**\n * Creates a binaryBitmap based in some image source.\n *\n * @param mediaElement HTML element containing drawable image source.\n */\n createBinaryBitmap(mediaElement) {\n const ctx = this.getCaptureCanvasContext(mediaElement);\n if (this._isHTMLVideoElement(mediaElement)) {\n this.drawFrameOnCanvas(mediaElement);\n } else {\n this.drawImageOnCanvas(mediaElement);\n }\n const canvas = this.getCaptureCanvas(mediaElement);\n const luminanceSource = new HTMLCanvasElementLuminanceSource(canvas);\n const hybridBinarizer = new HybridBinarizer(luminanceSource);\n\n return new BinaryBitmap(hybridBinarizer);\n }\n\n getCaptureCanvasContext(mediaElement) {\n if (!this.captureCanvasContext) {\n const elem = this.getCaptureCanvas(mediaElement);\n const ctx = elem.getContext('2d');\n this.captureCanvasContext = ctx;\n }\n return this.captureCanvasContext;\n }\n getCaptureCanvas(mediaElement) {\n if (!this.captureCanvas) {\n const elem = this.createCaptureCanvas(mediaElement);\n this.captureCanvas = elem;\n }\n return this.captureCanvas;\n }\n /**\n * Call the encapsulated readers decode\n */\n decodeBitmap(binaryBitmap) {\n return this.reader.decode(binaryBitmap, this._hints);\n }\n /**\n * \uD83D\uDD8C Prepares the canvas for capture and scan frames.\n */\n createCaptureCanvas(mediaElement) {\n if (typeof document === 'undefined') {\n this._destroyCaptureCanvas();\n return null;\n }\n const canvasElement = document.createElement('canvas');\n let width;\n let height;\n if (typeof mediaElement !== 'undefined') {\n if (mediaElement instanceof HTMLVideoElement) {\n width = mediaElement.videoWidth;\n height = mediaElement.videoHeight;\n }\n else if (mediaElement instanceof HTMLImageElement) {\n width = mediaElement.naturalWidth || mediaElement.width;\n height = mediaElement.naturalHeight || mediaElement.height;\n }\n }\n canvasElement.style.width = width + 'px';\n canvasElement.style.height = height + 'px';\n canvasElement.width = width;\n canvasElement.height = height;\n return canvasElement;\n }\n /**\n * Stops the continuous scan and cleans the stream.\n */\n stopStreams() {\n if (this.stream) {\n this.stream.getVideoTracks().forEach(t => t.stop());\n this.stream = undefined;\n }\n if (this._stopAsyncDecode === false) {\n this.stopAsyncDecode();\n }\n if (this._stopContinuousDecode === false) {\n this.stopContinuousDecode();\n }\n }\n /**\n * Resets the code reader to the initial state. Cancels any ongoing barcode scanning from video or camera.\n *\n * @memberOf BrowserCodeReader\n */\n reset() {\n // stops the camera, preview and scan \uD83D\uDD34\n this.stopStreams();\n // clean and forget about HTML elements\n this._destroyVideoElement();\n this._destroyImageElement();\n this._destroyCaptureCanvas();\n }\n _destroyVideoElement() {\n if (!this.videoElement) {\n return;\n }\n // first gives freedon to the element \uD83D\uDD4A\n if (typeof this.videoEndedListener !== 'undefined') {\n this.videoElement.removeEventListener('ended', this.videoEndedListener);\n }\n if (typeof this.videoPlayingEventListener !== 'undefined') {\n this.videoElement.removeEventListener('playing', this.videoPlayingEventListener);\n }\n if (typeof this.videoCanPlayListener !== 'undefined') {\n this.videoElement.removeEventListener('loadedmetadata', this.videoCanPlayListener);\n }\n // then forgets about that element \uD83D\uDE22\n this.cleanVideoSource(this.videoElement);\n this.videoElement = undefined;\n }\n _destroyImageElement() {\n if (!this.imageElement) {\n return;\n }\n // first gives freedon to the element \uD83D\uDD4A\n if (undefined !== this.imageLoadedListener) {\n this.imageElement.removeEventListener('load', this.imageLoadedListener);\n }\n // then forget about that element \uD83D\uDE22\n this.imageElement.src = undefined;\n this.imageElement.removeAttribute('src');\n this.imageElement = undefined;\n }\n /**\n * Cleans canvas references \uD83D\uDD8C\n */\n _destroyCaptureCanvas() {\n // then forget about that element \uD83D\uDE22\n this.captureCanvasContext = undefined;\n this.captureCanvas = undefined;\n }\n /**\n * Defines what the videoElement src will be.\n *\n * @param videoElement\n * @param stream\n */\n addVideoSource(videoElement, stream) {\n // Older browsers may not have `srcObject`\n try {\n // @note Throws Exception if interrupted by a new loaded request\n videoElement.srcObject = stream;\n }\n catch (err) {\n // @note Avoid using this in new browsers, as it is going away.\n videoElement.src = URL.createObjectURL(stream);\n }\n }\n /**\n * Unbinds a HTML video src property.\n *\n * @param videoElement\n */\n cleanVideoSource(videoElement) {\n try {\n videoElement.srcObject = null;\n }\n catch (err) {\n videoElement.src = '';\n }\n this.videoElement.removeAttribute('src');\n }\n }\n\n /*\n * Copyright 2007 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n /**\n *

Encapsulates the result of decoding a barcode within an image.

\n *\n * @author Sean Owen\n */\n class Result {\n // public constructor(private text: string,\n // Uint8Array rawBytes,\n // ResultPoconst resultPoints: Int32Array,\n // BarcodeFormat format) {\n // this(text, rawBytes, resultPoints, format, System.currentTimeMillis())\n // }\n // public constructor(text: string,\n // Uint8Array rawBytes,\n // ResultPoconst resultPoints: Int32Array,\n // BarcodeFormat format,\n // long timestamp) {\n // this(text, rawBytes, rawBytes == null ? 0 : 8 * rawBytes.length,\n // resultPoints, format, timestamp)\n // }\n constructor(text, rawBytes, numBits = rawBytes == null ? 0 : 8 * rawBytes.length, resultPoints, format, timestamp = System.currentTimeMillis()) {\n this.text = text;\n this.rawBytes = rawBytes;\n this.numBits = numBits;\n this.resultPoints = resultPoints;\n this.format = format;\n this.timestamp = timestamp;\n this.text = text;\n this.rawBytes = rawBytes;\n if (undefined === numBits || null === numBits) {\n this.numBits = (rawBytes === null || rawBytes === undefined) ? 0 : 8 * rawBytes.length;\n }\n else {\n this.numBits = numBits;\n }\n this.resultPoints = resultPoints;\n this.format = format;\n this.resultMetadata = null;\n if (undefined === timestamp || null === timestamp) {\n this.timestamp = System.currentTimeMillis();\n }\n else {\n this.timestamp = timestamp;\n }\n }\n /**\n * @return raw text encoded by the barcode\n */\n getText() {\n return this.text;\n }\n /**\n * @return raw bytes encoded by the barcode, if applicable, otherwise {@code null}\n */\n getRawBytes() {\n return this.rawBytes;\n }\n /**\n * @return how many bits of {@link #getRawBytes()} are valid; typically 8 times its length\n * @since 3.3.0\n */\n getNumBits() {\n return this.numBits;\n }\n /**\n * @return points related to the barcode in the image. These are typically points\n * identifying finder patterns or the corners of the barcode. The exact meaning is\n * specific to the type of barcode that was decoded.\n */\n getResultPoints() {\n return this.resultPoints;\n }\n /**\n * @return {@link BarcodeFormat} representing the format of the barcode that was decoded\n */\n getBarcodeFormat() {\n return this.format;\n }\n /**\n * @return {@link Map} mapping {@link ResultMetadataType} keys to values. May be\n * {@code null}. This contains optional metadata about what was detected about the barcode,\n * like orientation.\n */\n getResultMetadata() {\n return this.resultMetadata;\n }\n putMetadata(type, value) {\n if (this.resultMetadata === null) {\n this.resultMetadata = new Map();\n }\n this.resultMetadata.set(type, value);\n }\n putAllMetadata(metadata) {\n if (metadata !== null) {\n if (this.resultMetadata === null) {\n this.resultMetadata = metadata;\n }\n else {\n this.resultMetadata = new Map(metadata);\n }\n }\n }\n addResultPoints(newPoints) {\n const oldPoints = this.resultPoints;\n if (oldPoints === null) {\n this.resultPoints = newPoints;\n }\n else if (newPoints !== null && newPoints.length > 0) {\n const allPoints = new Array(oldPoints.length + newPoints.length);\n System.arraycopy(oldPoints, 0, allPoints, 0, oldPoints.length);\n System.arraycopy(newPoints, 0, allPoints, oldPoints.length, newPoints.length);\n this.resultPoints = allPoints;\n }\n }\n getTimestamp() {\n return this.timestamp;\n }\n /*@Override*/\n toString() {\n return this.text;\n }\n }\n\n /*\n * Direct port to TypeScript of ZXing by Adrian To\u0219c\u0103\n */\n /*\n * Copyright 2009 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n /*namespace com.google.zxing {*/\n /**\n * Enumerates barcode formats known to this package. Please keep alphabetized.\n *\n * @author Sean Owen\n */\n var BarcodeFormat;\n (function (BarcodeFormat) {\n /** Aztec 2D barcode format. */\n BarcodeFormat[BarcodeFormat[\"AZTEC\"] = 0] = \"AZTEC\";\n /** CODABAR 1D format. */\n BarcodeFormat[BarcodeFormat[\"CODABAR\"] = 1] = \"CODABAR\";\n /** Code 39 1D format. */\n BarcodeFormat[BarcodeFormat[\"CODE_39\"] = 2] = \"CODE_39\";\n /** Code 93 1D format. */\n BarcodeFormat[BarcodeFormat[\"CODE_93\"] = 3] = \"CODE_93\";\n /** Code 128 1D format. */\n BarcodeFormat[BarcodeFormat[\"CODE_128\"] = 4] = \"CODE_128\";\n /** Data Matrix 2D barcode format. */\n BarcodeFormat[BarcodeFormat[\"DATA_MATRIX\"] = 5] = \"DATA_MATRIX\";\n /** EAN-8 1D format. */\n BarcodeFormat[BarcodeFormat[\"EAN_8\"] = 6] = \"EAN_8\";\n /** EAN-13 1D format. */\n BarcodeFormat[BarcodeFormat[\"EAN_13\"] = 7] = \"EAN_13\";\n /** ITF (Interleaved Two of Five) 1D format. */\n BarcodeFormat[BarcodeFormat[\"ITF\"] = 8] = \"ITF\";\n /** MaxiCode 2D barcode format. */\n BarcodeFormat[BarcodeFormat[\"MAXICODE\"] = 9] = \"MAXICODE\";\n /** PDF417 format. */\n BarcodeFormat[BarcodeFormat[\"PDF_417\"] = 10] = \"PDF_417\";\n /** QR Code 2D barcode format. */\n BarcodeFormat[BarcodeFormat[\"QR_CODE\"] = 11] = \"QR_CODE\";\n /** RSS 14 */\n BarcodeFormat[BarcodeFormat[\"RSS_14\"] = 12] = \"RSS_14\";\n /** RSS EXPANDED */\n BarcodeFormat[BarcodeFormat[\"RSS_EXPANDED\"] = 13] = \"RSS_EXPANDED\";\n /** UPC-A 1D format. */\n BarcodeFormat[BarcodeFormat[\"UPC_A\"] = 14] = \"UPC_A\";\n /** UPC-E 1D format. */\n BarcodeFormat[BarcodeFormat[\"UPC_E\"] = 15] = \"UPC_E\";\n /** UPC/EAN extension format. Not a stand-alone format. */\n BarcodeFormat[BarcodeFormat[\"UPC_EAN_EXTENSION\"] = 16] = \"UPC_EAN_EXTENSION\";\n })(BarcodeFormat || (BarcodeFormat = {}));\n var BarcodeFormat$1 = BarcodeFormat;\n\n /*namespace com.google.zxing {*/\n /**\n * Represents some type of metadata about the result of the decoding that the decoder\n * wishes to communicate back to the caller.\n *\n * @author Sean Owen\n */\n var ResultMetadataType;\n (function (ResultMetadataType) {\n /**\n * Unspecified, application-specific metadata. Maps to an unspecified {@link Object}.\n */\n ResultMetadataType[ResultMetadataType[\"OTHER\"] = 0] = \"OTHER\";\n /**\n * Denotes the likely approximate orientation of the barcode in the image. This value\n * is given as degrees rotated clockwise from the normal, upright orientation.\n * For example a 1D barcode which was found by reading top-to-bottom would be\n * said to have orientation \"90\". This key maps to an {@link Integer} whose\n * value is in the range [0,360).\n */\n ResultMetadataType[ResultMetadataType[\"ORIENTATION\"] = 1] = \"ORIENTATION\";\n /**\n *

2D barcode formats typically encode text, but allow for a sort of 'byte mode'\n * which is sometimes used to encode binary data. While {@link Result} makes available\n * the complete raw bytes in the barcode for these formats, it does not offer the bytes\n * from the byte segments alone.

\n *\n *

This maps to a {@link java.util.List} of byte arrays corresponding to the\n * raw bytes in the byte segments in the barcode, in order.

\n */\n ResultMetadataType[ResultMetadataType[\"BYTE_SEGMENTS\"] = 2] = \"BYTE_SEGMENTS\";\n /**\n * Error correction level used, if applicable. The value type depends on the\n * format, but is typically a String.\n */\n ResultMetadataType[ResultMetadataType[\"ERROR_CORRECTION_LEVEL\"] = 3] = \"ERROR_CORRECTION_LEVEL\";\n /**\n * For some periodicals, indicates the issue number as an {@link Integer}.\n */\n ResultMetadataType[ResultMetadataType[\"ISSUE_NUMBER\"] = 4] = \"ISSUE_NUMBER\";\n /**\n * For some products, indicates the suggested retail price in the barcode as a\n * formatted {@link String}.\n */\n ResultMetadataType[ResultMetadataType[\"SUGGESTED_PRICE\"] = 5] = \"SUGGESTED_PRICE\";\n /**\n * For some products, the possible country of manufacture as a {@link String} denoting the\n * ISO country code. Some map to multiple possible countries, like \"US/CA\".\n */\n ResultMetadataType[ResultMetadataType[\"POSSIBLE_COUNTRY\"] = 6] = \"POSSIBLE_COUNTRY\";\n /**\n * For some products, the extension text\n */\n ResultMetadataType[ResultMetadataType[\"UPC_EAN_EXTENSION\"] = 7] = \"UPC_EAN_EXTENSION\";\n /**\n * PDF417-specific metadata\n */\n ResultMetadataType[ResultMetadataType[\"PDF417_EXTRA_METADATA\"] = 8] = \"PDF417_EXTRA_METADATA\";\n /**\n * If the code format supports structured append and the current scanned code is part of one then the\n * sequence number is given with it.\n */\n ResultMetadataType[ResultMetadataType[\"STRUCTURED_APPEND_SEQUENCE\"] = 9] = \"STRUCTURED_APPEND_SEQUENCE\";\n /**\n * If the code format supports structured append and the current scanned code is part of one then the\n * parity is given with it.\n */\n ResultMetadataType[ResultMetadataType[\"STRUCTURED_APPEND_PARITY\"] = 10] = \"STRUCTURED_APPEND_PARITY\";\n })(ResultMetadataType || (ResultMetadataType = {}));\n var ResultMetadataType$1 = ResultMetadataType;\n\n /*\n * Copyright 2007 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n /*namespace com.google.zxing.common {*/\n /*import java.util.List;*/\n /**\n *

Encapsulates the result of decoding a matrix of bits. This typically\n * applies to 2D barcode formats. For now it contains the raw bytes obtained,\n * as well as a String interpretation of those bytes, if applicable.

\n *\n * @author Sean Owen\n */\n class DecoderResult {\n // public constructor(rawBytes: Uint8Array,\n // text: string,\n // List byteSegments,\n // String ecLevel) {\n // this(rawBytes, text, byteSegments, ecLevel, -1, -1)\n // }\n constructor(rawBytes, text, byteSegments, ecLevel, structuredAppendSequenceNumber = -1, structuredAppendParity = -1) {\n this.rawBytes = rawBytes;\n this.text = text;\n this.byteSegments = byteSegments;\n this.ecLevel = ecLevel;\n this.structuredAppendSequenceNumber = structuredAppendSequenceNumber;\n this.structuredAppendParity = structuredAppendParity;\n this.numBits = (rawBytes === undefined || rawBytes === null) ? 0 : 8 * rawBytes.length;\n }\n /**\n * @return raw bytes representing the result, or {@code null} if not applicable\n */\n getRawBytes() {\n return this.rawBytes;\n }\n /**\n * @return how many bits of {@link #getRawBytes()} are valid; typically 8 times its length\n * @since 3.3.0\n */\n getNumBits() {\n return this.numBits;\n }\n /**\n * @param numBits overrides the number of bits that are valid in {@link #getRawBytes()}\n * @since 3.3.0\n */\n setNumBits(numBits /*int*/) {\n this.numBits = numBits;\n }\n /**\n * @return text representation of the result\n */\n getText() {\n return this.text;\n }\n /**\n * @return list of byte segments in the result, or {@code null} if not applicable\n */\n getByteSegments() {\n return this.byteSegments;\n }\n /**\n * @return name of error correction level used, or {@code null} if not applicable\n */\n getECLevel() {\n return this.ecLevel;\n }\n /**\n * @return number of errors corrected, or {@code null} if not applicable\n */\n getErrorsCorrected() {\n return this.errorsCorrected;\n }\n setErrorsCorrected(errorsCorrected /*Integer*/) {\n this.errorsCorrected = errorsCorrected;\n }\n /**\n * @return number of erasures corrected, or {@code null} if not applicable\n */\n getErasures() {\n return this.erasures;\n }\n setErasures(erasures /*Integer*/) {\n this.erasures = erasures;\n }\n /**\n * @return arbitrary additional metadata\n */\n getOther() {\n return this.other;\n }\n setOther(other) {\n this.other = other;\n }\n hasStructuredAppend() {\n return this.structuredAppendParity >= 0 && this.structuredAppendSequenceNumber >= 0;\n }\n getStructuredAppendParity() {\n return this.structuredAppendParity;\n }\n getStructuredAppendSequenceNumber() {\n return this.structuredAppendSequenceNumber;\n }\n }\n\n /*\n * Copyright 2007 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n /**\n *

This class contains utility methods for performing mathematical operations over\n * the Galois Fields. Operations use a given primitive polynomial in calculations.

\n *\n *

Throughout this package, elements of the GF are represented as an {@code int}\n * for convenience and speed (but at the cost of memory).\n *

\n *\n * @author Sean Owen\n * @author David Olivier\n */\n class AbstractGenericGF {\n /**\n * @return 2 to the power of a in GF(size)\n */\n exp(a) {\n return this.expTable[a];\n }\n /**\n * @return base 2 log of a in GF(size)\n */\n log(a /*int*/) {\n if (a === 0) {\n throw new IllegalArgumentException();\n }\n return this.logTable[a];\n }\n /**\n * Implements both addition and subtraction -- they are the same in GF(size).\n *\n * @return sum/difference of a and b\n */\n static addOrSubtract(a /*int*/, b /*int*/) {\n return a ^ b;\n }\n }\n\n /*\n * Copyright 2007 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n /**\n *

Represents a polynomial whose coefficients are elements of a GF.\n * Instances of this class are immutable.

\n *\n *

Much credit is due to William Rucklidge since portions of this code are an indirect\n * port of his C++ Reed-Solomon implementation.

\n *\n * @author Sean Owen\n */\n class GenericGFPoly {\n /**\n * @param field the {@link GenericGF} instance representing the field to use\n * to perform computations\n * @param coefficients coefficients as ints representing elements of GF(size), arranged\n * from most significant (highest-power term) coefficient to least significant\n * @throws IllegalArgumentException if argument is null or empty,\n * or if leading coefficient is 0 and this is not a\n * constant polynomial (that is, it is not the monomial \"0\")\n */\n constructor(field, coefficients) {\n if (coefficients.length === 0) {\n throw new IllegalArgumentException();\n }\n this.field = field;\n const coefficientsLength = coefficients.length;\n if (coefficientsLength > 1 && coefficients[0] === 0) {\n // Leading term must be non-zero for anything except the constant polynomial \"0\"\n let firstNonZero = 1;\n while (firstNonZero < coefficientsLength && coefficients[firstNonZero] === 0) {\n firstNonZero++;\n }\n if (firstNonZero === coefficientsLength) {\n this.coefficients = Int32Array.from([0]);\n }\n else {\n this.coefficients = new Int32Array(coefficientsLength - firstNonZero);\n System.arraycopy(coefficients, firstNonZero, this.coefficients, 0, this.coefficients.length);\n }\n }\n else {\n this.coefficients = coefficients;\n }\n }\n getCoefficients() {\n return this.coefficients;\n }\n /**\n * @return degree of this polynomial\n */\n getDegree() {\n return this.coefficients.length - 1;\n }\n /**\n * @return true iff this polynomial is the monomial \"0\"\n */\n isZero() {\n return this.coefficients[0] === 0;\n }\n /**\n * @return coefficient of x^degree term in this polynomial\n */\n getCoefficient(degree /*int*/) {\n return this.coefficients[this.coefficients.length - 1 - degree];\n }\n /**\n * @return evaluation of this polynomial at a given point\n */\n evaluateAt(a /*int*/) {\n if (a === 0) {\n // Just return the x^0 coefficient\n return this.getCoefficient(0);\n }\n const coefficients = this.coefficients;\n let result;\n if (a === 1) {\n // Just the sum of the coefficients\n result = 0;\n for (let i = 0, length = coefficients.length; i !== length; i++) {\n const coefficient = coefficients[i];\n result = AbstractGenericGF.addOrSubtract(result, coefficient);\n }\n return result;\n }\n result = coefficients[0];\n const size = coefficients.length;\n const field = this.field;\n for (let i = 1; i < size; i++) {\n result = AbstractGenericGF.addOrSubtract(field.multiply(a, result), coefficients[i]);\n }\n return result;\n }\n addOrSubtract(other) {\n if (!this.field.equals(other.field)) {\n throw new IllegalArgumentException('GenericGFPolys do not have same GenericGF field');\n }\n if (this.isZero()) {\n return other;\n }\n if (other.isZero()) {\n return this;\n }\n let smallerCoefficients = this.coefficients;\n let largerCoefficients = other.coefficients;\n if (smallerCoefficients.length > largerCoefficients.length) {\n const temp = smallerCoefficients;\n smallerCoefficients = largerCoefficients;\n largerCoefficients = temp;\n }\n let sumDiff = new Int32Array(largerCoefficients.length);\n const lengthDiff = largerCoefficients.length - smallerCoefficients.length;\n // Copy high-order terms only found in higher-degree polynomial's coefficients\n System.arraycopy(largerCoefficients, 0, sumDiff, 0, lengthDiff);\n for (let i = lengthDiff; i < largerCoefficients.length; i++) {\n sumDiff[i] = AbstractGenericGF.addOrSubtract(smallerCoefficients[i - lengthDiff], largerCoefficients[i]);\n }\n return new GenericGFPoly(this.field, sumDiff);\n }\n multiply(other) {\n if (!this.field.equals(other.field)) {\n throw new IllegalArgumentException('GenericGFPolys do not have same GenericGF field');\n }\n if (this.isZero() || other.isZero()) {\n return this.field.getZero();\n }\n const aCoefficients = this.coefficients;\n const aLength = aCoefficients.length;\n const bCoefficients = other.coefficients;\n const bLength = bCoefficients.length;\n const product = new Int32Array(aLength + bLength - 1);\n const field = this.field;\n for (let i = 0; i < aLength; i++) {\n const aCoeff = aCoefficients[i];\n for (let j = 0; j < bLength; j++) {\n product[i + j] = AbstractGenericGF.addOrSubtract(product[i + j], field.multiply(aCoeff, bCoefficients[j]));\n }\n }\n return new GenericGFPoly(field, product);\n }\n multiplyScalar(scalar /*int*/) {\n if (scalar === 0) {\n return this.field.getZero();\n }\n if (scalar === 1) {\n return this;\n }\n const size = this.coefficients.length;\n const field = this.field;\n const product = new Int32Array(size);\n const coefficients = this.coefficients;\n for (let i = 0; i < size; i++) {\n product[i] = field.multiply(coefficients[i], scalar);\n }\n return new GenericGFPoly(field, product);\n }\n multiplyByMonomial(degree /*int*/, coefficient /*int*/) {\n if (degree < 0) {\n throw new IllegalArgumentException();\n }\n if (coefficient === 0) {\n return this.field.getZero();\n }\n const coefficients = this.coefficients;\n const size = coefficients.length;\n const product = new Int32Array(size + degree);\n const field = this.field;\n for (let i = 0; i < size; i++) {\n product[i] = field.multiply(coefficients[i], coefficient);\n }\n return new GenericGFPoly(field, product);\n }\n divide(other) {\n if (!this.field.equals(other.field)) {\n throw new IllegalArgumentException('GenericGFPolys do not have same GenericGF field');\n }\n if (other.isZero()) {\n throw new IllegalArgumentException('Divide by 0');\n }\n const field = this.field;\n let quotient = field.getZero();\n let remainder = this;\n const denominatorLeadingTerm = other.getCoefficient(other.getDegree());\n const inverseDenominatorLeadingTerm = field.inverse(denominatorLeadingTerm);\n while (remainder.getDegree() >= other.getDegree() && !remainder.isZero()) {\n const degreeDifference = remainder.getDegree() - other.getDegree();\n const scale = field.multiply(remainder.getCoefficient(remainder.getDegree()), inverseDenominatorLeadingTerm);\n const term = other.multiplyByMonomial(degreeDifference, scale);\n const iterationQuotient = field.buildMonomial(degreeDifference, scale);\n quotient = quotient.addOrSubtract(iterationQuotient);\n remainder = remainder.addOrSubtract(term);\n }\n return [quotient, remainder];\n }\n /*@Override*/\n toString() {\n let result = '';\n for (let degree = this.getDegree(); degree >= 0; degree--) {\n let coefficient = this.getCoefficient(degree);\n if (coefficient !== 0) {\n if (coefficient < 0) {\n result += ' - ';\n coefficient = -coefficient;\n }\n else {\n if (result.length > 0) {\n result += ' + ';\n }\n }\n if (degree === 0 || coefficient !== 1) {\n const alphaPower = this.field.log(coefficient);\n if (alphaPower === 0) {\n result += '1';\n }\n else if (alphaPower === 1) {\n result += 'a';\n }\n else {\n result += 'a^';\n result += alphaPower;\n }\n }\n if (degree !== 0) {\n if (degree === 1) {\n result += 'x';\n }\n else {\n result += 'x^';\n result += degree;\n }\n }\n }\n }\n return result;\n }\n }\n\n /**\n * Custom Error class of type Exception.\n */\n class ArithmeticException extends Exception {\n }\n ArithmeticException.kind = 'ArithmeticException';\n\n /*\n * Copyright 2007 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n /**\n *

This class contains utility methods for performing mathematical operations over\n * the Galois Fields. Operations use a given primitive polynomial in calculations.

\n *\n *

Throughout this package, elements of the GF are represented as an {@code int}\n * for convenience and speed (but at the cost of memory).\n *

\n *\n * @author Sean Owen\n * @author David Olivier\n */\n class GenericGF extends AbstractGenericGF {\n /**\n * Create a representation of GF(size) using the given primitive polynomial.\n *\n * @param primitive irreducible polynomial whose coefficients are represented by\n * the bits of an int, where the least-significant bit represents the constant\n * coefficient\n * @param size the size of the field\n * @param b the factor b in the generator polynomial can be 0- or 1-based\n * (g(x) = (x+a^b)(x+a^(b+1))...(x+a^(b+2t-1))).\n * In most cases it should be 1, but for QR code it is 0.\n */\n constructor(primitive /*int*/, size /*int*/, generatorBase /*int*/) {\n super();\n this.primitive = primitive;\n this.size = size;\n this.generatorBase = generatorBase;\n const expTable = new Int32Array(size);\n let x = 1;\n for (let i = 0; i < size; i++) {\n expTable[i] = x;\n x *= 2; // we're assuming the generator alpha is 2\n if (x >= size) {\n x ^= primitive;\n x &= size - 1;\n }\n }\n this.expTable = expTable;\n const logTable = new Int32Array(size);\n for (let i = 0; i < size - 1; i++) {\n logTable[expTable[i]] = i;\n }\n this.logTable = logTable;\n // logTable[0] == 0 but this should never be used\n this.zero = new GenericGFPoly(this, Int32Array.from([0]));\n this.one = new GenericGFPoly(this, Int32Array.from([1]));\n }\n getZero() {\n return this.zero;\n }\n getOne() {\n return this.one;\n }\n /**\n * @return the monomial representing coefficient * x^degree\n */\n buildMonomial(degree /*int*/, coefficient /*int*/) {\n if (degree < 0) {\n throw new IllegalArgumentException();\n }\n if (coefficient === 0) {\n return this.zero;\n }\n const coefficients = new Int32Array(degree + 1);\n coefficients[0] = coefficient;\n return new GenericGFPoly(this, coefficients);\n }\n /**\n * @return multiplicative inverse of a\n */\n inverse(a /*int*/) {\n if (a === 0) {\n throw new ArithmeticException();\n }\n return this.expTable[this.size - this.logTable[a] - 1];\n }\n /**\n * @return product of a and b in GF(size)\n */\n multiply(a /*int*/, b /*int*/) {\n if (a === 0 || b === 0) {\n return 0;\n }\n return this.expTable[(this.logTable[a] + this.logTable[b]) % (this.size - 1)];\n }\n getSize() {\n return this.size;\n }\n getGeneratorBase() {\n return this.generatorBase;\n }\n /*@Override*/\n toString() {\n return ('GF(0x' + Integer.toHexString(this.primitive) + ',' + this.size + ')');\n }\n equals(o) {\n return o === this;\n }\n }\n GenericGF.AZTEC_DATA_12 = new GenericGF(0x1069, 4096, 1); // x^12 + x^6 + x^5 + x^3 + 1\n GenericGF.AZTEC_DATA_10 = new GenericGF(0x409, 1024, 1); // x^10 + x^3 + 1\n GenericGF.AZTEC_DATA_6 = new GenericGF(0x43, 64, 1); // x^6 + x + 1\n GenericGF.AZTEC_PARAM = new GenericGF(0x13, 16, 1); // x^4 + x + 1\n GenericGF.QR_CODE_FIELD_256 = new GenericGF(0x011d, 256, 0); // x^8 + x^4 + x^3 + x^2 + 1\n GenericGF.DATA_MATRIX_FIELD_256 = new GenericGF(0x012d, 256, 1); // x^8 + x^5 + x^3 + x^2 + 1\n GenericGF.AZTEC_DATA_8 = GenericGF.DATA_MATRIX_FIELD_256;\n GenericGF.MAXICODE_FIELD_64 = GenericGF.AZTEC_DATA_6;\n\n /**\n * Custom Error class of type Exception.\n */\n class ReedSolomonException extends Exception {\n }\n ReedSolomonException.kind = 'ReedSolomonException';\n\n /**\n * Custom Error class of type Exception.\n */\n class IllegalStateException extends Exception {\n }\n IllegalStateException.kind = 'IllegalStateException';\n\n /*\n * Copyright 2007 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n /**\n *

Implements Reed-Solomon decoding, as the name implies.

\n *\n *

The algorithm will not be explained here, but the following references were helpful\n * in creating this implementation:

\n *\n * \n *\n *

Much credit is due to William Rucklidge since portions of this code are an indirect\n * port of his C++ Reed-Solomon implementation.

\n *\n * @author Sean Owen\n * @author William Rucklidge\n * @author sanfordsquires\n */\n class ReedSolomonDecoder {\n constructor(field) {\n this.field = field;\n }\n /**\n *

Decodes given set of received codewords, which include both data and error-correction\n * codewords. Really, this means it uses Reed-Solomon to detect and correct errors, in-place,\n * in the input.

\n *\n * @param received data and error-correction codewords\n * @param twoS number of error-correction codewords available\n * @throws ReedSolomonException if decoding fails for any reason\n */\n decode(received, twoS /*int*/) {\n const field = this.field;\n const poly = new GenericGFPoly(field, received);\n const syndromeCoefficients = new Int32Array(twoS);\n let noError = true;\n for (let i = 0; i < twoS; i++) {\n const evalResult = poly.evaluateAt(field.exp(i + field.getGeneratorBase()));\n syndromeCoefficients[syndromeCoefficients.length - 1 - i] = evalResult;\n if (evalResult !== 0) {\n noError = false;\n }\n }\n if (noError) {\n return;\n }\n const syndrome = new GenericGFPoly(field, syndromeCoefficients);\n const sigmaOmega = this.runEuclideanAlgorithm(field.buildMonomial(twoS, 1), syndrome, twoS);\n const sigma = sigmaOmega[0];\n const omega = sigmaOmega[1];\n const errorLocations = this.findErrorLocations(sigma);\n const errorMagnitudes = this.findErrorMagnitudes(omega, errorLocations);\n for (let i = 0; i < errorLocations.length; i++) {\n const position = received.length - 1 - field.log(errorLocations[i]);\n if (position < 0) {\n throw new ReedSolomonException('Bad error location');\n }\n received[position] = GenericGF.addOrSubtract(received[position], errorMagnitudes[i]);\n }\n }\n runEuclideanAlgorithm(a, b, R /*int*/) {\n // Assume a's degree is >= b's\n if (a.getDegree() < b.getDegree()) {\n const temp = a;\n a = b;\n b = temp;\n }\n const field = this.field;\n let rLast = a;\n let r = b;\n let tLast = field.getZero();\n let t = field.getOne();\n // Run Euclidean algorithm until r's degree is less than R/2\n while (r.getDegree() >= (R / 2 | 0)) {\n let rLastLast = rLast;\n let tLastLast = tLast;\n rLast = r;\n tLast = t;\n // Divide rLastLast by rLast, with quotient in q and remainder in r\n if (rLast.isZero()) {\n // Oops, Euclidean algorithm already terminated?\n throw new ReedSolomonException('r_{i-1} was zero');\n }\n r = rLastLast;\n let q = field.getZero();\n const denominatorLeadingTerm = rLast.getCoefficient(rLast.getDegree());\n const dltInverse = field.inverse(denominatorLeadingTerm);\n while (r.getDegree() >= rLast.getDegree() && !r.isZero()) {\n const degreeDiff = r.getDegree() - rLast.getDegree();\n const scale = field.multiply(r.getCoefficient(r.getDegree()), dltInverse);\n q = q.addOrSubtract(field.buildMonomial(degreeDiff, scale));\n r = r.addOrSubtract(rLast.multiplyByMonomial(degreeDiff, scale));\n }\n t = q.multiply(tLast).addOrSubtract(tLastLast);\n if (r.getDegree() >= rLast.getDegree()) {\n throw new IllegalStateException('Division algorithm failed to reduce polynomial?');\n }\n }\n const sigmaTildeAtZero = t.getCoefficient(0);\n if (sigmaTildeAtZero === 0) {\n throw new ReedSolomonException('sigmaTilde(0) was zero');\n }\n const inverse = field.inverse(sigmaTildeAtZero);\n const sigma = t.multiplyScalar(inverse);\n const omega = r.multiplyScalar(inverse);\n return [sigma, omega];\n }\n findErrorLocations(errorLocator) {\n // This is a direct application of Chien's search\n const numErrors = errorLocator.getDegree();\n if (numErrors === 1) { // shortcut\n return Int32Array.from([errorLocator.getCoefficient(1)]);\n }\n const result = new Int32Array(numErrors);\n let e = 0;\n const field = this.field;\n for (let i = 1; i < field.getSize() && e < numErrors; i++) {\n if (errorLocator.evaluateAt(i) === 0) {\n result[e] = field.inverse(i);\n e++;\n }\n }\n if (e !== numErrors) {\n throw new ReedSolomonException('Error locator degree does not match number of roots');\n }\n return result;\n }\n findErrorMagnitudes(errorEvaluator, errorLocations) {\n // This is directly applying Forney's Formula\n const s = errorLocations.length;\n const result = new Int32Array(s);\n const field = this.field;\n for (let i = 0; i < s; i++) {\n const xiInverse = field.inverse(errorLocations[i]);\n let denominator = 1;\n for (let j = 0; j < s; j++) {\n if (i !== j) {\n // denominator = field.multiply(denominator,\n // GenericGF.addOrSubtract(1, field.multiply(errorLocations[j], xiInverse)))\n // Above should work but fails on some Apple and Linux JDKs due to a Hotspot bug.\n // Below is a funny-looking workaround from Steven Parkes\n const term = field.multiply(errorLocations[j], xiInverse);\n const termPlus1 = (term & 0x1) === 0 ? term | 1 : term & ~1;\n denominator = field.multiply(denominator, termPlus1);\n }\n }\n result[i] = field.multiply(errorEvaluator.evaluateAt(xiInverse), field.inverse(denominator));\n if (field.getGeneratorBase() !== 0) {\n result[i] = field.multiply(result[i], xiInverse);\n }\n }\n return result;\n }\n }\n\n /*\n * Copyright 2010 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n // import java.util.Arrays;\n var Table;\n (function (Table) {\n Table[Table[\"UPPER\"] = 0] = \"UPPER\";\n Table[Table[\"LOWER\"] = 1] = \"LOWER\";\n Table[Table[\"MIXED\"] = 2] = \"MIXED\";\n Table[Table[\"DIGIT\"] = 3] = \"DIGIT\";\n Table[Table[\"PUNCT\"] = 4] = \"PUNCT\";\n Table[Table[\"BINARY\"] = 5] = \"BINARY\";\n })(Table || (Table = {}));\n /**\n *

The main class which implements Aztec Code decoding -- as opposed to locating and extracting\n * the Aztec Code from an image.

\n *\n * @author David Olivier\n */\n class Decoder {\n decode(detectorResult) {\n this.ddata = detectorResult;\n let matrix = detectorResult.getBits();\n let rawbits = this.extractBits(matrix);\n let correctedBits = this.correctBits(rawbits);\n let rawBytes = Decoder.convertBoolArrayToByteArray(correctedBits);\n let result = Decoder.getEncodedData(correctedBits);\n let decoderResult = new DecoderResult(rawBytes, result, null, null);\n decoderResult.setNumBits(correctedBits.length);\n return decoderResult;\n }\n // This method is used for testing the high-level encoder\n static highLevelDecode(correctedBits) {\n return this.getEncodedData(correctedBits);\n }\n /**\n * Gets the string encoded in the aztec code bits\n *\n * @return the decoded string\n */\n static getEncodedData(correctedBits) {\n let endIndex = correctedBits.length;\n let latchTable = Table.UPPER; // table most recently latched to\n let shiftTable = Table.UPPER; // table to use for the next read\n let result = '';\n let index = 0;\n while (index < endIndex) {\n if (shiftTable === Table.BINARY) {\n if (endIndex - index < 5) {\n break;\n }\n let length = Decoder.readCode(correctedBits, index, 5);\n index += 5;\n if (length === 0) {\n if (endIndex - index < 11) {\n break;\n }\n length = Decoder.readCode(correctedBits, index, 11) + 31;\n index += 11;\n }\n for (let charCount = 0; charCount < length; charCount++) {\n if (endIndex - index < 8) {\n index = endIndex; // Force outer loop to exit\n break;\n }\n const code = Decoder.readCode(correctedBits, index, 8);\n result += /*(char)*/ StringUtils.castAsNonUtf8Char(code);\n index += 8;\n }\n // Go back to whatever mode we had been in\n shiftTable = latchTable;\n }\n else {\n let size = shiftTable === Table.DIGIT ? 4 : 5;\n if (endIndex - index < size) {\n break;\n }\n let code = Decoder.readCode(correctedBits, index, size);\n index += size;\n let str = Decoder.getCharacter(shiftTable, code);\n if (str.startsWith('CTRL_')) {\n // Table changes\n // ISO/IEC 24778:2008 prescribes ending a shift sequence in the mode from which it was invoked.\n // That's including when that mode is a shift.\n // Our test case dlusbs.png for issue #642 exercises that.\n latchTable = shiftTable; // Latch the current mode, so as to return to Upper after U/S B/S\n shiftTable = Decoder.getTable(str.charAt(5));\n if (str.charAt(6) === 'L') {\n latchTable = shiftTable;\n }\n }\n else {\n result += str;\n // Go back to whatever mode we had been in\n shiftTable = latchTable;\n }\n }\n }\n return result;\n }\n /**\n * gets the table corresponding to the char passed\n */\n static getTable(t) {\n switch (t) {\n case 'L':\n return Table.LOWER;\n case 'P':\n return Table.PUNCT;\n case 'M':\n return Table.MIXED;\n case 'D':\n return Table.DIGIT;\n case 'B':\n return Table.BINARY;\n case 'U':\n default:\n return Table.UPPER;\n }\n }\n /**\n * Gets the character (or string) corresponding to the passed code in the given table\n *\n * @param table the table used\n * @param code the code of the character\n */\n static getCharacter(table, code) {\n switch (table) {\n case Table.UPPER:\n return Decoder.UPPER_TABLE[code];\n case Table.LOWER:\n return Decoder.LOWER_TABLE[code];\n case Table.MIXED:\n return Decoder.MIXED_TABLE[code];\n case Table.PUNCT:\n return Decoder.PUNCT_TABLE[code];\n case Table.DIGIT:\n return Decoder.DIGIT_TABLE[code];\n default:\n // Should not reach here.\n throw new IllegalStateException('Bad table');\n }\n }\n /**\n *

Performs RS error correction on an array of bits.

\n *\n * @return the corrected array\n * @throws FormatException if the input contains too many errors\n */\n correctBits(rawbits) {\n let gf;\n let codewordSize;\n if (this.ddata.getNbLayers() <= 2) {\n codewordSize = 6;\n gf = GenericGF.AZTEC_DATA_6;\n }\n else if (this.ddata.getNbLayers() <= 8) {\n codewordSize = 8;\n gf = GenericGF.AZTEC_DATA_8;\n }\n else if (this.ddata.getNbLayers() <= 22) {\n codewordSize = 10;\n gf = GenericGF.AZTEC_DATA_10;\n }\n else {\n codewordSize = 12;\n gf = GenericGF.AZTEC_DATA_12;\n }\n let numDataCodewords = this.ddata.getNbDatablocks();\n let numCodewords = rawbits.length / codewordSize;\n if (numCodewords < numDataCodewords) {\n throw new FormatException();\n }\n let offset = rawbits.length % codewordSize;\n let dataWords = new Int32Array(numCodewords);\n for (let i = 0; i < numCodewords; i++, offset += codewordSize) {\n dataWords[i] = Decoder.readCode(rawbits, offset, codewordSize);\n }\n try {\n let rsDecoder = new ReedSolomonDecoder(gf);\n rsDecoder.decode(dataWords, numCodewords - numDataCodewords);\n }\n catch (ex) {\n throw new FormatException(ex);\n }\n // Now perform the unstuffing operation.\n // First, count how many bits are going to be thrown out as stuffing\n let mask = (1 << codewordSize) - 1;\n let stuffedBits = 0;\n for (let i = 0; i < numDataCodewords; i++) {\n let dataWord = dataWords[i];\n if (dataWord === 0 || dataWord === mask) {\n throw new FormatException();\n }\n else if (dataWord === 1 || dataWord === mask - 1) {\n stuffedBits++;\n }\n }\n // Now, actually unpack the bits and remove the stuffing\n let correctedBits = new Array(numDataCodewords * codewordSize - stuffedBits);\n let index = 0;\n for (let i = 0; i < numDataCodewords; i++) {\n let dataWord = dataWords[i];\n if (dataWord === 1 || dataWord === mask - 1) {\n // next codewordSize-1 bits are all zeros or all ones\n correctedBits.fill(dataWord > 1, index, index + codewordSize - 1);\n // Arrays.fill(correctedBits, index, index + codewordSize - 1, dataWord > 1);\n index += codewordSize - 1;\n }\n else {\n for (let bit = codewordSize - 1; bit >= 0; --bit) {\n correctedBits[index++] = (dataWord & (1 << bit)) !== 0;\n }\n }\n }\n return correctedBits;\n }\n /**\n * Gets the array of bits from an Aztec Code matrix\n *\n * @return the array of bits\n */\n extractBits(matrix) {\n let compact = this.ddata.isCompact();\n let layers = this.ddata.getNbLayers();\n let baseMatrixSize = (compact ? 11 : 14) + layers * 4; // not including alignment lines\n let alignmentMap = new Int32Array(baseMatrixSize);\n let rawbits = new Array(this.totalBitsInLayer(layers, compact));\n if (compact) {\n for (let i = 0; i < alignmentMap.length; i++) {\n alignmentMap[i] = i;\n }\n }\n else {\n let matrixSize = baseMatrixSize + 1 + 2 * Integer.truncDivision((Integer.truncDivision(baseMatrixSize, 2) - 1), 15);\n let origCenter = baseMatrixSize / 2;\n let center = Integer.truncDivision(matrixSize, 2);\n for (let i = 0; i < origCenter; i++) {\n let newOffset = i + Integer.truncDivision(i, 15);\n alignmentMap[origCenter - i - 1] = center - newOffset - 1;\n alignmentMap[origCenter + i] = center + newOffset + 1;\n }\n }\n for (let i = 0, rowOffset = 0; i < layers; i++) {\n let rowSize = (layers - i) * 4 + (compact ? 9 : 12);\n // The top-left most point of this layer is (not including alignment lines)\n let low = i * 2;\n // The bottom-right most point of this layer is (not including alignment lines)\n let high = baseMatrixSize - 1 - low;\n // We pull bits from the two 2 x rowSize columns and two rowSize x 2 rows\n for (let j = 0; j < rowSize; j++) {\n let columnOffset = j * 2;\n for (let k = 0; k < 2; k++) {\n // left column\n rawbits[rowOffset + columnOffset + k] =\n matrix.get(alignmentMap[low + k], alignmentMap[low + j]);\n // bottom row\n rawbits[rowOffset + 2 * rowSize + columnOffset + k] =\n matrix.get(alignmentMap[low + j], alignmentMap[high - k]);\n // right column\n rawbits[rowOffset + 4 * rowSize + columnOffset + k] =\n matrix.get(alignmentMap[high - k], alignmentMap[high - j]);\n // top row\n rawbits[rowOffset + 6 * rowSize + columnOffset + k] =\n matrix.get(alignmentMap[high - j], alignmentMap[low + k]);\n }\n }\n rowOffset += rowSize * 8;\n }\n return rawbits;\n }\n /**\n * Reads a code of given length and at given index in an array of bits\n */\n static readCode(rawbits, startIndex, length) {\n let res = 0;\n for (let i = startIndex; i < startIndex + length; i++) {\n res <<= 1;\n if (rawbits[i]) {\n res |= 0x01;\n }\n }\n return res;\n }\n /**\n * Reads a code of length 8 in an array of bits, padding with zeros\n */\n static readByte(rawbits, startIndex) {\n let n = rawbits.length - startIndex;\n if (n >= 8) {\n return Decoder.readCode(rawbits, startIndex, 8);\n }\n return Decoder.readCode(rawbits, startIndex, n) << (8 - n);\n }\n /**\n * Packs a bit array into bytes, most significant bit first\n */\n static convertBoolArrayToByteArray(boolArr) {\n let byteArr = new Uint8Array((boolArr.length + 7) / 8);\n for (let i = 0; i < byteArr.length; i++) {\n byteArr[i] = Decoder.readByte(boolArr, 8 * i);\n }\n return byteArr;\n }\n totalBitsInLayer(layers, compact) {\n return ((compact ? 88 : 112) + 16 * layers) * layers;\n }\n }\n Decoder.UPPER_TABLE = [\n 'CTRL_PS', ' ', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',\n 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'CTRL_LL', 'CTRL_ML', 'CTRL_DL', 'CTRL_BS'\n ];\n Decoder.LOWER_TABLE = [\n 'CTRL_PS', ' ', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p',\n 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'CTRL_US', 'CTRL_ML', 'CTRL_DL', 'CTRL_BS'\n ];\n Decoder.MIXED_TABLE = [\n // Module parse failed: Octal literal in strict mode (50:29)\n // so number string were scaped\n 'CTRL_PS', ' ', '\\\\1', '\\\\2', '\\\\3', '\\\\4', '\\\\5', '\\\\6', '\\\\7', '\\b', '\\t', '\\n',\n '\\\\13', '\\f', '\\r', '\\\\33', '\\\\34', '\\\\35', '\\\\36', '\\\\37', '@', '\\\\', '^', '_',\n '`', '|', '~', '\\\\177', 'CTRL_LL', 'CTRL_UL', 'CTRL_PL', 'CTRL_BS'\n ];\n Decoder.PUNCT_TABLE = [\n '', '\\r', '\\r\\n', '. ', ', ', ': ', '!', '\"', '#', '$', '%', '&', '\\'', '(', ')',\n '*', '+', ',', '-', '.', '/', ':', ';', '<', '=', '>', '?', '[', ']', '{', '}', 'CTRL_UL'\n ];\n Decoder.DIGIT_TABLE = [\n 'CTRL_PS', ' ', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ',', '.', 'CTRL_UL', 'CTRL_US'\n ];\n\n /*\n * Copyright 2012 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n /*namespace com.google.zxing.common.detector {*/\n /**\n * General math-related and numeric utility functions.\n */\n class MathUtils {\n constructor() { }\n /**\n * Ends up being a bit faster than {@link Math#round(float)}. This merely rounds its\n * argument to the nearest int, where x.5 rounds up to x+1. Semantics of this shortcut\n * differ slightly from {@link Math#round(float)} in that half rounds down for negative\n * values. -2.5 rounds to -3, not -2. For purposes here it makes no difference.\n *\n * @param d real value to round\n * @return nearest {@code int}\n */\n static round(d /*float*/) {\n if (NaN === d)\n return 0;\n if (d <= Number.MIN_SAFE_INTEGER)\n return Number.MIN_SAFE_INTEGER;\n if (d >= Number.MAX_SAFE_INTEGER)\n return Number.MAX_SAFE_INTEGER;\n return /*(int) */ (d + (d < 0.0 ? -0.5 : 0.5)) | 0;\n }\n // TYPESCRIPTPORT: maybe remove round method and call directly Math.round, it looks like it doesn't make sense for js\n /**\n * @param aX point A x coordinate\n * @param aY point A y coordinate\n * @param bX point B x coordinate\n * @param bY point B y coordinate\n * @return Euclidean distance between points A and B\n */\n static distance(aX /*float|int*/, aY /*float|int*/, bX /*float|int*/, bY /*float|int*/) {\n const xDiff = aX - bX;\n const yDiff = aY - bY;\n return /*(float) */ Math.sqrt(xDiff * xDiff + yDiff * yDiff);\n }\n /**\n * @param aX point A x coordinate\n * @param aY point A y coordinate\n * @param bX point B x coordinate\n * @param bY point B y coordinate\n * @return Euclidean distance between points A and B\n */\n // public static distance(aX: number /*int*/, aY: number /*int*/, bX: number /*int*/, bY: number /*int*/): float {\n // const xDiff = aX - bX\n // const yDiff = aY - bY\n // return (float) Math.sqrt(xDiff * xDiff + yDiff * yDiff);\n // }\n /**\n * @param array values to sum\n * @return sum of values in array\n */\n static sum(array) {\n let count = 0;\n for (let i = 0, length = array.length; i !== length; i++) {\n const a = array[i];\n count += a;\n }\n return count;\n }\n }\n\n /**\n * Ponyfill for Java's Float class.\n */\n class Float {\n /**\n * SincTS has no difference between int and float, there's all numbers,\n * this is used only to polyfill Java code.\n */\n static floatToIntBits(f) {\n return f;\n }\n }\n /**\n * The float max value in JS is the number max value.\n */\n Float.MAX_VALUE = Number.MAX_SAFE_INTEGER;\n\n /*\n * Copyright 2007 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n /**\n *

Encapsulates a point of interest in an image containing a barcode. Typically, this\n * would be the location of a finder pattern or the corner of the barcode, for example.

\n *\n * @author Sean Owen\n */\n class ResultPoint {\n constructor(x, y) {\n this.x = x;\n this.y = y;\n }\n getX() {\n return this.x;\n }\n getY() {\n return this.y;\n }\n /*@Override*/\n equals(other) {\n if (other instanceof ResultPoint) {\n const otherPoint = other;\n return this.x === otherPoint.x && this.y === otherPoint.y;\n }\n return false;\n }\n /*@Override*/\n hashCode() {\n return 31 * Float.floatToIntBits(this.x) + Float.floatToIntBits(this.y);\n }\n /*@Override*/\n toString() {\n return '(' + this.x + ',' + this.y + ')';\n }\n /**\n * Orders an array of three ResultPoints in an order [A,B,C] such that AB is less than AC\n * and BC is less than AC, and the angle between BC and BA is less than 180 degrees.\n *\n * @param patterns array of three {@code ResultPoint} to order\n */\n static orderBestPatterns(patterns) {\n // Find distances between pattern centers\n const zeroOneDistance = this.distance(patterns[0], patterns[1]);\n const oneTwoDistance = this.distance(patterns[1], patterns[2]);\n const zeroTwoDistance = this.distance(patterns[0], patterns[2]);\n let pointA;\n let pointB;\n let pointC;\n // Assume one closest to other two is B; A and C will just be guesses at first\n if (oneTwoDistance >= zeroOneDistance && oneTwoDistance >= zeroTwoDistance) {\n pointB = patterns[0];\n pointA = patterns[1];\n pointC = patterns[2];\n }\n else if (zeroTwoDistance >= oneTwoDistance && zeroTwoDistance >= zeroOneDistance) {\n pointB = patterns[1];\n pointA = patterns[0];\n pointC = patterns[2];\n }\n else {\n pointB = patterns[2];\n pointA = patterns[0];\n pointC = patterns[1];\n }\n // Use cross product to figure out whether A and C are correct or flipped.\n // This asks whether BC x BA has a positive z component, which is the arrangement\n // we want for A, B, C. If it's negative, then we've got it flipped around and\n // should swap A and C.\n if (this.crossProductZ(pointA, pointB, pointC) < 0.0) {\n const temp = pointA;\n pointA = pointC;\n pointC = temp;\n }\n patterns[0] = pointA;\n patterns[1] = pointB;\n patterns[2] = pointC;\n }\n /**\n * @param pattern1 first pattern\n * @param pattern2 second pattern\n * @return distance between two points\n */\n static distance(pattern1, pattern2) {\n return MathUtils.distance(pattern1.x, pattern1.y, pattern2.x, pattern2.y);\n }\n /**\n * Returns the z component of the cross product between vectors BC and BA.\n */\n static crossProductZ(pointA, pointB, pointC) {\n const bX = pointB.x;\n const bY = pointB.y;\n return ((pointC.x - bX) * (pointA.y - bY)) - ((pointC.y - bY) * (pointA.x - bX));\n }\n }\n\n /*\n * Copyright 2007 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n /**\n *

Encapsulates the result of detecting a barcode in an image. This includes the raw\n * matrix of black/white pixels corresponding to the barcode, and possibly points of interest\n * in the image, like the location of finder patterns or corners of the barcode in the image.

\n *\n * @author Sean Owen\n */\n class DetectorResult {\n constructor(bits, points) {\n this.bits = bits;\n this.points = points;\n }\n getBits() {\n return this.bits;\n }\n getPoints() {\n return this.points;\n }\n }\n\n /*\n * Copyright 2010 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n /**\n *

Extends {@link DetectorResult} with more information specific to the Aztec format,\n * like the number of layers and whether it's compact.

\n *\n * @author Sean Owen\n */\n class AztecDetectorResult extends DetectorResult {\n constructor(bits, points, compact, nbDatablocks, nbLayers) {\n super(bits, points);\n this.compact = compact;\n this.nbDatablocks = nbDatablocks;\n this.nbLayers = nbLayers;\n }\n getNbLayers() {\n return this.nbLayers;\n }\n getNbDatablocks() {\n return this.nbDatablocks;\n }\n isCompact() {\n return this.compact;\n }\n }\n\n /*\n * Copyright 2010 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n /**\n *

\n * Detects a candidate barcode-like rectangular region within an image. It\n * starts around the center of the image, increases the size of the candidate\n * region until it finds a white rectangular region. By keeping track of the\n * last black points it encountered, it determines the corners of the barcode.\n *

\n *\n * @author David Olivier\n */\n class WhiteRectangleDetector {\n // public constructor(private image: BitMatrix) /*throws NotFoundException*/ {\n // this(image, INIT_SIZE, image.getWidth() / 2, image.getHeight() / 2)\n // }\n /**\n * @param image barcode image to find a rectangle in\n * @param initSize initial size of search area around center\n * @param x x position of search center\n * @param y y position of search center\n * @throws NotFoundException if image is too small to accommodate {@code initSize}\n */\n constructor(image, initSize /*int*/, x /*int*/, y /*int*/) {\n this.image = image;\n this.height = image.getHeight();\n this.width = image.getWidth();\n if (undefined === initSize || null === initSize) {\n initSize = WhiteRectangleDetector.INIT_SIZE;\n }\n if (undefined === x || null === x) {\n x = image.getWidth() / 2 | 0;\n }\n if (undefined === y || null === y) {\n y = image.getHeight() / 2 | 0;\n }\n const halfsize = initSize / 2 | 0;\n this.leftInit = x - halfsize;\n this.rightInit = x + halfsize;\n this.upInit = y - halfsize;\n this.downInit = y + halfsize;\n if (this.upInit < 0 || this.leftInit < 0 || this.downInit >= this.height || this.rightInit >= this.width) {\n throw new NotFoundException();\n }\n }\n /**\n *

\n * Detects a candidate barcode-like rectangular region within an image. It\n * starts around the center of the image, increases the size of the candidate\n * region until it finds a white rectangular region.\n *

\n *\n * @return {@link ResultPoint}[] describing the corners of the rectangular\n * region. The first and last points are opposed on the diagonal, as\n * are the second and third. The first point will be the topmost\n * point and the last, the bottommost. The second point will be\n * leftmost and the third, the rightmost\n * @throws NotFoundException if no Data Matrix Code can be found\n */\n detect() {\n let left = this.leftInit;\n let right = this.rightInit;\n let up = this.upInit;\n let down = this.downInit;\n let sizeExceeded = false;\n let aBlackPointFoundOnBorder = true;\n let atLeastOneBlackPointFoundOnBorder = false;\n let atLeastOneBlackPointFoundOnRight = false;\n let atLeastOneBlackPointFoundOnBottom = false;\n let atLeastOneBlackPointFoundOnLeft = false;\n let atLeastOneBlackPointFoundOnTop = false;\n const width = this.width;\n const height = this.height;\n while (aBlackPointFoundOnBorder) {\n aBlackPointFoundOnBorder = false;\n // .....\n // . |\n // .....\n let rightBorderNotWhite = true;\n while ((rightBorderNotWhite || !atLeastOneBlackPointFoundOnRight) && right < width) {\n rightBorderNotWhite = this.containsBlackPoint(up, down, right, false);\n if (rightBorderNotWhite) {\n right++;\n aBlackPointFoundOnBorder = true;\n atLeastOneBlackPointFoundOnRight = true;\n }\n else if (!atLeastOneBlackPointFoundOnRight) {\n right++;\n }\n }\n if (right >= width) {\n sizeExceeded = true;\n break;\n }\n // .....\n // . .\n // .___.\n let bottomBorderNotWhite = true;\n while ((bottomBorderNotWhite || !atLeastOneBlackPointFoundOnBottom) && down < height) {\n bottomBorderNotWhite = this.containsBlackPoint(left, right, down, true);\n if (bottomBorderNotWhite) {\n down++;\n aBlackPointFoundOnBorder = true;\n atLeastOneBlackPointFoundOnBottom = true;\n }\n else if (!atLeastOneBlackPointFoundOnBottom) {\n down++;\n }\n }\n if (down >= height) {\n sizeExceeded = true;\n break;\n }\n // .....\n // | .\n // .....\n let leftBorderNotWhite = true;\n while ((leftBorderNotWhite || !atLeastOneBlackPointFoundOnLeft) && left >= 0) {\n leftBorderNotWhite = this.containsBlackPoint(up, down, left, false);\n if (leftBorderNotWhite) {\n left--;\n aBlackPointFoundOnBorder = true;\n atLeastOneBlackPointFoundOnLeft = true;\n }\n else if (!atLeastOneBlackPointFoundOnLeft) {\n left--;\n }\n }\n if (left < 0) {\n sizeExceeded = true;\n break;\n }\n // .___.\n // . .\n // .....\n let topBorderNotWhite = true;\n while ((topBorderNotWhite || !atLeastOneBlackPointFoundOnTop) && up >= 0) {\n topBorderNotWhite = this.containsBlackPoint(left, right, up, true);\n if (topBorderNotWhite) {\n up--;\n aBlackPointFoundOnBorder = true;\n atLeastOneBlackPointFoundOnTop = true;\n }\n else if (!atLeastOneBlackPointFoundOnTop) {\n up--;\n }\n }\n if (up < 0) {\n sizeExceeded = true;\n break;\n }\n if (aBlackPointFoundOnBorder) {\n atLeastOneBlackPointFoundOnBorder = true;\n }\n }\n if (!sizeExceeded && atLeastOneBlackPointFoundOnBorder) {\n const maxSize = right - left;\n let z = null;\n for (let i = 1; z === null && i < maxSize; i++) {\n z = this.getBlackPointOnSegment(left, down - i, left + i, down);\n }\n if (z == null) {\n throw new NotFoundException();\n }\n let t = null;\n // go down right\n for (let i = 1; t === null && i < maxSize; i++) {\n t = this.getBlackPointOnSegment(left, up + i, left + i, up);\n }\n if (t == null) {\n throw new NotFoundException();\n }\n let x = null;\n // go down left\n for (let i = 1; x === null && i < maxSize; i++) {\n x = this.getBlackPointOnSegment(right, up + i, right - i, up);\n }\n if (x == null) {\n throw new NotFoundException();\n }\n let y = null;\n // go up left\n for (let i = 1; y === null && i < maxSize; i++) {\n y = this.getBlackPointOnSegment(right, down - i, right - i, down);\n }\n if (y == null) {\n throw new NotFoundException();\n }\n return this.centerEdges(y, z, x, t);\n }\n else {\n throw new NotFoundException();\n }\n }\n getBlackPointOnSegment(aX /*float*/, aY /*float*/, bX /*float*/, bY /*float*/) {\n const dist = MathUtils.round(MathUtils.distance(aX, aY, bX, bY));\n const xStep = (bX - aX) / dist;\n const yStep = (bY - aY) / dist;\n const image = this.image;\n for (let i = 0; i < dist; i++) {\n const x = MathUtils.round(aX + i * xStep);\n const y = MathUtils.round(aY + i * yStep);\n if (image.get(x, y)) {\n return new ResultPoint(x, y);\n }\n }\n return null;\n }\n /**\n * recenters the points of a constant distance towards the center\n *\n * @param y bottom most point\n * @param z left most point\n * @param x right most point\n * @param t top most point\n * @return {@link ResultPoint}[] describing the corners of the rectangular\n * region. The first and last points are opposed on the diagonal, as\n * are the second and third. The first point will be the topmost\n * point and the last, the bottommost. The second point will be\n * leftmost and the third, the rightmost\n */\n centerEdges(y, z, x, t) {\n //\n // t t\n // z x\n // x OR z\n // y y\n //\n const yi = y.getX();\n const yj = y.getY();\n const zi = z.getX();\n const zj = z.getY();\n const xi = x.getX();\n const xj = x.getY();\n const ti = t.getX();\n const tj = t.getY();\n const CORR = WhiteRectangleDetector.CORR;\n if (yi < this.width / 2.0) {\n return [\n new ResultPoint(ti - CORR, tj + CORR),\n new ResultPoint(zi + CORR, zj + CORR),\n new ResultPoint(xi - CORR, xj - CORR),\n new ResultPoint(yi + CORR, yj - CORR)\n ];\n }\n else {\n return [\n new ResultPoint(ti + CORR, tj + CORR),\n new ResultPoint(zi + CORR, zj - CORR),\n new ResultPoint(xi - CORR, xj + CORR),\n new ResultPoint(yi - CORR, yj - CORR)\n ];\n }\n }\n /**\n * Determines whether a segment contains a black point\n *\n * @param a min value of the scanned coordinate\n * @param b max value of the scanned coordinate\n * @param fixed value of fixed coordinate\n * @param horizontal set to true if scan must be horizontal, false if vertical\n * @return true if a black point has been found, else false.\n */\n containsBlackPoint(a /*int*/, b /*int*/, fixed /*int*/, horizontal) {\n const image = this.image;\n if (horizontal) {\n for (let x = a; x <= b; x++) {\n if (image.get(x, fixed)) {\n return true;\n }\n }\n }\n else {\n for (let y = a; y <= b; y++) {\n if (image.get(fixed, y)) {\n return true;\n }\n }\n }\n return false;\n }\n }\n WhiteRectangleDetector.INIT_SIZE = 10;\n WhiteRectangleDetector.CORR = 1;\n\n /*\n * Copyright 2007 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n /**\n * Implementations of this class can, given locations of finder patterns for a QR code in an\n * image, sample the right points in the image to reconstruct the QR code, accounting for\n * perspective distortion. It is abstracted since it is relatively expensive and should be allowed\n * to take advantage of platform-specific optimized implementations, like Sun's Java Advanced\n * Imaging library, but which may not be available in other environments such as J2ME, and vice\n * versa.\n *\n * The implementation used can be controlled by calling {@link #setGridSampler(GridSampler)}\n * with an instance of a class which implements this interface.\n *\n * @author Sean Owen\n */\n class GridSampler {\n /**\n *

Checks a set of points that have been transformed to sample points on an image against\n * the image's dimensions to see if the point are even within the image.

\n *\n *

This method will actually \"nudge\" the endpoints back onto the image if they are found to be\n * barely (less than 1 pixel) off the image. This accounts for imperfect detection of finder\n * patterns in an image where the QR Code runs all the way to the image border.

\n *\n *

For efficiency, the method will check points from either end of the line until one is found\n * to be within the image. Because the set of points are assumed to be linear, this is valid.

\n *\n * @param image image into which the points should map\n * @param points actual points in x1,y1,...,xn,yn form\n * @throws NotFoundException if an endpoint is lies outside the image boundaries\n */\n static checkAndNudgePoints(image, points) {\n const width = image.getWidth();\n const height = image.getHeight();\n // Check and nudge points from start until we see some that are OK:\n let nudged = true;\n for (let offset = 0; offset < points.length && nudged; offset += 2) {\n const x = Math.floor(points[offset]);\n const y = Math.floor(points[offset + 1]);\n if (x < -1 || x > width || y < -1 || y > height) {\n throw new NotFoundException();\n }\n nudged = false;\n if (x === -1) {\n points[offset] = 0.0;\n nudged = true;\n }\n else if (x === width) {\n points[offset] = width - 1;\n nudged = true;\n }\n if (y === -1) {\n points[offset + 1] = 0.0;\n nudged = true;\n }\n else if (y === height) {\n points[offset + 1] = height - 1;\n nudged = true;\n }\n }\n // Check and nudge points from end:\n nudged = true;\n for (let offset = points.length - 2; offset >= 0 && nudged; offset -= 2) {\n const x = Math.floor(points[offset]);\n const y = Math.floor(points[offset + 1]);\n if (x < -1 || x > width || y < -1 || y > height) {\n throw new NotFoundException();\n }\n nudged = false;\n if (x === -1) {\n points[offset] = 0.0;\n nudged = true;\n }\n else if (x === width) {\n points[offset] = width - 1;\n nudged = true;\n }\n if (y === -1) {\n points[offset + 1] = 0.0;\n nudged = true;\n }\n else if (y === height) {\n points[offset + 1] = height - 1;\n nudged = true;\n }\n }\n }\n }\n\n /*\n * Copyright 2007 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n /*namespace com.google.zxing.common {*/\n /**\n *

This class implements a perspective transform in two dimensions. Given four source and four\n * destination points, it will compute the transformation implied between them. The code is based\n * directly upon section 3.4.2 of George Wolberg's \"Digital Image Warping\"; see pages 54-56.

\n *\n * @author Sean Owen\n */\n class PerspectiveTransform {\n constructor(a11 /*float*/, a21 /*float*/, a31 /*float*/, a12 /*float*/, a22 /*float*/, a32 /*float*/, a13 /*float*/, a23 /*float*/, a33 /*float*/) {\n this.a11 = a11;\n this.a21 = a21;\n this.a31 = a31;\n this.a12 = a12;\n this.a22 = a22;\n this.a32 = a32;\n this.a13 = a13;\n this.a23 = a23;\n this.a33 = a33;\n }\n static quadrilateralToQuadrilateral(x0 /*float*/, y0 /*float*/, x1 /*float*/, y1 /*float*/, x2 /*float*/, y2 /*float*/, x3 /*float*/, y3 /*float*/, x0p /*float*/, y0p /*float*/, x1p /*float*/, y1p /*float*/, x2p /*float*/, y2p /*float*/, x3p /*float*/, y3p /*float*/) {\n const qToS = PerspectiveTransform.quadrilateralToSquare(x0, y0, x1, y1, x2, y2, x3, y3);\n const sToQ = PerspectiveTransform.squareToQuadrilateral(x0p, y0p, x1p, y1p, x2p, y2p, x3p, y3p);\n return sToQ.times(qToS);\n }\n transformPoints(points) {\n const max = points.length;\n const a11 = this.a11;\n const a12 = this.a12;\n const a13 = this.a13;\n const a21 = this.a21;\n const a22 = this.a22;\n const a23 = this.a23;\n const a31 = this.a31;\n const a32 = this.a32;\n const a33 = this.a33;\n for (let i = 0; i < max; i += 2) {\n const x = points[i];\n const y = points[i + 1];\n const denominator = a13 * x + a23 * y + a33;\n points[i] = (a11 * x + a21 * y + a31) / denominator;\n points[i + 1] = (a12 * x + a22 * y + a32) / denominator;\n }\n }\n transformPointsWithValues(xValues, yValues) {\n const a11 = this.a11;\n const a12 = this.a12;\n const a13 = this.a13;\n const a21 = this.a21;\n const a22 = this.a22;\n const a23 = this.a23;\n const a31 = this.a31;\n const a32 = this.a32;\n const a33 = this.a33;\n const n = xValues.length;\n for (let i = 0; i < n; i++) {\n const x = xValues[i];\n const y = yValues[i];\n const denominator = a13 * x + a23 * y + a33;\n xValues[i] = (a11 * x + a21 * y + a31) / denominator;\n yValues[i] = (a12 * x + a22 * y + a32) / denominator;\n }\n }\n static squareToQuadrilateral(x0 /*float*/, y0 /*float*/, x1 /*float*/, y1 /*float*/, x2 /*float*/, y2 /*float*/, x3 /*float*/, y3 /*float*/) {\n const dx3 = x0 - x1 + x2 - x3;\n const dy3 = y0 - y1 + y2 - y3;\n if (dx3 === 0.0 && dy3 === 0.0) {\n // Affine\n return new PerspectiveTransform(x1 - x0, x2 - x1, x0, y1 - y0, y2 - y1, y0, 0.0, 0.0, 1.0);\n }\n else {\n const dx1 = x1 - x2;\n const dx2 = x3 - x2;\n const dy1 = y1 - y2;\n const dy2 = y3 - y2;\n const denominator = dx1 * dy2 - dx2 * dy1;\n const a13 = (dx3 * dy2 - dx2 * dy3) / denominator;\n const a23 = (dx1 * dy3 - dx3 * dy1) / denominator;\n return new PerspectiveTransform(x1 - x0 + a13 * x1, x3 - x0 + a23 * x3, x0, y1 - y0 + a13 * y1, y3 - y0 + a23 * y3, y0, a13, a23, 1.0);\n }\n }\n static quadrilateralToSquare(x0 /*float*/, y0 /*float*/, x1 /*float*/, y1 /*float*/, x2 /*float*/, y2 /*float*/, x3 /*float*/, y3 /*float*/) {\n // Here, the adjoint serves as the inverse:\n return PerspectiveTransform.squareToQuadrilateral(x0, y0, x1, y1, x2, y2, x3, y3).buildAdjoint();\n }\n buildAdjoint() {\n // Adjoint is the transpose of the cofactor matrix:\n return new PerspectiveTransform(this.a22 * this.a33 - this.a23 * this.a32, this.a23 * this.a31 - this.a21 * this.a33, this.a21 * this.a32 - this.a22 * this.a31, this.a13 * this.a32 - this.a12 * this.a33, this.a11 * this.a33 - this.a13 * this.a31, this.a12 * this.a31 - this.a11 * this.a32, this.a12 * this.a23 - this.a13 * this.a22, this.a13 * this.a21 - this.a11 * this.a23, this.a11 * this.a22 - this.a12 * this.a21);\n }\n times(other) {\n return new PerspectiveTransform(this.a11 * other.a11 + this.a21 * other.a12 + this.a31 * other.a13, this.a11 * other.a21 + this.a21 * other.a22 + this.a31 * other.a23, this.a11 * other.a31 + this.a21 * other.a32 + this.a31 * other.a33, this.a12 * other.a11 + this.a22 * other.a12 + this.a32 * other.a13, this.a12 * other.a21 + this.a22 * other.a22 + this.a32 * other.a23, this.a12 * other.a31 + this.a22 * other.a32 + this.a32 * other.a33, this.a13 * other.a11 + this.a23 * other.a12 + this.a33 * other.a13, this.a13 * other.a21 + this.a23 * other.a22 + this.a33 * other.a23, this.a13 * other.a31 + this.a23 * other.a32 + this.a33 * other.a33);\n }\n }\n\n /*\n * Copyright 2007 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n /**\n * @author Sean Owen\n */\n class DefaultGridSampler extends GridSampler {\n /*@Override*/\n sampleGrid(image, dimensionX /*int*/, dimensionY /*int*/, p1ToX /*float*/, p1ToY /*float*/, p2ToX /*float*/, p2ToY /*float*/, p3ToX /*float*/, p3ToY /*float*/, p4ToX /*float*/, p4ToY /*float*/, p1FromX /*float*/, p1FromY /*float*/, p2FromX /*float*/, p2FromY /*float*/, p3FromX /*float*/, p3FromY /*float*/, p4FromX /*float*/, p4FromY /*float*/) {\n const transform = PerspectiveTransform.quadrilateralToQuadrilateral(p1ToX, p1ToY, p2ToX, p2ToY, p3ToX, p3ToY, p4ToX, p4ToY, p1FromX, p1FromY, p2FromX, p2FromY, p3FromX, p3FromY, p4FromX, p4FromY);\n return this.sampleGridWithTransform(image, dimensionX, dimensionY, transform);\n }\n /*@Override*/\n sampleGridWithTransform(image, dimensionX /*int*/, dimensionY /*int*/, transform) {\n if (dimensionX <= 0 || dimensionY <= 0) {\n throw new NotFoundException();\n }\n const bits = new BitMatrix(dimensionX, dimensionY);\n const points = new Float32Array(2 * dimensionX);\n for (let y = 0; y < dimensionY; y++) {\n const max = points.length;\n const iValue = y + 0.5;\n for (let x = 0; x < max; x += 2) {\n points[x] = (x / 2) + 0.5;\n points[x + 1] = iValue;\n }\n transform.transformPoints(points);\n // Quick check to see if points transformed to something inside the image\n // sufficient to check the endpoints\n GridSampler.checkAndNudgePoints(image, points);\n try {\n for (let x = 0; x < max; x += 2) {\n if (image.get(Math.floor(points[x]), Math.floor(points[x + 1]))) {\n // Black(-ish) pixel\n bits.set(x / 2, y);\n }\n }\n }\n catch (aioobe /*: ArrayIndexOutOfBoundsException*/) {\n // This feels wrong, but, sometimes if the finder patterns are misidentified, the resulting\n // transform gets \"twisted\" such that it maps a straight line of points to a set of points\n // whose endpoints are in bounds, but others are not. There is probably some mathematical\n // way to detect this about the transformation that I don't know yet.\n // This results in an ugly runtime exception despite our clever checks above -- can't have\n // that. We could check each point's coordinates but that feels duplicative. We settle for\n // catching and wrapping ArrayIndexOutOfBoundsException.\n throw new NotFoundException();\n }\n }\n return bits;\n }\n }\n\n class GridSamplerInstance {\n /**\n * Sets the implementation of GridSampler used by the library. One global\n * instance is stored, which may sound problematic. But, the implementation provided\n * ought to be appropriate for the entire platform, and all uses of this library\n * in the whole lifetime of the JVM. For instance, an Android activity can swap in\n * an implementation that takes advantage of native platform libraries.\n *\n * @param newGridSampler The platform-specific object to install.\n */\n static setGridSampler(newGridSampler) {\n GridSamplerInstance.gridSampler = newGridSampler;\n }\n /**\n * @return the current implementation of GridSampler\n */\n static getInstance() {\n return GridSamplerInstance.gridSampler;\n }\n }\n GridSamplerInstance.gridSampler = new DefaultGridSampler();\n\n /*\n * Copyright 2010 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n class Point {\n constructor(x, y) {\n this.x = x;\n this.y = y;\n }\n toResultPoint() {\n return new ResultPoint(this.getX(), this.getY());\n }\n getX() {\n return this.x;\n }\n getY() {\n return this.y;\n }\n }\n /**\n * Encapsulates logic that can detect an Aztec Code in an image, even if the Aztec Code\n * is rotated or skewed, or partially obscured.\n *\n * @author David Olivier\n * @author Frank Yellin\n */\n class Detector {\n constructor(image) {\n this.EXPECTED_CORNER_BITS = new Int32Array([\n 0xee0,\n 0x1dc,\n 0x83b,\n 0x707,\n ]);\n this.image = image;\n }\n detect() {\n return this.detectMirror(false);\n }\n /**\n * Detects an Aztec Code in an image.\n *\n * @param isMirror if true, image is a mirror-image of original\n * @return {@link AztecDetectorResult} encapsulating results of detecting an Aztec Code\n * @throws NotFoundException if no Aztec Code can be found\n */\n detectMirror(isMirror) {\n // 1. Get the center of the aztec matrix\n let pCenter = this.getMatrixCenter();\n // 2. Get the center points of the four diagonal points just outside the bull's eye\n // [topRight, bottomRight, bottomLeft, topLeft]\n let bullsEyeCorners = this.getBullsEyeCorners(pCenter);\n if (isMirror) {\n let temp = bullsEyeCorners[0];\n bullsEyeCorners[0] = bullsEyeCorners[2];\n bullsEyeCorners[2] = temp;\n }\n // 3. Get the size of the matrix and other parameters from the bull's eye\n this.extractParameters(bullsEyeCorners);\n // 4. Sample the grid\n let bits = this.sampleGrid(this.image, bullsEyeCorners[this.shift % 4], bullsEyeCorners[(this.shift + 1) % 4], bullsEyeCorners[(this.shift + 2) % 4], bullsEyeCorners[(this.shift + 3) % 4]);\n // 5. Get the corners of the matrix.\n let corners = this.getMatrixCornerPoints(bullsEyeCorners);\n return new AztecDetectorResult(bits, corners, this.compact, this.nbDataBlocks, this.nbLayers);\n }\n /**\n * Extracts the number of data layers and data blocks from the layer around the bull's eye.\n *\n * @param bullsEyeCorners the array of bull's eye corners\n * @throws NotFoundException in case of too many errors or invalid parameters\n */\n extractParameters(bullsEyeCorners) {\n if (!this.isValidPoint(bullsEyeCorners[0]) || !this.isValidPoint(bullsEyeCorners[1]) ||\n !this.isValidPoint(bullsEyeCorners[2]) || !this.isValidPoint(bullsEyeCorners[3])) {\n throw new NotFoundException();\n }\n let length = 2 * this.nbCenterLayers;\n // Get the bits around the bull's eye\n let sides = new Int32Array([\n this.sampleLine(bullsEyeCorners[0], bullsEyeCorners[1], length),\n this.sampleLine(bullsEyeCorners[1], bullsEyeCorners[2], length),\n this.sampleLine(bullsEyeCorners[2], bullsEyeCorners[3], length),\n this.sampleLine(bullsEyeCorners[3], bullsEyeCorners[0], length) // Top\n ]);\n // bullsEyeCorners[shift] is the corner of the bulls'eye that has three\n // orientation marks.\n // sides[shift] is the row/column that goes from the corner with three\n // orientation marks to the corner with two.\n this.shift = this.getRotation(sides, length);\n // Flatten the parameter bits into a single 28- or 40-bit long\n let parameterData = 0;\n for (let i = 0; i < 4; i++) {\n let side = sides[(this.shift + i) % 4];\n if (this.compact) {\n // Each side of the form ..XXXXXXX. where Xs are parameter data\n parameterData <<= 7;\n parameterData += (side >> 1) & 0x7F;\n }\n else {\n // Each side of the form ..XXXXX.XXXXX. where Xs are parameter data\n parameterData <<= 10;\n parameterData += ((side >> 2) & (0x1f << 5)) + ((side >> 1) & 0x1F);\n }\n }\n // Corrects parameter data using RS. Returns just the data portion\n // without the error correction.\n let correctedData = this.getCorrectedParameterData(parameterData, this.compact);\n if (this.compact) {\n // 8 bits: 2 bits layers and 6 bits data blocks\n this.nbLayers = (correctedData >> 6) + 1;\n this.nbDataBlocks = (correctedData & 0x3F) + 1;\n }\n else {\n // 16 bits: 5 bits layers and 11 bits data blocks\n this.nbLayers = (correctedData >> 11) + 1;\n this.nbDataBlocks = (correctedData & 0x7FF) + 1;\n }\n }\n getRotation(sides, length) {\n // In a normal pattern, we expect to See\n // ** .* D A\n // * *\n //\n // . *\n // .. .. C B\n //\n // Grab the 3 bits from each of the sides the form the locator pattern and concatenate\n // into a 12-bit integer. Start with the bit at A\n let cornerBits = 0;\n sides.forEach((side, idx, arr) => {\n // XX......X where X's are orientation marks\n let t = ((side >> (length - 2)) << 1) + (side & 1);\n cornerBits = (cornerBits << 3) + t;\n });\n // for (var side in sides) {\n // // XX......X where X's are orientation marks\n // var t = ((side >> (length - 2)) << 1) + (side & 1);\n // cornerBits = (cornerBits << 3) + t;\n // }\n // Mov the bottom bit to the top, so that the three bits of the locator pattern at A are\n // together. cornerBits is now:\n // 3 orientation bits at A || 3 orientation bits at B || ... || 3 orientation bits at D\n cornerBits = ((cornerBits & 1) << 11) + (cornerBits >> 1);\n // The result shift indicates which element of BullsEyeCorners[] goes into the top-left\n // corner. Since the four rotation values have a Hamming distance of 8, we\n // can easily tolerate two errors.\n for (let shift = 0; shift < 4; shift++) {\n if (Integer.bitCount(cornerBits ^ this.EXPECTED_CORNER_BITS[shift]) <= 2) {\n return shift;\n }\n }\n throw new NotFoundException();\n }\n /**\n * Corrects the parameter bits using Reed-Solomon algorithm.\n *\n * @param parameterData parameter bits\n * @param compact true if this is a compact Aztec code\n * @throws NotFoundException if the array contains too many errors\n */\n getCorrectedParameterData(parameterData, compact) {\n let numCodewords;\n let numDataCodewords;\n if (compact) {\n numCodewords = 7;\n numDataCodewords = 2;\n }\n else {\n numCodewords = 10;\n numDataCodewords = 4;\n }\n let numECCodewords = numCodewords - numDataCodewords;\n let parameterWords = new Int32Array(numCodewords);\n for (let i = numCodewords - 1; i >= 0; --i) {\n parameterWords[i] = parameterData & 0xF;\n parameterData >>= 4;\n }\n try {\n let rsDecoder = new ReedSolomonDecoder(GenericGF.AZTEC_PARAM);\n rsDecoder.decode(parameterWords, numECCodewords);\n }\n catch (ignored) {\n throw new NotFoundException();\n }\n // Toss the error correction. Just return the data as an integer\n let result = 0;\n for (let i = 0; i < numDataCodewords; i++) {\n result = (result << 4) + parameterWords[i];\n }\n return result;\n }\n /**\n * Finds the corners of a bull-eye centered on the passed point.\n * This returns the centers of the diagonal points just outside the bull's eye\n * Returns [topRight, bottomRight, bottomLeft, topLeft]\n *\n * @param pCenter Center point\n * @return The corners of the bull-eye\n * @throws NotFoundException If no valid bull-eye can be found\n */\n getBullsEyeCorners(pCenter) {\n let pina = pCenter;\n let pinb = pCenter;\n let pinc = pCenter;\n let pind = pCenter;\n let color = true;\n for (this.nbCenterLayers = 1; this.nbCenterLayers < 9; this.nbCenterLayers++) {\n let pouta = this.getFirstDifferent(pina, color, 1, -1);\n let poutb = this.getFirstDifferent(pinb, color, 1, 1);\n let poutc = this.getFirstDifferent(pinc, color, -1, 1);\n let poutd = this.getFirstDifferent(pind, color, -1, -1);\n // d a\n //\n // c b\n if (this.nbCenterLayers > 2) {\n let q = (this.distancePoint(poutd, pouta) * this.nbCenterLayers) / (this.distancePoint(pind, pina) * (this.nbCenterLayers + 2));\n if (q < 0.75 || q > 1.25 || !this.isWhiteOrBlackRectangle(pouta, poutb, poutc, poutd)) {\n break;\n }\n }\n pina = pouta;\n pinb = poutb;\n pinc = poutc;\n pind = poutd;\n color = !color;\n }\n if (this.nbCenterLayers !== 5 && this.nbCenterLayers !== 7) {\n throw new NotFoundException();\n }\n this.compact = this.nbCenterLayers === 5;\n // Expand the square by .5 pixel in each direction so that we're on the border\n // between the white square and the black square\n let pinax = new ResultPoint(pina.getX() + 0.5, pina.getY() - 0.5);\n let pinbx = new ResultPoint(pinb.getX() + 0.5, pinb.getY() + 0.5);\n let pincx = new ResultPoint(pinc.getX() - 0.5, pinc.getY() + 0.5);\n let pindx = new ResultPoint(pind.getX() - 0.5, pind.getY() - 0.5);\n // Expand the square so that its corners are the centers of the points\n // just outside the bull's eye.\n return this.expandSquare([pinax, pinbx, pincx, pindx], 2 * this.nbCenterLayers - 3, 2 * this.nbCenterLayers);\n }\n /**\n * Finds a candidate center point of an Aztec code from an image\n *\n * @return the center point\n */\n getMatrixCenter() {\n let pointA;\n let pointB;\n let pointC;\n let pointD;\n // Get a white rectangle that can be the border of the matrix in center bull's eye or\n try {\n let cornerPoints = new WhiteRectangleDetector(this.image).detect();\n pointA = cornerPoints[0];\n pointB = cornerPoints[1];\n pointC = cornerPoints[2];\n pointD = cornerPoints[3];\n }\n catch (e) {\n // This exception can be in case the initial rectangle is white\n // In that case, surely in the bull's eye, we try to expand the rectangle.\n let cx = this.image.getWidth() / 2;\n let cy = this.image.getHeight() / 2;\n pointA = this.getFirstDifferent(new Point(cx + 7, cy - 7), false, 1, -1).toResultPoint();\n pointB = this.getFirstDifferent(new Point(cx + 7, cy + 7), false, 1, 1).toResultPoint();\n pointC = this.getFirstDifferent(new Point(cx - 7, cy + 7), false, -1, 1).toResultPoint();\n pointD = this.getFirstDifferent(new Point(cx - 7, cy - 7), false, -1, -1).toResultPoint();\n }\n // Compute the center of the rectangle\n let cx = MathUtils.round((pointA.getX() + pointD.getX() + pointB.getX() + pointC.getX()) / 4.0);\n let cy = MathUtils.round((pointA.getY() + pointD.getY() + pointB.getY() + pointC.getY()) / 4.0);\n // Redetermine the white rectangle starting from previously computed center.\n // This will ensure that we end up with a white rectangle in center bull's eye\n // in order to compute a more accurate center.\n try {\n let cornerPoints = new WhiteRectangleDetector(this.image, 15, cx, cy).detect();\n pointA = cornerPoints[0];\n pointB = cornerPoints[1];\n pointC = cornerPoints[2];\n pointD = cornerPoints[3];\n }\n catch (e) {\n // This exception can be in case the initial rectangle is white\n // In that case we try to expand the rectangle.\n pointA = this.getFirstDifferent(new Point(cx + 7, cy - 7), false, 1, -1).toResultPoint();\n pointB = this.getFirstDifferent(new Point(cx + 7, cy + 7), false, 1, 1).toResultPoint();\n pointC = this.getFirstDifferent(new Point(cx - 7, cy + 7), false, -1, 1).toResultPoint();\n pointD = this.getFirstDifferent(new Point(cx - 7, cy - 7), false, -1, -1).toResultPoint();\n }\n // Recompute the center of the rectangle\n cx = MathUtils.round((pointA.getX() + pointD.getX() + pointB.getX() + pointC.getX()) / 4.0);\n cy = MathUtils.round((pointA.getY() + pointD.getY() + pointB.getY() + pointC.getY()) / 4.0);\n return new Point(cx, cy);\n }\n /**\n * Gets the Aztec code corners from the bull's eye corners and the parameters.\n *\n * @param bullsEyeCorners the array of bull's eye corners\n * @return the array of aztec code corners\n */\n getMatrixCornerPoints(bullsEyeCorners) {\n return this.expandSquare(bullsEyeCorners, 2 * this.nbCenterLayers, this.getDimension());\n }\n /**\n * Creates a BitMatrix by sampling the provided image.\n * topLeft, topRight, bottomRight, and bottomLeft are the centers of the squares on the\n * diagonal just outside the bull's eye.\n */\n sampleGrid(image, topLeft, topRight, bottomRight, bottomLeft) {\n let sampler = GridSamplerInstance.getInstance();\n let dimension = this.getDimension();\n let low = dimension / 2 - this.nbCenterLayers;\n let high = dimension / 2 + this.nbCenterLayers;\n return sampler.sampleGrid(image, dimension, dimension, low, low, // topleft\n high, low, // topright\n high, high, // bottomright\n low, high, // bottomleft\n topLeft.getX(), topLeft.getY(), topRight.getX(), topRight.getY(), bottomRight.getX(), bottomRight.getY(), bottomLeft.getX(), bottomLeft.getY());\n }\n /**\n * Samples a line.\n *\n * @param p1 start point (inclusive)\n * @param p2 end point (exclusive)\n * @param size number of bits\n * @return the array of bits as an int (first bit is high-order bit of result)\n */\n sampleLine(p1, p2, size) {\n let result = 0;\n let d = this.distanceResultPoint(p1, p2);\n let moduleSize = d / size;\n let px = p1.getX();\n let py = p1.getY();\n let dx = moduleSize * (p2.getX() - p1.getX()) / d;\n let dy = moduleSize * (p2.getY() - p1.getY()) / d;\n for (let i = 0; i < size; i++) {\n if (this.image.get(MathUtils.round(px + i * dx), MathUtils.round(py + i * dy))) {\n result |= 1 << (size - i - 1);\n }\n }\n return result;\n }\n /**\n * @return true if the border of the rectangle passed in parameter is compound of white points only\n * or black points only\n */\n isWhiteOrBlackRectangle(p1, p2, p3, p4) {\n let corr = 3;\n p1 = new Point(p1.getX() - corr, p1.getY() + corr);\n p2 = new Point(p2.getX() - corr, p2.getY() - corr);\n p3 = new Point(p3.getX() + corr, p3.getY() - corr);\n p4 = new Point(p4.getX() + corr, p4.getY() + corr);\n let cInit = this.getColor(p4, p1);\n if (cInit === 0) {\n return false;\n }\n let c = this.getColor(p1, p2);\n if (c !== cInit) {\n return false;\n }\n c = this.getColor(p2, p3);\n if (c !== cInit) {\n return false;\n }\n c = this.getColor(p3, p4);\n return c === cInit;\n }\n /**\n * Gets the color of a segment\n *\n * @return 1 if segment more than 90% black, -1 if segment is more than 90% white, 0 else\n */\n getColor(p1, p2) {\n let d = this.distancePoint(p1, p2);\n let dx = (p2.getX() - p1.getX()) / d;\n let dy = (p2.getY() - p1.getY()) / d;\n let error = 0;\n let px = p1.getX();\n let py = p1.getY();\n let colorModel = this.image.get(p1.getX(), p1.getY());\n let iMax = Math.ceil(d);\n for (let i = 0; i < iMax; i++) {\n px += dx;\n py += dy;\n if (this.image.get(MathUtils.round(px), MathUtils.round(py)) !== colorModel) {\n error++;\n }\n }\n let errRatio = error / d;\n if (errRatio > 0.1 && errRatio < 0.9) {\n return 0;\n }\n return (errRatio <= 0.1) === colorModel ? 1 : -1;\n }\n /**\n * Gets the coordinate of the first point with a different color in the given direction\n */\n getFirstDifferent(init, color, dx, dy) {\n let x = init.getX() + dx;\n let y = init.getY() + dy;\n while (this.isValid(x, y) && this.image.get(x, y) === color) {\n x += dx;\n y += dy;\n }\n x -= dx;\n y -= dy;\n while (this.isValid(x, y) && this.image.get(x, y) === color) {\n x += dx;\n }\n x -= dx;\n while (this.isValid(x, y) && this.image.get(x, y) === color) {\n y += dy;\n }\n y -= dy;\n return new Point(x, y);\n }\n /**\n * Expand the square represented by the corner points by pushing out equally in all directions\n *\n * @param cornerPoints the corners of the square, which has the bull's eye at its center\n * @param oldSide the original length of the side of the square in the target bit matrix\n * @param newSide the new length of the size of the square in the target bit matrix\n * @return the corners of the expanded square\n */\n expandSquare(cornerPoints, oldSide, newSide) {\n let ratio = newSide / (2.0 * oldSide);\n let dx = cornerPoints[0].getX() - cornerPoints[2].getX();\n let dy = cornerPoints[0].getY() - cornerPoints[2].getY();\n let centerx = (cornerPoints[0].getX() + cornerPoints[2].getX()) / 2.0;\n let centery = (cornerPoints[0].getY() + cornerPoints[2].getY()) / 2.0;\n let result0 = new ResultPoint(centerx + ratio * dx, centery + ratio * dy);\n let result2 = new ResultPoint(centerx - ratio * dx, centery - ratio * dy);\n dx = cornerPoints[1].getX() - cornerPoints[3].getX();\n dy = cornerPoints[1].getY() - cornerPoints[3].getY();\n centerx = (cornerPoints[1].getX() + cornerPoints[3].getX()) / 2.0;\n centery = (cornerPoints[1].getY() + cornerPoints[3].getY()) / 2.0;\n let result1 = new ResultPoint(centerx + ratio * dx, centery + ratio * dy);\n let result3 = new ResultPoint(centerx - ratio * dx, centery - ratio * dy);\n let results = [result0, result1, result2, result3];\n return results;\n }\n isValid(x, y) {\n return x >= 0 && x < this.image.getWidth() && y > 0 && y < this.image.getHeight();\n }\n isValidPoint(point) {\n let x = MathUtils.round(point.getX());\n let y = MathUtils.round(point.getY());\n return this.isValid(x, y);\n }\n distancePoint(a, b) {\n return MathUtils.distance(a.getX(), a.getY(), b.getX(), b.getY());\n }\n distanceResultPoint(a, b) {\n return MathUtils.distance(a.getX(), a.getY(), b.getX(), b.getY());\n }\n getDimension() {\n if (this.compact) {\n return 4 * this.nbLayers + 11;\n }\n if (this.nbLayers <= 4) {\n return 4 * this.nbLayers + 15;\n }\n return 4 * this.nbLayers + 2 * (Integer.truncDivision((this.nbLayers - 4), 8) + 1) + 15;\n }\n }\n\n /*\n * Copyright 2010 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n // import java.util.List;\n // import java.util.Map;\n /**\n * This implementation can detect and decode Aztec codes in an image.\n *\n * @author David Olivier\n */\n class AztecReader {\n /**\n * Locates and decodes a Data Matrix code in an image.\n *\n * @return a String representing the content encoded by the Data Matrix code\n * @throws NotFoundException if a Data Matrix code cannot be found\n * @throws FormatException if a Data Matrix code cannot be decoded\n */\n decode(image, hints = null) {\n let exception = null;\n let detector = new Detector(image.getBlackMatrix());\n let points = null;\n let decoderResult = null;\n try {\n let detectorResult = detector.detectMirror(false);\n points = detectorResult.getPoints();\n this.reportFoundResultPoints(hints, points);\n decoderResult = new Decoder().decode(detectorResult);\n }\n catch (e) {\n exception = e;\n }\n if (decoderResult == null) {\n try {\n let detectorResult = detector.detectMirror(true);\n points = detectorResult.getPoints();\n this.reportFoundResultPoints(hints, points);\n decoderResult = new Decoder().decode(detectorResult);\n }\n catch (e) {\n if (exception != null) {\n throw exception;\n }\n throw e;\n }\n }\n let result = new Result(decoderResult.getText(), decoderResult.getRawBytes(), decoderResult.getNumBits(), points, BarcodeFormat$1.AZTEC, System.currentTimeMillis());\n let byteSegments = decoderResult.getByteSegments();\n if (byteSegments != null) {\n result.putMetadata(ResultMetadataType$1.BYTE_SEGMENTS, byteSegments);\n }\n let ecLevel = decoderResult.getECLevel();\n if (ecLevel != null) {\n result.putMetadata(ResultMetadataType$1.ERROR_CORRECTION_LEVEL, ecLevel);\n }\n return result;\n }\n reportFoundResultPoints(hints, points) {\n if (hints != null) {\n let rpcb = hints.get(DecodeHintType$1.NEED_RESULT_POINT_CALLBACK);\n if (rpcb != null) {\n points.forEach((point, idx, arr) => {\n rpcb.foundPossibleResultPoint(point);\n });\n }\n }\n }\n // @Override\n reset() {\n // do nothing\n }\n }\n\n /**\n * Aztec Code reader to use from browser.\n *\n * @class BrowserAztecCodeReader\n * @extends {BrowserCodeReader}\n */\n class BrowserAztecCodeReader extends BrowserCodeReader {\n /**\n * Creates an instance of BrowserAztecCodeReader.\n * @param {number} [timeBetweenScansMillis=500] the time delay between subsequent decode tries\n *\n * @memberOf BrowserAztecCodeReader\n */\n constructor(timeBetweenScansMillis = 500) {\n super(new AztecReader(), timeBetweenScansMillis);\n }\n }\n\n /**\n * Encapsulates functionality and implementation that is common to all families\n * of one-dimensional barcodes.\n *\n * @author dswitkin@google.com (Daniel Switkin)\n * @author Sean Owen\n */\n class OneDReader {\n /*\n @Override\n public Result decode(BinaryBitmap image) throws NotFoundException, FormatException {\n return decode(image, null);\n }\n */\n // Note that we don't try rotation without the try harder flag, even if rotation was supported.\n // @Override\n decode(image, hints) {\n try {\n return this.doDecode(image, hints);\n }\n catch (nfe) {\n const tryHarder = hints && (hints.get(DecodeHintType$1.TRY_HARDER) === true);\n if (tryHarder && image.isRotateSupported()) {\n const rotatedImage = image.rotateCounterClockwise();\n const result = this.doDecode(rotatedImage, hints);\n // Record that we found it rotated 90 degrees CCW / 270 degrees CW\n const metadata = result.getResultMetadata();\n let orientation = 270;\n if (metadata !== null && (metadata.get(ResultMetadataType$1.ORIENTATION) === true)) {\n // But if we found it reversed in doDecode(), add in that result here:\n orientation = (orientation + metadata.get(ResultMetadataType$1.ORIENTATION) % 360);\n }\n result.putMetadata(ResultMetadataType$1.ORIENTATION, orientation);\n // Update result points\n const points = result.getResultPoints();\n if (points !== null) {\n const height = rotatedImage.getHeight();\n for (let i = 0; i < points.length; i++) {\n points[i] = new ResultPoint(height - points[i].getY() - 1, points[i].getX());\n }\n }\n return result;\n }\n else {\n throw new NotFoundException();\n }\n }\n }\n // @Override\n reset() {\n // do nothing\n }\n /**\n * We're going to examine rows from the middle outward, searching alternately above and below the\n * middle, and farther out each time. rowStep is the number of rows between each successive\n * attempt above and below the middle. So we'd scan row middle, then middle - rowStep, then\n * middle + rowStep, then middle - (2 * rowStep), etc.\n * rowStep is bigger as the image is taller, but is always at least 1. We've somewhat arbitrarily\n * decided that moving up and down by about 1/16 of the image is pretty good; we try more of the\n * image if \"trying harder\".\n *\n * @param image The image to decode\n * @param hints Any hints that were requested\n * @return The contents of the decoded barcode\n * @throws NotFoundException Any spontaneous errors which occur\n */\n doDecode(image, hints) {\n const width = image.getWidth();\n const height = image.getHeight();\n let row = new BitArray(width);\n const tryHarder = hints && (hints.get(DecodeHintType$1.TRY_HARDER) === true);\n const rowStep = Math.max(1, height >> (tryHarder ? 8 : 5));\n let maxLines;\n if (tryHarder) {\n maxLines = height; // Look at the whole image, not just the center\n }\n else {\n maxLines = 15; // 15 rows spaced 1/32 apart is roughly the middle half of the image\n }\n const middle = Math.trunc(height / 2);\n for (let x = 0; x < maxLines; x++) {\n // Scanning from the middle out. Determine which row we're looking at next:\n const rowStepsAboveOrBelow = Math.trunc((x + 1) / 2);\n const isAbove = (x & 0x01) === 0; // i.e. is x even?\n const rowNumber = middle + rowStep * (isAbove ? rowStepsAboveOrBelow : -rowStepsAboveOrBelow);\n if (rowNumber < 0 || rowNumber >= height) {\n // Oops, if we run off the top or bottom, stop\n break;\n }\n // Estimate black point for this row and load it:\n try {\n row = image.getBlackRow(rowNumber, row);\n }\n catch (ignored) {\n continue;\n }\n // While we have the image data in a BitArray, it's fairly cheap to reverse it in place to\n // handle decoding upside down barcodes.\n for (let attempt = 0; attempt < 2; attempt++) {\n if (attempt === 1) { // trying again?\n row.reverse(); // reverse the row and continue\n // This means we will only ever draw result points *once* in the life of this method\n // since we want to avoid drawing the wrong points after flipping the row, and,\n // don't want to clutter with noise from every single row scan -- just the scans\n // that start on the center line.\n if (hints && (hints.get(DecodeHintType$1.NEED_RESULT_POINT_CALLBACK) === true)) {\n const newHints = new Map();\n hints.forEach((hint, key) => newHints.set(key, hint));\n newHints.delete(DecodeHintType$1.NEED_RESULT_POINT_CALLBACK);\n hints = newHints;\n }\n }\n try {\n // Look for a barcode\n const result = this.decodeRow(rowNumber, row, hints);\n // We found our barcode\n if (attempt === 1) {\n // But it was upside down, so note that\n result.putMetadata(ResultMetadataType$1.ORIENTATION, 180);\n // And remember to flip the result points horizontally.\n const points = result.getResultPoints();\n if (points !== null) {\n points[0] = new ResultPoint(width - points[0].getX() - 1, points[0].getY());\n points[1] = new ResultPoint(width - points[1].getX() - 1, points[1].getY());\n }\n }\n return result;\n }\n catch (re) {\n // continue -- just couldn't decode this row\n }\n }\n }\n throw new NotFoundException();\n }\n /**\n * Records the size of successive runs of white and black pixels in a row, starting at a given point.\n * The values are recorded in the given array, and the number of runs recorded is equal to the size\n * of the array. If the row starts on a white pixel at the given start point, then the first count\n * recorded is the run of white pixels starting from that point; likewise it is the count of a run\n * of black pixels if the row begin on a black pixels at that point.\n *\n * @param row row to count from\n * @param start offset into row to start at\n * @param counters array into which to record counts\n * @throws NotFoundException if counters cannot be filled entirely from row before running out\n * of pixels\n */\n static recordPattern(row, start, counters) {\n const numCounters = counters.length;\n for (let index = 0; index < numCounters; index++)\n counters[index] = 0;\n const end = row.getSize();\n if (start >= end) {\n throw new NotFoundException();\n }\n let isWhite = !row.get(start);\n let counterPosition = 0;\n let i = start;\n while (i < end) {\n if (row.get(i) !== isWhite) {\n counters[counterPosition]++;\n }\n else {\n if (++counterPosition === numCounters) {\n break;\n }\n else {\n counters[counterPosition] = 1;\n isWhite = !isWhite;\n }\n }\n i++;\n }\n // If we read fully the last section of pixels and filled up our counters -- or filled\n // the last counter but ran off the side of the image, OK. Otherwise, a problem.\n if (!(counterPosition === numCounters || (counterPosition === numCounters - 1 && i === end))) {\n throw new NotFoundException();\n }\n }\n static recordPatternInReverse(row, start, counters) {\n // This could be more efficient I guess\n let numTransitionsLeft = counters.length;\n let last = row.get(start);\n while (start > 0 && numTransitionsLeft >= 0) {\n if (row.get(--start) !== last) {\n numTransitionsLeft--;\n last = !last;\n }\n }\n if (numTransitionsLeft >= 0) {\n throw new NotFoundException();\n }\n OneDReader.recordPattern(row, start + 1, counters);\n }\n /**\n * Determines how closely a set of observed counts of runs of black/white values matches a given\n * target pattern. This is reported as the ratio of the total variance from the expected pattern\n * proportions across all pattern elements, to the length of the pattern.\n *\n * @param counters observed counters\n * @param pattern expected pattern\n * @param maxIndividualVariance The most any counter can differ before we give up\n * @return ratio of total variance between counters and pattern compared to total pattern size\n */\n static patternMatchVariance(counters, pattern, maxIndividualVariance) {\n const numCounters = counters.length;\n let total = 0;\n let patternLength = 0;\n for (let i = 0; i < numCounters; i++) {\n total += counters[i];\n patternLength += pattern[i];\n }\n if (total < patternLength) {\n // If we don't even have one pixel per unit of bar width, assume this is too small\n // to reliably match, so fail:\n return Number.POSITIVE_INFINITY;\n }\n const unitBarWidth = total / patternLength;\n maxIndividualVariance *= unitBarWidth;\n let totalVariance = 0.0;\n for (let x = 0; x < numCounters; x++) {\n const counter = counters[x];\n const scaledPattern = pattern[x] * unitBarWidth;\n const variance = counter > scaledPattern ? counter - scaledPattern : scaledPattern - counter;\n if (variance > maxIndividualVariance) {\n return Number.POSITIVE_INFINITY;\n }\n totalVariance += variance;\n }\n return totalVariance / total;\n }\n }\n\n /**\n *

Decodes Code 128 barcodes.

\n *\n * @author Sean Owen\n */\n class Code128Reader extends OneDReader {\n static findStartPattern(row) {\n const width = row.getSize();\n const rowOffset = row.getNextSet(0);\n let counterPosition = 0;\n let counters = Int32Array.from([0, 0, 0, 0, 0, 0]);\n let patternStart = rowOffset;\n let isWhite = false;\n const patternLength = 6;\n for (let i = rowOffset; i < width; i++) {\n if (row.get(i) !== isWhite) {\n counters[counterPosition]++;\n }\n else {\n if (counterPosition === (patternLength - 1)) {\n let bestVariance = Code128Reader.MAX_AVG_VARIANCE;\n let bestMatch = -1;\n for (let startCode = Code128Reader.CODE_START_A; startCode <= Code128Reader.CODE_START_C; startCode++) {\n const variance = OneDReader.patternMatchVariance(counters, Code128Reader.CODE_PATTERNS[startCode], Code128Reader.MAX_INDIVIDUAL_VARIANCE);\n if (variance < bestVariance) {\n bestVariance = variance;\n bestMatch = startCode;\n }\n }\n // Look for whitespace before start pattern, >= 50% of width of start pattern\n if (bestMatch >= 0 &&\n row.isRange(Math.max(0, patternStart - (i - patternStart) / 2), patternStart, false)) {\n return Int32Array.from([patternStart, i, bestMatch]);\n }\n patternStart += counters[0] + counters[1];\n counters = counters.slice(2, counters.length - 1);\n counters[counterPosition - 1] = 0;\n counters[counterPosition] = 0;\n counterPosition--;\n }\n else {\n counterPosition++;\n }\n counters[counterPosition] = 1;\n isWhite = !isWhite;\n }\n }\n throw new NotFoundException();\n }\n static decodeCode(row, counters, rowOffset) {\n OneDReader.recordPattern(row, rowOffset, counters);\n let bestVariance = Code128Reader.MAX_AVG_VARIANCE; // worst variance we'll accept\n let bestMatch = -1;\n for (let d = 0; d < Code128Reader.CODE_PATTERNS.length; d++) {\n const pattern = Code128Reader.CODE_PATTERNS[d];\n const variance = this.patternMatchVariance(counters, pattern, Code128Reader.MAX_INDIVIDUAL_VARIANCE);\n if (variance < bestVariance) {\n bestVariance = variance;\n bestMatch = d;\n }\n }\n // TODO We're overlooking the fact that the STOP pattern has 7 values, not 6.\n if (bestMatch >= 0) {\n return bestMatch;\n }\n else {\n throw new NotFoundException();\n }\n }\n decodeRow(rowNumber, row, hints) {\n const convertFNC1 = hints && (hints.get(DecodeHintType$1.ASSUME_GS1) === true);\n const startPatternInfo = Code128Reader.findStartPattern(row);\n const startCode = startPatternInfo[2];\n let currentRawCodesIndex = 0;\n const rawCodes = new Uint8Array(20);\n rawCodes[currentRawCodesIndex++] = startCode;\n let codeSet;\n switch (startCode) {\n case Code128Reader.CODE_START_A:\n codeSet = Code128Reader.CODE_CODE_A;\n break;\n case Code128Reader.CODE_START_B:\n codeSet = Code128Reader.CODE_CODE_B;\n break;\n case Code128Reader.CODE_START_C:\n codeSet = Code128Reader.CODE_CODE_C;\n break;\n default:\n throw new FormatException();\n }\n let done = false;\n let isNextShifted = false;\n let result = '';\n let lastStart = startPatternInfo[0];\n let nextStart = startPatternInfo[1];\n const counters = Int32Array.from([0, 0, 0, 0, 0, 0]);\n let lastCode = 0;\n let code = 0;\n let checksumTotal = startCode;\n let multiplier = 0;\n let lastCharacterWasPrintable = true;\n let upperMode = false;\n let shiftUpperMode = false;\n while (!done) {\n const unshift = isNextShifted;\n isNextShifted = false;\n // Save off last code\n lastCode = code;\n // Decode another code from image\n code = Code128Reader.decodeCode(row, counters, nextStart);\n rawCodes[currentRawCodesIndex++] = code;\n // Remember whether the last code was printable or not (excluding CODE_STOP)\n if (code !== Code128Reader.CODE_STOP) {\n lastCharacterWasPrintable = true;\n }\n // Add to checksum computation (if not CODE_STOP of course)\n if (code !== Code128Reader.CODE_STOP) {\n multiplier++;\n checksumTotal += multiplier * code;\n }\n // Advance to where the next code will to start\n lastStart = nextStart;\n nextStart += counters.reduce((previous, current) => previous + current, 0);\n // Take care of illegal start codes\n switch (code) {\n case Code128Reader.CODE_START_A:\n case Code128Reader.CODE_START_B:\n case Code128Reader.CODE_START_C:\n throw new FormatException();\n }\n switch (codeSet) {\n case Code128Reader.CODE_CODE_A:\n if (code < 64) {\n if (shiftUpperMode === upperMode) {\n result += String.fromCharCode((' '.charCodeAt(0) + code));\n }\n else {\n result += String.fromCharCode((' '.charCodeAt(0) + code + 128));\n }\n shiftUpperMode = false;\n }\n else if (code < 96) {\n if (shiftUpperMode === upperMode) {\n result += String.fromCharCode((code - 64));\n }\n else {\n result += String.fromCharCode((code + 64));\n }\n shiftUpperMode = false;\n }\n else {\n // Don't let CODE_STOP, which always appears, affect whether whether we think the last\n // code was printable or not.\n if (code !== Code128Reader.CODE_STOP) {\n lastCharacterWasPrintable = false;\n }\n switch (code) {\n case Code128Reader.CODE_FNC_1:\n if (convertFNC1) {\n if (result.length === 0) {\n // GS1 specification 5.4.3.7. and 5.4.6.4. If the first char after the start code\n // is FNC1 then this is GS1-128. We add the symbology identifier.\n result += ']C1';\n }\n else {\n // GS1 specification 5.4.7.5. Every subsequent FNC1 is returned as ASCII 29 (GS)\n result += String.fromCharCode(29);\n }\n }\n break;\n case Code128Reader.CODE_FNC_2:\n case Code128Reader.CODE_FNC_3:\n // do nothing?\n break;\n case Code128Reader.CODE_FNC_4_A:\n if (!upperMode && shiftUpperMode) {\n upperMode = true;\n shiftUpperMode = false;\n }\n else if (upperMode && shiftUpperMode) {\n upperMode = false;\n shiftUpperMode = false;\n }\n else {\n shiftUpperMode = true;\n }\n break;\n case Code128Reader.CODE_SHIFT:\n isNextShifted = true;\n codeSet = Code128Reader.CODE_CODE_B;\n break;\n case Code128Reader.CODE_CODE_B:\n codeSet = Code128Reader.CODE_CODE_B;\n break;\n case Code128Reader.CODE_CODE_C:\n codeSet = Code128Reader.CODE_CODE_C;\n break;\n case Code128Reader.CODE_STOP:\n done = true;\n break;\n }\n }\n break;\n case Code128Reader.CODE_CODE_B:\n if (code < 96) {\n if (shiftUpperMode === upperMode) {\n result += String.fromCharCode((' '.charCodeAt(0) + code));\n }\n else {\n result += String.fromCharCode((' '.charCodeAt(0) + code + 128));\n }\n shiftUpperMode = false;\n }\n else {\n if (code !== Code128Reader.CODE_STOP) {\n lastCharacterWasPrintable = false;\n }\n switch (code) {\n case Code128Reader.CODE_FNC_1:\n if (convertFNC1) {\n if (result.length === 0) {\n // GS1 specification 5.4.3.7. and 5.4.6.4. If the first char after the start code\n // is FNC1 then this is GS1-128. We add the symbology identifier.\n result += ']C1';\n }\n else {\n // GS1 specification 5.4.7.5. Every subsequent FNC1 is returned as ASCII 29 (GS)\n result += String.fromCharCode(29);\n }\n }\n break;\n case Code128Reader.CODE_FNC_2:\n case Code128Reader.CODE_FNC_3:\n // do nothing?\n break;\n case Code128Reader.CODE_FNC_4_B:\n if (!upperMode && shiftUpperMode) {\n upperMode = true;\n shiftUpperMode = false;\n }\n else if (upperMode && shiftUpperMode) {\n upperMode = false;\n shiftUpperMode = false;\n }\n else {\n shiftUpperMode = true;\n }\n break;\n case Code128Reader.CODE_SHIFT:\n isNextShifted = true;\n codeSet = Code128Reader.CODE_CODE_A;\n break;\n case Code128Reader.CODE_CODE_A:\n codeSet = Code128Reader.CODE_CODE_A;\n break;\n case Code128Reader.CODE_CODE_C:\n codeSet = Code128Reader.CODE_CODE_C;\n break;\n case Code128Reader.CODE_STOP:\n done = true;\n break;\n }\n }\n break;\n case Code128Reader.CODE_CODE_C:\n if (code < 100) {\n if (code < 10) {\n result += '0';\n }\n result += code;\n }\n else {\n if (code !== Code128Reader.CODE_STOP) {\n lastCharacterWasPrintable = false;\n }\n switch (code) {\n case Code128Reader.CODE_FNC_1:\n if (convertFNC1) {\n if (result.length === 0) {\n // GS1 specification 5.4.3.7. and 5.4.6.4. If the first char after the start code\n // is FNC1 then this is GS1-128. We add the symbology identifier.\n result += ']C1';\n }\n else {\n // GS1 specification 5.4.7.5. Every subsequent FNC1 is returned as ASCII 29 (GS)\n result += String.fromCharCode(29);\n }\n }\n break;\n case Code128Reader.CODE_CODE_A:\n codeSet = Code128Reader.CODE_CODE_A;\n break;\n case Code128Reader.CODE_CODE_B:\n codeSet = Code128Reader.CODE_CODE_B;\n break;\n case Code128Reader.CODE_STOP:\n done = true;\n break;\n }\n }\n break;\n }\n // Unshift back to another code set if we were shifted\n if (unshift) {\n codeSet = codeSet === Code128Reader.CODE_CODE_A ? Code128Reader.CODE_CODE_B : Code128Reader.CODE_CODE_A;\n }\n }\n const lastPatternSize = nextStart - lastStart;\n // Check for ample whitespace following pattern, but, to do this we first need to remember that\n // we fudged decoding CODE_STOP since it actually has 7 bars, not 6. There is a black bar left\n // to read off. Would be slightly better to properly read. Here we just skip it:\n nextStart = row.getNextUnset(nextStart);\n if (!row.isRange(nextStart, Math.min(row.getSize(), nextStart + (nextStart - lastStart) / 2), false)) {\n throw new NotFoundException();\n }\n // Pull out from sum the value of the penultimate check code\n checksumTotal -= multiplier * lastCode;\n // lastCode is the checksum then:\n if (checksumTotal % 103 !== lastCode) {\n throw new ChecksumException();\n }\n // Need to pull out the check digits from string\n const resultLength = result.length;\n if (resultLength === 0) {\n // false positive\n throw new NotFoundException();\n }\n // Only bother if the result had at least one character, and if the checksum digit happened to\n // be a printable character. If it was just interpreted as a control code, nothing to remove.\n if (resultLength > 0 && lastCharacterWasPrintable) {\n if (codeSet === Code128Reader.CODE_CODE_C) {\n result = result.substring(0, resultLength - 2);\n }\n else {\n result = result.substring(0, resultLength - 1);\n }\n }\n const left = (startPatternInfo[1] + startPatternInfo[0]) / 2.0;\n const right = lastStart + lastPatternSize / 2.0;\n const rawCodesSize = rawCodes.length;\n const rawBytes = new Uint8Array(rawCodesSize);\n for (let i = 0; i < rawCodesSize; i++) {\n rawBytes[i] = rawCodes[i];\n }\n const points = [new ResultPoint(left, rowNumber), new ResultPoint(right, rowNumber)];\n return new Result(result, rawBytes, 0, points, BarcodeFormat$1.CODE_128, new Date().getTime());\n }\n }\n Code128Reader.CODE_PATTERNS = [\n Int32Array.from([2, 1, 2, 2, 2, 2]),\n Int32Array.from([2, 2, 2, 1, 2, 2]),\n Int32Array.from([2, 2, 2, 2, 2, 1]),\n Int32Array.from([1, 2, 1, 2, 2, 3]),\n Int32Array.from([1, 2, 1, 3, 2, 2]),\n Int32Array.from([1, 3, 1, 2, 2, 2]),\n Int32Array.from([1, 2, 2, 2, 1, 3]),\n Int32Array.from([1, 2, 2, 3, 1, 2]),\n Int32Array.from([1, 3, 2, 2, 1, 2]),\n Int32Array.from([2, 2, 1, 2, 1, 3]),\n Int32Array.from([2, 2, 1, 3, 1, 2]),\n Int32Array.from([2, 3, 1, 2, 1, 2]),\n Int32Array.from([1, 1, 2, 2, 3, 2]),\n Int32Array.from([1, 2, 2, 1, 3, 2]),\n Int32Array.from([1, 2, 2, 2, 3, 1]),\n Int32Array.from([1, 1, 3, 2, 2, 2]),\n Int32Array.from([1, 2, 3, 1, 2, 2]),\n Int32Array.from([1, 2, 3, 2, 2, 1]),\n Int32Array.from([2, 2, 3, 2, 1, 1]),\n Int32Array.from([2, 2, 1, 1, 3, 2]),\n Int32Array.from([2, 2, 1, 2, 3, 1]),\n Int32Array.from([2, 1, 3, 2, 1, 2]),\n Int32Array.from([2, 2, 3, 1, 1, 2]),\n Int32Array.from([3, 1, 2, 1, 3, 1]),\n Int32Array.from([3, 1, 1, 2, 2, 2]),\n Int32Array.from([3, 2, 1, 1, 2, 2]),\n Int32Array.from([3, 2, 1, 2, 2, 1]),\n Int32Array.from([3, 1, 2, 2, 1, 2]),\n Int32Array.from([3, 2, 2, 1, 1, 2]),\n Int32Array.from([3, 2, 2, 2, 1, 1]),\n Int32Array.from([2, 1, 2, 1, 2, 3]),\n Int32Array.from([2, 1, 2, 3, 2, 1]),\n Int32Array.from([2, 3, 2, 1, 2, 1]),\n Int32Array.from([1, 1, 1, 3, 2, 3]),\n Int32Array.from([1, 3, 1, 1, 2, 3]),\n Int32Array.from([1, 3, 1, 3, 2, 1]),\n Int32Array.from([1, 1, 2, 3, 1, 3]),\n Int32Array.from([1, 3, 2, 1, 1, 3]),\n Int32Array.from([1, 3, 2, 3, 1, 1]),\n Int32Array.from([2, 1, 1, 3, 1, 3]),\n Int32Array.from([2, 3, 1, 1, 1, 3]),\n Int32Array.from([2, 3, 1, 3, 1, 1]),\n Int32Array.from([1, 1, 2, 1, 3, 3]),\n Int32Array.from([1, 1, 2, 3, 3, 1]),\n Int32Array.from([1, 3, 2, 1, 3, 1]),\n Int32Array.from([1, 1, 3, 1, 2, 3]),\n Int32Array.from([1, 1, 3, 3, 2, 1]),\n Int32Array.from([1, 3, 3, 1, 2, 1]),\n Int32Array.from([3, 1, 3, 1, 2, 1]),\n Int32Array.from([2, 1, 1, 3, 3, 1]),\n Int32Array.from([2, 3, 1, 1, 3, 1]),\n Int32Array.from([2, 1, 3, 1, 1, 3]),\n Int32Array.from([2, 1, 3, 3, 1, 1]),\n Int32Array.from([2, 1, 3, 1, 3, 1]),\n Int32Array.from([3, 1, 1, 1, 2, 3]),\n Int32Array.from([3, 1, 1, 3, 2, 1]),\n Int32Array.from([3, 3, 1, 1, 2, 1]),\n Int32Array.from([3, 1, 2, 1, 1, 3]),\n Int32Array.from([3, 1, 2, 3, 1, 1]),\n Int32Array.from([3, 3, 2, 1, 1, 1]),\n Int32Array.from([3, 1, 4, 1, 1, 1]),\n Int32Array.from([2, 2, 1, 4, 1, 1]),\n Int32Array.from([4, 3, 1, 1, 1, 1]),\n Int32Array.from([1, 1, 1, 2, 2, 4]),\n Int32Array.from([1, 1, 1, 4, 2, 2]),\n Int32Array.from([1, 2, 1, 1, 2, 4]),\n Int32Array.from([1, 2, 1, 4, 2, 1]),\n Int32Array.from([1, 4, 1, 1, 2, 2]),\n Int32Array.from([1, 4, 1, 2, 2, 1]),\n Int32Array.from([1, 1, 2, 2, 1, 4]),\n Int32Array.from([1, 1, 2, 4, 1, 2]),\n Int32Array.from([1, 2, 2, 1, 1, 4]),\n Int32Array.from([1, 2, 2, 4, 1, 1]),\n Int32Array.from([1, 4, 2, 1, 1, 2]),\n Int32Array.from([1, 4, 2, 2, 1, 1]),\n Int32Array.from([2, 4, 1, 2, 1, 1]),\n Int32Array.from([2, 2, 1, 1, 1, 4]),\n Int32Array.from([4, 1, 3, 1, 1, 1]),\n Int32Array.from([2, 4, 1, 1, 1, 2]),\n Int32Array.from([1, 3, 4, 1, 1, 1]),\n Int32Array.from([1, 1, 1, 2, 4, 2]),\n Int32Array.from([1, 2, 1, 1, 4, 2]),\n Int32Array.from([1, 2, 1, 2, 4, 1]),\n Int32Array.from([1, 1, 4, 2, 1, 2]),\n Int32Array.from([1, 2, 4, 1, 1, 2]),\n Int32Array.from([1, 2, 4, 2, 1, 1]),\n Int32Array.from([4, 1, 1, 2, 1, 2]),\n Int32Array.from([4, 2, 1, 1, 1, 2]),\n Int32Array.from([4, 2, 1, 2, 1, 1]),\n Int32Array.from([2, 1, 2, 1, 4, 1]),\n Int32Array.from([2, 1, 4, 1, 2, 1]),\n Int32Array.from([4, 1, 2, 1, 2, 1]),\n Int32Array.from([1, 1, 1, 1, 4, 3]),\n Int32Array.from([1, 1, 1, 3, 4, 1]),\n Int32Array.from([1, 3, 1, 1, 4, 1]),\n Int32Array.from([1, 1, 4, 1, 1, 3]),\n Int32Array.from([1, 1, 4, 3, 1, 1]),\n Int32Array.from([4, 1, 1, 1, 1, 3]),\n Int32Array.from([4, 1, 1, 3, 1, 1]),\n Int32Array.from([1, 1, 3, 1, 4, 1]),\n Int32Array.from([1, 1, 4, 1, 3, 1]),\n Int32Array.from([3, 1, 1, 1, 4, 1]),\n Int32Array.from([4, 1, 1, 1, 3, 1]),\n Int32Array.from([2, 1, 1, 4, 1, 2]),\n Int32Array.from([2, 1, 1, 2, 1, 4]),\n Int32Array.from([2, 1, 1, 2, 3, 2]),\n Int32Array.from([2, 3, 3, 1, 1, 1, 2]),\n ];\n Code128Reader.MAX_AVG_VARIANCE = 0.25;\n Code128Reader.MAX_INDIVIDUAL_VARIANCE = 0.7;\n Code128Reader.CODE_SHIFT = 98;\n Code128Reader.CODE_CODE_C = 99;\n Code128Reader.CODE_CODE_B = 100;\n Code128Reader.CODE_CODE_A = 101;\n Code128Reader.CODE_FNC_1 = 102;\n Code128Reader.CODE_FNC_2 = 97;\n Code128Reader.CODE_FNC_3 = 96;\n Code128Reader.CODE_FNC_4_A = 101;\n Code128Reader.CODE_FNC_4_B = 100;\n Code128Reader.CODE_START_A = 103;\n Code128Reader.CODE_START_B = 104;\n Code128Reader.CODE_START_C = 105;\n Code128Reader.CODE_STOP = 106;\n\n /**\n *

Decodes Code 39 barcodes. Supports \"Full ASCII Code 39\" if USE_CODE_39_EXTENDED_MODE is set.

\n *\n * @author Sean Owen\n * @see Code93Reader\n */\n class Code39Reader extends OneDReader {\n /**\n * Creates a reader that assumes all encoded data is data, and does not treat the final\n * character as a check digit. It will not decoded \"extended Code 39\" sequences.\n */\n // public Code39Reader() {\n // this(false);\n // }\n /**\n * Creates a reader that can be configured to check the last character as a check digit.\n * It will not decoded \"extended Code 39\" sequences.\n *\n * @param usingCheckDigit if true, treat the last data character as a check digit, not\n * data, and verify that the checksum passes.\n */\n // public Code39Reader(boolean usingCheckDigit) {\n // this(usingCheckDigit, false);\n // }\n /**\n * Creates a reader that can be configured to check the last character as a check digit,\n * or optionally attempt to decode \"extended Code 39\" sequences that are used to encode\n * the full ASCII character set.\n *\n * @param usingCheckDigit if true, treat the last data character as a check digit, not\n * data, and verify that the checksum passes.\n * @param extendedMode if true, will attempt to decode extended Code 39 sequences in the\n * text.\n */\n constructor(usingCheckDigit = false, extendedMode = false) {\n super();\n this.usingCheckDigit = usingCheckDigit;\n this.extendedMode = extendedMode;\n this.decodeRowResult = '';\n this.counters = new Int32Array(9);\n }\n decodeRow(rowNumber, row, hints) {\n let theCounters = this.counters;\n theCounters.fill(0);\n this.decodeRowResult = '';\n let start = Code39Reader.findAsteriskPattern(row, theCounters);\n // Read off white space\n let nextStart = row.getNextSet(start[1]);\n let end = row.getSize();\n let decodedChar;\n let lastStart;\n do {\n Code39Reader.recordPattern(row, nextStart, theCounters);\n let pattern = Code39Reader.toNarrowWidePattern(theCounters);\n if (pattern < 0) {\n throw new NotFoundException();\n }\n decodedChar = Code39Reader.patternToChar(pattern);\n this.decodeRowResult += decodedChar;\n lastStart = nextStart;\n for (let counter of theCounters) {\n nextStart += counter;\n }\n // Read off white space\n nextStart = row.getNextSet(nextStart);\n } while (decodedChar !== '*');\n this.decodeRowResult = this.decodeRowResult.substring(0, this.decodeRowResult.length - 1); // remove asterisk\n // Look for whitespace after pattern:\n let lastPatternSize = 0;\n for (let counter of theCounters) {\n lastPatternSize += counter;\n }\n let whiteSpaceAfterEnd = nextStart - lastStart - lastPatternSize;\n // If 50% of last pattern size, following last pattern, is not whitespace, fail\n // (but if it's whitespace to the very end of the image, that's OK)\n if (nextStart !== end && (whiteSpaceAfterEnd * 2) < lastPatternSize) {\n throw new NotFoundException();\n }\n if (this.usingCheckDigit) {\n let max = this.decodeRowResult.length - 1;\n let total = 0;\n for (let i = 0; i < max; i++) {\n total += Code39Reader.ALPHABET_STRING.indexOf(this.decodeRowResult.charAt(i));\n }\n if (this.decodeRowResult.charAt(max) !== Code39Reader.ALPHABET_STRING.charAt(total % 43)) {\n throw new ChecksumException();\n }\n this.decodeRowResult = this.decodeRowResult.substring(0, max);\n }\n if (this.decodeRowResult.length === 0) {\n // false positive\n throw new NotFoundException();\n }\n let resultString;\n if (this.extendedMode) {\n resultString = Code39Reader.decodeExtended(this.decodeRowResult);\n }\n else {\n resultString = this.decodeRowResult;\n }\n let left = (start[1] + start[0]) / 2.0;\n let right = lastStart + lastPatternSize / 2.0;\n return new Result(resultString, null, 0, [new ResultPoint(left, rowNumber), new ResultPoint(right, rowNumber)], BarcodeFormat$1.CODE_39, new Date().getTime());\n }\n static findAsteriskPattern(row, counters) {\n let width = row.getSize();\n let rowOffset = row.getNextSet(0);\n let counterPosition = 0;\n let patternStart = rowOffset;\n let isWhite = false;\n let patternLength = counters.length;\n for (let i = rowOffset; i < width; i++) {\n if (row.get(i) !== isWhite) {\n counters[counterPosition]++;\n }\n else {\n if (counterPosition === patternLength - 1) {\n // Look for whitespace before start pattern, >= 50% of width of start pattern\n if (this.toNarrowWidePattern(counters) === Code39Reader.ASTERISK_ENCODING &&\n row.isRange(Math.max(0, patternStart - Math.floor((i - patternStart) / 2)), patternStart, false)) {\n return [patternStart, i];\n }\n patternStart += counters[0] + counters[1];\n counters.copyWithin(0, 2, 2 + counterPosition - 1);\n counters[counterPosition - 1] = 0;\n counters[counterPosition] = 0;\n counterPosition--;\n }\n else {\n counterPosition++;\n }\n counters[counterPosition] = 1;\n isWhite = !isWhite;\n }\n }\n throw new NotFoundException();\n }\n // For efficiency, returns -1 on failure. Not throwing here saved as many as 700 exceptions\n // per image when using some of our blackbox images.\n static toNarrowWidePattern(counters) {\n let numCounters = counters.length;\n let maxNarrowCounter = 0;\n let wideCounters;\n do {\n let minCounter = 0x7fffffff;\n for (let counter of counters) {\n if (counter < minCounter && counter > maxNarrowCounter) {\n minCounter = counter;\n }\n }\n maxNarrowCounter = minCounter;\n wideCounters = 0;\n let totalWideCountersWidth = 0;\n let pattern = 0;\n for (let i = 0; i < numCounters; i++) {\n let counter = counters[i];\n if (counter > maxNarrowCounter) {\n pattern |= 1 << (numCounters - 1 - i);\n wideCounters++;\n totalWideCountersWidth += counter;\n }\n }\n if (wideCounters === 3) {\n // Found 3 wide counters, but are they close enough in width?\n // We can perform a cheap, conservative check to see if any individual\n // counter is more than 1.5 times the average:\n for (let i = 0; i < numCounters && wideCounters > 0; i++) {\n let counter = counters[i];\n if (counter > maxNarrowCounter) {\n wideCounters--;\n // totalWideCountersWidth = 3 * average, so this checks if counter >= 3/2 * average\n if ((counter * 2) >= totalWideCountersWidth) {\n return -1;\n }\n }\n }\n return pattern;\n }\n } while (wideCounters > 3);\n return -1;\n }\n static patternToChar(pattern) {\n for (let i = 0; i < Code39Reader.CHARACTER_ENCODINGS.length; i++) {\n if (Code39Reader.CHARACTER_ENCODINGS[i] === pattern) {\n return Code39Reader.ALPHABET_STRING.charAt(i);\n }\n }\n if (pattern === Code39Reader.ASTERISK_ENCODING) {\n return '*';\n }\n throw new NotFoundException();\n }\n static decodeExtended(encoded) {\n let length = encoded.length;\n let decoded = '';\n for (let i = 0; i < length; i++) {\n let c = encoded.charAt(i);\n if (c === '+' || c === '$' || c === '%' || c === '/') {\n let next = encoded.charAt(i + 1);\n let decodedChar = '\\0';\n switch (c) {\n case '+':\n // +A to +Z map to a to z\n if (next >= 'A' && next <= 'Z') {\n decodedChar = String.fromCharCode(next.charCodeAt(0) + 32);\n }\n else {\n throw new FormatException();\n }\n break;\n case '$':\n // $A to $Z map to control codes SH to SB\n if (next >= 'A' && next <= 'Z') {\n decodedChar = String.fromCharCode(next.charCodeAt(0) - 64);\n }\n else {\n throw new FormatException();\n }\n break;\n case '%':\n // %A to %E map to control codes ESC to US\n if (next >= 'A' && next <= 'E') {\n decodedChar = String.fromCharCode(next.charCodeAt(0) - 38);\n }\n else if (next >= 'F' && next <= 'J') {\n decodedChar = String.fromCharCode(next.charCodeAt(0) - 11);\n }\n else if (next >= 'K' && next <= 'O') {\n decodedChar = String.fromCharCode(next.charCodeAt(0) + 16);\n }\n else if (next >= 'P' && next <= 'T') {\n decodedChar = String.fromCharCode(next.charCodeAt(0) + 43);\n }\n else if (next === 'U') {\n decodedChar = '\\0';\n }\n else if (next === 'V') {\n decodedChar = '@';\n }\n else if (next === 'W') {\n decodedChar = '`';\n }\n else if (next === 'X' || next === 'Y' || next === 'Z') {\n decodedChar = '\\x7f';\n }\n else {\n throw new FormatException();\n }\n break;\n case '/':\n // /A to /O map to ! to , and /Z maps to :\n if (next >= 'A' && next <= 'O') {\n decodedChar = String.fromCharCode(next.charCodeAt(0) - 32);\n }\n else if (next === 'Z') {\n decodedChar = ':';\n }\n else {\n throw new FormatException();\n }\n break;\n }\n decoded += decodedChar;\n // bump up i again since we read two characters\n i++;\n }\n else {\n decoded += c;\n }\n }\n return decoded;\n }\n }\n Code39Reader.ALPHABET_STRING = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-. $/+%';\n /**\n * These represent the encodings of characters, as patterns of wide and narrow bars.\n * The 9 least-significant bits of each int correspond to the pattern of wide and narrow,\n * with 1s representing \"wide\" and 0s representing narrow.\n */\n Code39Reader.CHARACTER_ENCODINGS = [\n 0x034, 0x121, 0x061, 0x160, 0x031, 0x130, 0x070, 0x025, 0x124, 0x064,\n 0x109, 0x049, 0x148, 0x019, 0x118, 0x058, 0x00D, 0x10C, 0x04C, 0x01C,\n 0x103, 0x043, 0x142, 0x013, 0x112, 0x052, 0x007, 0x106, 0x046, 0x016,\n 0x181, 0x0C1, 0x1C0, 0x091, 0x190, 0x0D0, 0x085, 0x184, 0x0C4, 0x0A8,\n 0x0A2, 0x08A, 0x02A // /-%\n ];\n Code39Reader.ASTERISK_ENCODING = 0x094;\n\n /**\n *

Decodes ITF barcodes.

\n *\n * @author Tjieco\n */\n class ITFReader extends OneDReader {\n constructor() {\n // private static W = 3; // Pixel width of a 3x wide line\n // private static w = 2; // Pixel width of a 2x wide line\n // private static N = 1; // Pixed width of a narrow line\n super(...arguments);\n // Stores the actual narrow line width of the image being decoded.\n this.narrowLineWidth = -1;\n }\n // See ITFWriter.PATTERNS\n /*\n \n /!**\n * Patterns of Wide / Narrow lines to indicate each digit\n *!/\n */\n decodeRow(rowNumber, row, hints) {\n // Find out where the Middle section (payload) starts & ends\n let startRange = this.decodeStart(row);\n let endRange = this.decodeEnd(row);\n let result = new StringBuilder();\n ITFReader.decodeMiddle(row, startRange[1], endRange[0], result);\n let resultString = result.toString();\n let allowedLengths = null;\n if (hints != null) {\n allowedLengths = hints.get(DecodeHintType$1.ALLOWED_LENGTHS);\n }\n if (allowedLengths == null) {\n allowedLengths = ITFReader.DEFAULT_ALLOWED_LENGTHS;\n }\n // To avoid false positives with 2D barcodes (and other patterns), make\n // an assumption that the decoded string must be a 'standard' length if it's short\n let length = resultString.length;\n let lengthOK = false;\n let maxAllowedLength = 0;\n for (let value of allowedLengths) {\n if (length === value) {\n lengthOK = true;\n break;\n }\n if (value > maxAllowedLength) {\n maxAllowedLength = value;\n }\n }\n if (!lengthOK && length > maxAllowedLength) {\n lengthOK = true;\n }\n if (!lengthOK) {\n throw new FormatException();\n }\n const points = [new ResultPoint(startRange[1], rowNumber), new ResultPoint(endRange[0], rowNumber)];\n let resultReturn = new Result(resultString, null, // no natural byte representation for these barcodes\n 0, points, BarcodeFormat$1.ITF, new Date().getTime());\n return resultReturn;\n }\n /*\n /!**\n * @param row row of black/white values to search\n * @param payloadStart offset of start pattern\n * @param resultString {@link StringBuilder} to append decoded chars to\n * @throws NotFoundException if decoding could not complete successfully\n *!/*/\n static decodeMiddle(row, payloadStart, payloadEnd, resultString) {\n // Digits are interleaved in pairs - 5 black lines for one digit, and the\n // 5\n // interleaved white lines for the second digit.\n // Therefore, need to scan 10 lines and then\n // split these into two arrays\n let counterDigitPair = new Int32Array(10); // 10\n let counterBlack = new Int32Array(5); // 5\n let counterWhite = new Int32Array(5); // 5\n counterDigitPair.fill(0);\n counterBlack.fill(0);\n counterWhite.fill(0);\n while (payloadStart < payloadEnd) {\n // Get 10 runs of black/white.\n OneDReader.recordPattern(row, payloadStart, counterDigitPair);\n // Split them into each array\n for (let k = 0; k < 5; k++) {\n let twoK = 2 * k;\n counterBlack[k] = counterDigitPair[twoK];\n counterWhite[k] = counterDigitPair[twoK + 1];\n }\n let bestMatch = ITFReader.decodeDigit(counterBlack);\n resultString.append(bestMatch.toString());\n bestMatch = this.decodeDigit(counterWhite);\n resultString.append(bestMatch.toString());\n counterDigitPair.forEach(function (counterDigit) {\n payloadStart += counterDigit;\n });\n }\n }\n /*/!**\n * Identify where the start of the middle / payload section starts.\n *\n * @param row row of black/white values to search\n * @return Array, containing index of start of 'start block' and end of\n * 'start block'\n *!/*/\n decodeStart(row) {\n let endStart = ITFReader.skipWhiteSpace(row);\n let startPattern = ITFReader.findGuardPattern(row, endStart, ITFReader.START_PATTERN);\n // Determine the width of a narrow line in pixels. We can do this by\n // getting the width of the start pattern and dividing by 4 because its\n // made up of 4 narrow lines.\n this.narrowLineWidth = (startPattern[1] - startPattern[0]) / 4;\n this.validateQuietZone(row, startPattern[0]);\n return startPattern;\n }\n /*/!**\n * The start & end patterns must be pre/post fixed by a quiet zone. This\n * zone must be at least 10 times the width of a narrow line. Scan back until\n * we either get to the start of the barcode or match the necessary number of\n * quiet zone pixels.\n *\n * Note: Its assumed the row is reversed when using this method to find\n * quiet zone after the end pattern.\n *\n * ref: http://www.barcode-1.net/i25code.html\n *\n * @param row bit array representing the scanned barcode.\n * @param startPattern index into row of the start or end pattern.\n * @throws NotFoundException if the quiet zone cannot be found\n *!/*/\n validateQuietZone(row, startPattern) {\n let quietCount = this.narrowLineWidth * 10; // expect to find this many pixels of quiet zone\n // if there are not so many pixel at all let's try as many as possible\n quietCount = quietCount < startPattern ? quietCount : startPattern;\n for (let i = startPattern - 1; quietCount > 0 && i >= 0; i--) {\n if (row.get(i)) {\n break;\n }\n quietCount--;\n }\n if (quietCount !== 0) {\n // Unable to find the necessary number of quiet zone pixels.\n throw new NotFoundException();\n }\n }\n /*\n /!**\n * Skip all whitespace until we get to the first black line.\n *\n * @param row row of black/white values to search\n * @return index of the first black line.\n * @throws NotFoundException Throws exception if no black lines are found in the row\n *!/*/\n static skipWhiteSpace(row) {\n const width = row.getSize();\n const endStart = row.getNextSet(0);\n if (endStart === width) {\n throw new NotFoundException();\n }\n return endStart;\n }\n /*/!**\n * Identify where the end of the middle / payload section ends.\n *\n * @param row row of black/white values to search\n * @return Array, containing index of start of 'end block' and end of 'end\n * block'\n *!/*/\n decodeEnd(row) {\n // For convenience, reverse the row and then\n // search from 'the start' for the end block\n row.reverse();\n try {\n let endStart = ITFReader.skipWhiteSpace(row);\n let endPattern;\n try {\n endPattern = ITFReader.findGuardPattern(row, endStart, ITFReader.END_PATTERN_REVERSED[0]);\n }\n catch (error) {\n if (error instanceof NotFoundException) {\n endPattern = ITFReader.findGuardPattern(row, endStart, ITFReader.END_PATTERN_REVERSED[1]);\n }\n }\n // The start & end patterns must be pre/post fixed by a quiet zone. This\n // zone must be at least 10 times the width of a narrow line.\n // ref: http://www.barcode-1.net/i25code.html\n this.validateQuietZone(row, endPattern[0]);\n // Now recalculate the indices of where the 'endblock' starts & stops to\n // accommodate\n // the reversed nature of the search\n let temp = endPattern[0];\n endPattern[0] = row.getSize() - endPattern[1];\n endPattern[1] = row.getSize() - temp;\n return endPattern;\n }\n finally {\n // Put the row back the right way.\n row.reverse();\n }\n }\n /*\n /!**\n * @param row row of black/white values to search\n * @param rowOffset position to start search\n * @param pattern pattern of counts of number of black and white pixels that are\n * being searched for as a pattern\n * @return start/end horizontal offset of guard pattern, as an array of two\n * ints\n * @throws NotFoundException if pattern is not found\n *!/*/\n static findGuardPattern(row, rowOffset, pattern) {\n let patternLength = pattern.length;\n let counters = new Int32Array(patternLength);\n let width = row.getSize();\n let isWhite = false;\n let counterPosition = 0;\n let patternStart = rowOffset;\n counters.fill(0);\n for (let x = rowOffset; x < width; x++) {\n if (row.get(x) !== isWhite) {\n counters[counterPosition]++;\n }\n else {\n if (counterPosition === patternLength - 1) {\n if (OneDReader.patternMatchVariance(counters, pattern, ITFReader.MAX_INDIVIDUAL_VARIANCE) < ITFReader.MAX_AVG_VARIANCE) {\n return [patternStart, x];\n }\n patternStart += counters[0] + counters[1];\n System.arraycopy(counters, 2, counters, 0, counterPosition - 1);\n counters[counterPosition - 1] = 0;\n counters[counterPosition] = 0;\n counterPosition--;\n }\n else {\n counterPosition++;\n }\n counters[counterPosition] = 1;\n isWhite = !isWhite;\n }\n }\n throw new NotFoundException();\n }\n /*/!**\n * Attempts to decode a sequence of ITF black/white lines into single\n * digit.\n *\n * @param counters the counts of runs of observed black/white/black/... values\n * @return The decoded digit\n * @throws NotFoundException if digit cannot be decoded\n *!/*/\n static decodeDigit(counters) {\n let bestVariance = ITFReader.MAX_AVG_VARIANCE; // worst variance we'll accept\n let bestMatch = -1;\n let max = ITFReader.PATTERNS.length;\n for (let i = 0; i < max; i++) {\n let pattern = ITFReader.PATTERNS[i];\n let variance = OneDReader.patternMatchVariance(counters, pattern, ITFReader.MAX_INDIVIDUAL_VARIANCE);\n if (variance < bestVariance) {\n bestVariance = variance;\n bestMatch = i;\n }\n else if (variance === bestVariance) {\n // if we find a second 'best match' with the same variance, we can not reliably report to have a suitable match\n bestMatch = -1;\n }\n }\n if (bestMatch >= 0) {\n return bestMatch % 10;\n }\n else {\n throw new NotFoundException();\n }\n }\n }\n ITFReader.PATTERNS = [\n Int32Array.from([1, 1, 2, 2, 1]),\n Int32Array.from([2, 1, 1, 1, 2]),\n Int32Array.from([1, 2, 1, 1, 2]),\n Int32Array.from([2, 2, 1, 1, 1]),\n Int32Array.from([1, 1, 2, 1, 2]),\n Int32Array.from([2, 1, 2, 1, 1]),\n Int32Array.from([1, 2, 2, 1, 1]),\n Int32Array.from([1, 1, 1, 2, 2]),\n Int32Array.from([2, 1, 1, 2, 1]),\n Int32Array.from([1, 2, 1, 2, 1]),\n Int32Array.from([1, 1, 3, 3, 1]),\n Int32Array.from([3, 1, 1, 1, 3]),\n Int32Array.from([1, 3, 1, 1, 3]),\n Int32Array.from([3, 3, 1, 1, 1]),\n Int32Array.from([1, 1, 3, 1, 3]),\n Int32Array.from([3, 1, 3, 1, 1]),\n Int32Array.from([1, 3, 3, 1, 1]),\n Int32Array.from([1, 1, 1, 3, 3]),\n Int32Array.from([3, 1, 1, 3, 1]),\n Int32Array.from([1, 3, 1, 3, 1]) // 9\n ];\n ITFReader.MAX_AVG_VARIANCE = 0.38;\n ITFReader.MAX_INDIVIDUAL_VARIANCE = 0.5;\n /* /!** Valid ITF lengths. Anything longer than the largest value is also allowed. *!/*/\n ITFReader.DEFAULT_ALLOWED_LENGTHS = [6, 8, 10, 12, 14];\n /*/!**\n * Start/end guard pattern.\n *\n * Note: The end pattern is reversed because the row is reversed before\n * searching for the END_PATTERN\n *!/*/\n ITFReader.START_PATTERN = Int32Array.from([1, 1, 1, 1]);\n ITFReader.END_PATTERN_REVERSED = [\n Int32Array.from([1, 1, 2]),\n Int32Array.from([1, 1, 3]) // 3x\n ];\n\n /**\n *

Encapsulates functionality and implementation that is common to UPC and EAN families\n * of one-dimensional barcodes.

\n *\n * @author dswitkin@google.com (Daniel Switkin)\n * @author Sean Owen\n * @author alasdair@google.com (Alasdair Mackintosh)\n */\n class AbstractUPCEANReader extends OneDReader {\n constructor() {\n super(...arguments);\n this.decodeRowStringBuffer = '';\n }\n\n static findStartGuardPattern(row) {\n let foundStart = false;\n let startRange;\n let nextStart = 0;\n let counters = Int32Array.from([0, 0, 0]);\n while (!foundStart) {\n counters = Int32Array.from([0, 0, 0]);\n startRange = AbstractUPCEANReader.findGuardPattern(row, nextStart, false, this.START_END_PATTERN, counters);\n let start = startRange[0];\n nextStart = startRange[1];\n let quietStart = start - (nextStart - start);\n if (quietStart >= 0) {\n foundStart = row.isRange(quietStart, start, false);\n }\n }\n return startRange;\n }\n static checkChecksum(s) {\n return AbstractUPCEANReader.checkStandardUPCEANChecksum(s);\n }\n static checkStandardUPCEANChecksum(s) {\n let length = s.length;\n if (length === 0)\n return false;\n let check = parseInt(s.charAt(length - 1), 10);\n return AbstractUPCEANReader.getStandardUPCEANChecksum(s.substring(0, length - 1)) === check;\n }\n static getStandardUPCEANChecksum(s) {\n let length = s.length;\n let sum = 0;\n for (let i = length - 1; i >= 0; i -= 2) {\n let digit = s.charAt(i).charCodeAt(0) - '0'.charCodeAt(0);\n if (digit < 0 || digit > 9) {\n throw new FormatException();\n }\n sum += digit;\n }\n sum *= 3;\n for (let i = length - 2; i >= 0; i -= 2) {\n let digit = s.charAt(i).charCodeAt(0) - '0'.charCodeAt(0);\n if (digit < 0 || digit > 9) {\n throw new FormatException();\n }\n sum += digit;\n }\n return (1000 - sum) % 10;\n }\n static decodeEnd(row, endStart) {\n return AbstractUPCEANReader.findGuardPattern(row, endStart, false, AbstractUPCEANReader.START_END_PATTERN, new Int32Array(AbstractUPCEANReader.START_END_PATTERN.length).fill(0));\n }\n /**\n * @throws NotFoundException\n */\n static findGuardPatternWithoutCounters(row, rowOffset, whiteFirst, pattern) {\n return this.findGuardPattern(row, rowOffset, whiteFirst, pattern, new Int32Array(pattern.length));\n }\n /**\n * @param row row of black/white values to search\n * @param rowOffset position to start search\n * @param whiteFirst if true, indicates that the pattern specifies white/black/white/...\n * pixel counts, otherwise, it is interpreted as black/white/black/...\n * @param pattern pattern of counts of number of black and white pixels that are being\n * searched for as a pattern\n * @param counters array of counters, as long as pattern, to re-use\n * @return start/end horizontal offset of guard pattern, as an array of two ints\n * @throws NotFoundException if pattern is not found\n */\n static findGuardPattern(row, rowOffset, whiteFirst, pattern, counters) {\n let width = row.getSize();\n rowOffset = whiteFirst ? row.getNextUnset(rowOffset) : row.getNextSet(rowOffset);\n let counterPosition = 0;\n let patternStart = rowOffset;\n let patternLength = pattern.length;\n let isWhite = whiteFirst;\n for (let x = rowOffset; x < width; x++) {\n if (row.get(x) !== isWhite) {\n counters[counterPosition]++;\n }\n else {\n if (counterPosition === patternLength - 1) {\n if (OneDReader.patternMatchVariance(counters, pattern, AbstractUPCEANReader.MAX_INDIVIDUAL_VARIANCE) < AbstractUPCEANReader.MAX_AVG_VARIANCE) {\n return Int32Array.from([patternStart, x]);\n }\n patternStart += counters[0] + counters[1];\n let slice = counters.slice(2, counters.length - 1);\n for (let i = 0; i < counterPosition - 1; i++) {\n counters[i] = slice[i];\n }\n counters[counterPosition - 1] = 0;\n counters[counterPosition] = 0;\n counterPosition--;\n }\n else {\n counterPosition++;\n }\n counters[counterPosition] = 1;\n isWhite = !isWhite;\n }\n }\n throw new NotFoundException();\n }\n static decodeDigit(row, counters, rowOffset, patterns) {\n this.recordPattern(row, rowOffset, counters);\n let bestVariance = this.MAX_AVG_VARIANCE;\n let bestMatch = -1;\n let max = patterns.length;\n for (let i = 0; i < max; i++) {\n let pattern = patterns[i];\n let variance = OneDReader.patternMatchVariance(counters, pattern, AbstractUPCEANReader.MAX_INDIVIDUAL_VARIANCE);\n if (variance < bestVariance) {\n bestVariance = variance;\n bestMatch = i;\n }\n }\n if (bestMatch >= 0) {\n return bestMatch;\n }\n else {\n throw new NotFoundException();\n }\n }\n }\n // These two values are critical for determining how permissive the decoding will be.\n // We've arrived at these values through a lot of trial and error. Setting them any higher\n // lets false positives creep in quickly.\n AbstractUPCEANReader.MAX_AVG_VARIANCE = 0.48;\n AbstractUPCEANReader.MAX_INDIVIDUAL_VARIANCE = 0.7;\n /**\n * Start/end guard pattern.\n */\n AbstractUPCEANReader.START_END_PATTERN = Int32Array.from([1, 1, 1]);\n /**\n * Pattern marking the middle of a UPC/EAN pattern, separating the two halves.\n */\n AbstractUPCEANReader.MIDDLE_PATTERN = Int32Array.from([1, 1, 1, 1, 1]);\n /**\n * end guard pattern.\n */\n AbstractUPCEANReader.END_PATTERN = Int32Array.from([1, 1, 1, 1, 1, 1]);\n /**\n * \"Odd\", or \"L\" patterns used to encode UPC/EAN digits.\n */\n AbstractUPCEANReader.L_PATTERNS = [\n Int32Array.from([3, 2, 1, 1]),\n Int32Array.from([2, 2, 2, 1]),\n Int32Array.from([2, 1, 2, 2]),\n Int32Array.from([1, 4, 1, 1]),\n Int32Array.from([1, 1, 3, 2]),\n Int32Array.from([1, 2, 3, 1]),\n Int32Array.from([1, 1, 1, 4]),\n Int32Array.from([1, 3, 1, 2]),\n Int32Array.from([1, 2, 1, 3]),\n Int32Array.from([3, 1, 1, 2]),\n ];\n\n /**\n * @see UPCEANExtension2Support\n */\n class UPCEANExtension5Support {\n constructor() {\n this.CHECK_DIGIT_ENCODINGS = [0x18, 0x14, 0x12, 0x11, 0x0C, 0x06, 0x03, 0x0A, 0x09, 0x05];\n this.decodeMiddleCounters = Int32Array.from([0, 0, 0, 0]);\n this.decodeRowStringBuffer = '';\n }\n decodeRow(rowNumber, row, extensionStartRange) {\n let result = this.decodeRowStringBuffer;\n let end = this.decodeMiddle(row, extensionStartRange, result);\n let resultString = result.toString();\n let extensionData = UPCEANExtension5Support.parseExtensionString(resultString);\n let resultPoints = [\n new ResultPoint((extensionStartRange[0] + extensionStartRange[1]) / 2.0, rowNumber),\n new ResultPoint(end, rowNumber)\n ];\n let extensionResult = new Result(resultString, null, 0, resultPoints, BarcodeFormat$1.UPC_EAN_EXTENSION, new Date().getTime());\n if (extensionData != null) {\n extensionResult.putAllMetadata(extensionData);\n }\n return extensionResult;\n }\n decodeMiddle(row, startRange, resultString) {\n let counters = this.decodeMiddleCounters;\n counters[0] = 0;\n counters[1] = 0;\n counters[2] = 0;\n counters[3] = 0;\n let end = row.getSize();\n let rowOffset = startRange[1];\n let lgPatternFound = 0;\n for (let x = 0; x < 5 && rowOffset < end; x++) {\n let bestMatch = AbstractUPCEANReader.decodeDigit(\n row,\n counters,\n rowOffset,\n AbstractUPCEANReader.L_AND_G_PATTERNS);\n resultString += String.fromCharCode(('0'.charCodeAt(0) + bestMatch % 10));\n for (let counter of counters) {\n rowOffset += counter;\n }\n if (bestMatch >= 10) {\n lgPatternFound |= 1 << (4 - x);\n }\n if (x !== 4) {\n // Read off separator if not last\n rowOffset = row.getNextSet(rowOffset);\n rowOffset = row.getNextUnset(rowOffset);\n }\n }\n if (resultString.length !== 5) {\n throw new NotFoundException();\n }\n let checkDigit = this.determineCheckDigit(lgPatternFound);\n if (UPCEANExtension5Support.extensionChecksum(resultString.toString()) !== checkDigit) {\n throw new NotFoundException();\n }\n return rowOffset;\n }\n static extensionChecksum(s) {\n let length = s.length;\n let sum = 0;\n for (let i = length - 2; i >= 0; i -= 2) {\n sum += s.charAt(i).charCodeAt(0) - '0'.charCodeAt(0);\n }\n sum *= 3;\n for (let i = length - 1; i >= 0; i -= 2) {\n sum += s.charAt(i).charCodeAt(0) - '0'.charCodeAt(0);\n }\n sum *= 3;\n return sum % 10;\n }\n determineCheckDigit(lgPatternFound) {\n for (let d = 0; d < 10; d++) {\n if (lgPatternFound === this.CHECK_DIGIT_ENCODINGS[d]) {\n return d;\n }\n }\n throw new NotFoundException();\n }\n static parseExtensionString(raw) {\n if (raw.length !== 5) {\n return null;\n }\n let value = UPCEANExtension5Support.parseExtension5String(raw);\n if (value == null) {\n return null;\n }\n return new Map([[ResultMetadataType$1.SUGGESTED_PRICE, value]]);\n }\n static parseExtension5String(raw) {\n let currency;\n switch (raw.charAt(0)) {\n case '0':\n currency = '\u00A3';\n break;\n case '5':\n currency = '$';\n break;\n case '9':\n // Reference: http://www.jollytech.com\n switch (raw) {\n case '90000':\n // No suggested retail price\n return null;\n case '99991':\n // Complementary\n return '0.00';\n case '99990':\n return 'Used';\n }\n // Otherwise... unknown currency?\n currency = '';\n break;\n default:\n currency = '';\n break;\n }\n let rawAmount = parseInt(raw.substring(1));\n let unitsString = (rawAmount / 100).toString();\n let hundredths = rawAmount % 100;\n let hundredthsString = hundredths < 10 ? '0' + hundredths : hundredths.toString(); // fixme\n return currency + unitsString + '.' + hundredthsString;\n }\n }\n\n /**\n * @see UPCEANExtension5Support\n */\n class UPCEANExtension2Support {\n constructor() {\n this.decodeMiddleCounters = Int32Array.from([0, 0, 0, 0]);\n this.decodeRowStringBuffer = '';\n }\n decodeRow(rowNumber, row, extensionStartRange) {\n let result = this.decodeRowStringBuffer;\n let end = this.decodeMiddle(row, extensionStartRange, result);\n let resultString = result.toString();\n let extensionData = UPCEANExtension2Support.parseExtensionString(resultString);\n let resultPoints = [\n new ResultPoint((extensionStartRange[0] + extensionStartRange[1]) / 2.0, rowNumber),\n new ResultPoint(end, rowNumber)\n ];\n let extensionResult = new Result(resultString, null, 0, resultPoints, BarcodeFormat$1.UPC_EAN_EXTENSION, new Date().getTime());\n if (extensionData != null) {\n extensionResult.putAllMetadata(extensionData);\n }\n return extensionResult;\n }\n decodeMiddle(row, startRange, resultString) {\n let counters = this.decodeMiddleCounters;\n counters[0] = 0;\n counters[1] = 0;\n counters[2] = 0;\n counters[3] = 0;\n let end = row.getSize();\n let rowOffset = startRange[1];\n let checkParity = 0;\n for (let x = 0; x < 2 && rowOffset < end; x++) {\n let bestMatch = AbstractUPCEANReader.decodeDigit(row, counters, rowOffset, AbstractUPCEANReader.L_AND_G_PATTERNS);\n resultString += String.fromCharCode(('0'.charCodeAt(0) + bestMatch % 10));\n for (let counter of counters) {\n rowOffset += counter;\n }\n if (bestMatch >= 10) {\n checkParity |= 1 << (1 - x);\n }\n if (x !== 1) {\n // Read off separator if not last\n rowOffset = row.getNextSet(rowOffset);\n rowOffset = row.getNextUnset(rowOffset);\n }\n }\n if (resultString.length !== 2) {\n throw new NotFoundException();\n }\n if (parseInt(resultString.toString()) % 4 !== checkParity) {\n throw new NotFoundException();\n }\n return rowOffset;\n }\n static parseExtensionString(raw) {\n if (raw.length !== 2) {\n return null;\n }\n return new Map([[ResultMetadataType$1.ISSUE_NUMBER, parseInt(raw)]]);\n }\n }\n\n class UPCEANExtensionSupport {\n static decodeRow(rowNumber, row, rowOffset) {\n let extensionStartRange = AbstractUPCEANReader.findGuardPattern(\n row,\n rowOffset,\n false,\n this.EXTENSION_START_PATTERN,\n new Int32Array(this.EXTENSION_START_PATTERN.length).fill(0));\n try {\n // return null;\n let fiveSupport = new UPCEANExtension5Support();\n return fiveSupport.decodeRow(rowNumber, row, extensionStartRange);\n }\n catch (err) {\n // return null;\n let twoSupport = new UPCEANExtension2Support();\n return twoSupport.decodeRow(rowNumber, row, extensionStartRange);\n }\n }\n }\n UPCEANExtensionSupport.EXTENSION_START_PATTERN = Int32Array.from([1, 1, 2]);\n\n /**\n *

Encapsulates functionality and implementation that is common to UPC and EAN families\n * of one-dimensional barcodes.

\n *\n * @author dswitkin@google.com (Daniel Switkin)\n * @author Sean Owen\n * @author alasdair@google.com (Alasdair Mackintosh)\n */\n class UPCEANReader extends AbstractUPCEANReader {\n constructor() {\n super();\n this.decodeRowStringBuffer = '';\n UPCEANReader.L_AND_G_PATTERNS = UPCEANReader.L_PATTERNS.map(arr => Int32Array.from(arr));\n for (let i = 10; i < 20; i++) {\n let widths = UPCEANReader.L_PATTERNS[i - 10];\n let reversedWidths = new Int32Array(widths.length);\n for (let j = 0; j < widths.length; j++) {\n reversedWidths[j] = widths[widths.length - j - 1];\n }\n UPCEANReader.L_AND_G_PATTERNS[i] = reversedWidths;\n }\n }\n decodeRow(rowNumber, row, hints) {\n let startGuardRange = UPCEANReader.findStartGuardPattern(row);\n let resultPointCallback = hints == null ? null : hints.get(DecodeHintType$1.NEED_RESULT_POINT_CALLBACK);\n if (resultPointCallback != null) {\n const resultPoint = new ResultPoint((startGuardRange[0] + startGuardRange[1]) / 2.0, rowNumber);\n resultPointCallback.foundPossibleResultPoint(resultPoint);\n }\n let budello = this.decodeMiddle(row, startGuardRange, this.decodeRowStringBuffer);\n let endStart = budello.rowOffset;\n let result = budello.resultString;\n if (resultPointCallback != null) {\n const resultPoint = new ResultPoint(endStart, rowNumber);\n resultPointCallback.foundPossibleResultPoint(resultPoint);\n }\n let endRange = this.decodeEnd(row, endStart);\n if (resultPointCallback != null) {\n const resultPoint = new ResultPoint((endRange[0] + endRange[1]) / 2.0, rowNumber);\n resultPointCallback.foundPossibleResultPoint(resultPoint);\n }\n // Make sure there is a quiet zone at least as big as the end pattern after the barcode. The\n // spec might want more whitespace, but in practice this is the maximum we can count on.\n let end = endRange[1];\n let quietEnd = end + (end - endRange[0]);\n if (quietEnd >= row.getSize() || !row.isRange(end, quietEnd, false)) {\n throw new NotFoundException();\n }\n let resultString = result.toString();\n // UPC/EAN should never be less than 8 chars anyway\n if (resultString.length < 8) {\n throw new FormatException();\n }\n if (!UPCEANReader.checkChecksum(resultString)) {\n throw new ChecksumException();\n }\n let left = (startGuardRange[1] + startGuardRange[0]) / 2.0;\n let right = (endRange[1] + endRange[0]) / 2.0;\n let format = this.getBarcodeFormat();\n let resultPoint = [new ResultPoint(left, rowNumber), new ResultPoint(right, rowNumber)];\n let decodeResult = new Result(resultString, null, 0, resultPoint, format, new Date().getTime());\n let extensionLength = 0;\n try {\n let extensionResult = UPCEANExtensionSupport.decodeRow(rowNumber, row, endRange[1]);\n decodeResult.putMetadata(ResultMetadataType$1.UPC_EAN_EXTENSION, extensionResult.getText());\n decodeResult.putAllMetadata(extensionResult.getResultMetadata());\n decodeResult.addResultPoints(extensionResult.getResultPoints());\n extensionLength = extensionResult.getText().length;\n }\n catch (ignoreError) {}\n let allowedExtensions = hints == null ? null : hints.get(DecodeHintType$1.ALLOWED_EAN_EXTENSIONS);\n if (allowedExtensions != null) {\n let valid = false;\n for (let length in allowedExtensions) {\n if (extensionLength.toString() === length) { // check me\n valid = true;\n break;\n }\n }\n if (!valid) {\n throw new NotFoundException();\n }\n }\n return decodeResult;\n }\n decodeEnd(row, endStart) {\n return UPCEANReader.findGuardPattern(\n row, endStart, false, UPCEANReader.START_END_PATTERN,\n new Int32Array(UPCEANReader.START_END_PATTERN.length).fill(0));\n }\n static checkChecksum(s) {\n return UPCEANReader.checkStandardUPCEANChecksum(s);\n }\n static checkStandardUPCEANChecksum(s) {\n let length = s.length;\n if (length === 0)\n return false;\n let check = parseInt(s.charAt(length - 1), 10);\n return UPCEANReader.getStandardUPCEANChecksum(s.substring(0, length - 1)) === check;\n }\n static getStandardUPCEANChecksum(s) {\n let length = s.length;\n let sum = 0;\n for (let i = length - 1; i >= 0; i -= 2) {\n let digit = s.charAt(i).charCodeAt(0) - '0'.charCodeAt(0);\n if (digit < 0 || digit > 9) {\n throw new FormatException();\n }\n sum += digit;\n }\n sum *= 3;\n for (let i = length - 2; i >= 0; i -= 2) {\n let digit = s.charAt(i).charCodeAt(0) - '0'.charCodeAt(0);\n if (digit < 0 || digit > 9) {\n throw new FormatException();\n }\n sum += digit;\n }\n return (1000 - sum) % 10;\n }\n }\n\n /**\n *

Implements decoding of the EAN-13 format.

\n *\n * @author dswitkin@google.com (Daniel Switkin)\n * @author Sean Owen\n * @author alasdair@google.com (Alasdair Mackintosh)\n */\n class EAN13Reader extends UPCEANReader {\n constructor() {\n super();\n this.decodeMiddleCounters = Int32Array.from([0, 0, 0, 0]);\n }\n decodeMiddle(row, startRange, resultString) {\n let counters = this.decodeMiddleCounters;\n counters[0] = 0;\n counters[1] = 0;\n counters[2] = 0;\n counters[3] = 0;\n let end = row.getSize();\n let rowOffset = startRange[1];\n let lgPatternFound = 0;\n for (let x = 0; x < 6 && rowOffset < end; x++) {\n let bestMatch = UPCEANReader.decodeDigit(row, counters, rowOffset, UPCEANReader.L_AND_G_PATTERNS);\n resultString += String.fromCharCode(('0'.charCodeAt(0) + bestMatch % 10));\n for (let counter of counters) {\n rowOffset += counter;\n }\n if (bestMatch >= 10) {\n lgPatternFound |= 1 << (5 - x);\n }\n }\n resultString = EAN13Reader.determineFirstDigit(resultString, lgPatternFound);\n let middleRange = UPCEANReader.findGuardPattern(\n row,\n rowOffset,\n true,\n UPCEANReader.MIDDLE_PATTERN,\n new Int32Array(UPCEANReader.MIDDLE_PATTERN.length).fill(0));\n rowOffset = middleRange[1];\n for (let x = 0; x < 6 && rowOffset < end; x++) {\n let bestMatch = UPCEANReader.decodeDigit(row, counters, rowOffset, UPCEANReader.L_PATTERNS);\n resultString += String.fromCharCode(('0'.charCodeAt(0) + bestMatch));\n for (let counter of counters) {\n rowOffset += counter;\n }\n }\n return { rowOffset, resultString };\n }\n getBarcodeFormat() {\n return BarcodeFormat$1.EAN_13;\n }\n static determineFirstDigit(resultString, lgPatternFound) {\n for (let d = 0; d < 10; d++) {\n if (lgPatternFound === this.FIRST_DIGIT_ENCODINGS[d]) {\n resultString = String.fromCharCode(('0'.charCodeAt(0) + d)) + resultString;\n return resultString;\n }\n }\n throw new NotFoundException();\n }\n }\n EAN13Reader.FIRST_DIGIT_ENCODINGS = [0x00, 0x0B, 0x0D, 0xE, 0x13, 0x19, 0x1C, 0x15, 0x16, 0x1A];\n\n /**\n *

Implements decoding of the EAN-8 format.

\n *\n * @author Sean Owen\n */\n class EAN8Reader extends UPCEANReader {\n constructor() {\n super();\n this.decodeMiddleCounters = Int32Array.from([0, 0, 0, 0]);\n }\n decodeMiddle(row, startRange, resultString) {\n const counters = this.decodeMiddleCounters;\n counters[0] = 0;\n counters[1] = 0;\n counters[2] = 0;\n counters[3] = 0;\n let end = row.getSize();\n let rowOffset = startRange[1];\n for (let x = 0; x < 4 && rowOffset < end; x++) {\n let bestMatch = UPCEANReader.decodeDigit(row, counters, rowOffset, UPCEANReader.L_PATTERNS);\n resultString += String.fromCharCode(('0'.charCodeAt(0) + bestMatch));\n for (let counter of counters) {\n rowOffset += counter;\n }\n }\n let middleRange = UPCEANReader.findGuardPattern(row, rowOffset, true, UPCEANReader.MIDDLE_PATTERN, new Int32Array(UPCEANReader.MIDDLE_PATTERN.length).fill(0));\n rowOffset = middleRange[1];\n for (let x = 0; x < 4 && rowOffset < end; x++) {\n let bestMatch = UPCEANReader.decodeDigit(row, counters, rowOffset, UPCEANReader.L_PATTERNS);\n resultString += String.fromCharCode(('0'.charCodeAt(0) + bestMatch));\n for (let counter of counters) {\n rowOffset += counter;\n }\n }\n return { rowOffset, resultString };\n }\n getBarcodeFormat() {\n return BarcodeFormat$1.EAN_8;\n }\n }\n\n /**\n * Encapsulates functionality and implementation that is common to all families\n * of one-dimensional barcodes.\n *\n * @author dswitkin@google.com (Daniel Switkin)\n * @author Sean Owen\n * @author sam2332 (Sam Rudloff)\n *\n * @source https://github.com/zxing/zxing/blob/3c96923276dd5785d58eb970b6ba3f80d36a9505/core/src/main/java/com/google/zxing/oned/UPCAReader.java\n *\n * @experimental\n */\n class UPCAReader extends UPCEANReader {\n constructor() {\n super(...arguments);\n this.ean13Reader = new EAN13Reader();\n }\n // @Override\n getBarcodeFormat() {\n return BarcodeFormat$1.UPC_A;\n }\n // Note that we don't try rotation without the try harder flag, even if rotation was supported.\n // @Override\n decode(image, hints) {\n return this.maybeReturnResult(this.ean13Reader.decode(image));\n }\n // @Override\n decodeRow(rowNumber, row, hints) {\n return this.maybeReturnResult(this.ean13Reader.decodeRow(rowNumber, row, hints));\n }\n // @Override\n decodeMiddle(row, startRange, resultString) {\n return this.ean13Reader.decodeMiddle(row, startRange, resultString);\n }\n maybeReturnResult(result) {\n let text = result.getText();\n if (text.charAt(0) === '0') {\n let upcaResult = new Result(text.substring(1), null, null, result.getResultPoints(), BarcodeFormat$1.UPC_A);\n if (result.getResultMetadata() != null) {\n upcaResult.putAllMetadata(result.getResultMetadata());\n }\n return upcaResult;\n }\n else {\n throw new NotFoundException();\n }\n }\n reset() {\n this.ean13Reader.reset();\n }\n }\n\n /**\n *

Implements decoding of the UPC-E format.

\n *

This is a great reference for\n * UPC-E information.

\n *\n * @author Sean Owen\n *\n * @source https://github.com/zxing/zxing/blob/3c96923276dd5785d58eb970b6ba3f80d36a9505/core/src/main/java/com/google/zxing/oned/UPCEReader.java\n *\n * @experimental\n */\n /* final */ class UPCEReader extends UPCEANReader {\n constructor() {\n super();\n this.decodeMiddleCounters = new Int32Array(4);\n }\n /**\n * @throws NotFoundException\n */\n // @Override\n decodeMiddle(row, startRange, result) {\n const counters = this.decodeMiddleCounters.map(x => x);\n counters[0] = 0;\n counters[1] = 0;\n counters[2] = 0;\n counters[3] = 0;\n const end = row.getSize();\n let rowOffset = startRange[1];\n let lgPatternFound = 0;\n for (let x = 0; x < 6 && rowOffset < end; x++) {\n const bestMatch = UPCEReader.decodeDigit(\n row, counters, rowOffset, UPCEReader.L_AND_G_PATTERNS);\n result += String.fromCharCode(('0'.charCodeAt(0) + (bestMatch % 10)));\n for (let counter of counters) {\n rowOffset += counter;\n }\n if (bestMatch >= 10) {\n lgPatternFound |= (1 << (5 - x));\n }\n }\n let resultString = UPCEReader.determineNumSysAndCheckDigit(\n result, lgPatternFound);\n return {rowOffset, resultString};\n }\n /**\n * @throws NotFoundException\n */\n // @Override\n decodeEnd(row, endStart) {\n return UPCEReader.findGuardPatternWithoutCounters(\n row, endStart, true, UPCEReader.MIDDLE_END_PATTERN);\n }\n /**\n * @throws FormatException\n */\n // @Override\n checkChecksum(s) {\n return UPCEANReader.checkChecksum(UPCEReader.convertUPCEtoUPCA(s));\n }\n /**\n * @throws NotFoundException\n */\n static determineNumSysAndCheckDigit(resultString, lgPatternFound) {\n for (let numSys = 0; numSys <= 1; numSys++) {\n for (let d = 0; d < 10; d++) {\n if (lgPatternFound === this.NUMSYS_AND_CHECK_DIGIT_PATTERNS[numSys][d]) {\n let prefix = String.fromCharCode('0'.charCodeAt(0) + numSys);\n let suffix = String.fromCharCode('0'.charCodeAt(0) + d);\n return prefix + resultString + suffix;\n }\n }\n }\n throw NotFoundException.getNotFoundInstance();\n }\n // @Override\n getBarcodeFormat() {\n return BarcodeFormat$1.UPC_E;\n }\n /**\n * Expands a UPC-E value back into its full, equivalent UPC-A code value.\n *\n * @param upce UPC-E code as string of digits\n * @return equivalent UPC-A code as string of digits\n */\n static convertUPCEtoUPCA(upce) {\n // the following line is equivalent to upce.getChars(1, 7, upceChars, 0);\n const upceChars = upce.slice(1, 7).split('').map(x => x.charCodeAt(0));\n const result = new StringBuilder( /*12*/);\n result.append(upce.charAt(0));\n let lastChar = upceChars[5];\n switch (lastChar) {\n case 0:\n case 1:\n case 2:\n result.appendChars(upceChars, 0, 2);\n result.append(lastChar);\n result.append('0000');\n result.appendChars(upceChars, 2, 3);\n break;\n case 3:\n result.appendChars(upceChars, 0, 3);\n result.append('00000');\n result.appendChars(upceChars, 3, 2);\n break;\n case 4:\n result.appendChars(upceChars, 0, 4);\n result.append('00000');\n result.append(upceChars[4]);\n break;\n default:\n result.appendChars(upceChars, 0, 5);\n result.append('0000');\n result.append(lastChar);\n break;\n }\n // Only append check digit in conversion if supplied\n if (upce.length >= 8) {\n result.append(upce.charAt(7));\n }\n return result.toString();\n }\n }\n /**\n * The pattern that marks the middle, and end, of a UPC-E pattern.\n * There is no \"second half\" to a UPC-E barcode.\n */\n UPCEReader.MIDDLE_END_PATTERN = Int32Array.from([1, 1, 1, 1, 1, 1]);\n // For an UPC-E barcode, the final digit is represented by the parities used\n // to encode the middle six digits, according to the table below.\n //\n // Parity of next 6 digits\n // Digit 0 1 2 3 4 5\n // 0 Even Even Even Odd Odd Odd\n // 1 Even Even Odd Even Odd Odd\n // 2 Even Even Odd Odd Even Odd\n // 3 Even Even Odd Odd Odd Even\n // 4 Even Odd Even Even Odd Odd\n // 5 Even Odd Odd Even Even Odd\n // 6 Even Odd Odd Odd Even Even\n // 7 Even Odd Even Odd Even Odd\n // 8 Even Odd Even Odd Odd Even\n // 9 Even Odd Odd Even Odd Even\n //\n // The encoding is represented by the following array, which is a bit pattern\n // using Odd = 0 and Even = 1. For example, 5 is represented by:\n //\n // Odd Even Even Odd Odd Even\n // in binary:\n // 0 1 1 0 0 1 == 0x19\n //\n /**\n * See {@link #L_AND_G_PATTERNS}; these values similarly represent patterns of\n * even-odd parity encodings of digits that imply both the number system (0 or 1)\n * used, and the check digit.\n */\n UPCEReader.NUMSYS_AND_CHECK_DIGIT_PATTERNS = [\n Int32Array.from([0x38, 0x34, 0x32, 0x31, 0x2C, 0x26, 0x23, 0x2A, 0x29, 0x25]),\n Int32Array.from([0x07, 0x0B, 0x0D, 0x0E, 0x13, 0x19, 0x1C, 0x15, 0x16, 0x1A]),\n ];\n\n /**\n *

A reader that can read all available UPC/EAN formats. If a caller wants to try to\n * read all such formats, it is most efficient to use this implementation rather than invoke\n * individual readers.

\n *\n * @author Sean Owen\n */\n class MultiFormatUPCEANReader extends OneDReader {\n constructor(hints) {\n super();\n let possibleFormats = hints == null ? null : hints.get(DecodeHintType$1.POSSIBLE_FORMATS);\n let readers = [];\n if (!isNullOrUndefined(possibleFormats)) {\n if (possibleFormats.indexOf(BarcodeFormat$1.EAN_13) > -1) {\n readers.push(new EAN13Reader());\n }\n if (possibleFormats.indexOf(BarcodeFormat$1.UPC_A) > -1) {\n readers.push(new UPCAReader());\n }\n if (possibleFormats.indexOf(BarcodeFormat$1.EAN_8) > -1) {\n readers.push(new EAN8Reader());\n }\n if (possibleFormats.indexOf(BarcodeFormat$1.UPC_E) > -1) {\n readers.push(new UPCEReader());\n }\n } else {\n // No hints provided.\n readers.push(new EAN13Reader());\n readers.push(new UPCAReader());\n readers.push(new EAN8Reader());\n readers.push(new UPCEReader());\n }\n this.readers = readers;\n }\n decodeRow(rowNumber, row, hints) {\n for (let reader of this.readers) {\n try {\n // const result: Result = reader.decodeRow(rowNumber, row, startGuardPattern, hints);\n const result = reader.decodeRow(rowNumber, row, hints);\n // Special case: a 12-digit code encoded in UPC-A is identical to a \"0\"\n // followed by those 12 digits encoded as EAN-13. Each will recognize such a code,\n // UPC-A as a 12-digit string and EAN-13 as a 13-digit string starting with \"0\".\n // Individually these are correct and their readers will both read such a code\n // and correctly call it EAN-13, or UPC-A, respectively.\n //\n // In this case, if we've been looking for both types, we'd like to call it\n // a UPC-A code. But for efficiency we only run the EAN-13 decoder to also read\n // UPC-A. So we special case it here, and convert an EAN-13 result to a UPC-A\n // result if appropriate.\n //\n // But, don't return UPC-A if UPC-A was not a requested format!\n const ean13MayBeUPCA = result.getBarcodeFormat() === BarcodeFormat$1.EAN_13 &&\n result.getText().charAt(0) === '0';\n // @SuppressWarnings(\"unchecked\")\n const possibleFormats = hints == null ? null : hints.get(DecodeHintType$1.POSSIBLE_FORMATS);\n const canReturnUPCA = possibleFormats == null || possibleFormats.includes(BarcodeFormat$1.UPC_A);\n if (ean13MayBeUPCA && canReturnUPCA) {\n const rawBytes = result.getRawBytes();\n // Transfer the metadata across\n const resultUPCA = new Result(\n result.getText().substring(1),\n rawBytes,\n (rawBytes ? rawBytes.length : null),\n result.getResultPoints(),\n BarcodeFormat$1.UPC_A);\n resultUPCA.putAllMetadata(result.getResultMetadata());\n return resultUPCA;\n }\n return result;\n }\n catch (err) {\n // continue;\n }\n }\n throw new NotFoundException();\n }\n reset() {\n for (let reader of this.readers) {\n reader.reset();\n }\n }\n }\n\n // import Integer from '../../util/Integer';\n // import Float from '../../util/Float';\n class AbstractRSSReader extends OneDReader {\n constructor() {\n super();\n this.decodeFinderCounters = new Int32Array(4);\n this.dataCharacterCounters = new Int32Array(8);\n this.oddRoundingErrors = new Array(4);\n this.evenRoundingErrors = new Array(4);\n this.oddCounts = new Array(this.dataCharacterCounters.length / 2);\n this.evenCounts = new Array(this.dataCharacterCounters.length / 2);\n }\n getDecodeFinderCounters() {\n return this.decodeFinderCounters;\n }\n getDataCharacterCounters() {\n return this.dataCharacterCounters;\n }\n getOddRoundingErrors() {\n return this.oddRoundingErrors;\n }\n getEvenRoundingErrors() {\n return this.evenRoundingErrors;\n }\n getOddCounts() {\n return this.oddCounts;\n }\n getEvenCounts() {\n return this.evenCounts;\n }\n parseFinderValue(counters, finderPatterns) {\n for (let value = 0; value < finderPatterns.length; value++) {\n if (OneDReader.patternMatchVariance(counters, finderPatterns[value], AbstractRSSReader.MAX_INDIVIDUAL_VARIANCE) < AbstractRSSReader.MAX_AVG_VARIANCE) {\n return value;\n }\n }\n throw new NotFoundException();\n }\n /**\n * @param array values to sum\n * @return sum of values\n * @deprecated call {@link MathUtils#sum(int[])}\n */\n static count(array) {\n return MathUtils.sum(new Int32Array(array));\n }\n static increment(array, errors) {\n let index = 0;\n let biggestError = errors[0];\n for (let i = 1; i < array.length; i++) {\n if (errors[i] > biggestError) {\n biggestError = errors[i];\n index = i;\n }\n }\n array[index]++;\n }\n static decrement(array, errors) {\n let index = 0;\n let biggestError = errors[0];\n for (let i = 1; i < array.length; i++) {\n if (errors[i] < biggestError) {\n biggestError = errors[i];\n index = i;\n }\n }\n array[index]--;\n }\n static isFinderPattern(counters) {\n let firstTwoSum = counters[0] + counters[1];\n let sum = firstTwoSum + counters[2] + counters[3];\n let ratio = firstTwoSum / sum;\n if (ratio >= AbstractRSSReader.MIN_FINDER_PATTERN_RATIO && ratio <= AbstractRSSReader.MAX_FINDER_PATTERN_RATIO) {\n // passes ratio test in spec, but see if the counts are unreasonable\n let minCounter = Number.MAX_SAFE_INTEGER;\n let maxCounter = Number.MIN_SAFE_INTEGER;\n for (let counter of counters) {\n if (counter > maxCounter) {\n maxCounter = counter;\n }\n if (counter < minCounter) {\n minCounter = counter;\n }\n }\n return maxCounter < 10 * minCounter;\n }\n return false;\n }\n }\n AbstractRSSReader.MAX_AVG_VARIANCE = 0.2;\n AbstractRSSReader.MAX_INDIVIDUAL_VARIANCE = 0.45;\n AbstractRSSReader.MIN_FINDER_PATTERN_RATIO = 9.5 / 12.0;\n AbstractRSSReader.MAX_FINDER_PATTERN_RATIO = 12.5 / 14.0;\n\n class DataCharacter {\n constructor(value, checksumPortion) {\n this.value = value;\n this.checksumPortion = checksumPortion;\n }\n getValue() {\n return this.value;\n }\n getChecksumPortion() {\n return this.checksumPortion;\n }\n toString() {\n return this.value + '(' + this.checksumPortion + ')';\n }\n equals(o) {\n if (!(o instanceof DataCharacter)) {\n return false;\n }\n const that = o;\n return this.value === that.value && this.checksumPortion === that.checksumPortion;\n }\n hashCode() {\n return this.value ^ this.checksumPortion;\n }\n }\n\n class FinderPattern {\n constructor(value, startEnd, start, end, rowNumber) {\n this.value = value;\n this.startEnd = startEnd;\n this.value = value;\n this.startEnd = startEnd;\n this.resultPoints = new Array();\n this.resultPoints.push(new ResultPoint(start, rowNumber));\n this.resultPoints.push(new ResultPoint(end, rowNumber));\n }\n getValue() {\n return this.value;\n }\n getStartEnd() {\n return this.startEnd;\n }\n getResultPoints() {\n return this.resultPoints;\n }\n equals(o) {\n if (!(o instanceof FinderPattern)) {\n return false;\n }\n const that = o;\n return this.value === that.value;\n }\n hashCode() {\n return this.value;\n }\n }\n\n /**\n * RSS util functions.\n */\n class RSSUtils {\n constructor() { }\n static getRSSvalue(widths, maxWidth, noNarrow) {\n let n = 0;\n for (let width of widths) {\n n += width;\n }\n let val = 0;\n let narrowMask = 0;\n let elements = widths.length;\n for (let bar = 0; bar < elements - 1; bar++) {\n let elmWidth;\n for (elmWidth = 1, narrowMask |= 1 << bar; elmWidth < widths[bar]; elmWidth++, narrowMask &= ~(1 << bar)) {\n let subVal = RSSUtils.combins(n - elmWidth - 1, elements - bar - 2);\n if (noNarrow && (narrowMask === 0) && (n - elmWidth - (elements - bar - 1) >= elements - bar - 1)) {\n subVal -= RSSUtils.combins(n - elmWidth - (elements - bar), elements - bar - 2);\n }\n if (elements - bar - 1 > 1) {\n let lessVal = 0;\n for (let mxwElement = n - elmWidth - (elements - bar - 2); mxwElement > maxWidth; mxwElement--) {\n lessVal += RSSUtils.combins(n - elmWidth - mxwElement - 1, elements - bar - 3);\n }\n subVal -= lessVal * (elements - 1 - bar);\n }\n else if (n - elmWidth > maxWidth) {\n subVal--;\n }\n val += subVal;\n }\n n -= elmWidth;\n }\n return val;\n }\n static combins(n, r) {\n let maxDenom;\n let minDenom;\n if (n - r > r) {\n minDenom = r;\n maxDenom = n - r;\n }\n else {\n minDenom = n - r;\n maxDenom = r;\n }\n let val = 1;\n let j = 1;\n for (let i = n; i > maxDenom; i--) {\n val *= i;\n if (j <= minDenom) {\n val /= j;\n j++;\n }\n }\n while ((j <= minDenom)) {\n val /= j;\n j++;\n }\n return val;\n }\n }\n\n class BitArrayBuilder {\n static buildBitArray(pairs) {\n let charNumber = (pairs.length * 2) - 1;\n if (pairs[pairs.length - 1].getRightChar() == null) {\n charNumber -= 1;\n }\n let size = 12 * charNumber;\n let binary = new BitArray(size);\n let accPos = 0;\n let firstPair = pairs[0];\n let firstValue = firstPair.getRightChar().getValue();\n for (let i = 11; i >= 0; --i) {\n if ((firstValue & (1 << i)) != 0) {\n binary.set(accPos);\n }\n accPos++;\n }\n for (let i = 1; i < pairs.length; ++i) {\n let currentPair = pairs[i];\n let leftValue = currentPair.getLeftChar().getValue();\n for (let j = 11; j >= 0; --j) {\n if ((leftValue & (1 << j)) != 0) {\n binary.set(accPos);\n }\n accPos++;\n }\n if (currentPair.getRightChar() != null) {\n let rightValue = currentPair.getRightChar().getValue();\n for (let j = 11; j >= 0; --j) {\n if ((rightValue & (1 << j)) != 0) {\n binary.set(accPos);\n }\n accPos++;\n }\n }\n }\n return binary;\n }\n }\n\n class BlockParsedResult {\n constructor(finished, decodedInformation) {\n if (decodedInformation) {\n this.decodedInformation = null;\n }\n else {\n this.finished = finished;\n this.decodedInformation = decodedInformation;\n }\n }\n getDecodedInformation() {\n return this.decodedInformation;\n }\n isFinished() {\n return this.finished;\n }\n }\n\n class DecodedObject {\n constructor(newPosition) {\n this.newPosition = newPosition;\n }\n getNewPosition() {\n return this.newPosition;\n }\n }\n\n class DecodedChar extends DecodedObject {\n constructor(newPosition, value) {\n super(newPosition);\n this.value = value;\n }\n getValue() {\n return this.value;\n }\n isFNC1() {\n return this.value === DecodedChar.FNC1;\n }\n }\n DecodedChar.FNC1 = '$';\n\n class DecodedInformation extends DecodedObject {\n constructor(newPosition, newString, remainingValue) {\n super(newPosition);\n if (remainingValue) {\n this.remaining = true;\n this.remainingValue = this.remainingValue;\n }\n else {\n this.remaining = false;\n this.remainingValue = 0;\n }\n this.newString = newString;\n }\n getNewString() {\n return this.newString;\n }\n isRemaining() {\n return this.remaining;\n }\n getRemainingValue() {\n return this.remainingValue;\n }\n }\n\n class DecodedNumeric extends DecodedObject {\n constructor(newPosition, firstDigit, secondDigit) {\n super(newPosition);\n if (firstDigit < 0 || firstDigit > 10 || secondDigit < 0 || secondDigit > 10) {\n throw new FormatException();\n }\n this.firstDigit = firstDigit;\n this.secondDigit = secondDigit;\n }\n getFirstDigit() {\n return this.firstDigit;\n }\n getSecondDigit() {\n return this.secondDigit;\n }\n getValue() {\n return this.firstDigit * 10 + this.secondDigit;\n }\n isFirstDigitFNC1() {\n return this.firstDigit === DecodedNumeric.FNC1;\n }\n isSecondDigitFNC1() {\n return this.secondDigit === DecodedNumeric.FNC1;\n }\n isAnyFNC1() {\n return this.firstDigit === DecodedNumeric.FNC1 || this.secondDigit === DecodedNumeric.FNC1;\n }\n }\n DecodedNumeric.FNC1 = 10;\n\n class FieldParser {\n constructor() {\n }\n static parseFieldsInGeneralPurpose(rawInformation) {\n if (!rawInformation) {\n return null;\n }\n // Processing 2-digit AIs\n if (rawInformation.length < 2) {\n throw new NotFoundException();\n }\n let firstTwoDigits = rawInformation.substring(0, 2);\n for (let dataLength of FieldParser.TWO_DIGIT_DATA_LENGTH) {\n if (dataLength[0] === firstTwoDigits) {\n if (dataLength[1] === FieldParser.VARIABLE_LENGTH) {\n return FieldParser.processVariableAI(2, dataLength[2], rawInformation);\n }\n return FieldParser.processFixedAI(2, dataLength[1], rawInformation);\n }\n }\n if (rawInformation.length < 3) {\n throw new NotFoundException();\n }\n let firstThreeDigits = rawInformation.substring(0, 3);\n for (let dataLength of FieldParser.THREE_DIGIT_DATA_LENGTH) {\n if (dataLength[0] === firstThreeDigits) {\n if (dataLength[1] === FieldParser.VARIABLE_LENGTH) {\n return FieldParser.processVariableAI(3, dataLength[2], rawInformation);\n }\n return FieldParser.processFixedAI(3, dataLength[1], rawInformation);\n }\n }\n for (let dataLength of FieldParser.THREE_DIGIT_PLUS_DIGIT_DATA_LENGTH) {\n if (dataLength[0] === firstThreeDigits) {\n if (dataLength[1] === FieldParser.VARIABLE_LENGTH) {\n return FieldParser.processVariableAI(4, dataLength[2], rawInformation);\n }\n return FieldParser.processFixedAI(4, dataLength[1], rawInformation);\n }\n }\n if (rawInformation.length < 4) {\n throw new NotFoundException();\n }\n let firstFourDigits = rawInformation.substring(0, 4);\n for (let dataLength of FieldParser.FOUR_DIGIT_DATA_LENGTH) {\n if (dataLength[0] === firstFourDigits) {\n if (dataLength[1] === FieldParser.VARIABLE_LENGTH) {\n return FieldParser.processVariableAI(4, dataLength[2], rawInformation);\n }\n return FieldParser.processFixedAI(4, dataLength[1], rawInformation);\n }\n }\n throw new NotFoundException();\n }\n static processFixedAI(aiSize, fieldSize, rawInformation) {\n if (rawInformation.length < aiSize) {\n throw new NotFoundException();\n }\n let ai = rawInformation.substring(0, aiSize);\n if (rawInformation.length < aiSize + fieldSize) {\n throw new NotFoundException();\n }\n let field = rawInformation.substring(aiSize, aiSize + fieldSize);\n let remaining = rawInformation.substring(aiSize + fieldSize);\n let result = '(' + ai + ')' + field;\n let parsedAI = FieldParser.parseFieldsInGeneralPurpose(remaining);\n return parsedAI == null ? result : result + parsedAI;\n }\n static processVariableAI(aiSize, variableFieldSize, rawInformation) {\n let ai = rawInformation.substring(0, aiSize);\n let maxSize;\n if (rawInformation.length < aiSize + variableFieldSize) {\n maxSize = rawInformation.length;\n }\n else {\n maxSize = aiSize + variableFieldSize;\n }\n let field = rawInformation.substring(aiSize, maxSize);\n let remaining = rawInformation.substring(maxSize);\n let result = '(' + ai + ')' + field;\n let parsedAI = FieldParser.parseFieldsInGeneralPurpose(remaining);\n return parsedAI == null ? result : result + parsedAI;\n }\n }\n FieldParser.VARIABLE_LENGTH = [];\n FieldParser.TWO_DIGIT_DATA_LENGTH = [\n ['00', 18],\n ['01', 14],\n ['02', 14],\n ['10', FieldParser.VARIABLE_LENGTH, 20],\n ['11', 6],\n ['12', 6],\n ['13', 6],\n ['15', 6],\n ['17', 6],\n ['20', 2],\n ['21', FieldParser.VARIABLE_LENGTH, 20],\n ['22', FieldParser.VARIABLE_LENGTH, 29],\n ['30', FieldParser.VARIABLE_LENGTH, 8],\n ['37', FieldParser.VARIABLE_LENGTH, 8],\n // internal company codes\n ['90', FieldParser.VARIABLE_LENGTH, 30],\n ['91', FieldParser.VARIABLE_LENGTH, 30],\n ['92', FieldParser.VARIABLE_LENGTH, 30],\n ['93', FieldParser.VARIABLE_LENGTH, 30],\n ['94', FieldParser.VARIABLE_LENGTH, 30],\n ['95', FieldParser.VARIABLE_LENGTH, 30],\n ['96', FieldParser.VARIABLE_LENGTH, 30],\n ['97', FieldParser.VARIABLE_LENGTH, 3],\n ['98', FieldParser.VARIABLE_LENGTH, 30],\n ['99', FieldParser.VARIABLE_LENGTH, 30],\n ];\n FieldParser.THREE_DIGIT_DATA_LENGTH = [\n // Same format as above\n ['240', FieldParser.VARIABLE_LENGTH, 30],\n ['241', FieldParser.VARIABLE_LENGTH, 30],\n ['242', FieldParser.VARIABLE_LENGTH, 6],\n ['250', FieldParser.VARIABLE_LENGTH, 30],\n ['251', FieldParser.VARIABLE_LENGTH, 30],\n ['253', FieldParser.VARIABLE_LENGTH, 17],\n ['254', FieldParser.VARIABLE_LENGTH, 20],\n ['400', FieldParser.VARIABLE_LENGTH, 30],\n ['401', FieldParser.VARIABLE_LENGTH, 30],\n ['402', 17],\n ['403', FieldParser.VARIABLE_LENGTH, 30],\n ['410', 13],\n ['411', 13],\n ['412', 13],\n ['413', 13],\n ['414', 13],\n ['420', FieldParser.VARIABLE_LENGTH, 20],\n ['421', FieldParser.VARIABLE_LENGTH, 15],\n ['422', 3],\n ['423', FieldParser.VARIABLE_LENGTH, 15],\n ['424', 3],\n ['425', 3],\n ['426', 3],\n ];\n FieldParser.THREE_DIGIT_PLUS_DIGIT_DATA_LENGTH = [\n // Same format as above\n ['310', 6],\n ['311', 6],\n ['312', 6],\n ['313', 6],\n ['314', 6],\n ['315', 6],\n ['316', 6],\n ['320', 6],\n ['321', 6],\n ['322', 6],\n ['323', 6],\n ['324', 6],\n ['325', 6],\n ['326', 6],\n ['327', 6],\n ['328', 6],\n ['329', 6],\n ['330', 6],\n ['331', 6],\n ['332', 6],\n ['333', 6],\n ['334', 6],\n ['335', 6],\n ['336', 6],\n ['340', 6],\n ['341', 6],\n ['342', 6],\n ['343', 6],\n ['344', 6],\n ['345', 6],\n ['346', 6],\n ['347', 6],\n ['348', 6],\n ['349', 6],\n ['350', 6],\n ['351', 6],\n ['352', 6],\n ['353', 6],\n ['354', 6],\n ['355', 6],\n ['356', 6],\n ['357', 6],\n ['360', 6],\n ['361', 6],\n ['362', 6],\n ['363', 6],\n ['364', 6],\n ['365', 6],\n ['366', 6],\n ['367', 6],\n ['368', 6],\n ['369', 6],\n ['390', FieldParser.VARIABLE_LENGTH, 15],\n ['391', FieldParser.VARIABLE_LENGTH, 18],\n ['392', FieldParser.VARIABLE_LENGTH, 15],\n ['393', FieldParser.VARIABLE_LENGTH, 18],\n ['703', FieldParser.VARIABLE_LENGTH, 30],\n ];\n FieldParser.FOUR_DIGIT_DATA_LENGTH = [\n // Same format as above\n ['7001', 13],\n ['7002', FieldParser.VARIABLE_LENGTH, 30],\n ['7003', 10],\n ['8001', 14],\n ['8002', FieldParser.VARIABLE_LENGTH, 20],\n ['8003', FieldParser.VARIABLE_LENGTH, 30],\n ['8004', FieldParser.VARIABLE_LENGTH, 30],\n ['8005', 6],\n ['8006', 18],\n ['8007', FieldParser.VARIABLE_LENGTH, 30],\n ['8008', FieldParser.VARIABLE_LENGTH, 12],\n ['8018', 18],\n ['8020', FieldParser.VARIABLE_LENGTH, 25],\n ['8100', 6],\n ['8101', 10],\n ['8102', 2],\n ['8110', FieldParser.VARIABLE_LENGTH, 70],\n ['8200', FieldParser.VARIABLE_LENGTH, 70],\n ];\n\n class GeneralAppIdDecoder {\n constructor(information) {\n this.buffer = new StringBuilder();\n this.information = information;\n }\n decodeAllCodes(buff, initialPosition) {\n let currentPosition = initialPosition;\n let remaining = null;\n do {\n let info = this.decodeGeneralPurposeField(currentPosition, remaining);\n let parsedFields = FieldParser.parseFieldsInGeneralPurpose(info.getNewString());\n if (parsedFields != null) {\n buff.append(parsedFields);\n }\n if (info.isRemaining()) {\n remaining = '' + info.getRemainingValue();\n }\n else {\n remaining = null;\n }\n if (currentPosition === info.getNewPosition()) { // No step forward!\n break;\n }\n currentPosition = info.getNewPosition();\n } while (true);\n return buff.toString();\n }\n isStillNumeric(pos) {\n // It's numeric if it still has 7 positions\n // and one of the first 4 bits is \"1\".\n if (pos + 7 > this.information.getSize()) {\n return pos + 4 <= this.information.getSize();\n }\n for (let i = pos; i < pos + 3; ++i) {\n if (this.information.get(i)) {\n return true;\n }\n }\n return this.information.get(pos + 3);\n }\n decodeNumeric(pos) {\n if (pos + 7 > this.information.getSize()) {\n let numeric = this.extractNumericValueFromBitArray(pos, 4);\n if (numeric === 0) {\n return new DecodedNumeric(this.information.getSize(), DecodedNumeric.FNC1, DecodedNumeric.FNC1);\n }\n return new DecodedNumeric(this.information.getSize(), numeric - 1, DecodedNumeric.FNC1);\n }\n let numeric = this.extractNumericValueFromBitArray(pos, 7);\n let digit1 = (numeric - 8) / 11;\n let digit2 = (numeric - 8) % 11;\n return new DecodedNumeric(pos + 7, digit1, digit2);\n }\n extractNumericValueFromBitArray(pos, bits) {\n return GeneralAppIdDecoder.extractNumericValueFromBitArray(this.information, pos, bits);\n }\n static extractNumericValueFromBitArray(information, pos, bits) {\n let value = 0;\n for (let i = 0; i < bits; ++i) {\n if (information.get(pos + i)) {\n value |= 1 << (bits - i - 1);\n }\n }\n return value;\n }\n decodeGeneralPurposeField(pos, remaining) {\n // this.buffer.setLength(0);\n this.buffer.setLengthToZero();\n if (remaining != null) {\n this.buffer.append(remaining);\n }\n this.current.setPosition(pos);\n let lastDecoded = this.parseBlocks();\n if (lastDecoded != null && lastDecoded.isRemaining()) {\n return new DecodedInformation(this.current.getPosition(), this.buffer.toString(), lastDecoded.getRemainingValue());\n }\n return new DecodedInformation(this.current.getPosition(), this.buffer.toString());\n }\n parseBlocks() {\n let isFinished;\n let result;\n do {\n let initialPosition = this.current.getPosition();\n if (this.current.isAlpha()) {\n result = this.parseAlphaBlock();\n isFinished = result.isFinished();\n }\n else if (this.current.isIsoIec646()) {\n result = this.parseIsoIec646Block();\n isFinished = result.isFinished();\n }\n else { // it must be numeric\n result = this.parseNumericBlock();\n isFinished = result.isFinished();\n }\n let positionChanged = initialPosition !== this.current.getPosition();\n if (!positionChanged && !isFinished) {\n break;\n }\n } while (!isFinished);\n return result.getDecodedInformation();\n }\n parseNumericBlock() {\n while (this.isStillNumeric(this.current.getPosition())) {\n let numeric = this.decodeNumeric(this.current.getPosition());\n this.current.setPosition(numeric.getNewPosition());\n if (numeric.isFirstDigitFNC1()) {\n let information;\n if (numeric.isSecondDigitFNC1()) {\n information = new DecodedInformation(this.current.getPosition(), this.buffer.toString());\n }\n else {\n information = new DecodedInformation(this.current.getPosition(), this.buffer.toString(), numeric.getSecondDigit());\n }\n return new BlockParsedResult(true, information);\n }\n this.buffer.append(numeric.getFirstDigit());\n if (numeric.isSecondDigitFNC1()) {\n let information = new DecodedInformation(this.current.getPosition(), this.buffer.toString());\n return new BlockParsedResult(true, information);\n }\n this.buffer.append(numeric.getSecondDigit());\n }\n if (this.isNumericToAlphaNumericLatch(this.current.getPosition())) {\n this.current.setAlpha();\n this.current.incrementPosition(4);\n }\n return new BlockParsedResult(false);\n }\n parseIsoIec646Block() {\n while (this.isStillIsoIec646(this.current.getPosition())) {\n let iso = this.decodeIsoIec646(this.current.getPosition());\n this.current.setPosition(iso.getNewPosition());\n if (iso.isFNC1()) {\n let information = new DecodedInformation(this.current.getPosition(), this.buffer.toString());\n return new BlockParsedResult(true, information);\n }\n this.buffer.append(iso.getValue());\n }\n if (this.isAlphaOr646ToNumericLatch(this.current.getPosition())) {\n this.current.incrementPosition(3);\n this.current.setNumeric();\n }\n else if (this.isAlphaTo646ToAlphaLatch(this.current.getPosition())) {\n if (this.current.getPosition() + 5 < this.information.getSize()) {\n this.current.incrementPosition(5);\n }\n else {\n this.current.setPosition(this.information.getSize());\n }\n this.current.setAlpha();\n }\n return new BlockParsedResult(false);\n }\n parseAlphaBlock() {\n while (this.isStillAlpha(this.current.getPosition())) {\n let alpha = this.decodeAlphanumeric(this.current.getPosition());\n this.current.setPosition(alpha.getNewPosition());\n if (alpha.isFNC1()) {\n let information = new DecodedInformation(this.current.getPosition(), this.buffer.toString());\n return new BlockParsedResult(true, information); // end of the char block\n }\n this.buffer.append(alpha.getValue());\n }\n if (this.isAlphaOr646ToNumericLatch(this.current.getPosition())) {\n this.current.incrementPosition(3);\n this.current.setNumeric();\n }\n else if (this.isAlphaTo646ToAlphaLatch(this.current.getPosition())) {\n if (this.current.getPosition() + 5 < this.information.getSize()) {\n this.current.incrementPosition(5);\n }\n else {\n this.current.setPosition(this.information.getSize());\n }\n this.current.setIsoIec646();\n }\n return new BlockParsedResult(false);\n }\n isStillIsoIec646(pos) {\n if (pos + 5 > this.information.getSize()) {\n return false;\n }\n let fiveBitValue = this.extractNumericValueFromBitArray(pos, 5);\n if (fiveBitValue >= 5 && fiveBitValue < 16) {\n return true;\n }\n if (pos + 7 > this.information.getSize()) {\n return false;\n }\n let sevenBitValue = this.extractNumericValueFromBitArray(pos, 7);\n if (sevenBitValue >= 64 && sevenBitValue < 116) {\n return true;\n }\n if (pos + 8 > this.information.getSize()) {\n return false;\n }\n let eightBitValue = this.extractNumericValueFromBitArray(pos, 8);\n return eightBitValue >= 232 && eightBitValue < 253;\n }\n decodeIsoIec646(pos) {\n let fiveBitValue = this.extractNumericValueFromBitArray(pos, 5);\n if (fiveBitValue === 15) {\n return new DecodedChar(pos + 5, DecodedChar.FNC1);\n }\n if (fiveBitValue >= 5 && fiveBitValue < 15) {\n return new DecodedChar(pos + 5, ('0' + (fiveBitValue - 5)));\n }\n let sevenBitValue = this.extractNumericValueFromBitArray(pos, 7);\n if (sevenBitValue >= 64 && sevenBitValue < 90) {\n return new DecodedChar(pos + 7, ('' + (sevenBitValue + 1)));\n }\n if (sevenBitValue >= 90 && sevenBitValue < 116) {\n return new DecodedChar(pos + 7, ('' + (sevenBitValue + 7)));\n }\n let eightBitValue = this.extractNumericValueFromBitArray(pos, 8);\n let c;\n switch (eightBitValue) {\n case 232:\n c = '!';\n break;\n case 233:\n c = '\"';\n break;\n case 234:\n c = '%';\n break;\n case 235:\n c = '&';\n break;\n case 236:\n c = '\\'';\n break;\n case 237:\n c = '(';\n break;\n case 238:\n c = ')';\n break;\n case 239:\n c = '*';\n break;\n case 240:\n c = '+';\n break;\n case 241:\n c = ',';\n break;\n case 242:\n c = '-';\n break;\n case 243:\n c = '.';\n break;\n case 244:\n c = '/';\n break;\n case 245:\n c = ':';\n break;\n case 246:\n c = ';';\n break;\n case 247:\n c = '<';\n break;\n case 248:\n c = '=';\n break;\n case 249:\n c = '>';\n break;\n case 250:\n c = '?';\n break;\n case 251:\n c = '_';\n break;\n case 252:\n c = ' ';\n break;\n default:\n throw new FormatException();\n }\n return new DecodedChar(pos + 8, c);\n }\n isStillAlpha(pos) {\n if (pos + 5 > this.information.getSize()) {\n return false;\n }\n // We now check if it's a valid 5-bit value (0..9 and FNC1)\n let fiveBitValue = this.extractNumericValueFromBitArray(pos, 5);\n if (fiveBitValue >= 5 && fiveBitValue < 16) {\n return true;\n }\n if (pos + 6 > this.information.getSize()) {\n return false;\n }\n let sixBitValue = this.extractNumericValueFromBitArray(pos, 6);\n return sixBitValue >= 16 && sixBitValue < 63; // 63 not included\n }\n decodeAlphanumeric(pos) {\n let fiveBitValue = this.extractNumericValueFromBitArray(pos, 5);\n if (fiveBitValue === 15) {\n return new DecodedChar(pos + 5, DecodedChar.FNC1);\n }\n if (fiveBitValue >= 5 && fiveBitValue < 15) {\n return new DecodedChar(pos + 5, ('0' + (fiveBitValue - 5)));\n }\n let sixBitValue = this.extractNumericValueFromBitArray(pos, 6);\n if (sixBitValue >= 32 && sixBitValue < 58) {\n return new DecodedChar(pos + 6, ('' + (sixBitValue + 33)));\n }\n let c;\n switch (sixBitValue) {\n case 58:\n c = '*';\n break;\n case 59:\n c = ',';\n break;\n case 60:\n c = '-';\n break;\n case 61:\n c = '.';\n break;\n case 62:\n c = '/';\n break;\n default:\n throw new IllegalStateException('Decoding invalid alphanumeric value: ' + sixBitValue);\n }\n return new DecodedChar(pos + 6, c);\n }\n isAlphaTo646ToAlphaLatch(pos) {\n if (pos + 1 > this.information.getSize()) {\n return false;\n }\n for (let i = 0; i < 5 && i + pos < this.information.getSize(); ++i) {\n if (i === 2) {\n if (!this.information.get(pos + 2)) {\n return false;\n }\n }\n else if (this.information.get(pos + i)) {\n return false;\n }\n }\n return true;\n }\n isAlphaOr646ToNumericLatch(pos) {\n // Next is alphanumeric if there are 3 positions and they are all zeros\n if (pos + 3 > this.information.getSize()) {\n return false;\n }\n for (let i = pos; i < pos + 3; ++i) {\n if (this.information.get(i)) {\n return false;\n }\n }\n return true;\n }\n isNumericToAlphaNumericLatch(pos) {\n // Next is alphanumeric if there are 4 positions and they are all zeros, or\n // if there is a subset of this just before the end of the symbol\n if (pos + 1 > this.information.getSize()) {\n return false;\n }\n for (let i = 0; i < 4 && i + pos < this.information.getSize(); ++i) {\n if (this.information.get(pos + i)) {\n return false;\n }\n }\n return true;\n }\n }\n\n class AbstractExpandedDecoder {\n constructor(information) {\n this.information = information;\n this.generalDecoder = new GeneralAppIdDecoder(information);\n }\n getInformation() {\n return this.information;\n }\n getGeneralDecoder() {\n return this.generalDecoder;\n }\n }\n\n class AI01decoder extends AbstractExpandedDecoder {\n constructor(information) {\n super(information);\n }\n encodeCompressedGtin(buf, currentPos) {\n buf.append('(01)');\n let initialPosition = buf.length();\n buf.append('9');\n this.encodeCompressedGtinWithoutAI(buf, currentPos, initialPosition);\n }\n encodeCompressedGtinWithoutAI(buf, currentPos, initialBufferPosition) {\n for (let i = 0; i < 4; ++i) {\n let currentBlock = this.getGeneralDecoder().extractNumericValueFromBitArray(currentPos + 10 * i, 10);\n if (currentBlock / 100 === 0) {\n buf.append('0');\n }\n if (currentBlock / 10 === 0) {\n buf.append('0');\n }\n buf.append(currentBlock);\n }\n AI01decoder.appendCheckDigit(buf, initialBufferPosition);\n }\n static appendCheckDigit(buf, currentPos) {\n let checkDigit = 0;\n for (let i = 0; i < 13; i++) {\n // let digit = buf.charAt(i + currentPos) - '0';\n // To be checked\n let digit = buf.charAt(i + currentPos).charCodeAt(0) - '0'.charCodeAt(0);\n checkDigit += (i & 0x01) === 0 ? 3 * digit : digit;\n }\n checkDigit = 10 - (checkDigit % 10);\n if (checkDigit === 10) {\n checkDigit = 0;\n }\n buf.append(checkDigit);\n }\n }\n AI01decoder.GTIN_SIZE = 40;\n\n class AI01AndOtherAIs extends AI01decoder {\n // the second one is the encodation method, and the other two are for the variable length\n constructor(information) {\n super(information);\n }\n parseInformation() {\n let buff = new StringBuilder();\n buff.append('(01)');\n let initialGtinPosition = buff.length();\n let firstGtinDigit = this.getGeneralDecoder().extractNumericValueFromBitArray(AI01AndOtherAIs.HEADER_SIZE, 4);\n buff.append(firstGtinDigit);\n this.encodeCompressedGtinWithoutAI(buff, AI01AndOtherAIs.HEADER_SIZE + 4, initialGtinPosition);\n return this.getGeneralDecoder().decodeAllCodes(buff, AI01AndOtherAIs.HEADER_SIZE + 44);\n }\n }\n AI01AndOtherAIs.HEADER_SIZE = 1 + 1 + 2; // first bit encodes the linkage flag,\n\n class AnyAIDecoder extends AbstractExpandedDecoder {\n constructor(information) {\n super(information);\n }\n parseInformation() {\n let buf = new StringBuilder();\n return this.getGeneralDecoder().decodeAllCodes(buf, AnyAIDecoder.HEADER_SIZE);\n }\n }\n AnyAIDecoder.HEADER_SIZE = 2 + 1 + 2;\n\n class AI01weightDecoder extends AI01decoder {\n constructor(information) {\n super(information);\n }\n encodeCompressedWeight(buf, currentPos, weightSize) {\n let originalWeightNumeric = this.getGeneralDecoder().extractNumericValueFromBitArray(currentPos, weightSize);\n this.addWeightCode(buf, originalWeightNumeric);\n let weightNumeric = this.checkWeight(originalWeightNumeric);\n let currentDivisor = 100000;\n for (let i = 0; i < 5; ++i) {\n if (weightNumeric / currentDivisor === 0) {\n buf.append('0');\n }\n currentDivisor /= 10;\n }\n buf.append(weightNumeric);\n }\n }\n\n class AI013x0xDecoder extends AI01weightDecoder {\n constructor(information) {\n super(information);\n }\n parseInformation() {\n if (this.getInformation().getSize() != AI013x0xDecoder.HEADER_SIZE + AI01weightDecoder.GTIN_SIZE + AI013x0xDecoder.WEIGHT_SIZE) {\n throw new NotFoundException();\n }\n let buf = new StringBuilder();\n this.encodeCompressedGtin(buf, AI013x0xDecoder.HEADER_SIZE);\n this.encodeCompressedWeight(buf, AI013x0xDecoder.HEADER_SIZE + AI01weightDecoder.GTIN_SIZE, AI013x0xDecoder.WEIGHT_SIZE);\n return buf.toString();\n }\n }\n AI013x0xDecoder.HEADER_SIZE = 4 + 1;\n AI013x0xDecoder.WEIGHT_SIZE = 15;\n\n class AI013103decoder extends AI013x0xDecoder {\n constructor(information) {\n super(information);\n }\n addWeightCode(buf, weight) {\n buf.append('(3103)');\n }\n checkWeight(weight) {\n return weight;\n }\n }\n\n class AI01320xDecoder extends AI013x0xDecoder {\n constructor(information) {\n super(information);\n }\n addWeightCode(buf, weight) {\n if (weight < 10000) {\n buf.append('(3202)');\n }\n else {\n buf.append('(3203)');\n }\n }\n checkWeight(weight) {\n if (weight < 10000) {\n return weight;\n }\n return weight - 10000;\n }\n }\n\n class AI01392xDecoder extends AI01decoder {\n constructor(information) {\n super(information);\n }\n parseInformation() {\n if (this.getInformation().getSize() < AI01392xDecoder.HEADER_SIZE + AI01decoder.GTIN_SIZE) {\n throw new NotFoundException();\n }\n let buf = new StringBuilder();\n this.encodeCompressedGtin(buf, AI01392xDecoder.HEADER_SIZE);\n let lastAIdigit = this.getGeneralDecoder().extractNumericValueFromBitArray(AI01392xDecoder.HEADER_SIZE + AI01decoder.GTIN_SIZE, AI01392xDecoder.LAST_DIGIT_SIZE);\n buf.append('(392');\n buf.append(lastAIdigit);\n buf.append(')');\n let decodedInformation = this.getGeneralDecoder().decodeGeneralPurposeField(AI01392xDecoder.HEADER_SIZE + AI01decoder.GTIN_SIZE + AI01392xDecoder.LAST_DIGIT_SIZE, null);\n buf.append(decodedInformation.getNewString());\n return buf.toString();\n }\n }\n AI01392xDecoder.HEADER_SIZE = 5 + 1 + 2;\n AI01392xDecoder.LAST_DIGIT_SIZE = 2;\n\n class AI01393xDecoder extends AI01decoder {\n constructor(information) {\n super(information);\n }\n parseInformation() {\n if (this.getInformation().getSize() < AI01393xDecoder.HEADER_SIZE + AI01decoder.GTIN_SIZE) {\n throw new NotFoundException();\n }\n let buf = new StringBuilder();\n this.encodeCompressedGtin(buf, AI01393xDecoder.HEADER_SIZE);\n let lastAIdigit = this.getGeneralDecoder().extractNumericValueFromBitArray(AI01393xDecoder.HEADER_SIZE + AI01decoder.GTIN_SIZE, AI01393xDecoder.LAST_DIGIT_SIZE);\n buf.append('(393');\n buf.append(lastAIdigit);\n buf.append(')');\n let firstThreeDigits = this.getGeneralDecoder().extractNumericValueFromBitArray(AI01393xDecoder.HEADER_SIZE + AI01decoder.GTIN_SIZE + AI01393xDecoder.LAST_DIGIT_SIZE, AI01393xDecoder.FIRST_THREE_DIGITS_SIZE);\n if (firstThreeDigits / 100 == 0) {\n buf.append('0');\n }\n if (firstThreeDigits / 10 == 0) {\n buf.append('0');\n }\n buf.append(firstThreeDigits);\n let generalInformation = this.getGeneralDecoder().decodeGeneralPurposeField(AI01393xDecoder.HEADER_SIZE + AI01decoder.GTIN_SIZE + AI01393xDecoder.LAST_DIGIT_SIZE + AI01393xDecoder.FIRST_THREE_DIGITS_SIZE, null);\n buf.append(generalInformation.getNewString());\n return buf.toString();\n }\n }\n AI01393xDecoder.HEADER_SIZE = 5 + 1 + 2;\n AI01393xDecoder.LAST_DIGIT_SIZE = 2;\n AI01393xDecoder.FIRST_THREE_DIGITS_SIZE = 10;\n\n class AI013x0x1xDecoder extends AI01weightDecoder {\n constructor(information, firstAIdigits, dateCode) {\n super(information);\n this.dateCode = dateCode;\n this.firstAIdigits = firstAIdigits;\n }\n parseInformation() {\n if (this.getInformation().getSize() != AI013x0x1xDecoder.HEADER_SIZE + AI013x0x1xDecoder.GTIN_SIZE + AI013x0x1xDecoder.WEIGHT_SIZE + AI013x0x1xDecoder.DATE_SIZE) {\n throw new NotFoundException();\n }\n let buf = new StringBuilder();\n this.encodeCompressedGtin(buf, AI013x0x1xDecoder.HEADER_SIZE);\n this.encodeCompressedWeight(buf, AI013x0x1xDecoder.HEADER_SIZE + AI013x0x1xDecoder.GTIN_SIZE, AI013x0x1xDecoder.WEIGHT_SIZE);\n this.encodeCompressedDate(buf, AI013x0x1xDecoder.HEADER_SIZE + AI013x0x1xDecoder.GTIN_SIZE + AI013x0x1xDecoder.WEIGHT_SIZE);\n return buf.toString();\n }\n encodeCompressedDate(buf, currentPos) {\n let numericDate = this.getGeneralDecoder().extractNumericValueFromBitArray(currentPos, AI013x0x1xDecoder.DATE_SIZE);\n if (numericDate == 38400) {\n return;\n }\n buf.append('(');\n buf.append(this.dateCode);\n buf.append(')');\n let day = numericDate % 32;\n numericDate /= 32;\n let month = numericDate % 12 + 1;\n numericDate /= 12;\n let year = numericDate;\n if (year / 10 == 0) {\n buf.append('0');\n }\n buf.append(year);\n if (month / 10 == 0) {\n buf.append('0');\n }\n buf.append(month);\n if (day / 10 == 0) {\n buf.append('0');\n }\n buf.append(day);\n }\n addWeightCode(buf, weight) {\n buf.append('(');\n buf.append(this.firstAIdigits);\n buf.append(weight / 100000);\n buf.append(')');\n }\n checkWeight(weight) {\n return weight % 100000;\n }\n }\n AI013x0x1xDecoder.HEADER_SIZE = 7 + 1;\n AI013x0x1xDecoder.WEIGHT_SIZE = 20;\n AI013x0x1xDecoder.DATE_SIZE = 16;\n\n function createDecoder(information) {\n try {\n if (information.get(1)) {\n return new AI01AndOtherAIs(information);\n }\n if (!information.get(2)) {\n return new AnyAIDecoder(information);\n }\n let fourBitEncodationMethod = GeneralAppIdDecoder.extractNumericValueFromBitArray(information, 1, 4);\n switch (fourBitEncodationMethod) {\n case 4: return new AI013103decoder(information);\n case 5: return new AI01320xDecoder(information);\n }\n let fiveBitEncodationMethod = GeneralAppIdDecoder.extractNumericValueFromBitArray(information, 1, 5);\n switch (fiveBitEncodationMethod) {\n case 12: return new AI01392xDecoder(information);\n case 13: return new AI01393xDecoder(information);\n }\n let sevenBitEncodationMethod = GeneralAppIdDecoder.extractNumericValueFromBitArray(information, 1, 7);\n switch (sevenBitEncodationMethod) {\n case 56: return new AI013x0x1xDecoder(information, '310', '11');\n case 57: return new AI013x0x1xDecoder(information, '320', '11');\n case 58: return new AI013x0x1xDecoder(information, '310', '13');\n case 59: return new AI013x0x1xDecoder(information, '320', '13');\n case 60: return new AI013x0x1xDecoder(information, '310', '15');\n case 61: return new AI013x0x1xDecoder(information, '320', '15');\n case 62: return new AI013x0x1xDecoder(information, '310', '17');\n case 63: return new AI013x0x1xDecoder(information, '320', '17');\n }\n }\n catch (e) {\n console.log(e);\n throw new IllegalStateException('unknown decoder: ' + information);\n }\n }\n\n class ExpandedPair {\n constructor(leftChar, rightChar, finderPatter, mayBeLast) {\n this.leftchar = leftChar;\n this.rightchar = rightChar;\n this.finderpattern = finderPatter;\n this.maybeLast = mayBeLast;\n }\n mayBeLast() {\n return this.maybeLast;\n }\n getLeftChar() {\n return this.leftchar;\n }\n getRightChar() {\n return this.rightchar;\n }\n getFinderPattern() {\n return this.finderpattern;\n }\n mustBeLast() {\n return this.rightchar == null;\n }\n toString() {\n return '[ ' + this.leftchar + ', ' + this.rightchar + ' : ' + (this.finderpattern == null ? 'null' : this.finderpattern.getValue()) + ' ]';\n }\n static equals(o1, o2) {\n if (!(o1 instanceof ExpandedPair)) {\n return false;\n }\n return ExpandedPair.equalsOrNull(o1.leftchar, o2.leftchar) &&\n ExpandedPair.equalsOrNull(o1.rightchar, o2.rightchar) &&\n ExpandedPair.equalsOrNull(o1.finderpattern, o2.finderpattern);\n }\n static equalsOrNull(o1, o2) {\n return o1 === null ? o2 === null : ExpandedPair.equals(o1, o2);\n }\n hashCode() {\n // return ExpandedPair.hashNotNull(leftChar) ^ hashNotNull(rightChar) ^ hashNotNull(finderPattern);\n let value = this.leftchar.getValue() ^ this.rightchar.getValue() ^ this.finderpattern.getValue();\n return value;\n }\n }\n\n class ExpandedRow {\n constructor(pairs, rowNumber, wasReversed) {\n this.pairs = pairs;\n this.rowNumber = rowNumber;\n this.wasReversed = wasReversed;\n }\n getPairs() {\n return this.pairs;\n }\n getRowNumber() {\n return this.rowNumber;\n }\n isReversed() {\n return this.wasReversed;\n }\n // check implementation\n isEquivalent(otherPairs) {\n return this.checkEqualitity(this, otherPairs);\n }\n // @Override\n toString() {\n return '{ ' + this.pairs + ' }';\n }\n /**\n * Two rows are equal if they contain the same pairs in the same order.\n */\n // @Override\n // check implementation\n equals(o1, o2) {\n if (!(o1 instanceof ExpandedRow)) {\n return false;\n }\n return this.checkEqualitity(o1, o2) && o1.wasReversed === o2.wasReversed;\n }\n checkEqualitity(pair1, pair2) {\n if (!pair1 || !pair2)\n return;\n let result;\n pair1.forEach((e1, i) => {\n pair2.forEach(e2 => {\n if (e1.getLeftChar().getValue() === e2.getLeftChar().getValue() && e1.getRightChar().getValue() === e2.getRightChar().getValue() && e1.getFinderPatter().getValue() === e2.getFinderPatter().getValue()) {\n result = true;\n }\n });\n });\n return result;\n }\n }\n\n // import java.util.ArrayList;\n // import java.util.Iterator;\n // import java.util.List;\n // import java.util.Map;\n // import java.util.Collections;\n class RSSExpandedReader extends AbstractRSSReader {\n constructor(verbose) {\n super(...arguments);\n this.pairs = new Array(RSSExpandedReader.MAX_PAIRS);\n this.rows = new Array();\n this.startEnd = [2];\n this.verbose = (verbose === true);\n }\n decodeRow(rowNumber, row, hints) {\n // Rows can start with even pattern in case in prev rows there where odd number of patters.\n // So lets try twice\n // this.pairs.clear();\n this.pairs.length = 0;\n this.startFromEven = false;\n try {\n return RSSExpandedReader.constructResult(this.decodeRow2pairs(rowNumber, row));\n }\n catch (e) {\n // OK\n if (this.verbose) {\n console.log(e);\n }\n }\n this.pairs.length = 0;\n this.startFromEven = true;\n return RSSExpandedReader.constructResult(this.decodeRow2pairs(rowNumber, row));\n }\n reset() {\n this.pairs.length = 0;\n this.rows.length = 0;\n }\n // Not private for testing\n decodeRow2pairs(rowNumber, row) {\n let done = false;\n while (!done) {\n try {\n this.pairs.push(this.retrieveNextPair(row, this.pairs, rowNumber));\n }\n catch (error) {\n if (error instanceof NotFoundException) {\n if (!this.pairs.length) {\n throw new NotFoundException();\n }\n // exit this loop when retrieveNextPair() fails and throws\n done = true;\n }\n }\n }\n // TODO: verify sequence of finder patterns as in checkPairSequence()\n if (this.checkChecksum()) {\n return this.pairs;\n }\n let tryStackedDecode;\n if (this.rows.length) {\n tryStackedDecode = true;\n }\n else {\n tryStackedDecode = false;\n }\n // let tryStackedDecode = !this.rows.isEmpty();\n this.storeRow(rowNumber, false); // TODO: deal with reversed rows\n if (tryStackedDecode) {\n // When the image is 180-rotated, then rows are sorted in wrong direction.\n // Try twice with both the directions.\n let ps = this.checkRowsBoolean(false);\n if (ps != null) {\n return ps;\n }\n ps = this.checkRowsBoolean(true);\n if (ps != null) {\n return ps;\n }\n }\n throw new NotFoundException();\n }\n // Need to Verify\n checkRowsBoolean(reverse) {\n // Limit number of rows we are checking\n // We use recursive algorithm with pure complexity and don't want it to take forever\n // Stacked barcode can have up to 11 rows, so 25 seems reasonable enough\n if (this.rows.length > 25) {\n this.rows.length = 0; // We will never have a chance to get result, so clear it\n return null;\n }\n this.pairs.length = 0;\n if (reverse) {\n this.rows = this.rows.reverse();\n // Collections.reverse(this.rows);\n }\n let ps = null;\n try {\n ps = this.checkRows(new Array(), 0);\n }\n catch (e) {\n // OK\n if (this.verbose) {\n console.log(e);\n }\n }\n if (reverse) {\n this.rows = this.rows.reverse();\n // Collections.reverse(this.rows);\n }\n return ps;\n }\n // Try to construct a valid rows sequence\n // Recursion is used to implement backtracking\n checkRows(collectedRows, currentRow) {\n for (let i = currentRow; i < this.rows.length; i++) {\n let row = this.rows[i];\n this.pairs.length = 0;\n for (let collectedRow of collectedRows) {\n this.pairs.push(collectedRow.getPairs());\n }\n this.pairs.push(row.getPairs());\n if (!RSSExpandedReader.isValidSequence(this.pairs)) {\n continue;\n }\n if (this.checkChecksum()) {\n return this.pairs;\n }\n let rs = new Array(collectedRows);\n rs.push(row);\n try {\n // Recursion: try to add more rows\n return this.checkRows(rs, i + 1);\n }\n catch (e) {\n // We failed, try the next candidate\n if (this.verbose) {\n console.log(e);\n }\n }\n }\n throw new NotFoundException();\n }\n // Whether the pairs form a valid find pattern sequence,\n // either complete or a prefix\n static isValidSequence(pairs) {\n for (let sequence of RSSExpandedReader.FINDER_PATTERN_SEQUENCES) {\n if (pairs.length > sequence.length) {\n continue;\n }\n let stop = true;\n for (let j = 0; j < pairs.length; j++) {\n if (pairs[j].getFinderPattern().getValue() != sequence[j]) {\n stop = false;\n break;\n }\n }\n if (stop) {\n return true;\n }\n }\n return false;\n }\n storeRow(rowNumber, wasReversed) {\n // Discard if duplicate above or below; otherwise insert in order by row number.\n let insertPos = 0;\n let prevIsSame = false;\n let nextIsSame = false;\n while (insertPos < this.rows.length) {\n let erow = this.rows[insertPos];\n if (erow.getRowNumber() > rowNumber) {\n nextIsSame = erow.isEquivalent(this.pairs);\n break;\n }\n prevIsSame = erow.isEquivalent(this.pairs);\n insertPos++;\n }\n if (nextIsSame || prevIsSame) {\n return;\n }\n // When the row was partially decoded (e.g. 2 pairs found instead of 3),\n // it will prevent us from detecting the barcode.\n // Try to merge partial rows\n // Check whether the row is part of an allready detected row\n if (RSSExpandedReader.isPartialRow(this.pairs, this.rows)) {\n return;\n }\n this.rows.push(insertPos, new ExpandedRow(this.pairs, rowNumber, wasReversed));\n this.removePartialRows(this.pairs, this.rows);\n }\n // Remove all the rows that contains only specified pairs\n removePartialRows(pairs, rows) {\n // for (Iterator iterator = rows.iterator(); iterator.hasNext();) {\n // ExpandedRow r = iterator.next();\n // if (r.getPairs().size() == pairs.size()) {\n // continue;\n // }\n // boolean allFound = true;\n // for (ExpandedPair p : r.getPairs()) {\n // boolean found = false;\n // for (ExpandedPair pp : pairs) {\n // if (p.equals(pp)) {\n // found = true;\n // break;\n // }\n // }\n // if (!found) {\n // allFound = false;\n // break;\n // }\n // }\n // if (allFound) {\n // // 'pairs' contains all the pairs from the row 'r'\n // iterator.remove();\n // }\n // }\n for (let row of rows) {\n if (row.getPairs().length === pairs.length) {\n continue;\n }\n for (let p of row.getPairs()) {\n for (let pp of pairs) {\n if (ExpandedPair.equals(p, pp)) {\n break;\n }\n }\n }\n }\n }\n // Returns true when one of the rows already contains all the pairs\n static isPartialRow(pairs, rows) {\n for (let r of rows) {\n let allFound = true;\n for (let p of pairs) {\n let found = false;\n for (let pp of r.getPairs()) {\n if (p.equals(pp)) {\n found = true;\n break;\n }\n }\n if (!found) {\n allFound = false;\n break;\n }\n }\n if (allFound) {\n // the row 'r' contain all the pairs from 'pairs'\n return true;\n }\n }\n return false;\n }\n // Only used for unit testing\n getRows() {\n return this.rows;\n }\n // Not private for unit testing\n static constructResult(pairs) {\n let binary = BitArrayBuilder.buildBitArray(pairs);\n let decoder = createDecoder(binary);\n let resultingString = decoder.parseInformation();\n let firstPoints = pairs[0].getFinderPattern().getResultPoints();\n let lastPoints = pairs[pairs.length - 1].getFinderPattern().getResultPoints();\n let points = [firstPoints[0], firstPoints[1], lastPoints[0], lastPoints[1]];\n return new Result(resultingString, null, null, points, BarcodeFormat$1.RSS_EXPANDED, null);\n }\n checkChecksum() {\n let firstPair = this.pairs.get(0);\n let checkCharacter = firstPair.getLeftChar();\n let firstCharacter = firstPair.getRightChar();\n if (firstCharacter == null) {\n return false;\n }\n let checksum = firstCharacter.getChecksumPortion();\n let s = 2;\n for (let i = 1; i < this.pairs.size(); ++i) {\n let currentPair = this.pairs.get(i);\n checksum += currentPair.getLeftChar().getChecksumPortion();\n s++;\n let currentRightChar = currentPair.getRightChar();\n if (currentRightChar != null) {\n checksum += currentRightChar.getChecksumPortion();\n s++;\n }\n }\n checksum %= 211;\n let checkCharacterValue = 211 * (s - 4) + checksum;\n return checkCharacterValue == checkCharacter.getValue();\n }\n static getNextSecondBar(row, initialPos) {\n let currentPos;\n if (row.get(initialPos)) {\n currentPos = row.getNextUnset(initialPos);\n currentPos = row.getNextSet(currentPos);\n }\n else {\n currentPos = row.getNextSet(initialPos);\n currentPos = row.getNextUnset(currentPos);\n }\n return currentPos;\n }\n // not private for testing\n retrieveNextPair(row, previousPairs, rowNumber) {\n let isOddPattern = previousPairs.length % 2 == 0;\n if (this.startFromEven) {\n isOddPattern = !isOddPattern;\n }\n let pattern;\n let keepFinding = true;\n let forcedOffset = -1;\n do {\n this.findNextPair(row, previousPairs, forcedOffset);\n pattern = this.parseFoundFinderPattern(row, rowNumber, isOddPattern);\n if (pattern == null) {\n forcedOffset = RSSExpandedReader.getNextSecondBar(row, this.startEnd[0]);\n }\n else {\n keepFinding = false;\n }\n } while (keepFinding);\n // When stacked symbol is split over multiple rows, there's no way to guess if this pair can be last or not.\n // boolean mayBeLast = checkPairSequence(previousPairs, pattern);\n let leftChar = this.decodeDataCharacter(row, pattern, isOddPattern, true);\n if (!this.isEmptyPair(previousPairs) && previousPairs[previousPairs.length - 1].mustBeLast()) {\n throw new NotFoundException();\n }\n let rightChar;\n try {\n rightChar = this.decodeDataCharacter(row, pattern, isOddPattern, false);\n }\n catch (e) {\n rightChar = null;\n if (this.verbose) {\n console.log(e);\n }\n }\n return new ExpandedPair(leftChar, rightChar, pattern, true);\n }\n isEmptyPair(pairs) {\n if (pairs.length === 0) {\n return true;\n }\n return false;\n }\n findNextPair(row, previousPairs, forcedOffset) {\n let counters = this.getDecodeFinderCounters();\n counters[0] = 0;\n counters[1] = 0;\n counters[2] = 0;\n counters[3] = 0;\n let width = row.getSize();\n let rowOffset;\n if (forcedOffset >= 0) {\n rowOffset = forcedOffset;\n }\n else if (this.isEmptyPair(previousPairs)) {\n rowOffset = 0;\n }\n else {\n let lastPair = previousPairs[previousPairs.length - 1];\n rowOffset = lastPair.getFinderPattern().getStartEnd()[1];\n }\n let searchingEvenPair = previousPairs.length % 2 != 0;\n if (this.startFromEven) {\n searchingEvenPair = !searchingEvenPair;\n }\n let isWhite = false;\n while (rowOffset < width) {\n isWhite = !row.get(rowOffset);\n if (!isWhite) {\n break;\n }\n rowOffset++;\n }\n let counterPosition = 0;\n let patternStart = rowOffset;\n for (let x = rowOffset; x < width; x++) {\n if (row.get(x) != isWhite) {\n counters[counterPosition]++;\n }\n else {\n if (counterPosition == 3) {\n if (searchingEvenPair) {\n RSSExpandedReader.reverseCounters(counters);\n }\n if (RSSExpandedReader.isFinderPattern(counters)) {\n this.startEnd[0] = patternStart;\n this.startEnd[1] = x;\n return;\n }\n if (searchingEvenPair) {\n RSSExpandedReader.reverseCounters(counters);\n }\n patternStart += counters[0] + counters[1];\n counters[0] = counters[2];\n counters[1] = counters[3];\n counters[2] = 0;\n counters[3] = 0;\n counterPosition--;\n }\n else {\n counterPosition++;\n }\n counters[counterPosition] = 1;\n isWhite = !isWhite;\n }\n }\n throw new NotFoundException();\n }\n static reverseCounters(counters) {\n let length = counters.length;\n for (let i = 0; i < length / 2; ++i) {\n let tmp = counters[i];\n counters[i] = counters[length - i - 1];\n counters[length - i - 1] = tmp;\n }\n }\n parseFoundFinderPattern(row, rowNumber, oddPattern) {\n // Actually we found elements 2-5.\n let firstCounter;\n let start;\n let end;\n if (oddPattern) {\n // If pattern number is odd, we need to locate element 1 *before* the current block.\n let firstElementStart = this.startEnd[0] - 1;\n // Locate element 1\n while (firstElementStart >= 0 && !row.get(firstElementStart)) {\n firstElementStart--;\n }\n firstElementStart++;\n firstCounter = this.startEnd[0] - firstElementStart;\n start = firstElementStart;\n end = this.startEnd[1];\n }\n else {\n // If pattern number is even, the pattern is reversed, so we need to locate element 1 *after* the current block.\n start = this.startEnd[0];\n end = row.getNextUnset(this.startEnd[1] + 1);\n firstCounter = end - this.startEnd[1];\n }\n // Make 'counters' hold 1-4\n let counters = this.getDecodeFinderCounters();\n System.arraycopy(counters, 0, counters, 1, counters.length - 1);\n counters[0] = firstCounter;\n let value;\n try {\n value = this.parseFinderValue(counters, RSSExpandedReader.FINDER_PATTERNS);\n }\n catch (e) {\n return null;\n }\n // return new FinderPattern(value, new int[] { start, end }, start, end, rowNumber});\n return new FinderPattern(value, [start, end], start, end, rowNumber);\n }\n decodeDataCharacter(row, pattern, isOddPattern, leftChar) {\n let counters = this.getDataCharacterCounters();\n for (let x = 0; x < counters.length; x++) {\n counters[x] = 0;\n }\n if (leftChar) {\n RSSExpandedReader.recordPatternInReverse(row, pattern.getStartEnd()[0], counters);\n }\n else {\n RSSExpandedReader.recordPattern(row, pattern.getStartEnd()[1], counters);\n // reverse it\n for (let i = 0, j = counters.length - 1; i < j; i++, j--) {\n let temp = counters[i];\n counters[i] = counters[j];\n counters[j] = temp;\n }\n } // counters[] has the pixels of the module\n let numModules = 17; // left and right data characters have all the same length\n let elementWidth = MathUtils.sum(new Int32Array(counters)) / numModules;\n // Sanity check: element width for pattern and the character should match\n let expectedElementWidth = (pattern.getStartEnd()[1] - pattern.getStartEnd()[0]) / 15.0;\n if (Math.abs(elementWidth - expectedElementWidth) / expectedElementWidth > 0.3) {\n throw new NotFoundException();\n }\n let oddCounts = this.getOddCounts();\n let evenCounts = this.getEvenCounts();\n let oddRoundingErrors = this.getOddRoundingErrors();\n let evenRoundingErrors = this.getEvenRoundingErrors();\n for (let i = 0; i < counters.length; i++) {\n let value = 1.0 * counters[i] / elementWidth;\n let count = value + 0.5; // Round\n if (count < 1) {\n if (value < 0.3) {\n throw new NotFoundException();\n }\n count = 1;\n }\n else if (count > 8) {\n if (value > 8.7) {\n throw new NotFoundException();\n }\n count = 8;\n }\n let offset = i / 2;\n if ((i & 0x01) == 0) {\n oddCounts[offset] = count;\n oddRoundingErrors[offset] = value - count;\n }\n else {\n evenCounts[offset] = count;\n evenRoundingErrors[offset] = value - count;\n }\n }\n this.adjustOddEvenCounts(numModules);\n let weightRowNumber = 4 * pattern.getValue() + (isOddPattern ? 0 : 2) + (leftChar ? 0 : 1) - 1;\n let oddSum = 0;\n let oddChecksumPortion = 0;\n for (let i = oddCounts.length - 1; i >= 0; i--) {\n if (RSSExpandedReader.isNotA1left(pattern, isOddPattern, leftChar)) {\n let weight = RSSExpandedReader.WEIGHTS[weightRowNumber][2 * i];\n oddChecksumPortion += oddCounts[i] * weight;\n }\n oddSum += oddCounts[i];\n }\n let evenChecksumPortion = 0;\n // int evenSum = 0;\n for (let i = evenCounts.length - 1; i >= 0; i--) {\n if (RSSExpandedReader.isNotA1left(pattern, isOddPattern, leftChar)) {\n let weight = RSSExpandedReader.WEIGHTS[weightRowNumber][2 * i + 1];\n evenChecksumPortion += evenCounts[i] * weight;\n }\n // evenSum += evenCounts[i];\n }\n let checksumPortion = oddChecksumPortion + evenChecksumPortion;\n if ((oddSum & 0x01) != 0 || oddSum > 13 || oddSum < 4) {\n throw new NotFoundException();\n }\n let group = (13 - oddSum) / 2;\n let oddWidest = RSSExpandedReader.SYMBOL_WIDEST[group];\n let evenWidest = 9 - oddWidest;\n let vOdd = RSSUtils.getRSSvalue(oddCounts, oddWidest, true);\n let vEven = RSSUtils.getRSSvalue(evenCounts, evenWidest, false);\n let tEven = RSSExpandedReader.EVEN_TOTAL_SUBSET[group];\n let gSum = RSSExpandedReader.GSUM[group];\n let value = vOdd * tEven + vEven + gSum;\n return new DataCharacter(value, checksumPortion);\n }\n static isNotA1left(pattern, isOddPattern, leftChar) {\n // A1: pattern.getValue is 0 (A), and it's an oddPattern, and it is a left char\n return !(pattern.getValue() == 0 && isOddPattern && leftChar);\n }\n adjustOddEvenCounts(numModules) {\n let oddSum = MathUtils.sum(new Int32Array(this.getOddCounts()));\n let evenSum = MathUtils.sum(new Int32Array(this.getEvenCounts()));\n let incrementOdd = false;\n let decrementOdd = false;\n if (oddSum > 13) {\n decrementOdd = true;\n }\n else if (oddSum < 4) {\n incrementOdd = true;\n }\n let incrementEven = false;\n let decrementEven = false;\n if (evenSum > 13) {\n decrementEven = true;\n }\n else if (evenSum < 4) {\n incrementEven = true;\n }\n let mismatch = oddSum + evenSum - numModules;\n let oddParityBad = (oddSum & 0x01) == 1;\n let evenParityBad = (evenSum & 0x01) == 0;\n if (mismatch == 1) {\n if (oddParityBad) {\n if (evenParityBad) {\n throw new NotFoundException();\n }\n decrementOdd = true;\n }\n else {\n if (!evenParityBad) {\n throw new NotFoundException();\n }\n decrementEven = true;\n }\n }\n else if (mismatch == -1) {\n if (oddParityBad) {\n if (evenParityBad) {\n throw new NotFoundException();\n }\n incrementOdd = true;\n }\n else {\n if (!evenParityBad) {\n throw new NotFoundException();\n }\n incrementEven = true;\n }\n }\n else if (mismatch == 0) {\n if (oddParityBad) {\n if (!evenParityBad) {\n throw new NotFoundException();\n }\n // Both bad\n if (oddSum < evenSum) {\n incrementOdd = true;\n decrementEven = true;\n }\n else {\n decrementOdd = true;\n incrementEven = true;\n }\n }\n else {\n if (evenParityBad) {\n throw new NotFoundException();\n }\n // Nothing to do!\n }\n }\n else {\n throw new NotFoundException();\n }\n if (incrementOdd) {\n if (decrementOdd) {\n throw new NotFoundException();\n }\n RSSExpandedReader.increment(this.getOddCounts(), this.getOddRoundingErrors());\n }\n if (decrementOdd) {\n RSSExpandedReader.decrement(this.getOddCounts(), this.getOddRoundingErrors());\n }\n if (incrementEven) {\n if (decrementEven) {\n throw new NotFoundException();\n }\n RSSExpandedReader.increment(this.getEvenCounts(), this.getOddRoundingErrors());\n }\n if (decrementEven) {\n RSSExpandedReader.decrement(this.getEvenCounts(), this.getEvenRoundingErrors());\n }\n }\n }\n RSSExpandedReader.SYMBOL_WIDEST = [7, 5, 4, 3, 1];\n RSSExpandedReader.EVEN_TOTAL_SUBSET = [4, 20, 52, 104, 204];\n RSSExpandedReader.GSUM = [0, 348, 1388, 2948, 3988];\n RSSExpandedReader.FINDER_PATTERNS = [\n Int32Array.from([1, 8, 4, 1]),\n Int32Array.from([3, 6, 4, 1]),\n Int32Array.from([3, 4, 6, 1]),\n Int32Array.from([3, 2, 8, 1]),\n Int32Array.from([2, 6, 5, 1]),\n Int32Array.from([2, 2, 9, 1]) // F\n ];\n RSSExpandedReader.WEIGHTS = [\n [1, 3, 9, 27, 81, 32, 96, 77],\n [20, 60, 180, 118, 143, 7, 21, 63],\n [189, 145, 13, 39, 117, 140, 209, 205],\n [193, 157, 49, 147, 19, 57, 171, 91],\n [62, 186, 136, 197, 169, 85, 44, 132],\n [185, 133, 188, 142, 4, 12, 36, 108],\n [113, 128, 173, 97, 80, 29, 87, 50],\n [150, 28, 84, 41, 123, 158, 52, 156],\n [46, 138, 203, 187, 139, 206, 196, 166],\n [76, 17, 51, 153, 37, 111, 122, 155],\n [43, 129, 176, 106, 107, 110, 119, 146],\n [16, 48, 144, 10, 30, 90, 59, 177],\n [109, 116, 137, 200, 178, 112, 125, 164],\n [70, 210, 208, 202, 184, 130, 179, 115],\n [134, 191, 151, 31, 93, 68, 204, 190],\n [148, 22, 66, 198, 172, 94, 71, 2],\n [6, 18, 54, 162, 64, 192, 154, 40],\n [120, 149, 25, 75, 14, 42, 126, 167],\n [79, 26, 78, 23, 69, 207, 199, 175],\n [103, 98, 83, 38, 114, 131, 182, 124],\n [161, 61, 183, 127, 170, 88, 53, 159],\n [55, 165, 73, 8, 24, 72, 5, 15],\n [45, 135, 194, 160, 58, 174, 100, 89]\n ];\n RSSExpandedReader.FINDER_PAT_A = 0;\n RSSExpandedReader.FINDER_PAT_B = 1;\n RSSExpandedReader.FINDER_PAT_C = 2;\n RSSExpandedReader.FINDER_PAT_D = 3;\n RSSExpandedReader.FINDER_PAT_E = 4;\n RSSExpandedReader.FINDER_PAT_F = 5;\n RSSExpandedReader.FINDER_PATTERN_SEQUENCES = [\n [RSSExpandedReader.FINDER_PAT_A, RSSExpandedReader.FINDER_PAT_A],\n [RSSExpandedReader.FINDER_PAT_A, RSSExpandedReader.FINDER_PAT_B, RSSExpandedReader.FINDER_PAT_B],\n [RSSExpandedReader.FINDER_PAT_A, RSSExpandedReader.FINDER_PAT_C, RSSExpandedReader.FINDER_PAT_B, RSSExpandedReader.FINDER_PAT_D],\n [RSSExpandedReader.FINDER_PAT_A, RSSExpandedReader.FINDER_PAT_E, RSSExpandedReader.FINDER_PAT_B, RSSExpandedReader.FINDER_PAT_D, RSSExpandedReader.FINDER_PAT_C],\n [RSSExpandedReader.FINDER_PAT_A, RSSExpandedReader.FINDER_PAT_E, RSSExpandedReader.FINDER_PAT_B, RSSExpandedReader.FINDER_PAT_D, RSSExpandedReader.FINDER_PAT_D, RSSExpandedReader.FINDER_PAT_F],\n [RSSExpandedReader.FINDER_PAT_A, RSSExpandedReader.FINDER_PAT_E, RSSExpandedReader.FINDER_PAT_B, RSSExpandedReader.FINDER_PAT_D, RSSExpandedReader.FINDER_PAT_E, RSSExpandedReader.FINDER_PAT_F, RSSExpandedReader.FINDER_PAT_F],\n [RSSExpandedReader.FINDER_PAT_A, RSSExpandedReader.FINDER_PAT_A, RSSExpandedReader.FINDER_PAT_B, RSSExpandedReader.FINDER_PAT_B, RSSExpandedReader.FINDER_PAT_C, RSSExpandedReader.FINDER_PAT_C, RSSExpandedReader.FINDER_PAT_D, RSSExpandedReader.FINDER_PAT_D],\n [RSSExpandedReader.FINDER_PAT_A, RSSExpandedReader.FINDER_PAT_A, RSSExpandedReader.FINDER_PAT_B, RSSExpandedReader.FINDER_PAT_B, RSSExpandedReader.FINDER_PAT_C, RSSExpandedReader.FINDER_PAT_C, RSSExpandedReader.FINDER_PAT_D, RSSExpandedReader.FINDER_PAT_E, RSSExpandedReader.FINDER_PAT_E],\n [RSSExpandedReader.FINDER_PAT_A, RSSExpandedReader.FINDER_PAT_A, RSSExpandedReader.FINDER_PAT_B, RSSExpandedReader.FINDER_PAT_B, RSSExpandedReader.FINDER_PAT_C, RSSExpandedReader.FINDER_PAT_C, RSSExpandedReader.FINDER_PAT_D, RSSExpandedReader.FINDER_PAT_E, RSSExpandedReader.FINDER_PAT_F, RSSExpandedReader.FINDER_PAT_F],\n [RSSExpandedReader.FINDER_PAT_A, RSSExpandedReader.FINDER_PAT_A, RSSExpandedReader.FINDER_PAT_B, RSSExpandedReader.FINDER_PAT_B, RSSExpandedReader.FINDER_PAT_C, RSSExpandedReader.FINDER_PAT_D, RSSExpandedReader.FINDER_PAT_D, RSSExpandedReader.FINDER_PAT_E, RSSExpandedReader.FINDER_PAT_E, RSSExpandedReader.FINDER_PAT_F, RSSExpandedReader.FINDER_PAT_F],\n ];\n RSSExpandedReader.MAX_PAIRS = 11;\n\n class Pair extends DataCharacter {\n constructor(value, checksumPortion, finderPattern) {\n super(value, checksumPortion);\n this.count = 0;\n this.finderPattern = finderPattern;\n }\n getFinderPattern() {\n return this.finderPattern;\n }\n getCount() {\n return this.count;\n }\n incrementCount() {\n this.count++;\n }\n }\n\n class RSS14Reader extends AbstractRSSReader {\n constructor() {\n super(...arguments);\n this.possibleLeftPairs = [];\n this.possibleRightPairs = [];\n }\n decodeRow(rowNumber, row, hints) {\n const leftPair = this.decodePair(row, false, rowNumber, hints);\n RSS14Reader.addOrTally(this.possibleLeftPairs, leftPair);\n row.reverse();\n let rightPair = this.decodePair(row, true, rowNumber, hints);\n RSS14Reader.addOrTally(this.possibleRightPairs, rightPair);\n row.reverse();\n for (let left of this.possibleLeftPairs) {\n if (left.getCount() > 1) {\n for (let right of this.possibleRightPairs) {\n if (right.getCount() > 1 && RSS14Reader.checkChecksum(left, right)) {\n return RSS14Reader.constructResult(left, right);\n }\n }\n }\n }\n throw new NotFoundException();\n }\n static addOrTally(possiblePairs, pair) {\n if (pair == null) {\n return;\n }\n let found = false;\n for (let other of possiblePairs) {\n if (other.getValue() === pair.getValue()) {\n other.incrementCount();\n found = true;\n break;\n }\n }\n if (!found) {\n possiblePairs.push(pair);\n }\n }\n reset() {\n this.possibleLeftPairs.length = 0;\n this.possibleRightPairs.length = 0;\n }\n static constructResult(leftPair, rightPair) {\n let symbolValue = 4537077 * leftPair.getValue() + rightPair.getValue();\n let text = new String(symbolValue).toString();\n let buffer = new StringBuilder();\n for (let i = 13 - text.length; i > 0; i--) {\n buffer.append('0');\n }\n buffer.append(text);\n let checkDigit = 0;\n for (let i = 0; i < 13; i++) {\n let digit = buffer.charAt(i).charCodeAt(0) - '0'.charCodeAt(0);\n checkDigit += ((i & 0x01) === 0) ? 3 * digit : digit;\n }\n checkDigit = 10 - (checkDigit % 10);\n if (checkDigit === 10) {\n checkDigit = 0;\n }\n buffer.append(checkDigit.toString());\n let leftPoints = leftPair.getFinderPattern().getResultPoints();\n let rightPoints = rightPair.getFinderPattern().getResultPoints();\n return new Result(buffer.toString(), null, 0, [leftPoints[0], leftPoints[1], rightPoints[0], rightPoints[1]], BarcodeFormat$1.RSS_14, new Date().getTime());\n }\n static checkChecksum(leftPair, rightPair) {\n let checkValue = (leftPair.getChecksumPortion() + 16 * rightPair.getChecksumPortion()) % 79;\n let targetCheckValue = 9 * leftPair.getFinderPattern().getValue() + rightPair.getFinderPattern().getValue();\n if (targetCheckValue > 72) {\n targetCheckValue--;\n }\n if (targetCheckValue > 8) {\n targetCheckValue--;\n }\n return checkValue === targetCheckValue;\n }\n decodePair(row, right, rowNumber, hints) {\n try {\n let startEnd = this.findFinderPattern(row, right);\n let pattern = this.parseFoundFinderPattern(row, rowNumber, right, startEnd);\n let resultPointCallback = hints == null ? null : hints.get(DecodeHintType$1.NEED_RESULT_POINT_CALLBACK);\n if (resultPointCallback != null) {\n let center = (startEnd[0] + startEnd[1]) / 2.0;\n if (right) {\n // row is actually reversed\n center = row.getSize() - 1 - center;\n }\n resultPointCallback.foundPossibleResultPoint(new ResultPoint(center, rowNumber));\n }\n let outside = this.decodeDataCharacter(row, pattern, true);\n let inside = this.decodeDataCharacter(row, pattern, false);\n return new Pair(1597 * outside.getValue() + inside.getValue(), outside.getChecksumPortion() + 4 * inside.getChecksumPortion(), pattern);\n }\n catch (err) {\n return null;\n }\n }\n decodeDataCharacter(row, pattern, outsideChar) {\n let counters = this.getDataCharacterCounters();\n for (let x = 0; x < counters.length; x++) {\n counters[x] = 0;\n }\n if (outsideChar) {\n OneDReader.recordPatternInReverse(row, pattern.getStartEnd()[0], counters);\n }\n else {\n OneDReader.recordPattern(row, pattern.getStartEnd()[1] + 1, counters);\n // reverse it\n for (let i = 0, j = counters.length - 1; i < j; i++, j--) {\n let temp = counters[i];\n counters[i] = counters[j];\n counters[j] = temp;\n }\n }\n let numModules = outsideChar ? 16 : 15;\n let elementWidth = MathUtils.sum(new Int32Array(counters)) / numModules;\n let oddCounts = this.getOddCounts();\n let evenCounts = this.getEvenCounts();\n let oddRoundingErrors = this.getOddRoundingErrors();\n let evenRoundingErrors = this.getEvenRoundingErrors();\n for (let i = 0; i < counters.length; i++) {\n let value = counters[i] / elementWidth;\n let count = Math.floor(value + 0.5);\n if (count < 1) {\n count = 1;\n }\n else if (count > 8) {\n count = 8;\n }\n let offset = Math.floor(i / 2);\n if ((i & 0x01) === 0) {\n oddCounts[offset] = count;\n oddRoundingErrors[offset] = value - count;\n }\n else {\n evenCounts[offset] = count;\n evenRoundingErrors[offset] = value - count;\n }\n }\n this.adjustOddEvenCounts(outsideChar, numModules);\n let oddSum = 0;\n let oddChecksumPortion = 0;\n for (let i = oddCounts.length - 1; i >= 0; i--) {\n oddChecksumPortion *= 9;\n oddChecksumPortion += oddCounts[i];\n oddSum += oddCounts[i];\n }\n let evenChecksumPortion = 0;\n let evenSum = 0;\n for (let i = evenCounts.length - 1; i >= 0; i--) {\n evenChecksumPortion *= 9;\n evenChecksumPortion += evenCounts[i];\n evenSum += evenCounts[i];\n }\n let checksumPortion = oddChecksumPortion + 3 * evenChecksumPortion;\n if (outsideChar) {\n if ((oddSum & 0x01) !== 0 || oddSum > 12 || oddSum < 4) {\n throw new NotFoundException();\n }\n let group = (12 - oddSum) / 2;\n let oddWidest = RSS14Reader.OUTSIDE_ODD_WIDEST[group];\n let evenWidest = 9 - oddWidest;\n let vOdd = RSSUtils.getRSSvalue(oddCounts, oddWidest, false);\n let vEven = RSSUtils.getRSSvalue(evenCounts, evenWidest, true);\n let tEven = RSS14Reader.OUTSIDE_EVEN_TOTAL_SUBSET[group];\n let gSum = RSS14Reader.OUTSIDE_GSUM[group];\n return new DataCharacter(vOdd * tEven + vEven + gSum, checksumPortion);\n }\n else {\n if ((evenSum & 0x01) !== 0 || evenSum > 10 || evenSum < 4) {\n throw new NotFoundException();\n }\n let group = (10 - evenSum) / 2;\n let oddWidest = RSS14Reader.INSIDE_ODD_WIDEST[group];\n let evenWidest = 9 - oddWidest;\n let vOdd = RSSUtils.getRSSvalue(oddCounts, oddWidest, true);\n let vEven = RSSUtils.getRSSvalue(evenCounts, evenWidest, false);\n let tOdd = RSS14Reader.INSIDE_ODD_TOTAL_SUBSET[group];\n let gSum = RSS14Reader.INSIDE_GSUM[group];\n return new DataCharacter(vEven * tOdd + vOdd + gSum, checksumPortion);\n }\n }\n findFinderPattern(row, rightFinderPattern) {\n let counters = this.getDecodeFinderCounters();\n counters[0] = 0;\n counters[1] = 0;\n counters[2] = 0;\n counters[3] = 0;\n let width = row.getSize();\n let isWhite = false;\n let rowOffset = 0;\n while (rowOffset < width) {\n isWhite = !row.get(rowOffset);\n if (rightFinderPattern === isWhite) {\n // Will encounter white first when searching for right finder pattern\n break;\n }\n rowOffset++;\n }\n let counterPosition = 0;\n let patternStart = rowOffset;\n for (let x = rowOffset; x < width; x++) {\n if (row.get(x) !== isWhite) {\n counters[counterPosition]++;\n }\n else {\n if (counterPosition === 3) {\n if (AbstractRSSReader.isFinderPattern(counters)) {\n return [patternStart, x];\n }\n patternStart += counters[0] + counters[1];\n counters[0] = counters[2];\n counters[1] = counters[3];\n counters[2] = 0;\n counters[3] = 0;\n counterPosition--;\n }\n else {\n counterPosition++;\n }\n counters[counterPosition] = 1;\n isWhite = !isWhite;\n }\n }\n throw new NotFoundException();\n }\n parseFoundFinderPattern(row, rowNumber, right, startEnd) {\n // Actually we found elements 2-5\n let firstIsBlack = row.get(startEnd[0]);\n let firstElementStart = startEnd[0] - 1;\n // Locate element 1\n while (firstElementStart >= 0 && firstIsBlack !== row.get(firstElementStart)) {\n firstElementStart--;\n }\n firstElementStart++;\n const firstCounter = startEnd[0] - firstElementStart;\n // Make 'counters' hold 1-4\n const counters = this.getDecodeFinderCounters();\n const copy = new Int32Array(counters.length);\n System.arraycopy(counters, 0, copy, 1, counters.length - 1);\n copy[0] = firstCounter;\n const value = this.parseFinderValue(copy, RSS14Reader.FINDER_PATTERNS);\n let start = firstElementStart;\n let end = startEnd[1];\n if (right) {\n // row is actually reversed\n start = row.getSize() - 1 - start;\n end = row.getSize() - 1 - end;\n }\n return new FinderPattern(value, [firstElementStart, startEnd[1]], start, end, rowNumber);\n }\n adjustOddEvenCounts(outsideChar, numModules) {\n let oddSum = MathUtils.sum(new Int32Array(this.getOddCounts()));\n let evenSum = MathUtils.sum(new Int32Array(this.getEvenCounts()));\n let incrementOdd = false;\n let decrementOdd = false;\n let incrementEven = false;\n let decrementEven = false;\n if (outsideChar) {\n if (oddSum > 12) {\n decrementOdd = true;\n }\n else if (oddSum < 4) {\n incrementOdd = true;\n }\n if (evenSum > 12) {\n decrementEven = true;\n }\n else if (evenSum < 4) {\n incrementEven = true;\n }\n }\n else {\n if (oddSum > 11) {\n decrementOdd = true;\n }\n else if (oddSum < 5) {\n incrementOdd = true;\n }\n if (evenSum > 10) {\n decrementEven = true;\n }\n else if (evenSum < 4) {\n incrementEven = true;\n }\n }\n let mismatch = oddSum + evenSum - numModules;\n let oddParityBad = (oddSum & 0x01) === (outsideChar ? 1 : 0);\n let evenParityBad = (evenSum & 0x01) === 1;\n if (mismatch === 1) {\n if (oddParityBad) {\n if (evenParityBad) {\n throw new NotFoundException();\n }\n decrementOdd = true;\n }\n else {\n if (!evenParityBad) {\n throw new NotFoundException();\n }\n decrementEven = true;\n }\n }\n else if (mismatch === -1) {\n if (oddParityBad) {\n if (evenParityBad) {\n throw new NotFoundException();\n }\n incrementOdd = true;\n }\n else {\n if (!evenParityBad) {\n throw new NotFoundException();\n }\n incrementEven = true;\n }\n }\n else if (mismatch === 0) {\n if (oddParityBad) {\n if (!evenParityBad) {\n throw new NotFoundException();\n }\n // Both bad\n if (oddSum < evenSum) {\n incrementOdd = true;\n decrementEven = true;\n }\n else {\n decrementOdd = true;\n incrementEven = true;\n }\n }\n else {\n if (evenParityBad) {\n throw new NotFoundException();\n }\n // Nothing to do!\n }\n }\n else {\n throw new NotFoundException();\n }\n if (incrementOdd) {\n if (decrementOdd) {\n throw new NotFoundException();\n }\n AbstractRSSReader.increment(this.getOddCounts(), this.getOddRoundingErrors());\n }\n if (decrementOdd) {\n AbstractRSSReader.decrement(this.getOddCounts(), this.getOddRoundingErrors());\n }\n if (incrementEven) {\n if (decrementEven) {\n throw new NotFoundException();\n }\n AbstractRSSReader.increment(this.getEvenCounts(), this.getOddRoundingErrors());\n }\n if (decrementEven) {\n AbstractRSSReader.decrement(this.getEvenCounts(), this.getEvenRoundingErrors());\n }\n }\n }\n RSS14Reader.OUTSIDE_EVEN_TOTAL_SUBSET = [1, 10, 34, 70, 126];\n RSS14Reader.INSIDE_ODD_TOTAL_SUBSET = [4, 20, 48, 81];\n RSS14Reader.OUTSIDE_GSUM = [0, 161, 961, 2015, 2715];\n RSS14Reader.INSIDE_GSUM = [0, 336, 1036, 1516];\n RSS14Reader.OUTSIDE_ODD_WIDEST = [8, 6, 4, 3, 1];\n RSS14Reader.INSIDE_ODD_WIDEST = [2, 4, 6, 8];\n RSS14Reader.FINDER_PATTERNS = [\n Int32Array.from([3, 8, 2, 1]),\n Int32Array.from([3, 5, 5, 1]),\n Int32Array.from([3, 3, 7, 1]),\n Int32Array.from([3, 1, 9, 1]),\n Int32Array.from([2, 7, 4, 1]),\n Int32Array.from([2, 5, 6, 1]),\n Int32Array.from([2, 3, 8, 1]),\n Int32Array.from([1, 5, 7, 1]),\n Int32Array.from([1, 3, 9, 1]),\n ];\n\n /**\n * @author Daniel Switkin \n * @author Sean Owen\n */\n class MultiFormatOneDReader extends OneDReader {\n constructor(hints, verbose) {\n super();\n this.readers = [];\n this.verbose = (verbose === true);\n const possibleFormats = !hints ? null : hints.get(DecodeHintType$1.POSSIBLE_FORMATS);\n const useCode39CheckDigit = hints && hints.get(DecodeHintType$1.ASSUME_CODE_39_CHECK_DIGIT) !== undefined;\n if (possibleFormats) {\n if (possibleFormats.includes(BarcodeFormat$1.EAN_13) ||\n possibleFormats.includes(BarcodeFormat$1.UPC_A) ||\n possibleFormats.includes(BarcodeFormat$1.EAN_8) ||\n possibleFormats.includes(BarcodeFormat$1.UPC_E)) {\n this.readers.push(new MultiFormatUPCEANReader(hints));\n }\n if (possibleFormats.includes(BarcodeFormat$1.CODE_39)) {\n this.readers.push(new Code39Reader(useCode39CheckDigit));\n }\n // if (possibleFormats.includes(BarcodeFormat.CODE_93)) {\n // this.readers.push(new Code93Reader());\n // }\n if (possibleFormats.includes(BarcodeFormat$1.CODE_128)) {\n this.readers.push(new Code128Reader());\n }\n if (possibleFormats.includes(BarcodeFormat$1.ITF)) {\n this.readers.push(new ITFReader());\n }\n // if (possibleFormats.includes(BarcodeFormat.CODABAR)) {\n // this.readers.push(new CodaBarReader());\n // }\n if (possibleFormats.includes(BarcodeFormat$1.RSS_14)) {\n this.readers.push(new RSS14Reader());\n }\n if (possibleFormats.includes(BarcodeFormat$1.RSS_EXPANDED)) {\n this.readers.push(new RSSExpandedReader(this.verbose));\n }\n } else {\n // Case when no hints were provided -> add all.\n this.readers.push(new MultiFormatUPCEANReader(hints));\n this.readers.push(new Code39Reader());\n // this.readers.push(new CodaBarReader());\n // this.readers.push(new Code93Reader());\n this.readers.push(new MultiFormatUPCEANReader(hints));\n this.readers.push(new Code128Reader());\n this.readers.push(new ITFReader());\n this.readers.push(new RSS14Reader());\n this.readers.push(new RSSExpandedReader(this.verbose));\n }\n }\n // @Override\n decodeRow(rowNumber, row, hints) {\n for (let i = 0; i < this.readers.length; i++) {\n try {\n return this.readers[i].decodeRow(rowNumber, row, hints);\n }\n catch (re) {\n // continue\n }\n }\n throw new NotFoundException();\n }\n // @Override\n reset() {\n this.readers.forEach(reader => reader.reset());\n }\n }\n\n /**\n * @deprecated Moving to @zxing/browser\n *\n * Barcode reader reader to use from browser.\n */\n class BrowserBarcodeReader extends BrowserCodeReader {\n /**\n * Creates an instance of BrowserBarcodeReader.\n * @param {number} [timeBetweenScansMillis=500] the time delay between subsequent decode tries\n * @param {Map} hints\n */\n constructor(timeBetweenScansMillis = 500, hints) {\n super(new MultiFormatOneDReader(hints), timeBetweenScansMillis, hints);\n }\n }\n\n /*\n * Copyright 2007 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n /**\n *

Encapsulates a set of error-correction blocks in one symbol version. Most versions will\n * use blocks of differing sizes within one version, so, this encapsulates the parameters for\n * each set of blocks. It also holds the number of error-correction codewords per block since it\n * will be the same across all blocks within one version.

\n */\n class ECBlocks {\n constructor(ecCodewords, ecBlocks1, ecBlocks2) {\n this.ecCodewords = ecCodewords;\n this.ecBlocks = [ecBlocks1];\n ecBlocks2 && this.ecBlocks.push(ecBlocks2);\n }\n getECCodewords() {\n return this.ecCodewords;\n }\n getECBlocks() {\n return this.ecBlocks;\n }\n }\n /**\n *

Encapsulates the parameters for one error-correction block in one symbol version.\n * This includes the number of data codewords, and the number of times a block with these\n * parameters is used consecutively in the Data Matrix code version's format.

\n */\n class ECB {\n constructor(count, dataCodewords) {\n this.count = count;\n this.dataCodewords = dataCodewords;\n }\n getCount() {\n return this.count;\n }\n getDataCodewords() {\n return this.dataCodewords;\n }\n }\n /**\n * The Version object encapsulates attributes about a particular\n * size Data Matrix Code.\n *\n * @author bbrown@google.com (Brian Brown)\n */\n class Version {\n constructor(versionNumber, symbolSizeRows, symbolSizeColumns, dataRegionSizeRows, dataRegionSizeColumns, ecBlocks) {\n this.versionNumber = versionNumber;\n this.symbolSizeRows = symbolSizeRows;\n this.symbolSizeColumns = symbolSizeColumns;\n this.dataRegionSizeRows = dataRegionSizeRows;\n this.dataRegionSizeColumns = dataRegionSizeColumns;\n this.ecBlocks = ecBlocks;\n // Calculate the total number of codewords\n let total = 0;\n const ecCodewords = ecBlocks.getECCodewords();\n const ecbArray = ecBlocks.getECBlocks();\n for (let ecBlock of ecbArray) {\n total += ecBlock.getCount() * (ecBlock.getDataCodewords() + ecCodewords);\n }\n this.totalCodewords = total;\n }\n getVersionNumber() {\n return this.versionNumber;\n }\n getSymbolSizeRows() {\n return this.symbolSizeRows;\n }\n getSymbolSizeColumns() {\n return this.symbolSizeColumns;\n }\n getDataRegionSizeRows() {\n return this.dataRegionSizeRows;\n }\n getDataRegionSizeColumns() {\n return this.dataRegionSizeColumns;\n }\n getTotalCodewords() {\n return this.totalCodewords;\n }\n getECBlocks() {\n return this.ecBlocks;\n }\n /**\n *

Deduces version information from Data Matrix dimensions.

\n *\n * @param numRows Number of rows in modules\n * @param numColumns Number of columns in modules\n * @return Version for a Data Matrix Code of those dimensions\n * @throws FormatException if dimensions do correspond to a valid Data Matrix size\n */\n static getVersionForDimensions(numRows, numColumns) {\n if ((numRows & 0x01) !== 0 || (numColumns & 0x01) !== 0) {\n throw new FormatException();\n }\n for (let version of Version.VERSIONS) {\n if (version.symbolSizeRows === numRows && version.symbolSizeColumns === numColumns) {\n return version;\n }\n }\n throw new FormatException();\n }\n // @Override\n toString() {\n return '' + this.versionNumber;\n }\n /**\n * See ISO 16022:2006 5.5.1 Table 7\n */\n static buildVersions() {\n return [\n new Version(1, 10, 10, 8, 8, new ECBlocks(5, new ECB(1, 3))),\n new Version(2, 12, 12, 10, 10, new ECBlocks(7, new ECB(1, 5))),\n new Version(3, 14, 14, 12, 12, new ECBlocks(10, new ECB(1, 8))),\n new Version(4, 16, 16, 14, 14, new ECBlocks(12, new ECB(1, 12))),\n new Version(5, 18, 18, 16, 16, new ECBlocks(14, new ECB(1, 18))),\n new Version(6, 20, 20, 18, 18, new ECBlocks(18, new ECB(1, 22))),\n new Version(7, 22, 22, 20, 20, new ECBlocks(20, new ECB(1, 30))),\n new Version(8, 24, 24, 22, 22, new ECBlocks(24, new ECB(1, 36))),\n new Version(9, 26, 26, 24, 24, new ECBlocks(28, new ECB(1, 44))),\n new Version(10, 32, 32, 14, 14, new ECBlocks(36, new ECB(1, 62))),\n new Version(11, 36, 36, 16, 16, new ECBlocks(42, new ECB(1, 86))),\n new Version(12, 40, 40, 18, 18, new ECBlocks(48, new ECB(1, 114))),\n new Version(13, 44, 44, 20, 20, new ECBlocks(56, new ECB(1, 144))),\n new Version(14, 48, 48, 22, 22, new ECBlocks(68, new ECB(1, 174))),\n new Version(15, 52, 52, 24, 24, new ECBlocks(42, new ECB(2, 102))),\n new Version(16, 64, 64, 14, 14, new ECBlocks(56, new ECB(2, 140))),\n new Version(17, 72, 72, 16, 16, new ECBlocks(36, new ECB(4, 92))),\n new Version(18, 80, 80, 18, 18, new ECBlocks(48, new ECB(4, 114))),\n new Version(19, 88, 88, 20, 20, new ECBlocks(56, new ECB(4, 144))),\n new Version(20, 96, 96, 22, 22, new ECBlocks(68, new ECB(4, 174))),\n new Version(21, 104, 104, 24, 24, new ECBlocks(56, new ECB(6, 136))),\n new Version(22, 120, 120, 18, 18, new ECBlocks(68, new ECB(6, 175))),\n new Version(23, 132, 132, 20, 20, new ECBlocks(62, new ECB(8, 163))),\n new Version(24, 144, 144, 22, 22, new ECBlocks(62, new ECB(8, 156), new ECB(2, 155))),\n new Version(25, 8, 18, 6, 16, new ECBlocks(7, new ECB(1, 5))),\n new Version(26, 8, 32, 6, 14, new ECBlocks(11, new ECB(1, 10))),\n new Version(27, 12, 26, 10, 24, new ECBlocks(14, new ECB(1, 16))),\n new Version(28, 12, 36, 10, 16, new ECBlocks(18, new ECB(1, 22))),\n new Version(29, 16, 36, 14, 16, new ECBlocks(24, new ECB(1, 32))),\n new Version(30, 16, 48, 14, 22, new ECBlocks(28, new ECB(1, 49)))\n ];\n }\n }\n Version.VERSIONS = Version.buildVersions();\n\n /*\n * Copyright 2007 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n /**\n * @author bbrown@google.com (Brian Brown)\n */\n class BitMatrixParser {\n /**\n * @param bitMatrix {@link BitMatrix} to parse\n * @throws FormatException if dimension is < 8 or > 144 or not 0 mod 2\n */\n constructor(bitMatrix) {\n const dimension = bitMatrix.getHeight();\n if (dimension < 8 || dimension > 144 || (dimension & 0x01) !== 0) {\n throw new FormatException();\n }\n this.version = BitMatrixParser.readVersion(bitMatrix);\n this.mappingBitMatrix = this.extractDataRegion(bitMatrix);\n this.readMappingMatrix = new BitMatrix(this.mappingBitMatrix.getWidth(), this.mappingBitMatrix.getHeight());\n }\n getVersion() {\n return this.version;\n }\n /**\n *

Creates the version object based on the dimension of the original bit matrix from\n * the datamatrix code.

\n *\n *

See ISO 16022:2006 Table 7 - ECC 200 symbol attributes

\n *\n * @param bitMatrix Original {@link BitMatrix} including alignment patterns\n * @return {@link Version} encapsulating the Data Matrix Code's \"version\"\n * @throws FormatException if the dimensions of the mapping matrix are not valid\n * Data Matrix dimensions.\n */\n static readVersion(bitMatrix) {\n const numRows = bitMatrix.getHeight();\n const numColumns = bitMatrix.getWidth();\n return Version.getVersionForDimensions(numRows, numColumns);\n }\n /**\n *

Reads the bits in the {@link BitMatrix} representing the mapping matrix (No alignment patterns)\n * in the correct order in order to reconstitute the codewords bytes contained within the\n * Data Matrix Code.

\n *\n * @return bytes encoded within the Data Matrix Code\n * @throws FormatException if the exact number of bytes expected is not read\n */\n readCodewords() {\n const result = new Int8Array(this.version.getTotalCodewords());\n let resultOffset = 0;\n let row = 4;\n let column = 0;\n const numRows = this.mappingBitMatrix.getHeight();\n const numColumns = this.mappingBitMatrix.getWidth();\n let corner1Read = false;\n let corner2Read = false;\n let corner3Read = false;\n let corner4Read = false;\n // Read all of the codewords\n do {\n // Check the four corner cases\n if ((row === numRows) && (column === 0) && !corner1Read) {\n result[resultOffset++] = this.readCorner1(numRows, numColumns) & 0xff;\n row -= 2;\n column += 2;\n corner1Read = true;\n }\n else if ((row === numRows - 2) && (column === 0) && ((numColumns & 0x03) !== 0) && !corner2Read) {\n result[resultOffset++] = this.readCorner2(numRows, numColumns) & 0xff;\n row -= 2;\n column += 2;\n corner2Read = true;\n }\n else if ((row === numRows + 4) && (column === 2) && ((numColumns & 0x07) === 0) && !corner3Read) {\n result[resultOffset++] = this.readCorner3(numRows, numColumns) & 0xff;\n row -= 2;\n column += 2;\n corner3Read = true;\n }\n else if ((row === numRows - 2) && (column === 0) && ((numColumns & 0x07) === 4) && !corner4Read) {\n result[resultOffset++] = this.readCorner4(numRows, numColumns) & 0xff;\n row -= 2;\n column += 2;\n corner4Read = true;\n }\n else {\n // Sweep upward diagonally to the right\n do {\n if ((row < numRows) && (column >= 0) && !this.readMappingMatrix.get(column, row)) {\n result[resultOffset++] = this.readUtah(row, column, numRows, numColumns) & 0xff;\n }\n row -= 2;\n column += 2;\n } while ((row >= 0) && (column < numColumns));\n row += 1;\n column += 3;\n // Sweep downward diagonally to the left\n do {\n if ((row >= 0) && (column < numColumns) && !this.readMappingMatrix.get(column, row)) {\n result[resultOffset++] = this.readUtah(row, column, numRows, numColumns) & 0xff;\n }\n row += 2;\n column -= 2;\n } while ((row < numRows) && (column >= 0));\n row += 3;\n column += 1;\n }\n } while ((row < numRows) || (column < numColumns));\n if (resultOffset !== this.version.getTotalCodewords()) {\n throw new FormatException();\n }\n return result;\n }\n /**\n *

Reads a bit of the mapping matrix accounting for boundary wrapping.

\n *\n * @param row Row to read in the mapping matrix\n * @param column Column to read in the mapping matrix\n * @param numRows Number of rows in the mapping matrix\n * @param numColumns Number of columns in the mapping matrix\n * @return value of the given bit in the mapping matrix\n */\n readModule(row, column, numRows, numColumns) {\n // Adjust the row and column indices based on boundary wrapping\n if (row < 0) {\n row += numRows;\n column += 4 - ((numRows + 4) & 0x07);\n }\n if (column < 0) {\n column += numColumns;\n row += 4 - ((numColumns + 4) & 0x07);\n }\n this.readMappingMatrix.set(column, row);\n return this.mappingBitMatrix.get(column, row);\n }\n /**\n *

Reads the 8 bits of the standard Utah-shaped pattern.

\n *\n *

See ISO 16022:2006, 5.8.1 Figure 6

\n *\n * @param row Current row in the mapping matrix, anchored at the 8th bit (LSB) of the pattern\n * @param column Current column in the mapping matrix, anchored at the 8th bit (LSB) of the pattern\n * @param numRows Number of rows in the mapping matrix\n * @param numColumns Number of columns in the mapping matrix\n * @return byte from the utah shape\n */\n readUtah(row, column, numRows, numColumns) {\n let currentByte = 0;\n if (this.readModule(row - 2, column - 2, numRows, numColumns)) {\n currentByte |= 1;\n }\n currentByte <<= 1;\n if (this.readModule(row - 2, column - 1, numRows, numColumns)) {\n currentByte |= 1;\n }\n currentByte <<= 1;\n if (this.readModule(row - 1, column - 2, numRows, numColumns)) {\n currentByte |= 1;\n }\n currentByte <<= 1;\n if (this.readModule(row - 1, column - 1, numRows, numColumns)) {\n currentByte |= 1;\n }\n currentByte <<= 1;\n if (this.readModule(row - 1, column, numRows, numColumns)) {\n currentByte |= 1;\n }\n currentByte <<= 1;\n if (this.readModule(row, column - 2, numRows, numColumns)) {\n currentByte |= 1;\n }\n currentByte <<= 1;\n if (this.readModule(row, column - 1, numRows, numColumns)) {\n currentByte |= 1;\n }\n currentByte <<= 1;\n if (this.readModule(row, column, numRows, numColumns)) {\n currentByte |= 1;\n }\n return currentByte;\n }\n /**\n *

Reads the 8 bits of the special corner condition 1.

\n *\n *

See ISO 16022:2006, Figure F.3

\n *\n * @param numRows Number of rows in the mapping matrix\n * @param numColumns Number of columns in the mapping matrix\n * @return byte from the Corner condition 1\n */\n readCorner1(numRows, numColumns) {\n let currentByte = 0;\n if (this.readModule(numRows - 1, 0, numRows, numColumns)) {\n currentByte |= 1;\n }\n currentByte <<= 1;\n if (this.readModule(numRows - 1, 1, numRows, numColumns)) {\n currentByte |= 1;\n }\n currentByte <<= 1;\n if (this.readModule(numRows - 1, 2, numRows, numColumns)) {\n currentByte |= 1;\n }\n currentByte <<= 1;\n if (this.readModule(0, numColumns - 2, numRows, numColumns)) {\n currentByte |= 1;\n }\n currentByte <<= 1;\n if (this.readModule(0, numColumns - 1, numRows, numColumns)) {\n currentByte |= 1;\n }\n currentByte <<= 1;\n if (this.readModule(1, numColumns - 1, numRows, numColumns)) {\n currentByte |= 1;\n }\n currentByte <<= 1;\n if (this.readModule(2, numColumns - 1, numRows, numColumns)) {\n currentByte |= 1;\n }\n currentByte <<= 1;\n if (this.readModule(3, numColumns - 1, numRows, numColumns)) {\n currentByte |= 1;\n }\n return currentByte;\n }\n /**\n *

Reads the 8 bits of the special corner condition 2.

\n *\n *

See ISO 16022:2006, Figure F.4

\n *\n * @param numRows Number of rows in the mapping matrix\n * @param numColumns Number of columns in the mapping matrix\n * @return byte from the Corner condition 2\n */\n readCorner2(numRows, numColumns) {\n let currentByte = 0;\n if (this.readModule(numRows - 3, 0, numRows, numColumns)) {\n currentByte |= 1;\n }\n currentByte <<= 1;\n if (this.readModule(numRows - 2, 0, numRows, numColumns)) {\n currentByte |= 1;\n }\n currentByte <<= 1;\n if (this.readModule(numRows - 1, 0, numRows, numColumns)) {\n currentByte |= 1;\n }\n currentByte <<= 1;\n if (this.readModule(0, numColumns - 4, numRows, numColumns)) {\n currentByte |= 1;\n }\n currentByte <<= 1;\n if (this.readModule(0, numColumns - 3, numRows, numColumns)) {\n currentByte |= 1;\n }\n currentByte <<= 1;\n if (this.readModule(0, numColumns - 2, numRows, numColumns)) {\n currentByte |= 1;\n }\n currentByte <<= 1;\n if (this.readModule(0, numColumns - 1, numRows, numColumns)) {\n currentByte |= 1;\n }\n currentByte <<= 1;\n if (this.readModule(1, numColumns - 1, numRows, numColumns)) {\n currentByte |= 1;\n }\n return currentByte;\n }\n /**\n *

Reads the 8 bits of the special corner condition 3.

\n *\n *

See ISO 16022:2006, Figure F.5

\n *\n * @param numRows Number of rows in the mapping matrix\n * @param numColumns Number of columns in the mapping matrix\n * @return byte from the Corner condition 3\n */\n readCorner3(numRows, numColumns) {\n let currentByte = 0;\n if (this.readModule(numRows - 1, 0, numRows, numColumns)) {\n currentByte |= 1;\n }\n currentByte <<= 1;\n if (this.readModule(numRows - 1, numColumns - 1, numRows, numColumns)) {\n currentByte |= 1;\n }\n currentByte <<= 1;\n if (this.readModule(0, numColumns - 3, numRows, numColumns)) {\n currentByte |= 1;\n }\n currentByte <<= 1;\n if (this.readModule(0, numColumns - 2, numRows, numColumns)) {\n currentByte |= 1;\n }\n currentByte <<= 1;\n if (this.readModule(0, numColumns - 1, numRows, numColumns)) {\n currentByte |= 1;\n }\n currentByte <<= 1;\n if (this.readModule(1, numColumns - 3, numRows, numColumns)) {\n currentByte |= 1;\n }\n currentByte <<= 1;\n if (this.readModule(1, numColumns - 2, numRows, numColumns)) {\n currentByte |= 1;\n }\n currentByte <<= 1;\n if (this.readModule(1, numColumns - 1, numRows, numColumns)) {\n currentByte |= 1;\n }\n return currentByte;\n }\n /**\n *

Reads the 8 bits of the special corner condition 4.

\n *\n *

See ISO 16022:2006, Figure F.6

\n *\n * @param numRows Number of rows in the mapping matrix\n * @param numColumns Number of columns in the mapping matrix\n * @return byte from the Corner condition 4\n */\n readCorner4(numRows, numColumns) {\n let currentByte = 0;\n if (this.readModule(numRows - 3, 0, numRows, numColumns)) {\n currentByte |= 1;\n }\n currentByte <<= 1;\n if (this.readModule(numRows - 2, 0, numRows, numColumns)) {\n currentByte |= 1;\n }\n currentByte <<= 1;\n if (this.readModule(numRows - 1, 0, numRows, numColumns)) {\n currentByte |= 1;\n }\n currentByte <<= 1;\n if (this.readModule(0, numColumns - 2, numRows, numColumns)) {\n currentByte |= 1;\n }\n currentByte <<= 1;\n if (this.readModule(0, numColumns - 1, numRows, numColumns)) {\n currentByte |= 1;\n }\n currentByte <<= 1;\n if (this.readModule(1, numColumns - 1, numRows, numColumns)) {\n currentByte |= 1;\n }\n currentByte <<= 1;\n if (this.readModule(2, numColumns - 1, numRows, numColumns)) {\n currentByte |= 1;\n }\n currentByte <<= 1;\n if (this.readModule(3, numColumns - 1, numRows, numColumns)) {\n currentByte |= 1;\n }\n return currentByte;\n }\n /**\n *

Extracts the data region from a {@link BitMatrix} that contains\n * alignment patterns.

\n *\n * @param bitMatrix Original {@link BitMatrix} with alignment patterns\n * @return BitMatrix that has the alignment patterns removed\n */\n extractDataRegion(bitMatrix) {\n const symbolSizeRows = this.version.getSymbolSizeRows();\n const symbolSizeColumns = this.version.getSymbolSizeColumns();\n if (bitMatrix.getHeight() !== symbolSizeRows) {\n throw new IllegalArgumentException('Dimension of bitMatrix must match the version size');\n }\n const dataRegionSizeRows = this.version.getDataRegionSizeRows();\n const dataRegionSizeColumns = this.version.getDataRegionSizeColumns();\n const numDataRegionsRow = symbolSizeRows / dataRegionSizeRows | 0;\n const numDataRegionsColumn = symbolSizeColumns / dataRegionSizeColumns | 0;\n const sizeDataRegionRow = numDataRegionsRow * dataRegionSizeRows;\n const sizeDataRegionColumn = numDataRegionsColumn * dataRegionSizeColumns;\n const bitMatrixWithoutAlignment = new BitMatrix(sizeDataRegionColumn, sizeDataRegionRow);\n for (let dataRegionRow = 0; dataRegionRow < numDataRegionsRow; ++dataRegionRow) {\n const dataRegionRowOffset = dataRegionRow * dataRegionSizeRows;\n for (let dataRegionColumn = 0; dataRegionColumn < numDataRegionsColumn; ++dataRegionColumn) {\n const dataRegionColumnOffset = dataRegionColumn * dataRegionSizeColumns;\n for (let i = 0; i < dataRegionSizeRows; ++i) {\n const readRowOffset = dataRegionRow * (dataRegionSizeRows + 2) + 1 + i;\n const writeRowOffset = dataRegionRowOffset + i;\n for (let j = 0; j < dataRegionSizeColumns; ++j) {\n const readColumnOffset = dataRegionColumn * (dataRegionSizeColumns + 2) + 1 + j;\n if (bitMatrix.get(readColumnOffset, readRowOffset)) {\n const writeColumnOffset = dataRegionColumnOffset + j;\n bitMatrixWithoutAlignment.set(writeColumnOffset, writeRowOffset);\n }\n }\n }\n }\n }\n return bitMatrixWithoutAlignment;\n }\n }\n\n /**\n *

Encapsulates a block of data within a Data Matrix Code. Data Matrix Codes may split their data into\n * multiple blocks, each of which is a unit of data and error-correction codewords. Each\n * is represented by an instance of this class.

\n *\n * @author bbrown@google.com (Brian Brown)\n */\n class DataBlock {\n constructor(numDataCodewords, codewords) {\n this.numDataCodewords = numDataCodewords;\n this.codewords = codewords;\n }\n /**\n *

When Data Matrix Codes use multiple data blocks, they actually interleave the bytes of each of them.\n * That is, the first byte of data block 1 to n is written, then the second bytes, and so on. This\n * method will separate the data into original blocks.

\n *\n * @param rawCodewords bytes as read directly from the Data Matrix Code\n * @param version version of the Data Matrix Code\n * @return DataBlocks containing original bytes, \"de-interleaved\" from representation in the\n * Data Matrix Code\n */\n static getDataBlocks(rawCodewords, version) {\n // Figure out the number and size of data blocks used by this version\n const ecBlocks = version.getECBlocks();\n // First count the total number of data blocks\n let totalBlocks = 0;\n const ecBlockArray = ecBlocks.getECBlocks();\n for (let ecBlock of ecBlockArray) {\n totalBlocks += ecBlock.getCount();\n }\n // Now establish DataBlocks of the appropriate size and number of data codewords\n const result = new Array(totalBlocks);\n let numResultBlocks = 0;\n for (let ecBlock of ecBlockArray) {\n for (let i = 0; i < ecBlock.getCount(); i++) {\n const numDataCodewords = ecBlock.getDataCodewords();\n const numBlockCodewords = ecBlocks.getECCodewords() + numDataCodewords;\n result[numResultBlocks++] = new DataBlock(numDataCodewords, new Uint8Array(numBlockCodewords));\n }\n }\n // All blocks have the same amount of data, except that the last n\n // (where n may be 0) have 1 less byte. Figure out where these start.\n // TODO(bbrown): There is only one case where there is a difference for Data Matrix for size 144\n const longerBlocksTotalCodewords = result[0].codewords.length;\n // int shorterBlocksTotalCodewords = longerBlocksTotalCodewords - 1;\n const longerBlocksNumDataCodewords = longerBlocksTotalCodewords - ecBlocks.getECCodewords();\n const shorterBlocksNumDataCodewords = longerBlocksNumDataCodewords - 1;\n // The last elements of result may be 1 element shorter for 144 matrix\n // first fill out as many elements as all of them have minus 1\n let rawCodewordsOffset = 0;\n for (let i = 0; i < shorterBlocksNumDataCodewords; i++) {\n for (let j = 0; j < numResultBlocks; j++) {\n result[j].codewords[i] = rawCodewords[rawCodewordsOffset++];\n }\n }\n // Fill out the last data block in the longer ones\n const specialVersion = version.getVersionNumber() === 24;\n const numLongerBlocks = specialVersion ? 8 : numResultBlocks;\n for (let j = 0; j < numLongerBlocks; j++) {\n result[j].codewords[longerBlocksNumDataCodewords - 1] = rawCodewords[rawCodewordsOffset++];\n }\n // Now add in error correction blocks\n const max = result[0].codewords.length;\n for (let i = longerBlocksNumDataCodewords; i < max; i++) {\n for (let j = 0; j < numResultBlocks; j++) {\n const jOffset = specialVersion ? (j + 8) % numResultBlocks : j;\n const iOffset = specialVersion && jOffset > 7 ? i - 1 : i;\n result[jOffset].codewords[iOffset] = rawCodewords[rawCodewordsOffset++];\n }\n }\n if (rawCodewordsOffset !== rawCodewords.length) {\n throw new IllegalArgumentException();\n }\n return result;\n }\n getNumDataCodewords() {\n return this.numDataCodewords;\n }\n getCodewords() {\n return this.codewords;\n }\n }\n\n /*\n * Copyright 2007 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n /**\n *

This provides an easy abstraction to read bits at a time from a sequence of bytes, where the\n * number of bits read is not often a multiple of 8.

\n *\n *

This class is thread-safe but not reentrant -- unless the caller modifies the bytes array\n * it passed in, in which case all bets are off.

\n *\n * @author Sean Owen\n */\n class BitSource {\n /**\n * @param bytes bytes from which this will read bits. Bits will be read from the first byte first.\n * Bits are read within a byte from most-significant to least-significant bit.\n */\n constructor(bytes) {\n this.bytes = bytes;\n this.byteOffset = 0;\n this.bitOffset = 0;\n }\n /**\n * @return index of next bit in current byte which would be read by the next call to {@link #readBits(int)}.\n */\n getBitOffset() {\n return this.bitOffset;\n }\n /**\n * @return index of next byte in input byte array which would be read by the next call to {@link #readBits(int)}.\n */\n getByteOffset() {\n return this.byteOffset;\n }\n /**\n * @param numBits number of bits to read\n * @return int representing the bits read. The bits will appear as the least-significant\n * bits of the int\n * @throws IllegalArgumentException if numBits isn't in [1,32] or more than is available\n */\n readBits(numBits /*int*/) {\n if (numBits < 1 || numBits > 32 || numBits > this.available()) {\n throw new IllegalArgumentException('' + numBits);\n }\n let result = 0;\n let bitOffset = this.bitOffset;\n let byteOffset = this.byteOffset;\n const bytes = this.bytes;\n // First, read remainder from current byte\n if (bitOffset > 0) {\n const bitsLeft = 8 - bitOffset;\n const toRead = numBits < bitsLeft ? numBits : bitsLeft;\n const bitsToNotRead = bitsLeft - toRead;\n const mask = (0xFF >> (8 - toRead)) << bitsToNotRead;\n result = (bytes[byteOffset] & mask) >> bitsToNotRead;\n numBits -= toRead;\n bitOffset += toRead;\n if (bitOffset === 8) {\n bitOffset = 0;\n byteOffset++;\n }\n }\n // Next read whole bytes\n if (numBits > 0) {\n while (numBits >= 8) {\n result = (result << 8) | (bytes[byteOffset] & 0xFF);\n byteOffset++;\n numBits -= 8;\n }\n // Finally read a partial byte\n if (numBits > 0) {\n const bitsToNotRead = 8 - numBits;\n const mask = (0xFF >> bitsToNotRead) << bitsToNotRead;\n result = (result << numBits) | ((bytes[byteOffset] & mask) >> bitsToNotRead);\n bitOffset += numBits;\n }\n }\n this.bitOffset = bitOffset;\n this.byteOffset = byteOffset;\n return result;\n }\n /**\n * @return number of bits that can be read successfully\n */\n available() {\n return 8 * (this.bytes.length - this.byteOffset) - this.bitOffset;\n }\n }\n\n var Mode;\n (function (Mode) {\n Mode[Mode[\"PAD_ENCODE\"] = 0] = \"PAD_ENCODE\";\n Mode[Mode[\"ASCII_ENCODE\"] = 1] = \"ASCII_ENCODE\";\n Mode[Mode[\"C40_ENCODE\"] = 2] = \"C40_ENCODE\";\n Mode[Mode[\"TEXT_ENCODE\"] = 3] = \"TEXT_ENCODE\";\n Mode[Mode[\"ANSIX12_ENCODE\"] = 4] = \"ANSIX12_ENCODE\";\n Mode[Mode[\"EDIFACT_ENCODE\"] = 5] = \"EDIFACT_ENCODE\";\n Mode[Mode[\"BASE256_ENCODE\"] = 6] = \"BASE256_ENCODE\";\n })(Mode || (Mode = {}));\n /**\n *

Data Matrix Codes can encode text as bits in one of several modes, and can use multiple modes\n * in one Data Matrix Code. This class decodes the bits back into text.

\n *\n *

See ISO 16022:2006, 5.2.1 - 5.2.9.2

\n *\n * @author bbrown@google.com (Brian Brown)\n * @author Sean Owen\n */\n class DecodedBitStreamParser {\n static decode(bytes) {\n const bits = new BitSource(bytes);\n const result = new StringBuilder();\n const resultTrailer = new StringBuilder();\n const byteSegments = new Array();\n let mode = Mode.ASCII_ENCODE;\n do {\n if (mode === Mode.ASCII_ENCODE) {\n mode = this.decodeAsciiSegment(bits, result, resultTrailer);\n }\n else {\n switch (mode) {\n case Mode.C40_ENCODE:\n this.decodeC40Segment(bits, result);\n break;\n case Mode.TEXT_ENCODE:\n this.decodeTextSegment(bits, result);\n break;\n case Mode.ANSIX12_ENCODE:\n this.decodeAnsiX12Segment(bits, result);\n break;\n case Mode.EDIFACT_ENCODE:\n this.decodeEdifactSegment(bits, result);\n break;\n case Mode.BASE256_ENCODE:\n this.decodeBase256Segment(bits, result, byteSegments);\n break;\n default:\n throw new FormatException();\n }\n mode = Mode.ASCII_ENCODE;\n }\n } while (mode !== Mode.PAD_ENCODE && bits.available() > 0);\n if (resultTrailer.length() > 0) {\n result.append(resultTrailer.toString());\n }\n return new DecoderResult(bytes, result.toString(), byteSegments.length === 0 ? null : byteSegments, null);\n }\n /**\n * See ISO 16022:2006, 5.2.3 and Annex C, Table C.2\n */\n static decodeAsciiSegment(bits, result, resultTrailer) {\n let upperShift = false;\n do {\n let oneByte = bits.readBits(8);\n if (oneByte === 0) {\n throw new FormatException();\n }\n else if (oneByte <= 128) { // ASCII data (ASCII value + 1)\n if (upperShift) {\n oneByte += 128;\n // upperShift = false;\n }\n result.append(String.fromCharCode(oneByte - 1));\n return Mode.ASCII_ENCODE;\n }\n else if (oneByte === 129) { // Pad\n return Mode.PAD_ENCODE;\n }\n else if (oneByte <= 229) { // 2-digit data 00-99 (Numeric Value + 130)\n const value = oneByte - 130;\n if (value < 10) { // pad with '0' for single digit values\n result.append('0');\n }\n result.append('' + value);\n }\n else {\n switch (oneByte) {\n case 230: // Latch to C40 encodation\n return Mode.C40_ENCODE;\n case 231: // Latch to Base 256 encodation\n return Mode.BASE256_ENCODE;\n case 232: // FNC1\n result.append(String.fromCharCode(29)); // translate as ASCII 29\n break;\n case 233: // Structured Append\n case 234: // Reader Programming\n // Ignore these symbols for now\n // throw ReaderException.getInstance();\n break;\n case 235: // Upper Shift (shift to Extended ASCII)\n upperShift = true;\n break;\n case 236: // 05 Macro\n result.append('[)>\\u001E05\\u001D');\n resultTrailer.insert(0, '\\u001E\\u0004');\n break;\n case 237: // 06 Macro\n result.append('[)>\\u001E06\\u001D');\n resultTrailer.insert(0, '\\u001E\\u0004');\n break;\n case 238: // Latch to ANSI X12 encodation\n return Mode.ANSIX12_ENCODE;\n case 239: // Latch to Text encodation\n return Mode.TEXT_ENCODE;\n case 240: // Latch to EDIFACT encodation\n return Mode.EDIFACT_ENCODE;\n case 241: // ECI Character\n // TODO(bbrown): I think we need to support ECI\n // throw ReaderException.getInstance();\n // Ignore this symbol for now\n break;\n default:\n // Not to be used in ASCII encodation\n // but work around encoders that end with 254, latch back to ASCII\n if (oneByte !== 254 || bits.available() !== 0) {\n throw new FormatException();\n }\n break;\n }\n }\n } while (bits.available() > 0);\n return Mode.ASCII_ENCODE;\n }\n /**\n * See ISO 16022:2006, 5.2.5 and Annex C, Table C.1\n */\n static decodeC40Segment(bits, result) {\n // Three C40 values are encoded in a 16-bit value as\n // (1600 * C1) + (40 * C2) + C3 + 1\n // TODO(bbrown): The Upper Shift with C40 doesn't work in the 4 value scenario all the time\n let upperShift = false;\n const cValues = [];\n let shift = 0;\n do {\n // If there is only one byte left then it will be encoded as ASCII\n if (bits.available() === 8) {\n return;\n }\n const firstByte = bits.readBits(8);\n if (firstByte === 254) { // Unlatch codeword\n return;\n }\n this.parseTwoBytes(firstByte, bits.readBits(8), cValues);\n for (let i = 0; i < 3; i++) {\n const cValue = cValues[i];\n switch (shift) {\n case 0:\n if (cValue < 3) {\n shift = cValue + 1;\n }\n else if (cValue < this.C40_BASIC_SET_CHARS.length) {\n const c40char = this.C40_BASIC_SET_CHARS[cValue];\n if (upperShift) {\n result.append(String.fromCharCode(c40char.charCodeAt(0) + 128));\n upperShift = false;\n }\n else {\n result.append(c40char);\n }\n }\n else {\n throw new FormatException();\n }\n break;\n case 1:\n if (upperShift) {\n result.append(String.fromCharCode(cValue + 128));\n upperShift = false;\n }\n else {\n result.append(String.fromCharCode(cValue));\n }\n shift = 0;\n break;\n case 2:\n if (cValue < this.C40_SHIFT2_SET_CHARS.length) {\n const c40char = this.C40_SHIFT2_SET_CHARS[cValue];\n if (upperShift) {\n result.append(String.fromCharCode(c40char.charCodeAt(0) + 128));\n upperShift = false;\n }\n else {\n result.append(c40char);\n }\n }\n else {\n switch (cValue) {\n case 27: // FNC1\n result.append(String.fromCharCode(29)); // translate as ASCII 29\n break;\n case 30: // Upper Shift\n upperShift = true;\n break;\n default:\n throw new FormatException();\n }\n }\n shift = 0;\n break;\n case 3:\n if (upperShift) {\n result.append(String.fromCharCode(cValue + 224));\n upperShift = false;\n }\n else {\n result.append(String.fromCharCode(cValue + 96));\n }\n shift = 0;\n break;\n default:\n throw new FormatException();\n }\n }\n } while (bits.available() > 0);\n }\n /**\n * See ISO 16022:2006, 5.2.6 and Annex C, Table C.2\n */\n static decodeTextSegment(bits, result) {\n // Three Text values are encoded in a 16-bit value as\n // (1600 * C1) + (40 * C2) + C3 + 1\n // TODO(bbrown): The Upper Shift with Text doesn't work in the 4 value scenario all the time\n let upperShift = false;\n let cValues = [];\n let shift = 0;\n do {\n // If there is only one byte left then it will be encoded as ASCII\n if (bits.available() === 8) {\n return;\n }\n const firstByte = bits.readBits(8);\n if (firstByte === 254) { // Unlatch codeword\n return;\n }\n this.parseTwoBytes(firstByte, bits.readBits(8), cValues);\n for (let i = 0; i < 3; i++) {\n const cValue = cValues[i];\n switch (shift) {\n case 0:\n if (cValue < 3) {\n shift = cValue + 1;\n }\n else if (cValue < this.TEXT_BASIC_SET_CHARS.length) {\n const textChar = this.TEXT_BASIC_SET_CHARS[cValue];\n if (upperShift) {\n result.append(String.fromCharCode(textChar.charCodeAt(0) + 128));\n upperShift = false;\n }\n else {\n result.append(textChar);\n }\n }\n else {\n throw new FormatException();\n }\n break;\n case 1:\n if (upperShift) {\n result.append(String.fromCharCode(cValue + 128));\n upperShift = false;\n }\n else {\n result.append(String.fromCharCode(cValue));\n }\n shift = 0;\n break;\n case 2:\n // Shift 2 for Text is the same encoding as C40\n if (cValue < this.TEXT_SHIFT2_SET_CHARS.length) {\n const textChar = this.TEXT_SHIFT2_SET_CHARS[cValue];\n if (upperShift) {\n result.append(String.fromCharCode(textChar.charCodeAt(0) + 128));\n upperShift = false;\n }\n else {\n result.append(textChar);\n }\n }\n else {\n switch (cValue) {\n case 27: // FNC1\n result.append(String.fromCharCode(29)); // translate as ASCII 29\n break;\n case 30: // Upper Shift\n upperShift = true;\n break;\n default:\n throw new FormatException();\n }\n }\n shift = 0;\n break;\n case 3:\n if (cValue < this.TEXT_SHIFT3_SET_CHARS.length) {\n const textChar = this.TEXT_SHIFT3_SET_CHARS[cValue];\n if (upperShift) {\n result.append(String.fromCharCode(textChar.charCodeAt(0) + 128));\n upperShift = false;\n }\n else {\n result.append(textChar);\n }\n shift = 0;\n }\n else {\n throw new FormatException();\n }\n break;\n default:\n throw new FormatException();\n }\n }\n } while (bits.available() > 0);\n }\n /**\n * See ISO 16022:2006, 5.2.7\n */\n static decodeAnsiX12Segment(bits, result) {\n // Three ANSI X12 values are encoded in a 16-bit value as\n // (1600 * C1) + (40 * C2) + C3 + 1\n const cValues = [];\n do {\n // If there is only one byte left then it will be encoded as ASCII\n if (bits.available() === 8) {\n return;\n }\n const firstByte = bits.readBits(8);\n if (firstByte === 254) { // Unlatch codeword\n return;\n }\n this.parseTwoBytes(firstByte, bits.readBits(8), cValues);\n for (let i = 0; i < 3; i++) {\n const cValue = cValues[i];\n switch (cValue) {\n case 0: // X12 segment terminator \n result.append('\\r');\n break;\n case 1: // X12 segment separator *\n result.append('*');\n break;\n case 2: // X12 sub-element separator >\n result.append('>');\n break;\n case 3: // space\n result.append(' ');\n break;\n default:\n if (cValue < 14) { // 0 - 9\n result.append(String.fromCharCode(cValue + 44));\n }\n else if (cValue < 40) { // A - Z\n result.append(String.fromCharCode(cValue + 51));\n }\n else {\n throw new FormatException();\n }\n break;\n }\n }\n } while (bits.available() > 0);\n }\n static parseTwoBytes(firstByte, secondByte, result) {\n let fullBitValue = (firstByte << 8) + secondByte - 1;\n let temp = Math.floor(fullBitValue / 1600);\n result[0] = temp;\n fullBitValue -= temp * 1600;\n temp = Math.floor(fullBitValue / 40);\n result[1] = temp;\n result[2] = fullBitValue - temp * 40;\n }\n /**\n * See ISO 16022:2006, 5.2.8 and Annex C Table C.3\n */\n static decodeEdifactSegment(bits, result) {\n do {\n // If there is only two or less bytes left then it will be encoded as ASCII\n if (bits.available() <= 16) {\n return;\n }\n for (let i = 0; i < 4; i++) {\n let edifactValue = bits.readBits(6);\n // Check for the unlatch character\n if (edifactValue === 0x1F) { // 011111\n // Read rest of byte, which should be 0, and stop\n const bitsLeft = 8 - bits.getBitOffset();\n if (bitsLeft !== 8) {\n bits.readBits(bitsLeft);\n }\n return;\n }\n if ((edifactValue & 0x20) === 0) { // no 1 in the leading (6th) bit\n edifactValue |= 0x40; // Add a leading 01 to the 6 bit binary value\n }\n result.append(String.fromCharCode(edifactValue));\n }\n } while (bits.available() > 0);\n }\n /**\n * See ISO 16022:2006, 5.2.9 and Annex B, B.2\n */\n static decodeBase256Segment(bits, result, byteSegments) {\n // Figure out how long the Base 256 Segment is.\n let codewordPosition = 1 + bits.getByteOffset(); // position is 1-indexed\n const d1 = this.unrandomize255State(bits.readBits(8), codewordPosition++);\n let count;\n if (d1 === 0) { // Read the remainder of the symbol\n count = bits.available() / 8 | 0;\n }\n else if (d1 < 250) {\n count = d1;\n }\n else {\n count = 250 * (d1 - 249) + this.unrandomize255State(bits.readBits(8), codewordPosition++);\n }\n // We're seeing NegativeArraySizeException errors from users.\n if (count < 0) {\n throw new FormatException();\n }\n const bytes = new Uint8Array(count);\n for (let i = 0; i < count; i++) {\n // Have seen this particular error in the wild, such as at\n // http://www.bcgen.com/demo/IDAutomationStreamingDataMatrix.aspx?MODE=3&D=Fred&PFMT=3&PT=F&X=0.3&O=0&LM=0.2\n if (bits.available() < 8) {\n throw new FormatException();\n }\n bytes[i] = this.unrandomize255State(bits.readBits(8), codewordPosition++);\n }\n byteSegments.push(bytes);\n try {\n result.append(StringEncoding.decode(bytes, StringUtils.ISO88591));\n }\n catch (uee) {\n throw new IllegalStateException('Platform does not support required encoding: ' + uee.message);\n }\n }\n /**\n * See ISO 16022:2006, Annex B, B.2\n */\n static unrandomize255State(randomizedBase256Codeword, base256CodewordPosition) {\n const pseudoRandomNumber = ((149 * base256CodewordPosition) % 255) + 1;\n const tempVariable = randomizedBase256Codeword - pseudoRandomNumber;\n return tempVariable >= 0 ? tempVariable : tempVariable + 256;\n }\n }\n /**\n * See ISO 16022:2006, Annex C Table C.1\n * The C40 Basic Character Set (*'s used for placeholders for the shift values)\n */\n DecodedBitStreamParser.C40_BASIC_SET_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 DecodedBitStreamParser.C40_SHIFT2_SET_CHARS = [\n '!', '\"', '#', '$', '%', '&', '\\'', '(', ')', '*', '+', ',', '-', '.',\n '/', ':', ';', '<', '=', '>', '?', '@', '[', '\\\\', ']', '^', '_'\n ];\n /**\n * See ISO 16022:2006, Annex C Table C.2\n * The Text Basic Character Set (*'s used for placeholders for the shift values)\n */\n DecodedBitStreamParser.TEXT_BASIC_SET_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 // Shift 2 for Text is the same encoding as C40\n DecodedBitStreamParser.TEXT_SHIFT2_SET_CHARS = DecodedBitStreamParser.C40_SHIFT2_SET_CHARS;\n DecodedBitStreamParser.TEXT_SHIFT3_SET_CHARS = [\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', '{', '|', '}', '~', String.fromCharCode(127)\n ];\n\n /*\n * Copyright 2007 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n /**\n *

The main class which implements Data Matrix Code decoding -- as opposed to locating and extracting\n * the Data Matrix Code from an image.

\n *\n * @author bbrown@google.com (Brian Brown)\n */\n class Decoder$1 {\n constructor() {\n this.rsDecoder = new ReedSolomonDecoder(GenericGF.DATA_MATRIX_FIELD_256);\n }\n /**\n *

Decodes a Data Matrix Code represented as a {@link BitMatrix}. A 1 or \"true\" is taken\n * to mean a black module.

\n *\n * @param bits booleans representing white/black Data Matrix Code modules\n * @return text and bytes encoded within the Data Matrix Code\n * @throws FormatException if the Data Matrix Code cannot be decoded\n * @throws ChecksumException if error correction fails\n */\n decode(bits) {\n // Construct a parser and read version, error-correction level\n const parser = new BitMatrixParser(bits);\n const version = parser.getVersion();\n // Read codewords\n const codewords = parser.readCodewords();\n // Separate into data blocks\n const dataBlocks = DataBlock.getDataBlocks(codewords, version);\n // Count total number of data bytes\n let totalBytes = 0;\n for (let db of dataBlocks) {\n totalBytes += db.getNumDataCodewords();\n }\n const resultBytes = new Uint8Array(totalBytes);\n const dataBlocksCount = dataBlocks.length;\n // Error-correct and copy data blocks together into a stream of bytes\n for (let j = 0; j < dataBlocksCount; j++) {\n const dataBlock = dataBlocks[j];\n const codewordBytes = dataBlock.getCodewords();\n const numDataCodewords = dataBlock.getNumDataCodewords();\n this.correctErrors(codewordBytes, numDataCodewords);\n for (let i = 0; i < numDataCodewords; i++) {\n // De-interlace data blocks.\n resultBytes[i * dataBlocksCount + j] = codewordBytes[i];\n }\n }\n // Decode the contents of that stream of bytes\n return DecodedBitStreamParser.decode(resultBytes);\n }\n /**\n *

Given data and error-correction codewords received, possibly corrupted by errors, attempts to\n * correct the errors in-place using Reed-Solomon error correction.

\n *\n * @param codewordBytes data and error correction codewords\n * @param numDataCodewords number of codewords that are data bytes\n * @throws ChecksumException if error correction fails\n */\n correctErrors(codewordBytes, numDataCodewords) {\n // const numCodewords = codewordBytes.length;\n // First read into an array of ints\n const codewordsInts = new Int32Array(codewordBytes);\n // for (let i = 0; i < numCodewords; i++) {\n // codewordsInts[i] = codewordBytes[i] & 0xFF;\n // }\n try {\n this.rsDecoder.decode(codewordsInts, codewordBytes.length - numDataCodewords);\n }\n catch (ignored /* ReedSolomonException */) {\n throw new ChecksumException();\n }\n // Copy back into array of bytes -- only need to worry about the bytes that were data\n // We don't care about errors in the error-correction codewords\n for (let i = 0; i < numDataCodewords; i++) {\n codewordBytes[i] = codewordsInts[i];\n }\n }\n }\n\n /**\n *

Encapsulates logic that can detect a Data Matrix Code in an image, even if the Data Matrix Code\n * is rotated or skewed, or partially obscured.

\n *\n * @author Sean Owen\n */\n class Detector$1 {\n constructor(image) {\n this.image = image;\n this.rectangleDetector = new WhiteRectangleDetector(this.image);\n }\n /**\n *

Detects a Data Matrix Code in an image.

\n *\n * @return {@link DetectorResult} encapsulating results of detecting a Data Matrix Code\n * @throws NotFoundException if no Data Matrix Code can be found\n */\n detect() {\n const cornerPoints = this.rectangleDetector.detect();\n let points = this.detectSolid1(cornerPoints);\n points = this.detectSolid2(points);\n points[3] = this.correctTopRight(points);\n if (!points[3]) {\n throw new NotFoundException();\n }\n points = this.shiftToModuleCenter(points);\n const topLeft = points[0];\n const bottomLeft = points[1];\n const bottomRight = points[2];\n const topRight = points[3];\n let dimensionTop = this.transitionsBetween(topLeft, topRight) + 1;\n let dimensionRight = this.transitionsBetween(bottomRight, topRight) + 1;\n if ((dimensionTop & 0x01) === 1) {\n dimensionTop += 1;\n }\n if ((dimensionRight & 0x01) === 1) {\n dimensionRight += 1;\n }\n if (4 * dimensionTop < 7 * dimensionRight && 4 * dimensionRight < 7 * dimensionTop) {\n // The matrix is square\n dimensionTop = dimensionRight = Math.max(dimensionTop, dimensionRight);\n }\n let bits = Detector$1.sampleGrid(this.image, topLeft, bottomLeft, bottomRight, topRight, dimensionTop, dimensionRight);\n return new DetectorResult(bits, [topLeft, bottomLeft, bottomRight, topRight]);\n }\n static shiftPoint(point, to, div) {\n let x = (to.getX() - point.getX()) / (div + 1);\n let y = (to.getY() - point.getY()) / (div + 1);\n return new ResultPoint(point.getX() + x, point.getY() + y);\n }\n static moveAway(point, fromX, fromY) {\n let x = point.getX();\n let y = point.getY();\n if (x < fromX) {\n x -= 1;\n }\n else {\n x += 1;\n }\n if (y < fromY) {\n y -= 1;\n }\n else {\n y += 1;\n }\n return new ResultPoint(x, y);\n }\n /**\n * Detect a solid side which has minimum transition.\n */\n detectSolid1(cornerPoints) {\n // 0 2\n // 1 3\n let pointA = cornerPoints[0];\n let pointB = cornerPoints[1];\n let pointC = cornerPoints[3];\n let pointD = cornerPoints[2];\n let trAB = this.transitionsBetween(pointA, pointB);\n let trBC = this.transitionsBetween(pointB, pointC);\n let trCD = this.transitionsBetween(pointC, pointD);\n let trDA = this.transitionsBetween(pointD, pointA);\n // 0..3\n // : :\n // 1--2\n let min = trAB;\n let points = [pointD, pointA, pointB, pointC];\n if (min > trBC) {\n min = trBC;\n points[0] = pointA;\n points[1] = pointB;\n points[2] = pointC;\n points[3] = pointD;\n }\n if (min > trCD) {\n min = trCD;\n points[0] = pointB;\n points[1] = pointC;\n points[2] = pointD;\n points[3] = pointA;\n }\n if (min > trDA) {\n points[0] = pointC;\n points[1] = pointD;\n points[2] = pointA;\n points[3] = pointB;\n }\n return points;\n }\n /**\n * Detect a second solid side next to first solid side.\n */\n detectSolid2(points) {\n // A..D\n // : :\n // B--C\n let pointA = points[0];\n let pointB = points[1];\n let pointC = points[2];\n let pointD = points[3];\n // Transition detection on the edge is not stable.\n // To safely detect, shift the points to the module center.\n let tr = this.transitionsBetween(pointA, pointD);\n let pointBs = Detector$1.shiftPoint(pointB, pointC, (tr + 1) * 4);\n let pointCs = Detector$1.shiftPoint(pointC, pointB, (tr + 1) * 4);\n let trBA = this.transitionsBetween(pointBs, pointA);\n let trCD = this.transitionsBetween(pointCs, pointD);\n // 0..3\n // | :\n // 1--2\n if (trBA < trCD) {\n // solid sides: A-B-C\n points[0] = pointA;\n points[1] = pointB;\n points[2] = pointC;\n points[3] = pointD;\n }\n else {\n // solid sides: B-C-D\n points[0] = pointB;\n points[1] = pointC;\n points[2] = pointD;\n points[3] = pointA;\n }\n return points;\n }\n /**\n * Calculates the corner position of the white top right module.\n */\n correctTopRight(points) {\n // A..D\n // | :\n // B--C\n let pointA = points[0];\n let pointB = points[1];\n let pointC = points[2];\n let pointD = points[3];\n // shift points for safe transition detection.\n let trTop = this.transitionsBetween(pointA, pointD);\n let trRight = this.transitionsBetween(pointB, pointD);\n let pointAs = Detector$1.shiftPoint(pointA, pointB, (trRight + 1) * 4);\n let pointCs = Detector$1.shiftPoint(pointC, pointB, (trTop + 1) * 4);\n trTop = this.transitionsBetween(pointAs, pointD);\n trRight = this.transitionsBetween(pointCs, pointD);\n let candidate1 = new ResultPoint(pointD.getX() + (pointC.getX() - pointB.getX()) / (trTop + 1), pointD.getY() + (pointC.getY() - pointB.getY()) / (trTop + 1));\n let candidate2 = new ResultPoint(pointD.getX() + (pointA.getX() - pointB.getX()) / (trRight + 1), pointD.getY() + (pointA.getY() - pointB.getY()) / (trRight + 1));\n if (!this.isValid(candidate1)) {\n if (this.isValid(candidate2)) {\n return candidate2;\n }\n return null;\n }\n if (!this.isValid(candidate2)) {\n return candidate1;\n }\n let sumc1 = this.transitionsBetween(pointAs, candidate1) + this.transitionsBetween(pointCs, candidate1);\n let sumc2 = this.transitionsBetween(pointAs, candidate2) + this.transitionsBetween(pointCs, candidate2);\n if (sumc1 > sumc2) {\n return candidate1;\n }\n else {\n return candidate2;\n }\n }\n /**\n * Shift the edge points to the module center.\n */\n shiftToModuleCenter(points) {\n // A..D\n // | :\n // B--C\n let pointA = points[0];\n let pointB = points[1];\n let pointC = points[2];\n let pointD = points[3];\n // calculate pseudo dimensions\n let dimH = this.transitionsBetween(pointA, pointD) + 1;\n let dimV = this.transitionsBetween(pointC, pointD) + 1;\n // shift points for safe dimension detection\n let pointAs = Detector$1.shiftPoint(pointA, pointB, dimV * 4);\n let pointCs = Detector$1.shiftPoint(pointC, pointB, dimH * 4);\n // calculate more precise dimensions\n dimH = this.transitionsBetween(pointAs, pointD) + 1;\n dimV = this.transitionsBetween(pointCs, pointD) + 1;\n if ((dimH & 0x01) === 1) {\n dimH += 1;\n }\n if ((dimV & 0x01) === 1) {\n dimV += 1;\n }\n // WhiteRectangleDetector returns points inside of the rectangle.\n // I want points on the edges.\n let centerX = (pointA.getX() + pointB.getX() + pointC.getX() + pointD.getX()) / 4;\n let centerY = (pointA.getY() + pointB.getY() + pointC.getY() + pointD.getY()) / 4;\n pointA = Detector$1.moveAway(pointA, centerX, centerY);\n pointB = Detector$1.moveAway(pointB, centerX, centerY);\n pointC = Detector$1.moveAway(pointC, centerX, centerY);\n pointD = Detector$1.moveAway(pointD, centerX, centerY);\n let pointBs;\n let pointDs;\n // shift points to the center of each modules\n pointAs = Detector$1.shiftPoint(pointA, pointB, dimV * 4);\n pointAs = Detector$1.shiftPoint(pointAs, pointD, dimH * 4);\n pointBs = Detector$1.shiftPoint(pointB, pointA, dimV * 4);\n pointBs = Detector$1.shiftPoint(pointBs, pointC, dimH * 4);\n pointCs = Detector$1.shiftPoint(pointC, pointD, dimV * 4);\n pointCs = Detector$1.shiftPoint(pointCs, pointB, dimH * 4);\n pointDs = Detector$1.shiftPoint(pointD, pointC, dimV * 4);\n pointDs = Detector$1.shiftPoint(pointDs, pointA, dimH * 4);\n return [pointAs, pointBs, pointCs, pointDs];\n }\n isValid(p) {\n return p.getX() >= 0 && p.getX() < this.image.getWidth() && p.getY() > 0 && p.getY() < this.image.getHeight();\n }\n static sampleGrid(image, topLeft, bottomLeft, bottomRight, topRight, dimensionX, dimensionY) {\n const sampler = GridSamplerInstance.getInstance();\n return sampler.sampleGrid(image, dimensionX, dimensionY, 0.5, 0.5, dimensionX - 0.5, 0.5, dimensionX - 0.5, dimensionY - 0.5, 0.5, dimensionY - 0.5, topLeft.getX(), topLeft.getY(), topRight.getX(), topRight.getY(), bottomRight.getX(), bottomRight.getY(), bottomLeft.getX(), bottomLeft.getY());\n }\n /**\n * Counts the number of black/white transitions between two points, using something like Bresenham's algorithm.\n */\n transitionsBetween(from, to) {\n // See QR Code Detector, sizeOfBlackWhiteBlackRun()\n let fromX = Math.trunc(from.getX());\n let fromY = Math.trunc(from.getY());\n let toX = Math.trunc(to.getX());\n let toY = Math.trunc(to.getY());\n let steep = Math.abs(toY - fromY) > Math.abs(toX - fromX);\n if (steep) {\n let temp = fromX;\n fromX = fromY;\n fromY = temp;\n temp = toX;\n toX = toY;\n toY = temp;\n }\n let dx = Math.abs(toX - fromX);\n let dy = Math.abs(toY - fromY);\n let error = -dx / 2;\n let ystep = fromY < toY ? 1 : -1;\n let xstep = fromX < toX ? 1 : -1;\n let transitions = 0;\n let inBlack = this.image.get(steep ? fromY : fromX, steep ? fromX : fromY);\n for (let x = fromX, y = fromY; x !== toX; x += xstep) {\n let isBlack = this.image.get(steep ? y : x, steep ? x : y);\n if (isBlack !== inBlack) {\n transitions++;\n inBlack = isBlack;\n }\n error += dy;\n if (error > 0) {\n if (y === toY) {\n break;\n }\n y += ystep;\n error -= dx;\n }\n }\n return transitions;\n }\n }\n\n /*\n * Copyright 2007 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n /**\n * This implementation can detect and decode Data Matrix codes in an image.\n *\n * @author bbrown@google.com (Brian Brown)\n */\n class DataMatrixReader {\n constructor() {\n this.decoder = new Decoder$1();\n }\n /**\n * Locates and decodes a Data Matrix code in an image.\n *\n * @return a String representing the content encoded by the Data Matrix code\n * @throws NotFoundException if a Data Matrix code cannot be found\n * @throws FormatException if a Data Matrix code cannot be decoded\n * @throws ChecksumException if error correction fails\n */\n // @Override\n // public Result decode(BinaryBitmap image) throws NotFoundException, ChecksumException, FormatException {\n // return decode(image, null);\n // }\n // @Override\n decode(image, hints = null) {\n let decoderResult;\n let points;\n if (hints != null && hints.has(DecodeHintType$1.PURE_BARCODE)) {\n const bits = DataMatrixReader.extractPureBits(image.getBlackMatrix());\n decoderResult = this.decoder.decode(bits);\n points = DataMatrixReader.NO_POINTS;\n }\n else {\n const detectorResult = new Detector$1(image.getBlackMatrix()).detect();\n decoderResult = this.decoder.decode(detectorResult.getBits());\n points = detectorResult.getPoints();\n }\n const rawBytes = decoderResult.getRawBytes();\n const result = new Result(decoderResult.getText(), rawBytes, 8 * rawBytes.length, points, BarcodeFormat$1.DATA_MATRIX, System.currentTimeMillis());\n const byteSegments = decoderResult.getByteSegments();\n if (byteSegments != null) {\n result.putMetadata(ResultMetadataType$1.BYTE_SEGMENTS, byteSegments);\n }\n const ecLevel = decoderResult.getECLevel();\n if (ecLevel != null) {\n result.putMetadata(ResultMetadataType$1.ERROR_CORRECTION_LEVEL, ecLevel);\n }\n return result;\n }\n // @Override\n reset() {\n // do nothing\n }\n /**\n * This method detects a code in a \"pure\" image -- that is, pure monochrome image\n * which contains only an unrotated, unskewed, image of a code, with some white border\n * around it. This is a specialized method that works exceptionally fast in this special\n * case.\n *\n * @see com.google.zxing.qrcode.QRCodeReader#extractPureBits(BitMatrix)\n */\n static extractPureBits(image) {\n const leftTopBlack = image.getTopLeftOnBit();\n const rightBottomBlack = image.getBottomRightOnBit();\n if (leftTopBlack == null || rightBottomBlack == null) {\n throw new NotFoundException();\n }\n const moduleSize = this.moduleSize(leftTopBlack, image);\n let top = leftTopBlack[1];\n const bottom = rightBottomBlack[1];\n let left = leftTopBlack[0];\n const right = rightBottomBlack[0];\n const matrixWidth = (right - left + 1) / moduleSize;\n const matrixHeight = (bottom - top + 1) / moduleSize;\n if (matrixWidth <= 0 || matrixHeight <= 0) {\n throw new NotFoundException();\n }\n // Push in the \"border\" by half the module width so that we start\n // sampling in the middle of the module. Just in case the image is a\n // little off, this will help recover.\n const nudge = moduleSize / 2;\n top += nudge;\n left += nudge;\n // Now just read off the bits\n const bits = new BitMatrix(matrixWidth, matrixHeight);\n for (let y = 0; y < matrixHeight; y++) {\n const iOffset = top + y * moduleSize;\n for (let x = 0; x < matrixWidth; x++) {\n if (image.get(left + x * moduleSize, iOffset)) {\n bits.set(x, y);\n }\n }\n }\n return bits;\n }\n static moduleSize(leftTopBlack, image) {\n const width = image.getWidth();\n let x = leftTopBlack[0];\n const y = leftTopBlack[1];\n while (x < width && image.get(x, y)) {\n x++;\n }\n if (x === width) {\n throw new NotFoundException();\n }\n const moduleSize = x - leftTopBlack[0];\n if (moduleSize === 0) {\n throw new NotFoundException();\n }\n return moduleSize;\n }\n }\n DataMatrixReader.NO_POINTS = [];\n\n /**\n * @deprecated Moving to @zxing/browser\n *\n * QR Code reader to use from browser.\n */\n class BrowserDatamatrixCodeReader extends BrowserCodeReader {\n /**\n * Creates an instance of BrowserQRCodeReader.\n * @param {number} [timeBetweenScansMillis=500] the time delay between subsequent decode tries\n */\n constructor(timeBetweenScansMillis = 500) {\n super(new DataMatrixReader(), timeBetweenScansMillis);\n }\n }\n\n /*\n * Copyright 2007 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n var ErrorCorrectionLevelValues;\n (function (ErrorCorrectionLevelValues) {\n ErrorCorrectionLevelValues[ErrorCorrectionLevelValues[\"L\"] = 0] = \"L\";\n ErrorCorrectionLevelValues[ErrorCorrectionLevelValues[\"M\"] = 1] = \"M\";\n ErrorCorrectionLevelValues[ErrorCorrectionLevelValues[\"Q\"] = 2] = \"Q\";\n ErrorCorrectionLevelValues[ErrorCorrectionLevelValues[\"H\"] = 3] = \"H\";\n })(ErrorCorrectionLevelValues || (ErrorCorrectionLevelValues = {}));\n /**\n *

See ISO 18004:2006, 6.5.1. This enum encapsulates the four error correction levels\n * defined by the QR code standard.

\n *\n * @author Sean Owen\n */\n class ErrorCorrectionLevel {\n constructor(value, stringValue, bits /*int*/) {\n this.value = value;\n this.stringValue = stringValue;\n this.bits = bits;\n ErrorCorrectionLevel.FOR_BITS.set(bits, this);\n ErrorCorrectionLevel.FOR_VALUE.set(value, this);\n }\n getValue() {\n return this.value;\n }\n getBits() {\n return this.bits;\n }\n static fromString(s) {\n switch (s) {\n case 'L': return ErrorCorrectionLevel.L;\n case 'M': return ErrorCorrectionLevel.M;\n case 'Q': return ErrorCorrectionLevel.Q;\n case 'H': return ErrorCorrectionLevel.H;\n default: throw new ArgumentException(s + 'not available');\n }\n }\n toString() {\n return this.stringValue;\n }\n equals(o) {\n if (!(o instanceof ErrorCorrectionLevel)) {\n return false;\n }\n const other = o;\n return this.value === other.value;\n }\n /**\n * @param bits int containing the two bits encoding a QR Code's error correction level\n * @return ErrorCorrectionLevel representing the encoded error correction level\n */\n static forBits(bits /*int*/) {\n if (bits < 0 || bits >= ErrorCorrectionLevel.FOR_BITS.size) {\n throw new IllegalArgumentException();\n }\n return ErrorCorrectionLevel.FOR_BITS.get(bits);\n }\n }\n ErrorCorrectionLevel.FOR_BITS = new Map();\n ErrorCorrectionLevel.FOR_VALUE = new Map();\n /** L = ~7% correction */\n ErrorCorrectionLevel.L = new ErrorCorrectionLevel(ErrorCorrectionLevelValues.L, 'L', 0x01);\n /** M = ~15% correction */\n ErrorCorrectionLevel.M = new ErrorCorrectionLevel(ErrorCorrectionLevelValues.M, 'M', 0x00);\n /** Q = ~25% correction */\n ErrorCorrectionLevel.Q = new ErrorCorrectionLevel(ErrorCorrectionLevelValues.Q, 'Q', 0x03);\n /** H = ~30% correction */\n ErrorCorrectionLevel.H = new ErrorCorrectionLevel(ErrorCorrectionLevelValues.H, 'H', 0x02);\n\n /*\n * Copyright 2007 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n /**\n *

Encapsulates a QR Code's format information, including the data mask used and\n * error correction level.

\n *\n * @author Sean Owen\n * @see DataMask\n * @see ErrorCorrectionLevel\n */\n class FormatInformation {\n constructor(formatInfo /*int*/) {\n // Bits 3,4\n this.errorCorrectionLevel = ErrorCorrectionLevel.forBits((formatInfo >> 3) & 0x03);\n // Bottom 3 bits\n this.dataMask = /*(byte) */ (formatInfo & 0x07);\n }\n static numBitsDiffering(a /*int*/, b /*int*/) {\n return Integer.bitCount(a ^ b);\n }\n /**\n * @param maskedFormatInfo1 format info indicator, with mask still applied\n * @param maskedFormatInfo2 second copy of same info; both are checked at the same time\n * to establish best match\n * @return information about the format it specifies, or {@code null}\n * if doesn't seem to match any known pattern\n */\n static decodeFormatInformation(maskedFormatInfo1 /*int*/, maskedFormatInfo2 /*int*/) {\n const formatInfo = FormatInformation.doDecodeFormatInformation(maskedFormatInfo1, maskedFormatInfo2);\n if (formatInfo !== null) {\n return formatInfo;\n }\n // Should return null, but, some QR codes apparently\n // do not mask this info. Try again by actually masking the pattern\n // first\n return FormatInformation.doDecodeFormatInformation(maskedFormatInfo1 ^ FormatInformation.FORMAT_INFO_MASK_QR, maskedFormatInfo2 ^ FormatInformation.FORMAT_INFO_MASK_QR);\n }\n static doDecodeFormatInformation(maskedFormatInfo1 /*int*/, maskedFormatInfo2 /*int*/) {\n // Find the int in FORMAT_INFO_DECODE_LOOKUP with fewest bits differing\n let bestDifference = Number.MAX_SAFE_INTEGER;\n let bestFormatInfo = 0;\n for (const decodeInfo of FormatInformation.FORMAT_INFO_DECODE_LOOKUP) {\n const targetInfo = decodeInfo[0];\n if (targetInfo === maskedFormatInfo1 || targetInfo === maskedFormatInfo2) {\n // Found an exact match\n return new FormatInformation(decodeInfo[1]);\n }\n let bitsDifference = FormatInformation.numBitsDiffering(maskedFormatInfo1, targetInfo);\n if (bitsDifference < bestDifference) {\n bestFormatInfo = decodeInfo[1];\n bestDifference = bitsDifference;\n }\n if (maskedFormatInfo1 !== maskedFormatInfo2) {\n // also try the other option\n bitsDifference = FormatInformation.numBitsDiffering(maskedFormatInfo2, targetInfo);\n if (bitsDifference < bestDifference) {\n bestFormatInfo = decodeInfo[1];\n bestDifference = bitsDifference;\n }\n }\n }\n // Hamming distance of the 32 masked codes is 7, by construction, so <= 3 bits\n // differing means we found a match\n if (bestDifference <= 3) {\n return new FormatInformation(bestFormatInfo);\n }\n return null;\n }\n getErrorCorrectionLevel() {\n return this.errorCorrectionLevel;\n }\n getDataMask() {\n return this.dataMask;\n }\n /*@Override*/\n hashCode() {\n return (this.errorCorrectionLevel.getBits() << 3) | this.dataMask;\n }\n /*@Override*/\n equals(o) {\n if (!(o instanceof FormatInformation)) {\n return false;\n }\n const other = o;\n return this.errorCorrectionLevel === other.errorCorrectionLevel &&\n this.dataMask === other.dataMask;\n }\n }\n FormatInformation.FORMAT_INFO_MASK_QR = 0x5412;\n /**\n * See ISO 18004:2006, Annex C, Table C.1\n */\n FormatInformation.FORMAT_INFO_DECODE_LOOKUP = [\n Int32Array.from([0x5412, 0x00]),\n Int32Array.from([0x5125, 0x01]),\n Int32Array.from([0x5E7C, 0x02]),\n Int32Array.from([0x5B4B, 0x03]),\n Int32Array.from([0x45F9, 0x04]),\n Int32Array.from([0x40CE, 0x05]),\n Int32Array.from([0x4F97, 0x06]),\n Int32Array.from([0x4AA0, 0x07]),\n Int32Array.from([0x77C4, 0x08]),\n Int32Array.from([0x72F3, 0x09]),\n Int32Array.from([0x7DAA, 0x0A]),\n Int32Array.from([0x789D, 0x0B]),\n Int32Array.from([0x662F, 0x0C]),\n Int32Array.from([0x6318, 0x0D]),\n Int32Array.from([0x6C41, 0x0E]),\n Int32Array.from([0x6976, 0x0F]),\n Int32Array.from([0x1689, 0x10]),\n Int32Array.from([0x13BE, 0x11]),\n Int32Array.from([0x1CE7, 0x12]),\n Int32Array.from([0x19D0, 0x13]),\n Int32Array.from([0x0762, 0x14]),\n Int32Array.from([0x0255, 0x15]),\n Int32Array.from([0x0D0C, 0x16]),\n Int32Array.from([0x083B, 0x17]),\n Int32Array.from([0x355F, 0x18]),\n Int32Array.from([0x3068, 0x19]),\n Int32Array.from([0x3F31, 0x1A]),\n Int32Array.from([0x3A06, 0x1B]),\n Int32Array.from([0x24B4, 0x1C]),\n Int32Array.from([0x2183, 0x1D]),\n Int32Array.from([0x2EDA, 0x1E]),\n Int32Array.from([0x2BED, 0x1F]),\n ];\n\n /**\n *

Encapsulates a set of error-correction blocks in one symbol version. Most versions will\n * use blocks of differing sizes within one version, so, this encapsulates the parameters for\n * each set of blocks. It also holds the number of error-correction codewords per block since it\n * will be the same across all blocks within one version.

\n */\n class ECBlocks$1 {\n constructor(ecCodewordsPerBlock /*int*/, ...ecBlocks) {\n this.ecCodewordsPerBlock = ecCodewordsPerBlock;\n this.ecBlocks = ecBlocks;\n }\n getECCodewordsPerBlock() {\n return this.ecCodewordsPerBlock;\n }\n getNumBlocks() {\n let total = 0;\n const ecBlocks = this.ecBlocks;\n for (const ecBlock of ecBlocks) {\n total += ecBlock.getCount();\n }\n return total;\n }\n getTotalECCodewords() {\n return this.ecCodewordsPerBlock * this.getNumBlocks();\n }\n getECBlocks() {\n return this.ecBlocks;\n }\n }\n\n /**\n *

Encapsulates the parameters for one error-correction block in one symbol version.\n * This includes the number of data codewords, and the number of times a block with these\n * parameters is used consecutively in the QR code version's format.

\n */\n class ECB$1 {\n constructor(count /*int*/, dataCodewords /*int*/) {\n this.count = count;\n this.dataCodewords = dataCodewords;\n }\n getCount() {\n return this.count;\n }\n getDataCodewords() {\n return this.dataCodewords;\n }\n }\n\n /*\n * Copyright 2007 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n /**\n * See ISO 18004:2006 Annex D\n *\n * @author Sean Owen\n */\n class Version$1 {\n constructor(versionNumber /*int*/, alignmentPatternCenters, ...ecBlocks) {\n this.versionNumber = versionNumber;\n this.alignmentPatternCenters = alignmentPatternCenters;\n this.ecBlocks = ecBlocks;\n let total = 0;\n const ecCodewords = ecBlocks[0].getECCodewordsPerBlock();\n const ecbArray = ecBlocks[0].getECBlocks();\n for (const ecBlock of ecbArray) {\n total += ecBlock.getCount() * (ecBlock.getDataCodewords() + ecCodewords);\n }\n this.totalCodewords = total;\n }\n getVersionNumber() {\n return this.versionNumber;\n }\n getAlignmentPatternCenters() {\n return this.alignmentPatternCenters;\n }\n getTotalCodewords() {\n return this.totalCodewords;\n }\n getDimensionForVersion() {\n return 17 + 4 * this.versionNumber;\n }\n getECBlocksForLevel(ecLevel) {\n return this.ecBlocks[ecLevel.getValue()];\n // TYPESCRIPTPORT: original was using ordinal, and using the order of levels as defined in ErrorCorrectionLevel enum (LMQH)\n // I will use the direct value from ErrorCorrectionLevelValues enum which in typescript goes to a number\n }\n /**\n *

Deduces version information purely from QR Code dimensions.

\n *\n * @param dimension dimension in modules\n * @return Version for a QR Code of that dimension\n * @throws FormatException if dimension is not 1 mod 4\n */\n static getProvisionalVersionForDimension(dimension /*int*/) {\n if (dimension % 4 !== 1) {\n throw new FormatException();\n }\n try {\n return this.getVersionForNumber((dimension - 17) / 4);\n }\n catch (ignored /*: IllegalArgumentException*/) {\n throw new FormatException();\n }\n }\n static getVersionForNumber(versionNumber /*int*/) {\n if (versionNumber < 1 || versionNumber > 40) {\n throw new IllegalArgumentException();\n }\n return Version$1.VERSIONS[versionNumber - 1];\n }\n static decodeVersionInformation(versionBits /*int*/) {\n let bestDifference = Number.MAX_SAFE_INTEGER;\n let bestVersion = 0;\n for (let i = 0; i < Version$1.VERSION_DECODE_INFO.length; i++) {\n const targetVersion = Version$1.VERSION_DECODE_INFO[i];\n // Do the version info bits match exactly? done.\n if (targetVersion === versionBits) {\n return Version$1.getVersionForNumber(i + 7);\n }\n // Otherwise see if this is the closest to a real version info bit string\n // we have seen so far\n const bitsDifference = FormatInformation.numBitsDiffering(versionBits, targetVersion);\n if (bitsDifference < bestDifference) {\n bestVersion = i + 7;\n bestDifference = bitsDifference;\n }\n }\n // We can tolerate up to 3 bits of error since no two version info codewords will\n // differ in less than 8 bits.\n if (bestDifference <= 3) {\n return Version$1.getVersionForNumber(bestVersion);\n }\n // If we didn't find a close enough match, fail\n return null;\n }\n /**\n * See ISO 18004:2006 Annex E\n */\n buildFunctionPattern() {\n const dimension = this.getDimensionForVersion();\n const bitMatrix = new BitMatrix(dimension);\n // Top left finder pattern + separator + format\n bitMatrix.setRegion(0, 0, 9, 9);\n // Top right finder pattern + separator + format\n bitMatrix.setRegion(dimension - 8, 0, 8, 9);\n // Bottom left finder pattern + separator + format\n bitMatrix.setRegion(0, dimension - 8, 9, 8);\n // Alignment patterns\n const max = this.alignmentPatternCenters.length;\n for (let x = 0; x < max; x++) {\n const i = this.alignmentPatternCenters[x] - 2;\n for (let y = 0; y < max; y++) {\n if ((x === 0 && (y === 0 || y === max - 1)) || (x === max - 1 && y === 0)) {\n // No alignment patterns near the three finder patterns\n continue;\n }\n bitMatrix.setRegion(this.alignmentPatternCenters[y] - 2, i, 5, 5);\n }\n }\n // Vertical timing pattern\n bitMatrix.setRegion(6, 9, 1, dimension - 17);\n // Horizontal timing pattern\n bitMatrix.setRegion(9, 6, dimension - 17, 1);\n if (this.versionNumber > 6) {\n // Version info, top right\n bitMatrix.setRegion(dimension - 11, 0, 3, 6);\n // Version info, bottom left\n bitMatrix.setRegion(0, dimension - 11, 6, 3);\n }\n return bitMatrix;\n }\n /*@Override*/\n toString() {\n return '' + this.versionNumber;\n }\n }\n /**\n * See ISO 18004:2006 Annex D.\n * Element i represents the raw version bits that specify version i + 7\n */\n Version$1.VERSION_DECODE_INFO = Int32Array.from([\n 0x07C94, 0x085BC, 0x09A99, 0x0A4D3, 0x0BBF6,\n 0x0C762, 0x0D847, 0x0E60D, 0x0F928, 0x10B78,\n 0x1145D, 0x12A17, 0x13532, 0x149A6, 0x15683,\n 0x168C9, 0x177EC, 0x18EC4, 0x191E1, 0x1AFAB,\n 0x1B08E, 0x1CC1A, 0x1D33F, 0x1ED75, 0x1F250,\n 0x209D5, 0x216F0, 0x228BA, 0x2379F, 0x24B0B,\n 0x2542E, 0x26A64, 0x27541, 0x28C69\n ]);\n /**\n * See ISO 18004:2006 6.5.1 Table 9\n */\n Version$1.VERSIONS = [\n new Version$1(1, new Int32Array(0), new ECBlocks$1(7, new ECB$1(1, 19)), new ECBlocks$1(10, new ECB$1(1, 16)), new ECBlocks$1(13, new ECB$1(1, 13)), new ECBlocks$1(17, new ECB$1(1, 9))),\n new Version$1(2, Int32Array.from([6, 18]), new ECBlocks$1(10, new ECB$1(1, 34)), new ECBlocks$1(16, new ECB$1(1, 28)), new ECBlocks$1(22, new ECB$1(1, 22)), new ECBlocks$1(28, new ECB$1(1, 16))),\n new Version$1(3, Int32Array.from([6, 22]), new ECBlocks$1(15, new ECB$1(1, 55)), new ECBlocks$1(26, new ECB$1(1, 44)), new ECBlocks$1(18, new ECB$1(2, 17)), new ECBlocks$1(22, new ECB$1(2, 13))),\n new Version$1(4, Int32Array.from([6, 26]), new ECBlocks$1(20, new ECB$1(1, 80)), new ECBlocks$1(18, new ECB$1(2, 32)), new ECBlocks$1(26, new ECB$1(2, 24)), new ECBlocks$1(16, new ECB$1(4, 9))),\n new Version$1(5, Int32Array.from([6, 30]), new ECBlocks$1(26, new ECB$1(1, 108)), new ECBlocks$1(24, new ECB$1(2, 43)), new ECBlocks$1(18, new ECB$1(2, 15), new ECB$1(2, 16)), new ECBlocks$1(22, new ECB$1(2, 11), new ECB$1(2, 12))),\n new Version$1(6, Int32Array.from([6, 34]), new ECBlocks$1(18, new ECB$1(2, 68)), new ECBlocks$1(16, new ECB$1(4, 27)), new ECBlocks$1(24, new ECB$1(4, 19)), new ECBlocks$1(28, new ECB$1(4, 15))),\n new Version$1(7, Int32Array.from([6, 22, 38]), new ECBlocks$1(20, new ECB$1(2, 78)), new ECBlocks$1(18, new ECB$1(4, 31)), new ECBlocks$1(18, new ECB$1(2, 14), new ECB$1(4, 15)), new ECBlocks$1(26, new ECB$1(4, 13), new ECB$1(1, 14))),\n new Version$1(8, Int32Array.from([6, 24, 42]), new ECBlocks$1(24, new ECB$1(2, 97)), new ECBlocks$1(22, new ECB$1(2, 38), new ECB$1(2, 39)), new ECBlocks$1(22, new ECB$1(4, 18), new ECB$1(2, 19)), new ECBlocks$1(26, new ECB$1(4, 14), new ECB$1(2, 15))),\n new Version$1(9, Int32Array.from([6, 26, 46]), new ECBlocks$1(30, new ECB$1(2, 116)), new ECBlocks$1(22, new ECB$1(3, 36), new ECB$1(2, 37)), new ECBlocks$1(20, new ECB$1(4, 16), new ECB$1(4, 17)), new ECBlocks$1(24, new ECB$1(4, 12), new ECB$1(4, 13))),\n new Version$1(10, Int32Array.from([6, 28, 50]), new ECBlocks$1(18, new ECB$1(2, 68), new ECB$1(2, 69)), new ECBlocks$1(26, new ECB$1(4, 43), new ECB$1(1, 44)), new ECBlocks$1(24, new ECB$1(6, 19), new ECB$1(2, 20)), new ECBlocks$1(28, new ECB$1(6, 15), new ECB$1(2, 16))),\n new Version$1(11, Int32Array.from([6, 30, 54]), new ECBlocks$1(20, new ECB$1(4, 81)), new ECBlocks$1(30, new ECB$1(1, 50), new ECB$1(4, 51)), new ECBlocks$1(28, new ECB$1(4, 22), new ECB$1(4, 23)), new ECBlocks$1(24, new ECB$1(3, 12), new ECB$1(8, 13))),\n new Version$1(12, Int32Array.from([6, 32, 58]), new ECBlocks$1(24, new ECB$1(2, 92), new ECB$1(2, 93)), new ECBlocks$1(22, new ECB$1(6, 36), new ECB$1(2, 37)), new ECBlocks$1(26, new ECB$1(4, 20), new ECB$1(6, 21)), new ECBlocks$1(28, new ECB$1(7, 14), new ECB$1(4, 15))),\n new Version$1(13, Int32Array.from([6, 34, 62]), new ECBlocks$1(26, new ECB$1(4, 107)), new ECBlocks$1(22, new ECB$1(8, 37), new ECB$1(1, 38)), new ECBlocks$1(24, new ECB$1(8, 20), new ECB$1(4, 21)), new ECBlocks$1(22, new ECB$1(12, 11), new ECB$1(4, 12))),\n new Version$1(14, Int32Array.from([6, 26, 46, 66]), new ECBlocks$1(30, new ECB$1(3, 115), new ECB$1(1, 116)), new ECBlocks$1(24, new ECB$1(4, 40), new ECB$1(5, 41)), new ECBlocks$1(20, new ECB$1(11, 16), new ECB$1(5, 17)), new ECBlocks$1(24, new ECB$1(11, 12), new ECB$1(5, 13))),\n new Version$1(15, Int32Array.from([6, 26, 48, 70]), new ECBlocks$1(22, new ECB$1(5, 87), new ECB$1(1, 88)), new ECBlocks$1(24, new ECB$1(5, 41), new ECB$1(5, 42)), new ECBlocks$1(30, new ECB$1(5, 24), new ECB$1(7, 25)), new ECBlocks$1(24, new ECB$1(11, 12), new ECB$1(7, 13))),\n new Version$1(16, Int32Array.from([6, 26, 50, 74]), new ECBlocks$1(24, new ECB$1(5, 98), new ECB$1(1, 99)), new ECBlocks$1(28, new ECB$1(7, 45), new ECB$1(3, 46)), new ECBlocks$1(24, new ECB$1(15, 19), new ECB$1(2, 20)), new ECBlocks$1(30, new ECB$1(3, 15), new ECB$1(13, 16))),\n new Version$1(17, Int32Array.from([6, 30, 54, 78]), new ECBlocks$1(28, new ECB$1(1, 107), new ECB$1(5, 108)), new ECBlocks$1(28, new ECB$1(10, 46), new ECB$1(1, 47)), new ECBlocks$1(28, new ECB$1(1, 22), new ECB$1(15, 23)), new ECBlocks$1(28, new ECB$1(2, 14), new ECB$1(17, 15))),\n new Version$1(18, Int32Array.from([6, 30, 56, 82]), new ECBlocks$1(30, new ECB$1(5, 120), new ECB$1(1, 121)), new ECBlocks$1(26, new ECB$1(9, 43), new ECB$1(4, 44)), new ECBlocks$1(28, new ECB$1(17, 22), new ECB$1(1, 23)), new ECBlocks$1(28, new ECB$1(2, 14), new ECB$1(19, 15))),\n new Version$1(19, Int32Array.from([6, 30, 58, 86]), new ECBlocks$1(28, new ECB$1(3, 113), new ECB$1(4, 114)), new ECBlocks$1(26, new ECB$1(3, 44), new ECB$1(11, 45)), new ECBlocks$1(26, new ECB$1(17, 21), new ECB$1(4, 22)), new ECBlocks$1(26, new ECB$1(9, 13), new ECB$1(16, 14))),\n new Version$1(20, Int32Array.from([6, 34, 62, 90]), new ECBlocks$1(28, new ECB$1(3, 107), new ECB$1(5, 108)), new ECBlocks$1(26, new ECB$1(3, 41), new ECB$1(13, 42)), new ECBlocks$1(30, new ECB$1(15, 24), new ECB$1(5, 25)), new ECBlocks$1(28, new ECB$1(15, 15), new ECB$1(10, 16))),\n new Version$1(21, Int32Array.from([6, 28, 50, 72, 94]), new ECBlocks$1(28, new ECB$1(4, 116), new ECB$1(4, 117)), new ECBlocks$1(26, new ECB$1(17, 42)), new ECBlocks$1(28, new ECB$1(17, 22), new ECB$1(6, 23)), new ECBlocks$1(30, new ECB$1(19, 16), new ECB$1(6, 17))),\n new Version$1(22, Int32Array.from([6, 26, 50, 74, 98]), new ECBlocks$1(28, new ECB$1(2, 111), new ECB$1(7, 112)), new ECBlocks$1(28, new ECB$1(17, 46)), new ECBlocks$1(30, new ECB$1(7, 24), new ECB$1(16, 25)), new ECBlocks$1(24, new ECB$1(34, 13))),\n new Version$1(23, Int32Array.from([6, 30, 54, 78, 102]), new ECBlocks$1(30, new ECB$1(4, 121), new ECB$1(5, 122)), new ECBlocks$1(28, new ECB$1(4, 47), new ECB$1(14, 48)), new ECBlocks$1(30, new ECB$1(11, 24), new ECB$1(14, 25)), new ECBlocks$1(30, new ECB$1(16, 15), new ECB$1(14, 16))),\n new Version$1(24, Int32Array.from([6, 28, 54, 80, 106]), new ECBlocks$1(30, new ECB$1(6, 117), new ECB$1(4, 118)), new ECBlocks$1(28, new ECB$1(6, 45), new ECB$1(14, 46)), new ECBlocks$1(30, new ECB$1(11, 24), new ECB$1(16, 25)), new ECBlocks$1(30, new ECB$1(30, 16), new ECB$1(2, 17))),\n new Version$1(25, Int32Array.from([6, 32, 58, 84, 110]), new ECBlocks$1(26, new ECB$1(8, 106), new ECB$1(4, 107)), new ECBlocks$1(28, new ECB$1(8, 47), new ECB$1(13, 48)), new ECBlocks$1(30, new ECB$1(7, 24), new ECB$1(22, 25)), new ECBlocks$1(30, new ECB$1(22, 15), new ECB$1(13, 16))),\n new Version$1(26, Int32Array.from([6, 30, 58, 86, 114]), new ECBlocks$1(28, new ECB$1(10, 114), new ECB$1(2, 115)), new ECBlocks$1(28, new ECB$1(19, 46), new ECB$1(4, 47)), new ECBlocks$1(28, new ECB$1(28, 22), new ECB$1(6, 23)), new ECBlocks$1(30, new ECB$1(33, 16), new ECB$1(4, 17))),\n new Version$1(27, Int32Array.from([6, 34, 62, 90, 118]), new ECBlocks$1(30, new ECB$1(8, 122), new ECB$1(4, 123)), new ECBlocks$1(28, new ECB$1(22, 45), new ECB$1(3, 46)), new ECBlocks$1(30, new ECB$1(8, 23), new ECB$1(26, 24)), new ECBlocks$1(30, new ECB$1(12, 15), new ECB$1(28, 16))),\n new Version$1(28, Int32Array.from([6, 26, 50, 74, 98, 122]), new ECBlocks$1(30, new ECB$1(3, 117), new ECB$1(10, 118)), new ECBlocks$1(28, new ECB$1(3, 45), new ECB$1(23, 46)), new ECBlocks$1(30, new ECB$1(4, 24), new ECB$1(31, 25)), new ECBlocks$1(30, new ECB$1(11, 15), new ECB$1(31, 16))),\n new Version$1(29, Int32Array.from([6, 30, 54, 78, 102, 126]), new ECBlocks$1(30, new ECB$1(7, 116), new ECB$1(7, 117)), new ECBlocks$1(28, new ECB$1(21, 45), new ECB$1(7, 46)), new ECBlocks$1(30, new ECB$1(1, 23), new ECB$1(37, 24)), new ECBlocks$1(30, new ECB$1(19, 15), new ECB$1(26, 16))),\n new Version$1(30, Int32Array.from([6, 26, 52, 78, 104, 130]), new ECBlocks$1(30, new ECB$1(5, 115), new ECB$1(10, 116)), new ECBlocks$1(28, new ECB$1(19, 47), new ECB$1(10, 48)), new ECBlocks$1(30, new ECB$1(15, 24), new ECB$1(25, 25)), new ECBlocks$1(30, new ECB$1(23, 15), new ECB$1(25, 16))),\n new Version$1(31, Int32Array.from([6, 30, 56, 82, 108, 134]), new ECBlocks$1(30, new ECB$1(13, 115), new ECB$1(3, 116)), new ECBlocks$1(28, new ECB$1(2, 46), new ECB$1(29, 47)), new ECBlocks$1(30, new ECB$1(42, 24), new ECB$1(1, 25)), new ECBlocks$1(30, new ECB$1(23, 15), new ECB$1(28, 16))),\n new Version$1(32, Int32Array.from([6, 34, 60, 86, 112, 138]), new ECBlocks$1(30, new ECB$1(17, 115)), new ECBlocks$1(28, new ECB$1(10, 46), new ECB$1(23, 47)), new ECBlocks$1(30, new ECB$1(10, 24), new ECB$1(35, 25)), new ECBlocks$1(30, new ECB$1(19, 15), new ECB$1(35, 16))),\n new Version$1(33, Int32Array.from([6, 30, 58, 86, 114, 142]), new ECBlocks$1(30, new ECB$1(17, 115), new ECB$1(1, 116)), new ECBlocks$1(28, new ECB$1(14, 46), new ECB$1(21, 47)), new ECBlocks$1(30, new ECB$1(29, 24), new ECB$1(19, 25)), new ECBlocks$1(30, new ECB$1(11, 15), new ECB$1(46, 16))),\n new Version$1(34, Int32Array.from([6, 34, 62, 90, 118, 146]), new ECBlocks$1(30, new ECB$1(13, 115), new ECB$1(6, 116)), new ECBlocks$1(28, new ECB$1(14, 46), new ECB$1(23, 47)), new ECBlocks$1(30, new ECB$1(44, 24), new ECB$1(7, 25)), new ECBlocks$1(30, new ECB$1(59, 16), new ECB$1(1, 17))),\n new Version$1(35, Int32Array.from([6, 30, 54, 78, 102, 126, 150]), new ECBlocks$1(30, new ECB$1(12, 121), new ECB$1(7, 122)), new ECBlocks$1(28, new ECB$1(12, 47), new ECB$1(26, 48)), new ECBlocks$1(30, new ECB$1(39, 24), new ECB$1(14, 25)), new ECBlocks$1(30, new ECB$1(22, 15), new ECB$1(41, 16))),\n new Version$1(36, Int32Array.from([6, 24, 50, 76, 102, 128, 154]), new ECBlocks$1(30, new ECB$1(6, 121), new ECB$1(14, 122)), new ECBlocks$1(28, new ECB$1(6, 47), new ECB$1(34, 48)), new ECBlocks$1(30, new ECB$1(46, 24), new ECB$1(10, 25)), new ECBlocks$1(30, new ECB$1(2, 15), new ECB$1(64, 16))),\n new Version$1(37, Int32Array.from([6, 28, 54, 80, 106, 132, 158]), new ECBlocks$1(30, new ECB$1(17, 122), new ECB$1(4, 123)), new ECBlocks$1(28, new ECB$1(29, 46), new ECB$1(14, 47)), new ECBlocks$1(30, new ECB$1(49, 24), new ECB$1(10, 25)), new ECBlocks$1(30, new ECB$1(24, 15), new ECB$1(46, 16))),\n new Version$1(38, Int32Array.from([6, 32, 58, 84, 110, 136, 162]), new ECBlocks$1(30, new ECB$1(4, 122), new ECB$1(18, 123)), new ECBlocks$1(28, new ECB$1(13, 46), new ECB$1(32, 47)), new ECBlocks$1(30, new ECB$1(48, 24), new ECB$1(14, 25)), new ECBlocks$1(30, new ECB$1(42, 15), new ECB$1(32, 16))),\n new Version$1(39, Int32Array.from([6, 26, 54, 82, 110, 138, 166]), new ECBlocks$1(30, new ECB$1(20, 117), new ECB$1(4, 118)), new ECBlocks$1(28, new ECB$1(40, 47), new ECB$1(7, 48)), new ECBlocks$1(30, new ECB$1(43, 24), new ECB$1(22, 25)), new ECBlocks$1(30, new ECB$1(10, 15), new ECB$1(67, 16))),\n new Version$1(40, Int32Array.from([6, 30, 58, 86, 114, 142, 170]), new ECBlocks$1(30, new ECB$1(19, 118), new ECB$1(6, 119)), new ECBlocks$1(28, new ECB$1(18, 47), new ECB$1(31, 48)), new ECBlocks$1(30, new ECB$1(34, 24), new ECB$1(34, 25)), new ECBlocks$1(30, new ECB$1(20, 15), new ECB$1(61, 16)))\n ];\n\n /*\n * Copyright 2007 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n var DataMaskValues;\n (function (DataMaskValues) {\n DataMaskValues[DataMaskValues[\"DATA_MASK_000\"] = 0] = \"DATA_MASK_000\";\n DataMaskValues[DataMaskValues[\"DATA_MASK_001\"] = 1] = \"DATA_MASK_001\";\n DataMaskValues[DataMaskValues[\"DATA_MASK_010\"] = 2] = \"DATA_MASK_010\";\n DataMaskValues[DataMaskValues[\"DATA_MASK_011\"] = 3] = \"DATA_MASK_011\";\n DataMaskValues[DataMaskValues[\"DATA_MASK_100\"] = 4] = \"DATA_MASK_100\";\n DataMaskValues[DataMaskValues[\"DATA_MASK_101\"] = 5] = \"DATA_MASK_101\";\n DataMaskValues[DataMaskValues[\"DATA_MASK_110\"] = 6] = \"DATA_MASK_110\";\n DataMaskValues[DataMaskValues[\"DATA_MASK_111\"] = 7] = \"DATA_MASK_111\";\n })(DataMaskValues || (DataMaskValues = {}));\n /**\n *

Encapsulates data masks for the data bits in a QR code, per ISO 18004:2006 6.8. Implementations\n * of this class can un-mask a raw BitMatrix. For simplicity, they will unmask the entire BitMatrix,\n * including areas used for finder patterns, timing patterns, etc. These areas should be unused\n * after the point they are unmasked anyway.

\n *\n *

Note that the diagram in section 6.8.1 is misleading since it indicates that i is column position\n * and j is row position. In fact, as the text says, i is row position and j is column position.

\n *\n * @author Sean Owen\n */\n class DataMask {\n // See ISO 18004:2006 6.8.1\n constructor(value, isMasked) {\n this.value = value;\n this.isMasked = isMasked;\n }\n // End of enum constants.\n /**\n *

Implementations of this method reverse the data masking process applied to a QR Code and\n * make its bits ready to read.

\n *\n * @param bits representation of QR Code bits\n * @param dimension dimension of QR Code, represented by bits, being unmasked\n */\n unmaskBitMatrix(bits, dimension /*int*/) {\n for (let i = 0; i < dimension; i++) {\n for (let j = 0; j < dimension; j++) {\n if (this.isMasked(i, j)) {\n bits.flip(j, i);\n }\n }\n }\n }\n }\n DataMask.values = new Map([\n /**\n * 000: mask bits for which (x + y) mod 2 == 0\n */\n [DataMaskValues.DATA_MASK_000, new DataMask(DataMaskValues.DATA_MASK_000, (i /*int*/, j /*int*/) => { return ((i + j) & 0x01) === 0; })],\n /**\n * 001: mask bits for which x mod 2 == 0\n */\n [DataMaskValues.DATA_MASK_001, new DataMask(DataMaskValues.DATA_MASK_001, (i /*int*/, j /*int*/) => { return (i & 0x01) === 0; })],\n /**\n * 010: mask bits for which y mod 3 == 0\n */\n [DataMaskValues.DATA_MASK_010, new DataMask(DataMaskValues.DATA_MASK_010, (i /*int*/, j /*int*/) => { return j % 3 === 0; })],\n /**\n * 011: mask bits for which (x + y) mod 3 == 0\n */\n [DataMaskValues.DATA_MASK_011, new DataMask(DataMaskValues.DATA_MASK_011, (i /*int*/, j /*int*/) => { return (i + j) % 3 === 0; })],\n /**\n * 100: mask bits for which (x/2 + y/3) mod 2 == 0\n */\n [DataMaskValues.DATA_MASK_100, new DataMask(DataMaskValues.DATA_MASK_100, (i /*int*/, j /*int*/) => { return ((Math.floor(i / 2) + Math.floor(j / 3)) & 0x01) === 0; })],\n /**\n * 101: mask bits for which xy mod 2 + xy mod 3 == 0\n * equivalently, such that xy mod 6 == 0\n */\n [DataMaskValues.DATA_MASK_101, new DataMask(DataMaskValues.DATA_MASK_101, (i /*int*/, j /*int*/) => { return (i * j) % 6 === 0; })],\n /**\n * 110: mask bits for which (xy mod 2 + xy mod 3) mod 2 == 0\n * equivalently, such that xy mod 6 < 3\n */\n [DataMaskValues.DATA_MASK_110, new DataMask(DataMaskValues.DATA_MASK_110, (i /*int*/, j /*int*/) => { return ((i * j) % 6) < 3; })],\n /**\n * 111: mask bits for which ((x+y)mod 2 + xy mod 3) mod 2 == 0\n * equivalently, such that (x + y + xy mod 3) mod 2 == 0\n */\n [DataMaskValues.DATA_MASK_111, new DataMask(DataMaskValues.DATA_MASK_111, (i /*int*/, j /*int*/) => { return ((i + j + ((i * j) % 3)) & 0x01) === 0; })],\n ]);\n\n /*\n * Copyright 2007 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n /**\n * @author Sean Owen\n */\n class BitMatrixParser$1 {\n /**\n * @param bitMatrix {@link BitMatrix} to parse\n * @throws FormatException if dimension is not >= 21 and 1 mod 4\n */\n constructor(bitMatrix) {\n const dimension = bitMatrix.getHeight();\n if (dimension < 21 || (dimension & 0x03) !== 1) {\n throw new FormatException();\n }\n this.bitMatrix = bitMatrix;\n }\n /**\n *

Reads format information from one of its two locations within the QR Code.

\n *\n * @return {@link FormatInformation} encapsulating the QR Code's format info\n * @throws FormatException if both format information locations cannot be parsed as\n * the valid encoding of format information\n */\n readFormatInformation() {\n if (this.parsedFormatInfo !== null && this.parsedFormatInfo !== undefined) {\n return this.parsedFormatInfo;\n }\n // Read top-left format info bits\n let formatInfoBits1 = 0;\n for (let i = 0; i < 6; i++) {\n formatInfoBits1 = this.copyBit(i, 8, formatInfoBits1);\n }\n // .. and skip a bit in the timing pattern ...\n formatInfoBits1 = this.copyBit(7, 8, formatInfoBits1);\n formatInfoBits1 = this.copyBit(8, 8, formatInfoBits1);\n formatInfoBits1 = this.copyBit(8, 7, formatInfoBits1);\n // .. and skip a bit in the timing pattern ...\n for (let j = 5; j >= 0; j--) {\n formatInfoBits1 = this.copyBit(8, j, formatInfoBits1);\n }\n // Read the top-right/bottom-left pattern too\n const dimension = this.bitMatrix.getHeight();\n let formatInfoBits2 = 0;\n const jMin = dimension - 7;\n for (let j = dimension - 1; j >= jMin; j--) {\n formatInfoBits2 = this.copyBit(8, j, formatInfoBits2);\n }\n for (let i = dimension - 8; i < dimension; i++) {\n formatInfoBits2 = this.copyBit(i, 8, formatInfoBits2);\n }\n this.parsedFormatInfo = FormatInformation.decodeFormatInformation(formatInfoBits1, formatInfoBits2);\n if (this.parsedFormatInfo !== null) {\n return this.parsedFormatInfo;\n }\n throw new FormatException();\n }\n /**\n *

Reads version information from one of its two locations within the QR Code.

\n *\n * @return {@link Version} encapsulating the QR Code's version\n * @throws FormatException if both version information locations cannot be parsed as\n * the valid encoding of version information\n */\n readVersion() {\n if (this.parsedVersion !== null && this.parsedVersion !== undefined) {\n return this.parsedVersion;\n }\n const dimension = this.bitMatrix.getHeight();\n const provisionalVersion = Math.floor((dimension - 17) / 4);\n if (provisionalVersion <= 6) {\n return Version$1.getVersionForNumber(provisionalVersion);\n }\n // Read top-right version info: 3 wide by 6 tall\n let versionBits = 0;\n const ijMin = dimension - 11;\n for (let j = 5; j >= 0; j--) {\n for (let i = dimension - 9; i >= ijMin; i--) {\n versionBits = this.copyBit(i, j, versionBits);\n }\n }\n let theParsedVersion = Version$1.decodeVersionInformation(versionBits);\n if (theParsedVersion !== null && theParsedVersion.getDimensionForVersion() === dimension) {\n this.parsedVersion = theParsedVersion;\n return theParsedVersion;\n }\n // Hmm, failed. Try bottom left: 6 wide by 3 tall\n versionBits = 0;\n for (let i = 5; i >= 0; i--) {\n for (let j = dimension - 9; j >= ijMin; j--) {\n versionBits = this.copyBit(i, j, versionBits);\n }\n }\n theParsedVersion = Version$1.decodeVersionInformation(versionBits);\n if (theParsedVersion !== null && theParsedVersion.getDimensionForVersion() === dimension) {\n this.parsedVersion = theParsedVersion;\n return theParsedVersion;\n }\n throw new FormatException();\n }\n copyBit(i /*int*/, j /*int*/, versionBits /*int*/) {\n const bit = this.isMirror ? this.bitMatrix.get(j, i) : this.bitMatrix.get(i, j);\n return bit ? (versionBits << 1) | 0x1 : versionBits << 1;\n }\n /**\n *

Reads the bits in the {@link BitMatrix} representing the finder pattern in the\n * correct order in order to reconstruct the codewords bytes contained within the\n * QR Code.

\n *\n * @return bytes encoded within the QR Code\n * @throws FormatException if the exact number of bytes expected is not read\n */\n readCodewords() {\n const formatInfo = this.readFormatInformation();\n const version = this.readVersion();\n // Get the data mask for the format used in this QR Code. This will exclude\n // some bits from reading as we wind through the bit matrix.\n const dataMask = DataMask.values.get(formatInfo.getDataMask());\n const dimension = this.bitMatrix.getHeight();\n dataMask.unmaskBitMatrix(this.bitMatrix, dimension);\n const functionPattern = version.buildFunctionPattern();\n let readingUp = true;\n const result = new Uint8Array(version.getTotalCodewords());\n let resultOffset = 0;\n let currentByte = 0;\n let bitsRead = 0;\n // Read columns in pairs, from right to left\n for (let j = dimension - 1; j > 0; j -= 2) {\n if (j === 6) {\n // Skip whole column with vertical alignment pattern\n // saves time and makes the other code proceed more cleanly\n j--;\n }\n // Read alternatingly from bottom to top then top to bottom\n for (let count = 0; count < dimension; count++) {\n const i = readingUp ? dimension - 1 - count : count;\n for (let col = 0; col < 2; col++) {\n // Ignore bits covered by the function pattern\n if (!functionPattern.get(j - col, i)) {\n // Read a bit\n bitsRead++;\n currentByte <<= 1;\n if (this.bitMatrix.get(j - col, i)) {\n currentByte |= 1;\n }\n // If we've made a whole byte, save it off\n if (bitsRead === 8) {\n result[resultOffset++] = /*(byte) */ currentByte;\n bitsRead = 0;\n currentByte = 0;\n }\n }\n }\n }\n readingUp = !readingUp; // readingUp ^= true; // readingUp = !readingUp; // switch directions\n }\n if (resultOffset !== version.getTotalCodewords()) {\n throw new FormatException();\n }\n return result;\n }\n /**\n * Revert the mask removal done while reading the code words. The bit matrix should revert to its original state.\n */\n remask() {\n if (this.parsedFormatInfo === null) {\n return; // We have no format information, and have no data mask\n }\n const dataMask = DataMask.values[this.parsedFormatInfo.getDataMask()];\n const dimension = this.bitMatrix.getHeight();\n dataMask.unmaskBitMatrix(this.bitMatrix, dimension);\n }\n /**\n * Prepare the parser for a mirrored operation.\n * This flag has effect only on the {@link #readFormatInformation()} and the\n * {@link #readVersion()}. Before proceeding with {@link #readCodewords()} the\n * {@link #mirror()} method should be called.\n *\n * @param mirror Whether to read version and format information mirrored.\n */\n setMirror(isMirror) {\n this.parsedVersion = null;\n this.parsedFormatInfo = null;\n this.isMirror = isMirror;\n }\n /** Mirror the bit matrix in order to attempt a second reading. */\n mirror() {\n const bitMatrix = this.bitMatrix;\n for (let x = 0, width = bitMatrix.getWidth(); x < width; x++) {\n for (let y = x + 1, height = bitMatrix.getHeight(); y < height; y++) {\n if (bitMatrix.get(x, y) !== bitMatrix.get(y, x)) {\n bitMatrix.flip(y, x);\n bitMatrix.flip(x, y);\n }\n }\n }\n }\n }\n\n /*\n * Copyright 2007 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n /**\n *

Encapsulates a block of data within a QR Code. QR Codes may split their data into\n * multiple blocks, each of which is a unit of data and error-correction codewords. Each\n * is represented by an instance of this class.

\n *\n * @author Sean Owen\n */\n class DataBlock$1 {\n constructor(numDataCodewords /*int*/, codewords) {\n this.numDataCodewords = numDataCodewords;\n this.codewords = codewords;\n }\n /**\n *

When QR Codes use multiple data blocks, they are actually interleaved.\n * That is, the first byte of data block 1 to n is written, then the second bytes, and so on. This\n * method will separate the data into original blocks.

\n *\n * @param rawCodewords bytes as read directly from the QR Code\n * @param version version of the QR Code\n * @param ecLevel error-correction level of the QR Code\n * @return DataBlocks containing original bytes, \"de-interleaved\" from representation in the\n * QR Code\n */\n static getDataBlocks(rawCodewords, version, ecLevel) {\n if (rawCodewords.length !== version.getTotalCodewords()) {\n throw new IllegalArgumentException();\n }\n // Figure out the number and size of data blocks used by this version and\n // error correction level\n const ecBlocks = version.getECBlocksForLevel(ecLevel);\n // First count the total number of data blocks\n let totalBlocks = 0;\n const ecBlockArray = ecBlocks.getECBlocks();\n for (const ecBlock of ecBlockArray) {\n totalBlocks += ecBlock.getCount();\n }\n // Now establish DataBlocks of the appropriate size and number of data codewords\n const result = new Array(totalBlocks);\n let numResultBlocks = 0;\n for (const ecBlock of ecBlockArray) {\n for (let i = 0; i < ecBlock.getCount(); i++) {\n const numDataCodewords = ecBlock.getDataCodewords();\n const numBlockCodewords = ecBlocks.getECCodewordsPerBlock() + numDataCodewords;\n result[numResultBlocks++] = new DataBlock$1(numDataCodewords, new Uint8Array(numBlockCodewords));\n }\n }\n // All blocks have the same amount of data, except that the last n\n // (where n may be 0) have 1 more byte. Figure out where these start.\n const shorterBlocksTotalCodewords = result[0].codewords.length;\n let longerBlocksStartAt = result.length - 1;\n // TYPESCRIPTPORT: check length is correct here\n while (longerBlocksStartAt >= 0) {\n const numCodewords = result[longerBlocksStartAt].codewords.length;\n if (numCodewords === shorterBlocksTotalCodewords) {\n break;\n }\n longerBlocksStartAt--;\n }\n longerBlocksStartAt++;\n const shorterBlocksNumDataCodewords = shorterBlocksTotalCodewords - ecBlocks.getECCodewordsPerBlock();\n // The last elements of result may be 1 element longer\n // first fill out as many elements as all of them have\n let rawCodewordsOffset = 0;\n for (let i = 0; i < shorterBlocksNumDataCodewords; i++) {\n for (let j = 0; j < numResultBlocks; j++) {\n result[j].codewords[i] = rawCodewords[rawCodewordsOffset++];\n }\n }\n // Fill out the last data block in the longer ones\n for (let j = longerBlocksStartAt; j < numResultBlocks; j++) {\n result[j].codewords[shorterBlocksNumDataCodewords] = rawCodewords[rawCodewordsOffset++];\n }\n // Now add in error correction blocks\n const max = result[0].codewords.length;\n for (let i = shorterBlocksNumDataCodewords; i < max; i++) {\n for (let j = 0; j < numResultBlocks; j++) {\n const iOffset = j < longerBlocksStartAt ? i : i + 1;\n result[j].codewords[iOffset] = rawCodewords[rawCodewordsOffset++];\n }\n }\n return result;\n }\n getNumDataCodewords() {\n return this.numDataCodewords;\n }\n getCodewords() {\n return this.codewords;\n }\n }\n\n /*\n * Copyright 2007 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n var ModeValues;\n (function (ModeValues) {\n ModeValues[ModeValues[\"TERMINATOR\"] = 0] = \"TERMINATOR\";\n ModeValues[ModeValues[\"NUMERIC\"] = 1] = \"NUMERIC\";\n ModeValues[ModeValues[\"ALPHANUMERIC\"] = 2] = \"ALPHANUMERIC\";\n ModeValues[ModeValues[\"STRUCTURED_APPEND\"] = 3] = \"STRUCTURED_APPEND\";\n ModeValues[ModeValues[\"BYTE\"] = 4] = \"BYTE\";\n ModeValues[ModeValues[\"ECI\"] = 5] = \"ECI\";\n ModeValues[ModeValues[\"KANJI\"] = 6] = \"KANJI\";\n ModeValues[ModeValues[\"FNC1_FIRST_POSITION\"] = 7] = \"FNC1_FIRST_POSITION\";\n ModeValues[ModeValues[\"FNC1_SECOND_POSITION\"] = 8] = \"FNC1_SECOND_POSITION\";\n /** See GBT 18284-2000; \"Hanzi\" is a transliteration of this mode name. */\n ModeValues[ModeValues[\"HANZI\"] = 9] = \"HANZI\";\n })(ModeValues || (ModeValues = {}));\n /**\n *

See ISO 18004:2006, 6.4.1, Tables 2 and 3. This enum encapsulates the various modes in which\n * data can be encoded to bits in the QR code standard.

\n *\n * @author Sean Owen\n */\n class Mode$1 {\n constructor(value, stringValue, characterCountBitsForVersions, bits /*int*/) {\n this.value = value;\n this.stringValue = stringValue;\n this.characterCountBitsForVersions = characterCountBitsForVersions;\n this.bits = bits;\n Mode$1.FOR_BITS.set(bits, this);\n Mode$1.FOR_VALUE.set(value, this);\n }\n /**\n * @param bits four bits encoding a QR Code data mode\n * @return Mode encoded by these bits\n * @throws IllegalArgumentException if bits do not correspond to a known mode\n */\n static forBits(bits /*int*/) {\n const mode = Mode$1.FOR_BITS.get(bits);\n if (undefined === mode) {\n throw new IllegalArgumentException();\n }\n return mode;\n }\n /**\n * @param version version in question\n * @return number of bits used, in this QR Code symbol {@link Version}, to encode the\n * count of characters that will follow encoded in this Mode\n */\n getCharacterCountBits(version) {\n const versionNumber = version.getVersionNumber();\n let offset;\n if (versionNumber <= 9) {\n offset = 0;\n }\n else if (versionNumber <= 26) {\n offset = 1;\n }\n else {\n offset = 2;\n }\n return this.characterCountBitsForVersions[offset];\n }\n getValue() {\n return this.value;\n }\n getBits() {\n return this.bits;\n }\n equals(o) {\n if (!(o instanceof Mode$1)) {\n return false;\n }\n const other = o;\n return this.value === other.value;\n }\n toString() {\n return this.stringValue;\n }\n }\n Mode$1.FOR_BITS = new Map();\n Mode$1.FOR_VALUE = new Map();\n Mode$1.TERMINATOR = new Mode$1(ModeValues.TERMINATOR, 'TERMINATOR', Int32Array.from([0, 0, 0]), 0x00); // Not really a mode...\n Mode$1.NUMERIC = new Mode$1(ModeValues.NUMERIC, 'NUMERIC', Int32Array.from([10, 12, 14]), 0x01);\n Mode$1.ALPHANUMERIC = new Mode$1(ModeValues.ALPHANUMERIC, 'ALPHANUMERIC', Int32Array.from([9, 11, 13]), 0x02);\n Mode$1.STRUCTURED_APPEND = new Mode$1(ModeValues.STRUCTURED_APPEND, 'STRUCTURED_APPEND', Int32Array.from([0, 0, 0]), 0x03); // Not supported\n Mode$1.BYTE = new Mode$1(ModeValues.BYTE, 'BYTE', Int32Array.from([8, 16, 16]), 0x04);\n Mode$1.ECI = new Mode$1(ModeValues.ECI, 'ECI', Int32Array.from([0, 0, 0]), 0x07); // character counts don't apply\n Mode$1.KANJI = new Mode$1(ModeValues.KANJI, 'KANJI', Int32Array.from([8, 10, 12]), 0x08);\n Mode$1.FNC1_FIRST_POSITION = new Mode$1(ModeValues.FNC1_FIRST_POSITION, 'FNC1_FIRST_POSITION', Int32Array.from([0, 0, 0]), 0x05);\n Mode$1.FNC1_SECOND_POSITION = new Mode$1(ModeValues.FNC1_SECOND_POSITION, 'FNC1_SECOND_POSITION', Int32Array.from([0, 0, 0]), 0x09);\n /** See GBT 18284-2000; \"Hanzi\" is a transliteration of this mode name. */\n Mode$1.HANZI = new Mode$1(ModeValues.HANZI, 'HANZI', Int32Array.from([8, 10, 12]), 0x0D);\n\n /*\n * Copyright 2007 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n /*import java.io.UnsupportedEncodingException;*/\n /*import java.util.ArrayList;*/\n /*import java.util.Collection;*/\n /*import java.util.List;*/\n /*import java.util.Map;*/\n /**\n *

QR Codes can encode text as bits in one of several modes, and can use multiple modes\n * in one QR Code. This class decodes the bits back into text.

\n *\n *

See ISO 18004:2006, 6.4.3 - 6.4.7

\n *\n * @author Sean Owen\n */\n class DecodedBitStreamParser$1 {\n static decode(bytes, version, ecLevel, hints) {\n const bits = new BitSource(bytes);\n let result = new StringBuilder();\n const byteSegments = new Array(); // 1\n // TYPESCRIPTPORT: I do not use constructor with size 1 as in original Java means capacity and the array length is checked below\n let symbolSequence = -1;\n let parityData = -1;\n try {\n let currentCharacterSetECI = null;\n let fc1InEffect = false;\n let mode;\n do {\n // While still another segment to read...\n if (bits.available() < 4) {\n // OK, assume we're done. Really, a TERMINATOR mode should have been recorded here\n mode = Mode$1.TERMINATOR;\n }\n else {\n const modeBits = bits.readBits(4);\n mode = Mode$1.forBits(modeBits); // mode is encoded by 4 bits\n }\n switch (mode) {\n case Mode$1.TERMINATOR:\n break;\n case Mode$1.FNC1_FIRST_POSITION:\n case Mode$1.FNC1_SECOND_POSITION:\n // We do little with FNC1 except alter the parsed result a bit according to the spec\n fc1InEffect = true;\n break;\n case Mode$1.STRUCTURED_APPEND:\n if (bits.available() < 16) {\n throw new FormatException();\n }\n // sequence number and parity is added later to the result metadata\n // Read next 8 bits (symbol sequence #) and 8 bits (data: parity), then continue\n symbolSequence = bits.readBits(8);\n parityData = bits.readBits(8);\n break;\n case Mode$1.ECI:\n // Count doesn't apply to ECI\n const value = DecodedBitStreamParser$1.parseECIValue(bits);\n currentCharacterSetECI = CharacterSetECI.getCharacterSetECIByValue(value);\n if (currentCharacterSetECI === null) {\n throw new FormatException();\n }\n break;\n case Mode$1.HANZI:\n // First handle Hanzi mode which does not start with character count\n // Chinese mode contains a sub set indicator right after mode indicator\n const subset = bits.readBits(4);\n const countHanzi = bits.readBits(mode.getCharacterCountBits(version));\n if (subset === DecodedBitStreamParser$1.GB2312_SUBSET) {\n DecodedBitStreamParser$1.decodeHanziSegment(bits, result, countHanzi);\n }\n break;\n default:\n // \"Normal\" QR code modes:\n // How many characters will follow, encoded in this mode?\n const count = bits.readBits(mode.getCharacterCountBits(version));\n switch (mode) {\n case Mode$1.NUMERIC:\n DecodedBitStreamParser$1.decodeNumericSegment(bits, result, count);\n break;\n case Mode$1.ALPHANUMERIC:\n DecodedBitStreamParser$1.decodeAlphanumericSegment(bits, result, count, fc1InEffect);\n break;\n case Mode$1.BYTE:\n DecodedBitStreamParser$1.decodeByteSegment(bits, result, count, currentCharacterSetECI, byteSegments, hints);\n break;\n case Mode$1.KANJI:\n DecodedBitStreamParser$1.decodeKanjiSegment(bits, result, count);\n break;\n default:\n throw new FormatException();\n }\n break;\n }\n } while (mode !== Mode$1.TERMINATOR);\n }\n catch (iae /*: IllegalArgumentException*/) {\n // from readBits() calls\n throw new FormatException();\n }\n return new DecoderResult(bytes, result.toString(), byteSegments.length === 0 ? null : byteSegments, ecLevel === null ? null : ecLevel.toString(), symbolSequence, parityData);\n }\n /**\n * See specification GBT 18284-2000\n */\n static decodeHanziSegment(bits, result, count /*int*/) {\n // Don't crash trying to read more bits than we have available.\n if (count * 13 > bits.available()) {\n throw new FormatException();\n }\n // Each character will require 2 bytes. Read the characters as 2-byte pairs\n // and decode as GB2312 afterwards\n const buffer = new Uint8Array(2 * count);\n let offset = 0;\n while (count > 0) {\n // Each 13 bits encodes a 2-byte character\n const twoBytes = bits.readBits(13);\n let assembledTwoBytes = (((twoBytes / 0x060) << 8) & 0xFFFFFFFF) | (twoBytes % 0x060);\n if (assembledTwoBytes < 0x003BF) {\n // In the 0xA1A1 to 0xAAFE range\n assembledTwoBytes += 0x0A1A1;\n }\n else {\n // In the 0xB0A1 to 0xFAFE range\n assembledTwoBytes += 0x0A6A1;\n }\n buffer[offset] = /*(byte) */ ((assembledTwoBytes >> 8) & 0xFF);\n buffer[offset + 1] = /*(byte) */ (assembledTwoBytes & 0xFF);\n offset += 2;\n count--;\n }\n try {\n result.append(StringEncoding.decode(buffer, StringUtils.GB2312));\n // TYPESCRIPTPORT: TODO: implement GB2312 decode. StringView from MDN could be a starting point\n }\n catch (ignored /*: UnsupportedEncodingException*/) {\n throw new FormatException(ignored);\n }\n }\n static decodeKanjiSegment(bits, result, count /*int*/) {\n // Don't crash trying to read more bits than we have available.\n if (count * 13 > bits.available()) {\n throw new FormatException();\n }\n // Each character will require 2 bytes. Read the characters as 2-byte pairs\n // and decode as Shift_JIS afterwards\n const buffer = new Uint8Array(2 * count);\n let offset = 0;\n while (count > 0) {\n // Each 13 bits encodes a 2-byte character\n const twoBytes = bits.readBits(13);\n let assembledTwoBytes = (((twoBytes / 0x0C0) << 8) & 0xFFFFFFFF) | (twoBytes % 0x0C0);\n if (assembledTwoBytes < 0x01F00) {\n // In the 0x8140 to 0x9FFC range\n assembledTwoBytes += 0x08140;\n }\n else {\n // In the 0xE040 to 0xEBBF range\n assembledTwoBytes += 0x0C140;\n }\n buffer[offset] = /*(byte) */ (assembledTwoBytes >> 8);\n buffer[offset + 1] = /*(byte) */ assembledTwoBytes;\n offset += 2;\n count--;\n }\n // Shift_JIS may not be supported in some environments:\n try {\n result.append(StringEncoding.decode(buffer, StringUtils.SHIFT_JIS));\n // TYPESCRIPTPORT: TODO: implement SHIFT_JIS decode. StringView from MDN could be a starting point\n }\n catch (ignored /*: UnsupportedEncodingException*/) {\n throw new FormatException(ignored);\n }\n }\n static decodeByteSegment(bits, result, count /*int*/, currentCharacterSetECI, byteSegments, hints) {\n // Don't crash trying to read more bits than we have available.\n if (8 * count > bits.available()) {\n throw new FormatException();\n }\n const readBytes = new Uint8Array(count);\n for (let i = 0; i < count; i++) {\n readBytes[i] = /*(byte) */ bits.readBits(8);\n }\n let encoding;\n if (currentCharacterSetECI === null) {\n // The spec isn't clear on this mode; see\n // section 6.4.5: t does not say which encoding to assuming\n // upon decoding. I have seen ISO-8859-1 used as well as\n // Shift_JIS -- without anything like an ECI designator to\n // give a hint.\n encoding = StringUtils.guessEncoding(readBytes, hints);\n }\n else {\n encoding = currentCharacterSetECI.getName();\n }\n try {\n result.append(StringEncoding.decode(readBytes, encoding));\n }\n catch (ignored /*: UnsupportedEncodingException*/) {\n throw new FormatException(ignored);\n }\n byteSegments.push(readBytes);\n }\n static toAlphaNumericChar(value /*int*/) {\n if (value >= DecodedBitStreamParser$1.ALPHANUMERIC_CHARS.length) {\n throw new FormatException();\n }\n return DecodedBitStreamParser$1.ALPHANUMERIC_CHARS[value];\n }\n static decodeAlphanumericSegment(bits, result, count /*int*/, fc1InEffect) {\n // Read two characters at a time\n const start = result.length();\n while (count > 1) {\n if (bits.available() < 11) {\n throw new FormatException();\n }\n const nextTwoCharsBits = bits.readBits(11);\n result.append(DecodedBitStreamParser$1.toAlphaNumericChar(Math.floor(nextTwoCharsBits / 45)));\n result.append(DecodedBitStreamParser$1.toAlphaNumericChar(nextTwoCharsBits % 45));\n count -= 2;\n }\n if (count === 1) {\n // special case: one character left\n if (bits.available() < 6) {\n throw new FormatException();\n }\n result.append(DecodedBitStreamParser$1.toAlphaNumericChar(bits.readBits(6)));\n }\n // See section 6.4.8.1, 6.4.8.2\n if (fc1InEffect) {\n // We need to massage the result a bit if in an FNC1 mode:\n for (let i = start; i < result.length(); i++) {\n if (result.charAt(i) === '%') {\n if (i < result.length() - 1 && result.charAt(i + 1) === '%') {\n // %% is rendered as %\n result.deleteCharAt(i + 1);\n }\n else {\n // In alpha mode, % should be converted to FNC1 separator 0x1D\n result.setCharAt(i, String.fromCharCode(0x1D));\n }\n }\n }\n }\n }\n static decodeNumericSegment(bits, result, count /*int*/) {\n // Read three digits at a time\n while (count >= 3) {\n // Each 10 bits encodes three digits\n if (bits.available() < 10) {\n throw new FormatException();\n }\n const threeDigitsBits = bits.readBits(10);\n if (threeDigitsBits >= 1000) {\n throw new FormatException();\n }\n result.append(DecodedBitStreamParser$1.toAlphaNumericChar(Math.floor(threeDigitsBits / 100)));\n result.append(DecodedBitStreamParser$1.toAlphaNumericChar(Math.floor(threeDigitsBits / 10) % 10));\n result.append(DecodedBitStreamParser$1.toAlphaNumericChar(threeDigitsBits % 10));\n count -= 3;\n }\n if (count === 2) {\n // Two digits left over to read, encoded in 7 bits\n if (bits.available() < 7) {\n throw new FormatException();\n }\n const twoDigitsBits = bits.readBits(7);\n if (twoDigitsBits >= 100) {\n throw new FormatException();\n }\n result.append(DecodedBitStreamParser$1.toAlphaNumericChar(Math.floor(twoDigitsBits / 10)));\n result.append(DecodedBitStreamParser$1.toAlphaNumericChar(twoDigitsBits % 10));\n }\n else if (count === 1) {\n // One digit left over to read\n if (bits.available() < 4) {\n throw new FormatException();\n }\n const digitBits = bits.readBits(4);\n if (digitBits >= 10) {\n throw new FormatException();\n }\n result.append(DecodedBitStreamParser$1.toAlphaNumericChar(digitBits));\n }\n }\n static parseECIValue(bits) {\n const firstByte = bits.readBits(8);\n if ((firstByte & 0x80) === 0) {\n // just one byte\n return firstByte & 0x7F;\n }\n if ((firstByte & 0xC0) === 0x80) {\n // two bytes\n const secondByte = bits.readBits(8);\n return (((firstByte & 0x3F) << 8) & 0xFFFFFFFF) | secondByte;\n }\n if ((firstByte & 0xE0) === 0xC0) {\n // three bytes\n const secondThirdBytes = bits.readBits(16);\n return (((firstByte & 0x1F) << 16) & 0xFFFFFFFF) | secondThirdBytes;\n }\n throw new FormatException();\n }\n }\n /**\n * See ISO 18004:2006, 6.4.4 Table 5\n */\n DecodedBitStreamParser$1.ALPHANUMERIC_CHARS = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./:';\n DecodedBitStreamParser$1.GB2312_SUBSET = 1;\n // function Uint8ArrayToString(a: Uint8Array): string {\n // const CHUNK_SZ = 0x8000;\n // const c = new StringBuilder();\n // for (let i = 0, length = a.length; i < length; i += CHUNK_SZ) {\n // c.append(String.fromCharCode.apply(null, a.subarray(i, i + CHUNK_SZ)));\n // }\n // return c.toString();\n // }\n\n /*\n * Copyright 2013 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n /**\n * Meta-data container for QR Code decoding. Instances of this class may be used to convey information back to the\n * decoding caller. Callers are expected to process this.\n *\n * @see com.google.zxing.common.DecoderResult#getOther()\n */\n class QRCodeDecoderMetaData {\n constructor(mirrored) {\n this.mirrored = mirrored;\n }\n /**\n * @return true if the QR Code was mirrored.\n */\n isMirrored() {\n return this.mirrored;\n }\n /**\n * Apply the result points' order correction due to mirroring.\n *\n * @param points Array of points to apply mirror correction to.\n */\n applyMirroredCorrection(points) {\n if (!this.mirrored || points === null || points.length < 3) {\n return;\n }\n const bottomLeft = points[0];\n points[0] = points[2];\n points[2] = bottomLeft;\n // No need to 'fix' top-left and alignment pattern.\n }\n }\n\n /*\n * Copyright 2007 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n /*import java.util.Map;*/\n /**\n *

The main class which implements QR Code decoding -- as opposed to locating and extracting\n * the QR Code from an image.

\n *\n * @author Sean Owen\n */\n class Decoder$2 {\n constructor() {\n this.rsDecoder = new ReedSolomonDecoder(GenericGF.QR_CODE_FIELD_256);\n }\n // public decode(image: boolean[][]): DecoderResult /*throws ChecksumException, FormatException*/ {\n // return decode(image, null)\n // }\n /**\n *

Convenience method that can decode a QR Code represented as a 2D array of booleans.\n * \"true\" is taken to mean a black module.

\n *\n * @param image booleans representing white/black QR Code modules\n * @param hints decoding hints that should be used to influence decoding\n * @return text and bytes encoded within the QR Code\n * @throws FormatException if the QR Code cannot be decoded\n * @throws ChecksumException if error correction fails\n */\n decodeBooleanArray(image, hints) {\n return this.decodeBitMatrix(BitMatrix.parseFromBooleanArray(image), hints);\n }\n // public decodeBitMatrix(bits: BitMatrix): DecoderResult /*throws ChecksumException, FormatException*/ {\n // return decode(bits, null)\n // }\n /**\n *

Decodes a QR Code represented as a {@link BitMatrix}. A 1 or \"true\" is taken to mean a black module.

\n *\n * @param bits booleans representing white/black QR Code modules\n * @param hints decoding hints that should be used to influence decoding\n * @return text and bytes encoded within the QR Code\n * @throws FormatException if the QR Code cannot be decoded\n * @throws ChecksumException if error correction fails\n */\n decodeBitMatrix(bits, hints) {\n // Construct a parser and read version, error-correction level\n const parser = new BitMatrixParser$1(bits);\n let ex = null;\n try {\n return this.decodeBitMatrixParser(parser, hints);\n }\n catch (e /*: FormatException, ChecksumException*/) {\n ex = e;\n }\n try {\n // Revert the bit matrix\n parser.remask();\n // Will be attempting a mirrored reading of the version and format info.\n parser.setMirror(true);\n // Preemptively read the version.\n parser.readVersion();\n // Preemptively read the format information.\n parser.readFormatInformation();\n /*\n * Since we're here, this means we have successfully detected some kind\n * of version and format information when mirrored. This is a good sign,\n * that the QR code may be mirrored, and we should try once more with a\n * mirrored content.\n */\n // Prepare for a mirrored reading.\n parser.mirror();\n const result = this.decodeBitMatrixParser(parser, hints);\n // Success! Notify the caller that the code was mirrored.\n result.setOther(new QRCodeDecoderMetaData(true));\n return result;\n }\n catch (e /*FormatException | ChecksumException*/) {\n // Throw the exception from the original reading\n if (ex !== null) {\n throw ex;\n }\n throw e;\n }\n }\n decodeBitMatrixParser(parser, hints) {\n const version = parser.readVersion();\n const ecLevel = parser.readFormatInformation().getErrorCorrectionLevel();\n // Read codewords\n const codewords = parser.readCodewords();\n // Separate into data blocks\n const dataBlocks = DataBlock$1.getDataBlocks(codewords, version, ecLevel);\n // Count total number of data bytes\n let totalBytes = 0;\n for (const dataBlock of dataBlocks) {\n totalBytes += dataBlock.getNumDataCodewords();\n }\n const resultBytes = new Uint8Array(totalBytes);\n let resultOffset = 0;\n // Error-correct and copy data blocks together into a stream of bytes\n for (const dataBlock of dataBlocks) {\n const codewordBytes = dataBlock.getCodewords();\n const numDataCodewords = dataBlock.getNumDataCodewords();\n this.correctErrors(codewordBytes, numDataCodewords);\n for (let i = 0; i < numDataCodewords; i++) {\n resultBytes[resultOffset++] = codewordBytes[i];\n }\n }\n // Decode the contents of that stream of bytes\n return DecodedBitStreamParser$1.decode(resultBytes, version, ecLevel, hints);\n }\n /**\n *

Given data and error-correction codewords received, possibly corrupted by errors, attempts to\n * correct the errors in-place using Reed-Solomon error correction.

\n *\n * @param codewordBytes data and error correction codewords\n * @param numDataCodewords number of codewords that are data bytes\n * @throws ChecksumException if error correction fails\n */\n correctErrors(codewordBytes, numDataCodewords /*int*/) {\n // const numCodewords = codewordBytes.length;\n // First read into an array of ints\n const codewordsInts = new Int32Array(codewordBytes);\n // TYPESCRIPTPORT: not realy necessary to transform to ints? could redesign everything to work with unsigned bytes?\n // const codewordsInts = new Int32Array(numCodewords)\n // for (let i = 0; i < numCodewords; i++) {\n // codewordsInts[i] = codewordBytes[i] & 0xFF\n // }\n try {\n this.rsDecoder.decode(codewordsInts, codewordBytes.length - numDataCodewords);\n }\n catch (ignored /*: ReedSolomonException*/) {\n throw new ChecksumException();\n }\n // Copy back into array of bytes -- only need to worry about the bytes that were data\n // We don't care about errors in the error-correction codewords\n for (let i = 0; i < numDataCodewords; i++) {\n codewordBytes[i] = /*(byte) */ codewordsInts[i];\n }\n }\n }\n\n /*\n * Copyright 2007 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n /**\n *

Encapsulates an alignment pattern, which are the smaller square patterns found in\n * all but the simplest QR Codes.

\n *\n * @author Sean Owen\n */\n class AlignmentPattern extends ResultPoint {\n constructor(posX /*float*/, posY /*float*/, estimatedModuleSize /*float*/) {\n super(posX, posY);\n this.estimatedModuleSize = estimatedModuleSize;\n }\n /**\n *

Determines if this alignment pattern \"about equals\" an alignment pattern at the stated\n * position and size -- meaning, it is at nearly the same center with nearly the same size.

\n */\n aboutEquals(moduleSize /*float*/, i /*float*/, j /*float*/) {\n if (Math.abs(i - this.getY()) <= moduleSize && Math.abs(j - this.getX()) <= moduleSize) {\n const moduleSizeDiff = Math.abs(moduleSize - this.estimatedModuleSize);\n return moduleSizeDiff <= 1.0 || moduleSizeDiff <= this.estimatedModuleSize;\n }\n return false;\n }\n /**\n * Combines this object's current estimate of a finder pattern position and module size\n * with a new estimate. It returns a new {@code FinderPattern} containing an average of the two.\n */\n combineEstimate(i /*float*/, j /*float*/, newModuleSize /*float*/) {\n const combinedX = (this.getX() + j) / 2.0;\n const combinedY = (this.getY() + i) / 2.0;\n const combinedModuleSize = (this.estimatedModuleSize + newModuleSize) / 2.0;\n return new AlignmentPattern(combinedX, combinedY, combinedModuleSize);\n }\n }\n\n /*\n * Copyright 2007 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n /*import java.util.ArrayList;*/\n /*import java.util.List;*/\n /**\n *

This class attempts to find alignment patterns in a QR Code. Alignment patterns look like finder\n * patterns but are smaller and appear at regular intervals throughout the image.

\n *\n *

At the moment this only looks for the bottom-right alignment pattern.

\n *\n *

This is mostly a simplified copy of {@link FinderPatternFinder}. It is copied,\n * pasted and stripped down here for maximum performance but does unfortunately duplicate\n * some code.

\n *\n *

This class is thread-safe but not reentrant. Each thread must allocate its own object.

\n *\n * @author Sean Owen\n */\n class AlignmentPatternFinder {\n /**\n *

Creates a finder that will look in a portion of the whole image.

\n *\n * @param image image to search\n * @param startX left column from which to start searching\n * @param startY top row from which to start searching\n * @param width width of region to search\n * @param height height of region to search\n * @param moduleSize estimated module size so far\n */\n constructor(image, startX /*int*/, startY /*int*/, width /*int*/, height /*int*/, moduleSize /*float*/, resultPointCallback) {\n this.image = image;\n this.startX = startX;\n this.startY = startY;\n this.width = width;\n this.height = height;\n this.moduleSize = moduleSize;\n this.resultPointCallback = resultPointCallback;\n this.possibleCenters = []; // new Array(5))\n // TYPESCRIPTPORT: array initialization without size as the length is checked below\n this.crossCheckStateCount = new Int32Array(3);\n }\n /**\n *

This method attempts to find the bottom-right alignment pattern in the image. It is a bit messy since\n * it's pretty performance-critical and so is written to be fast foremost.

\n *\n * @return {@link AlignmentPattern} if found\n * @throws NotFoundException if not found\n */\n find() {\n const startX = this.startX;\n const height = this.height;\n const width = this.width;\n const maxJ = startX + width;\n const middleI = this.startY + (height / 2);\n // We are looking for black/white/black modules in 1:1:1 ratio\n // this tracks the number of black/white/black modules seen so far\n const stateCount = new Int32Array(3);\n const image = this.image;\n for (let iGen = 0; iGen < height; iGen++) {\n // Search from middle outwards\n const i = middleI + ((iGen & 0x01) === 0 ? Math.floor((iGen + 1) / 2) : -Math.floor((iGen + 1) / 2));\n stateCount[0] = 0;\n stateCount[1] = 0;\n stateCount[2] = 0;\n let j = startX;\n // Burn off leading white pixels before anything else; if we start in the middle of\n // a white run, it doesn't make sense to count its length, since we don't know if the\n // white run continued to the left of the start point\n while (j < maxJ && !image.get(j, i)) {\n j++;\n }\n let currentState = 0;\n while (j < maxJ) {\n if (image.get(j, i)) {\n // Black pixel\n if (currentState === 1) { // Counting black pixels\n stateCount[1]++;\n }\n else { // Counting white pixels\n if (currentState === 2) { // A winner?\n if (this.foundPatternCross(stateCount)) { // Yes\n const confirmed = this.handlePossibleCenter(stateCount, i, j);\n if (confirmed !== null) {\n return confirmed;\n }\n }\n stateCount[0] = stateCount[2];\n stateCount[1] = 1;\n stateCount[2] = 0;\n currentState = 1;\n }\n else {\n stateCount[++currentState]++;\n }\n }\n }\n else { // White pixel\n if (currentState === 1) { // Counting black pixels\n currentState++;\n }\n stateCount[currentState]++;\n }\n j++;\n }\n if (this.foundPatternCross(stateCount)) {\n const confirmed = this.handlePossibleCenter(stateCount, i, maxJ);\n if (confirmed !== null) {\n return confirmed;\n }\n }\n }\n // Hmm, nothing we saw was observed and confirmed twice. If we had\n // any guess at all, return it.\n if (this.possibleCenters.length !== 0) {\n return this.possibleCenters[0];\n }\n throw new NotFoundException();\n }\n /**\n * Given a count of black/white/black pixels just seen and an end position,\n * figures the location of the center of this black/white/black run.\n */\n static centerFromEnd(stateCount, end /*int*/) {\n return (end - stateCount[2]) - stateCount[1] / 2.0;\n }\n /**\n * @param stateCount count of black/white/black pixels just read\n * @return true iff the proportions of the counts is close enough to the 1/1/1 ratios\n * used by alignment patterns to be considered a match\n */\n foundPatternCross(stateCount) {\n const moduleSize = this.moduleSize;\n const maxVariance = moduleSize / 2.0;\n for (let i = 0; i < 3; i++) {\n if (Math.abs(moduleSize - stateCount[i]) >= maxVariance) {\n return false;\n }\n }\n return true;\n }\n /**\n *

After a horizontal scan finds a potential alignment pattern, this method\n * \"cross-checks\" by scanning down vertically through the center of the possible\n * alignment pattern to see if the same proportion is detected.

\n *\n * @param startI row where an alignment pattern was detected\n * @param centerJ center of the section that appears to cross an alignment pattern\n * @param maxCount maximum reasonable number of modules that should be\n * observed in any reading state, based on the results of the horizontal scan\n * @return vertical center of alignment pattern, or {@link Float#NaN} if not found\n */\n crossCheckVertical(startI /*int*/, centerJ /*int*/, maxCount /*int*/, originalStateCountTotal /*int*/) {\n const image = this.image;\n const maxI = image.getHeight();\n const stateCount = this.crossCheckStateCount;\n stateCount[0] = 0;\n stateCount[1] = 0;\n stateCount[2] = 0;\n // Start counting up from center\n let i = startI;\n while (i >= 0 && image.get(centerJ, i) && stateCount[1] <= maxCount) {\n stateCount[1]++;\n i--;\n }\n // If already too many modules in this state or ran off the edge:\n if (i < 0 || stateCount[1] > maxCount) {\n return NaN;\n }\n while (i >= 0 && !image.get(centerJ, i) && stateCount[0] <= maxCount) {\n stateCount[0]++;\n i--;\n }\n if (stateCount[0] > maxCount) {\n return NaN;\n }\n // Now also count down from center\n i = startI + 1;\n while (i < maxI && image.get(centerJ, i) && stateCount[1] <= maxCount) {\n stateCount[1]++;\n i++;\n }\n if (i === maxI || stateCount[1] > maxCount) {\n return NaN;\n }\n while (i < maxI && !image.get(centerJ, i) && stateCount[2] <= maxCount) {\n stateCount[2]++;\n i++;\n }\n if (stateCount[2] > maxCount) {\n return NaN;\n }\n const stateCountTotal = stateCount[0] + stateCount[1] + stateCount[2];\n if (5 * Math.abs(stateCountTotal - originalStateCountTotal) >= 2 * originalStateCountTotal) {\n return NaN;\n }\n return this.foundPatternCross(stateCount) ? AlignmentPatternFinder.centerFromEnd(stateCount, i) : NaN;\n }\n /**\n *

This is called when a horizontal scan finds a possible alignment pattern. It will\n * cross check with a vertical scan, and if successful, will see if this pattern had been\n * found on a previous horizontal scan. If so, we consider it confirmed and conclude we have\n * found the alignment pattern.

\n *\n * @param stateCount reading state module counts from horizontal scan\n * @param i row where alignment pattern may be found\n * @param j end of possible alignment pattern in row\n * @return {@link AlignmentPattern} if we have found the same pattern twice, or null if not\n */\n handlePossibleCenter(stateCount, i /*int*/, j /*int*/) {\n const stateCountTotal = stateCount[0] + stateCount[1] + stateCount[2];\n const centerJ = AlignmentPatternFinder.centerFromEnd(stateCount, j);\n const centerI = this.crossCheckVertical(i, /*(int) */ centerJ, 2 * stateCount[1], stateCountTotal);\n if (!isNaN(centerI)) {\n const estimatedModuleSize = (stateCount[0] + stateCount[1] + stateCount[2]) / 3.0;\n for (const center of this.possibleCenters) {\n // Look for about the same center and module size:\n if (center.aboutEquals(estimatedModuleSize, centerI, centerJ)) {\n return center.combineEstimate(centerI, centerJ, estimatedModuleSize);\n }\n }\n // Hadn't found this before; save it\n const point = new AlignmentPattern(centerJ, centerI, estimatedModuleSize);\n this.possibleCenters.push(point);\n if (this.resultPointCallback !== null && this.resultPointCallback !== undefined) {\n this.resultPointCallback.foundPossibleResultPoint(point);\n }\n }\n return null;\n }\n }\n\n /*\n * Copyright 2007 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n /**\n *

Encapsulates a finder pattern, which are the three square patterns found in\n * the corners of QR Codes. It also encapsulates a count of similar finder patterns,\n * as a convenience to the finder's bookkeeping.

\n *\n * @author Sean Owen\n */\n class FinderPattern$1 extends ResultPoint {\n // FinderPattern(posX: number/*float*/, posY: number/*float*/, estimatedModuleSize: number/*float*/) {\n // this(posX, posY, estimatedModuleSize, 1)\n // }\n constructor(posX /*float*/, posY /*float*/, estimatedModuleSize /*float*/, count /*int*/) {\n super(posX, posY);\n this.estimatedModuleSize = estimatedModuleSize;\n this.count = count;\n if (undefined === count) {\n this.count = 1;\n }\n }\n getEstimatedModuleSize() {\n return this.estimatedModuleSize;\n }\n getCount() {\n return this.count;\n }\n /*\n void incrementCount() {\n this.count++\n }\n */\n /**\n *

Determines if this finder pattern \"about equals\" a finder pattern at the stated\n * position and size -- meaning, it is at nearly the same center with nearly the same size.

\n */\n aboutEquals(moduleSize /*float*/, i /*float*/, j /*float*/) {\n if (Math.abs(i - this.getY()) <= moduleSize && Math.abs(j - this.getX()) <= moduleSize) {\n const moduleSizeDiff = Math.abs(moduleSize - this.estimatedModuleSize);\n return moduleSizeDiff <= 1.0 || moduleSizeDiff <= this.estimatedModuleSize;\n }\n return false;\n }\n /**\n * Combines this object's current estimate of a finder pattern position and module size\n * with a new estimate. It returns a new {@code FinderPattern} containing a weighted average\n * based on count.\n */\n combineEstimate(i /*float*/, j /*float*/, newModuleSize /*float*/) {\n const combinedCount = this.count + 1;\n const combinedX = (this.count * this.getX() + j) / combinedCount;\n const combinedY = (this.count * this.getY() + i) / combinedCount;\n const combinedModuleSize = (this.count * this.estimatedModuleSize + newModuleSize) / combinedCount;\n return new FinderPattern$1(combinedX, combinedY, combinedModuleSize, combinedCount);\n }\n }\n\n /*\n * Copyright 2007 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n /**\n *

Encapsulates information about finder patterns in an image, including the location of\n * the three finder patterns, and their estimated module size.

\n *\n * @author Sean Owen\n */\n class FinderPatternInfo {\n constructor(patternCenters) {\n this.bottomLeft = patternCenters[0];\n this.topLeft = patternCenters[1];\n this.topRight = patternCenters[2];\n }\n getBottomLeft() {\n return this.bottomLeft;\n }\n getTopLeft() {\n return this.topLeft;\n }\n getTopRight() {\n return this.topRight;\n }\n }\n\n /*\n * Copyright 2007 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n /*import java.io.Serializable;*/\n /*import java.util.ArrayList;*/\n /*import java.util.Collections;*/\n /*import java.util.Comparator;*/\n /*import java.util.List;*/\n /*import java.util.Map;*/\n /**\n *

This class attempts to find finder patterns in a QR Code. Finder patterns are the square\n * markers at three corners of a QR Code.

\n *\n *

This class is thread-safe but not reentrant. Each thread must allocate its own object.\n *\n * @author Sean Owen\n */\n class FinderPatternFinder {\n /**\n *

Creates a finder that will search the image for three finder patterns.

\n *\n * @param image image to search\n */\n // public constructor(image: BitMatrix) {\n // this(image, null)\n // }\n constructor(image, resultPointCallback) {\n this.image = image;\n this.resultPointCallback = resultPointCallback;\n this.possibleCenters = [];\n this.crossCheckStateCount = new Int32Array(5);\n this.resultPointCallback = resultPointCallback;\n }\n getImage() {\n return this.image;\n }\n getPossibleCenters() {\n return this.possibleCenters;\n }\n find(hints) {\n const tryHarder = (hints !== null && hints !== undefined) && undefined !== hints.get(DecodeHintType$1.TRY_HARDER);\n const pureBarcode = (hints !== null && hints !== undefined) && undefined !== hints.get(DecodeHintType$1.PURE_BARCODE);\n const image = this.image;\n const maxI = image.getHeight();\n const maxJ = image.getWidth();\n // We are looking for black/white/black/white/black modules in\n // 1:1:3:1:1 ratio; this tracks the number of such modules seen so far\n // Let's assume that the maximum version QR Code we support takes up 1/4 the height of the\n // image, and then account for the center being 3 modules in size. This gives the smallest\n // number of pixels the center could be, so skip this often. When trying harder, look for all\n // QR versions regardless of how dense they are.\n let iSkip = Math.floor((3 * maxI) / (4 * FinderPatternFinder.MAX_MODULES));\n if (iSkip < FinderPatternFinder.MIN_SKIP || tryHarder) {\n iSkip = FinderPatternFinder.MIN_SKIP;\n }\n let done = false;\n const stateCount = new Int32Array(5);\n for (let i = iSkip - 1; i < maxI && !done; i += iSkip) {\n // Get a row of black/white values\n stateCount[0] = 0;\n stateCount[1] = 0;\n stateCount[2] = 0;\n stateCount[3] = 0;\n stateCount[4] = 0;\n let currentState = 0;\n for (let j = 0; j < maxJ; j++) {\n if (image.get(j, i)) {\n // Black pixel\n if ((currentState & 1) === 1) { // Counting white pixels\n currentState++;\n }\n stateCount[currentState]++;\n }\n else { // White pixel\n if ((currentState & 1) === 0) { // Counting black pixels\n if (currentState === 4) { // A winner?\n if (FinderPatternFinder.foundPatternCross(stateCount)) { // Yes\n const confirmed = this.handlePossibleCenter(stateCount, i, j, pureBarcode);\n if (confirmed === true) {\n // Start examining every other line. Checking each line turned out to be too\n // expensive and didn't improve performance.\n iSkip = 2;\n if (this.hasSkipped === true) {\n done = this.haveMultiplyConfirmedCenters();\n }\n else {\n const rowSkip = this.findRowSkip();\n if (rowSkip > stateCount[2]) {\n // Skip rows between row of lower confirmed center\n // and top of presumed third confirmed center\n // but back up a bit to get a full chance of detecting\n // it, entire width of center of finder pattern\n // Skip by rowSkip, but back off by stateCount[2] (size of last center\n // of pattern we saw) to be conservative, and also back off by iSkip which\n // is about to be re-added\n i += rowSkip - stateCount[2] - iSkip;\n j = maxJ - 1;\n }\n }\n }\n else {\n stateCount[0] = stateCount[2];\n stateCount[1] = stateCount[3];\n stateCount[2] = stateCount[4];\n stateCount[3] = 1;\n stateCount[4] = 0;\n currentState = 3;\n continue;\n }\n // Clear state to start looking again\n currentState = 0;\n stateCount[0] = 0;\n stateCount[1] = 0;\n stateCount[2] = 0;\n stateCount[3] = 0;\n stateCount[4] = 0;\n }\n else { // No, shift counts back by two\n stateCount[0] = stateCount[2];\n stateCount[1] = stateCount[3];\n stateCount[2] = stateCount[4];\n stateCount[3] = 1;\n stateCount[4] = 0;\n currentState = 3;\n }\n }\n else {\n stateCount[++currentState]++;\n }\n }\n else { // Counting white pixels\n stateCount[currentState]++;\n }\n }\n }\n if (FinderPatternFinder.foundPatternCross(stateCount)) {\n const confirmed = this.handlePossibleCenter(stateCount, i, maxJ, pureBarcode);\n if (confirmed === true) {\n iSkip = stateCount[0];\n if (this.hasSkipped) {\n // Found a third one\n done = this.haveMultiplyConfirmedCenters();\n }\n }\n }\n }\n const patternInfo = this.selectBestPatterns();\n ResultPoint.orderBestPatterns(patternInfo);\n return new FinderPatternInfo(patternInfo);\n }\n /**\n * Given a count of black/white/black/white/black pixels just seen and an end position,\n * figures the location of the center of this run.\n */\n static centerFromEnd(stateCount, end /*int*/) {\n return (end - stateCount[4] - stateCount[3]) - stateCount[2] / 2.0;\n }\n /**\n * @param stateCount count of black/white/black/white/black pixels just read\n * @return true iff the proportions of the counts is close enough to the 1/1/3/1/1 ratios\n * used by finder patterns to be considered a match\n */\n static foundPatternCross(stateCount) {\n let totalModuleSize = 0;\n for (let i = 0; i < 5; i++) {\n const count = stateCount[i];\n if (count === 0) {\n return false;\n }\n totalModuleSize += count;\n }\n if (totalModuleSize < 7) {\n return false;\n }\n const moduleSize = totalModuleSize / 7.0;\n const maxVariance = moduleSize / 2.0;\n // Allow less than 50% variance from 1-1-3-1-1 proportions\n return Math.abs(moduleSize - stateCount[0]) < maxVariance &&\n Math.abs(moduleSize - stateCount[1]) < maxVariance &&\n Math.abs(3.0 * moduleSize - stateCount[2]) < 3 * maxVariance &&\n Math.abs(moduleSize - stateCount[3]) < maxVariance &&\n Math.abs(moduleSize - stateCount[4]) < maxVariance;\n }\n getCrossCheckStateCount() {\n const crossCheckStateCount = this.crossCheckStateCount;\n crossCheckStateCount[0] = 0;\n crossCheckStateCount[1] = 0;\n crossCheckStateCount[2] = 0;\n crossCheckStateCount[3] = 0;\n crossCheckStateCount[4] = 0;\n return crossCheckStateCount;\n }\n /**\n * After a vertical and horizontal scan finds a potential finder pattern, this method\n * \"cross-cross-cross-checks\" by scanning down diagonally through the center of the possible\n * finder pattern to see if the same proportion is detected.\n *\n * @param startI row where a finder pattern was detected\n * @param centerJ center of the section that appears to cross a finder pattern\n * @param maxCount maximum reasonable number of modules that should be\n * observed in any reading state, based on the results of the horizontal scan\n * @param originalStateCountTotal The original state count total.\n * @return true if proportions are withing expected limits\n */\n crossCheckDiagonal(startI /*int*/, centerJ /*int*/, maxCount /*int*/, originalStateCountTotal /*int*/) {\n const stateCount = this.getCrossCheckStateCount();\n // Start counting up, left from center finding black center mass\n let i = 0;\n const image = this.image;\n while (startI >= i && centerJ >= i && image.get(centerJ - i, startI - i)) {\n stateCount[2]++;\n i++;\n }\n if (startI < i || centerJ < i) {\n return false;\n }\n // Continue up, left finding white space\n while (startI >= i && centerJ >= i && !image.get(centerJ - i, startI - i) &&\n stateCount[1] <= maxCount) {\n stateCount[1]++;\n i++;\n }\n // If already too many modules in this state or ran off the edge:\n if (startI < i || centerJ < i || stateCount[1] > maxCount) {\n return false;\n }\n // Continue up, left finding black border\n while (startI >= i && centerJ >= i && image.get(centerJ - i, startI - i) &&\n stateCount[0] <= maxCount) {\n stateCount[0]++;\n i++;\n }\n if (stateCount[0] > maxCount) {\n return false;\n }\n const maxI = image.getHeight();\n const maxJ = image.getWidth();\n // Now also count down, right from center\n i = 1;\n while (startI + i < maxI && centerJ + i < maxJ && image.get(centerJ + i, startI + i)) {\n stateCount[2]++;\n i++;\n }\n // Ran off the edge?\n if (startI + i >= maxI || centerJ + i >= maxJ) {\n return false;\n }\n while (startI + i < maxI && centerJ + i < maxJ && !image.get(centerJ + i, startI + i) &&\n stateCount[3] < maxCount) {\n stateCount[3]++;\n i++;\n }\n if (startI + i >= maxI || centerJ + i >= maxJ || stateCount[3] >= maxCount) {\n return false;\n }\n while (startI + i < maxI && centerJ + i < maxJ && image.get(centerJ + i, startI + i) &&\n stateCount[4] < maxCount) {\n stateCount[4]++;\n i++;\n }\n if (stateCount[4] >= maxCount) {\n return false;\n }\n // If we found a finder-pattern-like section, but its size is more than 100% different than\n // the original, assume it's a false positive\n const stateCountTotal = stateCount[0] + stateCount[1] + stateCount[2] + stateCount[3] + stateCount[4];\n return Math.abs(stateCountTotal - originalStateCountTotal) < 2 * originalStateCountTotal &&\n FinderPatternFinder.foundPatternCross(stateCount);\n }\n /**\n *

After a horizontal scan finds a potential finder pattern, this method\n * \"cross-checks\" by scanning down vertically through the center of the possible\n * finder pattern to see if the same proportion is detected.

\n *\n * @param startI row where a finder pattern was detected\n * @param centerJ center of the section that appears to cross a finder pattern\n * @param maxCount maximum reasonable number of modules that should be\n * observed in any reading state, based on the results of the horizontal scan\n * @return vertical center of finder pattern, or {@link Float#NaN} if not found\n */\n crossCheckVertical(startI /*int*/, centerJ /*int*/, maxCount /*int*/, originalStateCountTotal /*int*/) {\n const image = this.image;\n const maxI = image.getHeight();\n const stateCount = this.getCrossCheckStateCount();\n // Start counting up from center\n let i = startI;\n while (i >= 0 && image.get(centerJ, i)) {\n stateCount[2]++;\n i--;\n }\n if (i < 0) {\n return NaN;\n }\n while (i >= 0 && !image.get(centerJ, i) && stateCount[1] <= maxCount) {\n stateCount[1]++;\n i--;\n }\n // If already too many modules in this state or ran off the edge:\n if (i < 0 || stateCount[1] > maxCount) {\n return NaN;\n }\n while (i >= 0 && image.get(centerJ, i) && stateCount[0] <= maxCount) {\n stateCount[0]++;\n i--;\n }\n if (stateCount[0] > maxCount) {\n return NaN;\n }\n // Now also count down from center\n i = startI + 1;\n while (i < maxI && image.get(centerJ, i)) {\n stateCount[2]++;\n i++;\n }\n if (i === maxI) {\n return NaN;\n }\n while (i < maxI && !image.get(centerJ, i) && stateCount[3] < maxCount) {\n stateCount[3]++;\n i++;\n }\n if (i === maxI || stateCount[3] >= maxCount) {\n return NaN;\n }\n while (i < maxI && image.get(centerJ, i) && stateCount[4] < maxCount) {\n stateCount[4]++;\n i++;\n }\n if (stateCount[4] >= maxCount) {\n return NaN;\n }\n // If we found a finder-pattern-like section, but its size is more than 40% different than\n // the original, assume it's a false positive\n const stateCountTotal = stateCount[0] + stateCount[1] + stateCount[2] + stateCount[3] +\n stateCount[4];\n if (5 * Math.abs(stateCountTotal - originalStateCountTotal) >= 2 * originalStateCountTotal) {\n return NaN;\n }\n return FinderPatternFinder.foundPatternCross(stateCount) ? FinderPatternFinder.centerFromEnd(stateCount, i) : NaN;\n }\n /**\n *

Like {@link #crossCheckVertical(int, int, int, int)}, and in fact is basically identical,\n * except it reads horizontally instead of vertically. This is used to cross-cross\n * check a vertical cross check and locate the real center of the alignment pattern.

\n */\n crossCheckHorizontal(startJ /*int*/, centerI /*int*/, maxCount /*int*/, originalStateCountTotal /*int*/) {\n const image = this.image;\n const maxJ = image.getWidth();\n const stateCount = this.getCrossCheckStateCount();\n let j = startJ;\n while (j >= 0 && image.get(j, centerI)) {\n stateCount[2]++;\n j--;\n }\n if (j < 0) {\n return NaN;\n }\n while (j >= 0 && !image.get(j, centerI) && stateCount[1] <= maxCount) {\n stateCount[1]++;\n j--;\n }\n if (j < 0 || stateCount[1] > maxCount) {\n return NaN;\n }\n while (j >= 0 && image.get(j, centerI) && stateCount[0] <= maxCount) {\n stateCount[0]++;\n j--;\n }\n if (stateCount[0] > maxCount) {\n return NaN;\n }\n j = startJ + 1;\n while (j < maxJ && image.get(j, centerI)) {\n stateCount[2]++;\n j++;\n }\n if (j === maxJ) {\n return NaN;\n }\n while (j < maxJ && !image.get(j, centerI) && stateCount[3] < maxCount) {\n stateCount[3]++;\n j++;\n }\n if (j === maxJ || stateCount[3] >= maxCount) {\n return NaN;\n }\n while (j < maxJ && image.get(j, centerI) && stateCount[4] < maxCount) {\n stateCount[4]++;\n j++;\n }\n if (stateCount[4] >= maxCount) {\n return NaN;\n }\n // If we found a finder-pattern-like section, but its size is significantly different than\n // the original, assume it's a false positive\n const stateCountTotal = stateCount[0] + stateCount[1] + stateCount[2] + stateCount[3] +\n stateCount[4];\n if (5 * Math.abs(stateCountTotal - originalStateCountTotal) >= originalStateCountTotal) {\n return NaN;\n }\n return FinderPatternFinder.foundPatternCross(stateCount) ? FinderPatternFinder.centerFromEnd(stateCount, j) : NaN;\n }\n /**\n *

This is called when a horizontal scan finds a possible alignment pattern. It will\n * cross check with a vertical scan, and if successful, will, ah, cross-cross-check\n * with another horizontal scan. This is needed primarily to locate the real horizontal\n * center of the pattern in cases of extreme skew.\n * And then we cross-cross-cross check with another diagonal scan.

\n *\n *

If that succeeds the finder pattern location is added to a list that tracks\n * the number of times each location has been nearly-matched as a finder pattern.\n * Each additional find is more evidence that the location is in fact a finder\n * pattern center\n *\n * @param stateCount reading state module counts from horizontal scan\n * @param i row where finder pattern may be found\n * @param j end of possible finder pattern in row\n * @param pureBarcode true if in \"pure barcode\" mode\n * @return true if a finder pattern candidate was found this time\n */\n handlePossibleCenter(stateCount, i /*int*/, j /*int*/, pureBarcode) {\n const stateCountTotal = stateCount[0] + stateCount[1] + stateCount[2] + stateCount[3] +\n stateCount[4];\n let centerJ = FinderPatternFinder.centerFromEnd(stateCount, j);\n let centerI = this.crossCheckVertical(i, /*(int) */ Math.floor(centerJ), stateCount[2], stateCountTotal);\n if (!isNaN(centerI)) {\n // Re-cross check\n centerJ = this.crossCheckHorizontal(/*(int) */ Math.floor(centerJ), /*(int) */ Math.floor(centerI), stateCount[2], stateCountTotal);\n if (!isNaN(centerJ) &&\n (!pureBarcode || this.crossCheckDiagonal(/*(int) */ Math.floor(centerI), /*(int) */ Math.floor(centerJ), stateCount[2], stateCountTotal))) {\n const estimatedModuleSize = stateCountTotal / 7.0;\n let found = false;\n const possibleCenters = this.possibleCenters;\n for (let index = 0, length = possibleCenters.length; index < length; index++) {\n const center = possibleCenters[index];\n // Look for about the same center and module size:\n if (center.aboutEquals(estimatedModuleSize, centerI, centerJ)) {\n possibleCenters[index] = center.combineEstimate(centerI, centerJ, estimatedModuleSize);\n found = true;\n break;\n }\n }\n if (!found) {\n const point = new FinderPattern$1(centerJ, centerI, estimatedModuleSize);\n possibleCenters.push(point);\n if (this.resultPointCallback !== null && this.resultPointCallback !== undefined) {\n this.resultPointCallback.foundPossibleResultPoint(point);\n }\n }\n return true;\n }\n }\n return false;\n }\n /**\n * @return number of rows we could safely skip during scanning, based on the first\n * two finder patterns that have been located. In some cases their position will\n * allow us to infer that the third pattern must lie below a certain point farther\n * down in the image.\n */\n findRowSkip() {\n const max = this.possibleCenters.length;\n if (max <= 1) {\n return 0;\n }\n let firstConfirmedCenter = null;\n for (const center of this.possibleCenters) {\n if (center.getCount() >= FinderPatternFinder.CENTER_QUORUM) {\n if (firstConfirmedCenter == null) {\n firstConfirmedCenter = center;\n }\n else {\n // We have two confirmed centers\n // How far down can we skip before resuming looking for the next\n // pattern? In the worst case, only the difference between the\n // difference in the x / y coordinates of the two centers.\n // This is the case where you find top left last.\n this.hasSkipped = true;\n return /*(int) */ Math.floor((Math.abs(firstConfirmedCenter.getX() - center.getX()) -\n Math.abs(firstConfirmedCenter.getY() - center.getY())) / 2);\n }\n }\n }\n return 0;\n }\n /**\n * @return true iff we have found at least 3 finder patterns that have been detected\n * at least {@link #CENTER_QUORUM} times each, and, the estimated module size of the\n * candidates is \"pretty similar\"\n */\n haveMultiplyConfirmedCenters() {\n let confirmedCount = 0;\n let totalModuleSize = 0.0;\n const max = this.possibleCenters.length;\n for (const pattern of this.possibleCenters) {\n if (pattern.getCount() >= FinderPatternFinder.CENTER_QUORUM) {\n confirmedCount++;\n totalModuleSize += pattern.getEstimatedModuleSize();\n }\n }\n if (confirmedCount < 3) {\n return false;\n }\n // OK, we have at least 3 confirmed centers, but, it's possible that one is a \"false positive\"\n // and that we need to keep looking. We detect this by asking if the estimated module sizes\n // vary too much. We arbitrarily say that when the total deviation from average exceeds\n // 5% of the total module size estimates, it's too much.\n const average = totalModuleSize / max;\n let totalDeviation = 0.0;\n for (const pattern of this.possibleCenters) {\n totalDeviation += Math.abs(pattern.getEstimatedModuleSize() - average);\n }\n return totalDeviation <= 0.05 * totalModuleSize;\n }\n /**\n * @return the 3 best {@link FinderPattern}s from our list of candidates. The \"best\" are\n * those that have been detected at least {@link #CENTER_QUORUM} times, and whose module\n * size differs from the average among those patterns the least\n * @throws NotFoundException if 3 such finder patterns do not exist\n */\n selectBestPatterns() {\n const startSize = this.possibleCenters.length;\n if (startSize < 3) {\n // Couldn't find enough finder patterns\n throw new NotFoundException();\n }\n const possibleCenters = this.possibleCenters;\n let average;\n // Filter outlier possibilities whose module size is too different\n if (startSize > 3) {\n // But we can only afford to do so if we have at least 4 possibilities to choose from\n let totalModuleSize = 0.0;\n let square = 0.0;\n for (const center of this.possibleCenters) {\n const size = center.getEstimatedModuleSize();\n totalModuleSize += size;\n square += size * size;\n }\n average = totalModuleSize / startSize;\n let stdDev = Math.sqrt(square / startSize - average * average);\n possibleCenters.sort(\n /**\n *

Orders by furthest from average

\n */\n // FurthestFromAverageComparator implements Comparator\n (center1, center2) => {\n const dA = Math.abs(center2.getEstimatedModuleSize() - average);\n const dB = Math.abs(center1.getEstimatedModuleSize() - average);\n return dA < dB ? -1 : dA > dB ? 1 : 0;\n });\n const limit = Math.max(0.2 * average, stdDev);\n for (let i = 0; i < possibleCenters.length && possibleCenters.length > 3; i++) {\n const pattern = possibleCenters[i];\n if (Math.abs(pattern.getEstimatedModuleSize() - average) > limit) {\n possibleCenters.splice(i, 1);\n i--;\n }\n }\n }\n if (possibleCenters.length > 3) {\n // Throw away all but those first size candidate points we found.\n let totalModuleSize = 0.0;\n for (const possibleCenter of possibleCenters) {\n totalModuleSize += possibleCenter.getEstimatedModuleSize();\n }\n average = totalModuleSize / possibleCenters.length;\n possibleCenters.sort(\n /**\n *

Orders by {@link FinderPattern#getCount()}, descending.

\n */\n // CenterComparator implements Comparator\n (center1, center2) => {\n if (center2.getCount() === center1.getCount()) {\n const dA = Math.abs(center2.getEstimatedModuleSize() - average);\n const dB = Math.abs(center1.getEstimatedModuleSize() - average);\n return dA < dB ? 1 : dA > dB ? -1 : 0;\n }\n else {\n return center2.getCount() - center1.getCount();\n }\n });\n possibleCenters.splice(3); // this is not realy necessary as we only return first 3 anyway\n }\n return [\n possibleCenters[0],\n possibleCenters[1],\n possibleCenters[2]\n ];\n }\n }\n FinderPatternFinder.CENTER_QUORUM = 2;\n FinderPatternFinder.MIN_SKIP = 3; // 1 pixel/module times 3 modules/center\n FinderPatternFinder.MAX_MODULES = 57; // support up to version 10 for mobile clients\n\n /*\n * Copyright 2007 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n /*import java.util.Map;*/\n /**\n *

Encapsulates logic that can detect a QR Code in an image, even if the QR Code\n * is rotated or skewed, or partially obscured.

\n *\n * @author Sean Owen\n */\n class Detector$2 {\n constructor(image) {\n this.image = image;\n }\n getImage() {\n return this.image;\n }\n getResultPointCallback() {\n return this.resultPointCallback;\n }\n /**\n *

Detects a QR Code in an image.

\n *\n * @return {@link DetectorResult} encapsulating results of detecting a QR Code\n * @throws NotFoundException if QR Code cannot be found\n * @throws FormatException if a QR Code cannot be decoded\n */\n // public detect(): DetectorResult /*throws NotFoundException, FormatException*/ {\n // return detect(null)\n // }\n /**\n *

Detects a QR Code in an image.

\n *\n * @param hints optional hints to detector\n * @return {@link DetectorResult} encapsulating results of detecting a QR Code\n * @throws NotFoundException if QR Code cannot be found\n * @throws FormatException if a QR Code cannot be decoded\n */\n detect(hints) {\n this.resultPointCallback = (hints === null || hints === undefined) ? null :\n /*(ResultPointCallback) */ hints.get(DecodeHintType$1.NEED_RESULT_POINT_CALLBACK);\n const finder = new FinderPatternFinder(this.image, this.resultPointCallback);\n const info = finder.find(hints);\n return this.processFinderPatternInfo(info);\n }\n processFinderPatternInfo(info) {\n const topLeft = info.getTopLeft();\n const topRight = info.getTopRight();\n const bottomLeft = info.getBottomLeft();\n const moduleSize = this.calculateModuleSize(topLeft, topRight, bottomLeft);\n if (moduleSize < 1.0) {\n throw new NotFoundException('No pattern found in proccess finder.');\n }\n const dimension = Detector$2.computeDimension(topLeft, topRight, bottomLeft, moduleSize);\n const provisionalVersion = Version$1.getProvisionalVersionForDimension(dimension);\n const modulesBetweenFPCenters = provisionalVersion.getDimensionForVersion() - 7;\n let alignmentPattern = null;\n // Anything above version 1 has an alignment pattern\n if (provisionalVersion.getAlignmentPatternCenters().length > 0) {\n // Guess where a \"bottom right\" finder pattern would have been\n const bottomRightX = topRight.getX() - topLeft.getX() + bottomLeft.getX();\n const bottomRightY = topRight.getY() - topLeft.getY() + bottomLeft.getY();\n // Estimate that alignment pattern is closer by 3 modules\n // from \"bottom right\" to known top left location\n const correctionToTopLeft = 1.0 - 3.0 / modulesBetweenFPCenters;\n const estAlignmentX = /*(int) */ Math.floor(topLeft.getX() + correctionToTopLeft * (bottomRightX - topLeft.getX()));\n const estAlignmentY = /*(int) */ Math.floor(topLeft.getY() + correctionToTopLeft * (bottomRightY - topLeft.getY()));\n // Kind of arbitrary -- expand search radius before giving up\n for (let i = 4; i <= 16; i <<= 1) {\n try {\n alignmentPattern = this.findAlignmentInRegion(moduleSize, estAlignmentX, estAlignmentY, i);\n break;\n }\n catch (re /*NotFoundException*/) {\n if (!(re instanceof NotFoundException)) {\n throw re;\n }\n // try next round\n }\n }\n // If we didn't find alignment pattern... well try anyway without it\n }\n const transform = Detector$2.createTransform(topLeft, topRight, bottomLeft, alignmentPattern, dimension);\n const bits = Detector$2.sampleGrid(this.image, transform, dimension);\n let points;\n if (alignmentPattern === null) {\n points = [bottomLeft, topLeft, topRight];\n }\n else {\n points = [bottomLeft, topLeft, topRight, alignmentPattern];\n }\n return new DetectorResult(bits, points);\n }\n static createTransform(topLeft, topRight, bottomLeft, alignmentPattern, dimension /*int*/) {\n const dimMinusThree = dimension - 3.5;\n let bottomRightX; /*float*/\n let bottomRightY; /*float*/\n let sourceBottomRightX; /*float*/\n let sourceBottomRightY; /*float*/\n if (alignmentPattern !== null) {\n bottomRightX = alignmentPattern.getX();\n bottomRightY = alignmentPattern.getY();\n sourceBottomRightX = dimMinusThree - 3.0;\n sourceBottomRightY = sourceBottomRightX;\n }\n else {\n // Don't have an alignment pattern, just make up the bottom-right point\n bottomRightX = (topRight.getX() - topLeft.getX()) + bottomLeft.getX();\n bottomRightY = (topRight.getY() - topLeft.getY()) + bottomLeft.getY();\n sourceBottomRightX = dimMinusThree;\n sourceBottomRightY = dimMinusThree;\n }\n return PerspectiveTransform.quadrilateralToQuadrilateral(3.5, 3.5, dimMinusThree, 3.5, sourceBottomRightX, sourceBottomRightY, 3.5, dimMinusThree, topLeft.getX(), topLeft.getY(), topRight.getX(), topRight.getY(), bottomRightX, bottomRightY, bottomLeft.getX(), bottomLeft.getY());\n }\n static sampleGrid(image, transform, dimension /*int*/) {\n const sampler = GridSamplerInstance.getInstance();\n return sampler.sampleGridWithTransform(image, dimension, dimension, transform);\n }\n /**\n *

Computes the dimension (number of modules on a size) of the QR Code based on the position\n * of the finder patterns and estimated module size.

\n */\n static computeDimension(topLeft, topRight, bottomLeft, moduleSize /*float*/) {\n const tltrCentersDimension = MathUtils.round(ResultPoint.distance(topLeft, topRight) / moduleSize);\n const tlblCentersDimension = MathUtils.round(ResultPoint.distance(topLeft, bottomLeft) / moduleSize);\n let dimension = Math.floor((tltrCentersDimension + tlblCentersDimension) / 2) + 7;\n switch (dimension & 0x03) { // mod 4\n case 0:\n dimension++;\n break;\n // 1? do nothing\n case 2:\n dimension--;\n break;\n case 3:\n throw new NotFoundException('Dimensions could be not found.');\n }\n return dimension;\n }\n /**\n *

Computes an average estimated module size based on estimated derived from the positions\n * of the three finder patterns.

\n *\n * @param topLeft detected top-left finder pattern center\n * @param topRight detected top-right finder pattern center\n * @param bottomLeft detected bottom-left finder pattern center\n * @return estimated module size\n */\n calculateModuleSize(topLeft, topRight, bottomLeft) {\n // Take the average\n return (this.calculateModuleSizeOneWay(topLeft, topRight) +\n this.calculateModuleSizeOneWay(topLeft, bottomLeft)) / 2.0;\n }\n /**\n *

Estimates module size based on two finder patterns -- it uses\n * {@link #sizeOfBlackWhiteBlackRunBothWays(int, int, int, int)} to figure the\n * width of each, measuring along the axis between their centers.

\n */\n calculateModuleSizeOneWay(pattern, otherPattern) {\n const moduleSizeEst1 = this.sizeOfBlackWhiteBlackRunBothWays(/*(int) */ Math.floor(pattern.getX()), \n /*(int) */ Math.floor(pattern.getY()), \n /*(int) */ Math.floor(otherPattern.getX()), \n /*(int) */ Math.floor(otherPattern.getY()));\n const moduleSizeEst2 = this.sizeOfBlackWhiteBlackRunBothWays(/*(int) */ Math.floor(otherPattern.getX()), \n /*(int) */ Math.floor(otherPattern.getY()), \n /*(int) */ Math.floor(pattern.getX()), \n /*(int) */ Math.floor(pattern.getY()));\n if (isNaN(moduleSizeEst1)) {\n return moduleSizeEst2 / 7.0;\n }\n if (isNaN(moduleSizeEst2)) {\n return moduleSizeEst1 / 7.0;\n }\n // Average them, and divide by 7 since we've counted the width of 3 black modules,\n // and 1 white and 1 black module on either side. Ergo, divide sum by 14.\n return (moduleSizeEst1 + moduleSizeEst2) / 14.0;\n }\n /**\n * See {@link #sizeOfBlackWhiteBlackRun(int, int, int, int)}; computes the total width of\n * a finder pattern by looking for a black-white-black run from the center in the direction\n * of another point (another finder pattern center), and in the opposite direction too.\n */\n sizeOfBlackWhiteBlackRunBothWays(fromX /*int*/, fromY /*int*/, toX /*int*/, toY /*int*/) {\n let result = this.sizeOfBlackWhiteBlackRun(fromX, fromY, toX, toY);\n // Now count other way -- don't run off image though of course\n let scale = 1.0;\n let otherToX = fromX - (toX - fromX);\n if (otherToX < 0) {\n scale = fromX / /*(float) */ (fromX - otherToX);\n otherToX = 0;\n }\n else if (otherToX >= this.image.getWidth()) {\n scale = (this.image.getWidth() - 1 - fromX) / /*(float) */ (otherToX - fromX);\n otherToX = this.image.getWidth() - 1;\n }\n let otherToY = /*(int) */ Math.floor(fromY - (toY - fromY) * scale);\n scale = 1.0;\n if (otherToY < 0) {\n scale = fromY / /*(float) */ (fromY - otherToY);\n otherToY = 0;\n }\n else if (otherToY >= this.image.getHeight()) {\n scale = (this.image.getHeight() - 1 - fromY) / /*(float) */ (otherToY - fromY);\n otherToY = this.image.getHeight() - 1;\n }\n otherToX = /*(int) */ Math.floor(fromX + (otherToX - fromX) * scale);\n result += this.sizeOfBlackWhiteBlackRun(fromX, fromY, otherToX, otherToY);\n // Middle pixel is double-counted this way; subtract 1\n return result - 1.0;\n }\n /**\n *

This method traces a line from a point in the image, in the direction towards another point.\n * It begins in a black region, and keeps going until it finds white, then black, then white again.\n * It reports the distance from the start to this point.

\n *\n *

This is used when figuring out how wide a finder pattern is, when the finder pattern\n * may be skewed or rotated.

\n */\n sizeOfBlackWhiteBlackRun(fromX /*int*/, fromY /*int*/, toX /*int*/, toY /*int*/) {\n // Mild variant of Bresenham's algorithm\n // see http://en.wikipedia.org/wiki/Bresenham's_line_algorithm\n const steep = Math.abs(toY - fromY) > Math.abs(toX - fromX);\n if (steep) {\n let temp = fromX;\n fromX = fromY;\n fromY = temp;\n temp = toX;\n toX = toY;\n toY = temp;\n }\n const dx = Math.abs(toX - fromX);\n const dy = Math.abs(toY - fromY);\n let error = -dx / 2;\n const xstep = fromX < toX ? 1 : -1;\n const ystep = fromY < toY ? 1 : -1;\n // In black pixels, looking for white, first or second time.\n let state = 0;\n // Loop up until x == toX, but not beyond\n const xLimit = toX + xstep;\n for (let x = fromX, y = fromY; x !== xLimit; x += xstep) {\n const realX = steep ? y : x;\n const realY = steep ? x : y;\n // Does current pixel mean we have moved white to black or vice versa?\n // Scanning black in state 0,2 and white in state 1, so if we find the wrong\n // color, advance to next state or end if we are in state 2 already\n if ((state === 1) === this.image.get(realX, realY)) {\n if (state === 2) {\n return MathUtils.distance(x, y, fromX, fromY);\n }\n state++;\n }\n error += dy;\n if (error > 0) {\n if (y === toY) {\n break;\n }\n y += ystep;\n error -= dx;\n }\n }\n // Found black-white-black; give the benefit of the doubt that the next pixel outside the image\n // is \"white\" so this last point at (toX+xStep,toY) is the right ending. This is really a\n // small approximation; (toX+xStep,toY+yStep) might be really correct. Ignore this.\n if (state === 2) {\n return MathUtils.distance(toX + xstep, toY, fromX, fromY);\n }\n // else we didn't find even black-white-black; no estimate is really possible\n return NaN;\n }\n /**\n *

Attempts to locate an alignment pattern in a limited region of the image, which is\n * guessed to contain it. This method uses {@link AlignmentPattern}.

\n *\n * @param overallEstModuleSize estimated module size so far\n * @param estAlignmentX x coordinate of center of area probably containing alignment pattern\n * @param estAlignmentY y coordinate of above\n * @param allowanceFactor number of pixels in all directions to search from the center\n * @return {@link AlignmentPattern} if found, or null otherwise\n * @throws NotFoundException if an unexpected error occurs during detection\n */\n findAlignmentInRegion(overallEstModuleSize /*float*/, estAlignmentX /*int*/, estAlignmentY /*int*/, allowanceFactor /*float*/) {\n // Look for an alignment pattern (3 modules in size) around where it\n // should be\n const allowance = /*(int) */ Math.floor(allowanceFactor * overallEstModuleSize);\n const alignmentAreaLeftX = Math.max(0, estAlignmentX - allowance);\n const alignmentAreaRightX = Math.min(this.image.getWidth() - 1, estAlignmentX + allowance);\n if (alignmentAreaRightX - alignmentAreaLeftX < overallEstModuleSize * 3) {\n throw new NotFoundException('Alignment top exceeds estimated module size.');\n }\n const alignmentAreaTopY = Math.max(0, estAlignmentY - allowance);\n const alignmentAreaBottomY = Math.min(this.image.getHeight() - 1, estAlignmentY + allowance);\n if (alignmentAreaBottomY - alignmentAreaTopY < overallEstModuleSize * 3) {\n throw new NotFoundException('Alignment bottom exceeds estimated module size.');\n }\n const alignmentFinder = new AlignmentPatternFinder(this.image, alignmentAreaLeftX, alignmentAreaTopY, alignmentAreaRightX - alignmentAreaLeftX, alignmentAreaBottomY - alignmentAreaTopY, overallEstModuleSize, this.resultPointCallback);\n return alignmentFinder.find();\n }\n }\n\n /*\n * Copyright 2007 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n /*import java.util.List;*/\n /*import java.util.Map;*/\n /**\n * This implementation can detect and decode QR Codes in an image.\n *\n * @author Sean Owen\n */\n class QRCodeReader {\n constructor() {\n this.decoder = new Decoder$2();\n }\n getDecoder() {\n return this.decoder;\n }\n /**\n * Locates and decodes a QR code in an image.\n *\n * @return a representing: string the content encoded by the QR code\n * @throws NotFoundException if a QR code cannot be found\n * @throws FormatException if a QR code cannot be decoded\n * @throws ChecksumException if error correction fails\n */\n /*@Override*/\n // public decode(image: BinaryBitmap): Result /*throws NotFoundException, ChecksumException, FormatException */ {\n // return this.decode(image, null)\n // }\n /*@Override*/\n decode(image, hints) {\n let decoderResult;\n let points;\n if (hints !== undefined && hints !== null && undefined !== hints.get(DecodeHintType$1.PURE_BARCODE)) {\n const bits = QRCodeReader.extractPureBits(image.getBlackMatrix());\n decoderResult = this.decoder.decodeBitMatrix(bits, hints);\n points = QRCodeReader.NO_POINTS;\n }\n else {\n const detectorResult = new Detector$2(image.getBlackMatrix()).detect(hints);\n decoderResult = this.decoder.decodeBitMatrix(detectorResult.getBits(), hints);\n points = detectorResult.getPoints();\n }\n // If the code was mirrored: swap the bottom-left and the top-right points.\n if (decoderResult.getOther() instanceof QRCodeDecoderMetaData) {\n decoderResult.getOther().applyMirroredCorrection(points);\n }\n const result = new Result(decoderResult.getText(), decoderResult.getRawBytes(), undefined, points, BarcodeFormat$1.QR_CODE, undefined);\n const byteSegments = decoderResult.getByteSegments();\n if (byteSegments !== null) {\n result.putMetadata(ResultMetadataType$1.BYTE_SEGMENTS, byteSegments);\n }\n const ecLevel = decoderResult.getECLevel();\n if (ecLevel !== null) {\n result.putMetadata(ResultMetadataType$1.ERROR_CORRECTION_LEVEL, ecLevel);\n }\n if (decoderResult.hasStructuredAppend()) {\n result.putMetadata(ResultMetadataType$1.STRUCTURED_APPEND_SEQUENCE, decoderResult.getStructuredAppendSequenceNumber());\n result.putMetadata(ResultMetadataType$1.STRUCTURED_APPEND_PARITY, decoderResult.getStructuredAppendParity());\n }\n return result;\n }\n /*@Override*/\n reset() {\n // do nothing\n }\n /**\n * This method detects a code in a \"pure\" image -- that is, pure monochrome image\n * which contains only an unrotated, unskewed, image of a code, with some white border\n * around it. This is a specialized method that works exceptionally fast in this special\n * case.\n *\n * @see com.google.zxing.datamatrix.DataMatrixReader#extractPureBits(BitMatrix)\n */\n static extractPureBits(image) {\n const leftTopBlack = image.getTopLeftOnBit();\n const rightBottomBlack = image.getBottomRightOnBit();\n if (leftTopBlack === null || rightBottomBlack === null) {\n throw new NotFoundException();\n }\n const moduleSize = this.moduleSize(leftTopBlack, image);\n let top = leftTopBlack[1];\n let bottom = rightBottomBlack[1];\n let left = leftTopBlack[0];\n let right = rightBottomBlack[0];\n // Sanity check!\n if (left >= right || top >= bottom) {\n throw new NotFoundException();\n }\n if (bottom - top !== right - left) {\n // Special case, where bottom-right module wasn't black so we found something else in the last row\n // Assume it's a square, so use height as the width\n right = left + (bottom - top);\n if (right >= image.getWidth()) {\n // Abort if that would not make sense -- off image\n throw new NotFoundException();\n }\n }\n const matrixWidth = Math.round((right - left + 1) / moduleSize);\n const matrixHeight = Math.round((bottom - top + 1) / moduleSize);\n if (matrixWidth <= 0 || matrixHeight <= 0) {\n throw new NotFoundException();\n }\n if (matrixHeight !== matrixWidth) {\n // Only possibly decode square regions\n throw new NotFoundException();\n }\n // Push in the \"border\" by half the module width so that we start\n // sampling in the middle of the module. Just in case the image is a\n // little off, this will help recover.\n const nudge = /*(int) */ Math.floor(moduleSize / 2.0);\n top += nudge;\n left += nudge;\n // But careful that this does not sample off the edge\n // \"right\" is the farthest-right valid pixel location -- right+1 is not necessarily\n // This is positive by how much the inner x loop below would be too large\n const nudgedTooFarRight = left + /*(int) */ Math.floor((matrixWidth - 1) * moduleSize) - right;\n if (nudgedTooFarRight > 0) {\n if (nudgedTooFarRight > nudge) {\n // Neither way fits; abort\n throw new NotFoundException();\n }\n left -= nudgedTooFarRight;\n }\n // See logic above\n const nudgedTooFarDown = top + /*(int) */ Math.floor((matrixHeight - 1) * moduleSize) - bottom;\n if (nudgedTooFarDown > 0) {\n if (nudgedTooFarDown > nudge) {\n // Neither way fits; abort\n throw new NotFoundException();\n }\n top -= nudgedTooFarDown;\n }\n // Now just read off the bits\n const bits = new BitMatrix(matrixWidth, matrixHeight);\n for (let y = 0; y < matrixHeight; y++) {\n const iOffset = top + /*(int) */ Math.floor(y * moduleSize);\n for (let x = 0; x < matrixWidth; x++) {\n if (image.get(left + /*(int) */ Math.floor(x * moduleSize), iOffset)) {\n bits.set(x, y);\n }\n }\n }\n return bits;\n }\n static moduleSize(leftTopBlack, image) {\n const height = image.getHeight();\n const width = image.getWidth();\n let x = leftTopBlack[0];\n let y = leftTopBlack[1];\n let inBlack = true;\n let transitions = 0;\n while (x < width && y < height) {\n if (inBlack !== image.get(x, y)) {\n if (++transitions === 5) {\n break;\n }\n inBlack = !inBlack;\n }\n x++;\n y++;\n }\n if (x === width || y === height) {\n throw new NotFoundException();\n }\n return (x - leftTopBlack[0]) / 7.0;\n }\n }\n QRCodeReader.NO_POINTS = new Array();\n\n /*\n * Copyright 2009 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n /**\n * @author SITA Lab (kevin.osullivan@sita.aero)\n * @author Guenther Grau\n */\n /*public final*/ class PDF417Common {\n PDF417Common() {\n }\n /**\n * @param moduleBitCount values to sum\n * @return sum of values\n * @deprecated call {@link MathUtils#sum(int[])}\n */\n // @Deprecated\n static getBitCountSum(moduleBitCount) {\n return MathUtils.sum(moduleBitCount);\n }\n static toIntArray(list) {\n if (list == null || !list.length) {\n return PDF417Common.EMPTY_INT_ARRAY;\n }\n const result = new Int32Array(list.length);\n let i = 0;\n for (const integer of list) {\n result[i++] = integer;\n }\n return result;\n }\n /**\n * @param symbol encoded symbol to translate to a codeword\n * @return the codeword corresponding to the symbol.\n */\n static getCodeword(symbol /*int*/) {\n const i = Arrays.binarySearch(PDF417Common.SYMBOL_TABLE, symbol & 0x3FFFF);\n if (i < 0) {\n return -1;\n }\n return (PDF417Common.CODEWORD_TABLE[i] - 1) % PDF417Common.NUMBER_OF_CODEWORDS;\n }\n }\n PDF417Common.NUMBER_OF_CODEWORDS = 929;\n // Maximum Codewords (Data + Error).\n PDF417Common.MAX_CODEWORDS_IN_BARCODE = PDF417Common.NUMBER_OF_CODEWORDS - 1;\n PDF417Common.MIN_ROWS_IN_BARCODE = 3;\n PDF417Common.MAX_ROWS_IN_BARCODE = 90;\n // One left row indication column + max 30 data columns + one right row indicator column\n // public static /*final*/ MAX_CODEWORDS_IN_ROW: /*int*/ number = 32;\n PDF417Common.MODULES_IN_CODEWORD = 17;\n PDF417Common.MODULES_IN_STOP_PATTERN = 18;\n PDF417Common.BARS_IN_MODULE = 8;\n PDF417Common.EMPTY_INT_ARRAY = new Int32Array([]);\n /**\n * The sorted table of all possible symbols. Extracted from the PDF417\n * specification. The index of a symbol in this table corresponds to the\n * index into the codeword table.\n */\n PDF417Common.SYMBOL_TABLE = Int32Array.from([\n 0x1025e, 0x1027a, 0x1029e, 0x102bc, 0x102f2, 0x102f4, 0x1032e, 0x1034e, 0x1035c, 0x10396, 0x103a6, 0x103ac,\n 0x10422, 0x10428, 0x10436, 0x10442, 0x10444, 0x10448, 0x10450, 0x1045e, 0x10466, 0x1046c, 0x1047a, 0x10482,\n 0x1049e, 0x104a0, 0x104bc, 0x104c6, 0x104d8, 0x104ee, 0x104f2, 0x104f4, 0x10504, 0x10508, 0x10510, 0x1051e,\n 0x10520, 0x1053c, 0x10540, 0x10578, 0x10586, 0x1058c, 0x10598, 0x105b0, 0x105be, 0x105ce, 0x105dc, 0x105e2,\n 0x105e4, 0x105e8, 0x105f6, 0x1062e, 0x1064e, 0x1065c, 0x1068e, 0x1069c, 0x106b8, 0x106de, 0x106fa, 0x10716,\n 0x10726, 0x1072c, 0x10746, 0x1074c, 0x10758, 0x1076e, 0x10792, 0x10794, 0x107a2, 0x107a4, 0x107a8, 0x107b6,\n 0x10822, 0x10828, 0x10842, 0x10848, 0x10850, 0x1085e, 0x10866, 0x1086c, 0x1087a, 0x10882, 0x10884, 0x10890,\n 0x1089e, 0x108a0, 0x108bc, 0x108c6, 0x108cc, 0x108d8, 0x108ee, 0x108f2, 0x108f4, 0x10902, 0x10908, 0x1091e,\n 0x10920, 0x1093c, 0x10940, 0x10978, 0x10986, 0x10998, 0x109b0, 0x109be, 0x109ce, 0x109dc, 0x109e2, 0x109e4,\n 0x109e8, 0x109f6, 0x10a08, 0x10a10, 0x10a1e, 0x10a20, 0x10a3c, 0x10a40, 0x10a78, 0x10af0, 0x10b06, 0x10b0c,\n 0x10b18, 0x10b30, 0x10b3e, 0x10b60, 0x10b7c, 0x10b8e, 0x10b9c, 0x10bb8, 0x10bc2, 0x10bc4, 0x10bc8, 0x10bd0,\n 0x10bde, 0x10be6, 0x10bec, 0x10c2e, 0x10c4e, 0x10c5c, 0x10c62, 0x10c64, 0x10c68, 0x10c76, 0x10c8e, 0x10c9c,\n 0x10cb8, 0x10cc2, 0x10cc4, 0x10cc8, 0x10cd0, 0x10cde, 0x10ce6, 0x10cec, 0x10cfa, 0x10d0e, 0x10d1c, 0x10d38,\n 0x10d70, 0x10d7e, 0x10d82, 0x10d84, 0x10d88, 0x10d90, 0x10d9e, 0x10da0, 0x10dbc, 0x10dc6, 0x10dcc, 0x10dd8,\n 0x10dee, 0x10df2, 0x10df4, 0x10e16, 0x10e26, 0x10e2c, 0x10e46, 0x10e58, 0x10e6e, 0x10e86, 0x10e8c, 0x10e98,\n 0x10eb0, 0x10ebe, 0x10ece, 0x10edc, 0x10f0a, 0x10f12, 0x10f14, 0x10f22, 0x10f28, 0x10f36, 0x10f42, 0x10f44,\n 0x10f48, 0x10f50, 0x10f5e, 0x10f66, 0x10f6c, 0x10fb2, 0x10fb4, 0x11022, 0x11028, 0x11042, 0x11048, 0x11050,\n 0x1105e, 0x1107a, 0x11082, 0x11084, 0x11090, 0x1109e, 0x110a0, 0x110bc, 0x110c6, 0x110cc, 0x110d8, 0x110ee,\n 0x110f2, 0x110f4, 0x11102, 0x1111e, 0x11120, 0x1113c, 0x11140, 0x11178, 0x11186, 0x11198, 0x111b0, 0x111be,\n 0x111ce, 0x111dc, 0x111e2, 0x111e4, 0x111e8, 0x111f6, 0x11208, 0x1121e, 0x11220, 0x11278, 0x112f0, 0x1130c,\n 0x11330, 0x1133e, 0x11360, 0x1137c, 0x1138e, 0x1139c, 0x113b8, 0x113c2, 0x113c8, 0x113d0, 0x113de, 0x113e6,\n 0x113ec, 0x11408, 0x11410, 0x1141e, 0x11420, 0x1143c, 0x11440, 0x11478, 0x114f0, 0x115e0, 0x1160c, 0x11618,\n 0x11630, 0x1163e, 0x11660, 0x1167c, 0x116c0, 0x116f8, 0x1171c, 0x11738, 0x11770, 0x1177e, 0x11782, 0x11784,\n 0x11788, 0x11790, 0x1179e, 0x117a0, 0x117bc, 0x117c6, 0x117cc, 0x117d8, 0x117ee, 0x1182e, 0x11834, 0x1184e,\n 0x1185c, 0x11862, 0x11864, 0x11868, 0x11876, 0x1188e, 0x1189c, 0x118b8, 0x118c2, 0x118c8, 0x118d0, 0x118de,\n 0x118e6, 0x118ec, 0x118fa, 0x1190e, 0x1191c, 0x11938, 0x11970, 0x1197e, 0x11982, 0x11984, 0x11990, 0x1199e,\n 0x119a0, 0x119bc, 0x119c6, 0x119cc, 0x119d8, 0x119ee, 0x119f2, 0x119f4, 0x11a0e, 0x11a1c, 0x11a38, 0x11a70,\n 0x11a7e, 0x11ae0, 0x11afc, 0x11b08, 0x11b10, 0x11b1e, 0x11b20, 0x11b3c, 0x11b40, 0x11b78, 0x11b8c, 0x11b98,\n 0x11bb0, 0x11bbe, 0x11bce, 0x11bdc, 0x11be2, 0x11be4, 0x11be8, 0x11bf6, 0x11c16, 0x11c26, 0x11c2c, 0x11c46,\n 0x11c4c, 0x11c58, 0x11c6e, 0x11c86, 0x11c98, 0x11cb0, 0x11cbe, 0x11cce, 0x11cdc, 0x11ce2, 0x11ce4, 0x11ce8,\n 0x11cf6, 0x11d06, 0x11d0c, 0x11d18, 0x11d30, 0x11d3e, 0x11d60, 0x11d7c, 0x11d8e, 0x11d9c, 0x11db8, 0x11dc4,\n 0x11dc8, 0x11dd0, 0x11dde, 0x11de6, 0x11dec, 0x11dfa, 0x11e0a, 0x11e12, 0x11e14, 0x11e22, 0x11e24, 0x11e28,\n 0x11e36, 0x11e42, 0x11e44, 0x11e50, 0x11e5e, 0x11e66, 0x11e6c, 0x11e82, 0x11e84, 0x11e88, 0x11e90, 0x11e9e,\n 0x11ea0, 0x11ebc, 0x11ec6, 0x11ecc, 0x11ed8, 0x11eee, 0x11f1a, 0x11f2e, 0x11f32, 0x11f34, 0x11f4e, 0x11f5c,\n 0x11f62, 0x11f64, 0x11f68, 0x11f76, 0x12048, 0x1205e, 0x12082, 0x12084, 0x12090, 0x1209e, 0x120a0, 0x120bc,\n 0x120d8, 0x120f2, 0x120f4, 0x12108, 0x1211e, 0x12120, 0x1213c, 0x12140, 0x12178, 0x12186, 0x12198, 0x121b0,\n 0x121be, 0x121e2, 0x121e4, 0x121e8, 0x121f6, 0x12204, 0x12210, 0x1221e, 0x12220, 0x12278, 0x122f0, 0x12306,\n 0x1230c, 0x12330, 0x1233e, 0x12360, 0x1237c, 0x1238e, 0x1239c, 0x123b8, 0x123c2, 0x123c8, 0x123d0, 0x123e6,\n 0x123ec, 0x1241e, 0x12420, 0x1243c, 0x124f0, 0x125e0, 0x12618, 0x1263e, 0x12660, 0x1267c, 0x126c0, 0x126f8,\n 0x12738, 0x12770, 0x1277e, 0x12782, 0x12784, 0x12790, 0x1279e, 0x127a0, 0x127bc, 0x127c6, 0x127cc, 0x127d8,\n 0x127ee, 0x12820, 0x1283c, 0x12840, 0x12878, 0x128f0, 0x129e0, 0x12bc0, 0x12c18, 0x12c30, 0x12c3e, 0x12c60,\n 0x12c7c, 0x12cc0, 0x12cf8, 0x12df0, 0x12e1c, 0x12e38, 0x12e70, 0x12e7e, 0x12ee0, 0x12efc, 0x12f04, 0x12f08,\n 0x12f10, 0x12f20, 0x12f3c, 0x12f40, 0x12f78, 0x12f86, 0x12f8c, 0x12f98, 0x12fb0, 0x12fbe, 0x12fce, 0x12fdc,\n 0x1302e, 0x1304e, 0x1305c, 0x13062, 0x13068, 0x1308e, 0x1309c, 0x130b8, 0x130c2, 0x130c8, 0x130d0, 0x130de,\n 0x130ec, 0x130fa, 0x1310e, 0x13138, 0x13170, 0x1317e, 0x13182, 0x13184, 0x13190, 0x1319e, 0x131a0, 0x131bc,\n 0x131c6, 0x131cc, 0x131d8, 0x131f2, 0x131f4, 0x1320e, 0x1321c, 0x13270, 0x1327e, 0x132e0, 0x132fc, 0x13308,\n 0x1331e, 0x13320, 0x1333c, 0x13340, 0x13378, 0x13386, 0x13398, 0x133b0, 0x133be, 0x133ce, 0x133dc, 0x133e2,\n 0x133e4, 0x133e8, 0x133f6, 0x1340e, 0x1341c, 0x13438, 0x13470, 0x1347e, 0x134e0, 0x134fc, 0x135c0, 0x135f8,\n 0x13608, 0x13610, 0x1361e, 0x13620, 0x1363c, 0x13640, 0x13678, 0x136f0, 0x1370c, 0x13718, 0x13730, 0x1373e,\n 0x13760, 0x1377c, 0x1379c, 0x137b8, 0x137c2, 0x137c4, 0x137c8, 0x137d0, 0x137de, 0x137e6, 0x137ec, 0x13816,\n 0x13826, 0x1382c, 0x13846, 0x1384c, 0x13858, 0x1386e, 0x13874, 0x13886, 0x13898, 0x138b0, 0x138be, 0x138ce,\n 0x138dc, 0x138e2, 0x138e4, 0x138e8, 0x13906, 0x1390c, 0x13930, 0x1393e, 0x13960, 0x1397c, 0x1398e, 0x1399c,\n 0x139b8, 0x139c8, 0x139d0, 0x139de, 0x139e6, 0x139ec, 0x139fa, 0x13a06, 0x13a0c, 0x13a18, 0x13a30, 0x13a3e,\n 0x13a60, 0x13a7c, 0x13ac0, 0x13af8, 0x13b0e, 0x13b1c, 0x13b38, 0x13b70, 0x13b7e, 0x13b88, 0x13b90, 0x13b9e,\n 0x13ba0, 0x13bbc, 0x13bcc, 0x13bd8, 0x13bee, 0x13bf2, 0x13bf4, 0x13c12, 0x13c14, 0x13c22, 0x13c24, 0x13c28,\n 0x13c36, 0x13c42, 0x13c48, 0x13c50, 0x13c5e, 0x13c66, 0x13c6c, 0x13c82, 0x13c84, 0x13c90, 0x13c9e, 0x13ca0,\n 0x13cbc, 0x13cc6, 0x13ccc, 0x13cd8, 0x13cee, 0x13d02, 0x13d04, 0x13d08, 0x13d10, 0x13d1e, 0x13d20, 0x13d3c,\n 0x13d40, 0x13d78, 0x13d86, 0x13d8c, 0x13d98, 0x13db0, 0x13dbe, 0x13dce, 0x13ddc, 0x13de4, 0x13de8, 0x13df6,\n 0x13e1a, 0x13e2e, 0x13e32, 0x13e34, 0x13e4e, 0x13e5c, 0x13e62, 0x13e64, 0x13e68, 0x13e76, 0x13e8e, 0x13e9c,\n 0x13eb8, 0x13ec2, 0x13ec4, 0x13ec8, 0x13ed0, 0x13ede, 0x13ee6, 0x13eec, 0x13f26, 0x13f2c, 0x13f3a, 0x13f46,\n 0x13f4c, 0x13f58, 0x13f6e, 0x13f72, 0x13f74, 0x14082, 0x1409e, 0x140a0, 0x140bc, 0x14104, 0x14108, 0x14110,\n 0x1411e, 0x14120, 0x1413c, 0x14140, 0x14178, 0x1418c, 0x14198, 0x141b0, 0x141be, 0x141e2, 0x141e4, 0x141e8,\n 0x14208, 0x14210, 0x1421e, 0x14220, 0x1423c, 0x14240, 0x14278, 0x142f0, 0x14306, 0x1430c, 0x14318, 0x14330,\n 0x1433e, 0x14360, 0x1437c, 0x1438e, 0x143c2, 0x143c4, 0x143c8, 0x143d0, 0x143e6, 0x143ec, 0x14408, 0x14410,\n 0x1441e, 0x14420, 0x1443c, 0x14440, 0x14478, 0x144f0, 0x145e0, 0x1460c, 0x14618, 0x14630, 0x1463e, 0x14660,\n 0x1467c, 0x146c0, 0x146f8, 0x1471c, 0x14738, 0x14770, 0x1477e, 0x14782, 0x14784, 0x14788, 0x14790, 0x147a0,\n 0x147bc, 0x147c6, 0x147cc, 0x147d8, 0x147ee, 0x14810, 0x14820, 0x1483c, 0x14840, 0x14878, 0x148f0, 0x149e0,\n 0x14bc0, 0x14c30, 0x14c3e, 0x14c60, 0x14c7c, 0x14cc0, 0x14cf8, 0x14df0, 0x14e38, 0x14e70, 0x14e7e, 0x14ee0,\n 0x14efc, 0x14f04, 0x14f08, 0x14f10, 0x14f1e, 0x14f20, 0x14f3c, 0x14f40, 0x14f78, 0x14f86, 0x14f8c, 0x14f98,\n 0x14fb0, 0x14fce, 0x14fdc, 0x15020, 0x15040, 0x15078, 0x150f0, 0x151e0, 0x153c0, 0x15860, 0x1587c, 0x158c0,\n 0x158f8, 0x159f0, 0x15be0, 0x15c70, 0x15c7e, 0x15ce0, 0x15cfc, 0x15dc0, 0x15df8, 0x15e08, 0x15e10, 0x15e20,\n 0x15e40, 0x15e78, 0x15ef0, 0x15f0c, 0x15f18, 0x15f30, 0x15f60, 0x15f7c, 0x15f8e, 0x15f9c, 0x15fb8, 0x1604e,\n 0x1605c, 0x1608e, 0x1609c, 0x160b8, 0x160c2, 0x160c4, 0x160c8, 0x160de, 0x1610e, 0x1611c, 0x16138, 0x16170,\n 0x1617e, 0x16184, 0x16188, 0x16190, 0x1619e, 0x161a0, 0x161bc, 0x161c6, 0x161cc, 0x161d8, 0x161f2, 0x161f4,\n 0x1620e, 0x1621c, 0x16238, 0x16270, 0x1627e, 0x162e0, 0x162fc, 0x16304, 0x16308, 0x16310, 0x1631e, 0x16320,\n 0x1633c, 0x16340, 0x16378, 0x16386, 0x1638c, 0x16398, 0x163b0, 0x163be, 0x163ce, 0x163dc, 0x163e2, 0x163e4,\n 0x163e8, 0x163f6, 0x1640e, 0x1641c, 0x16438, 0x16470, 0x1647e, 0x164e0, 0x164fc, 0x165c0, 0x165f8, 0x16610,\n 0x1661e, 0x16620, 0x1663c, 0x16640, 0x16678, 0x166f0, 0x16718, 0x16730, 0x1673e, 0x16760, 0x1677c, 0x1678e,\n 0x1679c, 0x167b8, 0x167c2, 0x167c4, 0x167c8, 0x167d0, 0x167de, 0x167e6, 0x167ec, 0x1681c, 0x16838, 0x16870,\n 0x168e0, 0x168fc, 0x169c0, 0x169f8, 0x16bf0, 0x16c10, 0x16c1e, 0x16c20, 0x16c3c, 0x16c40, 0x16c78, 0x16cf0,\n 0x16de0, 0x16e18, 0x16e30, 0x16e3e, 0x16e60, 0x16e7c, 0x16ec0, 0x16ef8, 0x16f1c, 0x16f38, 0x16f70, 0x16f7e,\n 0x16f84, 0x16f88, 0x16f90, 0x16f9e, 0x16fa0, 0x16fbc, 0x16fc6, 0x16fcc, 0x16fd8, 0x17026, 0x1702c, 0x17046,\n 0x1704c, 0x17058, 0x1706e, 0x17086, 0x1708c, 0x17098, 0x170b0, 0x170be, 0x170ce, 0x170dc, 0x170e8, 0x17106,\n 0x1710c, 0x17118, 0x17130, 0x1713e, 0x17160, 0x1717c, 0x1718e, 0x1719c, 0x171b8, 0x171c2, 0x171c4, 0x171c8,\n 0x171d0, 0x171de, 0x171e6, 0x171ec, 0x171fa, 0x17206, 0x1720c, 0x17218, 0x17230, 0x1723e, 0x17260, 0x1727c,\n 0x172c0, 0x172f8, 0x1730e, 0x1731c, 0x17338, 0x17370, 0x1737e, 0x17388, 0x17390, 0x1739e, 0x173a0, 0x173bc,\n 0x173cc, 0x173d8, 0x173ee, 0x173f2, 0x173f4, 0x1740c, 0x17418, 0x17430, 0x1743e, 0x17460, 0x1747c, 0x174c0,\n 0x174f8, 0x175f0, 0x1760e, 0x1761c, 0x17638, 0x17670, 0x1767e, 0x176e0, 0x176fc, 0x17708, 0x17710, 0x1771e,\n 0x17720, 0x1773c, 0x17740, 0x17778, 0x17798, 0x177b0, 0x177be, 0x177dc, 0x177e2, 0x177e4, 0x177e8, 0x17822,\n 0x17824, 0x17828, 0x17836, 0x17842, 0x17844, 0x17848, 0x17850, 0x1785e, 0x17866, 0x1786c, 0x17882, 0x17884,\n 0x17888, 0x17890, 0x1789e, 0x178a0, 0x178bc, 0x178c6, 0x178cc, 0x178d8, 0x178ee, 0x178f2, 0x178f4, 0x17902,\n 0x17904, 0x17908, 0x17910, 0x1791e, 0x17920, 0x1793c, 0x17940, 0x17978, 0x17986, 0x1798c, 0x17998, 0x179b0,\n 0x179be, 0x179ce, 0x179dc, 0x179e2, 0x179e4, 0x179e8, 0x179f6, 0x17a04, 0x17a08, 0x17a10, 0x17a1e, 0x17a20,\n 0x17a3c, 0x17a40, 0x17a78, 0x17af0, 0x17b06, 0x17b0c, 0x17b18, 0x17b30, 0x17b3e, 0x17b60, 0x17b7c, 0x17b8e,\n 0x17b9c, 0x17bb8, 0x17bc4, 0x17bc8, 0x17bd0, 0x17bde, 0x17be6, 0x17bec, 0x17c2e, 0x17c32, 0x17c34, 0x17c4e,\n 0x17c5c, 0x17c62, 0x17c64, 0x17c68, 0x17c76, 0x17c8e, 0x17c9c, 0x17cb8, 0x17cc2, 0x17cc4, 0x17cc8, 0x17cd0,\n 0x17cde, 0x17ce6, 0x17cec, 0x17d0e, 0x17d1c, 0x17d38, 0x17d70, 0x17d82, 0x17d84, 0x17d88, 0x17d90, 0x17d9e,\n 0x17da0, 0x17dbc, 0x17dc6, 0x17dcc, 0x17dd8, 0x17dee, 0x17e26, 0x17e2c, 0x17e3a, 0x17e46, 0x17e4c, 0x17e58,\n 0x17e6e, 0x17e72, 0x17e74, 0x17e86, 0x17e8c, 0x17e98, 0x17eb0, 0x17ece, 0x17edc, 0x17ee2, 0x17ee4, 0x17ee8,\n 0x17ef6, 0x1813a, 0x18172, 0x18174, 0x18216, 0x18226, 0x1823a, 0x1824c, 0x18258, 0x1826e, 0x18272, 0x18274,\n 0x18298, 0x182be, 0x182e2, 0x182e4, 0x182e8, 0x182f6, 0x1835e, 0x1837a, 0x183ae, 0x183d6, 0x18416, 0x18426,\n 0x1842c, 0x1843a, 0x18446, 0x18458, 0x1846e, 0x18472, 0x18474, 0x18486, 0x184b0, 0x184be, 0x184ce, 0x184dc,\n 0x184e2, 0x184e4, 0x184e8, 0x184f6, 0x18506, 0x1850c, 0x18518, 0x18530, 0x1853e, 0x18560, 0x1857c, 0x1858e,\n 0x1859c, 0x185b8, 0x185c2, 0x185c4, 0x185c8, 0x185d0, 0x185de, 0x185e6, 0x185ec, 0x185fa, 0x18612, 0x18614,\n 0x18622, 0x18628, 0x18636, 0x18642, 0x18650, 0x1865e, 0x1867a, 0x18682, 0x18684, 0x18688, 0x18690, 0x1869e,\n 0x186a0, 0x186bc, 0x186c6, 0x186cc, 0x186d8, 0x186ee, 0x186f2, 0x186f4, 0x1872e, 0x1874e, 0x1875c, 0x18796,\n 0x187a6, 0x187ac, 0x187d2, 0x187d4, 0x18826, 0x1882c, 0x1883a, 0x18846, 0x1884c, 0x18858, 0x1886e, 0x18872,\n 0x18874, 0x18886, 0x18898, 0x188b0, 0x188be, 0x188ce, 0x188dc, 0x188e2, 0x188e4, 0x188e8, 0x188f6, 0x1890c,\n 0x18930, 0x1893e, 0x18960, 0x1897c, 0x1898e, 0x189b8, 0x189c2, 0x189c8, 0x189d0, 0x189de, 0x189e6, 0x189ec,\n 0x189fa, 0x18a18, 0x18a30, 0x18a3e, 0x18a60, 0x18a7c, 0x18ac0, 0x18af8, 0x18b1c, 0x18b38, 0x18b70, 0x18b7e,\n 0x18b82, 0x18b84, 0x18b88, 0x18b90, 0x18b9e, 0x18ba0, 0x18bbc, 0x18bc6, 0x18bcc, 0x18bd8, 0x18bee, 0x18bf2,\n 0x18bf4, 0x18c22, 0x18c24, 0x18c28, 0x18c36, 0x18c42, 0x18c48, 0x18c50, 0x18c5e, 0x18c66, 0x18c7a, 0x18c82,\n 0x18c84, 0x18c90, 0x18c9e, 0x18ca0, 0x18cbc, 0x18ccc, 0x18cf2, 0x18cf4, 0x18d04, 0x18d08, 0x18d10, 0x18d1e,\n 0x18d20, 0x18d3c, 0x18d40, 0x18d78, 0x18d86, 0x18d98, 0x18dce, 0x18de2, 0x18de4, 0x18de8, 0x18e2e, 0x18e32,\n 0x18e34, 0x18e4e, 0x18e5c, 0x18e62, 0x18e64, 0x18e68, 0x18e8e, 0x18e9c, 0x18eb8, 0x18ec2, 0x18ec4, 0x18ec8,\n 0x18ed0, 0x18efa, 0x18f16, 0x18f26, 0x18f2c, 0x18f46, 0x18f4c, 0x18f58, 0x18f6e, 0x18f8a, 0x18f92, 0x18f94,\n 0x18fa2, 0x18fa4, 0x18fa8, 0x18fb6, 0x1902c, 0x1903a, 0x19046, 0x1904c, 0x19058, 0x19072, 0x19074, 0x19086,\n 0x19098, 0x190b0, 0x190be, 0x190ce, 0x190dc, 0x190e2, 0x190e8, 0x190f6, 0x19106, 0x1910c, 0x19130, 0x1913e,\n 0x19160, 0x1917c, 0x1918e, 0x1919c, 0x191b8, 0x191c2, 0x191c8, 0x191d0, 0x191de, 0x191e6, 0x191ec, 0x191fa,\n 0x19218, 0x1923e, 0x19260, 0x1927c, 0x192c0, 0x192f8, 0x19338, 0x19370, 0x1937e, 0x19382, 0x19384, 0x19390,\n 0x1939e, 0x193a0, 0x193bc, 0x193c6, 0x193cc, 0x193d8, 0x193ee, 0x193f2, 0x193f4, 0x19430, 0x1943e, 0x19460,\n 0x1947c, 0x194c0, 0x194f8, 0x195f0, 0x19638, 0x19670, 0x1967e, 0x196e0, 0x196fc, 0x19702, 0x19704, 0x19708,\n 0x19710, 0x19720, 0x1973c, 0x19740, 0x19778, 0x19786, 0x1978c, 0x19798, 0x197b0, 0x197be, 0x197ce, 0x197dc,\n 0x197e2, 0x197e4, 0x197e8, 0x19822, 0x19824, 0x19842, 0x19848, 0x19850, 0x1985e, 0x19866, 0x1987a, 0x19882,\n 0x19884, 0x19890, 0x1989e, 0x198a0, 0x198bc, 0x198cc, 0x198f2, 0x198f4, 0x19902, 0x19908, 0x1991e, 0x19920,\n 0x1993c, 0x19940, 0x19978, 0x19986, 0x19998, 0x199ce, 0x199e2, 0x199e4, 0x199e8, 0x19a08, 0x19a10, 0x19a1e,\n 0x19a20, 0x19a3c, 0x19a40, 0x19a78, 0x19af0, 0x19b18, 0x19b3e, 0x19b60, 0x19b9c, 0x19bc2, 0x19bc4, 0x19bc8,\n 0x19bd0, 0x19be6, 0x19c2e, 0x19c34, 0x19c4e, 0x19c5c, 0x19c62, 0x19c64, 0x19c68, 0x19c8e, 0x19c9c, 0x19cb8,\n 0x19cc2, 0x19cc8, 0x19cd0, 0x19ce6, 0x19cfa, 0x19d0e, 0x19d1c, 0x19d38, 0x19d70, 0x19d7e, 0x19d82, 0x19d84,\n 0x19d88, 0x19d90, 0x19da0, 0x19dcc, 0x19df2, 0x19df4, 0x19e16, 0x19e26, 0x19e2c, 0x19e46, 0x19e4c, 0x19e58,\n 0x19e74, 0x19e86, 0x19e8c, 0x19e98, 0x19eb0, 0x19ebe, 0x19ece, 0x19ee2, 0x19ee4, 0x19ee8, 0x19f0a, 0x19f12,\n 0x19f14, 0x19f22, 0x19f24, 0x19f28, 0x19f42, 0x19f44, 0x19f48, 0x19f50, 0x19f5e, 0x19f6c, 0x19f9a, 0x19fae,\n 0x19fb2, 0x19fb4, 0x1a046, 0x1a04c, 0x1a072, 0x1a074, 0x1a086, 0x1a08c, 0x1a098, 0x1a0b0, 0x1a0be, 0x1a0e2,\n 0x1a0e4, 0x1a0e8, 0x1a0f6, 0x1a106, 0x1a10c, 0x1a118, 0x1a130, 0x1a13e, 0x1a160, 0x1a17c, 0x1a18e, 0x1a19c,\n 0x1a1b8, 0x1a1c2, 0x1a1c4, 0x1a1c8, 0x1a1d0, 0x1a1de, 0x1a1e6, 0x1a1ec, 0x1a218, 0x1a230, 0x1a23e, 0x1a260,\n 0x1a27c, 0x1a2c0, 0x1a2f8, 0x1a31c, 0x1a338, 0x1a370, 0x1a37e, 0x1a382, 0x1a384, 0x1a388, 0x1a390, 0x1a39e,\n 0x1a3a0, 0x1a3bc, 0x1a3c6, 0x1a3cc, 0x1a3d8, 0x1a3ee, 0x1a3f2, 0x1a3f4, 0x1a418, 0x1a430, 0x1a43e, 0x1a460,\n 0x1a47c, 0x1a4c0, 0x1a4f8, 0x1a5f0, 0x1a61c, 0x1a638, 0x1a670, 0x1a67e, 0x1a6e0, 0x1a6fc, 0x1a702, 0x1a704,\n 0x1a708, 0x1a710, 0x1a71e, 0x1a720, 0x1a73c, 0x1a740, 0x1a778, 0x1a786, 0x1a78c, 0x1a798, 0x1a7b0, 0x1a7be,\n 0x1a7ce, 0x1a7dc, 0x1a7e2, 0x1a7e4, 0x1a7e8, 0x1a830, 0x1a860, 0x1a87c, 0x1a8c0, 0x1a8f8, 0x1a9f0, 0x1abe0,\n 0x1ac70, 0x1ac7e, 0x1ace0, 0x1acfc, 0x1adc0, 0x1adf8, 0x1ae04, 0x1ae08, 0x1ae10, 0x1ae20, 0x1ae3c, 0x1ae40,\n 0x1ae78, 0x1aef0, 0x1af06, 0x1af0c, 0x1af18, 0x1af30, 0x1af3e, 0x1af60, 0x1af7c, 0x1af8e, 0x1af9c, 0x1afb8,\n 0x1afc4, 0x1afc8, 0x1afd0, 0x1afde, 0x1b042, 0x1b05e, 0x1b07a, 0x1b082, 0x1b084, 0x1b088, 0x1b090, 0x1b09e,\n 0x1b0a0, 0x1b0bc, 0x1b0cc, 0x1b0f2, 0x1b0f4, 0x1b102, 0x1b104, 0x1b108, 0x1b110, 0x1b11e, 0x1b120, 0x1b13c,\n 0x1b140, 0x1b178, 0x1b186, 0x1b198, 0x1b1ce, 0x1b1e2, 0x1b1e4, 0x1b1e8, 0x1b204, 0x1b208, 0x1b210, 0x1b21e,\n 0x1b220, 0x1b23c, 0x1b240, 0x1b278, 0x1b2f0, 0x1b30c, 0x1b33e, 0x1b360, 0x1b39c, 0x1b3c2, 0x1b3c4, 0x1b3c8,\n 0x1b3d0, 0x1b3e6, 0x1b410, 0x1b41e, 0x1b420, 0x1b43c, 0x1b440, 0x1b478, 0x1b4f0, 0x1b5e0, 0x1b618, 0x1b660,\n 0x1b67c, 0x1b6c0, 0x1b738, 0x1b782, 0x1b784, 0x1b788, 0x1b790, 0x1b79e, 0x1b7a0, 0x1b7cc, 0x1b82e, 0x1b84e,\n 0x1b85c, 0x1b88e, 0x1b89c, 0x1b8b8, 0x1b8c2, 0x1b8c4, 0x1b8c8, 0x1b8d0, 0x1b8e6, 0x1b8fa, 0x1b90e, 0x1b91c,\n 0x1b938, 0x1b970, 0x1b97e, 0x1b982, 0x1b984, 0x1b988, 0x1b990, 0x1b99e, 0x1b9a0, 0x1b9cc, 0x1b9f2, 0x1b9f4,\n 0x1ba0e, 0x1ba1c, 0x1ba38, 0x1ba70, 0x1ba7e, 0x1bae0, 0x1bafc, 0x1bb08, 0x1bb10, 0x1bb20, 0x1bb3c, 0x1bb40,\n 0x1bb98, 0x1bbce, 0x1bbe2, 0x1bbe4, 0x1bbe8, 0x1bc16, 0x1bc26, 0x1bc2c, 0x1bc46, 0x1bc4c, 0x1bc58, 0x1bc72,\n 0x1bc74, 0x1bc86, 0x1bc8c, 0x1bc98, 0x1bcb0, 0x1bcbe, 0x1bcce, 0x1bce2, 0x1bce4, 0x1bce8, 0x1bd06, 0x1bd0c,\n 0x1bd18, 0x1bd30, 0x1bd3e, 0x1bd60, 0x1bd7c, 0x1bd9c, 0x1bdc2, 0x1bdc4, 0x1bdc8, 0x1bdd0, 0x1bde6, 0x1bdfa,\n 0x1be12, 0x1be14, 0x1be22, 0x1be24, 0x1be28, 0x1be42, 0x1be44, 0x1be48, 0x1be50, 0x1be5e, 0x1be66, 0x1be82,\n 0x1be84, 0x1be88, 0x1be90, 0x1be9e, 0x1bea0, 0x1bebc, 0x1becc, 0x1bef4, 0x1bf1a, 0x1bf2e, 0x1bf32, 0x1bf34,\n 0x1bf4e, 0x1bf5c, 0x1bf62, 0x1bf64, 0x1bf68, 0x1c09a, 0x1c0b2, 0x1c0b4, 0x1c11a, 0x1c132, 0x1c134, 0x1c162,\n 0x1c164, 0x1c168, 0x1c176, 0x1c1ba, 0x1c21a, 0x1c232, 0x1c234, 0x1c24e, 0x1c25c, 0x1c262, 0x1c264, 0x1c268,\n 0x1c276, 0x1c28e, 0x1c2c2, 0x1c2c4, 0x1c2c8, 0x1c2d0, 0x1c2de, 0x1c2e6, 0x1c2ec, 0x1c2fa, 0x1c316, 0x1c326,\n 0x1c33a, 0x1c346, 0x1c34c, 0x1c372, 0x1c374, 0x1c41a, 0x1c42e, 0x1c432, 0x1c434, 0x1c44e, 0x1c45c, 0x1c462,\n 0x1c464, 0x1c468, 0x1c476, 0x1c48e, 0x1c49c, 0x1c4b8, 0x1c4c2, 0x1c4c8, 0x1c4d0, 0x1c4de, 0x1c4e6, 0x1c4ec,\n 0x1c4fa, 0x1c51c, 0x1c538, 0x1c570, 0x1c57e, 0x1c582, 0x1c584, 0x1c588, 0x1c590, 0x1c59e, 0x1c5a0, 0x1c5bc,\n 0x1c5c6, 0x1c5cc, 0x1c5d8, 0x1c5ee, 0x1c5f2, 0x1c5f4, 0x1c616, 0x1c626, 0x1c62c, 0x1c63a, 0x1c646, 0x1c64c,\n 0x1c658, 0x1c66e, 0x1c672, 0x1c674, 0x1c686, 0x1c68c, 0x1c698, 0x1c6b0, 0x1c6be, 0x1c6ce, 0x1c6dc, 0x1c6e2,\n 0x1c6e4, 0x1c6e8, 0x1c712, 0x1c714, 0x1c722, 0x1c728, 0x1c736, 0x1c742, 0x1c744, 0x1c748, 0x1c750, 0x1c75e,\n 0x1c766, 0x1c76c, 0x1c77a, 0x1c7ae, 0x1c7d6, 0x1c7ea, 0x1c81a, 0x1c82e, 0x1c832, 0x1c834, 0x1c84e, 0x1c85c,\n 0x1c862, 0x1c864, 0x1c868, 0x1c876, 0x1c88e, 0x1c89c, 0x1c8b8, 0x1c8c2, 0x1c8c8, 0x1c8d0, 0x1c8de, 0x1c8e6,\n 0x1c8ec, 0x1c8fa, 0x1c90e, 0x1c938, 0x1c970, 0x1c97e, 0x1c982, 0x1c984, 0x1c990, 0x1c99e, 0x1c9a0, 0x1c9bc,\n 0x1c9c6, 0x1c9cc, 0x1c9d8, 0x1c9ee, 0x1c9f2, 0x1c9f4, 0x1ca38, 0x1ca70, 0x1ca7e, 0x1cae0, 0x1cafc, 0x1cb02,\n 0x1cb04, 0x1cb08, 0x1cb10, 0x1cb20, 0x1cb3c, 0x1cb40, 0x1cb78, 0x1cb86, 0x1cb8c, 0x1cb98, 0x1cbb0, 0x1cbbe,\n 0x1cbce, 0x1cbdc, 0x1cbe2, 0x1cbe4, 0x1cbe8, 0x1cbf6, 0x1cc16, 0x1cc26, 0x1cc2c, 0x1cc3a, 0x1cc46, 0x1cc58,\n 0x1cc72, 0x1cc74, 0x1cc86, 0x1ccb0, 0x1ccbe, 0x1ccce, 0x1cce2, 0x1cce4, 0x1cce8, 0x1cd06, 0x1cd0c, 0x1cd18,\n 0x1cd30, 0x1cd3e, 0x1cd60, 0x1cd7c, 0x1cd9c, 0x1cdc2, 0x1cdc4, 0x1cdc8, 0x1cdd0, 0x1cdde, 0x1cde6, 0x1cdfa,\n 0x1ce22, 0x1ce28, 0x1ce42, 0x1ce50, 0x1ce5e, 0x1ce66, 0x1ce7a, 0x1ce82, 0x1ce84, 0x1ce88, 0x1ce90, 0x1ce9e,\n 0x1cea0, 0x1cebc, 0x1cecc, 0x1cef2, 0x1cef4, 0x1cf2e, 0x1cf32, 0x1cf34, 0x1cf4e, 0x1cf5c, 0x1cf62, 0x1cf64,\n 0x1cf68, 0x1cf96, 0x1cfa6, 0x1cfac, 0x1cfca, 0x1cfd2, 0x1cfd4, 0x1d02e, 0x1d032, 0x1d034, 0x1d04e, 0x1d05c,\n 0x1d062, 0x1d064, 0x1d068, 0x1d076, 0x1d08e, 0x1d09c, 0x1d0b8, 0x1d0c2, 0x1d0c4, 0x1d0c8, 0x1d0d0, 0x1d0de,\n 0x1d0e6, 0x1d0ec, 0x1d0fa, 0x1d11c, 0x1d138, 0x1d170, 0x1d17e, 0x1d182, 0x1d184, 0x1d188, 0x1d190, 0x1d19e,\n 0x1d1a0, 0x1d1bc, 0x1d1c6, 0x1d1cc, 0x1d1d8, 0x1d1ee, 0x1d1f2, 0x1d1f4, 0x1d21c, 0x1d238, 0x1d270, 0x1d27e,\n 0x1d2e0, 0x1d2fc, 0x1d302, 0x1d304, 0x1d308, 0x1d310, 0x1d31e, 0x1d320, 0x1d33c, 0x1d340, 0x1d378, 0x1d386,\n 0x1d38c, 0x1d398, 0x1d3b0, 0x1d3be, 0x1d3ce, 0x1d3dc, 0x1d3e2, 0x1d3e4, 0x1d3e8, 0x1d3f6, 0x1d470, 0x1d47e,\n 0x1d4e0, 0x1d4fc, 0x1d5c0, 0x1d5f8, 0x1d604, 0x1d608, 0x1d610, 0x1d620, 0x1d640, 0x1d678, 0x1d6f0, 0x1d706,\n 0x1d70c, 0x1d718, 0x1d730, 0x1d73e, 0x1d760, 0x1d77c, 0x1d78e, 0x1d79c, 0x1d7b8, 0x1d7c2, 0x1d7c4, 0x1d7c8,\n 0x1d7d0, 0x1d7de, 0x1d7e6, 0x1d7ec, 0x1d826, 0x1d82c, 0x1d83a, 0x1d846, 0x1d84c, 0x1d858, 0x1d872, 0x1d874,\n 0x1d886, 0x1d88c, 0x1d898, 0x1d8b0, 0x1d8be, 0x1d8ce, 0x1d8e2, 0x1d8e4, 0x1d8e8, 0x1d8f6, 0x1d90c, 0x1d918,\n 0x1d930, 0x1d93e, 0x1d960, 0x1d97c, 0x1d99c, 0x1d9c2, 0x1d9c4, 0x1d9c8, 0x1d9d0, 0x1d9e6, 0x1d9fa, 0x1da0c,\n 0x1da18, 0x1da30, 0x1da3e, 0x1da60, 0x1da7c, 0x1dac0, 0x1daf8, 0x1db38, 0x1db82, 0x1db84, 0x1db88, 0x1db90,\n 0x1db9e, 0x1dba0, 0x1dbcc, 0x1dbf2, 0x1dbf4, 0x1dc22, 0x1dc42, 0x1dc44, 0x1dc48, 0x1dc50, 0x1dc5e, 0x1dc66,\n 0x1dc7a, 0x1dc82, 0x1dc84, 0x1dc88, 0x1dc90, 0x1dc9e, 0x1dca0, 0x1dcbc, 0x1dccc, 0x1dcf2, 0x1dcf4, 0x1dd04,\n 0x1dd08, 0x1dd10, 0x1dd1e, 0x1dd20, 0x1dd3c, 0x1dd40, 0x1dd78, 0x1dd86, 0x1dd98, 0x1ddce, 0x1dde2, 0x1dde4,\n 0x1dde8, 0x1de2e, 0x1de32, 0x1de34, 0x1de4e, 0x1de5c, 0x1de62, 0x1de64, 0x1de68, 0x1de8e, 0x1de9c, 0x1deb8,\n 0x1dec2, 0x1dec4, 0x1dec8, 0x1ded0, 0x1dee6, 0x1defa, 0x1df16, 0x1df26, 0x1df2c, 0x1df46, 0x1df4c, 0x1df58,\n 0x1df72, 0x1df74, 0x1df8a, 0x1df92, 0x1df94, 0x1dfa2, 0x1dfa4, 0x1dfa8, 0x1e08a, 0x1e092, 0x1e094, 0x1e0a2,\n 0x1e0a4, 0x1e0a8, 0x1e0b6, 0x1e0da, 0x1e10a, 0x1e112, 0x1e114, 0x1e122, 0x1e124, 0x1e128, 0x1e136, 0x1e142,\n 0x1e144, 0x1e148, 0x1e150, 0x1e166, 0x1e16c, 0x1e17a, 0x1e19a, 0x1e1b2, 0x1e1b4, 0x1e20a, 0x1e212, 0x1e214,\n 0x1e222, 0x1e224, 0x1e228, 0x1e236, 0x1e242, 0x1e248, 0x1e250, 0x1e25e, 0x1e266, 0x1e26c, 0x1e27a, 0x1e282,\n 0x1e284, 0x1e288, 0x1e290, 0x1e2a0, 0x1e2bc, 0x1e2c6, 0x1e2cc, 0x1e2d8, 0x1e2ee, 0x1e2f2, 0x1e2f4, 0x1e31a,\n 0x1e332, 0x1e334, 0x1e35c, 0x1e362, 0x1e364, 0x1e368, 0x1e3ba, 0x1e40a, 0x1e412, 0x1e414, 0x1e422, 0x1e428,\n 0x1e436, 0x1e442, 0x1e448, 0x1e450, 0x1e45e, 0x1e466, 0x1e46c, 0x1e47a, 0x1e482, 0x1e484, 0x1e490, 0x1e49e,\n 0x1e4a0, 0x1e4bc, 0x1e4c6, 0x1e4cc, 0x1e4d8, 0x1e4ee, 0x1e4f2, 0x1e4f4, 0x1e502, 0x1e504, 0x1e508, 0x1e510,\n 0x1e51e, 0x1e520, 0x1e53c, 0x1e540, 0x1e578, 0x1e586, 0x1e58c, 0x1e598, 0x1e5b0, 0x1e5be, 0x1e5ce, 0x1e5dc,\n 0x1e5e2, 0x1e5e4, 0x1e5e8, 0x1e5f6, 0x1e61a, 0x1e62e, 0x1e632, 0x1e634, 0x1e64e, 0x1e65c, 0x1e662, 0x1e668,\n 0x1e68e, 0x1e69c, 0x1e6b8, 0x1e6c2, 0x1e6c4, 0x1e6c8, 0x1e6d0, 0x1e6e6, 0x1e6fa, 0x1e716, 0x1e726, 0x1e72c,\n 0x1e73a, 0x1e746, 0x1e74c, 0x1e758, 0x1e772, 0x1e774, 0x1e792, 0x1e794, 0x1e7a2, 0x1e7a4, 0x1e7a8, 0x1e7b6,\n 0x1e812, 0x1e814, 0x1e822, 0x1e824, 0x1e828, 0x1e836, 0x1e842, 0x1e844, 0x1e848, 0x1e850, 0x1e85e, 0x1e866,\n 0x1e86c, 0x1e87a, 0x1e882, 0x1e884, 0x1e888, 0x1e890, 0x1e89e, 0x1e8a0, 0x1e8bc, 0x1e8c6, 0x1e8cc, 0x1e8d8,\n 0x1e8ee, 0x1e8f2, 0x1e8f4, 0x1e902, 0x1e904, 0x1e908, 0x1e910, 0x1e920, 0x1e93c, 0x1e940, 0x1e978, 0x1e986,\n 0x1e98c, 0x1e998, 0x1e9b0, 0x1e9be, 0x1e9ce, 0x1e9dc, 0x1e9e2, 0x1e9e4, 0x1e9e8, 0x1e9f6, 0x1ea04, 0x1ea08,\n 0x1ea10, 0x1ea20, 0x1ea40, 0x1ea78, 0x1eaf0, 0x1eb06, 0x1eb0c, 0x1eb18, 0x1eb30, 0x1eb3e, 0x1eb60, 0x1eb7c,\n 0x1eb8e, 0x1eb9c, 0x1ebb8, 0x1ebc2, 0x1ebc4, 0x1ebc8, 0x1ebd0, 0x1ebde, 0x1ebe6, 0x1ebec, 0x1ec1a, 0x1ec2e,\n 0x1ec32, 0x1ec34, 0x1ec4e, 0x1ec5c, 0x1ec62, 0x1ec64, 0x1ec68, 0x1ec8e, 0x1ec9c, 0x1ecb8, 0x1ecc2, 0x1ecc4,\n 0x1ecc8, 0x1ecd0, 0x1ece6, 0x1ecfa, 0x1ed0e, 0x1ed1c, 0x1ed38, 0x1ed70, 0x1ed7e, 0x1ed82, 0x1ed84, 0x1ed88,\n 0x1ed90, 0x1ed9e, 0x1eda0, 0x1edcc, 0x1edf2, 0x1edf4, 0x1ee16, 0x1ee26, 0x1ee2c, 0x1ee3a, 0x1ee46, 0x1ee4c,\n 0x1ee58, 0x1ee6e, 0x1ee72, 0x1ee74, 0x1ee86, 0x1ee8c, 0x1ee98, 0x1eeb0, 0x1eebe, 0x1eece, 0x1eedc, 0x1eee2,\n 0x1eee4, 0x1eee8, 0x1ef12, 0x1ef22, 0x1ef24, 0x1ef28, 0x1ef36, 0x1ef42, 0x1ef44, 0x1ef48, 0x1ef50, 0x1ef5e,\n 0x1ef66, 0x1ef6c, 0x1ef7a, 0x1efae, 0x1efb2, 0x1efb4, 0x1efd6, 0x1f096, 0x1f0a6, 0x1f0ac, 0x1f0ba, 0x1f0ca,\n 0x1f0d2, 0x1f0d4, 0x1f116, 0x1f126, 0x1f12c, 0x1f13a, 0x1f146, 0x1f14c, 0x1f158, 0x1f16e, 0x1f172, 0x1f174,\n 0x1f18a, 0x1f192, 0x1f194, 0x1f1a2, 0x1f1a4, 0x1f1a8, 0x1f1da, 0x1f216, 0x1f226, 0x1f22c, 0x1f23a, 0x1f246,\n 0x1f258, 0x1f26e, 0x1f272, 0x1f274, 0x1f286, 0x1f28c, 0x1f298, 0x1f2b0, 0x1f2be, 0x1f2ce, 0x1f2dc, 0x1f2e2,\n 0x1f2e4, 0x1f2e8, 0x1f2f6, 0x1f30a, 0x1f312, 0x1f314, 0x1f322, 0x1f328, 0x1f342, 0x1f344, 0x1f348, 0x1f350,\n 0x1f35e, 0x1f366, 0x1f37a, 0x1f39a, 0x1f3ae, 0x1f3b2, 0x1f3b4, 0x1f416, 0x1f426, 0x1f42c, 0x1f43a, 0x1f446,\n 0x1f44c, 0x1f458, 0x1f46e, 0x1f472, 0x1f474, 0x1f486, 0x1f48c, 0x1f498, 0x1f4b0, 0x1f4be, 0x1f4ce, 0x1f4dc,\n 0x1f4e2, 0x1f4e4, 0x1f4e8, 0x1f4f6, 0x1f506, 0x1f50c, 0x1f518, 0x1f530, 0x1f53e, 0x1f560, 0x1f57c, 0x1f58e,\n 0x1f59c, 0x1f5b8, 0x1f5c2, 0x1f5c4, 0x1f5c8, 0x1f5d0, 0x1f5de, 0x1f5e6, 0x1f5ec, 0x1f5fa, 0x1f60a, 0x1f612,\n 0x1f614, 0x1f622, 0x1f624, 0x1f628, 0x1f636, 0x1f642, 0x1f644, 0x1f648, 0x1f650, 0x1f65e, 0x1f666, 0x1f67a,\n 0x1f682, 0x1f684, 0x1f688, 0x1f690, 0x1f69e, 0x1f6a0, 0x1f6bc, 0x1f6cc, 0x1f6f2, 0x1f6f4, 0x1f71a, 0x1f72e,\n 0x1f732, 0x1f734, 0x1f74e, 0x1f75c, 0x1f762, 0x1f764, 0x1f768, 0x1f776, 0x1f796, 0x1f7a6, 0x1f7ac, 0x1f7ba,\n 0x1f7d2, 0x1f7d4, 0x1f89a, 0x1f8ae, 0x1f8b2, 0x1f8b4, 0x1f8d6, 0x1f8ea, 0x1f91a, 0x1f92e, 0x1f932, 0x1f934,\n 0x1f94e, 0x1f95c, 0x1f962, 0x1f964, 0x1f968, 0x1f976, 0x1f996, 0x1f9a6, 0x1f9ac, 0x1f9ba, 0x1f9ca, 0x1f9d2,\n 0x1f9d4, 0x1fa1a, 0x1fa2e, 0x1fa32, 0x1fa34, 0x1fa4e, 0x1fa5c, 0x1fa62, 0x1fa64, 0x1fa68, 0x1fa76, 0x1fa8e,\n 0x1fa9c, 0x1fab8, 0x1fac2, 0x1fac4, 0x1fac8, 0x1fad0, 0x1fade, 0x1fae6, 0x1faec, 0x1fb16, 0x1fb26, 0x1fb2c,\n 0x1fb3a, 0x1fb46, 0x1fb4c, 0x1fb58, 0x1fb6e, 0x1fb72, 0x1fb74, 0x1fb8a, 0x1fb92, 0x1fb94, 0x1fba2, 0x1fba4,\n 0x1fba8, 0x1fbb6, 0x1fbda\n ]);\n /**\n * This table contains to codewords for all symbols.\n */\n PDF417Common.CODEWORD_TABLE = Int32Array.from([\n 2627, 1819, 2622, 2621, 1813, 1812, 2729, 2724, 2723, 2779, 2774, 2773, 902, 896, 908, 868, 865, 861, 859, 2511,\n 873, 871, 1780, 835, 2493, 825, 2491, 842, 837, 844, 1764, 1762, 811, 810, 809, 2483, 807, 2482, 806, 2480, 815,\n 814, 813, 812, 2484, 817, 816, 1745, 1744, 1742, 1746, 2655, 2637, 2635, 2626, 2625, 2623, 2628, 1820, 2752,\n 2739, 2737, 2728, 2727, 2725, 2730, 2785, 2783, 2778, 2777, 2775, 2780, 787, 781, 747, 739, 736, 2413, 754, 752,\n 1719, 692, 689, 681, 2371, 678, 2369, 700, 697, 694, 703, 1688, 1686, 642, 638, 2343, 631, 2341, 627, 2338, 651,\n 646, 643, 2345, 654, 652, 1652, 1650, 1647, 1654, 601, 599, 2322, 596, 2321, 594, 2319, 2317, 611, 610, 608, 606,\n 2324, 603, 2323, 615, 614, 612, 1617, 1616, 1614, 1612, 616, 1619, 1618, 2575, 2538, 2536, 905, 901, 898, 909,\n 2509, 2507, 2504, 870, 867, 864, 860, 2512, 875, 872, 1781, 2490, 2489, 2487, 2485, 1748, 836, 834, 832, 830,\n 2494, 827, 2492, 843, 841, 839, 845, 1765, 1763, 2701, 2676, 2674, 2653, 2648, 2656, 2634, 2633, 2631, 2629,\n 1821, 2638, 2636, 2770, 2763, 2761, 2750, 2745, 2753, 2736, 2735, 2733, 2731, 1848, 2740, 2738, 2786, 2784, 591,\n 588, 576, 569, 566, 2296, 1590, 537, 534, 526, 2276, 522, 2274, 545, 542, 539, 548, 1572, 1570, 481, 2245, 466,\n 2242, 462, 2239, 492, 485, 482, 2249, 496, 494, 1534, 1531, 1528, 1538, 413, 2196, 406, 2191, 2188, 425, 419,\n 2202, 415, 2199, 432, 430, 427, 1472, 1467, 1464, 433, 1476, 1474, 368, 367, 2160, 365, 2159, 362, 2157, 2155,\n 2152, 378, 377, 375, 2166, 372, 2165, 369, 2162, 383, 381, 379, 2168, 1419, 1418, 1416, 1414, 385, 1411, 384,\n 1423, 1422, 1420, 1424, 2461, 802, 2441, 2439, 790, 786, 783, 794, 2409, 2406, 2403, 750, 742, 738, 2414, 756,\n 753, 1720, 2367, 2365, 2362, 2359, 1663, 693, 691, 684, 2373, 680, 2370, 702, 699, 696, 704, 1690, 1687, 2337,\n 2336, 2334, 2332, 1624, 2329, 1622, 640, 637, 2344, 634, 2342, 630, 2340, 650, 648, 645, 2346, 655, 653, 1653,\n 1651, 1649, 1655, 2612, 2597, 2595, 2571, 2568, 2565, 2576, 2534, 2529, 2526, 1787, 2540, 2537, 907, 904, 900,\n 910, 2503, 2502, 2500, 2498, 1768, 2495, 1767, 2510, 2508, 2506, 869, 866, 863, 2513, 876, 874, 1782, 2720, 2713,\n 2711, 2697, 2694, 2691, 2702, 2672, 2670, 2664, 1828, 2678, 2675, 2647, 2646, 2644, 2642, 1823, 2639, 1822, 2654,\n 2652, 2650, 2657, 2771, 1855, 2765, 2762, 1850, 1849, 2751, 2749, 2747, 2754, 353, 2148, 344, 342, 336, 2142,\n 332, 2140, 345, 1375, 1373, 306, 2130, 299, 2128, 295, 2125, 319, 314, 311, 2132, 1354, 1352, 1349, 1356, 262,\n 257, 2101, 253, 2096, 2093, 274, 273, 267, 2107, 263, 2104, 280, 278, 275, 1316, 1311, 1308, 1320, 1318, 2052,\n 202, 2050, 2044, 2040, 219, 2063, 212, 2060, 208, 2055, 224, 221, 2066, 1260, 1258, 1252, 231, 1248, 229, 1266,\n 1264, 1261, 1268, 155, 1998, 153, 1996, 1994, 1991, 1988, 165, 164, 2007, 162, 2006, 159, 2003, 2000, 172, 171,\n 169, 2012, 166, 2010, 1186, 1184, 1182, 1179, 175, 1176, 173, 1192, 1191, 1189, 1187, 176, 1194, 1193, 2313,\n 2307, 2305, 592, 589, 2294, 2292, 2289, 578, 572, 568, 2297, 580, 1591, 2272, 2267, 2264, 1547, 538, 536, 529,\n 2278, 525, 2275, 547, 544, 541, 1574, 1571, 2237, 2235, 2229, 1493, 2225, 1489, 478, 2247, 470, 2244, 465, 2241,\n 493, 488, 484, 2250, 498, 495, 1536, 1533, 1530, 1539, 2187, 2186, 2184, 2182, 1432, 2179, 1430, 2176, 1427, 414,\n 412, 2197, 409, 2195, 405, 2193, 2190, 426, 424, 421, 2203, 418, 2201, 431, 429, 1473, 1471, 1469, 1466, 434,\n 1477, 1475, 2478, 2472, 2470, 2459, 2457, 2454, 2462, 803, 2437, 2432, 2429, 1726, 2443, 2440, 792, 789, 785,\n 2401, 2399, 2393, 1702, 2389, 1699, 2411, 2408, 2405, 745, 741, 2415, 758, 755, 1721, 2358, 2357, 2355, 2353,\n 1661, 2350, 1660, 2347, 1657, 2368, 2366, 2364, 2361, 1666, 690, 687, 2374, 683, 2372, 701, 698, 705, 1691, 1689,\n 2619, 2617, 2610, 2608, 2605, 2613, 2593, 2588, 2585, 1803, 2599, 2596, 2563, 2561, 2555, 1797, 2551, 1795, 2573,\n 2570, 2567, 2577, 2525, 2524, 2522, 2520, 1786, 2517, 1785, 2514, 1783, 2535, 2533, 2531, 2528, 1788, 2541, 2539,\n 906, 903, 911, 2721, 1844, 2715, 2712, 1838, 1836, 2699, 2696, 2693, 2703, 1827, 1826, 1824, 2673, 2671, 2669,\n 2666, 1829, 2679, 2677, 1858, 1857, 2772, 1854, 1853, 1851, 1856, 2766, 2764, 143, 1987, 139, 1986, 135, 133,\n 131, 1984, 128, 1983, 125, 1981, 138, 137, 136, 1985, 1133, 1132, 1130, 112, 110, 1974, 107, 1973, 104, 1971,\n 1969, 122, 121, 119, 117, 1977, 114, 1976, 124, 1115, 1114, 1112, 1110, 1117, 1116, 84, 83, 1953, 81, 1952, 78,\n 1950, 1948, 1945, 94, 93, 91, 1959, 88, 1958, 85, 1955, 99, 97, 95, 1961, 1086, 1085, 1083, 1081, 1078, 100,\n 1090, 1089, 1087, 1091, 49, 47, 1917, 44, 1915, 1913, 1910, 1907, 59, 1926, 56, 1925, 53, 1922, 1919, 66, 64,\n 1931, 61, 1929, 1042, 1040, 1038, 71, 1035, 70, 1032, 68, 1048, 1047, 1045, 1043, 1050, 1049, 12, 10, 1869, 1867,\n 1864, 1861, 21, 1880, 19, 1877, 1874, 1871, 28, 1888, 25, 1886, 22, 1883, 982, 980, 977, 974, 32, 30, 991, 989,\n 987, 984, 34, 995, 994, 992, 2151, 2150, 2147, 2146, 2144, 356, 355, 354, 2149, 2139, 2138, 2136, 2134, 1359,\n 343, 341, 338, 2143, 335, 2141, 348, 347, 346, 1376, 1374, 2124, 2123, 2121, 2119, 1326, 2116, 1324, 310, 308,\n 305, 2131, 302, 2129, 298, 2127, 320, 318, 316, 313, 2133, 322, 321, 1355, 1353, 1351, 1357, 2092, 2091, 2089,\n 2087, 1276, 2084, 1274, 2081, 1271, 259, 2102, 256, 2100, 252, 2098, 2095, 272, 269, 2108, 266, 2106, 281, 279,\n 277, 1317, 1315, 1313, 1310, 282, 1321, 1319, 2039, 2037, 2035, 2032, 1203, 2029, 1200, 1197, 207, 2053, 205,\n 2051, 201, 2049, 2046, 2043, 220, 218, 2064, 215, 2062, 211, 2059, 228, 226, 223, 2069, 1259, 1257, 1254, 232,\n 1251, 230, 1267, 1265, 1263, 2316, 2315, 2312, 2311, 2309, 2314, 2304, 2303, 2301, 2299, 1593, 2308, 2306, 590,\n 2288, 2287, 2285, 2283, 1578, 2280, 1577, 2295, 2293, 2291, 579, 577, 574, 571, 2298, 582, 581, 1592, 2263, 2262,\n 2260, 2258, 1545, 2255, 1544, 2252, 1541, 2273, 2271, 2269, 2266, 1550, 535, 532, 2279, 528, 2277, 546, 543, 549,\n 1575, 1573, 2224, 2222, 2220, 1486, 2217, 1485, 2214, 1482, 1479, 2238, 2236, 2234, 2231, 1496, 2228, 1492, 480,\n 477, 2248, 473, 2246, 469, 2243, 490, 487, 2251, 497, 1537, 1535, 1532, 2477, 2476, 2474, 2479, 2469, 2468, 2466,\n 2464, 1730, 2473, 2471, 2453, 2452, 2450, 2448, 1729, 2445, 1728, 2460, 2458, 2456, 2463, 805, 804, 2428, 2427,\n 2425, 2423, 1725, 2420, 1724, 2417, 1722, 2438, 2436, 2434, 2431, 1727, 2444, 2442, 793, 791, 788, 795, 2388,\n 2386, 2384, 1697, 2381, 1696, 2378, 1694, 1692, 2402, 2400, 2398, 2395, 1703, 2392, 1701, 2412, 2410, 2407, 751,\n 748, 744, 2416, 759, 757, 1807, 2620, 2618, 1806, 1805, 2611, 2609, 2607, 2614, 1802, 1801, 1799, 2594, 2592,\n 2590, 2587, 1804, 2600, 2598, 1794, 1793, 1791, 1789, 2564, 2562, 2560, 2557, 1798, 2554, 1796, 2574, 2572, 2569,\n 2578, 1847, 1846, 2722, 1843, 1842, 1840, 1845, 2716, 2714, 1835, 1834, 1832, 1830, 1839, 1837, 2700, 2698, 2695,\n 2704, 1817, 1811, 1810, 897, 862, 1777, 829, 826, 838, 1760, 1758, 808, 2481, 1741, 1740, 1738, 1743, 2624, 1818,\n 2726, 2776, 782, 740, 737, 1715, 686, 679, 695, 1682, 1680, 639, 628, 2339, 647, 644, 1645, 1643, 1640, 1648,\n 602, 600, 597, 595, 2320, 593, 2318, 609, 607, 604, 1611, 1610, 1608, 1606, 613, 1615, 1613, 2328, 926, 924, 892,\n 886, 899, 857, 850, 2505, 1778, 824, 823, 821, 819, 2488, 818, 2486, 833, 831, 828, 840, 1761, 1759, 2649, 2632,\n 2630, 2746, 2734, 2732, 2782, 2781, 570, 567, 1587, 531, 527, 523, 540, 1566, 1564, 476, 467, 463, 2240, 486,\n 483, 1524, 1521, 1518, 1529, 411, 403, 2192, 399, 2189, 423, 416, 1462, 1457, 1454, 428, 1468, 1465, 2210, 366,\n 363, 2158, 360, 2156, 357, 2153, 376, 373, 370, 2163, 1410, 1409, 1407, 1405, 382, 1402, 380, 1417, 1415, 1412,\n 1421, 2175, 2174, 777, 774, 771, 784, 732, 725, 722, 2404, 743, 1716, 676, 674, 668, 2363, 665, 2360, 685, 1684,\n 1681, 626, 624, 622, 2335, 620, 2333, 617, 2330, 641, 635, 649, 1646, 1644, 1642, 2566, 928, 925, 2530, 2527,\n 894, 891, 888, 2501, 2499, 2496, 858, 856, 854, 851, 1779, 2692, 2668, 2665, 2645, 2643, 2640, 2651, 2768, 2759,\n 2757, 2744, 2743, 2741, 2748, 352, 1382, 340, 337, 333, 1371, 1369, 307, 300, 296, 2126, 315, 312, 1347, 1342,\n 1350, 261, 258, 250, 2097, 246, 2094, 271, 268, 264, 1306, 1301, 1298, 276, 1312, 1309, 2115, 203, 2048, 195,\n 2045, 191, 2041, 213, 209, 2056, 1246, 1244, 1238, 225, 1234, 222, 1256, 1253, 1249, 1262, 2080, 2079, 154, 1997,\n 150, 1995, 147, 1992, 1989, 163, 160, 2004, 156, 2001, 1175, 1174, 1172, 1170, 1167, 170, 1164, 167, 1185, 1183,\n 1180, 1177, 174, 1190, 1188, 2025, 2024, 2022, 587, 586, 564, 559, 556, 2290, 573, 1588, 520, 518, 512, 2268,\n 508, 2265, 530, 1568, 1565, 461, 457, 2233, 450, 2230, 446, 2226, 479, 471, 489, 1526, 1523, 1520, 397, 395,\n 2185, 392, 2183, 389, 2180, 2177, 410, 2194, 402, 422, 1463, 1461, 1459, 1456, 1470, 2455, 799, 2433, 2430, 779,\n 776, 773, 2397, 2394, 2390, 734, 728, 724, 746, 1717, 2356, 2354, 2351, 2348, 1658, 677, 675, 673, 670, 667, 688,\n 1685, 1683, 2606, 2589, 2586, 2559, 2556, 2552, 927, 2523, 2521, 2518, 2515, 1784, 2532, 895, 893, 890, 2718,\n 2709, 2707, 2689, 2687, 2684, 2663, 2662, 2660, 2658, 1825, 2667, 2769, 1852, 2760, 2758, 142, 141, 1139, 1138,\n 134, 132, 129, 126, 1982, 1129, 1128, 1126, 1131, 113, 111, 108, 105, 1972, 101, 1970, 120, 118, 115, 1109, 1108,\n 1106, 1104, 123, 1113, 1111, 82, 79, 1951, 75, 1949, 72, 1946, 92, 89, 86, 1956, 1077, 1076, 1074, 1072, 98,\n 1069, 96, 1084, 1082, 1079, 1088, 1968, 1967, 48, 45, 1916, 42, 1914, 39, 1911, 1908, 60, 57, 54, 1923, 50, 1920,\n 1031, 1030, 1028, 1026, 67, 1023, 65, 1020, 62, 1041, 1039, 1036, 1033, 69, 1046, 1044, 1944, 1943, 1941, 11, 9,\n 1868, 7, 1865, 1862, 1859, 20, 1878, 16, 1875, 13, 1872, 970, 968, 966, 963, 29, 960, 26, 23, 983, 981, 978, 975,\n 33, 971, 31, 990, 988, 985, 1906, 1904, 1902, 993, 351, 2145, 1383, 331, 330, 328, 326, 2137, 323, 2135, 339,\n 1372, 1370, 294, 293, 291, 289, 2122, 286, 2120, 283, 2117, 309, 303, 317, 1348, 1346, 1344, 245, 244, 242, 2090,\n 239, 2088, 236, 2085, 2082, 260, 2099, 249, 270, 1307, 1305, 1303, 1300, 1314, 189, 2038, 186, 2036, 183, 2033,\n 2030, 2026, 206, 198, 2047, 194, 216, 1247, 1245, 1243, 1240, 227, 1237, 1255, 2310, 2302, 2300, 2286, 2284,\n 2281, 565, 563, 561, 558, 575, 1589, 2261, 2259, 2256, 2253, 1542, 521, 519, 517, 514, 2270, 511, 533, 1569,\n 1567, 2223, 2221, 2218, 2215, 1483, 2211, 1480, 459, 456, 453, 2232, 449, 474, 491, 1527, 1525, 1522, 2475, 2467,\n 2465, 2451, 2449, 2446, 801, 800, 2426, 2424, 2421, 2418, 1723, 2435, 780, 778, 775, 2387, 2385, 2382, 2379,\n 1695, 2375, 1693, 2396, 735, 733, 730, 727, 749, 1718, 2616, 2615, 2604, 2603, 2601, 2584, 2583, 2581, 2579,\n 1800, 2591, 2550, 2549, 2547, 2545, 1792, 2542, 1790, 2558, 929, 2719, 1841, 2710, 2708, 1833, 1831, 2690, 2688,\n 2686, 1815, 1809, 1808, 1774, 1756, 1754, 1737, 1736, 1734, 1739, 1816, 1711, 1676, 1674, 633, 629, 1638, 1636,\n 1633, 1641, 598, 1605, 1604, 1602, 1600, 605, 1609, 1607, 2327, 887, 853, 1775, 822, 820, 1757, 1755, 1584, 524,\n 1560, 1558, 468, 464, 1514, 1511, 1508, 1519, 408, 404, 400, 1452, 1447, 1444, 417, 1458, 1455, 2208, 364, 361,\n 358, 2154, 1401, 1400, 1398, 1396, 374, 1393, 371, 1408, 1406, 1403, 1413, 2173, 2172, 772, 726, 723, 1712, 672,\n 669, 666, 682, 1678, 1675, 625, 623, 621, 618, 2331, 636, 632, 1639, 1637, 1635, 920, 918, 884, 880, 889, 849,\n 848, 847, 846, 2497, 855, 852, 1776, 2641, 2742, 2787, 1380, 334, 1367, 1365, 301, 297, 1340, 1338, 1335, 1343,\n 255, 251, 247, 1296, 1291, 1288, 265, 1302, 1299, 2113, 204, 196, 192, 2042, 1232, 1230, 1224, 214, 1220, 210,\n 1242, 1239, 1235, 1250, 2077, 2075, 151, 148, 1993, 144, 1990, 1163, 1162, 1160, 1158, 1155, 161, 1152, 157,\n 1173, 1171, 1168, 1165, 168, 1181, 1178, 2021, 2020, 2018, 2023, 585, 560, 557, 1585, 516, 509, 1562, 1559, 458,\n 447, 2227, 472, 1516, 1513, 1510, 398, 396, 393, 390, 2181, 386, 2178, 407, 1453, 1451, 1449, 1446, 420, 1460,\n 2209, 769, 764, 720, 712, 2391, 729, 1713, 664, 663, 661, 659, 2352, 656, 2349, 671, 1679, 1677, 2553, 922, 919,\n 2519, 2516, 885, 883, 881, 2685, 2661, 2659, 2767, 2756, 2755, 140, 1137, 1136, 130, 127, 1125, 1124, 1122, 1127,\n 109, 106, 102, 1103, 1102, 1100, 1098, 116, 1107, 1105, 1980, 80, 76, 73, 1947, 1068, 1067, 1065, 1063, 90, 1060,\n 87, 1075, 1073, 1070, 1080, 1966, 1965, 46, 43, 40, 1912, 36, 1909, 1019, 1018, 1016, 1014, 58, 1011, 55, 1008,\n 51, 1029, 1027, 1024, 1021, 63, 1037, 1034, 1940, 1939, 1937, 1942, 8, 1866, 4, 1863, 1, 1860, 956, 954, 952,\n 949, 946, 17, 14, 969, 967, 964, 961, 27, 957, 24, 979, 976, 972, 1901, 1900, 1898, 1896, 986, 1905, 1903, 350,\n 349, 1381, 329, 327, 324, 1368, 1366, 292, 290, 287, 284, 2118, 304, 1341, 1339, 1337, 1345, 243, 240, 237, 2086,\n 233, 2083, 254, 1297, 1295, 1293, 1290, 1304, 2114, 190, 187, 184, 2034, 180, 2031, 177, 2027, 199, 1233, 1231,\n 1229, 1226, 217, 1223, 1241, 2078, 2076, 584, 555, 554, 552, 550, 2282, 562, 1586, 507, 506, 504, 502, 2257, 499,\n 2254, 515, 1563, 1561, 445, 443, 441, 2219, 438, 2216, 435, 2212, 460, 454, 475, 1517, 1515, 1512, 2447, 798,\n 797, 2422, 2419, 770, 768, 766, 2383, 2380, 2376, 721, 719, 717, 714, 731, 1714, 2602, 2582, 2580, 2548, 2546,\n 2543, 923, 921, 2717, 2706, 2705, 2683, 2682, 2680, 1771, 1752, 1750, 1733, 1732, 1731, 1735, 1814, 1707, 1670,\n 1668, 1631, 1629, 1626, 1634, 1599, 1598, 1596, 1594, 1603, 1601, 2326, 1772, 1753, 1751, 1581, 1554, 1552, 1504,\n 1501, 1498, 1509, 1442, 1437, 1434, 401, 1448, 1445, 2206, 1392, 1391, 1389, 1387, 1384, 359, 1399, 1397, 1394,\n 1404, 2171, 2170, 1708, 1672, 1669, 619, 1632, 1630, 1628, 1773, 1378, 1363, 1361, 1333, 1328, 1336, 1286, 1281,\n 1278, 248, 1292, 1289, 2111, 1218, 1216, 1210, 197, 1206, 193, 1228, 1225, 1221, 1236, 2073, 2071, 1151, 1150,\n 1148, 1146, 152, 1143, 149, 1140, 145, 1161, 1159, 1156, 1153, 158, 1169, 1166, 2017, 2016, 2014, 2019, 1582,\n 510, 1556, 1553, 452, 448, 1506, 1500, 394, 391, 387, 1443, 1441, 1439, 1436, 1450, 2207, 765, 716, 713, 1709,\n 662, 660, 657, 1673, 1671, 916, 914, 879, 878, 877, 882, 1135, 1134, 1121, 1120, 1118, 1123, 1097, 1096, 1094,\n 1092, 103, 1101, 1099, 1979, 1059, 1058, 1056, 1054, 77, 1051, 74, 1066, 1064, 1061, 1071, 1964, 1963, 1007,\n 1006, 1004, 1002, 999, 41, 996, 37, 1017, 1015, 1012, 1009, 52, 1025, 1022, 1936, 1935, 1933, 1938, 942, 940,\n 938, 935, 932, 5, 2, 955, 953, 950, 947, 18, 943, 15, 965, 962, 958, 1895, 1894, 1892, 1890, 973, 1899, 1897,\n 1379, 325, 1364, 1362, 288, 285, 1334, 1332, 1330, 241, 238, 234, 1287, 1285, 1283, 1280, 1294, 2112, 188, 185,\n 181, 178, 2028, 1219, 1217, 1215, 1212, 200, 1209, 1227, 2074, 2072, 583, 553, 551, 1583, 505, 503, 500, 513,\n 1557, 1555, 444, 442, 439, 436, 2213, 455, 451, 1507, 1505, 1502, 796, 763, 762, 760, 767, 711, 710, 708, 706,\n 2377, 718, 715, 1710, 2544, 917, 915, 2681, 1627, 1597, 1595, 2325, 1769, 1749, 1747, 1499, 1438, 1435, 2204,\n 1390, 1388, 1385, 1395, 2169, 2167, 1704, 1665, 1662, 1625, 1623, 1620, 1770, 1329, 1282, 1279, 2109, 1214, 1207,\n 1222, 2068, 2065, 1149, 1147, 1144, 1141, 146, 1157, 1154, 2013, 2011, 2008, 2015, 1579, 1549, 1546, 1495, 1487,\n 1433, 1431, 1428, 1425, 388, 1440, 2205, 1705, 658, 1667, 1664, 1119, 1095, 1093, 1978, 1057, 1055, 1052, 1062,\n 1962, 1960, 1005, 1003, 1000, 997, 38, 1013, 1010, 1932, 1930, 1927, 1934, 941, 939, 936, 933, 6, 930, 3, 951,\n 948, 944, 1889, 1887, 1884, 1881, 959, 1893, 1891, 35, 1377, 1360, 1358, 1327, 1325, 1322, 1331, 1277, 1275,\n 1272, 1269, 235, 1284, 2110, 1205, 1204, 1201, 1198, 182, 1195, 179, 1213, 2070, 2067, 1580, 501, 1551, 1548,\n 440, 437, 1497, 1494, 1490, 1503, 761, 709, 707, 1706, 913, 912, 2198, 1386, 2164, 2161, 1621, 1766, 2103, 1208,\n 2058, 2054, 1145, 1142, 2005, 2002, 1999, 2009, 1488, 1429, 1426, 2200, 1698, 1659, 1656, 1975, 1053, 1957, 1954,\n 1001, 998, 1924, 1921, 1918, 1928, 937, 934, 931, 1879, 1876, 1873, 1870, 945, 1885, 1882, 1323, 1273, 1270,\n 2105, 1202, 1199, 1196, 1211, 2061, 2057, 1576, 1543, 1540, 1484, 1481, 1478, 1491, 1700\n ]);\n\n /*\n * Copyright 2007 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n // import java.util.List;\n /**\n * @author Guenther Grau\n */\n /*public final*/ class PDF417DetectorResult {\n constructor(bits, points) {\n this.bits = bits;\n this.points = points;\n }\n getBits() {\n return this.bits;\n }\n getPoints() {\n return this.points;\n }\n }\n\n /*\n * Copyright 2009 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n // import java.util.ArrayList;\n // import java.util.Arrays;\n // import java.util.List;\n // import java.util.Map;\n /**\n *

Encapsulates logic that can detect a PDF417 Code in an image, even if the\n * PDF417 Code is rotated or skewed, or partially obscured.

\n *\n * @author SITA Lab (kevin.osullivan@sita.aero)\n * @author dswitkin@google.com (Daniel Switkin)\n * @author Guenther Grau\n */\n /*public*/ /*final*/ class Detector$3 {\n /**\n *

Detects a PDF417 Code in an image. Only checks 0 and 180 degree rotations.

\n *\n * @param image barcode image to decode\n * @param hints optional hints to detector\n * @param multiple if true, then the image is searched for multiple codes. If false, then at most one code will\n * be found and returned\n * @return {@link PDF417DetectorResult} encapsulating results of detecting a PDF417 code\n * @throws NotFoundException if no PDF417 Code can be found\n */\n static detectMultiple(image, hints, multiple) {\n // TODO detection improvement, tryHarder could try several different luminance thresholds/blackpoints or even\n // different binarizers\n // boolean tryHarder = hints != null && hints.containsKey(DecodeHintType.TRY_HARDER);\n let bitMatrix = image.getBlackMatrix();\n let barcodeCoordinates = Detector$3.detect(multiple, bitMatrix);\n if (!barcodeCoordinates.length) {\n bitMatrix = bitMatrix.clone();\n bitMatrix.rotate180();\n barcodeCoordinates = Detector$3.detect(multiple, bitMatrix);\n }\n return new PDF417DetectorResult(bitMatrix, barcodeCoordinates);\n }\n /**\n * Detects PDF417 codes in an image. Only checks 0 degree rotation\n * @param multiple if true, then the image is searched for multiple codes. If false, then at most one code will\n * be found and returned\n * @param bitMatrix bit matrix to detect barcodes in\n * @return List of ResultPoint arrays containing the coordinates of found barcodes\n */\n static detect(multiple, bitMatrix) {\n const barcodeCoordinates = new Array();\n let row = 0;\n let column = 0;\n let foundBarcodeInRow = false;\n while (row < bitMatrix.getHeight()) {\n const vertices = Detector$3.findVertices(bitMatrix, row, column);\n if (vertices[0] == null && vertices[3] == null) {\n if (!foundBarcodeInRow) {\n // we didn't find any barcode so that's the end of searching\n break;\n }\n // we didn't find a barcode starting at the given column and row. Try again from the first column and slightly\n // below the lowest barcode we found so far.\n foundBarcodeInRow = false;\n column = 0;\n for (const barcodeCoordinate of barcodeCoordinates) {\n if (barcodeCoordinate[1] != null) {\n row = Math.trunc(Math.max(row, barcodeCoordinate[1].getY()));\n }\n if (barcodeCoordinate[3] != null) {\n row = Math.max(row, Math.trunc(barcodeCoordinate[3].getY()));\n }\n }\n row += Detector$3.ROW_STEP;\n continue;\n }\n foundBarcodeInRow = true;\n barcodeCoordinates.push(vertices);\n if (!multiple) {\n break;\n }\n // if we didn't find a right row indicator column, then continue the search for the next barcode after the\n // start pattern of the barcode just found.\n if (vertices[2] != null) {\n column = Math.trunc(vertices[2].getX());\n row = Math.trunc(vertices[2].getY());\n }\n else {\n column = Math.trunc(vertices[4].getX());\n row = Math.trunc(vertices[4].getY());\n }\n }\n return barcodeCoordinates;\n }\n /**\n * Locate the vertices and the codewords area of a black blob using the Start\n * and Stop patterns as locators.\n *\n * @param matrix the scanned barcode image.\n * @return an array containing the vertices:\n * vertices[0] x, y top left barcode\n * vertices[1] x, y bottom left barcode\n * vertices[2] x, y top right barcode\n * vertices[3] x, y bottom right barcode\n * vertices[4] x, y top left codeword area\n * vertices[5] x, y bottom left codeword area\n * vertices[6] x, y top right codeword area\n * vertices[7] x, y bottom right codeword area\n */\n static findVertices(matrix, startRow, startColumn) {\n const height = matrix.getHeight();\n const width = matrix.getWidth();\n // const result = new ResultPoint[8];\n const result = new Array(8);\n Detector$3.copyToResult(result, Detector$3.findRowsWithPattern(matrix, height, width, startRow, startColumn, Detector$3.START_PATTERN), Detector$3.INDEXES_START_PATTERN);\n if (result[4] != null) {\n startColumn = Math.trunc(result[4].getX());\n startRow = Math.trunc(result[4].getY());\n }\n Detector$3.copyToResult(result, Detector$3.findRowsWithPattern(matrix, height, width, startRow, startColumn, Detector$3.STOP_PATTERN), Detector$3.INDEXES_STOP_PATTERN);\n return result;\n }\n static copyToResult(result, tmpResult, destinationIndexes) {\n for (let i = 0; i < destinationIndexes.length; i++) {\n result[destinationIndexes[i]] = tmpResult[i];\n }\n }\n static findRowsWithPattern(matrix, height, width, startRow, startColumn, pattern) {\n // const result = new ResultPoint[4];\n const result = new Array(4);\n let found = false;\n const counters = new Int32Array(pattern.length);\n for (; startRow < height; startRow += Detector$3.ROW_STEP) {\n let loc = Detector$3.findGuardPattern(matrix, startColumn, startRow, width, false, pattern, counters);\n if (loc != null) {\n while (startRow > 0) {\n const previousRowLoc = Detector$3.findGuardPattern(matrix, startColumn, --startRow, width, false, pattern, counters);\n if (previousRowLoc != null) {\n loc = previousRowLoc;\n }\n else {\n startRow++;\n break;\n }\n }\n result[0] = new ResultPoint(loc[0], startRow);\n result[1] = new ResultPoint(loc[1], startRow);\n found = true;\n break;\n }\n }\n let stopRow = startRow + 1;\n // Last row of the current symbol that contains pattern\n if (found) {\n let skippedRowCount = 0;\n let previousRowLoc = Int32Array.from([Math.trunc(result[0].getX()), Math.trunc(result[1].getX())]);\n for (; stopRow < height; stopRow++) {\n const loc = Detector$3.findGuardPattern(matrix, previousRowLoc[0], stopRow, width, false, pattern, counters);\n // a found pattern is only considered to belong to the same barcode if the start and end positions\n // don't differ too much. Pattern drift should be not bigger than two for consecutive rows. With\n // a higher number of skipped rows drift could be larger. To keep it simple for now, we allow a slightly\n // larger drift and don't check for skipped rows.\n if (loc != null &&\n Math.abs(previousRowLoc[0] - loc[0]) < Detector$3.MAX_PATTERN_DRIFT &&\n Math.abs(previousRowLoc[1] - loc[1]) < Detector$3.MAX_PATTERN_DRIFT) {\n previousRowLoc = loc;\n skippedRowCount = 0;\n }\n else {\n if (skippedRowCount > Detector$3.SKIPPED_ROW_COUNT_MAX) {\n break;\n }\n else {\n skippedRowCount++;\n }\n }\n }\n stopRow -= skippedRowCount + 1;\n result[2] = new ResultPoint(previousRowLoc[0], stopRow);\n result[3] = new ResultPoint(previousRowLoc[1], stopRow);\n }\n if (stopRow - startRow < Detector$3.BARCODE_MIN_HEIGHT) {\n Arrays.fill(result, null);\n }\n return result;\n }\n /**\n * @param matrix row of black/white values to search\n * @param column x position to start search\n * @param row y position to start search\n * @param width the number of pixels to search on this row\n * @param pattern pattern of counts of number of black and white pixels that are\n * being searched for as a pattern\n * @param counters array of counters, as long as pattern, to re-use\n * @return start/end horizontal offset of guard pattern, as an array of two ints.\n */\n static findGuardPattern(matrix, column, row, width, whiteFirst, pattern, counters) {\n Arrays.fillWithin(counters, 0, counters.length, 0);\n let patternStart = column;\n let pixelDrift = 0;\n // if there are black pixels left of the current pixel shift to the left, but only for MAX_PIXEL_DRIFT pixels\n while (matrix.get(patternStart, row) && patternStart > 0 && pixelDrift++ < Detector$3.MAX_PIXEL_DRIFT) {\n patternStart--;\n }\n let x = patternStart;\n let counterPosition = 0;\n let patternLength = pattern.length;\n for (let isWhite = whiteFirst; x < width; x++) {\n let pixel = matrix.get(x, row);\n if (pixel !== isWhite) {\n counters[counterPosition]++;\n }\n else {\n if (counterPosition === patternLength - 1) {\n if (Detector$3.patternMatchVariance(counters, pattern, Detector$3.MAX_INDIVIDUAL_VARIANCE) < Detector$3.MAX_AVG_VARIANCE) {\n return new Int32Array([patternStart, x]);\n }\n patternStart += counters[0] + counters[1];\n System.arraycopy(counters, 2, counters, 0, counterPosition - 1);\n counters[counterPosition - 1] = 0;\n counters[counterPosition] = 0;\n counterPosition--;\n }\n else {\n counterPosition++;\n }\n counters[counterPosition] = 1;\n isWhite = !isWhite;\n }\n }\n if (counterPosition === patternLength - 1 &&\n Detector$3.patternMatchVariance(counters, pattern, Detector$3.MAX_INDIVIDUAL_VARIANCE) < Detector$3.MAX_AVG_VARIANCE) {\n return new Int32Array([patternStart, x - 1]);\n }\n return null;\n }\n /**\n * Determines how closely a set of observed counts of runs of black/white\n * values matches a given target pattern. This is reported as the ratio of\n * the total variance from the expected pattern proportions across all\n * pattern elements, to the length of the pattern.\n *\n * @param counters observed counters\n * @param pattern expected pattern\n * @param maxIndividualVariance The most any counter can differ before we give up\n * @return ratio of total variance between counters and pattern compared to total pattern size\n */\n static patternMatchVariance(counters, pattern, maxIndividualVariance) {\n let numCounters = counters.length;\n let total = 0;\n let patternLength = 0;\n for (let i = 0; i < numCounters; i++) {\n total += counters[i];\n patternLength += pattern[i];\n }\n if (total < patternLength) {\n // If we don't even have one pixel per unit of bar width, assume this\n // is too small to reliably match, so fail:\n return /*Float.POSITIVE_INFINITY*/ Infinity;\n }\n // We're going to fake floating-point math in integers. We just need to use more bits.\n // Scale up patternLength so that intermediate values below like scaledCounter will have\n // more \"significant digits\".\n let unitBarWidth = total / patternLength;\n maxIndividualVariance *= unitBarWidth;\n let totalVariance = 0.0;\n for (let x = 0; x < numCounters; x++) {\n let counter = counters[x];\n let scaledPattern = pattern[x] * unitBarWidth;\n let variance = counter > scaledPattern ? counter - scaledPattern : scaledPattern - counter;\n if (variance > maxIndividualVariance) {\n return /*Float.POSITIVE_INFINITY*/ Infinity;\n }\n totalVariance += variance;\n }\n return totalVariance / total;\n }\n }\n Detector$3.INDEXES_START_PATTERN = Int32Array.from([0, 4, 1, 5]);\n Detector$3.INDEXES_STOP_PATTERN = Int32Array.from([6, 2, 7, 3]);\n Detector$3.MAX_AVG_VARIANCE = 0.42;\n Detector$3.MAX_INDIVIDUAL_VARIANCE = 0.8;\n // B S B S B S B S Bar/Space pattern\n // 11111111 0 1 0 1 0 1 000\n Detector$3.START_PATTERN = Int32Array.from([8, 1, 1, 1, 1, 1, 1, 3]);\n // 1111111 0 1 000 1 0 1 00 1\n Detector$3.STOP_PATTERN = Int32Array.from([7, 1, 1, 3, 1, 1, 1, 2, 1]);\n Detector$3.MAX_PIXEL_DRIFT = 3;\n Detector$3.MAX_PATTERN_DRIFT = 5;\n // if we set the value too low, then we don't detect the correct height of the bar if the start patterns are damaged.\n // if we set the value too high, then we might detect the start pattern from a neighbor barcode.\n Detector$3.SKIPPED_ROW_COUNT_MAX = 25;\n // A PDF471 barcode should have at least 3 rows, with each row being >= 3 times the module width. Therefore it should be at least\n // 9 pixels tall. To be conservative, we use about half the size to ensure we don't miss it.\n Detector$3.ROW_STEP = 5;\n Detector$3.BARCODE_MIN_HEIGHT = 10;\n\n /*\n * Copyright 2012 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n /**\n * @author Sean Owen\n * @see com.google.zxing.common.reedsolomon.GenericGFPoly\n */\n /*final*/ class ModulusPoly {\n constructor(field, coefficients) {\n if (coefficients.length === 0) {\n throw new IllegalArgumentException();\n }\n this.field = field;\n let coefficientsLength = /*int*/ coefficients.length;\n if (coefficientsLength > 1 && coefficients[0] === 0) {\n // Leading term must be non-zero for anything except the constant polynomial \"0\"\n let firstNonZero = /*int*/ 1;\n while (firstNonZero < coefficientsLength && coefficients[firstNonZero] === 0) {\n firstNonZero++;\n }\n if (firstNonZero === coefficientsLength) {\n this.coefficients = new Int32Array([0]);\n }\n else {\n this.coefficients = new Int32Array(coefficientsLength - firstNonZero);\n System.arraycopy(coefficients, firstNonZero, this.coefficients, 0, this.coefficients.length);\n }\n }\n else {\n this.coefficients = coefficients;\n }\n }\n getCoefficients() {\n return this.coefficients;\n }\n /**\n * @return degree of this polynomial\n */\n getDegree() {\n return this.coefficients.length - 1;\n }\n /**\n * @return true iff this polynomial is the monomial \"0\"\n */\n isZero() {\n return this.coefficients[0] === 0;\n }\n /**\n * @return coefficient of x^degree term in this polynomial\n */\n getCoefficient(degree) {\n return this.coefficients[this.coefficients.length - 1 - degree];\n }\n /**\n * @return evaluation of this polynomial at a given point\n */\n evaluateAt(a) {\n if (a === 0) {\n // Just return the x^0 coefficient\n return this.getCoefficient(0);\n }\n if (a === 1) {\n // Just the sum of the coefficients\n let sum = /*int*/ 0;\n for (let coefficient /*int*/ of this.coefficients) {\n sum = this.field.add(sum, coefficient);\n }\n return sum;\n }\n let result = /*int*/ this.coefficients[0];\n let size = /*int*/ this.coefficients.length;\n for (let i /*int*/ = 1; i < size; i++) {\n result = this.field.add(this.field.multiply(a, result), this.coefficients[i]);\n }\n return result;\n }\n add(other) {\n if (!this.field.equals(other.field)) {\n throw new IllegalArgumentException('ModulusPolys do not have same ModulusGF field');\n }\n if (this.isZero()) {\n return other;\n }\n if (other.isZero()) {\n return this;\n }\n let smallerCoefficients = this.coefficients;\n let largerCoefficients = other.coefficients;\n if (smallerCoefficients.length > largerCoefficients.length) {\n let temp = smallerCoefficients;\n smallerCoefficients = largerCoefficients;\n largerCoefficients = temp;\n }\n let sumDiff = new Int32Array(largerCoefficients.length);\n let lengthDiff = /*int*/ largerCoefficients.length - smallerCoefficients.length;\n // Copy high-order terms only found in higher-degree polynomial's coefficients\n System.arraycopy(largerCoefficients, 0, sumDiff, 0, lengthDiff);\n for (let i /*int*/ = lengthDiff; i < largerCoefficients.length; i++) {\n sumDiff[i] = this.field.add(smallerCoefficients[i - lengthDiff], largerCoefficients[i]);\n }\n return new ModulusPoly(this.field, sumDiff);\n }\n subtract(other) {\n if (!this.field.equals(other.field)) {\n throw new IllegalArgumentException('ModulusPolys do not have same ModulusGF field');\n }\n if (other.isZero()) {\n return this;\n }\n return this.add(other.negative());\n }\n multiply(other) {\n if (other instanceof ModulusPoly) {\n return this.multiplyOther(other);\n }\n return this.multiplyScalar(other);\n }\n multiplyOther(other) {\n if (!this.field.equals(other.field)) {\n throw new IllegalArgumentException('ModulusPolys do not have same ModulusGF field');\n }\n if (this.isZero() || other.isZero()) {\n // return this.field.getZero();\n return new ModulusPoly(this.field, new Int32Array([0]));\n }\n let aCoefficients = this.coefficients;\n let aLength = /*int*/ aCoefficients.length;\n let bCoefficients = other.coefficients;\n let bLength = /*int*/ bCoefficients.length;\n let product = new Int32Array(aLength + bLength - 1);\n for (let i /*int*/ = 0; i < aLength; i++) {\n let aCoeff = /*int*/ aCoefficients[i];\n for (let j /*int*/ = 0; j < bLength; j++) {\n product[i + j] = this.field.add(product[i + j], this.field.multiply(aCoeff, bCoefficients[j]));\n }\n }\n return new ModulusPoly(this.field, product);\n }\n negative() {\n let size = /*int*/ this.coefficients.length;\n let negativeCoefficients = new Int32Array(size);\n for (let i /*int*/ = 0; i < size; i++) {\n negativeCoefficients[i] = this.field.subtract(0, this.coefficients[i]);\n }\n return new ModulusPoly(this.field, negativeCoefficients);\n }\n multiplyScalar(scalar) {\n if (scalar === 0) {\n return new ModulusPoly(this.field, new Int32Array([0]));\n }\n if (scalar === 1) {\n return this;\n }\n let size = /*int*/ this.coefficients.length;\n let product = new Int32Array(size);\n for (let i /*int*/ = 0; i < size; i++) {\n product[i] = this.field.multiply(this.coefficients[i], scalar);\n }\n return new ModulusPoly(this.field, product);\n }\n multiplyByMonomial(degree, coefficient) {\n if (degree < 0) {\n throw new IllegalArgumentException();\n }\n if (coefficient === 0) {\n return new ModulusPoly(this.field, new Int32Array([0]));\n }\n let size = /*int*/ this.coefficients.length;\n let product = new Int32Array(size + degree);\n for (let i /*int*/ = 0; i < size; i++) {\n product[i] = this.field.multiply(this.coefficients[i], coefficient);\n }\n return new ModulusPoly(this.field, product);\n }\n /*\n ModulusPoly[] divide(other: ModulusPoly) {\n if (!field.equals(other.field)) {\n throw new IllegalArgumentException(\"ModulusPolys do not have same ModulusGF field\");\n }\n if (other.isZero()) {\n throw new IllegalArgumentException(\"Divide by 0\");\n }\n \n let quotient: ModulusPoly = field.getZero();\n let remainder: ModulusPoly = this;\n \n let denominatorLeadingTerm: /*int/ number = other.getCoefficient(other.getDegree());\n let inverseDenominatorLeadingTerm: /*int/ number = field.inverse(denominatorLeadingTerm);\n \n while (remainder.getDegree() >= other.getDegree() && !remainder.isZero()) {\n let degreeDifference: /*int/ number = remainder.getDegree() - other.getDegree();\n let scale: /*int/ number = field.multiply(remainder.getCoefficient(remainder.getDegree()), inverseDenominatorLeadingTerm);\n let term: ModulusPoly = other.multiplyByMonomial(degreeDifference, scale);\n let iterationQuotient: ModulusPoly = field.buildMonomial(degreeDifference, scale);\n quotient = quotient.add(iterationQuotient);\n remainder = remainder.subtract(term);\n }\n \n return new ModulusPoly[] { quotient, remainder };\n }\n */\n // @Override\n toString() {\n let result = new StringBuilder( /*8 * this.getDegree()*/); // dynamic string size in JS\n for (let degree /*int*/ = this.getDegree(); degree >= 0; degree--) {\n let coefficient = /*int*/ this.getCoefficient(degree);\n if (coefficient !== 0) {\n if (coefficient < 0) {\n result.append(' - ');\n coefficient = -coefficient;\n }\n else {\n if (result.length() > 0) {\n result.append(' + ');\n }\n }\n if (degree === 0 || coefficient !== 1) {\n result.append(coefficient);\n }\n if (degree !== 0) {\n if (degree === 1) {\n result.append('x');\n }\n else {\n result.append('x^');\n result.append(degree);\n }\n }\n }\n }\n return result.toString();\n }\n }\n\n class ModulusBase {\n add(a, b) {\n return (a + b) % this.modulus;\n }\n subtract(a, b) {\n return (this.modulus + a - b) % this.modulus;\n }\n exp(a) {\n return this.expTable[a];\n }\n log(a) {\n if (a === 0) {\n throw new IllegalArgumentException();\n }\n return this.logTable[a];\n }\n inverse(a) {\n if (a === 0) {\n throw new ArithmeticException();\n }\n return this.expTable[this.modulus - this.logTable[a] - 1];\n }\n multiply(a, b) {\n if (a === 0 || b === 0) {\n return 0;\n }\n return this.expTable[(this.logTable[a] + this.logTable[b]) % (this.modulus - 1)];\n }\n getSize() {\n return this.modulus;\n }\n equals(o) {\n return o === this;\n }\n }\n\n /*\n * Copyright 2012 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n /**\n *

A field based on powers of a generator integer, modulo some modulus.

\n *\n * @author Sean Owen\n * @see com.google.zxing.common.reedsolomon.GenericGF\n */\n /*public final*/ class ModulusGF extends ModulusBase {\n // private /*final*/ modulus: /*int*/ number;\n constructor(modulus, generator) {\n super();\n this.modulus = modulus;\n this.expTable = new Int32Array(modulus);\n this.logTable = new Int32Array(modulus);\n let x = /*int*/ 1;\n for (let i /*int*/ = 0; i < modulus; i++) {\n this.expTable[i] = x;\n x = (x * generator) % modulus;\n }\n for (let i /*int*/ = 0; i < modulus - 1; i++) {\n this.logTable[this.expTable[i]] = i;\n }\n // logTable[0] == 0 but this should never be used\n this.zero = new ModulusPoly(this, new Int32Array([0]));\n this.one = new ModulusPoly(this, new Int32Array([1]));\n }\n getZero() {\n return this.zero;\n }\n getOne() {\n return this.one;\n }\n buildMonomial(degree, coefficient) {\n if (degree < 0) {\n throw new IllegalArgumentException();\n }\n if (coefficient === 0) {\n return this.zero;\n }\n let coefficients = new Int32Array(degree + 1);\n coefficients[0] = coefficient;\n return new ModulusPoly(this, coefficients);\n }\n }\n ModulusGF.PDF417_GF = new ModulusGF(PDF417Common.NUMBER_OF_CODEWORDS, 3);\n\n /*\n * Copyright 2012 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n /**\n *

PDF417 error correction implementation.

\n *\n *

This example\n * is quite useful in understanding the algorithm.

\n *\n * @author Sean Owen\n * @see com.google.zxing.common.reedsolomon.ReedSolomonDecoder\n */\n /*public final*/ class ErrorCorrection {\n constructor() {\n this.field = ModulusGF.PDF417_GF;\n }\n /**\n * @param received received codewords\n * @param numECCodewords number of those codewords used for EC\n * @param erasures location of erasures\n * @return number of errors\n * @throws ChecksumException if errors cannot be corrected, maybe because of too many errors\n */\n decode(received, numECCodewords, erasures) {\n let poly = new ModulusPoly(this.field, received);\n let S = new Int32Array(numECCodewords);\n let error = false;\n for (let i /*int*/ = numECCodewords; i > 0; i--) {\n let evaluation = poly.evaluateAt(this.field.exp(i));\n S[numECCodewords - i] = evaluation;\n if (evaluation !== 0) {\n error = true;\n }\n }\n if (!error) {\n return 0;\n }\n let knownErrors = this.field.getOne();\n if (erasures != null) {\n for (const erasure of erasures) {\n let b = this.field.exp(received.length - 1 - erasure);\n // Add (1 - bx) term:\n let term = new ModulusPoly(this.field, new Int32Array([this.field.subtract(0, b), 1]));\n knownErrors = knownErrors.multiply(term);\n }\n }\n let syndrome = new ModulusPoly(this.field, S);\n // syndrome = syndrome.multiply(knownErrors);\n let sigmaOmega = this.runEuclideanAlgorithm(this.field.buildMonomial(numECCodewords, 1), syndrome, numECCodewords);\n let sigma = sigmaOmega[0];\n let omega = sigmaOmega[1];\n // sigma = sigma.multiply(knownErrors);\n let errorLocations = this.findErrorLocations(sigma);\n let errorMagnitudes = this.findErrorMagnitudes(omega, sigma, errorLocations);\n for (let i /*int*/ = 0; i < errorLocations.length; i++) {\n let position = received.length - 1 - this.field.log(errorLocations[i]);\n if (position < 0) {\n throw ChecksumException.getChecksumInstance();\n }\n received[position] = this.field.subtract(received[position], errorMagnitudes[i]);\n }\n return errorLocations.length;\n }\n /**\n *\n * @param ModulusPoly\n * @param a\n * @param ModulusPoly\n * @param b\n * @param int\n * @param R\n * @throws ChecksumException\n */\n runEuclideanAlgorithm(a, b, R) {\n // Assume a's degree is >= b's\n if (a.getDegree() < b.getDegree()) {\n let temp = a;\n a = b;\n b = temp;\n }\n let rLast = a;\n let r = b;\n let tLast = this.field.getZero();\n let t = this.field.getOne();\n // Run Euclidean algorithm until r's degree is less than R/2\n while (r.getDegree() >= Math.round(R / 2)) {\n let rLastLast = rLast;\n let tLastLast = tLast;\n rLast = r;\n tLast = t;\n // Divide rLastLast by rLast, with quotient in q and remainder in r\n if (rLast.isZero()) {\n // Oops, Euclidean algorithm already terminated?\n throw ChecksumException.getChecksumInstance();\n }\n r = rLastLast;\n let q = this.field.getZero();\n let denominatorLeadingTerm = rLast.getCoefficient(rLast.getDegree());\n let dltInverse = this.field.inverse(denominatorLeadingTerm);\n while (r.getDegree() >= rLast.getDegree() && !r.isZero()) {\n let degreeDiff = r.getDegree() - rLast.getDegree();\n let scale = this.field.multiply(r.getCoefficient(r.getDegree()), dltInverse);\n q = q.add(this.field.buildMonomial(degreeDiff, scale));\n r = r.subtract(rLast.multiplyByMonomial(degreeDiff, scale));\n }\n t = q.multiply(tLast).subtract(tLastLast).negative();\n }\n let sigmaTildeAtZero = t.getCoefficient(0);\n if (sigmaTildeAtZero === 0) {\n throw ChecksumException.getChecksumInstance();\n }\n let inverse = this.field.inverse(sigmaTildeAtZero);\n let sigma = t.multiply(inverse);\n let omega = r.multiply(inverse);\n return [sigma, omega];\n }\n /**\n *\n * @param errorLocator\n * @throws ChecksumException\n */\n findErrorLocations(errorLocator) {\n // This is a direct application of Chien's search\n let numErrors = errorLocator.getDegree();\n let result = new Int32Array(numErrors);\n let e = 0;\n for (let i /*int*/ = 1; i < this.field.getSize() && e < numErrors; i++) {\n if (errorLocator.evaluateAt(i) === 0) {\n result[e] = this.field.inverse(i);\n e++;\n }\n }\n if (e !== numErrors) {\n throw ChecksumException.getChecksumInstance();\n }\n return result;\n }\n findErrorMagnitudes(errorEvaluator, errorLocator, errorLocations) {\n let errorLocatorDegree = errorLocator.getDegree();\n let formalDerivativeCoefficients = new Int32Array(errorLocatorDegree);\n for (let i /*int*/ = 1; i <= errorLocatorDegree; i++) {\n formalDerivativeCoefficients[errorLocatorDegree - i] =\n this.field.multiply(i, errorLocator.getCoefficient(i));\n }\n let formalDerivative = new ModulusPoly(this.field, formalDerivativeCoefficients);\n // This is directly applying Forney's Formula\n let s = errorLocations.length;\n let result = new Int32Array(s);\n for (let i /*int*/ = 0; i < s; i++) {\n let xiInverse = this.field.inverse(errorLocations[i]);\n let numerator = this.field.subtract(0, errorEvaluator.evaluateAt(xiInverse));\n let denominator = this.field.inverse(formalDerivative.evaluateAt(xiInverse));\n result[i] = this.field.multiply(numerator, denominator);\n }\n return result;\n }\n }\n\n /*\n * Copyright 2013 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n /**\n * @author Guenther Grau\n */\n /*final*/ class BoundingBox {\n constructor(image, topLeft, bottomLeft, topRight, bottomRight) {\n if (image instanceof BoundingBox) {\n this.constructor_2(image);\n }\n else {\n this.constructor_1(image, topLeft, bottomLeft, topRight, bottomRight);\n }\n }\n /**\n *\n * @param image\n * @param topLeft\n * @param bottomLeft\n * @param topRight\n * @param bottomRight\n *\n * @throws NotFoundException\n */\n constructor_1(image, topLeft, bottomLeft, topRight, bottomRight) {\n const leftUnspecified = topLeft == null || bottomLeft == null;\n const rightUnspecified = topRight == null || bottomRight == null;\n if (leftUnspecified && rightUnspecified) {\n throw new NotFoundException();\n }\n if (leftUnspecified) {\n topLeft = new ResultPoint(0, topRight.getY());\n bottomLeft = new ResultPoint(0, bottomRight.getY());\n }\n else if (rightUnspecified) {\n topRight = new ResultPoint(image.getWidth() - 1, topLeft.getY());\n bottomRight = new ResultPoint(image.getWidth() - 1, bottomLeft.getY());\n }\n this.image = image;\n this.topLeft = topLeft;\n this.bottomLeft = bottomLeft;\n this.topRight = topRight;\n this.bottomRight = bottomRight;\n this.minX = Math.trunc(Math.min(topLeft.getX(), bottomLeft.getX()));\n this.maxX = Math.trunc(Math.max(topRight.getX(), bottomRight.getX()));\n this.minY = Math.trunc(Math.min(topLeft.getY(), topRight.getY()));\n this.maxY = Math.trunc(Math.max(bottomLeft.getY(), bottomRight.getY()));\n }\n constructor_2(boundingBox) {\n this.image = boundingBox.image;\n this.topLeft = boundingBox.getTopLeft();\n this.bottomLeft = boundingBox.getBottomLeft();\n this.topRight = boundingBox.getTopRight();\n this.bottomRight = boundingBox.getBottomRight();\n this.minX = boundingBox.getMinX();\n this.maxX = boundingBox.getMaxX();\n this.minY = boundingBox.getMinY();\n this.maxY = boundingBox.getMaxY();\n }\n /**\n * @throws NotFoundException\n */\n static merge(leftBox, rightBox) {\n if (leftBox == null) {\n return rightBox;\n }\n if (rightBox == null) {\n return leftBox;\n }\n return new BoundingBox(leftBox.image, leftBox.topLeft, leftBox.bottomLeft, rightBox.topRight, rightBox.bottomRight);\n }\n /**\n * @throws NotFoundException\n */\n addMissingRows(missingStartRows, missingEndRows, isLeft) {\n let newTopLeft = this.topLeft;\n let newBottomLeft = this.bottomLeft;\n let newTopRight = this.topRight;\n let newBottomRight = this.bottomRight;\n if (missingStartRows > 0) {\n let top = isLeft ? this.topLeft : this.topRight;\n let newMinY = Math.trunc(top.getY() - missingStartRows);\n if (newMinY < 0) {\n newMinY = 0;\n }\n let newTop = new ResultPoint(top.getX(), newMinY);\n if (isLeft) {\n newTopLeft = newTop;\n }\n else {\n newTopRight = newTop;\n }\n }\n if (missingEndRows > 0) {\n let bottom = isLeft ? this.bottomLeft : this.bottomRight;\n let newMaxY = Math.trunc(bottom.getY() + missingEndRows);\n if (newMaxY >= this.image.getHeight()) {\n newMaxY = this.image.getHeight() - 1;\n }\n let newBottom = new ResultPoint(bottom.getX(), newMaxY);\n if (isLeft) {\n newBottomLeft = newBottom;\n }\n else {\n newBottomRight = newBottom;\n }\n }\n return new BoundingBox(this.image, newTopLeft, newBottomLeft, newTopRight, newBottomRight);\n }\n getMinX() {\n return this.minX;\n }\n getMaxX() {\n return this.maxX;\n }\n getMinY() {\n return this.minY;\n }\n getMaxY() {\n return this.maxY;\n }\n getTopLeft() {\n return this.topLeft;\n }\n getTopRight() {\n return this.topRight;\n }\n getBottomLeft() {\n return this.bottomLeft;\n }\n getBottomRight() {\n return this.bottomRight;\n }\n }\n\n /*\n * Copyright 2013 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n // package com.google.zxing.pdf417.decoder;\n /**\n * @author Guenther Grau\n */\n /*final*/ class BarcodeMetadata {\n constructor(columnCount, rowCountUpperPart, rowCountLowerPart, errorCorrectionLevel) {\n this.columnCount = columnCount;\n this.errorCorrectionLevel = errorCorrectionLevel;\n this.rowCountUpperPart = rowCountUpperPart;\n this.rowCountLowerPart = rowCountLowerPart;\n this.rowCount = rowCountUpperPart + rowCountLowerPart;\n }\n getColumnCount() {\n return this.columnCount;\n }\n getErrorCorrectionLevel() {\n return this.errorCorrectionLevel;\n }\n getRowCount() {\n return this.rowCount;\n }\n getRowCountUpperPart() {\n return this.rowCountUpperPart;\n }\n getRowCountLowerPart() {\n return this.rowCountLowerPart;\n }\n }\n\n /**\n * Java Formatter class polyfill that works in the JS way.\n */\n class Formatter {\n constructor() {\n this.buffer = '';\n }\n /**\n *\n * @see https://stackoverflow.com/a/13439711/4367683\n *\n * @param str\n * @param arr\n */\n static form(str, arr) {\n let i = -1;\n function callback(exp, p0, p1, p2, p3, p4) {\n if (exp === '%%')\n return '%';\n if (arr[++i] === undefined)\n return undefined;\n exp = p2 ? parseInt(p2.substr(1)) : undefined;\n let base = p3 ? parseInt(p3.substr(1)) : undefined;\n let val;\n switch (p4) {\n case 's':\n val = arr[i];\n break;\n case 'c':\n val = arr[i][0];\n break;\n case 'f':\n val = parseFloat(arr[i]).toFixed(exp);\n break;\n case 'p':\n val = parseFloat(arr[i]).toPrecision(exp);\n break;\n case 'e':\n val = parseFloat(arr[i]).toExponential(exp);\n break;\n case 'x':\n val = parseInt(arr[i]).toString(base ? base : 16);\n break;\n case 'd':\n val = parseFloat(parseInt(arr[i], base ? base : 10).toPrecision(exp)).toFixed(0);\n break;\n }\n val = typeof val === 'object' ? JSON.stringify(val) : (+val).toString(base);\n let size = parseInt(p1); /* padding size */\n let ch = p1 && (p1[0] + '') === '0' ? '0' : ' '; /* isnull? */\n while (val.length < size)\n val = p0 !== undefined ? val + ch : ch + val; /* isminus? */\n return val;\n }\n let regex = /%(-)?(0?[0-9]+)?([.][0-9]+)?([#][0-9]+)?([scfpexd%])/g;\n return str.replace(regex, callback);\n }\n /**\n *\n * @param append The new string to append.\n * @param args Argumets values to be formated.\n */\n format(append, ...args) {\n this.buffer += Formatter.form(append, args);\n }\n /**\n * Returns the Formatter string value.\n */\n toString() {\n return this.buffer;\n }\n }\n\n /*\n * Copyright 2013 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n /**\n * @author Guenther Grau\n */\n class DetectionResultColumn {\n constructor(boundingBox) {\n this.boundingBox = new BoundingBox(boundingBox);\n // this.codewords = new Codeword[boundingBox.getMaxY() - boundingBox.getMinY() + 1];\n this.codewords = new Array(boundingBox.getMaxY() - boundingBox.getMinY() + 1);\n }\n /*final*/ getCodewordNearby(imageRow) {\n let codeword = this.getCodeword(imageRow);\n if (codeword != null) {\n return codeword;\n }\n for (let i = 1; i < DetectionResultColumn.MAX_NEARBY_DISTANCE; i++) {\n let nearImageRow = this.imageRowToCodewordIndex(imageRow) - i;\n if (nearImageRow >= 0) {\n codeword = this.codewords[nearImageRow];\n if (codeword != null) {\n return codeword;\n }\n }\n nearImageRow = this.imageRowToCodewordIndex(imageRow) + i;\n if (nearImageRow < this.codewords.length) {\n codeword = this.codewords[nearImageRow];\n if (codeword != null) {\n return codeword;\n }\n }\n }\n return null;\n }\n /*final int*/ imageRowToCodewordIndex(imageRow) {\n return imageRow - this.boundingBox.getMinY();\n }\n /*final void*/ setCodeword(imageRow, codeword) {\n this.codewords[this.imageRowToCodewordIndex(imageRow)] = codeword;\n }\n /*final*/ getCodeword(imageRow) {\n return this.codewords[this.imageRowToCodewordIndex(imageRow)];\n }\n /*final*/ getBoundingBox() {\n return this.boundingBox;\n }\n /*final*/ getCodewords() {\n return this.codewords;\n }\n // @Override\n toString() {\n const formatter = new Formatter();\n let row = 0;\n for (const codeword of this.codewords) {\n if (codeword == null) {\n formatter.format('%3d: | %n', row++);\n continue;\n }\n formatter.format('%3d: %3d|%3d%n', row++, codeword.getRowNumber(), codeword.getValue());\n }\n return formatter.toString();\n }\n }\n DetectionResultColumn.MAX_NEARBY_DISTANCE = 5;\n\n /*\n * Copyright 2013 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n // import java.util.ArrayList;\n // import java.util.Collection;\n // import java.util.HashMap;\n // import java.util.Map;\n // import java.util.Map.Entry;\n /**\n * @author Guenther Grau\n */\n /*final*/ class BarcodeValue {\n constructor() {\n this.values = new Map();\n }\n /**\n * Add an occurrence of a value\n */\n setValue(value) {\n value = Math.trunc(value);\n let confidence = this.values.get(value);\n if (confidence == null) {\n confidence = 0;\n }\n confidence++;\n this.values.set(value, confidence);\n }\n /**\n * Determines the maximum occurrence of a set value and returns all values which were set with this occurrence.\n * @return an array of int, containing the values with the highest occurrence, or null, if no value was set\n */\n getValue() {\n let maxConfidence = -1;\n let result = new Array();\n for (const [key, value] of this.values.entries()) {\n const entry = {\n getKey: () => key,\n getValue: () => value,\n };\n if (entry.getValue() > maxConfidence) {\n maxConfidence = entry.getValue();\n result = [];\n result.push(entry.getKey());\n }\n else if (entry.getValue() === maxConfidence) {\n result.push(entry.getKey());\n }\n }\n return PDF417Common.toIntArray(result);\n }\n getConfidence(value) {\n return this.values.get(value);\n }\n }\n\n /*\n * Copyright 2013 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n /**\n * @author Guenther Grau\n */\n /*final*/ class DetectionResultRowIndicatorColumn extends DetectionResultColumn {\n constructor(boundingBox, isLeft) {\n super(boundingBox);\n this._isLeft = isLeft;\n }\n setRowNumbers() {\n for (let codeword /*Codeword*/ of this.getCodewords()) {\n if (codeword != null) {\n codeword.setRowNumberAsRowIndicatorColumn();\n }\n }\n }\n // TODO implement properly\n // TODO maybe we should add missing codewords to store the correct row number to make\n // finding row numbers for other columns easier\n // use row height count to make detection of invalid row numbers more reliable\n adjustCompleteIndicatorColumnRowNumbers(barcodeMetadata) {\n let codewords = this.getCodewords();\n this.setRowNumbers();\n this.removeIncorrectCodewords(codewords, barcodeMetadata);\n let boundingBox = this.getBoundingBox();\n let top = this._isLeft ? boundingBox.getTopLeft() : boundingBox.getTopRight();\n let bottom = this._isLeft ? boundingBox.getBottomLeft() : boundingBox.getBottomRight();\n let firstRow = this.imageRowToCodewordIndex(Math.trunc(top.getY()));\n let lastRow = this.imageRowToCodewordIndex(Math.trunc(bottom.getY()));\n // We need to be careful using the average row height. Barcode could be skewed so that we have smaller and\n // taller rows\n // float averageRowHeight = (lastRow - firstRow) / /*(float)*/ barcodeMetadata.getRowCount();\n let barcodeRow = -1;\n let maxRowHeight = 1;\n let currentRowHeight = 0;\n for (let codewordsRow /*int*/ = firstRow; codewordsRow < lastRow; codewordsRow++) {\n if (codewords[codewordsRow] == null) {\n continue;\n }\n let codeword = codewords[codewordsRow];\n // float expectedRowNumber = (codewordsRow - firstRow) / averageRowHeight;\n // if (Math.abs(codeword.getRowNumber() - expectedRowNumber) > 2) {\n // SimpleLog.log(LEVEL.WARNING,\n // \"Removing codeword, rowNumberSkew too high, codeword[\" + codewordsRow + \"]: Expected Row: \" +\n // expectedRowNumber + \", RealRow: \" + codeword.getRowNumber() + \", value: \" + codeword.getValue());\n // codewords[codewordsRow] = null;\n // }\n let rowDifference = codeword.getRowNumber() - barcodeRow;\n // TODO improve handling with case where first row indicator doesn't start with 0\n if (rowDifference === 0) {\n currentRowHeight++;\n }\n else if (rowDifference === 1) {\n maxRowHeight = Math.max(maxRowHeight, currentRowHeight);\n currentRowHeight = 1;\n barcodeRow = codeword.getRowNumber();\n }\n else if (rowDifference < 0 ||\n codeword.getRowNumber() >= barcodeMetadata.getRowCount() ||\n rowDifference > codewordsRow) {\n codewords[codewordsRow] = null;\n }\n else {\n let checkedRows;\n if (maxRowHeight > 2) {\n checkedRows = (maxRowHeight - 2) * rowDifference;\n }\n else {\n checkedRows = rowDifference;\n }\n let closePreviousCodewordFound = checkedRows >= codewordsRow;\n for (let i /*int*/ = 1; i <= checkedRows && !closePreviousCodewordFound; i++) {\n // there must be (height * rowDifference) number of codewords missing. For now we assume height = 1.\n // This should hopefully get rid of most problems already.\n closePreviousCodewordFound = codewords[codewordsRow - i] != null;\n }\n if (closePreviousCodewordFound) {\n codewords[codewordsRow] = null;\n }\n else {\n barcodeRow = codeword.getRowNumber();\n currentRowHeight = 1;\n }\n }\n }\n // return (int) (averageRowHeight + 0.5);\n }\n getRowHeights() {\n let barcodeMetadata = this.getBarcodeMetadata();\n if (barcodeMetadata == null) {\n return null;\n }\n this.adjustIncompleteIndicatorColumnRowNumbers(barcodeMetadata);\n let result = new Int32Array(barcodeMetadata.getRowCount());\n for (let codeword /*Codeword*/ of this.getCodewords()) {\n if (codeword != null) {\n let rowNumber = codeword.getRowNumber();\n if (rowNumber >= result.length) {\n // We have more rows than the barcode metadata allows for, ignore them.\n continue;\n }\n result[rowNumber]++;\n } // else throw exception?\n }\n return result;\n }\n // TODO maybe we should add missing codewords to store the correct row number to make\n // finding row numbers for other columns easier\n // use row height count to make detection of invalid row numbers more reliable\n adjustIncompleteIndicatorColumnRowNumbers(barcodeMetadata) {\n let boundingBox = this.getBoundingBox();\n let top = this._isLeft ? boundingBox.getTopLeft() : boundingBox.getTopRight();\n let bottom = this._isLeft ? boundingBox.getBottomLeft() : boundingBox.getBottomRight();\n let firstRow = this.imageRowToCodewordIndex(Math.trunc(top.getY()));\n let lastRow = this.imageRowToCodewordIndex(Math.trunc(bottom.getY()));\n // float averageRowHeight = (lastRow - firstRow) / /*(float)*/ barcodeMetadata.getRowCount();\n let codewords = this.getCodewords();\n let barcodeRow = -1;\n for (let codewordsRow /*int*/ = firstRow; codewordsRow < lastRow; codewordsRow++) {\n if (codewords[codewordsRow] == null) {\n continue;\n }\n let codeword = codewords[codewordsRow];\n codeword.setRowNumberAsRowIndicatorColumn();\n let rowDifference = codeword.getRowNumber() - barcodeRow;\n // TODO improve handling with case where first row indicator doesn't start with 0\n if (rowDifference === 0) ;\n else if (rowDifference === 1) {\n barcodeRow = codeword.getRowNumber();\n }\n else if (codeword.getRowNumber() >= barcodeMetadata.getRowCount()) {\n codewords[codewordsRow] = null;\n }\n else {\n barcodeRow = codeword.getRowNumber();\n }\n }\n // return (int) (averageRowHeight + 0.5);\n }\n getBarcodeMetadata() {\n let codewords = this.getCodewords();\n let barcodeColumnCount = new BarcodeValue();\n let barcodeRowCountUpperPart = new BarcodeValue();\n let barcodeRowCountLowerPart = new BarcodeValue();\n let barcodeECLevel = new BarcodeValue();\n for (let codeword /*Codeword*/ of codewords) {\n if (codeword == null) {\n continue;\n }\n codeword.setRowNumberAsRowIndicatorColumn();\n let rowIndicatorValue = codeword.getValue() % 30;\n let codewordRowNumber = codeword.getRowNumber();\n if (!this._isLeft) {\n codewordRowNumber += 2;\n }\n switch (codewordRowNumber % 3) {\n case 0:\n barcodeRowCountUpperPart.setValue(rowIndicatorValue * 3 + 1);\n break;\n case 1:\n barcodeECLevel.setValue(rowIndicatorValue / 3);\n barcodeRowCountLowerPart.setValue(rowIndicatorValue % 3);\n break;\n case 2:\n barcodeColumnCount.setValue(rowIndicatorValue + 1);\n break;\n }\n }\n // Maybe we should check if we have ambiguous values?\n if ((barcodeColumnCount.getValue().length === 0) ||\n (barcodeRowCountUpperPart.getValue().length === 0) ||\n (barcodeRowCountLowerPart.getValue().length === 0) ||\n (barcodeECLevel.getValue().length === 0) ||\n barcodeColumnCount.getValue()[0] < 1 ||\n barcodeRowCountUpperPart.getValue()[0] + barcodeRowCountLowerPart.getValue()[0] < PDF417Common.MIN_ROWS_IN_BARCODE ||\n barcodeRowCountUpperPart.getValue()[0] + barcodeRowCountLowerPart.getValue()[0] > PDF417Common.MAX_ROWS_IN_BARCODE) {\n return null;\n }\n let barcodeMetadata = new BarcodeMetadata(barcodeColumnCount.getValue()[0], barcodeRowCountUpperPart.getValue()[0], barcodeRowCountLowerPart.getValue()[0], barcodeECLevel.getValue()[0]);\n this.removeIncorrectCodewords(codewords, barcodeMetadata);\n return barcodeMetadata;\n }\n removeIncorrectCodewords(codewords, barcodeMetadata) {\n // Remove codewords which do not match the metadata\n // TODO Maybe we should keep the incorrect codewords for the start and end positions?\n for (let codewordRow /*int*/ = 0; codewordRow < codewords.length; codewordRow++) {\n let codeword = codewords[codewordRow];\n if (codewords[codewordRow] == null) {\n continue;\n }\n let rowIndicatorValue = codeword.getValue() % 30;\n let codewordRowNumber = codeword.getRowNumber();\n if (codewordRowNumber > barcodeMetadata.getRowCount()) {\n codewords[codewordRow] = null;\n continue;\n }\n if (!this._isLeft) {\n codewordRowNumber += 2;\n }\n switch (codewordRowNumber % 3) {\n case 0:\n if (rowIndicatorValue * 3 + 1 !== barcodeMetadata.getRowCountUpperPart()) {\n codewords[codewordRow] = null;\n }\n break;\n case 1:\n if (Math.trunc(rowIndicatorValue / 3) !== barcodeMetadata.getErrorCorrectionLevel() ||\n rowIndicatorValue % 3 !== barcodeMetadata.getRowCountLowerPart()) {\n codewords[codewordRow] = null;\n }\n break;\n case 2:\n if (rowIndicatorValue + 1 !== barcodeMetadata.getColumnCount()) {\n codewords[codewordRow] = null;\n }\n break;\n }\n }\n }\n isLeft() {\n return this._isLeft;\n }\n // @Override\n toString() {\n return 'IsLeft: ' + this._isLeft + '\\n' + super.toString();\n }\n }\n\n /*\n * Copyright 2013 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n /**\n * @author Guenther Grau\n */\n /*final*/ class DetectionResult {\n constructor(barcodeMetadata, boundingBox) {\n /*final*/ this.ADJUST_ROW_NUMBER_SKIP = 2;\n this.barcodeMetadata = barcodeMetadata;\n this.barcodeColumnCount = barcodeMetadata.getColumnCount();\n this.boundingBox = boundingBox;\n // this.detectionResultColumns = new DetectionResultColumn[this.barcodeColumnCount + 2];\n this.detectionResultColumns = new Array(this.barcodeColumnCount + 2);\n }\n getDetectionResultColumns() {\n this.adjustIndicatorColumnRowNumbers(this.detectionResultColumns[0]);\n this.adjustIndicatorColumnRowNumbers(this.detectionResultColumns[this.barcodeColumnCount + 1]);\n let unadjustedCodewordCount = PDF417Common.MAX_CODEWORDS_IN_BARCODE;\n let previousUnadjustedCount;\n do {\n previousUnadjustedCount = unadjustedCodewordCount;\n unadjustedCodewordCount = this.adjustRowNumbersAndGetCount();\n } while (unadjustedCodewordCount > 0 && unadjustedCodewordCount < previousUnadjustedCount);\n return this.detectionResultColumns;\n }\n adjustIndicatorColumnRowNumbers(detectionResultColumn) {\n if (detectionResultColumn != null) {\n detectionResultColumn\n .adjustCompleteIndicatorColumnRowNumbers(this.barcodeMetadata);\n }\n }\n // TODO ensure that no detected codewords with unknown row number are left\n // we should be able to estimate the row height and use it as a hint for the row number\n // we should also fill the rows top to bottom and bottom to top\n /**\n * @return number of codewords which don't have a valid row number. Note that the count is not accurate as codewords\n * will be counted several times. It just serves as an indicator to see when we can stop adjusting row numbers\n */\n adjustRowNumbersAndGetCount() {\n let unadjustedCount = this.adjustRowNumbersByRow();\n if (unadjustedCount === 0) {\n return 0;\n }\n for (let barcodeColumn /*int*/ = 1; barcodeColumn < this.barcodeColumnCount + 1; barcodeColumn++) {\n let codewords = this.detectionResultColumns[barcodeColumn].getCodewords();\n for (let codewordsRow /*int*/ = 0; codewordsRow < codewords.length; codewordsRow++) {\n if (codewords[codewordsRow] == null) {\n continue;\n }\n if (!codewords[codewordsRow].hasValidRowNumber()) {\n this.adjustRowNumbers(barcodeColumn, codewordsRow, codewords);\n }\n }\n }\n return unadjustedCount;\n }\n adjustRowNumbersByRow() {\n this.adjustRowNumbersFromBothRI();\n // TODO we should only do full row adjustments if row numbers of left and right row indicator column match.\n // Maybe it's even better to calculated the height (rows: d) and divide it by the number of barcode\n // rows. This, together with the LRI and RRI row numbers should allow us to get a good estimate where a row\n // number starts and ends.\n let unadjustedCount = this.adjustRowNumbersFromLRI();\n return unadjustedCount + this.adjustRowNumbersFromRRI();\n }\n adjustRowNumbersFromBothRI() {\n if (this.detectionResultColumns[0] == null || this.detectionResultColumns[this.barcodeColumnCount + 1] == null) {\n return;\n }\n let LRIcodewords = this.detectionResultColumns[0].getCodewords();\n let RRIcodewords = this.detectionResultColumns[this.barcodeColumnCount + 1].getCodewords();\n for (let codewordsRow /*int*/ = 0; codewordsRow < LRIcodewords.length; codewordsRow++) {\n if (LRIcodewords[codewordsRow] != null &&\n RRIcodewords[codewordsRow] != null &&\n LRIcodewords[codewordsRow].getRowNumber() === RRIcodewords[codewordsRow].getRowNumber()) {\n for (let barcodeColumn /*int*/ = 1; barcodeColumn <= this.barcodeColumnCount; barcodeColumn++) {\n let codeword = this.detectionResultColumns[barcodeColumn].getCodewords()[codewordsRow];\n if (codeword == null) {\n continue;\n }\n codeword.setRowNumber(LRIcodewords[codewordsRow].getRowNumber());\n if (!codeword.hasValidRowNumber()) {\n this.detectionResultColumns[barcodeColumn].getCodewords()[codewordsRow] = null;\n }\n }\n }\n }\n }\n adjustRowNumbersFromRRI() {\n if (this.detectionResultColumns[this.barcodeColumnCount + 1] == null) {\n return 0;\n }\n let unadjustedCount = 0;\n let codewords = this.detectionResultColumns[this.barcodeColumnCount + 1].getCodewords();\n for (let codewordsRow /*int*/ = 0; codewordsRow < codewords.length; codewordsRow++) {\n if (codewords[codewordsRow] == null) {\n continue;\n }\n let rowIndicatorRowNumber = codewords[codewordsRow].getRowNumber();\n let invalidRowCounts = 0;\n for (let barcodeColumn /*int*/ = this.barcodeColumnCount + 1; barcodeColumn > 0 && invalidRowCounts < this.ADJUST_ROW_NUMBER_SKIP; barcodeColumn--) {\n let codeword = this.detectionResultColumns[barcodeColumn].getCodewords()[codewordsRow];\n if (codeword != null) {\n invalidRowCounts = DetectionResult.adjustRowNumberIfValid(rowIndicatorRowNumber, invalidRowCounts, codeword);\n if (!codeword.hasValidRowNumber()) {\n unadjustedCount++;\n }\n }\n }\n }\n return unadjustedCount;\n }\n adjustRowNumbersFromLRI() {\n if (this.detectionResultColumns[0] == null) {\n return 0;\n }\n let unadjustedCount = 0;\n let codewords = this.detectionResultColumns[0].getCodewords();\n for (let codewordsRow /*int*/ = 0; codewordsRow < codewords.length; codewordsRow++) {\n if (codewords[codewordsRow] == null) {\n continue;\n }\n let rowIndicatorRowNumber = codewords[codewordsRow].getRowNumber();\n let invalidRowCounts = 0;\n for (let barcodeColumn /*int*/ = 1; barcodeColumn < this.barcodeColumnCount + 1 && invalidRowCounts < this.ADJUST_ROW_NUMBER_SKIP; barcodeColumn++) {\n let codeword = this.detectionResultColumns[barcodeColumn].getCodewords()[codewordsRow];\n if (codeword != null) {\n invalidRowCounts = DetectionResult.adjustRowNumberIfValid(rowIndicatorRowNumber, invalidRowCounts, codeword);\n if (!codeword.hasValidRowNumber()) {\n unadjustedCount++;\n }\n }\n }\n }\n return unadjustedCount;\n }\n static adjustRowNumberIfValid(rowIndicatorRowNumber, invalidRowCounts, codeword) {\n if (codeword == null) {\n return invalidRowCounts;\n }\n if (!codeword.hasValidRowNumber()) {\n if (codeword.isValidRowNumber(rowIndicatorRowNumber)) {\n codeword.setRowNumber(rowIndicatorRowNumber);\n invalidRowCounts = 0;\n }\n else {\n ++invalidRowCounts;\n }\n }\n return invalidRowCounts;\n }\n adjustRowNumbers(barcodeColumn, codewordsRow, codewords) {\n if (!this.detectionResultColumns[barcodeColumn - 1]) {\n return;\n }\n let codeword = codewords[codewordsRow];\n let previousColumnCodewords = this.detectionResultColumns[barcodeColumn - 1].getCodewords();\n let nextColumnCodewords = previousColumnCodewords;\n if (this.detectionResultColumns[barcodeColumn + 1] != null) {\n nextColumnCodewords = this.detectionResultColumns[barcodeColumn + 1].getCodewords();\n }\n // let otherCodewords: Codeword[] = new Codeword[14];\n let otherCodewords = new Array(14);\n otherCodewords[2] = previousColumnCodewords[codewordsRow];\n otherCodewords[3] = nextColumnCodewords[codewordsRow];\n if (codewordsRow > 0) {\n otherCodewords[0] = codewords[codewordsRow - 1];\n otherCodewords[4] = previousColumnCodewords[codewordsRow - 1];\n otherCodewords[5] = nextColumnCodewords[codewordsRow - 1];\n }\n if (codewordsRow > 1) {\n otherCodewords[8] = codewords[codewordsRow - 2];\n otherCodewords[10] = previousColumnCodewords[codewordsRow - 2];\n otherCodewords[11] = nextColumnCodewords[codewordsRow - 2];\n }\n if (codewordsRow < codewords.length - 1) {\n otherCodewords[1] = codewords[codewordsRow + 1];\n otherCodewords[6] = previousColumnCodewords[codewordsRow + 1];\n otherCodewords[7] = nextColumnCodewords[codewordsRow + 1];\n }\n if (codewordsRow < codewords.length - 2) {\n otherCodewords[9] = codewords[codewordsRow + 2];\n otherCodewords[12] = previousColumnCodewords[codewordsRow + 2];\n otherCodewords[13] = nextColumnCodewords[codewordsRow + 2];\n }\n for (let otherCodeword of otherCodewords) {\n if (DetectionResult.adjustRowNumber(codeword, otherCodeword)) {\n return;\n }\n }\n }\n /**\n * @return true, if row number was adjusted, false otherwise\n */\n static adjustRowNumber(codeword, otherCodeword) {\n if (otherCodeword == null) {\n return false;\n }\n if (otherCodeword.hasValidRowNumber() && otherCodeword.getBucket() === codeword.getBucket()) {\n codeword.setRowNumber(otherCodeword.getRowNumber());\n return true;\n }\n return false;\n }\n getBarcodeColumnCount() {\n return this.barcodeColumnCount;\n }\n getBarcodeRowCount() {\n return this.barcodeMetadata.getRowCount();\n }\n getBarcodeECLevel() {\n return this.barcodeMetadata.getErrorCorrectionLevel();\n }\n setBoundingBox(boundingBox) {\n this.boundingBox = boundingBox;\n }\n getBoundingBox() {\n return this.boundingBox;\n }\n setDetectionResultColumn(barcodeColumn, detectionResultColumn) {\n this.detectionResultColumns[barcodeColumn] = detectionResultColumn;\n }\n getDetectionResultColumn(barcodeColumn) {\n return this.detectionResultColumns[barcodeColumn];\n }\n // @Override\n toString() {\n let rowIndicatorColumn = this.detectionResultColumns[0];\n if (rowIndicatorColumn == null) {\n rowIndicatorColumn = this.detectionResultColumns[this.barcodeColumnCount + 1];\n }\n // try (\n let formatter = new Formatter();\n // ) {\n for (let codewordsRow /*int*/ = 0; codewordsRow < rowIndicatorColumn.getCodewords().length; codewordsRow++) {\n formatter.format('CW %3d:', codewordsRow);\n for (let barcodeColumn /*int*/ = 0; barcodeColumn < this.barcodeColumnCount + 2; barcodeColumn++) {\n if (this.detectionResultColumns[barcodeColumn] == null) {\n formatter.format(' | ');\n continue;\n }\n let codeword = this.detectionResultColumns[barcodeColumn].getCodewords()[codewordsRow];\n if (codeword == null) {\n formatter.format(' | ');\n continue;\n }\n formatter.format(' %3d|%3d', codeword.getRowNumber(), codeword.getValue());\n }\n formatter.format('%n');\n }\n return formatter.toString();\n // }\n }\n }\n\n /*\n * Copyright 2013 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n // package com.google.zxing.pdf417.decoder;\n /**\n * @author Guenther Grau\n */\n /*final*/ class Codeword {\n constructor(startX, endX, bucket, value) {\n this.rowNumber = Codeword.BARCODE_ROW_UNKNOWN;\n this.startX = Math.trunc(startX);\n this.endX = Math.trunc(endX);\n this.bucket = Math.trunc(bucket);\n this.value = Math.trunc(value);\n }\n hasValidRowNumber() {\n return this.isValidRowNumber(this.rowNumber);\n }\n isValidRowNumber(rowNumber) {\n return rowNumber !== Codeword.BARCODE_ROW_UNKNOWN && this.bucket === (rowNumber % 3) * 3;\n }\n setRowNumberAsRowIndicatorColumn() {\n this.rowNumber = Math.trunc((Math.trunc(this.value / 30)) * 3 + Math.trunc(this.bucket / 3));\n }\n getWidth() {\n return this.endX - this.startX;\n }\n getStartX() {\n return this.startX;\n }\n getEndX() {\n return this.endX;\n }\n getBucket() {\n return this.bucket;\n }\n getValue() {\n return this.value;\n }\n getRowNumber() {\n return this.rowNumber;\n }\n setRowNumber(rowNumber) {\n this.rowNumber = rowNumber;\n }\n // @Override\n toString() {\n return this.rowNumber + '|' + this.value;\n }\n }\n Codeword.BARCODE_ROW_UNKNOWN = -1;\n\n /*\n * Copyright 2013 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n /**\n * @author Guenther Grau\n * @author creatale GmbH (christoph.schulz@creatale.de)\n */\n /*final*/ class PDF417CodewordDecoder {\n /* @note\n * this action have to be performed before first use of class\n * - static constructor\n * working with 32bit float (based from Java logic)\n */\n static initialize() {\n // Pre-computes the symbol ratio table.\n for ( /*int*/let i = 0; i < PDF417Common.SYMBOL_TABLE.length; i++) {\n let currentSymbol = PDF417Common.SYMBOL_TABLE[i];\n let currentBit = currentSymbol & 0x1;\n for ( /*int*/let j = 0; j < PDF417Common.BARS_IN_MODULE; j++) {\n let size = 0.0;\n while ((currentSymbol & 0x1) === currentBit) {\n size += 1.0;\n currentSymbol >>= 1;\n }\n currentBit = currentSymbol & 0x1;\n if (!PDF417CodewordDecoder.RATIOS_TABLE[i]) {\n PDF417CodewordDecoder.RATIOS_TABLE[i] = new Array(PDF417Common.BARS_IN_MODULE);\n }\n PDF417CodewordDecoder.RATIOS_TABLE[i][PDF417Common.BARS_IN_MODULE - j - 1] = Math.fround(size / PDF417Common.MODULES_IN_CODEWORD);\n }\n }\n this.bSymbolTableReady = true;\n }\n static getDecodedValue(moduleBitCount) {\n let decodedValue = PDF417CodewordDecoder.getDecodedCodewordValue(PDF417CodewordDecoder.sampleBitCounts(moduleBitCount));\n if (decodedValue !== -1) {\n return decodedValue;\n }\n return PDF417CodewordDecoder.getClosestDecodedValue(moduleBitCount);\n }\n static sampleBitCounts(moduleBitCount) {\n let bitCountSum = MathUtils.sum(moduleBitCount);\n let result = new Int32Array(PDF417Common.BARS_IN_MODULE);\n let bitCountIndex = 0;\n let sumPreviousBits = 0;\n for ( /*int*/let i = 0; i < PDF417Common.MODULES_IN_CODEWORD; i++) {\n let sampleIndex = bitCountSum / (2 * PDF417Common.MODULES_IN_CODEWORD) +\n (i * bitCountSum) / PDF417Common.MODULES_IN_CODEWORD;\n if (sumPreviousBits + moduleBitCount[bitCountIndex] <= sampleIndex) {\n sumPreviousBits += moduleBitCount[bitCountIndex];\n bitCountIndex++;\n }\n result[bitCountIndex]++;\n }\n return result;\n }\n static getDecodedCodewordValue(moduleBitCount) {\n let decodedValue = PDF417CodewordDecoder.getBitValue(moduleBitCount);\n return PDF417Common.getCodeword(decodedValue) === -1 ? -1 : decodedValue;\n }\n static getBitValue(moduleBitCount) {\n let result = /*long*/ 0;\n for (let /*int*/ i = 0; i < moduleBitCount.length; i++) {\n for ( /*int*/let bit = 0; bit < moduleBitCount[i]; bit++) {\n result = (result << 1) | (i % 2 === 0 ? 1 : 0);\n }\n }\n return Math.trunc(result);\n }\n // working with 32bit float (as in Java)\n static getClosestDecodedValue(moduleBitCount) {\n let bitCountSum = MathUtils.sum(moduleBitCount);\n let bitCountRatios = new Array(PDF417Common.BARS_IN_MODULE);\n if (bitCountSum > 1) {\n for (let /*int*/ i = 0; i < bitCountRatios.length; i++) {\n bitCountRatios[i] = Math.fround(moduleBitCount[i] / bitCountSum);\n }\n }\n let bestMatchError = Float.MAX_VALUE;\n let bestMatch = -1;\n if (!this.bSymbolTableReady) {\n PDF417CodewordDecoder.initialize();\n }\n for ( /*int*/let j = 0; j < PDF417CodewordDecoder.RATIOS_TABLE.length; j++) {\n let error = 0.0;\n let ratioTableRow = PDF417CodewordDecoder.RATIOS_TABLE[j];\n for ( /*int*/let k = 0; k < PDF417Common.BARS_IN_MODULE; k++) {\n let diff = Math.fround(ratioTableRow[k] - bitCountRatios[k]);\n error += Math.fround(diff * diff);\n if (error >= bestMatchError) {\n break;\n }\n }\n if (error < bestMatchError) {\n bestMatchError = error;\n bestMatch = PDF417Common.SYMBOL_TABLE[j];\n }\n }\n return bestMatch;\n }\n }\n // flag that the table is ready for use\n PDF417CodewordDecoder.bSymbolTableReady = false;\n PDF417CodewordDecoder.RATIOS_TABLE = new Array(PDF417Common.SYMBOL_TABLE.length).map(x => x = new Array(PDF417Common.BARS_IN_MODULE));\n\n /*\n * Copyright 2013 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n // package com.google.zxing.pdf417;\n /**\n * @author Guenther Grau\n */\n /*public final*/ class PDF417ResultMetadata {\n constructor() {\n this.segmentCount = -1;\n this.fileSize = -1;\n this.timestamp = -1;\n this.checksum = -1;\n }\n /**\n * The Segment ID represents the segment of the whole file distributed over different symbols.\n *\n * @return File segment index\n */\n getSegmentIndex() {\n return this.segmentIndex;\n }\n setSegmentIndex(segmentIndex) {\n this.segmentIndex = segmentIndex;\n }\n /**\n * Is the same for each related PDF417 symbol\n *\n * @return File ID\n */\n getFileId() {\n return this.fileId;\n }\n setFileId(fileId) {\n this.fileId = fileId;\n }\n /**\n * @return always null\n * @deprecated use dedicated already parsed fields\n */\n // @Deprecated\n getOptionalData() {\n return this.optionalData;\n }\n /**\n * @param optionalData old optional data format as int array\n * @deprecated parse and use new fields\n */\n // @Deprecated\n setOptionalData(optionalData) {\n this.optionalData = optionalData;\n }\n /**\n * @return true if it is the last segment\n */\n isLastSegment() {\n return this.lastSegment;\n }\n setLastSegment(lastSegment) {\n this.lastSegment = lastSegment;\n }\n /**\n * @return count of segments, -1 if not set\n */\n getSegmentCount() {\n return this.segmentCount;\n }\n setSegmentCount(segmentCount /*int*/) {\n this.segmentCount = segmentCount;\n }\n getSender() {\n return this.sender || null;\n }\n setSender(sender) {\n this.sender = sender;\n }\n getAddressee() {\n return this.addressee || null;\n }\n setAddressee(addressee) {\n this.addressee = addressee;\n }\n /**\n * Filename of the encoded file\n *\n * @return filename\n */\n getFileName() {\n return this.fileName;\n }\n setFileName(fileName) {\n this.fileName = fileName;\n }\n /**\n * filesize in bytes of the encoded file\n *\n * @return filesize in bytes, -1 if not set\n */\n getFileSize() {\n return this.fileSize;\n }\n setFileSize(fileSize /*long*/) {\n this.fileSize = fileSize;\n }\n /**\n * 16-bit CRC checksum using CCITT-16\n *\n * @return crc checksum, -1 if not set\n */\n getChecksum() {\n return this.checksum;\n }\n setChecksum(checksum /*int*/) {\n this.checksum = checksum;\n }\n /**\n * unix epock timestamp, elapsed seconds since 1970-01-01\n *\n * @return elapsed seconds, -1 if not set\n */\n getTimestamp() {\n return this.timestamp;\n }\n setTimestamp(timestamp /*long*/) {\n this.timestamp = timestamp;\n }\n }\n\n /**\n * Ponyfill for Java's Long class.\n */\n class Long {\n /**\n * Parses a string to a number, since JS has no really Int64.\n *\n * @param num Numeric string.\n * @param radix Destination radix.\n */\n static parseLong(num, radix = undefined) {\n return parseInt(num, radix);\n }\n }\n\n /**\n * Custom Error class of type Exception.\n */\n class NullPointerException extends Exception {\n }\n NullPointerException.kind = 'NullPointerException';\n\n /*\n * Copyright (c) 1994, 2004, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.\n *\n * This code is free software; you can redistribute it and/or modify it\n * under the terms of the GNU General Public License version 2 only, as\n * published by the Free Software Foundation. Oracle designates this\n * particular file as subject to the \"Classpath\" exception as provided\n * by Oracle in the LICENSE file that accompanied this code.\n *\n * This code is distributed in the hope that it will be useful, but WITHOUT\n * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or\n * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License\n * version 2 for more details (a copy is included in the LICENSE file that\n * accompanied this code).\n *\n * You should have received a copy of the GNU General Public License version\n * 2 along with this work; if not, write to the Free Software Foundation,\n * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.\n *\n * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA\n * or visit www.oracle.com if you need additional information or have any\n * questions.\n */\n // package java.io;\n /**\n * This abstract class is the superclass of all classes representing\n * an output stream of bytes. An output stream accepts output bytes\n * and sends them to some sink.\n *

\n * Applications that need to define a subclass of\n * OutputStream must always provide at least a method\n * that writes one byte of output.\n *\n * @author Arthur van Hoff\n * @see java.io.BufferedOutputStream\n * @see java.io.ByteArrayOutputStream\n * @see java.io.DataOutputStream\n * @see java.io.FilterOutputStream\n * @see java.io.InputStream\n * @see java.io.OutputStream#write(int)\n * @since JDK1.0\n */\n /*public*/ class OutputStream /*implements Closeable, Flushable*/ {\n /**\n * Writes b.length bytes from the specified byte array\n * to this output stream. The general contract for write(b)\n * is that it should have exactly the same effect as the call\n * write(b, 0, b.length).\n *\n * @param b the data.\n * @exception IOException if an I/O error occurs.\n * @see java.io.OutputStream#write(byte[], int, int)\n */\n writeBytes(b) {\n this.writeBytesOffset(b, 0, b.length);\n }\n /**\n * Writes len bytes from the specified byte array\n * starting at offset off to this output stream.\n * The general contract for write(b, off, len) is that\n * some of the bytes in the array b are written to the\n * output stream in order; element b[off] is the first\n * byte written and b[off+len-1] is the last byte written\n * by this operation.\n *

\n * The write method of OutputStream calls\n * the write method of one argument on each of the bytes to be\n * written out. Subclasses are encouraged to override this method and\n * provide a more efficient implementation.\n *

\n * If b is null, a\n * NullPointerException is thrown.\n *

\n * If off is negative, or len is negative, or\n * off+len is greater than the length of the array\n * b, then an IndexOutOfBoundsException is thrown.\n *\n * @param b the data.\n * @param off the start offset in the data.\n * @param len the number of bytes to write.\n * @exception IOException if an I/O error occurs. In particular,\n * an IOException is thrown if the output\n * stream is closed.\n */\n writeBytesOffset(b, off, len) {\n if (b == null) {\n throw new NullPointerException();\n }\n else if ((off < 0) || (off > b.length) || (len < 0) ||\n ((off + len) > b.length) || ((off + len) < 0)) {\n throw new IndexOutOfBoundsException();\n }\n else if (len === 0) {\n return;\n }\n for (let i = 0; i < len; i++) {\n this.write(b[off + i]);\n }\n }\n /**\n * Flushes this output stream and forces any buffered output bytes\n * to be written out. The general contract of flush is\n * that calling it is an indication that, if any bytes previously\n * written have been buffered by the implementation of the output\n * stream, such bytes should immediately be written to their\n * intended destination.\n *

\n * If the intended destination of this stream is an abstraction provided by\n * the underlying operating system, for example a file, then flushing the\n * stream guarantees only that bytes previously written to the stream are\n * passed to the operating system for writing; it does not guarantee that\n * they are actually written to a physical device such as a disk drive.\n *

\n * The flush method of OutputStream does nothing.\n *\n * @exception IOException if an I/O error occurs.\n */\n flush() {\n }\n /**\n * Closes this output stream and releases any system resources\n * associated with this stream. The general contract of close\n * is that it closes the output stream. A closed stream cannot perform\n * output operations and cannot be reopened.\n *

\n * The close method of OutputStream does nothing.\n *\n * @exception IOException if an I/O error occurs.\n */\n close() {\n }\n }\n\n /**\n * Custom Error class of type Exception.\n */\n class OutOfMemoryError extends Exception {\n }\n\n /*\n * Copyright (c) 1994, 2010, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.\n *\n * This code is free software; you can redistribute it and/or modify it\n * under the terms of the GNU General Public License version 2 only, as\n * published by the Free Software Foundation. Oracle designates this\n * particular file as subject to the \"Classpath\" exception as provided\n * by Oracle in the LICENSE file that accompanied this code.\n *\n * This code is distributed in the hope that it will be useful, but WITHOUT\n * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or\n * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License\n * version 2 for more details (a copy is included in the LICENSE file that\n * accompanied this code).\n *\n * You should have received a copy of the GNU General Public License version\n * 2 along with this work; if not, write to the Free Software Foundation,\n * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.\n *\n * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA\n * or visit www.oracle.com if you need additional information or have any\n * questions.\n */\n /**\n * This class implements an output stream in which the data is\n * written into a byte array. The buffer automatically grows as data\n * is written to it.\n * The data can be retrieved using toByteArray() and\n * toString().\n *

\n * Closing a ByteArrayOutputStream has no effect. The methods in\n * this class can be called after the stream has been closed without\n * generating an IOException.\n *\n * @author Arthur van Hoff\n * @since JDK1.0\n */\n /*public*/ class ByteArrayOutputStream extends OutputStream {\n /**\n * Creates a new byte array output stream. The buffer capacity is\n * initially 32 bytes, though its size increases if necessary.\n */\n // public constructor() {\n // this(32);\n // }\n /**\n * Creates a new byte array output stream, with a buffer capacity of\n * the specified size, in bytes.\n *\n * @param size the initial size.\n * @exception IllegalArgumentException if size is negative.\n */\n constructor(size = 32) {\n super();\n /**\n * The number of valid bytes in the buffer.\n */\n this.count = 0;\n if (size < 0) {\n throw new IllegalArgumentException('Negative initial size: '\n + size);\n }\n this.buf = new Uint8Array(size);\n }\n /**\n * Increases the capacity if necessary to ensure that it can hold\n * at least the number of elements specified by the minimum\n * capacity argument.\n *\n * @param minCapacity the desired minimum capacity\n * @throws OutOfMemoryError if {@code minCapacity < 0}. This is\n * interpreted as a request for the unsatisfiably large capacity\n * {@code (long) Integer.MAX_VALUE + (minCapacity - Integer.MAX_VALUE)}.\n */\n ensureCapacity(minCapacity) {\n // overflow-conscious code\n if (minCapacity - this.buf.length > 0)\n this.grow(minCapacity);\n }\n /**\n * Increases the capacity to ensure that it can hold at least the\n * number of elements specified by the minimum capacity argument.\n *\n * @param minCapacity the desired minimum capacity\n */\n grow(minCapacity) {\n // overflow-conscious code\n let oldCapacity = this.buf.length;\n let newCapacity = oldCapacity << 1;\n if (newCapacity - minCapacity < 0)\n newCapacity = minCapacity;\n if (newCapacity < 0) {\n if (minCapacity < 0) // overflow\n throw new OutOfMemoryError();\n newCapacity = Integer.MAX_VALUE;\n }\n this.buf = Arrays.copyOfUint8Array(this.buf, newCapacity);\n }\n /**\n * Writes the specified byte to this byte array output stream.\n *\n * @param b the byte to be written.\n */\n write(b) {\n this.ensureCapacity(this.count + 1);\n this.buf[this.count] = /*(byte)*/ b;\n this.count += 1;\n }\n /**\n * Writes len bytes from the specified byte array\n * starting at offset off to this byte array output stream.\n *\n * @param b the data.\n * @param off the start offset in the data.\n * @param len the number of bytes to write.\n */\n writeBytesOffset(b, off, len) {\n if ((off < 0) || (off > b.length) || (len < 0) ||\n ((off + len) - b.length > 0)) {\n throw new IndexOutOfBoundsException();\n }\n this.ensureCapacity(this.count + len);\n System.arraycopy(b, off, this.buf, this.count, len);\n this.count += len;\n }\n /**\n * Writes the complete contents of this byte array output stream to\n * the specified output stream argument, as if by calling the output\n * stream's write method using out.write(buf, 0, count).\n *\n * @param out the output stream to which to write the data.\n * @exception IOException if an I/O error occurs.\n */\n writeTo(out) {\n out.writeBytesOffset(this.buf, 0, this.count);\n }\n /**\n * Resets the count field of this byte array output\n * stream to zero, so that all currently accumulated output in the\n * output stream is discarded. The output stream can be used again,\n * reusing the already allocated buffer space.\n *\n * @see java.io.ByteArrayInputStream#count\n */\n reset() {\n this.count = 0;\n }\n /**\n * Creates a newly allocated byte array. Its size is the current\n * size of this output stream and the valid contents of the buffer\n * have been copied into it.\n *\n * @return the current contents of this output stream, as a byte array.\n * @see java.io.ByteArrayOutputStream#size()\n */\n toByteArray() {\n return Arrays.copyOfUint8Array(this.buf, this.count);\n }\n /**\n * Returns the current size of the buffer.\n *\n * @return the value of the count field, which is the number\n * of valid bytes in this output stream.\n * @see java.io.ByteArrayOutputStream#count\n */\n size() {\n return this.count;\n }\n toString(param) {\n if (!param) {\n return this.toString_void();\n }\n if (typeof param === 'string') {\n return this.toString_string(param);\n }\n return this.toString_number(param);\n }\n /**\n * Converts the buffer's contents into a string decoding bytes using the\n * platform's default character set. The length of the new String\n * is a function of the character set, and hence may not be equal to the\n * size of the buffer.\n *\n *

This method always replaces malformed-input and unmappable-character\n * sequences with the default replacement string for the platform's\n * default character set. The {@linkplain java.nio.charset.CharsetDecoder}\n * class should be used when more control over the decoding process is\n * required.\n *\n * @return String decoded from the buffer's contents.\n * @since JDK1.1\n */\n toString_void() {\n return new String(this.buf /*, 0, this.count*/).toString();\n }\n /**\n * Converts the buffer's contents into a string by decoding the bytes using\n * the specified {@link java.nio.charset.Charset charsetName}. The length of\n * the new String is a function of the charset, and hence may not be\n * equal to the length of the byte array.\n *\n *

This method always replaces malformed-input and unmappable-character\n * sequences with this charset's default replacement string. The {@link\n * java.nio.charset.CharsetDecoder} class should be used when more control\n * over the decoding process is required.\n *\n * @param charsetName the name of a supported\n * {@linkplain java.nio.charset.Charset charset}\n * @return String decoded from the buffer's contents.\n * @exception UnsupportedEncodingException\n * If the named charset is not supported\n * @since JDK1.1\n */\n toString_string(charsetName) {\n return new String(this.buf /*, 0, this.count, charsetName*/).toString();\n }\n /**\n * Creates a newly allocated string. Its size is the current size of\n * the output stream and the valid contents of the buffer have been\n * copied into it. Each character c in the resulting string is\n * constructed from the corresponding element b in the byte\n * array such that:\n *

\n         *     c == (char)(((hibyte & 0xff) << 8) | (b & 0xff))\n         * 
\n *\n * @deprecated This method does not properly convert bytes into characters.\n * As of JDK 1.1, the preferred way to do this is via the\n * toString(String enc) method, which takes an encoding-name\n * argument, or the toString() method, which uses the\n * platform's default character encoding.\n *\n * @param hibyte the high byte of each resulting Unicode character.\n * @return the current contents of the output stream, as a string.\n * @see java.io.ByteArrayOutputStream#size()\n * @see java.io.ByteArrayOutputStream#toString(String)\n * @see java.io.ByteArrayOutputStream#toString()\n */\n // @Deprecated\n toString_number(hibyte) {\n return new String(this.buf /*, hibyte, 0, this.count*/).toString();\n }\n /**\n * Closing a ByteArrayOutputStream has no effect. The methods in\n * this class can be called after the stream has been closed without\n * generating an IOException.\n *

\n *\n * @throws IOException\n */\n close() {\n }\n }\n\n /*\n * Copyright 2009 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n /*private*/ var Mode$2;\n (function (Mode) {\n Mode[Mode[\"ALPHA\"] = 0] = \"ALPHA\";\n Mode[Mode[\"LOWER\"] = 1] = \"LOWER\";\n Mode[Mode[\"MIXED\"] = 2] = \"MIXED\";\n Mode[Mode[\"PUNCT\"] = 3] = \"PUNCT\";\n Mode[Mode[\"ALPHA_SHIFT\"] = 4] = \"ALPHA_SHIFT\";\n Mode[Mode[\"PUNCT_SHIFT\"] = 5] = \"PUNCT_SHIFT\";\n })(Mode$2 || (Mode$2 = {}));\n /**\n * Indirectly access the global BigInt constructor, it\n * allows browsers that doesn't support BigInt to run\n * the library without breaking due to \"undefined BigInt\"\n * errors.\n */\n function getBigIntConstructor() {\n if (typeof window !== 'undefined') {\n return window['BigInt'] || null;\n }\n if (typeof global !== 'undefined') {\n return global['BigInt'] || null;\n }\n if (typeof self !== 'undefined') {\n return self['BigInt'] || null;\n }\n throw new Error('Can\\'t search globals for BigInt!');\n }\n /**\n * Used to store the BigInt constructor.\n */\n let BigInteger;\n /**\n * This function creates a bigint value. It allows browsers\n * that doesn't support BigInt to run the rest of the library\n * by not directly accessing the BigInt constructor.\n */\n function createBigInt(num) {\n if (typeof BigInteger === 'undefined') {\n BigInteger = getBigIntConstructor();\n }\n if (BigInteger === null) {\n throw new Error('BigInt is not supported!');\n }\n return BigInteger(num);\n }\n function getEXP900() {\n // in Java - array with length = 16\n let EXP900 = [];\n EXP900[0] = createBigInt(1);\n let nineHundred = createBigInt(900);\n EXP900[1] = nineHundred;\n // in Java - array with length = 16\n for (let i /*int*/ = 2; i < 16; i++) {\n EXP900[i] = EXP900[i - 1] * nineHundred;\n }\n return EXP900;\n }\n /**\n *

This class contains the methods for decoding the PDF417 codewords.

\n *\n * @author SITA Lab (kevin.osullivan@sita.aero)\n * @author Guenther Grau\n */\n /*final*/ class DecodedBitStreamParser$2 {\n // private DecodedBitStreamParser() {\n // }\n /**\n *\n * @param codewords\n * @param ecLevel\n *\n * @throws FormatException\n */\n static decode(codewords, ecLevel) {\n // pass encoding to result (will be used for decode symbols in byte mode)\n let result = new StringBuilder('');\n // let encoding: Charset = StandardCharsets.ISO_8859_1;\n let encoding = CharacterSetECI.ISO8859_1;\n /**\n * @note the next command is specific from this TypeScript library\n * because TS can't properly cast some values to char and\n * convert it to string later correctly due to encoding\n * differences from Java version. As reported here:\n * https://github.com/zxing-js/library/pull/264/files#r382831593\n */\n result.enableDecoding(encoding);\n // Get compaction mode\n let codeIndex = 1;\n let code = codewords[codeIndex++];\n let resultMetadata = new PDF417ResultMetadata();\n while (codeIndex < codewords[0]) {\n switch (code) {\n case DecodedBitStreamParser$2.TEXT_COMPACTION_MODE_LATCH:\n codeIndex = DecodedBitStreamParser$2.textCompaction(codewords, codeIndex, result);\n break;\n case DecodedBitStreamParser$2.BYTE_COMPACTION_MODE_LATCH:\n case DecodedBitStreamParser$2.BYTE_COMPACTION_MODE_LATCH_6:\n codeIndex = DecodedBitStreamParser$2.byteCompaction(code, codewords, encoding, codeIndex, result);\n break;\n case DecodedBitStreamParser$2.MODE_SHIFT_TO_BYTE_COMPACTION_MODE:\n result.append(/*(char)*/ codewords[codeIndex++]);\n break;\n case DecodedBitStreamParser$2.NUMERIC_COMPACTION_MODE_LATCH:\n codeIndex = DecodedBitStreamParser$2.numericCompaction(codewords, codeIndex, result);\n break;\n case DecodedBitStreamParser$2.ECI_CHARSET:\n let charsetECI = CharacterSetECI.getCharacterSetECIByValue(codewords[codeIndex++]);\n // encoding = Charset.forName(charsetECI.getName());\n break;\n case DecodedBitStreamParser$2.ECI_GENERAL_PURPOSE:\n // Can't do anything with generic ECI; skip its 2 characters\n codeIndex += 2;\n break;\n case DecodedBitStreamParser$2.ECI_USER_DEFINED:\n // Can't do anything with user ECI; skip its 1 character\n codeIndex++;\n break;\n case DecodedBitStreamParser$2.BEGIN_MACRO_PDF417_CONTROL_BLOCK:\n codeIndex = DecodedBitStreamParser$2.decodeMacroBlock(codewords, codeIndex, resultMetadata);\n break;\n case DecodedBitStreamParser$2.BEGIN_MACRO_PDF417_OPTIONAL_FIELD:\n case DecodedBitStreamParser$2.MACRO_PDF417_TERMINATOR:\n // Should not see these outside a macro block\n throw new FormatException();\n default:\n // Default to text compaction. During testing numerous barcodes\n // appeared to be missing the starting mode. In these cases defaulting\n // to text compaction seems to work.\n codeIndex--;\n codeIndex = DecodedBitStreamParser$2.textCompaction(codewords, codeIndex, result);\n break;\n }\n if (codeIndex < codewords.length) {\n code = codewords[codeIndex++];\n }\n else {\n throw FormatException.getFormatInstance();\n }\n }\n if (result.length() === 0) {\n throw FormatException.getFormatInstance();\n }\n let decoderResult = new DecoderResult(null, result.toString(), null, ecLevel);\n decoderResult.setOther(resultMetadata);\n return decoderResult;\n }\n /**\n *\n * @param int\n * @param param1\n * @param codewords\n * @param int\n * @param codeIndex\n * @param PDF417ResultMetadata\n * @param resultMetadata\n *\n * @throws FormatException\n */\n // @SuppressWarnings(\"deprecation\")\n static decodeMacroBlock(codewords, codeIndex, resultMetadata) {\n if (codeIndex + DecodedBitStreamParser$2.NUMBER_OF_SEQUENCE_CODEWORDS > codewords[0]) {\n // we must have at least two bytes left for the segment index\n throw FormatException.getFormatInstance();\n }\n let segmentIndexArray = new Int32Array(DecodedBitStreamParser$2.NUMBER_OF_SEQUENCE_CODEWORDS);\n for (let i /*int*/ = 0; i < DecodedBitStreamParser$2.NUMBER_OF_SEQUENCE_CODEWORDS; i++, codeIndex++) {\n segmentIndexArray[i] = codewords[codeIndex];\n }\n resultMetadata.setSegmentIndex(Integer.parseInt(DecodedBitStreamParser$2.decodeBase900toBase10(segmentIndexArray, DecodedBitStreamParser$2.NUMBER_OF_SEQUENCE_CODEWORDS)));\n let fileId = new StringBuilder();\n codeIndex = DecodedBitStreamParser$2.textCompaction(codewords, codeIndex, fileId);\n resultMetadata.setFileId(fileId.toString());\n let optionalFieldsStart = -1;\n if (codewords[codeIndex] === DecodedBitStreamParser$2.BEGIN_MACRO_PDF417_OPTIONAL_FIELD) {\n optionalFieldsStart = codeIndex + 1;\n }\n while (codeIndex < codewords[0]) {\n switch (codewords[codeIndex]) {\n case DecodedBitStreamParser$2.BEGIN_MACRO_PDF417_OPTIONAL_FIELD:\n codeIndex++;\n switch (codewords[codeIndex]) {\n case DecodedBitStreamParser$2.MACRO_PDF417_OPTIONAL_FIELD_FILE_NAME:\n let fileName = new StringBuilder();\n codeIndex = DecodedBitStreamParser$2.textCompaction(codewords, codeIndex + 1, fileName);\n resultMetadata.setFileName(fileName.toString());\n break;\n case DecodedBitStreamParser$2.MACRO_PDF417_OPTIONAL_FIELD_SENDER:\n let sender = new StringBuilder();\n codeIndex = DecodedBitStreamParser$2.textCompaction(codewords, codeIndex + 1, sender);\n resultMetadata.setSender(sender.toString());\n break;\n case DecodedBitStreamParser$2.MACRO_PDF417_OPTIONAL_FIELD_ADDRESSEE:\n let addressee = new StringBuilder();\n codeIndex = DecodedBitStreamParser$2.textCompaction(codewords, codeIndex + 1, addressee);\n resultMetadata.setAddressee(addressee.toString());\n break;\n case DecodedBitStreamParser$2.MACRO_PDF417_OPTIONAL_FIELD_SEGMENT_COUNT:\n let segmentCount = new StringBuilder();\n codeIndex = DecodedBitStreamParser$2.numericCompaction(codewords, codeIndex + 1, segmentCount);\n resultMetadata.setSegmentCount(Integer.parseInt(segmentCount.toString()));\n break;\n case DecodedBitStreamParser$2.MACRO_PDF417_OPTIONAL_FIELD_TIME_STAMP:\n let timestamp = new StringBuilder();\n codeIndex = DecodedBitStreamParser$2.numericCompaction(codewords, codeIndex + 1, timestamp);\n resultMetadata.setTimestamp(Long.parseLong(timestamp.toString()));\n break;\n case DecodedBitStreamParser$2.MACRO_PDF417_OPTIONAL_FIELD_CHECKSUM:\n let checksum = new StringBuilder();\n codeIndex = DecodedBitStreamParser$2.numericCompaction(codewords, codeIndex + 1, checksum);\n resultMetadata.setChecksum(Integer.parseInt(checksum.toString()));\n break;\n case DecodedBitStreamParser$2.MACRO_PDF417_OPTIONAL_FIELD_FILE_SIZE:\n let fileSize = new StringBuilder();\n codeIndex = DecodedBitStreamParser$2.numericCompaction(codewords, codeIndex + 1, fileSize);\n resultMetadata.setFileSize(Long.parseLong(fileSize.toString()));\n break;\n default:\n throw FormatException.getFormatInstance();\n }\n break;\n case DecodedBitStreamParser$2.MACRO_PDF417_TERMINATOR:\n codeIndex++;\n resultMetadata.setLastSegment(true);\n break;\n default:\n throw FormatException.getFormatInstance();\n }\n }\n // copy optional fields to additional options\n if (optionalFieldsStart !== -1) {\n let optionalFieldsLength = codeIndex - optionalFieldsStart;\n if (resultMetadata.isLastSegment()) {\n // do not include terminator\n optionalFieldsLength--;\n }\n resultMetadata.setOptionalData(Arrays.copyOfRange(codewords, optionalFieldsStart, optionalFieldsStart + optionalFieldsLength));\n }\n return codeIndex;\n }\n /**\n * Text Compaction mode (see 5.4.1.5) permits all printable ASCII characters to be\n * encoded, i.e. values 32 - 126 inclusive in accordance with ISO/IEC 646 (IRV), as\n * well as selected control characters.\n *\n * @param codewords The array of codewords (data + error)\n * @param codeIndex The current index into the codeword array.\n * @param result The decoded data is appended to the result.\n * @return The next index into the codeword array.\n */\n static textCompaction(codewords, codeIndex, result) {\n // 2 character per codeword\n let textCompactionData = new Int32Array((codewords[0] - codeIndex) * 2);\n // Used to hold the byte compaction value if there is a mode shift\n let byteCompactionData = new Int32Array((codewords[0] - codeIndex) * 2);\n let index = 0;\n let end = false;\n while ((codeIndex < codewords[0]) && !end) {\n let code = codewords[codeIndex++];\n if (code < DecodedBitStreamParser$2.TEXT_COMPACTION_MODE_LATCH) {\n textCompactionData[index] = code / 30;\n textCompactionData[index + 1] = code % 30;\n index += 2;\n }\n else {\n switch (code) {\n case DecodedBitStreamParser$2.TEXT_COMPACTION_MODE_LATCH:\n // reinitialize text compaction mode to alpha sub mode\n textCompactionData[index++] = DecodedBitStreamParser$2.TEXT_COMPACTION_MODE_LATCH;\n break;\n case DecodedBitStreamParser$2.BYTE_COMPACTION_MODE_LATCH:\n case DecodedBitStreamParser$2.BYTE_COMPACTION_MODE_LATCH_6:\n case DecodedBitStreamParser$2.NUMERIC_COMPACTION_MODE_LATCH:\n case DecodedBitStreamParser$2.BEGIN_MACRO_PDF417_CONTROL_BLOCK:\n case DecodedBitStreamParser$2.BEGIN_MACRO_PDF417_OPTIONAL_FIELD:\n case DecodedBitStreamParser$2.MACRO_PDF417_TERMINATOR:\n codeIndex--;\n end = true;\n break;\n case DecodedBitStreamParser$2.MODE_SHIFT_TO_BYTE_COMPACTION_MODE:\n // The Mode Shift codeword 913 shall cause a temporary\n // switch from Text Compaction mode to Byte Compaction mode.\n // This switch shall be in effect for only the next codeword,\n // after which the mode shall revert to the prevailing sub-mode\n // of the Text Compaction mode. Codeword 913 is only available\n // in Text Compaction mode; its use is described in 5.4.2.4.\n textCompactionData[index] = DecodedBitStreamParser$2.MODE_SHIFT_TO_BYTE_COMPACTION_MODE;\n code = codewords[codeIndex++];\n byteCompactionData[index] = code;\n index++;\n break;\n }\n }\n }\n DecodedBitStreamParser$2.decodeTextCompaction(textCompactionData, byteCompactionData, index, result);\n return codeIndex;\n }\n /**\n * The Text Compaction mode includes all the printable ASCII characters\n * (i.e. values from 32 to 126) and three ASCII control characters: HT or tab\n * (9: e), LF or line feed (10: e), and CR or carriage\n * return (13: e). The Text Compaction mode also includes various latch\n * and shift characters which are used exclusively within the mode. The Text\n * Compaction mode encodes up to 2 characters per codeword. The compaction rules\n * for converting data into PDF417 codewords are defined in 5.4.2.2. The sub-mode\n * switches are defined in 5.4.2.3.\n *\n * @param textCompactionData The text compaction data.\n * @param byteCompactionData The byte compaction data if there\n * was a mode shift.\n * @param length The size of the text compaction and byte compaction data.\n * @param result The decoded data is appended to the result.\n */\n static decodeTextCompaction(textCompactionData, byteCompactionData, length, result) {\n // Beginning from an initial state of the Alpha sub-mode\n // The default compaction mode for PDF417 in effect at the start of each symbol shall always be Text\n // Compaction mode Alpha sub-mode (alphabetic: uppercase). A latch codeword from another mode to the Text\n // Compaction mode shall always switch to the Text Compaction Alpha sub-mode.\n let subMode = Mode$2.ALPHA;\n let priorToShiftMode = Mode$2.ALPHA;\n let i = 0;\n while (i < length) {\n let subModeCh = textCompactionData[i];\n let ch = /*char*/ '';\n switch (subMode) {\n case Mode$2.ALPHA:\n // Alpha (alphabetic: uppercase)\n if (subModeCh < 26) {\n // Upper case Alpha Character\n // Note: 65 = 'A' ASCII -> there is byte code of symbol\n ch = /*(char)('A' + subModeCh) */ String.fromCharCode(65 + subModeCh);\n }\n else {\n switch (subModeCh) {\n case 26:\n ch = ' ';\n break;\n case DecodedBitStreamParser$2.LL:\n subMode = Mode$2.LOWER;\n break;\n case DecodedBitStreamParser$2.ML:\n subMode = Mode$2.MIXED;\n break;\n case DecodedBitStreamParser$2.PS:\n // Shift to punctuation\n priorToShiftMode = subMode;\n subMode = Mode$2.PUNCT_SHIFT;\n break;\n case DecodedBitStreamParser$2.MODE_SHIFT_TO_BYTE_COMPACTION_MODE:\n result.append(/*(char)*/ byteCompactionData[i]);\n break;\n case DecodedBitStreamParser$2.TEXT_COMPACTION_MODE_LATCH:\n subMode = Mode$2.ALPHA;\n break;\n }\n }\n break;\n case Mode$2.LOWER:\n // Lower (alphabetic: lowercase)\n if (subModeCh < 26) {\n ch = /*(char)('a' + subModeCh)*/ String.fromCharCode(97 + subModeCh);\n }\n else {\n switch (subModeCh) {\n case 26:\n ch = ' ';\n break;\n case DecodedBitStreamParser$2.AS:\n // Shift to alpha\n priorToShiftMode = subMode;\n subMode = Mode$2.ALPHA_SHIFT;\n break;\n case DecodedBitStreamParser$2.ML:\n subMode = Mode$2.MIXED;\n break;\n case DecodedBitStreamParser$2.PS:\n // Shift to punctuation\n priorToShiftMode = subMode;\n subMode = Mode$2.PUNCT_SHIFT;\n break;\n case DecodedBitStreamParser$2.MODE_SHIFT_TO_BYTE_COMPACTION_MODE:\n // TODO Does this need to use the current character encoding? See other occurrences below\n result.append(/*(char)*/ byteCompactionData[i]);\n break;\n case DecodedBitStreamParser$2.TEXT_COMPACTION_MODE_LATCH:\n subMode = Mode$2.ALPHA;\n break;\n }\n }\n break;\n case Mode$2.MIXED:\n // Mixed (punctuation: e)\n if (subModeCh < DecodedBitStreamParser$2.PL) {\n ch = DecodedBitStreamParser$2.MIXED_CHARS[subModeCh];\n }\n else {\n switch (subModeCh) {\n case DecodedBitStreamParser$2.PL:\n subMode = Mode$2.PUNCT;\n break;\n case 26:\n ch = ' ';\n break;\n case DecodedBitStreamParser$2.LL:\n subMode = Mode$2.LOWER;\n break;\n case DecodedBitStreamParser$2.AL:\n subMode = Mode$2.ALPHA;\n break;\n case DecodedBitStreamParser$2.PS:\n // Shift to punctuation\n priorToShiftMode = subMode;\n subMode = Mode$2.PUNCT_SHIFT;\n break;\n case DecodedBitStreamParser$2.MODE_SHIFT_TO_BYTE_COMPACTION_MODE:\n result.append(/*(char)*/ byteCompactionData[i]);\n break;\n case DecodedBitStreamParser$2.TEXT_COMPACTION_MODE_LATCH:\n subMode = Mode$2.ALPHA;\n break;\n }\n }\n break;\n case Mode$2.PUNCT:\n // Punctuation\n if (subModeCh < DecodedBitStreamParser$2.PAL) {\n ch = DecodedBitStreamParser$2.PUNCT_CHARS[subModeCh];\n }\n else {\n switch (subModeCh) {\n case DecodedBitStreamParser$2.PAL:\n subMode = Mode$2.ALPHA;\n break;\n case DecodedBitStreamParser$2.MODE_SHIFT_TO_BYTE_COMPACTION_MODE:\n result.append(/*(char)*/ byteCompactionData[i]);\n break;\n case DecodedBitStreamParser$2.TEXT_COMPACTION_MODE_LATCH:\n subMode = Mode$2.ALPHA;\n break;\n }\n }\n break;\n case Mode$2.ALPHA_SHIFT:\n // Restore sub-mode\n subMode = priorToShiftMode;\n if (subModeCh < 26) {\n ch = /*(char)('A' + subModeCh)*/ String.fromCharCode(65 + subModeCh);\n }\n else {\n switch (subModeCh) {\n case 26:\n ch = ' ';\n break;\n case DecodedBitStreamParser$2.TEXT_COMPACTION_MODE_LATCH:\n subMode = Mode$2.ALPHA;\n break;\n }\n }\n break;\n case Mode$2.PUNCT_SHIFT:\n // Restore sub-mode\n subMode = priorToShiftMode;\n if (subModeCh < DecodedBitStreamParser$2.PAL) {\n ch = DecodedBitStreamParser$2.PUNCT_CHARS[subModeCh];\n }\n else {\n switch (subModeCh) {\n case DecodedBitStreamParser$2.PAL:\n subMode = Mode$2.ALPHA;\n break;\n case DecodedBitStreamParser$2.MODE_SHIFT_TO_BYTE_COMPACTION_MODE:\n // PS before Shift-to-Byte is used as a padding character,\n // see 5.4.2.4 of the specification\n result.append(/*(char)*/ byteCompactionData[i]);\n break;\n case DecodedBitStreamParser$2.TEXT_COMPACTION_MODE_LATCH:\n subMode = Mode$2.ALPHA;\n break;\n }\n }\n break;\n }\n // if (ch !== 0) {\n if (ch !== '') {\n // Append decoded character to result\n result.append(ch);\n }\n i++;\n }\n }\n /**\n * Byte Compaction mode (see 5.4.3) permits all 256 possible 8-bit byte values to be encoded.\n * This includes all ASCII characters value 0 to 127 inclusive and provides for international\n * character set support.\n *\n * @param mode The byte compaction mode i.e. 901 or 924\n * @param codewords The array of codewords (data + error)\n * @param encoding Currently active character encoding\n * @param codeIndex The current index into the codeword array.\n * @param result The decoded data is appended to the result.\n * @return The next index into the codeword array.\n */\n static /*int*/ byteCompaction(mode, codewords, encoding, codeIndex, result) {\n let decodedBytes = new ByteArrayOutputStream();\n let count = 0;\n let value = /*long*/ 0;\n let end = false;\n switch (mode) {\n case DecodedBitStreamParser$2.BYTE_COMPACTION_MODE_LATCH:\n // Total number of Byte Compaction characters to be encoded\n // is not a multiple of 6\n let byteCompactedCodewords = new Int32Array(6);\n let nextCode = codewords[codeIndex++];\n while ((codeIndex < codewords[0]) && !end) {\n byteCompactedCodewords[count++] = nextCode;\n // Base 900\n value = 900 * value + nextCode;\n nextCode = codewords[codeIndex++];\n // perhaps it should be ok to check only nextCode >= TEXT_COMPACTION_MODE_LATCH\n switch (nextCode) {\n case DecodedBitStreamParser$2.TEXT_COMPACTION_MODE_LATCH:\n case DecodedBitStreamParser$2.BYTE_COMPACTION_MODE_LATCH:\n case DecodedBitStreamParser$2.NUMERIC_COMPACTION_MODE_LATCH:\n case DecodedBitStreamParser$2.BYTE_COMPACTION_MODE_LATCH_6:\n case DecodedBitStreamParser$2.BEGIN_MACRO_PDF417_CONTROL_BLOCK:\n case DecodedBitStreamParser$2.BEGIN_MACRO_PDF417_OPTIONAL_FIELD:\n case DecodedBitStreamParser$2.MACRO_PDF417_TERMINATOR:\n codeIndex--;\n end = true;\n break;\n default:\n if ((count % 5 === 0) && (count > 0)) {\n // Decode every 5 codewords\n // Convert to Base 256\n for (let j /*int*/ = 0; j < 6; ++j) {\n /* @note\n * JavaScript stores numbers as 64 bits floating point numbers, but all bitwise operations are performed on 32 bits binary numbers.\n * So the next bitwise operation could not be done with simple numbers\n */\n decodedBytes.write(/*(byte)*/ Number(createBigInt(value) >> createBigInt(8 * (5 - j))));\n }\n value = 0;\n count = 0;\n }\n break;\n }\n }\n // if the end of all codewords is reached the last codeword needs to be added\n if (codeIndex === codewords[0] && nextCode < DecodedBitStreamParser$2.TEXT_COMPACTION_MODE_LATCH) {\n byteCompactedCodewords[count++] = nextCode;\n }\n // If Byte Compaction mode is invoked with codeword 901,\n // the last group of codewords is interpreted directly\n // as one byte per codeword, without compaction.\n for (let i /*int*/ = 0; i < count; i++) {\n decodedBytes.write(/*(byte)*/ byteCompactedCodewords[i]);\n }\n break;\n case DecodedBitStreamParser$2.BYTE_COMPACTION_MODE_LATCH_6:\n // Total number of Byte Compaction characters to be encoded\n // is an integer multiple of 6\n while (codeIndex < codewords[0] && !end) {\n let code = codewords[codeIndex++];\n if (code < DecodedBitStreamParser$2.TEXT_COMPACTION_MODE_LATCH) {\n count++;\n // Base 900\n value = 900 * value + code;\n }\n else {\n switch (code) {\n case DecodedBitStreamParser$2.TEXT_COMPACTION_MODE_LATCH:\n case DecodedBitStreamParser$2.BYTE_COMPACTION_MODE_LATCH:\n case DecodedBitStreamParser$2.NUMERIC_COMPACTION_MODE_LATCH:\n case DecodedBitStreamParser$2.BYTE_COMPACTION_MODE_LATCH_6:\n case DecodedBitStreamParser$2.BEGIN_MACRO_PDF417_CONTROL_BLOCK:\n case DecodedBitStreamParser$2.BEGIN_MACRO_PDF417_OPTIONAL_FIELD:\n case DecodedBitStreamParser$2.MACRO_PDF417_TERMINATOR:\n codeIndex--;\n end = true;\n break;\n }\n }\n if ((count % 5 === 0) && (count > 0)) {\n // Decode every 5 codewords\n // Convert to Base 256\n /* @note\n * JavaScript stores numbers as 64 bits floating point numbers, but all bitwise operations are performed on 32 bits binary numbers.\n * So the next bitwise operation could not be done with simple numbers\n */\n for (let j /*int*/ = 0; j < 6; ++j) {\n decodedBytes.write(/*(byte)*/ Number(createBigInt(value) >> createBigInt(8 * (5 - j))));\n }\n value = 0;\n count = 0;\n }\n }\n break;\n }\n result.append(StringEncoding.decode(decodedBytes.toByteArray(), encoding));\n return codeIndex;\n }\n /**\n * Numeric Compaction mode (see 5.4.4) permits efficient encoding of numeric data strings.\n *\n * @param codewords The array of codewords (data + error)\n * @param codeIndex The current index into the codeword array.\n * @param result The decoded data is appended to the result.\n * @return The next index into the codeword array.\n *\n * @throws FormatException\n */\n static numericCompaction(codewords, codeIndex /*int*/, result) {\n let count = 0;\n let end = false;\n let numericCodewords = new Int32Array(DecodedBitStreamParser$2.MAX_NUMERIC_CODEWORDS);\n while (codeIndex < codewords[0] && !end) {\n let code = codewords[codeIndex++];\n if (codeIndex === codewords[0]) {\n end = true;\n }\n if (code < DecodedBitStreamParser$2.TEXT_COMPACTION_MODE_LATCH) {\n numericCodewords[count] = code;\n count++;\n }\n else {\n switch (code) {\n case DecodedBitStreamParser$2.TEXT_COMPACTION_MODE_LATCH:\n case DecodedBitStreamParser$2.BYTE_COMPACTION_MODE_LATCH:\n case DecodedBitStreamParser$2.BYTE_COMPACTION_MODE_LATCH_6:\n case DecodedBitStreamParser$2.BEGIN_MACRO_PDF417_CONTROL_BLOCK:\n case DecodedBitStreamParser$2.BEGIN_MACRO_PDF417_OPTIONAL_FIELD:\n case DecodedBitStreamParser$2.MACRO_PDF417_TERMINATOR:\n codeIndex--;\n end = true;\n break;\n }\n }\n if ((count % DecodedBitStreamParser$2.MAX_NUMERIC_CODEWORDS === 0 || code === DecodedBitStreamParser$2.NUMERIC_COMPACTION_MODE_LATCH || end) && count > 0) {\n // Re-invoking Numeric Compaction mode (by using codeword 902\n // while in Numeric Compaction mode) serves to terminate the\n // current Numeric Compaction mode grouping as described in 5.4.4.2,\n // and then to start a new one grouping.\n result.append(DecodedBitStreamParser$2.decodeBase900toBase10(numericCodewords, count));\n count = 0;\n }\n }\n return codeIndex;\n }\n /**\n * Convert a list of Numeric Compacted codewords from Base 900 to Base 10.\n *\n * @param codewords The array of codewords\n * @param count The number of codewords\n * @return The decoded string representing the Numeric data.\n *\n * EXAMPLE\n * Encode the fifteen digit numeric string 000213298174000\n * Prefix the numeric string with a 1 and set the initial value of\n * t = 1 000 213 298 174 000\n * Calculate codeword 0\n * d0 = 1 000 213 298 174 000 mod 900 = 200\n *\n * t = 1 000 213 298 174 000 div 900 = 1 111 348 109 082\n * Calculate codeword 1\n * d1 = 1 111 348 109 082 mod 900 = 282\n *\n * t = 1 111 348 109 082 div 900 = 1 234 831 232\n * Calculate codeword 2\n * d2 = 1 234 831 232 mod 900 = 632\n *\n * t = 1 234 831 232 div 900 = 1 372 034\n * Calculate codeword 3\n * d3 = 1 372 034 mod 900 = 434\n *\n * t = 1 372 034 div 900 = 1 524\n * Calculate codeword 4\n * d4 = 1 524 mod 900 = 624\n *\n * t = 1 524 div 900 = 1\n * Calculate codeword 5\n * d5 = 1 mod 900 = 1\n * t = 1 div 900 = 0\n * Codeword sequence is: 1, 624, 434, 632, 282, 200\n *\n * Decode the above codewords involves\n * 1 x 900 power of 5 + 624 x 900 power of 4 + 434 x 900 power of 3 +\n * 632 x 900 power of 2 + 282 x 900 power of 1 + 200 x 900 power of 0 = 1000213298174000\n *\n * Remove leading 1 => Result is 000213298174000\n *\n * @throws FormatException\n */\n static decodeBase900toBase10(codewords, count) {\n let result = createBigInt(0);\n for (let i /*int*/ = 0; i < count; i++) {\n result += DecodedBitStreamParser$2.EXP900[count - i - 1] * createBigInt(codewords[i]);\n }\n let resultString = result.toString();\n if (resultString.charAt(0) !== '1') {\n throw new FormatException();\n }\n return resultString.substring(1);\n }\n }\n DecodedBitStreamParser$2.TEXT_COMPACTION_MODE_LATCH = 900;\n DecodedBitStreamParser$2.BYTE_COMPACTION_MODE_LATCH = 901;\n DecodedBitStreamParser$2.NUMERIC_COMPACTION_MODE_LATCH = 902;\n DecodedBitStreamParser$2.BYTE_COMPACTION_MODE_LATCH_6 = 924;\n DecodedBitStreamParser$2.ECI_USER_DEFINED = 925;\n DecodedBitStreamParser$2.ECI_GENERAL_PURPOSE = 926;\n DecodedBitStreamParser$2.ECI_CHARSET = 927;\n DecodedBitStreamParser$2.BEGIN_MACRO_PDF417_CONTROL_BLOCK = 928;\n DecodedBitStreamParser$2.BEGIN_MACRO_PDF417_OPTIONAL_FIELD = 923;\n DecodedBitStreamParser$2.MACRO_PDF417_TERMINATOR = 922;\n DecodedBitStreamParser$2.MODE_SHIFT_TO_BYTE_COMPACTION_MODE = 913;\n DecodedBitStreamParser$2.MAX_NUMERIC_CODEWORDS = 15;\n DecodedBitStreamParser$2.MACRO_PDF417_OPTIONAL_FIELD_FILE_NAME = 0;\n DecodedBitStreamParser$2.MACRO_PDF417_OPTIONAL_FIELD_SEGMENT_COUNT = 1;\n DecodedBitStreamParser$2.MACRO_PDF417_OPTIONAL_FIELD_TIME_STAMP = 2;\n DecodedBitStreamParser$2.MACRO_PDF417_OPTIONAL_FIELD_SENDER = 3;\n DecodedBitStreamParser$2.MACRO_PDF417_OPTIONAL_FIELD_ADDRESSEE = 4;\n DecodedBitStreamParser$2.MACRO_PDF417_OPTIONAL_FIELD_FILE_SIZE = 5;\n DecodedBitStreamParser$2.MACRO_PDF417_OPTIONAL_FIELD_CHECKSUM = 6;\n DecodedBitStreamParser$2.PL = 25;\n DecodedBitStreamParser$2.LL = 27;\n DecodedBitStreamParser$2.AS = 27;\n DecodedBitStreamParser$2.ML = 28;\n DecodedBitStreamParser$2.AL = 28;\n DecodedBitStreamParser$2.PS = 29;\n DecodedBitStreamParser$2.PAL = 29;\n DecodedBitStreamParser$2.PUNCT_CHARS = ';<>@[\\\\]_`~!\\r\\t,:\\n-.$/\"|*()?{}\\'';\n DecodedBitStreamParser$2.MIXED_CHARS = '0123456789&\\r\\t,:#-.$/+%*=^';\n /**\n * Table containing values for the exponent of 900.\n * This is used in the numeric compaction decode algorithm.\n */\n DecodedBitStreamParser$2.EXP900 = getBigIntConstructor() ? getEXP900() : [];\n DecodedBitStreamParser$2.NUMBER_OF_SEQUENCE_CODEWORDS = 2;\n\n /*\n * Copyright 2013 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n // import java.util.ArrayList;\n // import java.util.Collection;\n // import java.util.Formatter;\n // import java.util.List;\n /**\n * @author Guenther Grau\n */\n /*public final*/ class PDF417ScanningDecoder {\n constructor() { }\n /**\n * @TODO don't pass in minCodewordWidth and maxCodewordWidth, pass in barcode columns for start and stop pattern\n *\n * columns. That way width can be deducted from the pattern column.\n * This approach also allows to detect more details about the barcode, e.g. if a bar type (white or black) is wider\n * than it should be. This can happen if the scanner used a bad blackpoint.\n *\n * @param BitMatrix\n * @param image\n * @param ResultPoint\n * @param imageTopLeft\n * @param ResultPoint\n * @param imageBottomLeft\n * @param ResultPoint\n * @param imageTopRight\n * @param ResultPoint\n * @param imageBottomRight\n * @param int\n * @param minCodewordWidth\n * @param int\n * @param maxCodewordWidth\n *\n * @throws NotFoundException\n * @throws FormatException\n * @throws ChecksumException\n */\n static decode(image, imageTopLeft, imageBottomLeft, imageTopRight, imageBottomRight, minCodewordWidth, maxCodewordWidth) {\n let boundingBox = new BoundingBox(image, imageTopLeft, imageBottomLeft, imageTopRight, imageBottomRight);\n let leftRowIndicatorColumn = null;\n let rightRowIndicatorColumn = null;\n let detectionResult;\n for (let firstPass /*boolean*/ = true;; firstPass = false) {\n if (imageTopLeft != null) {\n leftRowIndicatorColumn = PDF417ScanningDecoder.getRowIndicatorColumn(image, boundingBox, imageTopLeft, true, minCodewordWidth, maxCodewordWidth);\n }\n if (imageTopRight != null) {\n rightRowIndicatorColumn = PDF417ScanningDecoder.getRowIndicatorColumn(image, boundingBox, imageTopRight, false, minCodewordWidth, maxCodewordWidth);\n }\n detectionResult = PDF417ScanningDecoder.merge(leftRowIndicatorColumn, rightRowIndicatorColumn);\n if (detectionResult == null) {\n throw NotFoundException.getNotFoundInstance();\n }\n let resultBox = detectionResult.getBoundingBox();\n if (firstPass && resultBox != null &&\n (resultBox.getMinY() < boundingBox.getMinY() || resultBox.getMaxY() > boundingBox.getMaxY())) {\n boundingBox = resultBox;\n }\n else {\n break;\n }\n }\n detectionResult.setBoundingBox(boundingBox);\n let maxBarcodeColumn = detectionResult.getBarcodeColumnCount() + 1;\n detectionResult.setDetectionResultColumn(0, leftRowIndicatorColumn);\n detectionResult.setDetectionResultColumn(maxBarcodeColumn, rightRowIndicatorColumn);\n let leftToRight = leftRowIndicatorColumn != null;\n for (let barcodeColumnCount /*int*/ = 1; barcodeColumnCount <= maxBarcodeColumn; barcodeColumnCount++) {\n let barcodeColumn = leftToRight ? barcodeColumnCount : maxBarcodeColumn - barcodeColumnCount;\n if (detectionResult.getDetectionResultColumn(barcodeColumn) !== /* null */ undefined) {\n // This will be the case for the opposite row indicator column, which doesn't need to be decoded again.\n continue;\n }\n let detectionResultColumn;\n if (barcodeColumn === 0 || barcodeColumn === maxBarcodeColumn) {\n detectionResultColumn = new DetectionResultRowIndicatorColumn(boundingBox, barcodeColumn === 0);\n }\n else {\n detectionResultColumn = new DetectionResultColumn(boundingBox);\n }\n detectionResult.setDetectionResultColumn(barcodeColumn, detectionResultColumn);\n let startColumn = -1;\n let previousStartColumn = startColumn;\n // TODO start at a row for which we know the start position, then detect upwards and downwards from there.\n for (let imageRow /*int*/ = boundingBox.getMinY(); imageRow <= boundingBox.getMaxY(); imageRow++) {\n startColumn = PDF417ScanningDecoder.getStartColumn(detectionResult, barcodeColumn, imageRow, leftToRight);\n if (startColumn < 0 || startColumn > boundingBox.getMaxX()) {\n if (previousStartColumn === -1) {\n continue;\n }\n startColumn = previousStartColumn;\n }\n let codeword = PDF417ScanningDecoder.detectCodeword(image, boundingBox.getMinX(), boundingBox.getMaxX(), leftToRight, startColumn, imageRow, minCodewordWidth, maxCodewordWidth);\n if (codeword != null) {\n detectionResultColumn.setCodeword(imageRow, codeword);\n previousStartColumn = startColumn;\n minCodewordWidth = Math.min(minCodewordWidth, codeword.getWidth());\n maxCodewordWidth = Math.max(maxCodewordWidth, codeword.getWidth());\n }\n }\n }\n return PDF417ScanningDecoder.createDecoderResult(detectionResult);\n }\n /**\n *\n * @param leftRowIndicatorColumn\n * @param rightRowIndicatorColumn\n *\n * @throws NotFoundException\n */\n static merge(leftRowIndicatorColumn, rightRowIndicatorColumn) {\n if (leftRowIndicatorColumn == null && rightRowIndicatorColumn == null) {\n return null;\n }\n let barcodeMetadata = PDF417ScanningDecoder.getBarcodeMetadata(leftRowIndicatorColumn, rightRowIndicatorColumn);\n if (barcodeMetadata == null) {\n return null;\n }\n let boundingBox = BoundingBox.merge(PDF417ScanningDecoder.adjustBoundingBox(leftRowIndicatorColumn), PDF417ScanningDecoder.adjustBoundingBox(rightRowIndicatorColumn));\n return new DetectionResult(barcodeMetadata, boundingBox);\n }\n /**\n *\n * @param rowIndicatorColumn\n *\n * @throws NotFoundException\n */\n static adjustBoundingBox(rowIndicatorColumn) {\n if (rowIndicatorColumn == null) {\n return null;\n }\n let rowHeights = rowIndicatorColumn.getRowHeights();\n if (rowHeights == null) {\n return null;\n }\n let maxRowHeight = PDF417ScanningDecoder.getMax(rowHeights);\n let missingStartRows = 0;\n for (let rowHeight /*int*/ of rowHeights) {\n missingStartRows += maxRowHeight - rowHeight;\n if (rowHeight > 0) {\n break;\n }\n }\n let codewords = rowIndicatorColumn.getCodewords();\n for (let row /*int*/ = 0; missingStartRows > 0 && codewords[row] == null; row++) {\n missingStartRows--;\n }\n let missingEndRows = 0;\n for (let row /*int*/ = rowHeights.length - 1; row >= 0; row--) {\n missingEndRows += maxRowHeight - rowHeights[row];\n if (rowHeights[row] > 0) {\n break;\n }\n }\n for (let row /*int*/ = codewords.length - 1; missingEndRows > 0 && codewords[row] == null; row--) {\n missingEndRows--;\n }\n return rowIndicatorColumn.getBoundingBox().addMissingRows(missingStartRows, missingEndRows, rowIndicatorColumn.isLeft());\n }\n static getMax(values) {\n let maxValue = -1;\n for (let value /*int*/ of values) {\n maxValue = Math.max(maxValue, value);\n }\n return maxValue;\n }\n static getBarcodeMetadata(leftRowIndicatorColumn, rightRowIndicatorColumn) {\n let leftBarcodeMetadata;\n if (leftRowIndicatorColumn == null ||\n (leftBarcodeMetadata = leftRowIndicatorColumn.getBarcodeMetadata()) == null) {\n return rightRowIndicatorColumn == null ? null : rightRowIndicatorColumn.getBarcodeMetadata();\n }\n let rightBarcodeMetadata;\n if (rightRowIndicatorColumn == null ||\n (rightBarcodeMetadata = rightRowIndicatorColumn.getBarcodeMetadata()) == null) {\n return leftBarcodeMetadata;\n }\n if (leftBarcodeMetadata.getColumnCount() !== rightBarcodeMetadata.getColumnCount() &&\n leftBarcodeMetadata.getErrorCorrectionLevel() !== rightBarcodeMetadata.getErrorCorrectionLevel() &&\n leftBarcodeMetadata.getRowCount() !== rightBarcodeMetadata.getRowCount()) {\n return null;\n }\n return leftBarcodeMetadata;\n }\n static getRowIndicatorColumn(image, boundingBox, startPoint, leftToRight, minCodewordWidth, maxCodewordWidth) {\n let rowIndicatorColumn = new DetectionResultRowIndicatorColumn(boundingBox, leftToRight);\n for (let i /*int*/ = 0; i < 2; i++) {\n let increment = i === 0 ? 1 : -1;\n let startColumn = Math.trunc(Math.trunc(startPoint.getX()));\n for (let imageRow /*int*/ = Math.trunc(Math.trunc(startPoint.getY())); imageRow <= boundingBox.getMaxY() &&\n imageRow >= boundingBox.getMinY(); imageRow += increment) {\n let codeword = PDF417ScanningDecoder.detectCodeword(image, 0, image.getWidth(), leftToRight, startColumn, imageRow, minCodewordWidth, maxCodewordWidth);\n if (codeword != null) {\n rowIndicatorColumn.setCodeword(imageRow, codeword);\n if (leftToRight) {\n startColumn = codeword.getStartX();\n }\n else {\n startColumn = codeword.getEndX();\n }\n }\n }\n }\n return rowIndicatorColumn;\n }\n /**\n *\n * @param detectionResult\n * @param BarcodeValue\n * @param param2\n * @param param3\n * @param barcodeMatrix\n *\n * @throws NotFoundException\n */\n static adjustCodewordCount(detectionResult, barcodeMatrix) {\n let barcodeMatrix01 = barcodeMatrix[0][1];\n let numberOfCodewords = barcodeMatrix01.getValue();\n let calculatedNumberOfCodewords = detectionResult.getBarcodeColumnCount() *\n detectionResult.getBarcodeRowCount() -\n PDF417ScanningDecoder.getNumberOfECCodeWords(detectionResult.getBarcodeECLevel());\n if (numberOfCodewords.length === 0) {\n if (calculatedNumberOfCodewords < 1 || calculatedNumberOfCodewords > PDF417Common.MAX_CODEWORDS_IN_BARCODE) {\n throw NotFoundException.getNotFoundInstance();\n }\n barcodeMatrix01.setValue(calculatedNumberOfCodewords);\n }\n else if (numberOfCodewords[0] !== calculatedNumberOfCodewords) {\n // The calculated one is more reliable as it is derived from the row indicator columns\n barcodeMatrix01.setValue(calculatedNumberOfCodewords);\n }\n }\n /**\n *\n * @param detectionResult\n *\n * @throws FormatException\n * @throws ChecksumException\n * @throws NotFoundException\n */\n static createDecoderResult(detectionResult) {\n let barcodeMatrix = PDF417ScanningDecoder.createBarcodeMatrix(detectionResult);\n PDF417ScanningDecoder.adjustCodewordCount(detectionResult, barcodeMatrix);\n let erasures /*Collection*/ = new Array();\n let codewords = new Int32Array(detectionResult.getBarcodeRowCount() * detectionResult.getBarcodeColumnCount());\n let ambiguousIndexValuesList = /*List*/ [];\n let ambiguousIndexesList = /*Collection*/ new Array();\n for (let row /*int*/ = 0; row < detectionResult.getBarcodeRowCount(); row++) {\n for (let column /*int*/ = 0; column < detectionResult.getBarcodeColumnCount(); column++) {\n let values = barcodeMatrix[row][column + 1].getValue();\n let codewordIndex = row * detectionResult.getBarcodeColumnCount() + column;\n if (values.length === 0) {\n erasures.push(codewordIndex);\n }\n else if (values.length === 1) {\n codewords[codewordIndex] = values[0];\n }\n else {\n ambiguousIndexesList.push(codewordIndex);\n ambiguousIndexValuesList.push(values);\n }\n }\n }\n let ambiguousIndexValues = new Array(ambiguousIndexValuesList.length);\n for (let i /*int*/ = 0; i < ambiguousIndexValues.length; i++) {\n ambiguousIndexValues[i] = ambiguousIndexValuesList[i];\n }\n return PDF417ScanningDecoder.createDecoderResultFromAmbiguousValues(detectionResult.getBarcodeECLevel(), codewords, PDF417Common.toIntArray(erasures), PDF417Common.toIntArray(ambiguousIndexesList), ambiguousIndexValues);\n }\n /**\n * This method deals with the fact, that the decoding process doesn't always yield a single most likely value. The\n * current error correction implementation doesn't deal with erasures very well, so it's better to provide a value\n * for these ambiguous codewords instead of treating it as an erasure. The problem is that we don't know which of\n * the ambiguous values to choose. We try decode using the first value, and if that fails, we use another of the\n * ambiguous values and try to decode again. This usually only happens on very hard to read and decode barcodes,\n * so decoding the normal barcodes is not affected by this.\n *\n * @param erasureArray contains the indexes of erasures\n * @param ambiguousIndexes array with the indexes that have more than one most likely value\n * @param ambiguousIndexValues two dimensional array that contains the ambiguous values. The first dimension must\n * be the same length as the ambiguousIndexes array\n *\n * @throws FormatException\n * @throws ChecksumException\n */\n static createDecoderResultFromAmbiguousValues(ecLevel, codewords, erasureArray, ambiguousIndexes, ambiguousIndexValues) {\n let ambiguousIndexCount = new Int32Array(ambiguousIndexes.length);\n let tries = 100;\n while (tries-- > 0) {\n for (let i /*int*/ = 0; i < ambiguousIndexCount.length; i++) {\n codewords[ambiguousIndexes[i]] = ambiguousIndexValues[i][ambiguousIndexCount[i]];\n }\n try {\n return PDF417ScanningDecoder.decodeCodewords(codewords, ecLevel, erasureArray);\n }\n catch (err) {\n let ignored = err instanceof ChecksumException;\n if (!ignored) {\n throw err;\n }\n }\n if (ambiguousIndexCount.length === 0) {\n throw ChecksumException.getChecksumInstance();\n }\n for (let i /*int*/ = 0; i < ambiguousIndexCount.length; i++) {\n if (ambiguousIndexCount[i] < ambiguousIndexValues[i].length - 1) {\n ambiguousIndexCount[i]++;\n break;\n }\n else {\n ambiguousIndexCount[i] = 0;\n if (i === ambiguousIndexCount.length - 1) {\n throw ChecksumException.getChecksumInstance();\n }\n }\n }\n }\n throw ChecksumException.getChecksumInstance();\n }\n static createBarcodeMatrix(detectionResult) {\n // let barcodeMatrix: BarcodeValue[][] =\n // new BarcodeValue[detectionResult.getBarcodeRowCount()][detectionResult.getBarcodeColumnCount() + 2];\n let barcodeMatrix = Array.from({ length: detectionResult.getBarcodeRowCount() }, () => new Array(detectionResult.getBarcodeColumnCount() + 2));\n for (let row /*int*/ = 0; row < barcodeMatrix.length; row++) {\n for (let column /*int*/ = 0; column < barcodeMatrix[row].length; column++) {\n barcodeMatrix[row][column] = new BarcodeValue();\n }\n }\n let column = 0;\n for (let detectionResultColumn /*DetectionResultColumn*/ of detectionResult.getDetectionResultColumns()) {\n if (detectionResultColumn != null) {\n for (let codeword /*Codeword*/ of detectionResultColumn.getCodewords()) {\n if (codeword != null) {\n let rowNumber = codeword.getRowNumber();\n if (rowNumber >= 0) {\n if (rowNumber >= barcodeMatrix.length) {\n // We have more rows than the barcode metadata allows for, ignore them.\n continue;\n }\n barcodeMatrix[rowNumber][column].setValue(codeword.getValue());\n }\n }\n }\n }\n column++;\n }\n return barcodeMatrix;\n }\n static isValidBarcodeColumn(detectionResult, barcodeColumn) {\n return barcodeColumn >= 0 && barcodeColumn <= detectionResult.getBarcodeColumnCount() + 1;\n }\n static getStartColumn(detectionResult, barcodeColumn, imageRow, leftToRight) {\n let offset = leftToRight ? 1 : -1;\n let codeword = null;\n if (PDF417ScanningDecoder.isValidBarcodeColumn(detectionResult, barcodeColumn - offset)) {\n codeword = detectionResult.getDetectionResultColumn(barcodeColumn - offset).getCodeword(imageRow);\n }\n if (codeword != null) {\n return leftToRight ? codeword.getEndX() : codeword.getStartX();\n }\n codeword = detectionResult.getDetectionResultColumn(barcodeColumn).getCodewordNearby(imageRow);\n if (codeword != null) {\n return leftToRight ? codeword.getStartX() : codeword.getEndX();\n }\n if (PDF417ScanningDecoder.isValidBarcodeColumn(detectionResult, barcodeColumn - offset)) {\n codeword = detectionResult.getDetectionResultColumn(barcodeColumn - offset).getCodewordNearby(imageRow);\n }\n if (codeword != null) {\n return leftToRight ? codeword.getEndX() : codeword.getStartX();\n }\n let skippedColumns = 0;\n while (PDF417ScanningDecoder.isValidBarcodeColumn(detectionResult, barcodeColumn - offset)) {\n barcodeColumn -= offset;\n for (let previousRowCodeword /*Codeword*/ of detectionResult.getDetectionResultColumn(barcodeColumn).getCodewords()) {\n if (previousRowCodeword != null) {\n return (leftToRight ? previousRowCodeword.getEndX() : previousRowCodeword.getStartX()) +\n offset *\n skippedColumns *\n (previousRowCodeword.getEndX() - previousRowCodeword.getStartX());\n }\n }\n skippedColumns++;\n }\n return leftToRight ? detectionResult.getBoundingBox().getMinX() : detectionResult.getBoundingBox().getMaxX();\n }\n static detectCodeword(image, minColumn, maxColumn, leftToRight, startColumn, imageRow, minCodewordWidth, maxCodewordWidth) {\n startColumn = PDF417ScanningDecoder.adjustCodewordStartColumn(image, minColumn, maxColumn, leftToRight, startColumn, imageRow);\n // we usually know fairly exact now how long a codeword is. We should provide minimum and maximum expected length\n // and try to adjust the read pixels, e.g. remove single pixel errors or try to cut off exceeding pixels.\n // min and maxCodewordWidth should not be used as they are calculated for the whole barcode an can be inaccurate\n // for the current position\n let moduleBitCount = PDF417ScanningDecoder.getModuleBitCount(image, minColumn, maxColumn, leftToRight, startColumn, imageRow);\n if (moduleBitCount == null) {\n return null;\n }\n let endColumn;\n let codewordBitCount = MathUtils.sum(moduleBitCount);\n if (leftToRight) {\n endColumn = startColumn + codewordBitCount;\n }\n else {\n for (let i /*int*/ = 0; i < moduleBitCount.length / 2; i++) {\n let tmpCount = moduleBitCount[i];\n moduleBitCount[i] = moduleBitCount[moduleBitCount.length - 1 - i];\n moduleBitCount[moduleBitCount.length - 1 - i] = tmpCount;\n }\n endColumn = startColumn;\n startColumn = endColumn - codewordBitCount;\n }\n // TODO implement check for width and correction of black and white bars\n // use start (and maybe stop pattern) to determine if black bars are wider than white bars. If so, adjust.\n // should probably done only for codewords with a lot more than 17 bits.\n // The following fixes 10-1.png, which has wide black bars and small white bars\n // for (let i /*int*/ = 0; i < moduleBitCount.length; i++) {\n // if (i % 2 === 0) {\n // moduleBitCount[i]--;\n // } else {\n // moduleBitCount[i]++;\n // }\n // }\n // We could also use the width of surrounding codewords for more accurate results, but this seems\n // sufficient for now\n if (!PDF417ScanningDecoder.checkCodewordSkew(codewordBitCount, minCodewordWidth, maxCodewordWidth)) {\n // We could try to use the startX and endX position of the codeword in the same column in the previous row,\n // create the bit count from it and normalize it to 8. This would help with single pixel errors.\n return null;\n }\n let decodedValue = PDF417CodewordDecoder.getDecodedValue(moduleBitCount);\n let codeword = PDF417Common.getCodeword(decodedValue);\n if (codeword === -1) {\n return null;\n }\n return new Codeword(startColumn, endColumn, PDF417ScanningDecoder.getCodewordBucketNumber(decodedValue), codeword);\n }\n static getModuleBitCount(image, minColumn, maxColumn, leftToRight, startColumn, imageRow) {\n let imageColumn = startColumn;\n let moduleBitCount = new Int32Array(8);\n let moduleNumber = 0;\n let increment = leftToRight ? 1 : -1;\n let previousPixelValue = leftToRight;\n while ((leftToRight ? imageColumn < maxColumn : imageColumn >= minColumn) &&\n moduleNumber < moduleBitCount.length) {\n if (image.get(imageColumn, imageRow) === previousPixelValue) {\n moduleBitCount[moduleNumber]++;\n imageColumn += increment;\n }\n else {\n moduleNumber++;\n previousPixelValue = !previousPixelValue;\n }\n }\n if (moduleNumber === moduleBitCount.length ||\n ((imageColumn === (leftToRight ? maxColumn : minColumn)) &&\n moduleNumber === moduleBitCount.length - 1)) {\n return moduleBitCount;\n }\n return null;\n }\n static getNumberOfECCodeWords(barcodeECLevel) {\n return 2 << barcodeECLevel;\n }\n static adjustCodewordStartColumn(image, minColumn, maxColumn, leftToRight, codewordStartColumn, imageRow) {\n let correctedStartColumn = codewordStartColumn;\n let increment = leftToRight ? -1 : 1;\n // there should be no black pixels before the start column. If there are, then we need to start earlier.\n for (let i /*int*/ = 0; i < 2; i++) {\n while ((leftToRight ? correctedStartColumn >= minColumn : correctedStartColumn < maxColumn) &&\n leftToRight === image.get(correctedStartColumn, imageRow)) {\n if (Math.abs(codewordStartColumn - correctedStartColumn) > PDF417ScanningDecoder.CODEWORD_SKEW_SIZE) {\n return codewordStartColumn;\n }\n correctedStartColumn += increment;\n }\n increment = -increment;\n leftToRight = !leftToRight;\n }\n return correctedStartColumn;\n }\n static checkCodewordSkew(codewordSize, minCodewordWidth, maxCodewordWidth) {\n return minCodewordWidth - PDF417ScanningDecoder.CODEWORD_SKEW_SIZE <= codewordSize &&\n codewordSize <= maxCodewordWidth + PDF417ScanningDecoder.CODEWORD_SKEW_SIZE;\n }\n /**\n * @throws FormatException,\n * @throws ChecksumException\n */\n static decodeCodewords(codewords, ecLevel, erasures) {\n if (codewords.length === 0) {\n throw FormatException.getFormatInstance();\n }\n let numECCodewords = 1 << (ecLevel + 1);\n let correctedErrorsCount = PDF417ScanningDecoder.correctErrors(codewords, erasures, numECCodewords);\n PDF417ScanningDecoder.verifyCodewordCount(codewords, numECCodewords);\n // Decode the codewords\n let decoderResult = DecodedBitStreamParser$2.decode(codewords, '' + ecLevel);\n decoderResult.setErrorsCorrected(correctedErrorsCount);\n decoderResult.setErasures(erasures.length);\n return decoderResult;\n }\n /**\n *

Given data and error-correction codewords received, possibly corrupted by errors, attempts to\n * correct the errors in-place.

\n *\n * @param codewords data and error correction codewords\n * @param erasures positions of any known erasures\n * @param numECCodewords number of error correction codewords that are available in codewords\n * @throws ChecksumException if error correction fails\n */\n static correctErrors(codewords, erasures, numECCodewords) {\n if (erasures != null &&\n erasures.length > numECCodewords / 2 + PDF417ScanningDecoder.MAX_ERRORS ||\n numECCodewords < 0 ||\n numECCodewords > PDF417ScanningDecoder.MAX_EC_CODEWORDS) {\n // Too many errors or EC Codewords is corrupted\n throw ChecksumException.getChecksumInstance();\n }\n return PDF417ScanningDecoder.errorCorrection.decode(codewords, numECCodewords, erasures);\n }\n /**\n * Verify that all is OK with the codeword array.\n * @throws FormatException\n */\n static verifyCodewordCount(codewords, numECCodewords) {\n if (codewords.length < 4) {\n // Codeword array size should be at least 4 allowing for\n // Count CW, At least one Data CW, Error Correction CW, Error Correction CW\n throw FormatException.getFormatInstance();\n }\n // The first codeword, the Symbol Length Descriptor, shall always encode the total number of data\n // codewords in the symbol, including the Symbol Length Descriptor itself, data codewords and pad\n // codewords, but excluding the number of error correction codewords.\n let numberOfCodewords = codewords[0];\n if (numberOfCodewords > codewords.length) {\n throw FormatException.getFormatInstance();\n }\n if (numberOfCodewords === 0) {\n // Reset to the length of the array - 8 (Allow for at least level 3 Error Correction (8 Error Codewords)\n if (numECCodewords < codewords.length) {\n codewords[0] = codewords.length - numECCodewords;\n }\n else {\n throw FormatException.getFormatInstance();\n }\n }\n }\n static getBitCountForCodeword(codeword) {\n let result = new Int32Array(8);\n let previousValue = 0;\n let i = result.length - 1;\n while (true) {\n if ((codeword & 0x1) !== previousValue) {\n previousValue = codeword & 0x1;\n i--;\n if (i < 0) {\n break;\n }\n }\n result[i]++;\n codeword >>= 1;\n }\n return result;\n }\n static getCodewordBucketNumber(codeword) {\n if (codeword instanceof Int32Array) {\n return this.getCodewordBucketNumber_Int32Array(codeword);\n }\n return this.getCodewordBucketNumber_number(codeword);\n }\n static getCodewordBucketNumber_number(codeword) {\n return PDF417ScanningDecoder.getCodewordBucketNumber(PDF417ScanningDecoder.getBitCountForCodeword(codeword));\n }\n static getCodewordBucketNumber_Int32Array(moduleBitCount) {\n return (moduleBitCount[0] - moduleBitCount[2] + moduleBitCount[4] - moduleBitCount[6] + 9) % 9;\n }\n static toString(barcodeMatrix) {\n let formatter = new Formatter();\n // try (let formatter = new Formatter()) {\n for (let row /*int*/ = 0; row < barcodeMatrix.length; row++) {\n formatter.format('Row %2d: ', row);\n for (let column /*int*/ = 0; column < barcodeMatrix[row].length; column++) {\n let barcodeValue = barcodeMatrix[row][column];\n if (barcodeValue.getValue().length === 0) {\n formatter.format(' ', null);\n }\n else {\n formatter.format('%4d(%2d)', barcodeValue.getValue()[0], barcodeValue.getConfidence(barcodeValue.getValue()[0]));\n }\n }\n formatter.format('%n');\n }\n return formatter.toString();\n // }\n }\n }\n /*final*/ PDF417ScanningDecoder.CODEWORD_SKEW_SIZE = 2;\n /*final*/ PDF417ScanningDecoder.MAX_ERRORS = 3;\n /*final*/ PDF417ScanningDecoder.MAX_EC_CODEWORDS = 512;\n /*final*/ PDF417ScanningDecoder.errorCorrection = new ErrorCorrection();\n\n /*\n * Copyright 2009 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n // import java.util.ArrayList;\n // import java.util.List;\n // import java.util.Map;\n /**\n * This implementation can detect and decode PDF417 codes in an image.\n *\n * @author Guenther Grau\n */\n /*public final*/ class PDF417Reader {\n // private static /*final Result[]*/ EMPTY_RESULT_ARRAY: Result[] = new Result([0]);\n /**\n * Locates and decodes a PDF417 code in an image.\n *\n * @return a String representing the content encoded by the PDF417 code\n * @throws NotFoundException if a PDF417 code cannot be found,\n * @throws FormatException if a PDF417 cannot be decoded\n * @throws ChecksumException\n */\n // @Override\n decode(image, hints = null) {\n let result = PDF417Reader.decode(image, hints, false);\n if (result == null || result.length === 0 || result[0] == null) {\n throw NotFoundException.getNotFoundInstance();\n }\n return result[0];\n }\n /**\n *\n * @param BinaryBitmap\n * @param image\n * @throws NotFoundException\n */\n // @Override\n decodeMultiple(image, hints = null) {\n try {\n return PDF417Reader.decode(image, hints, true);\n }\n catch (ignored) {\n if (ignored instanceof FormatException || ignored instanceof ChecksumException) {\n throw NotFoundException.getNotFoundInstance();\n }\n throw ignored;\n }\n }\n /**\n *\n * @param image\n * @param hints\n * @param multiple\n *\n * @throws NotFoundException\n * @throws FormatException\u00DF\n * @throws ChecksumException\n */\n static decode(image, hints, multiple) {\n const results = new Array();\n const detectorResult = Detector$3.detectMultiple(image, hints, multiple);\n for (const points of detectorResult.getPoints()) {\n const decoderResult = PDF417ScanningDecoder.decode(detectorResult.getBits(), points[4], points[5], points[6], points[7], PDF417Reader.getMinCodewordWidth(points), PDF417Reader.getMaxCodewordWidth(points));\n const result = new Result(decoderResult.getText(), decoderResult.getRawBytes(), undefined, points, BarcodeFormat$1.PDF_417);\n result.putMetadata(ResultMetadataType$1.ERROR_CORRECTION_LEVEL, decoderResult.getECLevel());\n const pdf417ResultMetadata = decoderResult.getOther();\n if (pdf417ResultMetadata != null) {\n result.putMetadata(ResultMetadataType$1.PDF417_EXTRA_METADATA, pdf417ResultMetadata);\n }\n results.push(result);\n }\n return results.map(x => x);\n }\n static getMaxWidth(p1, p2) {\n if (p1 == null || p2 == null) {\n return 0;\n }\n return Math.trunc(Math.abs(p1.getX() - p2.getX()));\n }\n static getMinWidth(p1, p2) {\n if (p1 == null || p2 == null) {\n return Integer.MAX_VALUE;\n }\n return Math.trunc(Math.abs(p1.getX() - p2.getX()));\n }\n static getMaxCodewordWidth(p) {\n return Math.floor(Math.max(Math.max(PDF417Reader.getMaxWidth(p[0], p[4]), PDF417Reader.getMaxWidth(p[6], p[2]) * PDF417Common.MODULES_IN_CODEWORD /\n PDF417Common.MODULES_IN_STOP_PATTERN), Math.max(PDF417Reader.getMaxWidth(p[1], p[5]), PDF417Reader.getMaxWidth(p[7], p[3]) * PDF417Common.MODULES_IN_CODEWORD /\n PDF417Common.MODULES_IN_STOP_PATTERN)));\n }\n static getMinCodewordWidth(p) {\n return Math.floor(Math.min(Math.min(PDF417Reader.getMinWidth(p[0], p[4]), PDF417Reader.getMinWidth(p[6], p[2]) * PDF417Common.MODULES_IN_CODEWORD /\n PDF417Common.MODULES_IN_STOP_PATTERN), Math.min(PDF417Reader.getMinWidth(p[1], p[5]), PDF417Reader.getMinWidth(p[7], p[3]) * PDF417Common.MODULES_IN_CODEWORD /\n PDF417Common.MODULES_IN_STOP_PATTERN)));\n }\n // @Override\n reset() {\n // nothing needs to be reset\n }\n }\n\n /**\n * Custom Error class of type Exception.\n */\n class ReaderException extends Exception {\n }\n ReaderException.kind = 'ReaderException';\n\n /*\n * Copyright 2009 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n /*namespace com.google.zxing {*/\n /**\n * MultiFormatReader is a convenience class and the main entry point into the library for most uses.\n * By default it attempts to decode all barcode formats that the library supports. Optionally, you\n * can provide a hints object to request different behavior, for example only decoding QR codes.\n *\n * @author Sean Owen\n * @author dswitkin@google.com (Daniel Switkin)\n */\n class MultiFormatReader {\n /**\n * Creates an instance of this class\n * \n * @param {Boolean} verbose if 'true' logs will be dumped to console, otherwise hidden.\n * @param hints The hints to use, clearing the previous state.\n */\n constructor(verbose, hints) {\n this.verbose = (verbose === true);\n if (hints) {\n this.setHints(hints);\n }\n }\n /**\n * This version of decode honors the intent of Reader.decode(BinaryBitmap) in that it\n * passes null as a hint to the decoders. However, that makes it inefficient to call repeatedly.\n * Use setHints() followed by decodeWithState() for continuous scan applications.\n *\n * @param image The pixel data to decode\n * @return The contents of the image\n *\n * @throws NotFoundException Any errors which occurred\n */\n /*@Override*/\n // public decode(image: BinaryBitmap): Result {\n // setHints(null)\n // return decodeInternal(image)\n // }\n /**\n * Decode an image using the hints provided. Does not honor existing state.\n *\n * @param image The pixel data to decode\n * @param hints The hints to use, clearing the previous state.\n * @return The contents of the image\n *\n * @throws NotFoundException Any errors which occurred\n */\n /*@Override*/\n decode(image, hints) {\n if (hints) {\n this.setHints(hints);\n }\n return this.decodeInternal(image);\n }\n /**\n * Decode an image using the state set up by calling setHints() previously. Continuous scan\n * clients will get a large speed increase by using this instead of decode().\n *\n * @param image The pixel data to decode\n * @return The contents of the image\n *\n * @throws NotFoundException Any errors which occurred\n */\n decodeWithState(image) {\n // Make sure to set up the default state so we don't crash\n if (this.readers === null || this.readers === undefined) {\n this.setHints(null);\n }\n return this.decodeInternal(image);\n }\n /**\n * This method adds state to the MultiFormatReader. By setting the hints once, subsequent calls\n * to decodeWithState(image) can reuse the same set of readers without reallocating memory. This\n * is important for performance in continuous scan clients.\n *\n * @param hints The set of hints to use for subsequent calls to decode(image)\n */\n setHints(hints) {\n this.hints = hints;\n const tryHarder = !isNullOrUndefined(hints)\n && hints.get(DecodeHintType$1.TRY_HARDER) === true;\n const formats = isNullOrUndefined(hints) ? null : hints.get(DecodeHintType$1.POSSIBLE_FORMATS);\n const readers = new Array();\n if (!isNullOrUndefined(formats)) {\n const addOneDReader = formats.some(f => {\n return (\n f === BarcodeFormat$1.UPC_A ||\n f === BarcodeFormat$1.UPC_E ||\n f === BarcodeFormat$1.EAN_13 ||\n f === BarcodeFormat$1.EAN_8 ||\n f === BarcodeFormat$1.CODABAR ||\n f === BarcodeFormat$1.CODE_39 ||\n f === BarcodeFormat$1.CODE_93 ||\n f === BarcodeFormat$1.CODE_128 ||\n f === BarcodeFormat$1.ITF ||\n f === BarcodeFormat$1.RSS_14 ||\n f === BarcodeFormat$1.RSS_EXPANDED);\n });\n // Put 1D readers upfront in \"normal\" mode\n if (addOneDReader && !tryHarder) {\n readers.push(new MultiFormatOneDReader(hints, this.verbose));\n }\n if (formats.includes(BarcodeFormat$1.QR_CODE)) {\n readers.push(new QRCodeReader());\n }\n if (formats.includes(BarcodeFormat$1.DATA_MATRIX)) {\n readers.push(new DataMatrixReader());\n }\n if (formats.includes(BarcodeFormat$1.AZTEC)) {\n readers.push(new AztecReader());\n }\n if (formats.includes(BarcodeFormat$1.PDF_417)) {\n readers.push(new PDF417Reader());\n }\n // if (formats.includes(BarcodeFormat.MAXICODE)) {\n // readers.push(new MaxiCodeReader())\n // }\n // At end in \"try harder\" mode\n if (addOneDReader && tryHarder) {\n readers.push(new MultiFormatOneDReader(hints, this.verbose));\n }\n }\n if (readers.length === 0) {\n if (!tryHarder) {\n readers.push(new MultiFormatOneDReader(hints, this.verbose));\n }\n readers.push(new QRCodeReader());\n readers.push(new DataMatrixReader());\n readers.push(new AztecReader());\n readers.push(new PDF417Reader());\n // readers.push(new MaxiCodeReader())\n if (tryHarder) {\n readers.push(new MultiFormatOneDReader(hints, this.verbose));\n }\n }\n this.readers = readers; // .toArray(new Reader[readers.size()])\n }\n /*@Override*/\n reset() {\n if (this.readers !== null) {\n for (const reader of this.readers) {\n reader.reset();\n }\n }\n }\n /**\n * @throws NotFoundException\n */\n decodeInternal(image) {\n if (this.readers === null) {\n throw new ReaderException('No readers where selected, nothing can be read.');\n }\n for (const reader of this.readers) {\n // Trying to decode with ${reader} reader.\n try {\n return reader.decode(image, this.hints);\n }\n catch (ex) {\n if (ex instanceof ReaderException) {\n continue;\n }\n // Bad Exception.\n }\n }\n throw new NotFoundException('No MultiFormat Readers were able to detect the code.');\n }\n }\n\n class BrowserMultiFormatReader extends BrowserCodeReader {\n constructor(hints = null, timeBetweenScansMillis = 500) {\n const reader = new MultiFormatReader();\n reader.setHints(hints);\n super(reader, timeBetweenScansMillis);\n }\n /**\n * Overwrite decodeBitmap to call decodeWithState, which will pay\n * attention to the hints set in the constructor function\n */\n decodeBitmap(binaryBitmap) {\n return this.reader.decodeWithState(binaryBitmap);\n }\n }\n\n /**\n * @deprecated Moving to @zxing/browser\n *\n * QR Code reader to use from browser.\n */\n class BrowserPDF417Reader extends BrowserCodeReader {\n /**\n * Creates an instance of BrowserPDF417Reader.\n * @param {number} [timeBetweenScansMillis=500] the time delay between subsequent decode tries\n */\n constructor(timeBetweenScansMillis = 500) {\n super(new PDF417Reader(), timeBetweenScansMillis);\n }\n }\n\n /**\n * @deprecated Moving to @zxing/browser\n *\n * QR Code reader to use from browser.\n */\n class BrowserQRCodeReader extends BrowserCodeReader {\n /**\n * Creates an instance of BrowserQRCodeReader.\n * @param {number} [timeBetweenScansMillis=500] the time delay between subsequent decode tries\n */\n constructor(timeBetweenScansMillis = 500) {\n super(new QRCodeReader(), timeBetweenScansMillis);\n }\n }\n\n /*\n * Copyright 2009 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n /*namespace com.google.zxing {*/\n /**\n * These are a set of hints that you may pass to Writers to specify their behavior.\n *\n * @author dswitkin@google.com (Daniel Switkin)\n */\n var EncodeHintType;\n (function (EncodeHintType) {\n /**\n * Specifies what degree of error correction to use, for example in QR Codes.\n * Type depends on the encoder. For example for QR codes it's type\n * {@link com.google.zxing.qrcode.decoder.ErrorCorrectionLevel ErrorCorrectionLevel}.\n * For Aztec it is of type {@link Integer}, representing the minimal percentage of error correction words.\n * For PDF417 it is of type {@link Integer}, valid values being 0 to 8.\n * In all cases, it can also be a {@link String} representation of the desired value as well.\n * Note: an Aztec symbol should have a minimum of 25% EC words.\n */\n EncodeHintType[EncodeHintType[\"ERROR_CORRECTION\"] = 0] = \"ERROR_CORRECTION\";\n /**\n * Specifies what character encoding to use where applicable (type {@link String})\n */\n EncodeHintType[EncodeHintType[\"CHARACTER_SET\"] = 1] = \"CHARACTER_SET\";\n /**\n * Specifies the matrix shape for Data Matrix (type {@link com.google.zxing.datamatrix.encoder.SymbolShapeHint})\n */\n EncodeHintType[EncodeHintType[\"DATA_MATRIX_SHAPE\"] = 2] = \"DATA_MATRIX_SHAPE\";\n /**\n * Specifies a minimum barcode size (type {@link Dimension}). Only applicable to Data Matrix now.\n *\n * @deprecated use width/height params in\n * {@link com.google.zxing.datamatrix.DataMatrixWriter#encode(String, BarcodeFormat, int, int)}\n */\n /*@Deprecated*/\n EncodeHintType[EncodeHintType[\"MIN_SIZE\"] = 3] = \"MIN_SIZE\";\n /**\n * Specifies a maximum barcode size (type {@link Dimension}). Only applicable to Data Matrix now.\n *\n * @deprecated without replacement\n */\n /*@Deprecated*/\n EncodeHintType[EncodeHintType[\"MAX_SIZE\"] = 4] = \"MAX_SIZE\";\n /**\n * Specifies margin, in pixels, to use when generating the barcode. The meaning can vary\n * by format; for example it controls margin before and after the barcode horizontally for\n * most 1D formats. (Type {@link Integer}, or {@link String} representation of the integer value).\n */\n EncodeHintType[EncodeHintType[\"MARGIN\"] = 5] = \"MARGIN\";\n /**\n * Specifies whether to use compact mode for PDF417 (type {@link Boolean}, or \"true\" or \"false\"\n * {@link String} value).\n */\n EncodeHintType[EncodeHintType[\"PDF417_COMPACT\"] = 6] = \"PDF417_COMPACT\";\n /**\n * Specifies what compaction mode to use for PDF417 (type\n * {@link com.google.zxing.pdf417.encoder.Compaction Compaction} or {@link String} value of one of its\n * enum values).\n */\n EncodeHintType[EncodeHintType[\"PDF417_COMPACTION\"] = 7] = \"PDF417_COMPACTION\";\n /**\n * Specifies the minimum and maximum number of rows and columns for PDF417 (type\n * {@link com.google.zxing.pdf417.encoder.Dimensions Dimensions}).\n */\n EncodeHintType[EncodeHintType[\"PDF417_DIMENSIONS\"] = 8] = \"PDF417_DIMENSIONS\";\n /**\n * Specifies the required number of layers for an Aztec code.\n * A negative number (-1, -2, -3, -4) specifies a compact Aztec code.\n * 0 indicates to use the minimum number of layers (the default).\n * A positive number (1, 2, .. 32) specifies a normal (non-compact) Aztec code.\n * (Type {@link Integer}, or {@link String} representation of the integer value).\n */\n EncodeHintType[EncodeHintType[\"AZTEC_LAYERS\"] = 9] = \"AZTEC_LAYERS\";\n /**\n * Specifies the exact version of QR code to be encoded.\n * (Type {@link Integer}, or {@link String} representation of the integer value).\n */\n EncodeHintType[EncodeHintType[\"QR_VERSION\"] = 10] = \"QR_VERSION\";\n })(EncodeHintType || (EncodeHintType = {}));\n var EncodeHintType$1 = EncodeHintType;\n\n /**\n *

Implements Reed-Solomon encoding, as the name implies.

\n *\n * @author Sean Owen\n * @author William Rucklidge\n */\n class ReedSolomonEncoder {\n /**\n * A reed solomon error-correcting encoding constructor is created by\n * passing as Galois Field with of size equal to the number of code\n * words (symbols) in the alphabet (the number of values in each\n * element of arrays that are encoded/decoded).\n * @param field A galois field with a number of elements equal to the size\n * of the alphabet of symbols to encode.\n */\n constructor(field) {\n this.field = field;\n this.cachedGenerators = [];\n this.cachedGenerators.push(new GenericGFPoly(field, Int32Array.from([1])));\n }\n buildGenerator(degree /*int*/) {\n const cachedGenerators = this.cachedGenerators;\n if (degree >= cachedGenerators.length) {\n let lastGenerator = cachedGenerators[cachedGenerators.length - 1];\n const field = this.field;\n for (let d = cachedGenerators.length; d <= degree; d++) {\n const nextGenerator = lastGenerator.multiply(new GenericGFPoly(field, Int32Array.from([1, field.exp(d - 1 + field.getGeneratorBase())])));\n cachedGenerators.push(nextGenerator);\n lastGenerator = nextGenerator;\n }\n }\n return cachedGenerators[degree];\n }\n /**\n *

Encode a sequence of code words (symbols) using Reed-Solomon to allow decoders\n * to detect and correct errors that may have been introduced when the resulting\n * data is stored or transmitted.

\n *\n * @param toEncode array used for both and output. Caller initializes the array with\n * the code words (symbols) to be encoded followed by empty elements allocated to make\n * space for error-correction code words in the encoded output. The array contains\n * the encdoded output when encode returns. Code words are encoded as numbers from\n * 0 to n-1, where n is the number of possible code words (symbols), as determined\n * by the size of the Galois Field passed in the constructor of this object.\n * @param ecBytes the number of elements reserved in the array (first parameter)\n * to store error-correction code words. Thus, the number of code words (symbols)\n * to encode in the first parameter is thus toEncode.length - ecBytes.\n * Note, the use of \"bytes\" in the name of this parameter is misleading, as there may\n * be more or fewer than 256 symbols being encoded, as determined by the number of\n * elements in the Galois Field passed as a constructor to this object.\n * @throws IllegalArgumentException thrown in response to validation errros.\n */\n encode(toEncode, ecBytes /*int*/) {\n if (ecBytes === 0) {\n throw new IllegalArgumentException('No error correction bytes');\n }\n const dataBytes = toEncode.length - ecBytes;\n if (dataBytes <= 0) {\n throw new IllegalArgumentException('No data bytes provided');\n }\n const generator = this.buildGenerator(ecBytes);\n const infoCoefficients = new Int32Array(dataBytes);\n System.arraycopy(toEncode, 0, infoCoefficients, 0, dataBytes);\n let info = new GenericGFPoly(this.field, infoCoefficients);\n info = info.multiplyByMonomial(ecBytes, 1);\n const remainder = info.divide(generator)[1];\n const coefficients = remainder.getCoefficients();\n const numZeroCoefficients = ecBytes - coefficients.length;\n for (let i = 0; i < numZeroCoefficients; i++) {\n toEncode[dataBytes + i] = 0;\n }\n System.arraycopy(coefficients, 0, toEncode, dataBytes + numZeroCoefficients, coefficients.length);\n }\n }\n\n /**\n * @author Satoru Takabayashi\n * @author Daniel Switkin\n * @author Sean Owen\n */\n class MaskUtil {\n constructor() {\n // do nothing\n }\n /**\n * Apply mask penalty rule 1 and return the penalty. Find repetitive cells with the same color and\n * give penalty to them. Example: 00000 or 11111.\n */\n static applyMaskPenaltyRule1(matrix) {\n return MaskUtil.applyMaskPenaltyRule1Internal(matrix, true) + MaskUtil.applyMaskPenaltyRule1Internal(matrix, false);\n }\n /**\n * Apply mask penalty rule 2 and return the penalty. Find 2x2 blocks with the same color and give\n * penalty to them. This is actually equivalent to the spec's rule, which is to find MxN blocks and give a\n * penalty proportional to (M-1)x(N-1), because this is the number of 2x2 blocks inside such a block.\n */\n static applyMaskPenaltyRule2(matrix) {\n let penalty = 0;\n const array = matrix.getArray();\n const width = matrix.getWidth();\n const height = matrix.getHeight();\n for (let y = 0; y < height - 1; y++) {\n const arrayY = array[y];\n for (let x = 0; x < width - 1; x++) {\n const value = arrayY[x];\n if (value === arrayY[x + 1] && value === array[y + 1][x] && value === array[y + 1][x + 1]) {\n penalty++;\n }\n }\n }\n return MaskUtil.N2 * penalty;\n }\n /**\n * Apply mask penalty rule 3 and return the penalty. Find consecutive runs of 1:1:3:1:1:4\n * starting with black, or 4:1:1:3:1:1 starting with white, and give penalty to them. If we\n * find patterns like 000010111010000, we give penalty once.\n */\n static applyMaskPenaltyRule3(matrix) {\n let numPenalties = 0;\n const array = matrix.getArray();\n const width = matrix.getWidth();\n const height = matrix.getHeight();\n for (let y = 0; y < height; y++) {\n for (let x = 0; x < width; x++) {\n const arrayY = array[y]; // We can at least optimize this access\n if (x + 6 < width &&\n arrayY[x] === 1 &&\n arrayY[x + 1] === 0 &&\n arrayY[x + 2] === 1 &&\n arrayY[x + 3] === 1 &&\n arrayY[x + 4] === 1 &&\n arrayY[x + 5] === 0 &&\n arrayY[x + 6] === 1 &&\n (MaskUtil.isWhiteHorizontal(arrayY, x - 4, x) || MaskUtil.isWhiteHorizontal(arrayY, x + 7, x + 11))) {\n numPenalties++;\n }\n if (y + 6 < height &&\n array[y][x] === 1 &&\n array[y + 1][x] === 0 &&\n array[y + 2][x] === 1 &&\n array[y + 3][x] === 1 &&\n array[y + 4][x] === 1 &&\n array[y + 5][x] === 0 &&\n array[y + 6][x] === 1 &&\n (MaskUtil.isWhiteVertical(array, x, y - 4, y) || MaskUtil.isWhiteVertical(array, x, y + 7, y + 11))) {\n numPenalties++;\n }\n }\n }\n return numPenalties * MaskUtil.N3;\n }\n static isWhiteHorizontal(rowArray, from /*int*/, to /*int*/) {\n from = Math.max(from, 0);\n to = Math.min(to, rowArray.length);\n for (let i = from; i < to; i++) {\n if (rowArray[i] === 1) {\n return false;\n }\n }\n return true;\n }\n static isWhiteVertical(array, col /*int*/, from /*int*/, to /*int*/) {\n from = Math.max(from, 0);\n to = Math.min(to, array.length);\n for (let i = from; i < to; i++) {\n if (array[i][col] === 1) {\n return false;\n }\n }\n return true;\n }\n /**\n * Apply mask penalty rule 4 and return the penalty. Calculate the ratio of dark cells and give\n * penalty if the ratio is far from 50%. It gives 10 penalty for 5% distance.\n */\n static applyMaskPenaltyRule4(matrix) {\n let numDarkCells = 0;\n const array = matrix.getArray();\n const width = matrix.getWidth();\n const height = matrix.getHeight();\n for (let y = 0; y < height; y++) {\n const arrayY = array[y];\n for (let x = 0; x < width; x++) {\n if (arrayY[x] === 1) {\n numDarkCells++;\n }\n }\n }\n const numTotalCells = matrix.getHeight() * matrix.getWidth();\n const fivePercentVariances = Math.floor(Math.abs(numDarkCells * 2 - numTotalCells) * 10 / numTotalCells);\n return fivePercentVariances * MaskUtil.N4;\n }\n /**\n * Return the mask bit for \"getMaskPattern\" at \"x\" and \"y\". See 8.8 of JISX0510:2004 for mask\n * pattern conditions.\n */\n static getDataMaskBit(maskPattern /*int*/, x /*int*/, y /*int*/) {\n let intermediate; /*int*/\n let temp; /*int*/\n switch (maskPattern) {\n case 0:\n intermediate = (y + x) & 0x1;\n break;\n case 1:\n intermediate = y & 0x1;\n break;\n case 2:\n intermediate = x % 3;\n break;\n case 3:\n intermediate = (y + x) % 3;\n break;\n case 4:\n intermediate = (Math.floor(y / 2) + Math.floor(x / 3)) & 0x1;\n break;\n case 5:\n temp = y * x;\n intermediate = (temp & 0x1) + (temp % 3);\n break;\n case 6:\n temp = y * x;\n intermediate = ((temp & 0x1) + (temp % 3)) & 0x1;\n break;\n case 7:\n temp = y * x;\n intermediate = ((temp % 3) + ((y + x) & 0x1)) & 0x1;\n break;\n default:\n throw new IllegalArgumentException('Invalid mask pattern: ' + maskPattern);\n }\n return intermediate === 0;\n }\n /**\n * Helper function for applyMaskPenaltyRule1. We need this for doing this calculation in both\n * vertical and horizontal orders respectively.\n */\n static applyMaskPenaltyRule1Internal(matrix, isHorizontal) {\n let penalty = 0;\n const iLimit = isHorizontal ? matrix.getHeight() : matrix.getWidth();\n const jLimit = isHorizontal ? matrix.getWidth() : matrix.getHeight();\n const array = matrix.getArray();\n for (let i = 0; i < iLimit; i++) {\n let numSameBitCells = 0;\n let prevBit = -1;\n for (let j = 0; j < jLimit; j++) {\n const bit = isHorizontal ? array[i][j] : array[j][i];\n if (bit === prevBit) {\n numSameBitCells++;\n }\n else {\n if (numSameBitCells >= 5) {\n penalty += MaskUtil.N1 + (numSameBitCells - 5);\n }\n numSameBitCells = 1; // Include the cell itself.\n prevBit = bit;\n }\n }\n if (numSameBitCells >= 5) {\n penalty += MaskUtil.N1 + (numSameBitCells - 5);\n }\n }\n return penalty;\n }\n }\n // Penalty weights from section 6.8.2.1\n MaskUtil.N1 = 3;\n MaskUtil.N2 = 3;\n MaskUtil.N3 = 40;\n MaskUtil.N4 = 10;\n\n /**\n * JAVAPORT: The original code was a 2D array of ints, but since it only ever gets assigned\n * -1, 0, and 1, I'm going to use less memory and go with bytes.\n *\n * @author dswitkin@google.com (Daniel Switkin)\n */\n class ByteMatrix {\n constructor(width /*int*/, height /*int*/) {\n this.width = width;\n this.height = height;\n const bytes = new Array(height); // [height][width]\n for (let i = 0; i !== height; i++) {\n bytes[i] = new Uint8Array(width);\n }\n this.bytes = bytes;\n }\n getHeight() {\n return this.height;\n }\n getWidth() {\n return this.width;\n }\n get(x /*int*/, y /*int*/) {\n return this.bytes[y][x];\n }\n /**\n * @return an internal representation as bytes, in row-major order. array[y][x] represents point (x,y)\n */\n getArray() {\n return this.bytes;\n }\n // TYPESCRIPTPORT: preffer to let two methods instead of override to avoid type comparison inside\n setNumber(x /*int*/, y /*int*/, value /*byte|int*/) {\n this.bytes[y][x] = value;\n }\n // public set(x: number /*int*/, y: number /*int*/, value: number /*int*/): void {\n // bytes[y][x] = (byte) value\n // }\n setBoolean(x /*int*/, y /*int*/, value) {\n this.bytes[y][x] = /*(byte) */ (value ? 1 : 0);\n }\n clear(value /*byte*/) {\n for (const aByte of this.bytes) {\n Arrays.fill(aByte, value);\n }\n }\n equals(o) {\n if (!(o instanceof ByteMatrix)) {\n return false;\n }\n const other = o;\n if (this.width !== other.width) {\n return false;\n }\n if (this.height !== other.height) {\n return false;\n }\n for (let y = 0, height = this.height; y < height; ++y) {\n const bytesY = this.bytes[y];\n const otherBytesY = other.bytes[y];\n for (let x = 0, width = this.width; x < width; ++x) {\n if (bytesY[x] !== otherBytesY[x]) {\n return false;\n }\n }\n }\n return true;\n }\n /*@Override*/\n toString() {\n const result = new StringBuilder(); // (2 * width * height + 2)\n for (let y = 0, height = this.height; y < height; ++y) {\n const bytesY = this.bytes[y];\n for (let x = 0, width = this.width; x < width; ++x) {\n switch (bytesY[x]) {\n case 0:\n result.append(' 0');\n break;\n case 1:\n result.append(' 1');\n break;\n default:\n result.append(' ');\n break;\n }\n }\n result.append('\\n');\n }\n return result.toString();\n }\n }\n\n /**\n * @author satorux@google.com (Satoru Takabayashi) - creator\n * @author dswitkin@google.com (Daniel Switkin) - ported from C++\n */\n class QRCode {\n constructor() {\n this.maskPattern = -1;\n }\n getMode() {\n return this.mode;\n }\n getECLevel() {\n return this.ecLevel;\n }\n getVersion() {\n return this.version;\n }\n getMaskPattern() {\n return this.maskPattern;\n }\n getMatrix() {\n return this.matrix;\n }\n /*@Override*/\n toString() {\n const result = new StringBuilder(); // (200)\n result.append('<<\\n');\n result.append(' mode: ');\n result.append(this.mode ? this.mode.toString() : 'null');\n result.append('\\n ecLevel: ');\n result.append(this.ecLevel ? this.ecLevel.toString() : 'null');\n result.append('\\n version: ');\n result.append(this.version ? this.version.toString() : 'null');\n result.append('\\n maskPattern: ');\n result.append(this.maskPattern.toString());\n if (this.matrix) {\n result.append('\\n matrix:\\n');\n result.append(this.matrix.toString());\n }\n else {\n result.append('\\n matrix: null\\n');\n }\n result.append('>>\\n');\n return result.toString();\n }\n setMode(value) {\n this.mode = value;\n }\n setECLevel(value) {\n this.ecLevel = value;\n }\n setVersion(version) {\n this.version = version;\n }\n setMaskPattern(value /*int*/) {\n this.maskPattern = value;\n }\n setMatrix(value) {\n this.matrix = value;\n }\n // Check if \"mask_pattern\" is valid.\n static isValidMaskPattern(maskPattern /*int*/) {\n return maskPattern >= 0 && maskPattern < QRCode.NUM_MASK_PATTERNS;\n }\n }\n QRCode.NUM_MASK_PATTERNS = 8;\n\n /**\n * Custom Error class of type Exception.\n */\n class WriterException extends Exception {\n }\n WriterException.kind = 'WriterException';\n\n /**\n * @author satorux@google.com (Satoru Takabayashi) - creator\n * @author dswitkin@google.com (Daniel Switkin) - ported from C++\n */\n class MatrixUtil {\n constructor() {\n // do nothing\n }\n // Set all cells to -1 (TYPESCRIPTPORT: 255). -1 (TYPESCRIPTPORT: 255) means that the cell is empty (not set yet).\n //\n // JAVAPORT: We shouldn't need to do this at all. The code should be rewritten to begin encoding\n // with the ByteMatrix initialized all to zero.\n static clearMatrix(matrix) {\n // TYPESCRIPTPORT: we use UintArray se changed here from -1 to 255\n matrix.clear(/*(byte) */ /*-1*/ 255);\n }\n // Build 2D matrix of QR Code from \"dataBits\" with \"ecLevel\", \"version\" and \"getMaskPattern\". On\n // success, store the result in \"matrix\" and return true.\n static buildMatrix(dataBits, ecLevel, version, maskPattern /*int*/, matrix) {\n MatrixUtil.clearMatrix(matrix);\n MatrixUtil.embedBasicPatterns(version, matrix);\n // Type information appear with any version.\n MatrixUtil.embedTypeInfo(ecLevel, maskPattern, matrix);\n // Version info appear if version >= 7.\n MatrixUtil.maybeEmbedVersionInfo(version, matrix);\n // Data should be embedded at end.\n MatrixUtil.embedDataBits(dataBits, maskPattern, matrix);\n }\n // Embed basic patterns. On success, modify the matrix and return true.\n // The basic patterns are:\n // - Position detection patterns\n // - Timing patterns\n // - Dark dot at the left bottom corner\n // - Position adjustment patterns, if need be\n static embedBasicPatterns(version, matrix) {\n // Let's get started with embedding big squares at corners.\n MatrixUtil.embedPositionDetectionPatternsAndSeparators(matrix);\n // Then, embed the dark dot at the left bottom corner.\n MatrixUtil.embedDarkDotAtLeftBottomCorner(matrix);\n // Position adjustment patterns appear if version >= 2.\n MatrixUtil.maybeEmbedPositionAdjustmentPatterns(version, matrix);\n // Timing patterns should be embedded after position adj. patterns.\n MatrixUtil.embedTimingPatterns(matrix);\n }\n // Embed type information. On success, modify the matrix.\n static embedTypeInfo(ecLevel, maskPattern /*int*/, matrix) {\n const typeInfoBits = new BitArray();\n MatrixUtil.makeTypeInfoBits(ecLevel, maskPattern, typeInfoBits);\n for (let i = 0, size = typeInfoBits.getSize(); i < size; ++i) {\n // Place bits in LSB to MSB order. LSB (least significant bit) is the last value in\n // \"typeInfoBits\".\n const bit = typeInfoBits.get(typeInfoBits.getSize() - 1 - i);\n // Type info bits at the left top corner. See 8.9 of JISX0510:2004 (p.46).\n const coordinates = MatrixUtil.TYPE_INFO_COORDINATES[i];\n const x1 = coordinates[0];\n const y1 = coordinates[1];\n matrix.setBoolean(x1, y1, bit);\n if (i < 8) {\n // Right top corner.\n const x2 = matrix.getWidth() - i - 1;\n const y2 = 8;\n matrix.setBoolean(x2, y2, bit);\n }\n else {\n // Left bottom corner.\n const x2 = 8;\n const y2 = matrix.getHeight() - 7 + (i - 8);\n matrix.setBoolean(x2, y2, bit);\n }\n }\n }\n // Embed version information if need be. On success, modify the matrix and return true.\n // See 8.10 of JISX0510:2004 (p.47) for how to embed version information.\n static maybeEmbedVersionInfo(version, matrix) {\n if (version.getVersionNumber() < 7) { // Version info is necessary if version >= 7.\n return; // Don't need version info.\n }\n const versionInfoBits = new BitArray();\n MatrixUtil.makeVersionInfoBits(version, versionInfoBits);\n let bitIndex = 6 * 3 - 1; // It will decrease from 17 to 0.\n for (let i = 0; i < 6; ++i) {\n for (let j = 0; j < 3; ++j) {\n // Place bits in LSB (least significant bit) to MSB order.\n const bit = versionInfoBits.get(bitIndex);\n bitIndex--;\n // Left bottom corner.\n matrix.setBoolean(i, matrix.getHeight() - 11 + j, bit);\n // Right bottom corner.\n matrix.setBoolean(matrix.getHeight() - 11 + j, i, bit);\n }\n }\n }\n // Embed \"dataBits\" using \"getMaskPattern\". On success, modify the matrix and return true.\n // For debugging purposes, it skips masking process if \"getMaskPattern\" is -1(TYPESCRIPTPORT: 255).\n // See 8.7 of JISX0510:2004 (p.38) for how to embed data bits.\n static embedDataBits(dataBits, maskPattern /*int*/, matrix) {\n let bitIndex = 0;\n let direction = -1;\n // Start from the right bottom cell.\n let x = matrix.getWidth() - 1;\n let y = matrix.getHeight() - 1;\n while (x > 0) {\n // Skip the vertical timing pattern.\n if (x === 6) {\n x -= 1;\n }\n while (y >= 0 && y < matrix.getHeight()) {\n for (let i = 0; i < 2; ++i) {\n const xx = x - i;\n // Skip the cell if it's not empty.\n if (!MatrixUtil.isEmpty(matrix.get(xx, y))) {\n continue;\n }\n let bit;\n if (bitIndex < dataBits.getSize()) {\n bit = dataBits.get(bitIndex);\n ++bitIndex;\n }\n else {\n // Padding bit. If there is no bit left, we'll fill the left cells with 0, as described\n // in 8.4.9 of JISX0510:2004 (p. 24).\n bit = false;\n }\n // Skip masking if mask_pattern is -1 (TYPESCRIPTPORT: 255).\n if (maskPattern !== 255 && MaskUtil.getDataMaskBit(maskPattern, xx, y)) {\n bit = !bit;\n }\n matrix.setBoolean(xx, y, bit);\n }\n y += direction;\n }\n direction = -direction; // Reverse the direction.\n y += direction;\n x -= 2; // Move to the left.\n }\n // All bits should be consumed.\n if (bitIndex !== dataBits.getSize()) {\n throw new WriterException('Not all bits consumed: ' + bitIndex + '/' + dataBits.getSize());\n }\n }\n // Return the position of the most significant bit set (one: to) in the \"value\". The most\n // significant bit is position 32. If there is no bit set, return 0. Examples:\n // - findMSBSet(0) => 0\n // - findMSBSet(1) => 1\n // - findMSBSet(255) => 8\n static findMSBSet(value /*int*/) {\n return 32 - Integer.numberOfLeadingZeros(value);\n }\n // Calculate BCH (Bose-Chaudhuri-Hocquenghem) code for \"value\" using polynomial \"poly\". The BCH\n // code is used for encoding type information and version information.\n // Example: Calculation of version information of 7.\n // f(x) is created from 7.\n // - 7 = 000111 in 6 bits\n // - f(x) = x^2 + x^1 + x^0\n // g(x) is given by the standard (p. 67)\n // - g(x) = x^12 + x^11 + x^10 + x^9 + x^8 + x^5 + x^2 + 1\n // Multiply f(x) by x^(18 - 6)\n // - f'(x) = f(x) * x^(18 - 6)\n // - f'(x) = x^14 + x^13 + x^12\n // Calculate the remainder of f'(x) / g(x)\n // x^2\n // __________________________________________________\n // g(x) )x^14 + x^13 + x^12\n // x^14 + x^13 + x^12 + x^11 + x^10 + x^7 + x^4 + x^2\n // --------------------------------------------------\n // x^11 + x^10 + x^7 + x^4 + x^2\n //\n // The remainder is x^11 + x^10 + x^7 + x^4 + x^2\n // Encode it in binary: 110010010100\n // The return value is 0xc94 (1100 1001 0100)\n //\n // Since all coefficients in the polynomials are 1 or 0, we can do the calculation by bit\n // operations. We don't care if coefficients are positive or negative.\n static calculateBCHCode(value /*int*/, poly /*int*/) {\n if (poly === 0) {\n throw new IllegalArgumentException('0 polynomial');\n }\n // If poly is \"1 1111 0010 0101\" (version info poly), msbSetInPoly is 13. We'll subtract 1\n // from 13 to make it 12.\n const msbSetInPoly = MatrixUtil.findMSBSet(poly);\n value <<= msbSetInPoly - 1;\n // Do the division business using exclusive-or operations.\n while (MatrixUtil.findMSBSet(value) >= msbSetInPoly) {\n value ^= poly << (MatrixUtil.findMSBSet(value) - msbSetInPoly);\n }\n // Now the \"value\" is the remainder (i.e. the BCH code)\n return value;\n }\n // Make bit vector of type information. On success, store the result in \"bits\" and return true.\n // Encode error correction level and mask pattern. See 8.9 of\n // JISX0510:2004 (p.45) for details.\n static makeTypeInfoBits(ecLevel, maskPattern /*int*/, bits) {\n if (!QRCode.isValidMaskPattern(maskPattern)) {\n throw new WriterException('Invalid mask pattern');\n }\n const typeInfo = (ecLevel.getBits() << 3) | maskPattern;\n bits.appendBits(typeInfo, 5);\n const bchCode = MatrixUtil.calculateBCHCode(typeInfo, MatrixUtil.TYPE_INFO_POLY);\n bits.appendBits(bchCode, 10);\n const maskBits = new BitArray();\n maskBits.appendBits(MatrixUtil.TYPE_INFO_MASK_PATTERN, 15);\n bits.xor(maskBits);\n if (bits.getSize() !== 15) { // Just in case.\n throw new WriterException('should not happen but we got: ' + bits.getSize());\n }\n }\n // Make bit vector of version information. On success, store the result in \"bits\" and return true.\n // See 8.10 of JISX0510:2004 (p.45) for details.\n static makeVersionInfoBits(version, bits) {\n bits.appendBits(version.getVersionNumber(), 6);\n const bchCode = MatrixUtil.calculateBCHCode(version.getVersionNumber(), MatrixUtil.VERSION_INFO_POLY);\n bits.appendBits(bchCode, 12);\n if (bits.getSize() !== 18) { // Just in case.\n throw new WriterException('should not happen but we got: ' + bits.getSize());\n }\n }\n // Check if \"value\" is empty.\n static isEmpty(value /*int*/) {\n return value === 255; // -1\n }\n static embedTimingPatterns(matrix) {\n // -8 is for skipping position detection patterns (7: size), and two horizontal/vertical\n // separation patterns (1: size). Thus, 8 = 7 + 1.\n for (let i = 8; i < matrix.getWidth() - 8; ++i) {\n const bit = (i + 1) % 2;\n // Horizontal line.\n if (MatrixUtil.isEmpty(matrix.get(i, 6))) {\n matrix.setNumber(i, 6, bit);\n }\n // Vertical line.\n if (MatrixUtil.isEmpty(matrix.get(6, i))) {\n matrix.setNumber(6, i, bit);\n }\n }\n }\n // Embed the lonely dark dot at left bottom corner. JISX0510:2004 (p.46)\n static embedDarkDotAtLeftBottomCorner(matrix) {\n if (matrix.get(8, matrix.getHeight() - 8) === 0) {\n throw new WriterException();\n }\n matrix.setNumber(8, matrix.getHeight() - 8, 1);\n }\n static embedHorizontalSeparationPattern(xStart /*int*/, yStart /*int*/, matrix) {\n for (let x = 0; x < 8; ++x) {\n if (!MatrixUtil.isEmpty(matrix.get(xStart + x, yStart))) {\n throw new WriterException();\n }\n matrix.setNumber(xStart + x, yStart, 0);\n }\n }\n static embedVerticalSeparationPattern(xStart /*int*/, yStart /*int*/, matrix) {\n for (let y = 0; y < 7; ++y) {\n if (!MatrixUtil.isEmpty(matrix.get(xStart, yStart + y))) {\n throw new WriterException();\n }\n matrix.setNumber(xStart, yStart + y, 0);\n }\n }\n static embedPositionAdjustmentPattern(xStart /*int*/, yStart /*int*/, matrix) {\n for (let y = 0; y < 5; ++y) {\n const patternY = MatrixUtil.POSITION_ADJUSTMENT_PATTERN[y];\n for (let x = 0; x < 5; ++x) {\n matrix.setNumber(xStart + x, yStart + y, patternY[x]);\n }\n }\n }\n static embedPositionDetectionPattern(xStart /*int*/, yStart /*int*/, matrix) {\n for (let y = 0; y < 7; ++y) {\n const patternY = MatrixUtil.POSITION_DETECTION_PATTERN[y];\n for (let x = 0; x < 7; ++x) {\n matrix.setNumber(xStart + x, yStart + y, patternY[x]);\n }\n }\n }\n // Embed position detection patterns and surrounding vertical/horizontal separators.\n static embedPositionDetectionPatternsAndSeparators(matrix) {\n // Embed three big squares at corners.\n const pdpWidth = MatrixUtil.POSITION_DETECTION_PATTERN[0].length;\n // Left top corner.\n MatrixUtil.embedPositionDetectionPattern(0, 0, matrix);\n // Right top corner.\n MatrixUtil.embedPositionDetectionPattern(matrix.getWidth() - pdpWidth, 0, matrix);\n // Left bottom corner.\n MatrixUtil.embedPositionDetectionPattern(0, matrix.getWidth() - pdpWidth, matrix);\n // Embed horizontal separation patterns around the squares.\n const hspWidth = 8;\n // Left top corner.\n MatrixUtil.embedHorizontalSeparationPattern(0, hspWidth - 1, matrix);\n // Right top corner.\n MatrixUtil.embedHorizontalSeparationPattern(matrix.getWidth() - hspWidth, hspWidth - 1, matrix);\n // Left bottom corner.\n MatrixUtil.embedHorizontalSeparationPattern(0, matrix.getWidth() - hspWidth, matrix);\n // Embed vertical separation patterns around the squares.\n const vspSize = 7;\n // Left top corner.\n MatrixUtil.embedVerticalSeparationPattern(vspSize, 0, matrix);\n // Right top corner.\n MatrixUtil.embedVerticalSeparationPattern(matrix.getHeight() - vspSize - 1, 0, matrix);\n // Left bottom corner.\n MatrixUtil.embedVerticalSeparationPattern(vspSize, matrix.getHeight() - vspSize, matrix);\n }\n // Embed position adjustment patterns if need be.\n static maybeEmbedPositionAdjustmentPatterns(version, matrix) {\n if (version.getVersionNumber() < 2) { // The patterns appear if version >= 2\n return;\n }\n const index = version.getVersionNumber() - 1;\n const coordinates = MatrixUtil.POSITION_ADJUSTMENT_PATTERN_COORDINATE_TABLE[index];\n for (let i = 0, length = coordinates.length; i !== length; i++) {\n const y = coordinates[i];\n if (y >= 0) {\n for (let j = 0; j !== length; j++) {\n const x = coordinates[j];\n if (x >= 0 && MatrixUtil.isEmpty(matrix.get(x, y))) {\n // If the cell is unset, we embed the position adjustment pattern here.\n // -2 is necessary since the x/y coordinates point to the center of the pattern, not the\n // left top corner.\n MatrixUtil.embedPositionAdjustmentPattern(x - 2, y - 2, matrix);\n }\n }\n }\n }\n }\n }\n MatrixUtil.POSITION_DETECTION_PATTERN = Array.from([\n Int32Array.from([1, 1, 1, 1, 1, 1, 1]),\n Int32Array.from([1, 0, 0, 0, 0, 0, 1]),\n Int32Array.from([1, 0, 1, 1, 1, 0, 1]),\n Int32Array.from([1, 0, 1, 1, 1, 0, 1]),\n Int32Array.from([1, 0, 1, 1, 1, 0, 1]),\n Int32Array.from([1, 0, 0, 0, 0, 0, 1]),\n Int32Array.from([1, 1, 1, 1, 1, 1, 1]),\n ]);\n MatrixUtil.POSITION_ADJUSTMENT_PATTERN = Array.from([\n Int32Array.from([1, 1, 1, 1, 1]),\n Int32Array.from([1, 0, 0, 0, 1]),\n Int32Array.from([1, 0, 1, 0, 1]),\n Int32Array.from([1, 0, 0, 0, 1]),\n Int32Array.from([1, 1, 1, 1, 1]),\n ]);\n // From Appendix E. Table 1, JIS0510X:2004 (71: p). The table was double-checked by komatsu.\n MatrixUtil.POSITION_ADJUSTMENT_PATTERN_COORDINATE_TABLE = Array.from([\n Int32Array.from([-1, -1, -1, -1, -1, -1, -1]),\n Int32Array.from([6, 18, -1, -1, -1, -1, -1]),\n Int32Array.from([6, 22, -1, -1, -1, -1, -1]),\n Int32Array.from([6, 26, -1, -1, -1, -1, -1]),\n Int32Array.from([6, 30, -1, -1, -1, -1, -1]),\n Int32Array.from([6, 34, -1, -1, -1, -1, -1]),\n Int32Array.from([6, 22, 38, -1, -1, -1, -1]),\n Int32Array.from([6, 24, 42, -1, -1, -1, -1]),\n Int32Array.from([6, 26, 46, -1, -1, -1, -1]),\n Int32Array.from([6, 28, 50, -1, -1, -1, -1]),\n Int32Array.from([6, 30, 54, -1, -1, -1, -1]),\n Int32Array.from([6, 32, 58, -1, -1, -1, -1]),\n Int32Array.from([6, 34, 62, -1, -1, -1, -1]),\n Int32Array.from([6, 26, 46, 66, -1, -1, -1]),\n Int32Array.from([6, 26, 48, 70, -1, -1, -1]),\n Int32Array.from([6, 26, 50, 74, -1, -1, -1]),\n Int32Array.from([6, 30, 54, 78, -1, -1, -1]),\n Int32Array.from([6, 30, 56, 82, -1, -1, -1]),\n Int32Array.from([6, 30, 58, 86, -1, -1, -1]),\n Int32Array.from([6, 34, 62, 90, -1, -1, -1]),\n Int32Array.from([6, 28, 50, 72, 94, -1, -1]),\n Int32Array.from([6, 26, 50, 74, 98, -1, -1]),\n Int32Array.from([6, 30, 54, 78, 102, -1, -1]),\n Int32Array.from([6, 28, 54, 80, 106, -1, -1]),\n Int32Array.from([6, 32, 58, 84, 110, -1, -1]),\n Int32Array.from([6, 30, 58, 86, 114, -1, -1]),\n Int32Array.from([6, 34, 62, 90, 118, -1, -1]),\n Int32Array.from([6, 26, 50, 74, 98, 122, -1]),\n Int32Array.from([6, 30, 54, 78, 102, 126, -1]),\n Int32Array.from([6, 26, 52, 78, 104, 130, -1]),\n Int32Array.from([6, 30, 56, 82, 108, 134, -1]),\n Int32Array.from([6, 34, 60, 86, 112, 138, -1]),\n Int32Array.from([6, 30, 58, 86, 114, 142, -1]),\n Int32Array.from([6, 34, 62, 90, 118, 146, -1]),\n Int32Array.from([6, 30, 54, 78, 102, 126, 150]),\n Int32Array.from([6, 24, 50, 76, 102, 128, 154]),\n Int32Array.from([6, 28, 54, 80, 106, 132, 158]),\n Int32Array.from([6, 32, 58, 84, 110, 136, 162]),\n Int32Array.from([6, 26, 54, 82, 110, 138, 166]),\n Int32Array.from([6, 30, 58, 86, 114, 142, 170]),\n ]);\n // Type info cells at the left top corner.\n MatrixUtil.TYPE_INFO_COORDINATES = Array.from([\n Int32Array.from([8, 0]),\n Int32Array.from([8, 1]),\n Int32Array.from([8, 2]),\n Int32Array.from([8, 3]),\n Int32Array.from([8, 4]),\n Int32Array.from([8, 5]),\n Int32Array.from([8, 7]),\n Int32Array.from([8, 8]),\n Int32Array.from([7, 8]),\n Int32Array.from([5, 8]),\n Int32Array.from([4, 8]),\n Int32Array.from([3, 8]),\n Int32Array.from([2, 8]),\n Int32Array.from([1, 8]),\n Int32Array.from([0, 8]),\n ]);\n // From Appendix D in JISX0510:2004 (p. 67)\n MatrixUtil.VERSION_INFO_POLY = 0x1f25; // 1 1111 0010 0101\n // From Appendix C in JISX0510:2004 (p.65).\n MatrixUtil.TYPE_INFO_POLY = 0x537;\n MatrixUtil.TYPE_INFO_MASK_PATTERN = 0x5412;\n\n /*namespace com.google.zxing.qrcode.encoder {*/\n class BlockPair {\n constructor(dataBytes, errorCorrectionBytes) {\n this.dataBytes = dataBytes;\n this.errorCorrectionBytes = errorCorrectionBytes;\n }\n getDataBytes() {\n return this.dataBytes;\n }\n getErrorCorrectionBytes() {\n return this.errorCorrectionBytes;\n }\n }\n\n /*import java.io.UnsupportedEncodingException;*/\n /*import java.util.ArrayList;*/\n /*import java.util.Collection;*/\n /*import java.util.Map;*/\n /**\n * @author satorux@google.com (Satoru Takabayashi) - creator\n * @author dswitkin@google.com (Daniel Switkin) - ported from C++\n */\n class Encoder {\n // TYPESCRIPTPORT: changed to UTF8, the default for js\n constructor() { }\n // The mask penalty calculation is complicated. See Table 21 of JISX0510:2004 (p.45) for details.\n // Basically it applies four rules and summate all penalties.\n static calculateMaskPenalty(matrix) {\n return MaskUtil.applyMaskPenaltyRule1(matrix)\n + MaskUtil.applyMaskPenaltyRule2(matrix)\n + MaskUtil.applyMaskPenaltyRule3(matrix)\n + MaskUtil.applyMaskPenaltyRule4(matrix);\n }\n /**\n * @param content text to encode\n * @param ecLevel error correction level to use\n * @return {@link QRCode} representing the encoded QR code\n * @throws WriterException if encoding can't succeed, because of for example invalid content\n * or configuration\n */\n // public static encode(content: string, ecLevel: ErrorCorrectionLevel): QRCode /*throws WriterException*/ {\n // return encode(content, ecLevel, null)\n // }\n static encode(content, ecLevel, hints = null) {\n // Determine what character encoding has been specified by the caller, if any\n let encoding = Encoder.DEFAULT_BYTE_MODE_ENCODING;\n const hasEncodingHint = hints !== null && undefined !== hints.get(EncodeHintType$1.CHARACTER_SET);\n if (hasEncodingHint) {\n encoding = hints.get(EncodeHintType$1.CHARACTER_SET).toString();\n }\n // Pick an encoding mode appropriate for the content. Note that this will not attempt to use\n // multiple modes / segments even if that were more efficient. Twould be nice.\n const mode = this.chooseMode(content, encoding);\n // This will store the header information, like mode and\n // length, as well as \"header\" segments like an ECI segment.\n const headerBits = new BitArray();\n // Append ECI segment if applicable\n if (mode === Mode$1.BYTE && (hasEncodingHint || Encoder.DEFAULT_BYTE_MODE_ENCODING !== encoding)) {\n const eci = CharacterSetECI.getCharacterSetECIByName(encoding);\n if (eci !== undefined) {\n this.appendECI(eci, headerBits);\n }\n }\n // (With ECI in place,) Write the mode marker\n this.appendModeInfo(mode, headerBits);\n // Collect data within the main segment, separately, to count its size if needed. Don't add it to\n // main payload yet.\n const dataBits = new BitArray();\n this.appendBytes(content, mode, dataBits, encoding);\n let version;\n if (hints !== null && undefined !== hints.get(EncodeHintType$1.QR_VERSION)) {\n const versionNumber = Number.parseInt(hints.get(EncodeHintType$1.QR_VERSION).toString(), 10);\n version = Version$1.getVersionForNumber(versionNumber);\n const bitsNeeded = this.calculateBitsNeeded(mode, headerBits, dataBits, version);\n if (!this.willFit(bitsNeeded, version, ecLevel)) {\n throw new WriterException('Data too big for requested version');\n }\n }\n else {\n version = this.recommendVersion(ecLevel, mode, headerBits, dataBits);\n }\n const headerAndDataBits = new BitArray();\n headerAndDataBits.appendBitArray(headerBits);\n // Find \"length\" of main segment and write it\n const numLetters = mode === Mode$1.BYTE ? dataBits.getSizeInBytes() : content.length;\n this.appendLengthInfo(numLetters, version, mode, headerAndDataBits);\n // Put data together into the overall payload\n headerAndDataBits.appendBitArray(dataBits);\n const ecBlocks = version.getECBlocksForLevel(ecLevel);\n const numDataBytes = version.getTotalCodewords() - ecBlocks.getTotalECCodewords();\n // Terminate the bits properly.\n this.terminateBits(numDataBytes, headerAndDataBits);\n // Interleave data bits with error correction code.\n const finalBits = this.interleaveWithECBytes(headerAndDataBits, version.getTotalCodewords(), numDataBytes, ecBlocks.getNumBlocks());\n const qrCode = new QRCode();\n qrCode.setECLevel(ecLevel);\n qrCode.setMode(mode);\n qrCode.setVersion(version);\n // Choose the mask pattern and set to \"qrCode\".\n const dimension = version.getDimensionForVersion();\n const matrix = new ByteMatrix(dimension, dimension);\n const maskPattern = this.chooseMaskPattern(finalBits, ecLevel, version, matrix);\n qrCode.setMaskPattern(maskPattern);\n // Build the matrix and set it to \"qrCode\".\n MatrixUtil.buildMatrix(finalBits, ecLevel, version, maskPattern, matrix);\n qrCode.setMatrix(matrix);\n return qrCode;\n }\n /**\n * Decides the smallest version of QR code that will contain all of the provided data.\n *\n * @throws WriterException if the data cannot fit in any version\n */\n static recommendVersion(ecLevel, mode, headerBits, dataBits) {\n // Hard part: need to know version to know how many bits length takes. But need to know how many\n // bits it takes to know version. First we take a guess at version by assuming version will be\n // the minimum, 1:\n const provisionalBitsNeeded = this.calculateBitsNeeded(mode, headerBits, dataBits, Version$1.getVersionForNumber(1));\n const provisionalVersion = this.chooseVersion(provisionalBitsNeeded, ecLevel);\n // Use that guess to calculate the right version. I am still not sure this works in 100% of cases.\n const bitsNeeded = this.calculateBitsNeeded(mode, headerBits, dataBits, provisionalVersion);\n return this.chooseVersion(bitsNeeded, ecLevel);\n }\n static calculateBitsNeeded(mode, headerBits, dataBits, version) {\n return headerBits.getSize() + mode.getCharacterCountBits(version) + dataBits.getSize();\n }\n /**\n * @return the code point of the table used in alphanumeric mode or\n * -1 if there is no corresponding code in the table.\n */\n static getAlphanumericCode(code /*int*/) {\n if (code < Encoder.ALPHANUMERIC_TABLE.length) {\n return Encoder.ALPHANUMERIC_TABLE[code];\n }\n return -1;\n }\n // public static chooseMode(content: string): Mode {\n // return chooseMode(content, null);\n // }\n /**\n * Choose the best mode by examining the content. Note that 'encoding' is used as a hint;\n * if it is Shift_JIS, and the input is only double-byte Kanji, then we return {@link Mode#KANJI}.\n */\n static chooseMode(content, encoding = null) {\n if (CharacterSetECI.SJIS.getName() === encoding && this.isOnlyDoubleByteKanji(content)) {\n // Choose Kanji mode if all input are double-byte characters\n return Mode$1.KANJI;\n }\n let hasNumeric = false;\n let hasAlphanumeric = false;\n for (let i = 0, length = content.length; i < length; ++i) {\n const c = content.charAt(i);\n if (Encoder.isDigit(c)) {\n hasNumeric = true;\n }\n else if (this.getAlphanumericCode(c.charCodeAt(0)) !== -1) {\n hasAlphanumeric = true;\n }\n else {\n return Mode$1.BYTE;\n }\n }\n if (hasAlphanumeric) {\n return Mode$1.ALPHANUMERIC;\n }\n if (hasNumeric) {\n return Mode$1.NUMERIC;\n }\n return Mode$1.BYTE;\n }\n static isOnlyDoubleByteKanji(content) {\n let bytes;\n try {\n bytes = StringEncoding.encode(content, CharacterSetECI.SJIS); // content.getBytes(\"Shift_JIS\"))\n }\n catch (ignored /*: UnsupportedEncodingException*/) {\n return false;\n }\n const length = bytes.length;\n if (length % 2 !== 0) {\n return false;\n }\n for (let i = 0; i < length; i += 2) {\n const byte1 = bytes[i] & 0xFF;\n if ((byte1 < 0x81 || byte1 > 0x9F) && (byte1 < 0xE0 || byte1 > 0xEB)) {\n return false;\n }\n }\n return true;\n }\n static chooseMaskPattern(bits, ecLevel, version, matrix) {\n let minPenalty = Number.MAX_SAFE_INTEGER; // Lower penalty is better.\n let bestMaskPattern = -1;\n // We try all mask patterns to choose the best one.\n for (let maskPattern = 0; maskPattern < QRCode.NUM_MASK_PATTERNS; maskPattern++) {\n MatrixUtil.buildMatrix(bits, ecLevel, version, maskPattern, matrix);\n let penalty = this.calculateMaskPenalty(matrix);\n if (penalty < minPenalty) {\n minPenalty = penalty;\n bestMaskPattern = maskPattern;\n }\n }\n return bestMaskPattern;\n }\n static chooseVersion(numInputBits /*int*/, ecLevel) {\n for (let versionNum = 1; versionNum <= 40; versionNum++) {\n const version = Version$1.getVersionForNumber(versionNum);\n if (Encoder.willFit(numInputBits, version, ecLevel)) {\n return version;\n }\n }\n throw new WriterException('Data too big');\n }\n /**\n * @return true if the number of input bits will fit in a code with the specified version and\n * error correction level.\n */\n static willFit(numInputBits /*int*/, version, ecLevel) {\n // In the following comments, we use numbers of Version 7-H.\n // numBytes = 196\n const numBytes = version.getTotalCodewords();\n // getNumECBytes = 130\n const ecBlocks = version.getECBlocksForLevel(ecLevel);\n const numEcBytes = ecBlocks.getTotalECCodewords();\n // getNumDataBytes = 196 - 130 = 66\n const numDataBytes = numBytes - numEcBytes;\n const totalInputBytes = (numInputBits + 7) / 8;\n return numDataBytes >= totalInputBytes;\n }\n /**\n * Terminate bits as described in 8.4.8 and 8.4.9 of JISX0510:2004 (p.24).\n */\n static terminateBits(numDataBytes /*int*/, bits) {\n const capacity = numDataBytes * 8;\n if (bits.getSize() > capacity) {\n throw new WriterException('data bits cannot fit in the QR Code' + bits.getSize() + ' > ' +\n capacity);\n }\n for (let i = 0; i < 4 && bits.getSize() < capacity; ++i) {\n bits.appendBit(false);\n }\n // Append termination bits. See 8.4.8 of JISX0510:2004 (p.24) for details.\n // If the last byte isn't 8-bit aligned, we'll add padding bits.\n const numBitsInLastByte = bits.getSize() & 0x07;\n if (numBitsInLastByte > 0) {\n for (let i = numBitsInLastByte; i < 8; i++) {\n bits.appendBit(false);\n }\n }\n // If we have more space, we'll fill the space with padding patterns defined in 8.4.9 (p.24).\n const numPaddingBytes = numDataBytes - bits.getSizeInBytes();\n for (let i = 0; i < numPaddingBytes; ++i) {\n bits.appendBits((i & 0x01) === 0 ? 0xEC : 0x11, 8);\n }\n if (bits.getSize() !== capacity) {\n throw new WriterException('Bits size does not equal capacity');\n }\n }\n /**\n * Get number of data bytes and number of error correction bytes for block id \"blockID\". Store\n * the result in \"numDataBytesInBlock\", and \"numECBytesInBlock\". See table 12 in 8.5.1 of\n * JISX0510:2004 (p.30)\n */\n static getNumDataBytesAndNumECBytesForBlockID(numTotalBytes /*int*/, numDataBytes /*int*/, numRSBlocks /*int*/, blockID /*int*/, numDataBytesInBlock, numECBytesInBlock) {\n if (blockID >= numRSBlocks) {\n throw new WriterException('Block ID too large');\n }\n // numRsBlocksInGroup2 = 196 % 5 = 1\n const numRsBlocksInGroup2 = numTotalBytes % numRSBlocks;\n // numRsBlocksInGroup1 = 5 - 1 = 4\n const numRsBlocksInGroup1 = numRSBlocks - numRsBlocksInGroup2;\n // numTotalBytesInGroup1 = 196 / 5 = 39\n const numTotalBytesInGroup1 = Math.floor(numTotalBytes / numRSBlocks);\n // numTotalBytesInGroup2 = 39 + 1 = 40\n const numTotalBytesInGroup2 = numTotalBytesInGroup1 + 1;\n // numDataBytesInGroup1 = 66 / 5 = 13\n const numDataBytesInGroup1 = Math.floor(numDataBytes / numRSBlocks);\n // numDataBytesInGroup2 = 13 + 1 = 14\n const numDataBytesInGroup2 = numDataBytesInGroup1 + 1;\n // numEcBytesInGroup1 = 39 - 13 = 26\n const numEcBytesInGroup1 = numTotalBytesInGroup1 - numDataBytesInGroup1;\n // numEcBytesInGroup2 = 40 - 14 = 26\n const numEcBytesInGroup2 = numTotalBytesInGroup2 - numDataBytesInGroup2;\n // Sanity checks.\n // 26 = 26\n if (numEcBytesInGroup1 !== numEcBytesInGroup2) {\n throw new WriterException('EC bytes mismatch');\n }\n // 5 = 4 + 1.\n if (numRSBlocks !== numRsBlocksInGroup1 + numRsBlocksInGroup2) {\n throw new WriterException('RS blocks mismatch');\n }\n // 196 = (13 + 26) * 4 + (14 + 26) * 1\n if (numTotalBytes !==\n ((numDataBytesInGroup1 + numEcBytesInGroup1) *\n numRsBlocksInGroup1) +\n ((numDataBytesInGroup2 + numEcBytesInGroup2) *\n numRsBlocksInGroup2)) {\n throw new WriterException('Total bytes mismatch');\n }\n if (blockID < numRsBlocksInGroup1) {\n numDataBytesInBlock[0] = numDataBytesInGroup1;\n numECBytesInBlock[0] = numEcBytesInGroup1;\n }\n else {\n numDataBytesInBlock[0] = numDataBytesInGroup2;\n numECBytesInBlock[0] = numEcBytesInGroup2;\n }\n }\n /**\n * Interleave \"bits\" with corresponding error correction bytes. On success, store the result in\n * \"result\". The interleave rule is complicated. See 8.6 of JISX0510:2004 (p.37) for details.\n */\n static interleaveWithECBytes(bits, numTotalBytes /*int*/, numDataBytes /*int*/, numRSBlocks /*int*/) {\n // \"bits\" must have \"getNumDataBytes\" bytes of data.\n if (bits.getSizeInBytes() !== numDataBytes) {\n throw new WriterException('Number of bits and data bytes does not match');\n }\n // Step 1. Divide data bytes into blocks and generate error correction bytes for them. We'll\n // store the divided data bytes blocks and error correction bytes blocks into \"blocks\".\n let dataBytesOffset = 0;\n let maxNumDataBytes = 0;\n let maxNumEcBytes = 0;\n // Since, we know the number of reedsolmon blocks, we can initialize the vector with the number.\n const blocks = new Array(); // new Array(numRSBlocks)\n for (let i = 0; i < numRSBlocks; ++i) {\n const numDataBytesInBlock = new Int32Array(1);\n const numEcBytesInBlock = new Int32Array(1);\n Encoder.getNumDataBytesAndNumECBytesForBlockID(numTotalBytes, numDataBytes, numRSBlocks, i, numDataBytesInBlock, numEcBytesInBlock);\n const size = numDataBytesInBlock[0];\n const dataBytes = new Uint8Array(size);\n bits.toBytes(8 * dataBytesOffset, dataBytes, 0, size);\n const ecBytes = Encoder.generateECBytes(dataBytes, numEcBytesInBlock[0]);\n blocks.push(new BlockPair(dataBytes, ecBytes));\n maxNumDataBytes = Math.max(maxNumDataBytes, size);\n maxNumEcBytes = Math.max(maxNumEcBytes, ecBytes.length);\n dataBytesOffset += numDataBytesInBlock[0];\n }\n if (numDataBytes !== dataBytesOffset) {\n throw new WriterException('Data bytes does not match offset');\n }\n const result = new BitArray();\n // First, place data blocks.\n for (let i = 0; i < maxNumDataBytes; ++i) {\n for (const block of blocks) {\n const dataBytes = block.getDataBytes();\n if (i < dataBytes.length) {\n result.appendBits(dataBytes[i], 8);\n }\n }\n }\n // Then, place error correction blocks.\n for (let i = 0; i < maxNumEcBytes; ++i) {\n for (const block of blocks) {\n const ecBytes = block.getErrorCorrectionBytes();\n if (i < ecBytes.length) {\n result.appendBits(ecBytes[i], 8);\n }\n }\n }\n if (numTotalBytes !== result.getSizeInBytes()) { // Should be same.\n throw new WriterException('Interleaving error: ' + numTotalBytes + ' and ' +\n result.getSizeInBytes() + ' differ.');\n }\n return result;\n }\n static generateECBytes(dataBytes, numEcBytesInBlock /*int*/) {\n const numDataBytes = dataBytes.length;\n const toEncode = new Int32Array(numDataBytes + numEcBytesInBlock); // int[numDataBytes + numEcBytesInBlock]\n for (let i = 0; i < numDataBytes; i++) {\n toEncode[i] = dataBytes[i] & 0xFF;\n }\n new ReedSolomonEncoder(GenericGF.QR_CODE_FIELD_256).encode(toEncode, numEcBytesInBlock);\n const ecBytes = new Uint8Array(numEcBytesInBlock);\n for (let i = 0; i < numEcBytesInBlock; i++) {\n ecBytes[i] = /*(byte) */ toEncode[numDataBytes + i];\n }\n return ecBytes;\n }\n /**\n * Append mode info. On success, store the result in \"bits\".\n */\n static appendModeInfo(mode, bits) {\n bits.appendBits(mode.getBits(), 4);\n }\n /**\n * Append length info. On success, store the result in \"bits\".\n */\n static appendLengthInfo(numLetters /*int*/, version, mode, bits) {\n const numBits = mode.getCharacterCountBits(version);\n if (numLetters >= (1 << numBits)) {\n throw new WriterException(numLetters + ' is bigger than ' + ((1 << numBits) - 1));\n }\n bits.appendBits(numLetters, numBits);\n }\n /**\n * Append \"bytes\" in \"mode\" mode (encoding) into \"bits\". On success, store the result in \"bits\".\n */\n static appendBytes(content, mode, bits, encoding) {\n switch (mode) {\n case Mode$1.NUMERIC:\n Encoder.appendNumericBytes(content, bits);\n break;\n case Mode$1.ALPHANUMERIC:\n Encoder.appendAlphanumericBytes(content, bits);\n break;\n case Mode$1.BYTE:\n Encoder.append8BitBytes(content, bits, encoding);\n break;\n case Mode$1.KANJI:\n Encoder.appendKanjiBytes(content, bits);\n break;\n default:\n throw new WriterException('Invalid mode: ' + mode);\n }\n }\n static getDigit(singleCharacter) {\n return singleCharacter.charCodeAt(0) - 48;\n }\n static isDigit(singleCharacter) {\n const cn = Encoder.getDigit(singleCharacter);\n return cn >= 0 && cn <= 9;\n }\n static appendNumericBytes(content, bits) {\n const length = content.length;\n let i = 0;\n while (i < length) {\n const num1 = Encoder.getDigit(content.charAt(i));\n if (i + 2 < length) {\n // Encode three numeric letters in ten bits.\n const num2 = Encoder.getDigit(content.charAt(i + 1));\n const num3 = Encoder.getDigit(content.charAt(i + 2));\n bits.appendBits(num1 * 100 + num2 * 10 + num3, 10);\n i += 3;\n }\n else if (i + 1 < length) {\n // Encode two numeric letters in seven bits.\n const num2 = Encoder.getDigit(content.charAt(i + 1));\n bits.appendBits(num1 * 10 + num2, 7);\n i += 2;\n }\n else {\n // Encode one numeric letter in four bits.\n bits.appendBits(num1, 4);\n i++;\n }\n }\n }\n static appendAlphanumericBytes(content, bits) {\n const length = content.length;\n let i = 0;\n while (i < length) {\n const code1 = Encoder.getAlphanumericCode(content.charCodeAt(i));\n if (code1 === -1) {\n throw new WriterException();\n }\n if (i + 1 < length) {\n const code2 = Encoder.getAlphanumericCode(content.charCodeAt(i + 1));\n if (code2 === -1) {\n throw new WriterException();\n }\n // Encode two alphanumeric letters in 11 bits.\n bits.appendBits(code1 * 45 + code2, 11);\n i += 2;\n }\n else {\n // Encode one alphanumeric letter in six bits.\n bits.appendBits(code1, 6);\n i++;\n }\n }\n }\n static append8BitBytes(content, bits, encoding) {\n let bytes;\n try {\n bytes = StringEncoding.encode(content, encoding);\n }\n catch (uee /*: UnsupportedEncodingException*/) {\n throw new WriterException(uee);\n }\n for (let i = 0, length = bytes.length; i !== length; i++) {\n const b = bytes[i];\n bits.appendBits(b, 8);\n }\n }\n /**\n * @throws WriterException\n */\n static appendKanjiBytes(content, bits) {\n let bytes;\n try {\n bytes = StringEncoding.encode(content, CharacterSetECI.SJIS);\n }\n catch (uee /*: UnsupportedEncodingException*/) {\n throw new WriterException(uee);\n }\n const length = bytes.length;\n for (let i = 0; i < length; i += 2) {\n const byte1 = bytes[i] & 0xFF;\n const byte2 = bytes[i + 1] & 0xFF;\n const code = ((byte1 << 8) & 0xFFFFFFFF) | byte2;\n let subtracted = -1;\n if (code >= 0x8140 && code <= 0x9ffc) {\n subtracted = code - 0x8140;\n }\n else if (code >= 0xe040 && code <= 0xebbf) {\n subtracted = code - 0xc140;\n }\n if (subtracted === -1) {\n throw new WriterException('Invalid byte sequence');\n }\n const encoded = ((subtracted >> 8) * 0xc0) + (subtracted & 0xff);\n bits.appendBits(encoded, 13);\n }\n }\n static appendECI(eci, bits) {\n bits.appendBits(Mode$1.ECI.getBits(), 4);\n // This is correct for values up to 127, which is all we need now.\n bits.appendBits(eci.getValue(), 8);\n }\n }\n // The original table is defined in the table 5 of JISX0510:2004 (p.19).\n Encoder.ALPHANUMERIC_TABLE = Int32Array.from([\n -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n 36, -1, -1, -1, 37, 38, -1, -1, -1, -1, 39, 40, -1, 41, 42, 43,\n 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 44, -1, -1, -1, -1, -1,\n -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,\n 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1,\n ]);\n Encoder.DEFAULT_BYTE_MODE_ENCODING = CharacterSetECI.UTF8.getName(); // \"ISO-8859-1\"\n\n /**\n * @deprecated Moving to @zxing/browser\n */\n class BrowserQRCodeSvgWriter {\n /**\n * Writes and renders a QRCode SVG element.\n *\n * @param contents\n * @param width\n * @param height\n * @param hints\n */\n write(contents, width, height, hints = null) {\n if (contents.length === 0) {\n throw new IllegalArgumentException('Found empty contents');\n }\n // if (format != BarcodeFormat.QR_CODE) {\n // throw new IllegalArgumentException(\"Can only encode QR_CODE, but got \" + format)\n // }\n if (width < 0 || height < 0) {\n throw new IllegalArgumentException('Requested dimensions are too small: ' + width + 'x' + height);\n }\n let errorCorrectionLevel = ErrorCorrectionLevel.L;\n let quietZone = BrowserQRCodeSvgWriter.QUIET_ZONE_SIZE;\n if (hints !== null) {\n if (undefined !== hints.get(EncodeHintType$1.ERROR_CORRECTION)) {\n errorCorrectionLevel = ErrorCorrectionLevel.fromString(hints.get(EncodeHintType$1.ERROR_CORRECTION).toString());\n }\n if (undefined !== hints.get(EncodeHintType$1.MARGIN)) {\n quietZone = Number.parseInt(hints.get(EncodeHintType$1.MARGIN).toString(), 10);\n }\n }\n const code = Encoder.encode(contents, errorCorrectionLevel, hints);\n return this.renderResult(code, width, height, quietZone);\n }\n /**\n * Renders the result and then appends it to the DOM.\n */\n writeToDom(containerElement, contents, width, height, hints = null) {\n if (typeof containerElement === 'string') {\n containerElement = document.querySelector(containerElement);\n }\n const svgElement = this.write(contents, width, height, hints);\n if (containerElement)\n containerElement.appendChild(svgElement);\n }\n /**\n * Note that the input matrix uses 0 == white, 1 == black.\n * The output matrix uses 0 == black, 255 == white (i.e. an 8 bit greyscale bitmap).\n */\n renderResult(code, width /*int*/, height /*int*/, quietZone /*int*/) {\n const input = code.getMatrix();\n if (input === null) {\n throw new IllegalStateException();\n }\n const inputWidth = input.getWidth();\n const inputHeight = input.getHeight();\n const qrWidth = inputWidth + (quietZone * 2);\n const qrHeight = inputHeight + (quietZone * 2);\n const outputWidth = Math.max(width, qrWidth);\n const outputHeight = Math.max(height, qrHeight);\n const multiple = Math.min(Math.floor(outputWidth / qrWidth), Math.floor(outputHeight / qrHeight));\n // Padding includes both the quiet zone and the extra white pixels to accommodate the requested\n // dimensions. For example, if input is 25x25 the QR will be 33x33 including the quiet zone.\n // If the requested size is 200x160, the multiple will be 4, for a QR of 132x132. These will\n // handle all the padding from 100x100 (the actual QR) up to 200x160.\n const leftPadding = Math.floor((outputWidth - (inputWidth * multiple)) / 2);\n const topPadding = Math.floor((outputHeight - (inputHeight * multiple)) / 2);\n const svgElement = this.createSVGElement(outputWidth, outputHeight);\n for (let inputY = 0, outputY = topPadding; inputY < inputHeight; inputY++, outputY += multiple) {\n // Write the contents of this row of the barcode\n for (let inputX = 0, outputX = leftPadding; inputX < inputWidth; inputX++, outputX += multiple) {\n if (input.get(inputX, inputY) === 1) {\n const svgRectElement = this.createSvgRectElement(outputX, outputY, multiple, multiple);\n svgElement.appendChild(svgRectElement);\n }\n }\n }\n return svgElement;\n }\n /**\n * Creates a SVG element.\n *\n * @param w SVG's width attribute\n * @param h SVG's height attribute\n */\n createSVGElement(w, h) {\n const svgElement = document.createElementNS(BrowserQRCodeSvgWriter.SVG_NS, 'svg');\n svgElement.setAttributeNS(null, 'height', w.toString());\n svgElement.setAttributeNS(null, 'width', h.toString());\n return svgElement;\n }\n /**\n * Creates a SVG rect element.\n *\n * @param x Element's x coordinate\n * @param y Element's y coordinate\n * @param w Element's width attribute\n * @param h Element's height attribute\n */\n createSvgRectElement(x, y, w, h) {\n const rect = document.createElementNS(BrowserQRCodeSvgWriter.SVG_NS, 'rect');\n rect.setAttributeNS(null, 'x', x.toString());\n rect.setAttributeNS(null, 'y', y.toString());\n rect.setAttributeNS(null, 'height', w.toString());\n rect.setAttributeNS(null, 'width', h.toString());\n rect.setAttributeNS(null, 'fill', '#000000');\n return rect;\n }\n }\n BrowserQRCodeSvgWriter.QUIET_ZONE_SIZE = 4;\n /**\n * SVG markup NameSpace\n */\n BrowserQRCodeSvgWriter.SVG_NS = 'http://www.w3.org/2000/svg';\n\n /*import java.util.Map;*/\n /**\n * This object renders a QR Code as a BitMatrix 2D array of greyscale values.\n *\n * @author dswitkin@google.com (Daniel Switkin)\n */\n class QRCodeWriter {\n /*@Override*/\n // public encode(contents: string, format: BarcodeFormat, width: number /*int*/, height: number /*int*/): BitMatrix\n // /*throws WriterException */ {\n // return encode(contents, format, width, height, null)\n // }\n /*@Override*/\n encode(contents, format, width /*int*/, height /*int*/, hints) {\n if (contents.length === 0) {\n throw new IllegalArgumentException('Found empty contents');\n }\n if (format !== BarcodeFormat$1.QR_CODE) {\n throw new IllegalArgumentException('Can only encode QR_CODE, but got ' + format);\n }\n if (width < 0 || height < 0) {\n throw new IllegalArgumentException(`Requested dimensions are too small: ${width}x${height}`);\n }\n let errorCorrectionLevel = ErrorCorrectionLevel.L;\n let quietZone = QRCodeWriter.QUIET_ZONE_SIZE;\n if (hints !== null) {\n if (undefined !== hints.get(EncodeHintType$1.ERROR_CORRECTION)) {\n errorCorrectionLevel = ErrorCorrectionLevel.fromString(hints.get(EncodeHintType$1.ERROR_CORRECTION).toString());\n }\n if (undefined !== hints.get(EncodeHintType$1.MARGIN)) {\n quietZone = Number.parseInt(hints.get(EncodeHintType$1.MARGIN).toString(), 10);\n }\n }\n const code = Encoder.encode(contents, errorCorrectionLevel, hints);\n return QRCodeWriter.renderResult(code, width, height, quietZone);\n }\n // Note that the input matrix uses 0 == white, 1 == black, while the output matrix uses\n // 0 == black, 255 == white (i.e. an 8 bit greyscale bitmap).\n static renderResult(code, width /*int*/, height /*int*/, quietZone /*int*/) {\n const input = code.getMatrix();\n if (input === null) {\n throw new IllegalStateException();\n }\n const inputWidth = input.getWidth();\n const inputHeight = input.getHeight();\n const qrWidth = inputWidth + (quietZone * 2);\n const qrHeight = inputHeight + (quietZone * 2);\n const outputWidth = Math.max(width, qrWidth);\n const outputHeight = Math.max(height, qrHeight);\n const multiple = Math.min(Math.floor(outputWidth / qrWidth), Math.floor(outputHeight / qrHeight));\n // Padding includes both the quiet zone and the extra white pixels to accommodate the requested\n // dimensions. For example, if input is 25x25 the QR will be 33x33 including the quiet zone.\n // If the requested size is 200x160, the multiple will be 4, for a QR of 132x132. These will\n // handle all the padding from 100x100 (the actual QR) up to 200x160.\n const leftPadding = Math.floor((outputWidth - (inputWidth * multiple)) / 2);\n const topPadding = Math.floor((outputHeight - (inputHeight * multiple)) / 2);\n const output = new BitMatrix(outputWidth, outputHeight);\n for (let inputY = 0, outputY = topPadding; inputY < inputHeight; inputY++, outputY += multiple) {\n // Write the contents of this row of the barcode\n for (let inputX = 0, outputX = leftPadding; inputX < inputWidth; inputX++, outputX += multiple) {\n if (input.get(inputX, inputY) === 1) {\n output.setRegion(outputX, outputY, multiple, multiple);\n }\n }\n }\n return output;\n }\n }\n QRCodeWriter.QUIET_ZONE_SIZE = 4;\n\n /*import java.util.Map;*/\n /**\n * This is a factory class which finds the appropriate Writer subclass for the BarcodeFormat\n * requested and encodes the barcode with the supplied contents.\n *\n * @author dswitkin@google.com (Daniel Switkin)\n */\n class MultiFormatWriter {\n /*@Override*/\n // public encode(contents: string,\n // format: BarcodeFormat,\n // width: number /*int*/,\n // height: number /*int*/): BitMatrix /*throws WriterException */ {\n // return encode(contents, format, width, height, null)\n // }\n /*@Override*/\n encode(contents, format, width /*int*/, height /*int*/, hints) {\n let writer;\n switch (format) {\n // case BarcodeFormat.EAN_8:\n // writer = new EAN8Writer()\n // break\n // case BarcodeFormat.UPC_E:\n // writer = new UPCEWriter()\n // break\n // case BarcodeFormat.EAN_13:\n // writer = new EAN13Writer()\n // break\n // case BarcodeFormat.UPC_A:\n // writer = new UPCAWriter()\n // break\n case BarcodeFormat$1.QR_CODE:\n writer = new QRCodeWriter();\n break;\n // case BarcodeFormat.CODE_39:\n // writer = new Code39Writer()\n // break\n // case BarcodeFormat.CODE_93:\n // writer = new Code93Writer()\n // break\n // case BarcodeFormat.CODE_128:\n // writer = new Code128Writer()\n // break\n // case BarcodeFormat.ITF:\n // writer = new ITFWriter()\n // break\n // case BarcodeFormat.PDF_417:\n // writer = new PDF417Writer()\n // break\n // case BarcodeFormat.CODABAR:\n // writer = new CodaBarWriter()\n // break\n // case BarcodeFormat.DATA_MATRIX:\n // writer = new DataMatrixWriter()\n // break\n // case BarcodeFormat.AZTEC:\n // writer = new AztecWriter()\n // break\n default:\n throw new IllegalArgumentException('No encoder available for format ' + format);\n }\n return writer.encode(contents, format, width, height, hints);\n }\n }\n\n /*\n * Copyright 2009 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n /**\n * This object extends LuminanceSource around an array of YUV data returned from the camera driver,\n * with the option to crop to a rectangle within the full data. This can be used to exclude\n * superfluous pixels around the perimeter and speed up decoding.\n *\n * It works for any pixel format where the Y channel is planar and appears first, including\n * YCbCr_420_SP and YCbCr_422_SP.\n *\n * @author dswitkin@google.com (Daniel Switkin)\n */\n class PlanarYUVLuminanceSource extends LuminanceSource {\n constructor(yuvData, dataWidth /*int*/, dataHeight /*int*/, left /*int*/, top /*int*/, width /*int*/, height /*int*/, reverseHorizontal) {\n super(width, height);\n this.yuvData = yuvData;\n this.dataWidth = dataWidth;\n this.dataHeight = dataHeight;\n this.left = left;\n this.top = top;\n if (left + width > dataWidth || top + height > dataHeight) {\n throw new IllegalArgumentException('Crop rectangle does not fit within image data.');\n }\n if (reverseHorizontal) {\n this.reverseHorizontal(width, height);\n }\n }\n /*@Override*/\n getRow(y /*int*/, row) {\n if (y < 0 || y >= this.getHeight()) {\n throw new IllegalArgumentException('Requested row is outside the image: ' + y);\n }\n const width = this.getWidth();\n if (row === null || row === undefined || row.length < width) {\n row = new Uint8ClampedArray(width);\n }\n const offset = (y + this.top) * this.dataWidth + this.left;\n System.arraycopy(this.yuvData, offset, row, 0, width);\n return row;\n }\n /*@Override*/\n getMatrix() {\n const width = this.getWidth();\n const height = this.getHeight();\n // If the caller asks for the entire underlying image, save the copy and give them the\n // original data. The docs specifically warn that result.length must be ignored.\n if (width === this.dataWidth && height === this.dataHeight) {\n return this.yuvData;\n }\n const area = width * height;\n const matrix = new Uint8ClampedArray(area);\n let inputOffset = this.top * this.dataWidth + this.left;\n // If the width matches the full width of the underlying data, perform a single copy.\n if (width === this.dataWidth) {\n System.arraycopy(this.yuvData, inputOffset, matrix, 0, area);\n return matrix;\n }\n // Otherwise copy one cropped row at a time.\n for (let y = 0; y < height; y++) {\n const outputOffset = y * width;\n System.arraycopy(this.yuvData, inputOffset, matrix, outputOffset, width);\n inputOffset += this.dataWidth;\n }\n return matrix;\n }\n /*@Override*/\n isCropSupported() {\n return true;\n }\n /*@Override*/\n crop(left /*int*/, top /*int*/, width /*int*/, height /*int*/) {\n return new PlanarYUVLuminanceSource(this.yuvData, this.dataWidth, this.dataHeight, this.left + left, this.top + top, width, height, false);\n }\n renderThumbnail() {\n const width = this.getWidth() / PlanarYUVLuminanceSource.THUMBNAIL_SCALE_FACTOR;\n const height = this.getHeight() / PlanarYUVLuminanceSource.THUMBNAIL_SCALE_FACTOR;\n const pixels = new Int32Array(width * height);\n const yuv = this.yuvData;\n let inputOffset = this.top * this.dataWidth + this.left;\n for (let y = 0; y < height; y++) {\n const outputOffset = y * width;\n for (let x = 0; x < width; x++) {\n const grey = yuv[inputOffset + x * PlanarYUVLuminanceSource.THUMBNAIL_SCALE_FACTOR] & 0xff;\n pixels[outputOffset + x] = 0xFF000000 | (grey * 0x00010101);\n }\n inputOffset += this.dataWidth * PlanarYUVLuminanceSource.THUMBNAIL_SCALE_FACTOR;\n }\n return pixels;\n }\n /**\n * @return width of image from {@link #renderThumbnail()}\n */\n getThumbnailWidth() {\n return this.getWidth() / PlanarYUVLuminanceSource.THUMBNAIL_SCALE_FACTOR;\n }\n /**\n * @return height of image from {@link #renderThumbnail()}\n */\n getThumbnailHeight() {\n return this.getHeight() / PlanarYUVLuminanceSource.THUMBNAIL_SCALE_FACTOR;\n }\n reverseHorizontal(width /*int*/, height /*int*/) {\n const yuvData = this.yuvData;\n for (let y = 0, rowStart = this.top * this.dataWidth + this.left; y < height; y++, rowStart += this.dataWidth) {\n const middle = rowStart + width / 2;\n for (let x1 = rowStart, x2 = rowStart + width - 1; x1 < middle; x1++, x2--) {\n const temp = yuvData[x1];\n yuvData[x1] = yuvData[x2];\n yuvData[x2] = temp;\n }\n }\n }\n invert() {\n return new InvertedLuminanceSource(this);\n }\n }\n PlanarYUVLuminanceSource.THUMBNAIL_SCALE_FACTOR = 2;\n\n /*\n * Copyright 2009 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n /**\n * This class is used to help decode images from files which arrive as RGB data from\n * an ARGB pixel array. It does not support rotation.\n *\n * @author dswitkin@google.com (Daniel Switkin)\n * @author Betaminos\n */\n class RGBLuminanceSource extends LuminanceSource {\n constructor(luminances, width /*int*/, height /*int*/, dataWidth /*int*/, dataHeight /*int*/, left /*int*/, top /*int*/) {\n super(width, height);\n this.dataWidth = dataWidth;\n this.dataHeight = dataHeight;\n this.left = left;\n this.top = top;\n if (luminances.BYTES_PER_ELEMENT === 4) { // Int32Array\n const size = width * height;\n const luminancesUint8Array = new Uint8ClampedArray(size);\n for (let offset = 0; offset < size; offset++) {\n const pixel = luminances[offset];\n const r = (pixel >> 16) & 0xff; // red\n const g2 = (pixel >> 7) & 0x1fe; // 2 * green\n const b = pixel & 0xff; // blue\n // Calculate green-favouring average cheaply\n luminancesUint8Array[offset] = /*(byte) */ ((r + g2 + b) / 4) & 0xFF;\n }\n this.luminances = luminancesUint8Array;\n }\n else {\n this.luminances = luminances;\n }\n if (undefined === dataWidth) {\n this.dataWidth = width;\n }\n if (undefined === dataHeight) {\n this.dataHeight = height;\n }\n if (undefined === left) {\n this.left = 0;\n }\n if (undefined === top) {\n this.top = 0;\n }\n if (this.left + width > this.dataWidth || this.top + height > this.dataHeight) {\n throw new IllegalArgumentException('Crop rectangle does not fit within image data.');\n }\n }\n /*@Override*/\n getRow(y /*int*/, row) {\n if (y < 0 || y >= this.getHeight()) {\n throw new IllegalArgumentException('Requested row is outside the image: ' + y);\n }\n const width = this.getWidth();\n if (row === null || row === undefined || row.length < width) {\n row = new Uint8ClampedArray(width);\n }\n const offset = (y + this.top) * this.dataWidth + this.left;\n System.arraycopy(this.luminances, offset, row, 0, width);\n return row;\n }\n /*@Override*/\n getMatrix() {\n const width = this.getWidth();\n const height = this.getHeight();\n // If the caller asks for the entire underlying image, save the copy and give them the\n // original data. The docs specifically warn that result.length must be ignored.\n if (width === this.dataWidth && height === this.dataHeight) {\n return this.luminances;\n }\n const area = width * height;\n const matrix = new Uint8ClampedArray(area);\n let inputOffset = this.top * this.dataWidth + this.left;\n // If the width matches the full width of the underlying data, perform a single copy.\n if (width === this.dataWidth) {\n System.arraycopy(this.luminances, inputOffset, matrix, 0, area);\n return matrix;\n }\n // Otherwise copy one cropped row at a time.\n for (let y = 0; y < height; y++) {\n const outputOffset = y * width;\n System.arraycopy(this.luminances, inputOffset, matrix, outputOffset, width);\n inputOffset += this.dataWidth;\n }\n return matrix;\n }\n /*@Override*/\n isCropSupported() {\n return true;\n }\n /*@Override*/\n crop(left /*int*/, top /*int*/, width /*int*/, height /*int*/) {\n return new RGBLuminanceSource(this.luminances, width, height, this.dataWidth, this.dataHeight, this.left + left, this.top + top);\n }\n invert() {\n return new InvertedLuminanceSource(this);\n }\n }\n\n /**\n * Just to make a shortcut between Java code and TS code.\n */\n class Charset extends CharacterSetECI {\n static forName(name) {\n return this.getCharacterSetECIByName(name);\n }\n }\n\n /**\n * Just to make a shortcut between Java code and TS code.\n */\n class StandardCharsets {\n }\n StandardCharsets.ISO_8859_1 = CharacterSetECI.ISO8859_1;\n\n /*\n * Copyright 2013 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n /**\n * Aztec 2D code representation\n *\n * @author Rustam Abdullaev\n */\n /*public final*/ class AztecCode {\n /**\n * @return {@code true} if compact instead of full mode\n */\n isCompact() {\n return this.compact;\n }\n setCompact(compact) {\n this.compact = compact;\n }\n /**\n * @return size in pixels (width and height)\n */\n getSize() {\n return this.size;\n }\n setSize(size) {\n this.size = size;\n }\n /**\n * @return number of levels\n */\n getLayers() {\n return this.layers;\n }\n setLayers(layers) {\n this.layers = layers;\n }\n /**\n * @return number of data codewords\n */\n getCodeWords() {\n return this.codeWords;\n }\n setCodeWords(codeWords) {\n this.codeWords = codeWords;\n }\n /**\n * @return the symbol image\n */\n getMatrix() {\n return this.matrix;\n }\n setMatrix(matrix) {\n this.matrix = matrix;\n }\n }\n\n class Collections {\n /**\n * The singletonList(T) method is used to return an immutable list containing only the specified object.\n */\n static singletonList(item) {\n return [item];\n }\n /**\n * The min(Collection, Comparator) method is used to return the minimum element of the given collection, according to the order induced by the specified comparator.\n */\n static min(collection, comparator) {\n return collection.sort(comparator)[0];\n }\n }\n\n /*\n * Copyright 2013 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n class Token {\n constructor(previous) {\n this.previous = previous;\n }\n getPrevious() {\n return this.previous;\n }\n }\n\n /*\n * Copyright 2013 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n /*final*/ class SimpleToken extends Token {\n constructor(previous, value, bitCount) {\n super(previous);\n this.value = value;\n this.bitCount = bitCount;\n }\n /**\n * @Override\n */\n appendTo(bitArray, text) {\n bitArray.appendBits(this.value, this.bitCount);\n }\n add(value, bitCount) {\n return new SimpleToken(this, value, bitCount);\n }\n addBinaryShift(start, byteCount) {\n // no-op can't binary shift a simple token\n console.warn('addBinaryShift on SimpleToken, this simply returns a copy of this token');\n return new SimpleToken(this, start, byteCount);\n }\n /**\n * @Override\n */\n toString() {\n let value = this.value & ((1 << this.bitCount) - 1);\n value |= 1 << this.bitCount;\n return '<' + Integer.toBinaryString(value | (1 << this.bitCount)).substring(1) + '>';\n }\n }\n\n /*\n * Copyright 2013 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n /*final*/ class BinaryShiftToken extends SimpleToken {\n constructor(previous, binaryShiftStart, binaryShiftByteCount) {\n super(previous, 0, 0);\n this.binaryShiftStart = binaryShiftStart;\n this.binaryShiftByteCount = binaryShiftByteCount;\n }\n /**\n * @Override\n */\n appendTo(bitArray, text) {\n for (let i = 0; i < this.binaryShiftByteCount; i++) {\n if (i === 0 || (i === 31 && this.binaryShiftByteCount <= 62)) {\n // We need a header before the first character, and before\n // character 31 when the total byte code is <= 62\n bitArray.appendBits(31, 5); // BINARY_SHIFT\n if (this.binaryShiftByteCount > 62) {\n bitArray.appendBits(this.binaryShiftByteCount - 31, 16);\n }\n else if (i === 0) {\n // 1 <= binaryShiftByteCode <= 62\n bitArray.appendBits(Math.min(this.binaryShiftByteCount, 31), 5);\n }\n else {\n // 32 <= binaryShiftCount <= 62 and i == 31\n bitArray.appendBits(this.binaryShiftByteCount - 31, 5);\n }\n }\n bitArray.appendBits(text[this.binaryShiftStart + i], 8);\n }\n }\n addBinaryShift(start, byteCount) {\n // int bitCount = (byteCount * 8) + (byteCount <= 31 ? 10 : byteCount <= 62 ? 20 : 21);\n return new BinaryShiftToken(this, start, byteCount);\n }\n /**\n * @Override\n */\n toString() {\n return '<' + this.binaryShiftStart + '::' + (this.binaryShiftStart + this.binaryShiftByteCount - 1) + '>';\n }\n }\n\n function addBinaryShift(token, start, byteCount) {\n // int bitCount = (byteCount * 8) + (byteCount <= 31 ? 10 : byteCount <= 62 ? 20 : 21);\n return new BinaryShiftToken(token, start, byteCount);\n }\n function add(token, value, bitCount) {\n return new SimpleToken(token, value, bitCount);\n }\n\n const /*final*/ MODE_NAMES = [\n 'UPPER',\n 'LOWER',\n 'DIGIT',\n 'MIXED',\n 'PUNCT'\n ];\n const /*final*/ MODE_UPPER = 0; // 5 bits\n const /*final*/ MODE_LOWER = 1; // 5 bits\n const /*final*/ MODE_DIGIT = 2; // 4 bits\n const /*final*/ MODE_MIXED = 3; // 5 bits\n const /*final*/ MODE_PUNCT = 4; // 5 bits\n const EMPTY_TOKEN = new SimpleToken(null, 0, 0);\n\n // The Latch Table shows, for each pair of Modes, the optimal method for\n // getting from one mode to another. In the worst possible case, this can\n // be up to 14 bits. In the best possible case, we are already there!\n // The high half-word of each entry gives the number of bits.\n // The low half-word of each entry are the actual bits necessary to change\n const LATCH_TABLE = [\n Int32Array.from([\n 0,\n (5 << 16) + 28,\n (5 << 16) + 30,\n (5 << 16) + 29,\n (10 << 16) + (29 << 5) + 30 // UPPER -> MIXED -> PUNCT\n ]),\n Int32Array.from([\n (9 << 16) + (30 << 4) + 14,\n 0,\n (5 << 16) + 30,\n (5 << 16) + 29,\n (10 << 16) + (29 << 5) + 30 // LOWER -> MIXED -> PUNCT\n ]),\n Int32Array.from([\n (4 << 16) + 14,\n (9 << 16) + (14 << 5) + 28,\n 0,\n (9 << 16) + (14 << 5) + 29,\n (14 << 16) + (14 << 10) + (29 << 5) + 30\n // DIGIT -> UPPER -> MIXED -> PUNCT\n ]),\n Int32Array.from([\n (5 << 16) + 29,\n (5 << 16) + 28,\n (10 << 16) + (29 << 5) + 30,\n 0,\n (5 << 16) + 30 // MIXED -> PUNCT\n ]),\n Int32Array.from([\n (5 << 16) + 31,\n (10 << 16) + (31 << 5) + 28,\n (10 << 16) + (31 << 5) + 30,\n (10 << 16) + (31 << 5) + 29,\n 0\n ])\n ];\n\n function static_SHIFT_TABLE(SHIFT_TABLE) {\n for (let table /*Int32Array*/ of SHIFT_TABLE) {\n Arrays.fill(table, -1);\n }\n SHIFT_TABLE[MODE_UPPER][MODE_PUNCT] = 0;\n SHIFT_TABLE[MODE_LOWER][MODE_PUNCT] = 0;\n SHIFT_TABLE[MODE_LOWER][MODE_UPPER] = 28;\n SHIFT_TABLE[MODE_MIXED][MODE_PUNCT] = 0;\n SHIFT_TABLE[MODE_DIGIT][MODE_PUNCT] = 0;\n SHIFT_TABLE[MODE_DIGIT][MODE_UPPER] = 15;\n return SHIFT_TABLE;\n }\n const /*final*/ SHIFT_TABLE = static_SHIFT_TABLE(Arrays.createInt32Array(6, 6)); // mode shift codes, per table\n\n /*\n * Copyright 2013 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n /**\n * State represents all information about a sequence necessary to generate the current output.\n * Note that a state is immutable.\n */\n /*final*/ class State {\n constructor(token, mode, binaryBytes, bitCount) {\n this.token = token;\n this.mode = mode;\n this.binaryShiftByteCount = binaryBytes;\n this.bitCount = bitCount;\n // Make sure we match the token\n // int binaryShiftBitCount = (binaryShiftByteCount * 8) +\n // (binaryShiftByteCount === 0 ? 0 :\n // binaryShiftByteCount <= 31 ? 10 :\n // binaryShiftByteCount <= 62 ? 20 : 21);\n // assert this.bitCount === token.getTotalBitCount() + binaryShiftBitCount;\n }\n getMode() {\n return this.mode;\n }\n getToken() {\n return this.token;\n }\n getBinaryShiftByteCount() {\n return this.binaryShiftByteCount;\n }\n getBitCount() {\n return this.bitCount;\n }\n // Create a new state representing this state with a latch to a (not\n // necessary different) mode, and then a code.\n latchAndAppend(mode, value) {\n // assert binaryShiftByteCount === 0;\n let bitCount = this.bitCount;\n let token = this.token;\n if (mode !== this.mode) {\n let latch = LATCH_TABLE[this.mode][mode];\n token = add(token, latch & 0xffff, latch >> 16);\n bitCount += latch >> 16;\n }\n let latchModeBitCount = mode === MODE_DIGIT ? 4 : 5;\n token = add(token, value, latchModeBitCount);\n return new State(token, mode, 0, bitCount + latchModeBitCount);\n }\n // Create a new state representing this state, with a temporary shift\n // to a different mode to output a single value.\n shiftAndAppend(mode, value) {\n // assert binaryShiftByteCount === 0 && this.mode !== mode;\n let token = this.token;\n let thisModeBitCount = this.mode === MODE_DIGIT ? 4 : 5;\n // Shifts exist only to UPPER and PUNCT, both with tokens size 5.\n token = add(token, SHIFT_TABLE[this.mode][mode], thisModeBitCount);\n token = add(token, value, 5);\n return new State(token, this.mode, 0, this.bitCount + thisModeBitCount + 5);\n }\n // Create a new state representing this state, but an additional character\n // output in Binary Shift mode.\n addBinaryShiftChar(index) {\n let token = this.token;\n let mode = this.mode;\n let bitCount = this.bitCount;\n if (this.mode === MODE_PUNCT || this.mode === MODE_DIGIT) {\n // assert binaryShiftByteCount === 0;\n let latch = LATCH_TABLE[mode][MODE_UPPER];\n token = add(token, latch & 0xffff, latch >> 16);\n bitCount += latch >> 16;\n mode = MODE_UPPER;\n }\n let deltaBitCount = this.binaryShiftByteCount === 0 || this.binaryShiftByteCount === 31\n ? 18\n : this.binaryShiftByteCount === 62\n ? 9\n : 8;\n let result = new State(token, mode, this.binaryShiftByteCount + 1, bitCount + deltaBitCount);\n if (result.binaryShiftByteCount === 2047 + 31) {\n // The string is as long as it's allowed to be. We should end it.\n result = result.endBinaryShift(index + 1);\n }\n return result;\n }\n // Create the state identical to this one, but we are no longer in\n // Binary Shift mode.\n endBinaryShift(index) {\n if (this.binaryShiftByteCount === 0) {\n return this;\n }\n let token = this.token;\n token = addBinaryShift(token, index - this.binaryShiftByteCount, this.binaryShiftByteCount);\n // assert token.getTotalBitCount() === this.bitCount;\n return new State(token, this.mode, 0, this.bitCount);\n }\n // Returns true if \"this\" state is better (equal: or) to be in than \"that\"\n // state under all possible circumstances.\n isBetterThanOrEqualTo(other) {\n let newModeBitCount = this.bitCount + (LATCH_TABLE[this.mode][other.mode] >> 16);\n if (this.binaryShiftByteCount < other.binaryShiftByteCount) {\n // add additional B/S encoding cost of other, if any\n newModeBitCount +=\n State.calculateBinaryShiftCost(other) -\n State.calculateBinaryShiftCost(this);\n }\n else if (this.binaryShiftByteCount > other.binaryShiftByteCount &&\n other.binaryShiftByteCount > 0) {\n // maximum possible additional cost (it: h)\n newModeBitCount += 10;\n }\n return newModeBitCount <= other.bitCount;\n }\n toBitArray(text) {\n // Reverse the tokens, so that they are in the order that they should\n // be output\n let symbols = [];\n for (let token = this.endBinaryShift(text.length).token; token !== null; token = token.getPrevious()) {\n symbols.unshift(token);\n }\n let bitArray = new BitArray();\n // Add each token to the result.\n for (const symbol of symbols) {\n symbol.appendTo(bitArray, text);\n }\n // assert bitArray.getSize() === this.bitCount;\n return bitArray;\n }\n /**\n * @Override\n */\n toString() {\n return StringUtils.format('%s bits=%d bytes=%d', MODE_NAMES[this.mode], this.bitCount, this.binaryShiftByteCount);\n }\n static calculateBinaryShiftCost(state) {\n if (state.binaryShiftByteCount > 62) {\n return 21; // B/S with extended length\n }\n if (state.binaryShiftByteCount > 31) {\n return 20; // two B/S\n }\n if (state.binaryShiftByteCount > 0) {\n return 10; // one B/S\n }\n return 0;\n }\n }\n State.INITIAL_STATE = new State(EMPTY_TOKEN, MODE_UPPER, 0, 0);\n\n function static_CHAR_MAP(CHAR_MAP) {\n const spaceCharCode = StringUtils.getCharCode(' ');\n const pointCharCode = StringUtils.getCharCode('.');\n const commaCharCode = StringUtils.getCharCode(',');\n CHAR_MAP[MODE_UPPER][spaceCharCode] = 1;\n const zUpperCharCode = StringUtils.getCharCode('Z');\n const aUpperCharCode = StringUtils.getCharCode('A');\n for (let c = aUpperCharCode; c <= zUpperCharCode; c++) {\n CHAR_MAP[MODE_UPPER][c] = c - aUpperCharCode + 2;\n }\n CHAR_MAP[MODE_LOWER][spaceCharCode] = 1;\n const zLowerCharCode = StringUtils.getCharCode('z');\n const aLowerCharCode = StringUtils.getCharCode('a');\n for (let c = aLowerCharCode; c <= zLowerCharCode; c++) {\n CHAR_MAP[MODE_LOWER][c] = c - aLowerCharCode + 2;\n }\n CHAR_MAP[MODE_DIGIT][spaceCharCode] = 1;\n const nineCharCode = StringUtils.getCharCode('9');\n const zeroCharCode = StringUtils.getCharCode('0');\n for (let c = zeroCharCode; c <= nineCharCode; c++) {\n CHAR_MAP[MODE_DIGIT][c] = c - zeroCharCode + 2;\n }\n CHAR_MAP[MODE_DIGIT][commaCharCode] = 12;\n CHAR_MAP[MODE_DIGIT][pointCharCode] = 13;\n const mixedTable = [\n '\\x00',\n ' ',\n '\\x01',\n '\\x02',\n '\\x03',\n '\\x04',\n '\\x05',\n '\\x06',\n '\\x07',\n '\\b',\n '\\t',\n '\\n',\n '\\x0b',\n '\\f',\n '\\r',\n '\\x1b',\n '\\x1c',\n '\\x1d',\n '\\x1e',\n '\\x1f',\n '@',\n '\\\\',\n '^',\n '_',\n '`',\n '|',\n '~',\n '\\x7f'\n ];\n for (let i = 0; i < mixedTable.length; i++) {\n CHAR_MAP[MODE_MIXED][StringUtils.getCharCode(mixedTable[i])] = i;\n }\n const punctTable = [\n '\\x00',\n '\\r',\n '\\x00',\n '\\x00',\n '\\x00',\n '\\x00',\n '!',\n '\\'',\n '#',\n '$',\n '%',\n '&',\n '\\'',\n '(',\n ')',\n '*',\n '+',\n ',',\n '-',\n '.',\n '/',\n ':',\n ';',\n '<',\n '=',\n '>',\n '?',\n '[',\n ']',\n '{',\n '}'\n ];\n for (let i = 0; i < punctTable.length; i++) {\n if (StringUtils.getCharCode(punctTable[i]) > 0) {\n CHAR_MAP[MODE_PUNCT][StringUtils.getCharCode(punctTable[i])] = i;\n }\n }\n return CHAR_MAP;\n }\n const CHAR_MAP = static_CHAR_MAP(Arrays.createInt32Array(5, 256));\n\n /*\n * Copyright 2013 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n /**\n * This produces nearly optimal encodings of text into the first-level of\n * encoding used by Aztec code.\n *\n * It uses a dynamic algorithm. For each prefix of the string, it determines\n * a set of encodings that could lead to this prefix. We repeatedly add a\n * character and generate a new set of optimal encodings until we have read\n * through the entire input.\n *\n * @author Frank Yellin\n * @author Rustam Abdullaev\n */\n /*public final*/ class HighLevelEncoder {\n constructor(text) {\n this.text = text;\n }\n /**\n * @return text represented by this encoder encoded as a {@link BitArray}\n */\n encode() {\n const spaceCharCode = StringUtils.getCharCode(' ');\n const lineBreakCharCode = StringUtils.getCharCode('\\n');\n let states = Collections.singletonList(State.INITIAL_STATE);\n for (let index = 0; index < this.text.length; index++) {\n let pairCode;\n let nextChar = index + 1 < this.text.length ? this.text[index + 1] : 0;\n switch (this.text[index]) {\n case StringUtils.getCharCode('\\r'):\n pairCode = nextChar === lineBreakCharCode ? 2 : 0;\n break;\n case StringUtils.getCharCode('.'):\n pairCode = nextChar === spaceCharCode ? 3 : 0;\n break;\n case StringUtils.getCharCode(','):\n pairCode = nextChar === spaceCharCode ? 4 : 0;\n break;\n case StringUtils.getCharCode(':'):\n pairCode = nextChar === spaceCharCode ? 5 : 0;\n break;\n default:\n pairCode = 0;\n }\n if (pairCode > 0) {\n // We have one of the four special PUNCT pairs. Treat them specially.\n // Get a new set of states for the two new characters.\n states = HighLevelEncoder.updateStateListForPair(states, index, pairCode);\n index++;\n }\n else {\n // Get a new set of states for the new character.\n states = this.updateStateListForChar(states, index);\n }\n }\n // We are left with a set of states. Find the shortest one.\n const minState = Collections.min(states, (a, b) => {\n return a.getBitCount() - b.getBitCount();\n });\n // Convert it to a bit array, and return.\n return minState.toBitArray(this.text);\n }\n // We update a set of states for a new character by updating each state\n // for the new character, merging the results, and then removing the\n // non-optimal states.\n updateStateListForChar(states, index) {\n const result = [];\n for (let state /*State*/ of states) {\n this.updateStateForChar(state, index, result);\n }\n return HighLevelEncoder.simplifyStates(result);\n }\n // Return a set of states that represent the possible ways of updating this\n // state for the next character. The resulting set of states are added to\n // the \"result\" list.\n updateStateForChar(state, index, result) {\n let ch = (this.text[index] & 0xff);\n let charInCurrentTable = CHAR_MAP[state.getMode()][ch] > 0;\n let stateNoBinary = null;\n for (let mode /*int*/ = 0; mode <= MODE_PUNCT; mode++) {\n let charInMode = CHAR_MAP[mode][ch];\n if (charInMode > 0) {\n if (stateNoBinary == null) {\n // Only create stateNoBinary the first time it's required.\n stateNoBinary = state.endBinaryShift(index);\n }\n // Try generating the character by latching to its mode\n if (!charInCurrentTable ||\n mode === state.getMode() ||\n mode === MODE_DIGIT) {\n // If the character is in the current table, we don't want to latch to\n // any other mode except possibly digit (which uses only 4 bits). Any\n // other latch would be equally successful *after* this character, and\n // so wouldn't save any bits.\n const latchState = stateNoBinary.latchAndAppend(mode, charInMode);\n result.push(latchState);\n }\n // Try generating the character by switching to its mode.\n if (!charInCurrentTable &&\n SHIFT_TABLE[state.getMode()][mode] >= 0) {\n // It never makes sense to temporarily shift to another mode if the\n // character exists in the current mode. That can never save bits.\n const shiftState = stateNoBinary.shiftAndAppend(mode, charInMode);\n result.push(shiftState);\n }\n }\n }\n if (state.getBinaryShiftByteCount() > 0 ||\n CHAR_MAP[state.getMode()][ch] === 0) {\n // It's never worthwhile to go into binary shift mode if you're not already\n // in binary shift mode, and the character exists in your current mode.\n // That can never save bits over just outputting the char in the current mode.\n let binaryState = state.addBinaryShiftChar(index);\n result.push(binaryState);\n }\n }\n static updateStateListForPair(states, index, pairCode) {\n const result = [];\n for (let state /*State*/ of states) {\n this.updateStateForPair(state, index, pairCode, result);\n }\n return this.simplifyStates(result);\n }\n static updateStateForPair(state, index, pairCode, result) {\n let stateNoBinary = state.endBinaryShift(index);\n // Possibility 1. Latch to C.MODE_PUNCT, and then append this code\n result.push(stateNoBinary.latchAndAppend(MODE_PUNCT, pairCode));\n if (state.getMode() !== MODE_PUNCT) {\n // Possibility 2. Shift to C.MODE_PUNCT, and then append this code.\n // Every state except C.MODE_PUNCT (handled above) can shift\n result.push(stateNoBinary.shiftAndAppend(MODE_PUNCT, pairCode));\n }\n if (pairCode === 3 || pairCode === 4) {\n // both characters are in DIGITS. Sometimes better to just add two digits\n let digitState = stateNoBinary\n .latchAndAppend(MODE_DIGIT, 16 - pairCode) // period or comma in DIGIT\n .latchAndAppend(MODE_DIGIT, 1); // space in DIGIT\n result.push(digitState);\n }\n if (state.getBinaryShiftByteCount() > 0) {\n // It only makes sense to do the characters as binary if we're already\n // in binary mode.\n let binaryState = state\n .addBinaryShiftChar(index)\n .addBinaryShiftChar(index + 1);\n result.push(binaryState);\n }\n }\n static simplifyStates(states) {\n let result = [];\n for (const newState of states) {\n let add = true;\n for (const oldState of result) {\n if (oldState.isBetterThanOrEqualTo(newState)) {\n add = false;\n break;\n }\n if (newState.isBetterThanOrEqualTo(oldState)) {\n // iterator.remove();\n result = result.filter(x => x !== oldState); // remove old state\n }\n }\n if (add) {\n result.push(newState);\n }\n }\n return result;\n }\n }\n\n /*\n * Copyright 2013 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n // package com.google.zxing.aztec.encoder;\n // import com.google.zxing.common.BitArray;\n // import com.google.zxing.common.BitMatrix;\n // import com.google.zxing.common.reedsolomon.GenericGF;\n // import com.google.zxing.common.reedsolomon.ReedSolomonEncoder;\n /**\n * Generates Aztec 2D barcodes.\n *\n * @author Rustam Abdullaev\n */\n /*public final*/ class Encoder$1 {\n constructor() {\n }\n /**\n * Encodes the given binary content as an Aztec symbol\n *\n * @param data input data string\n * @return Aztec symbol matrix with metadata\n */\n static encodeBytes(data) {\n return Encoder$1.encode(data, Encoder$1.DEFAULT_EC_PERCENT, Encoder$1.DEFAULT_AZTEC_LAYERS);\n }\n /**\n * Encodes the given binary content as an Aztec symbol\n *\n * @param data input data string\n * @param minECCPercent minimal percentage of error check words (According to ISO/IEC 24778:2008,\n * a minimum of 23% + 3 words is recommended)\n * @param userSpecifiedLayers if non-zero, a user-specified value for the number of layers\n * @return Aztec symbol matrix with metadata\n */\n static encode(data, minECCPercent, userSpecifiedLayers) {\n // High-level encode\n let bits = new HighLevelEncoder(data).encode();\n // stuff bits and choose symbol size\n let eccBits = Integer.truncDivision((bits.getSize() * minECCPercent), 100) + 11;\n let totalSizeBits = bits.getSize() + eccBits;\n let compact;\n let layers;\n let totalBitsInLayer;\n let wordSize;\n let stuffedBits;\n if (userSpecifiedLayers !== Encoder$1.DEFAULT_AZTEC_LAYERS) {\n compact = userSpecifiedLayers < 0;\n layers = Math.abs(userSpecifiedLayers);\n if (layers > (compact ? Encoder$1.MAX_NB_BITS_COMPACT : Encoder$1.MAX_NB_BITS)) {\n throw new IllegalArgumentException(StringUtils.format('Illegal value %s for layers', userSpecifiedLayers));\n }\n totalBitsInLayer = Encoder$1.totalBitsInLayer(layers, compact);\n wordSize = Encoder$1.WORD_SIZE[layers];\n let usableBitsInLayers = totalBitsInLayer - (totalBitsInLayer % wordSize);\n stuffedBits = Encoder$1.stuffBits(bits, wordSize);\n if (stuffedBits.getSize() + eccBits > usableBitsInLayers) {\n throw new IllegalArgumentException('Data to large for user specified layer');\n }\n if (compact && stuffedBits.getSize() > wordSize * 64) {\n // Compact format only allows 64 data words, though C4 can hold more words than that\n throw new IllegalArgumentException('Data to large for user specified layer');\n }\n }\n else {\n wordSize = 0;\n stuffedBits = null;\n // We look at the possible table sizes in the order Compact1, Compact2, Compact3,\n // Compact4, Normal4,... Normal(i) for i < 4 isn't typically used since Compact(i+1)\n // is the same size, but has more data.\n for (let i /*int*/ = 0;; i++) {\n if (i > Encoder$1.MAX_NB_BITS) {\n throw new IllegalArgumentException('Data too large for an Aztec code');\n }\n compact = i <= 3;\n layers = compact ? i + 1 : i;\n totalBitsInLayer = Encoder$1.totalBitsInLayer(layers, compact);\n if (totalSizeBits > totalBitsInLayer) {\n continue;\n }\n // [Re]stuff the bits if this is the first opportunity, or if the\n // wordSize has changed\n if (stuffedBits == null || wordSize !== Encoder$1.WORD_SIZE[layers]) {\n wordSize = Encoder$1.WORD_SIZE[layers];\n stuffedBits = Encoder$1.stuffBits(bits, wordSize);\n }\n let usableBitsInLayers = totalBitsInLayer - (totalBitsInLayer % wordSize);\n if (compact && stuffedBits.getSize() > wordSize * 64) {\n // Compact format only allows 64 data words, though C4 can hold more words than that\n continue;\n }\n if (stuffedBits.getSize() + eccBits <= usableBitsInLayers) {\n break;\n }\n }\n }\n let messageBits = Encoder$1.generateCheckWords(stuffedBits, totalBitsInLayer, wordSize);\n // generate mode message\n let messageSizeInWords = stuffedBits.getSize() / wordSize;\n let modeMessage = Encoder$1.generateModeMessage(compact, layers, messageSizeInWords);\n // allocate symbol\n let baseMatrixSize = (compact ? 11 : 14) + layers * 4; // not including alignment lines\n let alignmentMap = new Int32Array(baseMatrixSize);\n let matrixSize;\n if (compact) {\n // no alignment marks in compact mode, alignmentMap is a no-op\n matrixSize = baseMatrixSize;\n for (let i /*int*/ = 0; i < alignmentMap.length; i++) {\n alignmentMap[i] = i;\n }\n }\n else {\n matrixSize = baseMatrixSize + 1 + 2 * Integer.truncDivision((Integer.truncDivision(baseMatrixSize, 2) - 1), 15);\n let origCenter = Integer.truncDivision(baseMatrixSize, 2);\n let center = Integer.truncDivision(matrixSize, 2);\n for (let i /*int*/ = 0; i < origCenter; i++) {\n let newOffset = i + Integer.truncDivision(i, 15);\n alignmentMap[origCenter - i - 1] = center - newOffset - 1;\n alignmentMap[origCenter + i] = center + newOffset + 1;\n }\n }\n let matrix = new BitMatrix(matrixSize);\n // draw data bits\n for (let i /*int*/ = 0, rowOffset = 0; i < layers; i++) {\n let rowSize = (layers - i) * 4 + (compact ? 9 : 12);\n for (let j /*int*/ = 0; j < rowSize; j++) {\n let columnOffset = j * 2;\n for (let k /*int*/ = 0; k < 2; k++) {\n if (messageBits.get(rowOffset + columnOffset + k)) {\n matrix.set(alignmentMap[i * 2 + k], alignmentMap[i * 2 + j]);\n }\n if (messageBits.get(rowOffset + rowSize * 2 + columnOffset + k)) {\n matrix.set(alignmentMap[i * 2 + j], alignmentMap[baseMatrixSize - 1 - i * 2 - k]);\n }\n if (messageBits.get(rowOffset + rowSize * 4 + columnOffset + k)) {\n matrix.set(alignmentMap[baseMatrixSize - 1 - i * 2 - k], alignmentMap[baseMatrixSize - 1 - i * 2 - j]);\n }\n if (messageBits.get(rowOffset + rowSize * 6 + columnOffset + k)) {\n matrix.set(alignmentMap[baseMatrixSize - 1 - i * 2 - j], alignmentMap[i * 2 + k]);\n }\n }\n }\n rowOffset += rowSize * 8;\n }\n // draw mode message\n Encoder$1.drawModeMessage(matrix, compact, matrixSize, modeMessage);\n // draw alignment marks\n if (compact) {\n Encoder$1.drawBullsEye(matrix, Integer.truncDivision(matrixSize, 2), 5);\n }\n else {\n Encoder$1.drawBullsEye(matrix, Integer.truncDivision(matrixSize, 2), 7);\n for (let i /*int*/ = 0, j = 0; i < Integer.truncDivision(baseMatrixSize, 2) - 1; i += 15, j += 16) {\n for (let k /*int*/ = Integer.truncDivision(matrixSize, 2) & 1; k < matrixSize; k += 2) {\n matrix.set(Integer.truncDivision(matrixSize, 2) - j, k);\n matrix.set(Integer.truncDivision(matrixSize, 2) + j, k);\n matrix.set(k, Integer.truncDivision(matrixSize, 2) - j);\n matrix.set(k, Integer.truncDivision(matrixSize, 2) + j);\n }\n }\n }\n let aztec = new AztecCode();\n aztec.setCompact(compact);\n aztec.setSize(matrixSize);\n aztec.setLayers(layers);\n aztec.setCodeWords(messageSizeInWords);\n aztec.setMatrix(matrix);\n return aztec;\n }\n static drawBullsEye(matrix, center, size) {\n for (let i /*int*/ = 0; i < size; i += 2) {\n for (let j /*int*/ = center - i; j <= center + i; j++) {\n matrix.set(j, center - i);\n matrix.set(j, center + i);\n matrix.set(center - i, j);\n matrix.set(center + i, j);\n }\n }\n matrix.set(center - size, center - size);\n matrix.set(center - size + 1, center - size);\n matrix.set(center - size, center - size + 1);\n matrix.set(center + size, center - size);\n matrix.set(center + size, center - size + 1);\n matrix.set(center + size, center + size - 1);\n }\n static generateModeMessage(compact, layers, messageSizeInWords) {\n let modeMessage = new BitArray();\n if (compact) {\n modeMessage.appendBits(layers - 1, 2);\n modeMessage.appendBits(messageSizeInWords - 1, 6);\n modeMessage = Encoder$1.generateCheckWords(modeMessage, 28, 4);\n }\n else {\n modeMessage.appendBits(layers - 1, 5);\n modeMessage.appendBits(messageSizeInWords - 1, 11);\n modeMessage = Encoder$1.generateCheckWords(modeMessage, 40, 4);\n }\n return modeMessage;\n }\n static drawModeMessage(matrix, compact, matrixSize, modeMessage) {\n let center = Integer.truncDivision(matrixSize, 2);\n if (compact) {\n for (let i /*int*/ = 0; i < 7; i++) {\n let offset = center - 3 + i;\n if (modeMessage.get(i)) {\n matrix.set(offset, center - 5);\n }\n if (modeMessage.get(i + 7)) {\n matrix.set(center + 5, offset);\n }\n if (modeMessage.get(20 - i)) {\n matrix.set(offset, center + 5);\n }\n if (modeMessage.get(27 - i)) {\n matrix.set(center - 5, offset);\n }\n }\n }\n else {\n for (let i /*int*/ = 0; i < 10; i++) {\n let offset = center - 5 + i + Integer.truncDivision(i, 5);\n if (modeMessage.get(i)) {\n matrix.set(offset, center - 7);\n }\n if (modeMessage.get(i + 10)) {\n matrix.set(center + 7, offset);\n }\n if (modeMessage.get(29 - i)) {\n matrix.set(offset, center + 7);\n }\n if (modeMessage.get(39 - i)) {\n matrix.set(center - 7, offset);\n }\n }\n }\n }\n static generateCheckWords(bitArray, totalBits, wordSize) {\n // bitArray is guaranteed to be a multiple of the wordSize, so no padding needed\n let messageSizeInWords = bitArray.getSize() / wordSize;\n let rs = new ReedSolomonEncoder(Encoder$1.getGF(wordSize));\n let totalWords = Integer.truncDivision(totalBits, wordSize);\n let messageWords = Encoder$1.bitsToWords(bitArray, wordSize, totalWords);\n rs.encode(messageWords, totalWords - messageSizeInWords);\n let startPad = totalBits % wordSize;\n let messageBits = new BitArray();\n messageBits.appendBits(0, startPad);\n for (const messageWord /*: int*/ of Array.from(messageWords)) {\n messageBits.appendBits(messageWord, wordSize);\n }\n return messageBits;\n }\n static bitsToWords(stuffedBits, wordSize, totalWords) {\n let message = new Int32Array(totalWords);\n let i;\n let n;\n for (i = 0, n = stuffedBits.getSize() / wordSize; i < n; i++) {\n let value = 0;\n for (let j /*int*/ = 0; j < wordSize; j++) {\n value |= stuffedBits.get(i * wordSize + j) ? (1 << wordSize - j - 1) : 0;\n }\n message[i] = value;\n }\n return message;\n }\n static getGF(wordSize) {\n switch (wordSize) {\n case 4:\n return GenericGF.AZTEC_PARAM;\n case 6:\n return GenericGF.AZTEC_DATA_6;\n case 8:\n return GenericGF.AZTEC_DATA_8;\n case 10:\n return GenericGF.AZTEC_DATA_10;\n case 12:\n return GenericGF.AZTEC_DATA_12;\n default:\n throw new IllegalArgumentException('Unsupported word size ' + wordSize);\n }\n }\n static stuffBits(bits, wordSize) {\n let out = new BitArray();\n let n = bits.getSize();\n let mask = (1 << wordSize) - 2;\n for (let i /*int*/ = 0; i < n; i += wordSize) {\n let word = 0;\n for (let j /*int*/ = 0; j < wordSize; j++) {\n if (i + j >= n || bits.get(i + j)) {\n word |= 1 << (wordSize - 1 - j);\n }\n }\n if ((word & mask) === mask) {\n out.appendBits(word & mask, wordSize);\n i--;\n }\n else if ((word & mask) === 0) {\n out.appendBits(word | 1, wordSize);\n i--;\n }\n else {\n out.appendBits(word, wordSize);\n }\n }\n return out;\n }\n static totalBitsInLayer(layers, compact) {\n return ((compact ? 88 : 112) + 16 * layers) * layers;\n }\n }\n Encoder$1.DEFAULT_EC_PERCENT = 33; // default minimal percentage of error check words\n Encoder$1.DEFAULT_AZTEC_LAYERS = 0;\n Encoder$1.MAX_NB_BITS = 32;\n Encoder$1.MAX_NB_BITS_COMPACT = 4;\n Encoder$1.WORD_SIZE = Int32Array.from([\n 4, 6, 6, 8, 8, 8, 8, 8, 8, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,\n 12, 12, 12, 12, 12, 12, 12, 12, 12, 12\n ]);\n\n /*\n * Copyright 2013 ZXing authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n /**\n * Renders an Aztec code as a {@link BitMatrix}.\n */\n /*public final*/ class AztecWriter {\n // @Override\n encode(contents, format, width, height) {\n return this.encodeWithHints(contents, format, width, height, null);\n }\n // @Override\n encodeWithHints(contents, format, width, height, hints) {\n let charset = StandardCharsets.ISO_8859_1;\n let eccPercent = Encoder$1.DEFAULT_EC_PERCENT;\n let layers = Encoder$1.DEFAULT_AZTEC_LAYERS;\n if (hints != null) {\n if (hints.has(EncodeHintType$1.CHARACTER_SET)) {\n charset = Charset.forName(hints.get(EncodeHintType$1.CHARACTER_SET).toString());\n }\n if (hints.has(EncodeHintType$1.ERROR_CORRECTION)) {\n eccPercent = Integer.parseInt(hints.get(EncodeHintType$1.ERROR_CORRECTION).toString());\n }\n if (hints.has(EncodeHintType$1.AZTEC_LAYERS)) {\n layers = Integer.parseInt(hints.get(EncodeHintType$1.AZTEC_LAYERS).toString());\n }\n }\n return AztecWriter.encodeLayers(contents, format, width, height, charset, eccPercent, layers);\n }\n static encodeLayers(contents, format, width, height, charset, eccPercent, layers) {\n if (format !== BarcodeFormat$1.AZTEC) {\n throw new IllegalArgumentException('Can only encode AZTEC, but got ' + format);\n }\n let aztec = Encoder$1.encode(StringUtils.getBytes(contents, charset), eccPercent, layers);\n return AztecWriter.renderResult(aztec, width, height);\n }\n static renderResult(code, width, height) {\n let input = code.getMatrix();\n if (input == null) {\n throw new IllegalStateException();\n }\n let inputWidth = input.getWidth();\n let inputHeight = input.getHeight();\n let outputWidth = Math.max(width, inputWidth);\n let outputHeight = Math.max(height, inputHeight);\n let multiple = Math.min(outputWidth / inputWidth, outputHeight / inputHeight);\n let leftPadding = (outputWidth - (inputWidth * multiple)) / 2;\n let topPadding = (outputHeight - (inputHeight * multiple)) / 2;\n let output = new BitMatrix(outputWidth, outputHeight);\n for (let inputY /*int*/ = 0, outputY = topPadding; inputY < inputHeight; inputY++, outputY += multiple) {\n // Write the contents of this row of the barcode\n for (let inputX /*int*/ = 0, outputX = leftPadding; inputX < inputWidth; inputX++, outputX += multiple) {\n if (input.get(inputX, inputY)) {\n output.setRegion(outputX, outputY, multiple, multiple);\n }\n }\n }\n return output;\n }\n }\n\n exports.AbstractExpandedDecoder = AbstractExpandedDecoder;\n exports.ArgumentException = ArgumentException;\n exports.ArithmeticException = ArithmeticException;\n exports.AztecCode = AztecCode;\n exports.AztecCodeReader = AztecReader;\n exports.AztecCodeWriter = AztecWriter;\n exports.AztecDecoder = Decoder;\n exports.AztecDetector = Detector;\n exports.AztecDetectorResult = AztecDetectorResult;\n exports.AztecEncoder = Encoder$1;\n exports.AztecHighLevelEncoder = HighLevelEncoder;\n exports.AztecPoint = Point;\n exports.BarcodeFormat = BarcodeFormat$1;\n exports.Binarizer = Binarizer;\n exports.BinaryBitmap = BinaryBitmap;\n exports.BitArray = BitArray;\n exports.BitMatrix = BitMatrix;\n exports.BitSource = BitSource;\n exports.BrowserAztecCodeReader = BrowserAztecCodeReader;\n exports.BrowserBarcodeReader = BrowserBarcodeReader;\n exports.BrowserCodeReader = BrowserCodeReader;\n exports.BrowserDatamatrixCodeReader = BrowserDatamatrixCodeReader;\n exports.BrowserMultiFormatReader = BrowserMultiFormatReader;\n exports.BrowserPDF417Reader = BrowserPDF417Reader;\n exports.BrowserQRCodeReader = BrowserQRCodeReader;\n exports.BrowserQRCodeSvgWriter = BrowserQRCodeSvgWriter;\n exports.CharacterSetECI = CharacterSetECI;\n exports.ChecksumException = ChecksumException;\n exports.Code128Reader = Code128Reader;\n exports.Code39Reader = Code39Reader;\n exports.DataMatrixDecodedBitStreamParser = DecodedBitStreamParser;\n exports.DataMatrixReader = DataMatrixReader;\n exports.DecodeHintType = DecodeHintType$1;\n exports.DecoderResult = DecoderResult;\n exports.DefaultGridSampler = DefaultGridSampler;\n exports.DetectorResult = DetectorResult;\n exports.EAN13Reader = EAN13Reader;\n exports.EncodeHintType = EncodeHintType$1;\n exports.Exception = Exception;\n exports.FormatException = FormatException;\n exports.GenericGF = GenericGF;\n exports.GenericGFPoly = GenericGFPoly;\n exports.GlobalHistogramBinarizer = GlobalHistogramBinarizer;\n exports.GridSampler = GridSampler;\n exports.GridSamplerInstance = GridSamplerInstance;\n exports.HTMLCanvasElementLuminanceSource = HTMLCanvasElementLuminanceSource;\n exports.HybridBinarizer = HybridBinarizer;\n exports.ITFReader = ITFReader;\n exports.IllegalArgumentException = IllegalArgumentException;\n exports.IllegalStateException = IllegalStateException;\n exports.InvertedLuminanceSource = InvertedLuminanceSource;\n exports.LuminanceSource = LuminanceSource;\n exports.MathUtils = MathUtils;\n exports.MultiFormatOneDReader = MultiFormatOneDReader;\n exports.MultiFormatReader = MultiFormatReader;\n exports.MultiFormatWriter = MultiFormatWriter;\n exports.NotFoundException = NotFoundException;\n exports.OneDReader = OneDReader;\n exports.PDF417DecodedBitStreamParser = DecodedBitStreamParser$2;\n exports.PDF417DecoderErrorCorrection = ErrorCorrection;\n exports.PDF417Reader = PDF417Reader;\n exports.PDF417ResultMetadata = PDF417ResultMetadata;\n exports.PerspectiveTransform = PerspectiveTransform;\n exports.PlanarYUVLuminanceSource = PlanarYUVLuminanceSource;\n exports.QRCodeByteMatrix = ByteMatrix;\n exports.QRCodeDataMask = DataMask;\n exports.QRCodeDecodedBitStreamParser = DecodedBitStreamParser$1;\n exports.QRCodeDecoderErrorCorrectionLevel = ErrorCorrectionLevel;\n exports.QRCodeDecoderFormatInformation = FormatInformation;\n exports.QRCodeEncoder = Encoder;\n exports.QRCodeEncoderQRCode = QRCode;\n exports.QRCodeMaskUtil = MaskUtil;\n exports.QRCodeMatrixUtil = MatrixUtil;\n exports.QRCodeMode = Mode$1;\n exports.QRCodeReader = QRCodeReader;\n exports.QRCodeVersion = Version$1;\n exports.QRCodeWriter = QRCodeWriter;\n exports.RGBLuminanceSource = RGBLuminanceSource;\n exports.RSS14Reader = RSS14Reader;\n exports.RSSExpandedReader = RSSExpandedReader;\n exports.ReaderException = ReaderException;\n exports.ReedSolomonDecoder = ReedSolomonDecoder;\n exports.ReedSolomonEncoder = ReedSolomonEncoder;\n exports.ReedSolomonException = ReedSolomonException;\n exports.Result = Result;\n exports.ResultMetadataType = ResultMetadataType$1;\n exports.ResultPoint = ResultPoint;\n exports.StringUtils = StringUtils;\n exports.UnsupportedOperationException = UnsupportedOperationException;\n exports.VideoInputDevice = VideoInputDevice;\n exports.WhiteRectangleDetector = WhiteRectangleDetector;\n exports.WriterException = WriterException;\n exports.ZXingArrays = Arrays;\n exports.ZXingCharset = Charset;\n exports.ZXingInteger = Integer;\n exports.ZXingStandardCharsets = StandardCharsets;\n exports.ZXingStringBuilder = StringBuilder;\n exports.ZXingStringEncoding = StringEncoding;\n exports.ZXingSystem = System;\n exports.createAbstractExpandedDecoder = createDecoder;\n\n Object.defineProperty(exports, '__esModule', { value: true });\n\n})));\n", "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2014 Patrick Gansterer \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\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 THE\n * SOFTWARE.\n */\n\n(function(global, undefined) { \"use strict\";\nvar POW_2_24 = Math.pow(2, -24),\n POW_2_32 = Math.pow(2, 32),\n POW_2_53 = Math.pow(2, 53);\n\nfunction encode(value) {\n var data = new ArrayBuffer(256);\n var dataView = new DataView(data);\n var lastLength;\n var offset = 0;\n\n function ensureSpace(length) {\n var newByteLength = data.byteLength;\n var requiredLength = offset + length;\n while (newByteLength < requiredLength)\n newByteLength *= 2;\n if (newByteLength !== data.byteLength) {\n var oldDataView = dataView;\n data = new ArrayBuffer(newByteLength);\n dataView = new DataView(data);\n var uint32count = (offset + 3) >> 2;\n for (var i = 0; i < uint32count; ++i)\n dataView.setUint32(i * 4, oldDataView.getUint32(i * 4));\n }\n\n lastLength = length;\n return dataView;\n }\n function write() {\n offset += lastLength;\n }\n function writeFloat64(value) {\n write(ensureSpace(8).setFloat64(offset, value));\n }\n function writeUint8(value) {\n write(ensureSpace(1).setUint8(offset, value));\n }\n function writeUint8Array(value) {\n var dataView = ensureSpace(value.length);\n for (var i = 0; i < value.length; ++i)\n dataView.setUint8(offset + i, value[i]);\n write();\n }\n function writeUint16(value) {\n write(ensureSpace(2).setUint16(offset, value));\n }\n function writeUint32(value) {\n write(ensureSpace(4).setUint32(offset, value));\n }\n function writeUint64(value) {\n var low = value % POW_2_32;\n var high = (value - low) / POW_2_32;\n var dataView = ensureSpace(8);\n dataView.setUint32(offset, high);\n dataView.setUint32(offset + 4, low);\n write();\n }\n function writeTypeAndLength(type, length) {\n if (length < 24) {\n writeUint8(type << 5 | length);\n } else if (length < 0x100) {\n writeUint8(type << 5 | 24);\n writeUint8(length);\n } else if (length < 0x10000) {\n writeUint8(type << 5 | 25);\n writeUint16(length);\n } else if (length < 0x100000000) {\n writeUint8(type << 5 | 26);\n writeUint32(length);\n } else {\n writeUint8(type << 5 | 27);\n writeUint64(length);\n }\n }\n \n function encodeItem(value) {\n var i;\n\n if (value === false)\n return writeUint8(0xf4);\n if (value === true)\n return writeUint8(0xf5);\n if (value === null)\n return writeUint8(0xf6);\n if (value === undefined)\n return writeUint8(0xf7);\n \n switch (typeof value) {\n case \"number\":\n if (Math.floor(value) === value) {\n if (0 <= value && value <= POW_2_53)\n return writeTypeAndLength(0, value);\n if (-POW_2_53 <= value && value < 0)\n return writeTypeAndLength(1, -(value + 1));\n }\n writeUint8(0xfb);\n return writeFloat64(value);\n\n case \"string\":\n var utf8data = [];\n for (i = 0; i < value.length; ++i) {\n var charCode = value.charCodeAt(i);\n if (charCode < 0x80) {\n utf8data.push(charCode);\n } else if (charCode < 0x800) {\n utf8data.push(0xc0 | charCode >> 6);\n utf8data.push(0x80 | charCode & 0x3f);\n } else if (charCode < 0xd800) {\n utf8data.push(0xe0 | charCode >> 12);\n utf8data.push(0x80 | (charCode >> 6) & 0x3f);\n utf8data.push(0x80 | charCode & 0x3f);\n } else {\n charCode = (charCode & 0x3ff) << 10;\n charCode |= value.charCodeAt(++i) & 0x3ff;\n charCode += 0x10000;\n\n utf8data.push(0xf0 | charCode >> 18);\n utf8data.push(0x80 | (charCode >> 12) & 0x3f);\n utf8data.push(0x80 | (charCode >> 6) & 0x3f);\n utf8data.push(0x80 | charCode & 0x3f);\n }\n }\n\n writeTypeAndLength(3, utf8data.length);\n return writeUint8Array(utf8data);\n\n default:\n var length;\n if (Array.isArray(value)) {\n length = value.length;\n writeTypeAndLength(4, length);\n for (i = 0; i < length; ++i)\n encodeItem(value[i]);\n } else if (value instanceof Uint8Array) {\n writeTypeAndLength(2, value.length);\n writeUint8Array(value);\n } else {\n var keys = Object.keys(value);\n length = keys.length;\n writeTypeAndLength(5, length);\n for (i = 0; i < length; ++i) {\n var key = keys[i];\n encodeItem(key);\n encodeItem(value[key]);\n }\n }\n }\n }\n \n encodeItem(value);\n\n if (\"slice\" in data)\n return data.slice(0, offset);\n \n var ret = new ArrayBuffer(offset);\n var retView = new DataView(ret);\n for (var i = 0; i < offset; ++i)\n retView.setUint8(i, dataView.getUint8(i));\n return ret;\n}\n\nfunction decode(data, tagger, simpleValue) {\n var dataView = new DataView(data);\n var offset = 0;\n \n if (typeof tagger !== \"function\")\n tagger = function(value) { return value; };\n if (typeof simpleValue !== \"function\")\n simpleValue = function() { return undefined; };\n\n function read(value, length) {\n offset += length;\n return value;\n }\n function readArrayBuffer(length) {\n return read(new Uint8Array(data, offset, length), length);\n }\n function readFloat16() {\n var tempArrayBuffer = new ArrayBuffer(4);\n var tempDataView = new DataView(tempArrayBuffer);\n var value = readUint16();\n\n var sign = value & 0x8000;\n var exponent = value & 0x7c00;\n var fraction = value & 0x03ff;\n \n if (exponent === 0x7c00)\n exponent = 0xff << 10;\n else if (exponent !== 0)\n exponent += (127 - 15) << 10;\n else if (fraction !== 0)\n return fraction * POW_2_24;\n \n tempDataView.setUint32(0, sign << 16 | exponent << 13 | fraction << 13);\n return tempDataView.getFloat32(0);\n }\n function readFloat32() {\n return read(dataView.getFloat32(offset), 4);\n }\n function readFloat64() {\n return read(dataView.getFloat64(offset), 8);\n }\n function readUint8() {\n return read(dataView.getUint8(offset), 1);\n }\n function readUint16() {\n return read(dataView.getUint16(offset), 2);\n }\n function readUint32() {\n return read(dataView.getUint32(offset), 4);\n }\n function readUint64() {\n return readUint32() * POW_2_32 + readUint32();\n }\n function readBreak() {\n if (dataView.getUint8(offset) !== 0xff)\n return false;\n offset += 1;\n return true;\n }\n function readLength(additionalInformation) {\n if (additionalInformation < 24)\n return additionalInformation;\n if (additionalInformation === 24)\n return readUint8();\n if (additionalInformation === 25)\n return readUint16();\n if (additionalInformation === 26)\n return readUint32();\n if (additionalInformation === 27)\n return readUint64();\n if (additionalInformation === 31)\n return -1;\n throw \"Invalid length encoding\";\n }\n function readIndefiniteStringLength(majorType) {\n var initialByte = readUint8();\n if (initialByte === 0xff)\n return -1;\n var length = readLength(initialByte & 0x1f);\n if (length < 0 || (initialByte >> 5) !== majorType)\n throw \"Invalid indefinite length element\";\n return length;\n }\n\n function appendUtf16data(utf16data, length) {\n for (var i = 0; i < length; ++i) {\n var value = readUint8();\n if (value & 0x80) {\n if (value < 0xe0) {\n value = (value & 0x1f) << 6\n | (readUint8() & 0x3f);\n length -= 1;\n } else if (value < 0xf0) {\n value = (value & 0x0f) << 12\n | (readUint8() & 0x3f) << 6\n | (readUint8() & 0x3f);\n length -= 2;\n } else {\n value = (value & 0x0f) << 18\n | (readUint8() & 0x3f) << 12\n | (readUint8() & 0x3f) << 6\n | (readUint8() & 0x3f);\n length -= 3;\n }\n }\n\n if (value < 0x10000) {\n utf16data.push(value);\n } else {\n value -= 0x10000;\n utf16data.push(0xd800 | (value >> 10));\n utf16data.push(0xdc00 | (value & 0x3ff));\n }\n }\n }\n\n function decodeItem() {\n var initialByte = readUint8();\n var majorType = initialByte >> 5;\n var additionalInformation = initialByte & 0x1f;\n var i;\n var length;\n\n if (majorType === 7) {\n switch (additionalInformation) {\n case 25:\n return readFloat16();\n case 26:\n return readFloat32();\n case 27:\n return readFloat64();\n }\n }\n\n length = readLength(additionalInformation);\n if (length < 0 && (majorType < 2 || 6 < majorType))\n throw \"Invalid length\";\n\n switch (majorType) {\n case 0:\n return length;\n case 1:\n return -1 - length;\n case 2:\n if (length < 0) {\n var elements = [];\n var fullArrayLength = 0;\n while ((length = readIndefiniteStringLength(majorType)) >= 0) {\n fullArrayLength += length;\n elements.push(readArrayBuffer(length));\n }\n var fullArray = new Uint8Array(fullArrayLength);\n var fullArrayOffset = 0;\n for (i = 0; i < elements.length; ++i) {\n fullArray.set(elements[i], fullArrayOffset);\n fullArrayOffset += elements[i].length;\n }\n return fullArray;\n }\n return readArrayBuffer(length);\n case 3:\n var utf16data = [];\n if (length < 0) {\n while ((length = readIndefiniteStringLength(majorType)) >= 0)\n appendUtf16data(utf16data, length);\n } else\n appendUtf16data(utf16data, length);\n return String.fromCharCode.apply(null, utf16data);\n case 4:\n var retArray;\n if (length < 0) {\n retArray = [];\n while (!readBreak())\n retArray.push(decodeItem());\n } else {\n retArray = new Array(length);\n for (i = 0; i < length; ++i)\n retArray[i] = decodeItem();\n }\n return retArray;\n case 5:\n var retObject = {};\n for (i = 0; i < length || length < 0 && !readBreak(); ++i) {\n var key = decodeItem();\n retObject[key] = decodeItem();\n }\n return retObject;\n case 6:\n return tagger(decodeItem(), length);\n case 7:\n switch (length) {\n case 20:\n return false;\n case 21:\n return true;\n case 22:\n return null;\n case 23:\n return undefined;\n default:\n return simpleValue(length);\n }\n }\n }\n\n var ret = decodeItem();\n if (offset !== data.byteLength)\n throw \"Remaining bytes\";\n return ret;\n}\n\nvar obj = { encode: encode, decode: decode };\n\nif (typeof define === \"function\" && define.amd)\n define(\"cbor/cbor\", obj);\nelse if (typeof module !== 'undefined' && module.exports)\n module.exports = obj;\nelse if (!global.CBOR)\n global.CBOR = obj;\n\n})(this);\n", "'use strict'\n\nexports.byteLength = byteLength\nexports.toByteArray = toByteArray\nexports.fromByteArray = fromByteArray\n\nvar lookup = []\nvar revLookup = []\nvar Arr = typeof Uint8Array !== 'undefined' ? Uint8Array : Array\n\nvar code = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'\nfor (var i = 0, len = code.length; i < len; ++i) {\n lookup[i] = code[i]\n revLookup[code.charCodeAt(i)] = i\n}\n\n// Support decoding URL-safe base64 strings, as Node.js does.\n// See: https://en.wikipedia.org/wiki/Base64#URL_applications\nrevLookup['-'.charCodeAt(0)] = 62\nrevLookup['_'.charCodeAt(0)] = 63\n\nfunction getLens (b64) {\n var len = b64.length\n\n if (len % 4 > 0) {\n throw new Error('Invalid string. Length must be a multiple of 4')\n }\n\n // Trim off extra bytes after placeholder bytes are found\n // See: https://github.com/beatgammit/base64-js/issues/42\n var validLen = b64.indexOf('=')\n if (validLen === -1) validLen = len\n\n var placeHoldersLen = validLen === len\n ? 0\n : 4 - (validLen % 4)\n\n return [validLen, placeHoldersLen]\n}\n\n// base64 is 4/3 + up to two characters of the original data\nfunction byteLength (b64) {\n var lens = getLens(b64)\n var validLen = lens[0]\n var placeHoldersLen = lens[1]\n return ((validLen + placeHoldersLen) * 3 / 4) - placeHoldersLen\n}\n\nfunction _byteLength (b64, validLen, placeHoldersLen) {\n return ((validLen + placeHoldersLen) * 3 / 4) - placeHoldersLen\n}\n\nfunction toByteArray (b64) {\n var tmp\n var lens = getLens(b64)\n var validLen = lens[0]\n var placeHoldersLen = lens[1]\n\n var arr = new Arr(_byteLength(b64, validLen, placeHoldersLen))\n\n var curByte = 0\n\n // if there are placeholders, only get up to the last complete 4 chars\n var len = placeHoldersLen > 0\n ? validLen - 4\n : validLen\n\n var i\n for (i = 0; i < len; i += 4) {\n tmp =\n (revLookup[b64.charCodeAt(i)] << 18) |\n (revLookup[b64.charCodeAt(i + 1)] << 12) |\n (revLookup[b64.charCodeAt(i + 2)] << 6) |\n revLookup[b64.charCodeAt(i + 3)]\n arr[curByte++] = (tmp >> 16) & 0xFF\n arr[curByte++] = (tmp >> 8) & 0xFF\n arr[curByte++] = tmp & 0xFF\n }\n\n if (placeHoldersLen === 2) {\n tmp =\n (revLookup[b64.charCodeAt(i)] << 2) |\n (revLookup[b64.charCodeAt(i + 1)] >> 4)\n arr[curByte++] = tmp & 0xFF\n }\n\n if (placeHoldersLen === 1) {\n tmp =\n (revLookup[b64.charCodeAt(i)] << 10) |\n (revLookup[b64.charCodeAt(i + 1)] << 4) |\n (revLookup[b64.charCodeAt(i + 2)] >> 2)\n arr[curByte++] = (tmp >> 8) & 0xFF\n arr[curByte++] = tmp & 0xFF\n }\n\n return arr\n}\n\nfunction tripletToBase64 (num) {\n return lookup[num >> 18 & 0x3F] +\n lookup[num >> 12 & 0x3F] +\n lookup[num >> 6 & 0x3F] +\n lookup[num & 0x3F]\n}\n\nfunction encodeChunk (uint8, start, end) {\n var tmp\n var output = []\n for (var i = start; i < end; i += 3) {\n tmp =\n ((uint8[i] << 16) & 0xFF0000) +\n ((uint8[i + 1] << 8) & 0xFF00) +\n (uint8[i + 2] & 0xFF)\n output.push(tripletToBase64(tmp))\n }\n return output.join('')\n}\n\nfunction fromByteArray (uint8) {\n var tmp\n var len = uint8.length\n var extraBytes = len % 3 // if we have 1 byte left, pad 2 bytes\n var parts = []\n var maxChunkLength = 16383 // must be multiple of 3\n\n // go through the array every three bytes, we'll deal with trailing stuff later\n for (var i = 0, len2 = len - extraBytes; i < len2; i += maxChunkLength) {\n parts.push(encodeChunk(uint8, i, (i + maxChunkLength) > len2 ? len2 : (i + maxChunkLength)))\n }\n\n // pad the end with zeros, but make sure to not forget the extra bytes\n if (extraBytes === 1) {\n tmp = uint8[len - 1]\n parts.push(\n lookup[tmp >> 2] +\n lookup[(tmp << 4) & 0x3F] +\n '=='\n )\n } else if (extraBytes === 2) {\n tmp = (uint8[len - 2] << 8) + uint8[len - 1]\n parts.push(\n lookup[tmp >> 10] +\n lookup[(tmp >> 4) & 0x3F] +\n lookup[(tmp << 2) & 0x3F] +\n '='\n )\n }\n\n return parts.join('')\n}\n", "// Local QR generator and scanner with COSE compression (no external CDNs)\n// Exposes: \n// - window.generateQRCode(text, { size?: number, margin?: number, errorCorrectionLevel?: 'L'|'M'|'Q'|'H' })\n// - window.generateCOSEQRCode(data, senderKey?, recipientKey?) - COSE-based compression\n// - window.Html5Qrcode (for scanning QR codes)\n// - window.packSecurePayload, window.receiveAndProcess (COSE functions)\n\nimport * as QRCode from 'qrcode';\nimport { Html5Qrcode } from 'html5-qrcode';\nimport { gzip, ungzip, deflate, inflate } from 'pako';\nimport * as cbor from 'cbor-js';\nimport { packSecurePayload, receiveAndProcess } from '../crypto/cose-qr.js';\n\n// Compact payload prefix to signal gzip+base64 content\nconst COMPRESSION_PREFIX = 'SB1:gz:';\nconst BINARY_PREFIX = 'SB1:bin:'; // CBOR + deflate + base64url\n\nfunction uint8ToBase64(bytes) {\n let binary = '';\n const chunkSize = 0x8000;\n for (let i = 0; i < bytes.length; i += chunkSize) {\n const chunk = bytes.subarray(i, i + chunkSize);\n binary += String.fromCharCode.apply(null, chunk);\n }\n return btoa(binary);\n}\n\nfunction base64ToUint8(b64) {\n const binary = atob(b64);\n const len = binary.length;\n const bytes = new Uint8Array(len);\n for (let i = 0; i < len; i++) bytes[i] = binary.charCodeAt(i);\n return bytes;\n}\n\nfunction compressStringToBase64Gzip(text) {\n const utf8 = new TextEncoder().encode(text);\n const gz = gzip(utf8);\n return uint8ToBase64(gz);\n}\n\nfunction decompressBase64GzipToString(b64) {\n const gz = base64ToUint8(b64);\n const out = ungzip(gz);\n return new TextDecoder().decode(out);\n}\n\nasync function generateQRCode(text, opts = {}) {\n const size = opts.size || 512;\n const margin = opts.margin ?? 2;\n const errorCorrectionLevel = opts.errorCorrectionLevel || 'M';\n return await QRCode.toDataURL(text, { width: size, margin, errorCorrectionLevel });\n}\n\n// Generate QR with gzip+base64 payload and recognizable prefix for scanners\nasync function generateCompressedQRCode(text, opts = {}) {\n try {\n const compressedB64 = compressStringToBase64Gzip(text);\n const payload = COMPRESSION_PREFIX + compressedB64;\n return await generateQRCode(payload, opts);\n } catch (e) {\n console.warn('generateCompressedQRCode failed, falling back to plain:', e?.message || e);\n return await generateQRCode(text, opts);\n }\n}\n\n// ---- Binary (CBOR) encode/decode helpers ----\nfunction base64ToBase64Url(b64) {\n return b64.replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=+$/g, '');\n}\nfunction base64UrlToBase64(b64url) {\n let b64 = b64url.replace(/-/g, '+').replace(/_/g, '/');\n const pad = b64.length % 4;\n if (pad) b64 += '='.repeat(4 - pad);\n return b64;\n}\n\nfunction encodeObjectToBinaryBase64Url(obj) {\n const cborBytes = cbor.encode(obj);\n const compressed = deflate(new Uint8Array(cborBytes));\n const b64 = uint8ToBase64(compressed);\n return base64ToBase64Url(b64);\n}\n\nfunction decodeBinaryBase64UrlToObject(b64url) {\n const b64 = base64UrlToBase64(b64url);\n const compressed = base64ToUint8(b64);\n const decompressed = inflate(compressed);\n const ab = decompressed.buffer.slice(decompressed.byteOffset, decompressed.byteOffset + decompressed.byteLength);\n return cbor.decode(ab);\n}\n\nasync function generateBinaryQRCodeFromObject(obj, opts = {}) {\n try {\n const b64url = encodeObjectToBinaryBase64Url(obj);\n const payload = BINARY_PREFIX + b64url;\n return await generateQRCode(payload, opts);\n } catch (e) {\n console.warn('generateBinaryQRCodeFromObject failed, falling back to JSON compressed:', e?.message || e);\n const text = JSON.stringify(obj);\n return await generateCompressedQRCode(text, opts);\n }\n}\n\n// COSE-based QR generation for large data\nasync function generateCOSEQRCode(data, senderKey = null, recipientKey = null) {\n try {\n console.log('\uD83D\uDD10 Generating COSE-based QR code...');\n \n // Pack data using COSE\n const chunks = await packSecurePayload(data, senderKey, recipientKey);\n \n if (chunks.length === 1) {\n // Single QR code\n return await generateQRCode(chunks[0]);\n } else {\n // Enforce single-QR policy: let caller fallback to template/reference\n console.warn(`\uD83D\uDCCA COSE packing produced ${chunks.length} chunks; falling back to non-COSE strategy`);\n throw new Error('COSE QR would require multiple chunks');\n }\n } catch (error) {\n console.error('Error generating COSE QR code:', error);\n throw error;\n }\n}\n\n// Expose functions to global scope\nwindow.generateQRCode = generateQRCode;\nwindow.generateCompressedQRCode = generateCompressedQRCode;\nwindow.generateBinaryQRCodeFromObject = generateBinaryQRCodeFromObject;\nwindow.generateCOSEQRCode = generateCOSEQRCode;\nwindow.Html5Qrcode = Html5Qrcode;\nwindow.packSecurePayload = packSecurePayload;\nwindow.receiveAndProcess = receiveAndProcess;\n\n// Expose helper to transparently decompress scanner payloads\nwindow.decompressIfNeeded = function (scannedText) {\n try {\n if (typeof scannedText === 'string' && scannedText.startsWith(COMPRESSION_PREFIX)) {\n const b64 = scannedText.slice(COMPRESSION_PREFIX.length);\n return decompressBase64GzipToString(b64);\n }\n } catch (e) {\n console.warn('decompressIfNeeded failed:', e?.message || e);\n }\n return scannedText;\n};\n\n// Expose helper to get compressed string with prefix for copy/paste flows\nwindow.compressToPrefixedGzip = function (text) {\n try {\n const payload = String(text || '');\n const compressedB64 = compressStringToBase64Gzip(payload);\n return COMPRESSION_PREFIX + compressedB64;\n } catch (e) {\n console.warn('compressToPrefixedGzip failed:', e?.message || e);\n return String(text || '');\n }\n};\n\n// Expose helpers for binary payloads in copy/paste\nwindow.encodeBinaryToPrefixed = function (objOrJson) {\n try {\n const obj = typeof objOrJson === 'string' ? JSON.parse(objOrJson) : objOrJson;\n const b64url = encodeObjectToBinaryBase64Url(obj);\n return BINARY_PREFIX + b64url;\n } catch (e) {\n console.warn('encodeBinaryToPrefixed failed:', e?.message || e);\n return typeof objOrJson === 'string' ? objOrJson : JSON.stringify(objOrJson);\n }\n};\n\nwindow.decodeAnyPayload = function (scannedText) {\n try {\n if (typeof scannedText === 'string') {\n if (scannedText.startsWith(BINARY_PREFIX)) {\n const b64url = scannedText.slice(BINARY_PREFIX.length);\n return decodeBinaryBase64UrlToObject(b64url); // returns object\n }\n if (scannedText.startsWith(COMPRESSION_PREFIX)) {\n const s = window.decompressIfNeeded(scannedText);\n return s; // returns JSON string\n }\n // Not prefixed: return as-is\n return scannedText;\n }\n } catch (e) {\n console.warn('decodeAnyPayload failed:', e?.message || e);\n }\n return scannedText;\n};\n\nconsole.log('QR libraries loaded: generateQRCode, generateCompressedQRCode, generateBinaryQRCodeFromObject, Html5Qrcode, COSE functions');", null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, "\n/*! pako 2.1.0 https://github.com/nodeca/pako @license (MIT AND Zlib) */\n// (C) 1995-2013 Jean-loup Gailly and Mark Adler\n// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin\n//\n// This software is provided 'as-is', without any express or implied\n// warranty. In no event will the authors be held liable for any damages\n// arising from the use of this software.\n//\n// Permission is granted to anyone to use this software for any purpose,\n// including commercial applications, and to alter it and redistribute it\n// freely, subject to the following restrictions:\n//\n// 1. The origin of this software must not be misrepresented; you must not\n// claim that you wrote the original software. If you use this software\n// in a product, an acknowledgment in the product documentation would be\n// appreciated but is not required.\n// 2. Altered source versions must be plainly marked as such, and must not be\n// misrepresented as being the original software.\n// 3. This notice may not be removed or altered from any source distribution.\n\n/* eslint-disable space-unary-ops */\n\n/* Public constants ==========================================================*/\n/* ===========================================================================*/\n\n\n//const Z_FILTERED = 1;\n//const Z_HUFFMAN_ONLY = 2;\n//const Z_RLE = 3;\nconst Z_FIXED$1 = 4;\n//const Z_DEFAULT_STRATEGY = 0;\n\n/* Possible values of the data_type field (though see inflate()) */\nconst Z_BINARY = 0;\nconst Z_TEXT = 1;\n//const Z_ASCII = 1; // = Z_TEXT\nconst Z_UNKNOWN$1 = 2;\n\n/*============================================================================*/\n\n\nfunction zero$1(buf) { let len = buf.length; while (--len >= 0) { buf[len] = 0; } }\n\n// From zutil.h\n\nconst STORED_BLOCK = 0;\nconst STATIC_TREES = 1;\nconst DYN_TREES = 2;\n/* The three kinds of block type */\n\nconst MIN_MATCH$1 = 3;\nconst MAX_MATCH$1 = 258;\n/* The minimum and maximum match lengths */\n\n// From deflate.h\n/* ===========================================================================\n * Internal compression state.\n */\n\nconst LENGTH_CODES$1 = 29;\n/* number of length codes, not counting the special END_BLOCK code */\n\nconst LITERALS$1 = 256;\n/* number of literal bytes 0..255 */\n\nconst L_CODES$1 = LITERALS$1 + 1 + LENGTH_CODES$1;\n/* number of Literal or Length codes, including the END_BLOCK code */\n\nconst D_CODES$1 = 30;\n/* number of distance codes */\n\nconst BL_CODES$1 = 19;\n/* number of codes used to transfer the bit lengths */\n\nconst HEAP_SIZE$1 = 2 * L_CODES$1 + 1;\n/* maximum heap size */\n\nconst MAX_BITS$1 = 15;\n/* All codes must not exceed MAX_BITS bits */\n\nconst Buf_size = 16;\n/* size of bit buffer in bi_buf */\n\n\n/* ===========================================================================\n * Constants\n */\n\nconst MAX_BL_BITS = 7;\n/* Bit length codes must not exceed MAX_BL_BITS bits */\n\nconst END_BLOCK = 256;\n/* end of block literal code */\n\nconst REP_3_6 = 16;\n/* repeat previous bit length 3-6 times (2 bits of repeat count) */\n\nconst REPZ_3_10 = 17;\n/* repeat a zero length 3-10 times (3 bits of repeat count) */\n\nconst REPZ_11_138 = 18;\n/* repeat a zero length 11-138 times (7 bits of repeat count) */\n\n/* eslint-disable comma-spacing,array-bracket-spacing */\nconst extra_lbits = /* extra bits for each length code */\n new Uint8Array([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]);\n\nconst extra_dbits = /* extra bits for each distance code */\n new Uint8Array([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]);\n\nconst extra_blbits = /* extra bits for each bit length code */\n new Uint8Array([0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7]);\n\nconst bl_order =\n new Uint8Array([16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15]);\n/* eslint-enable comma-spacing,array-bracket-spacing */\n\n/* The lengths of the bit length codes are sent in order of decreasing\n * probability, to avoid transmitting the lengths for unused bit length codes.\n */\n\n/* ===========================================================================\n * Local data. These are initialized only once.\n */\n\n// We pre-fill arrays with 0 to avoid uninitialized gaps\n\nconst DIST_CODE_LEN = 512; /* see definition of array dist_code below */\n\n// !!!! Use flat array instead of structure, Freq = i*2, Len = i*2+1\nconst static_ltree = new Array((L_CODES$1 + 2) * 2);\nzero$1(static_ltree);\n/* The static literal tree. Since the bit lengths are imposed, there is no\n * need for the L_CODES extra codes used during heap construction. However\n * The codes 286 and 287 are needed to build a canonical tree (see _tr_init\n * below).\n */\n\nconst static_dtree = new Array(D_CODES$1 * 2);\nzero$1(static_dtree);\n/* The static distance tree. (Actually a trivial tree since all codes use\n * 5 bits.)\n */\n\nconst _dist_code = new Array(DIST_CODE_LEN);\nzero$1(_dist_code);\n/* Distance codes. The first 256 values correspond to the distances\n * 3 .. 258, the last 256 values correspond to the top 8 bits of\n * the 15 bit distances.\n */\n\nconst _length_code = new Array(MAX_MATCH$1 - MIN_MATCH$1 + 1);\nzero$1(_length_code);\n/* length code for each normalized match length (0 == MIN_MATCH) */\n\nconst base_length = new Array(LENGTH_CODES$1);\nzero$1(base_length);\n/* First normalized length for each code (0 = MIN_MATCH) */\n\nconst base_dist = new Array(D_CODES$1);\nzero$1(base_dist);\n/* First normalized distance for each code (0 = distance of 1) */\n\n\nfunction StaticTreeDesc(static_tree, extra_bits, extra_base, elems, max_length) {\n\n this.static_tree = static_tree; /* static tree or NULL */\n this.extra_bits = extra_bits; /* extra bits for each code or NULL */\n this.extra_base = extra_base; /* base index for extra_bits */\n this.elems = elems; /* max number of elements in the tree */\n this.max_length = max_length; /* max bit length for the codes */\n\n // show if `static_tree` has data or dummy - needed for monomorphic objects\n this.has_stree = static_tree && static_tree.length;\n}\n\n\nlet static_l_desc;\nlet static_d_desc;\nlet static_bl_desc;\n\n\nfunction TreeDesc(dyn_tree, stat_desc) {\n this.dyn_tree = dyn_tree; /* the dynamic tree */\n this.max_code = 0; /* largest code with non zero frequency */\n this.stat_desc = stat_desc; /* the corresponding static tree */\n}\n\n\n\nconst d_code = (dist) => {\n\n return dist < 256 ? _dist_code[dist] : _dist_code[256 + (dist >>> 7)];\n};\n\n\n/* ===========================================================================\n * Output a short LSB first on the stream.\n * IN assertion: there is enough room in pendingBuf.\n */\nconst put_short = (s, w) => {\n// put_byte(s, (uch)((w) & 0xff));\n// put_byte(s, (uch)((ush)(w) >> 8));\n s.pending_buf[s.pending++] = (w) & 0xff;\n s.pending_buf[s.pending++] = (w >>> 8) & 0xff;\n};\n\n\n/* ===========================================================================\n * Send a value on a given number of bits.\n * IN assertion: length <= 16 and value fits in length bits.\n */\nconst send_bits = (s, value, length) => {\n\n if (s.bi_valid > (Buf_size - length)) {\n s.bi_buf |= (value << s.bi_valid) & 0xffff;\n put_short(s, s.bi_buf);\n s.bi_buf = value >> (Buf_size - s.bi_valid);\n s.bi_valid += length - Buf_size;\n } else {\n s.bi_buf |= (value << s.bi_valid) & 0xffff;\n s.bi_valid += length;\n }\n};\n\n\nconst send_code = (s, c, tree) => {\n\n send_bits(s, tree[c * 2]/*.Code*/, tree[c * 2 + 1]/*.Len*/);\n};\n\n\n/* ===========================================================================\n * Reverse the first len bits of a code, using straightforward code (a faster\n * method would use a table)\n * IN assertion: 1 <= len <= 15\n */\nconst bi_reverse = (code, len) => {\n\n let res = 0;\n do {\n res |= code & 1;\n code >>>= 1;\n res <<= 1;\n } while (--len > 0);\n return res >>> 1;\n};\n\n\n/* ===========================================================================\n * Flush the bit buffer, keeping at most 7 bits in it.\n */\nconst bi_flush = (s) => {\n\n if (s.bi_valid === 16) {\n put_short(s, s.bi_buf);\n s.bi_buf = 0;\n s.bi_valid = 0;\n\n } else if (s.bi_valid >= 8) {\n s.pending_buf[s.pending++] = s.bi_buf & 0xff;\n s.bi_buf >>= 8;\n s.bi_valid -= 8;\n }\n};\n\n\n/* ===========================================================================\n * Compute the optimal bit lengths for a tree and update the total bit length\n * for the current block.\n * IN assertion: the fields freq and dad are set, heap[heap_max] and\n * above are the tree nodes sorted by increasing frequency.\n * OUT assertions: the field len is set to the optimal bit length, the\n * array bl_count contains the frequencies for each bit length.\n * The length opt_len is updated; static_len is also updated if stree is\n * not null.\n */\nconst gen_bitlen = (s, desc) => {\n// deflate_state *s;\n// tree_desc *desc; /* the tree descriptor */\n\n const tree = desc.dyn_tree;\n const max_code = desc.max_code;\n const stree = desc.stat_desc.static_tree;\n const has_stree = desc.stat_desc.has_stree;\n const extra = desc.stat_desc.extra_bits;\n const base = desc.stat_desc.extra_base;\n const max_length = desc.stat_desc.max_length;\n let h; /* heap index */\n let n, m; /* iterate over the tree elements */\n let bits; /* bit length */\n let xbits; /* extra bits */\n let f; /* frequency */\n let overflow = 0; /* number of elements with bit length too large */\n\n for (bits = 0; bits <= MAX_BITS$1; bits++) {\n s.bl_count[bits] = 0;\n }\n\n /* In a first pass, compute the optimal bit lengths (which may\n * overflow in the case of the bit length tree).\n */\n tree[s.heap[s.heap_max] * 2 + 1]/*.Len*/ = 0; /* root of the heap */\n\n for (h = s.heap_max + 1; h < HEAP_SIZE$1; h++) {\n n = s.heap[h];\n bits = tree[tree[n * 2 + 1]/*.Dad*/ * 2 + 1]/*.Len*/ + 1;\n if (bits > max_length) {\n bits = max_length;\n overflow++;\n }\n tree[n * 2 + 1]/*.Len*/ = bits;\n /* We overwrite tree[n].Dad which is no longer needed */\n\n if (n > max_code) { continue; } /* not a leaf node */\n\n s.bl_count[bits]++;\n xbits = 0;\n if (n >= base) {\n xbits = extra[n - base];\n }\n f = tree[n * 2]/*.Freq*/;\n s.opt_len += f * (bits + xbits);\n if (has_stree) {\n s.static_len += f * (stree[n * 2 + 1]/*.Len*/ + xbits);\n }\n }\n if (overflow === 0) { return; }\n\n // Tracev((stderr,\"\\nbit length overflow\\n\"));\n /* This happens for example on obj2 and pic of the Calgary corpus */\n\n /* Find the first bit length which could increase: */\n do {\n bits = max_length - 1;\n while (s.bl_count[bits] === 0) { bits--; }\n s.bl_count[bits]--; /* move one leaf down the tree */\n s.bl_count[bits + 1] += 2; /* move one overflow item as its brother */\n s.bl_count[max_length]--;\n /* The brother of the overflow item also moves one step up,\n * but this does not affect bl_count[max_length]\n */\n overflow -= 2;\n } while (overflow > 0);\n\n /* Now recompute all bit lengths, scanning in increasing frequency.\n * h is still equal to HEAP_SIZE. (It is simpler to reconstruct all\n * lengths instead of fixing only the wrong ones. This idea is taken\n * from 'ar' written by Haruhiko Okumura.)\n */\n for (bits = max_length; bits !== 0; bits--) {\n n = s.bl_count[bits];\n while (n !== 0) {\n m = s.heap[--h];\n if (m > max_code) { continue; }\n if (tree[m * 2 + 1]/*.Len*/ !== bits) {\n // Tracev((stderr,\"code %d bits %d->%d\\n\", m, tree[m].Len, bits));\n s.opt_len += (bits - tree[m * 2 + 1]/*.Len*/) * tree[m * 2]/*.Freq*/;\n tree[m * 2 + 1]/*.Len*/ = bits;\n }\n n--;\n }\n }\n};\n\n\n/* ===========================================================================\n * Generate the codes for a given tree and bit counts (which need not be\n * optimal).\n * IN assertion: the array bl_count contains the bit length statistics for\n * the given tree and the field len is set for all tree elements.\n * OUT assertion: the field code is set for all tree elements of non\n * zero code length.\n */\nconst gen_codes = (tree, max_code, bl_count) => {\n// ct_data *tree; /* the tree to decorate */\n// int max_code; /* largest code with non zero frequency */\n// ushf *bl_count; /* number of codes at each bit length */\n\n const next_code = new Array(MAX_BITS$1 + 1); /* next code value for each bit length */\n let code = 0; /* running code value */\n let bits; /* bit index */\n let n; /* code index */\n\n /* The distribution counts are first used to generate the code values\n * without bit reversal.\n */\n for (bits = 1; bits <= MAX_BITS$1; bits++) {\n code = (code + bl_count[bits - 1]) << 1;\n next_code[bits] = code;\n }\n /* Check that the bit counts in bl_count are consistent. The last code\n * must be all ones.\n */\n //Assert (code + bl_count[MAX_BITS]-1 == (1< {\n\n let n; /* iterates over tree elements */\n let bits; /* bit counter */\n let length; /* length value */\n let code; /* code value */\n let dist; /* distance index */\n const bl_count = new Array(MAX_BITS$1 + 1);\n /* number of codes at each bit length for an optimal tree */\n\n // do check in _tr_init()\n //if (static_init_done) return;\n\n /* For some embedded targets, global variables are not initialized: */\n/*#ifdef NO_INIT_GLOBAL_POINTERS\n static_l_desc.static_tree = static_ltree;\n static_l_desc.extra_bits = extra_lbits;\n static_d_desc.static_tree = static_dtree;\n static_d_desc.extra_bits = extra_dbits;\n static_bl_desc.extra_bits = extra_blbits;\n#endif*/\n\n /* Initialize the mapping length (0..255) -> length code (0..28) */\n length = 0;\n for (code = 0; code < LENGTH_CODES$1 - 1; code++) {\n base_length[code] = length;\n for (n = 0; n < (1 << extra_lbits[code]); n++) {\n _length_code[length++] = code;\n }\n }\n //Assert (length == 256, \"tr_static_init: length != 256\");\n /* Note that the length 255 (match length 258) can be represented\n * in two different ways: code 284 + 5 bits or code 285, so we\n * overwrite length_code[255] to use the best encoding:\n */\n _length_code[length - 1] = code;\n\n /* Initialize the mapping dist (0..32K) -> dist code (0..29) */\n dist = 0;\n for (code = 0; code < 16; code++) {\n base_dist[code] = dist;\n for (n = 0; n < (1 << extra_dbits[code]); n++) {\n _dist_code[dist++] = code;\n }\n }\n //Assert (dist == 256, \"tr_static_init: dist != 256\");\n dist >>= 7; /* from now on, all distances are divided by 128 */\n for (; code < D_CODES$1; code++) {\n base_dist[code] = dist << 7;\n for (n = 0; n < (1 << (extra_dbits[code] - 7)); n++) {\n _dist_code[256 + dist++] = code;\n }\n }\n //Assert (dist == 256, \"tr_static_init: 256+dist != 512\");\n\n /* Construct the codes of the static literal tree */\n for (bits = 0; bits <= MAX_BITS$1; bits++) {\n bl_count[bits] = 0;\n }\n\n n = 0;\n while (n <= 143) {\n static_ltree[n * 2 + 1]/*.Len*/ = 8;\n n++;\n bl_count[8]++;\n }\n while (n <= 255) {\n static_ltree[n * 2 + 1]/*.Len*/ = 9;\n n++;\n bl_count[9]++;\n }\n while (n <= 279) {\n static_ltree[n * 2 + 1]/*.Len*/ = 7;\n n++;\n bl_count[7]++;\n }\n while (n <= 287) {\n static_ltree[n * 2 + 1]/*.Len*/ = 8;\n n++;\n bl_count[8]++;\n }\n /* Codes 286 and 287 do not exist, but we must include them in the\n * tree construction to get a canonical Huffman tree (longest code\n * all ones)\n */\n gen_codes(static_ltree, L_CODES$1 + 1, bl_count);\n\n /* The static distance tree is trivial: */\n for (n = 0; n < D_CODES$1; n++) {\n static_dtree[n * 2 + 1]/*.Len*/ = 5;\n static_dtree[n * 2]/*.Code*/ = bi_reverse(n, 5);\n }\n\n // Now data ready and we can init static trees\n static_l_desc = new StaticTreeDesc(static_ltree, extra_lbits, LITERALS$1 + 1, L_CODES$1, MAX_BITS$1);\n static_d_desc = new StaticTreeDesc(static_dtree, extra_dbits, 0, D_CODES$1, MAX_BITS$1);\n static_bl_desc = new StaticTreeDesc(new Array(0), extra_blbits, 0, BL_CODES$1, MAX_BL_BITS);\n\n //static_init_done = true;\n};\n\n\n/* ===========================================================================\n * Initialize a new block.\n */\nconst init_block = (s) => {\n\n let n; /* iterates over tree elements */\n\n /* Initialize the trees. */\n for (n = 0; n < L_CODES$1; n++) { s.dyn_ltree[n * 2]/*.Freq*/ = 0; }\n for (n = 0; n < D_CODES$1; n++) { s.dyn_dtree[n * 2]/*.Freq*/ = 0; }\n for (n = 0; n < BL_CODES$1; n++) { s.bl_tree[n * 2]/*.Freq*/ = 0; }\n\n s.dyn_ltree[END_BLOCK * 2]/*.Freq*/ = 1;\n s.opt_len = s.static_len = 0;\n s.sym_next = s.matches = 0;\n};\n\n\n/* ===========================================================================\n * Flush the bit buffer and align the output on a byte boundary\n */\nconst bi_windup = (s) =>\n{\n if (s.bi_valid > 8) {\n put_short(s, s.bi_buf);\n } else if (s.bi_valid > 0) {\n //put_byte(s, (Byte)s->bi_buf);\n s.pending_buf[s.pending++] = s.bi_buf;\n }\n s.bi_buf = 0;\n s.bi_valid = 0;\n};\n\n/* ===========================================================================\n * Compares to subtrees, using the tree depth as tie breaker when\n * the subtrees have equal frequency. This minimizes the worst case length.\n */\nconst smaller = (tree, n, m, depth) => {\n\n const _n2 = n * 2;\n const _m2 = m * 2;\n return (tree[_n2]/*.Freq*/ < tree[_m2]/*.Freq*/ ||\n (tree[_n2]/*.Freq*/ === tree[_m2]/*.Freq*/ && depth[n] <= depth[m]));\n};\n\n/* ===========================================================================\n * Restore the heap property by moving down the tree starting at node k,\n * exchanging a node with the smallest of its two sons if necessary, stopping\n * when the heap property is re-established (each father smaller than its\n * two sons).\n */\nconst pqdownheap = (s, tree, k) => {\n// deflate_state *s;\n// ct_data *tree; /* the tree to restore */\n// int k; /* node to move down */\n\n const v = s.heap[k];\n let j = k << 1; /* left son of k */\n while (j <= s.heap_len) {\n /* Set j to the smallest of the two sons: */\n if (j < s.heap_len &&\n smaller(tree, s.heap[j + 1], s.heap[j], s.depth)) {\n j++;\n }\n /* Exit if v is smaller than both sons */\n if (smaller(tree, v, s.heap[j], s.depth)) { break; }\n\n /* Exchange v with the smallest son */\n s.heap[k] = s.heap[j];\n k = j;\n\n /* And continue down the tree, setting j to the left son of k */\n j <<= 1;\n }\n s.heap[k] = v;\n};\n\n\n// inlined manually\n// const SMALLEST = 1;\n\n/* ===========================================================================\n * Send the block data compressed using the given Huffman trees\n */\nconst compress_block = (s, ltree, dtree) => {\n// deflate_state *s;\n// const ct_data *ltree; /* literal tree */\n// const ct_data *dtree; /* distance tree */\n\n let dist; /* distance of matched string */\n let lc; /* match length or unmatched char (if dist == 0) */\n let sx = 0; /* running index in sym_buf */\n let code; /* the code to send */\n let extra; /* number of extra bits to send */\n\n if (s.sym_next !== 0) {\n do {\n dist = s.pending_buf[s.sym_buf + sx++] & 0xff;\n dist += (s.pending_buf[s.sym_buf + sx++] & 0xff) << 8;\n lc = s.pending_buf[s.sym_buf + sx++];\n if (dist === 0) {\n send_code(s, lc, ltree); /* send a literal byte */\n //Tracecv(isgraph(lc), (stderr,\" '%c' \", lc));\n } else {\n /* Here, lc is the match length - MIN_MATCH */\n code = _length_code[lc];\n send_code(s, code + LITERALS$1 + 1, ltree); /* send the length code */\n extra = extra_lbits[code];\n if (extra !== 0) {\n lc -= base_length[code];\n send_bits(s, lc, extra); /* send the extra length bits */\n }\n dist--; /* dist is now the match distance - 1 */\n code = d_code(dist);\n //Assert (code < D_CODES, \"bad d_code\");\n\n send_code(s, code, dtree); /* send the distance code */\n extra = extra_dbits[code];\n if (extra !== 0) {\n dist -= base_dist[code];\n send_bits(s, dist, extra); /* send the extra distance bits */\n }\n } /* literal or match pair ? */\n\n /* Check that the overlay between pending_buf and sym_buf is ok: */\n //Assert(s->pending < s->lit_bufsize + sx, \"pendingBuf overflow\");\n\n } while (sx < s.sym_next);\n }\n\n send_code(s, END_BLOCK, ltree);\n};\n\n\n/* ===========================================================================\n * Construct one Huffman tree and assigns the code bit strings and lengths.\n * Update the total bit length for the current block.\n * IN assertion: the field freq is set for all tree elements.\n * OUT assertions: the fields len and code are set to the optimal bit length\n * and corresponding code. The length opt_len is updated; static_len is\n * also updated if stree is not null. The field max_code is set.\n */\nconst build_tree = (s, desc) => {\n// deflate_state *s;\n// tree_desc *desc; /* the tree descriptor */\n\n const tree = desc.dyn_tree;\n const stree = desc.stat_desc.static_tree;\n const has_stree = desc.stat_desc.has_stree;\n const elems = desc.stat_desc.elems;\n let n, m; /* iterate over heap elements */\n let max_code = -1; /* largest code with non zero frequency */\n let node; /* new node being created */\n\n /* Construct the initial heap, with least frequent element in\n * heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n+1].\n * heap[0] is not used.\n */\n s.heap_len = 0;\n s.heap_max = HEAP_SIZE$1;\n\n for (n = 0; n < elems; n++) {\n if (tree[n * 2]/*.Freq*/ !== 0) {\n s.heap[++s.heap_len] = max_code = n;\n s.depth[n] = 0;\n\n } else {\n tree[n * 2 + 1]/*.Len*/ = 0;\n }\n }\n\n /* The pkzip format requires that at least one distance code exists,\n * and that at least one bit should be sent even if there is only one\n * possible code. So to avoid special checks later on we force at least\n * two codes of non zero frequency.\n */\n while (s.heap_len < 2) {\n node = s.heap[++s.heap_len] = (max_code < 2 ? ++max_code : 0);\n tree[node * 2]/*.Freq*/ = 1;\n s.depth[node] = 0;\n s.opt_len--;\n\n if (has_stree) {\n s.static_len -= stree[node * 2 + 1]/*.Len*/;\n }\n /* node is 0 or 1 so it does not have extra bits */\n }\n desc.max_code = max_code;\n\n /* The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree,\n * establish sub-heaps of increasing lengths:\n */\n for (n = (s.heap_len >> 1/*int /2*/); n >= 1; n--) { pqdownheap(s, tree, n); }\n\n /* Construct the Huffman tree by repeatedly combining the least two\n * frequent nodes.\n */\n node = elems; /* next internal node of the tree */\n do {\n //pqremove(s, tree, n); /* n = node of least frequency */\n /*** pqremove ***/\n n = s.heap[1/*SMALLEST*/];\n s.heap[1/*SMALLEST*/] = s.heap[s.heap_len--];\n pqdownheap(s, tree, 1/*SMALLEST*/);\n /***/\n\n m = s.heap[1/*SMALLEST*/]; /* m = node of next least frequency */\n\n s.heap[--s.heap_max] = n; /* keep the nodes sorted by frequency */\n s.heap[--s.heap_max] = m;\n\n /* Create a new node father of n and m */\n tree[node * 2]/*.Freq*/ = tree[n * 2]/*.Freq*/ + tree[m * 2]/*.Freq*/;\n s.depth[node] = (s.depth[n] >= s.depth[m] ? s.depth[n] : s.depth[m]) + 1;\n tree[n * 2 + 1]/*.Dad*/ = tree[m * 2 + 1]/*.Dad*/ = node;\n\n /* and insert the new node in the heap */\n s.heap[1/*SMALLEST*/] = node++;\n pqdownheap(s, tree, 1/*SMALLEST*/);\n\n } while (s.heap_len >= 2);\n\n s.heap[--s.heap_max] = s.heap[1/*SMALLEST*/];\n\n /* At this point, the fields freq and dad are set. We can now\n * generate the bit lengths.\n */\n gen_bitlen(s, desc);\n\n /* The field len is now set, we can generate the bit codes */\n gen_codes(tree, max_code, s.bl_count);\n};\n\n\n/* ===========================================================================\n * Scan a literal or distance tree to determine the frequencies of the codes\n * in the bit length tree.\n */\nconst scan_tree = (s, tree, max_code) => {\n// deflate_state *s;\n// ct_data *tree; /* the tree to be scanned */\n// int max_code; /* and its largest code of non zero frequency */\n\n let n; /* iterates over all tree elements */\n let prevlen = -1; /* last emitted length */\n let curlen; /* length of current code */\n\n let nextlen = tree[0 * 2 + 1]/*.Len*/; /* length of next code */\n\n let count = 0; /* repeat count of the current code */\n let max_count = 7; /* max repeat count */\n let min_count = 4; /* min repeat count */\n\n if (nextlen === 0) {\n max_count = 138;\n min_count = 3;\n }\n tree[(max_code + 1) * 2 + 1]/*.Len*/ = 0xffff; /* guard */\n\n for (n = 0; n <= max_code; n++) {\n curlen = nextlen;\n nextlen = tree[(n + 1) * 2 + 1]/*.Len*/;\n\n if (++count < max_count && curlen === nextlen) {\n continue;\n\n } else if (count < min_count) {\n s.bl_tree[curlen * 2]/*.Freq*/ += count;\n\n } else if (curlen !== 0) {\n\n if (curlen !== prevlen) { s.bl_tree[curlen * 2]/*.Freq*/++; }\n s.bl_tree[REP_3_6 * 2]/*.Freq*/++;\n\n } else if (count <= 10) {\n s.bl_tree[REPZ_3_10 * 2]/*.Freq*/++;\n\n } else {\n s.bl_tree[REPZ_11_138 * 2]/*.Freq*/++;\n }\n\n count = 0;\n prevlen = curlen;\n\n if (nextlen === 0) {\n max_count = 138;\n min_count = 3;\n\n } else if (curlen === nextlen) {\n max_count = 6;\n min_count = 3;\n\n } else {\n max_count = 7;\n min_count = 4;\n }\n }\n};\n\n\n/* ===========================================================================\n * Send a literal or distance tree in compressed form, using the codes in\n * bl_tree.\n */\nconst send_tree = (s, tree, max_code) => {\n// deflate_state *s;\n// ct_data *tree; /* the tree to be scanned */\n// int max_code; /* and its largest code of non zero frequency */\n\n let n; /* iterates over all tree elements */\n let prevlen = -1; /* last emitted length */\n let curlen; /* length of current code */\n\n let nextlen = tree[0 * 2 + 1]/*.Len*/; /* length of next code */\n\n let count = 0; /* repeat count of the current code */\n let max_count = 7; /* max repeat count */\n let min_count = 4; /* min repeat count */\n\n /* tree[max_code+1].Len = -1; */ /* guard already set */\n if (nextlen === 0) {\n max_count = 138;\n min_count = 3;\n }\n\n for (n = 0; n <= max_code; n++) {\n curlen = nextlen;\n nextlen = tree[(n + 1) * 2 + 1]/*.Len*/;\n\n if (++count < max_count && curlen === nextlen) {\n continue;\n\n } else if (count < min_count) {\n do { send_code(s, curlen, s.bl_tree); } while (--count !== 0);\n\n } else if (curlen !== 0) {\n if (curlen !== prevlen) {\n send_code(s, curlen, s.bl_tree);\n count--;\n }\n //Assert(count >= 3 && count <= 6, \" 3_6?\");\n send_code(s, REP_3_6, s.bl_tree);\n send_bits(s, count - 3, 2);\n\n } else if (count <= 10) {\n send_code(s, REPZ_3_10, s.bl_tree);\n send_bits(s, count - 3, 3);\n\n } else {\n send_code(s, REPZ_11_138, s.bl_tree);\n send_bits(s, count - 11, 7);\n }\n\n count = 0;\n prevlen = curlen;\n if (nextlen === 0) {\n max_count = 138;\n min_count = 3;\n\n } else if (curlen === nextlen) {\n max_count = 6;\n min_count = 3;\n\n } else {\n max_count = 7;\n min_count = 4;\n }\n }\n};\n\n\n/* ===========================================================================\n * Construct the Huffman tree for the bit lengths and return the index in\n * bl_order of the last bit length code to send.\n */\nconst build_bl_tree = (s) => {\n\n let max_blindex; /* index of last bit length code of non zero freq */\n\n /* Determine the bit length frequencies for literal and distance trees */\n scan_tree(s, s.dyn_ltree, s.l_desc.max_code);\n scan_tree(s, s.dyn_dtree, s.d_desc.max_code);\n\n /* Build the bit length tree: */\n build_tree(s, s.bl_desc);\n /* opt_len now includes the length of the tree representations, except\n * the lengths of the bit lengths codes and the 5+5+4 bits for the counts.\n */\n\n /* Determine the number of bit length codes to send. The pkzip format\n * requires that at least 4 bit length codes be sent. (appnote.txt says\n * 3 but the actual value used is 4.)\n */\n for (max_blindex = BL_CODES$1 - 1; max_blindex >= 3; max_blindex--) {\n if (s.bl_tree[bl_order[max_blindex] * 2 + 1]/*.Len*/ !== 0) {\n break;\n }\n }\n /* Update opt_len to include the bit length tree and counts */\n s.opt_len += 3 * (max_blindex + 1) + 5 + 5 + 4;\n //Tracev((stderr, \"\\ndyn trees: dyn %ld, stat %ld\",\n // s->opt_len, s->static_len));\n\n return max_blindex;\n};\n\n\n/* ===========================================================================\n * Send the header for a block using dynamic Huffman trees: the counts, the\n * lengths of the bit length codes, the literal tree and the distance tree.\n * IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4.\n */\nconst send_all_trees = (s, lcodes, dcodes, blcodes) => {\n// deflate_state *s;\n// int lcodes, dcodes, blcodes; /* number of codes for each tree */\n\n let rank; /* index in bl_order */\n\n //Assert (lcodes >= 257 && dcodes >= 1 && blcodes >= 4, \"not enough codes\");\n //Assert (lcodes <= L_CODES && dcodes <= D_CODES && blcodes <= BL_CODES,\n // \"too many codes\");\n //Tracev((stderr, \"\\nbl counts: \"));\n send_bits(s, lcodes - 257, 5); /* not +255 as stated in appnote.txt */\n send_bits(s, dcodes - 1, 5);\n send_bits(s, blcodes - 4, 4); /* not -3 as stated in appnote.txt */\n for (rank = 0; rank < blcodes; rank++) {\n //Tracev((stderr, \"\\nbl code %2d \", bl_order[rank]));\n send_bits(s, s.bl_tree[bl_order[rank] * 2 + 1]/*.Len*/, 3);\n }\n //Tracev((stderr, \"\\nbl tree: sent %ld\", s->bits_sent));\n\n send_tree(s, s.dyn_ltree, lcodes - 1); /* literal tree */\n //Tracev((stderr, \"\\nlit tree: sent %ld\", s->bits_sent));\n\n send_tree(s, s.dyn_dtree, dcodes - 1); /* distance tree */\n //Tracev((stderr, \"\\ndist tree: sent %ld\", s->bits_sent));\n};\n\n\n/* ===========================================================================\n * Check if the data type is TEXT or BINARY, using the following algorithm:\n * - TEXT if the two conditions below are satisfied:\n * a) There are no non-portable control characters belonging to the\n * \"block list\" (0..6, 14..25, 28..31).\n * b) There is at least one printable character belonging to the\n * \"allow list\" (9 {TAB}, 10 {LF}, 13 {CR}, 32..255).\n * - BINARY otherwise.\n * - The following partially-portable control characters form a\n * \"gray list\" that is ignored in this detection algorithm:\n * (7 {BEL}, 8 {BS}, 11 {VT}, 12 {FF}, 26 {SUB}, 27 {ESC}).\n * IN assertion: the fields Freq of dyn_ltree are set.\n */\nconst detect_data_type = (s) => {\n /* block_mask is the bit mask of block-listed bytes\n * set bits 0..6, 14..25, and 28..31\n * 0xf3ffc07f = binary 11110011111111111100000001111111\n */\n let block_mask = 0xf3ffc07f;\n let n;\n\n /* Check for non-textual (\"block-listed\") bytes. */\n for (n = 0; n <= 31; n++, block_mask >>>= 1) {\n if ((block_mask & 1) && (s.dyn_ltree[n * 2]/*.Freq*/ !== 0)) {\n return Z_BINARY;\n }\n }\n\n /* Check for textual (\"allow-listed\") bytes. */\n if (s.dyn_ltree[9 * 2]/*.Freq*/ !== 0 || s.dyn_ltree[10 * 2]/*.Freq*/ !== 0 ||\n s.dyn_ltree[13 * 2]/*.Freq*/ !== 0) {\n return Z_TEXT;\n }\n for (n = 32; n < LITERALS$1; n++) {\n if (s.dyn_ltree[n * 2]/*.Freq*/ !== 0) {\n return Z_TEXT;\n }\n }\n\n /* There are no \"block-listed\" or \"allow-listed\" bytes:\n * this stream either is empty or has tolerated (\"gray-listed\") bytes only.\n */\n return Z_BINARY;\n};\n\n\nlet static_init_done = false;\n\n/* ===========================================================================\n * Initialize the tree data structures for a new zlib stream.\n */\nconst _tr_init$1 = (s) =>\n{\n\n if (!static_init_done) {\n tr_static_init();\n static_init_done = true;\n }\n\n s.l_desc = new TreeDesc(s.dyn_ltree, static_l_desc);\n s.d_desc = new TreeDesc(s.dyn_dtree, static_d_desc);\n s.bl_desc = new TreeDesc(s.bl_tree, static_bl_desc);\n\n s.bi_buf = 0;\n s.bi_valid = 0;\n\n /* Initialize the first block of the first file: */\n init_block(s);\n};\n\n\n/* ===========================================================================\n * Send a stored block\n */\nconst _tr_stored_block$1 = (s, buf, stored_len, last) => {\n//DeflateState *s;\n//charf *buf; /* input block */\n//ulg stored_len; /* length of input block */\n//int last; /* one if this is the last block for a file */\n\n send_bits(s, (STORED_BLOCK << 1) + (last ? 1 : 0), 3); /* send block type */\n bi_windup(s); /* align on byte boundary */\n put_short(s, stored_len);\n put_short(s, ~stored_len);\n if (stored_len) {\n s.pending_buf.set(s.window.subarray(buf, buf + stored_len), s.pending);\n }\n s.pending += stored_len;\n};\n\n\n/* ===========================================================================\n * Send one empty static block to give enough lookahead for inflate.\n * This takes 10 bits, of which 7 may remain in the bit buffer.\n */\nconst _tr_align$1 = (s) => {\n send_bits(s, STATIC_TREES << 1, 3);\n send_code(s, END_BLOCK, static_ltree);\n bi_flush(s);\n};\n\n\n/* ===========================================================================\n * Determine the best encoding for the current block: dynamic trees, static\n * trees or store, and write out the encoded block.\n */\nconst _tr_flush_block$1 = (s, buf, stored_len, last) => {\n//DeflateState *s;\n//charf *buf; /* input block, or NULL if too old */\n//ulg stored_len; /* length of input block */\n//int last; /* one if this is the last block for a file */\n\n let opt_lenb, static_lenb; /* opt_len and static_len in bytes */\n let max_blindex = 0; /* index of last bit length code of non zero freq */\n\n /* Build the Huffman trees unless a stored block is forced */\n if (s.level > 0) {\n\n /* Check if the file is binary or text */\n if (s.strm.data_type === Z_UNKNOWN$1) {\n s.strm.data_type = detect_data_type(s);\n }\n\n /* Construct the literal and distance trees */\n build_tree(s, s.l_desc);\n // Tracev((stderr, \"\\nlit data: dyn %ld, stat %ld\", s->opt_len,\n // s->static_len));\n\n build_tree(s, s.d_desc);\n // Tracev((stderr, \"\\ndist data: dyn %ld, stat %ld\", s->opt_len,\n // s->static_len));\n /* At this point, opt_len and static_len are the total bit lengths of\n * the compressed block data, excluding the tree representations.\n */\n\n /* Build the bit length tree for the above two trees, and get the index\n * in bl_order of the last bit length code to send.\n */\n max_blindex = build_bl_tree(s);\n\n /* Determine the best encoding. Compute the block lengths in bytes. */\n opt_lenb = (s.opt_len + 3 + 7) >>> 3;\n static_lenb = (s.static_len + 3 + 7) >>> 3;\n\n // Tracev((stderr, \"\\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u \",\n // opt_lenb, s->opt_len, static_lenb, s->static_len, stored_len,\n // s->sym_next / 3));\n\n if (static_lenb <= opt_lenb) { opt_lenb = static_lenb; }\n\n } else {\n // Assert(buf != (char*)0, \"lost buf\");\n opt_lenb = static_lenb = stored_len + 5; /* force a stored block */\n }\n\n if ((stored_len + 4 <= opt_lenb) && (buf !== -1)) {\n /* 4: two words for the lengths */\n\n /* The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE.\n * Otherwise we can't have processed more than WSIZE input bytes since\n * the last block flush, because compression would have been\n * successful. If LIT_BUFSIZE <= WSIZE, it is never too late to\n * transform a block into a stored block.\n */\n _tr_stored_block$1(s, buf, stored_len, last);\n\n } else if (s.strategy === Z_FIXED$1 || static_lenb === opt_lenb) {\n\n send_bits(s, (STATIC_TREES << 1) + (last ? 1 : 0), 3);\n compress_block(s, static_ltree, static_dtree);\n\n } else {\n send_bits(s, (DYN_TREES << 1) + (last ? 1 : 0), 3);\n send_all_trees(s, s.l_desc.max_code + 1, s.d_desc.max_code + 1, max_blindex + 1);\n compress_block(s, s.dyn_ltree, s.dyn_dtree);\n }\n // Assert (s->compressed_len == s->bits_sent, \"bad compressed size\");\n /* The above check is made mod 2^32, for files larger than 512 MB\n * and uLong implemented on 32 bits.\n */\n init_block(s);\n\n if (last) {\n bi_windup(s);\n }\n // Tracev((stderr,\"\\ncomprlen %lu(%lu) \", s->compressed_len>>3,\n // s->compressed_len-7*last));\n};\n\n/* ===========================================================================\n * Save the match info and tally the frequency counts. Return true if\n * the current block must be flushed.\n */\nconst _tr_tally$1 = (s, dist, lc) => {\n// deflate_state *s;\n// unsigned dist; /* distance of matched string */\n// unsigned lc; /* match length-MIN_MATCH or unmatched char (if dist==0) */\n\n s.pending_buf[s.sym_buf + s.sym_next++] = dist;\n s.pending_buf[s.sym_buf + s.sym_next++] = dist >> 8;\n s.pending_buf[s.sym_buf + s.sym_next++] = lc;\n if (dist === 0) {\n /* lc is the unmatched char */\n s.dyn_ltree[lc * 2]/*.Freq*/++;\n } else {\n s.matches++;\n /* Here, lc is the match length - MIN_MATCH */\n dist--; /* dist = match distance - 1 */\n //Assert((ush)dist < (ush)MAX_DIST(s) &&\n // (ush)lc <= (ush)(MAX_MATCH-MIN_MATCH) &&\n // (ush)d_code(dist) < (ush)D_CODES, \"_tr_tally: bad match\");\n\n s.dyn_ltree[(_length_code[lc] + LITERALS$1 + 1) * 2]/*.Freq*/++;\n s.dyn_dtree[d_code(dist) * 2]/*.Freq*/++;\n }\n\n return (s.sym_next === s.sym_end);\n};\n\nvar _tr_init_1 = _tr_init$1;\nvar _tr_stored_block_1 = _tr_stored_block$1;\nvar _tr_flush_block_1 = _tr_flush_block$1;\nvar _tr_tally_1 = _tr_tally$1;\nvar _tr_align_1 = _tr_align$1;\n\nvar trees = {\n\t_tr_init: _tr_init_1,\n\t_tr_stored_block: _tr_stored_block_1,\n\t_tr_flush_block: _tr_flush_block_1,\n\t_tr_tally: _tr_tally_1,\n\t_tr_align: _tr_align_1\n};\n\n// Note: adler32 takes 12% for level 0 and 2% for level 6.\n// It isn't worth it to make additional optimizations as in original.\n// Small size is preferable.\n\n// (C) 1995-2013 Jean-loup Gailly and Mark Adler\n// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin\n//\n// This software is provided 'as-is', without any express or implied\n// warranty. In no event will the authors be held liable for any damages\n// arising from the use of this software.\n//\n// Permission is granted to anyone to use this software for any purpose,\n// including commercial applications, and to alter it and redistribute it\n// freely, subject to the following restrictions:\n//\n// 1. The origin of this software must not be misrepresented; you must not\n// claim that you wrote the original software. If you use this software\n// in a product, an acknowledgment in the product documentation would be\n// appreciated but is not required.\n// 2. Altered source versions must be plainly marked as such, and must not be\n// misrepresented as being the original software.\n// 3. This notice may not be removed or altered from any source distribution.\n\nconst adler32 = (adler, buf, len, pos) => {\n let s1 = (adler & 0xffff) |0,\n s2 = ((adler >>> 16) & 0xffff) |0,\n n = 0;\n\n while (len !== 0) {\n // Set limit ~ twice less than 5552, to keep\n // s2 in 31-bits, because we force signed ints.\n // in other case %= will fail.\n n = len > 2000 ? 2000 : len;\n len -= n;\n\n do {\n s1 = (s1 + buf[pos++]) |0;\n s2 = (s2 + s1) |0;\n } while (--n);\n\n s1 %= 65521;\n s2 %= 65521;\n }\n\n return (s1 | (s2 << 16)) |0;\n};\n\n\nvar adler32_1 = adler32;\n\n// Note: we can't get significant speed boost here.\n// So write code to minimize size - no pregenerated tables\n// and array tools dependencies.\n\n// (C) 1995-2013 Jean-loup Gailly and Mark Adler\n// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin\n//\n// This software is provided 'as-is', without any express or implied\n// warranty. In no event will the authors be held liable for any damages\n// arising from the use of this software.\n//\n// Permission is granted to anyone to use this software for any purpose,\n// including commercial applications, and to alter it and redistribute it\n// freely, subject to the following restrictions:\n//\n// 1. The origin of this software must not be misrepresented; you must not\n// claim that you wrote the original software. If you use this software\n// in a product, an acknowledgment in the product documentation would be\n// appreciated but is not required.\n// 2. Altered source versions must be plainly marked as such, and must not be\n// misrepresented as being the original software.\n// 3. This notice may not be removed or altered from any source distribution.\n\n// Use ordinary array, since untyped makes no boost here\nconst makeTable = () => {\n let c, table = [];\n\n for (var n = 0; n < 256; n++) {\n c = n;\n for (var k = 0; k < 8; k++) {\n c = ((c & 1) ? (0xEDB88320 ^ (c >>> 1)) : (c >>> 1));\n }\n table[n] = c;\n }\n\n return table;\n};\n\n// Create table on load. Just 255 signed longs. Not a problem.\nconst crcTable = new Uint32Array(makeTable());\n\n\nconst crc32 = (crc, buf, len, pos) => {\n const t = crcTable;\n const end = pos + len;\n\n crc ^= -1;\n\n for (let i = pos; i < end; i++) {\n crc = (crc >>> 8) ^ t[(crc ^ buf[i]) & 0xFF];\n }\n\n return (crc ^ (-1)); // >>> 0;\n};\n\n\nvar crc32_1 = crc32;\n\n// (C) 1995-2013 Jean-loup Gailly and Mark Adler\n// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin\n//\n// This software is provided 'as-is', without any express or implied\n// warranty. In no event will the authors be held liable for any damages\n// arising from the use of this software.\n//\n// Permission is granted to anyone to use this software for any purpose,\n// including commercial applications, and to alter it and redistribute it\n// freely, subject to the following restrictions:\n//\n// 1. The origin of this software must not be misrepresented; you must not\n// claim that you wrote the original software. If you use this software\n// in a product, an acknowledgment in the product documentation would be\n// appreciated but is not required.\n// 2. Altered source versions must be plainly marked as such, and must not be\n// misrepresented as being the original software.\n// 3. This notice may not be removed or altered from any source distribution.\n\nvar messages = {\n 2: 'need dictionary', /* Z_NEED_DICT 2 */\n 1: 'stream end', /* Z_STREAM_END 1 */\n 0: '', /* Z_OK 0 */\n '-1': 'file error', /* Z_ERRNO (-1) */\n '-2': 'stream error', /* Z_STREAM_ERROR (-2) */\n '-3': 'data error', /* Z_DATA_ERROR (-3) */\n '-4': 'insufficient memory', /* Z_MEM_ERROR (-4) */\n '-5': 'buffer error', /* Z_BUF_ERROR (-5) */\n '-6': 'incompatible version' /* Z_VERSION_ERROR (-6) */\n};\n\n// (C) 1995-2013 Jean-loup Gailly and Mark Adler\n// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin\n//\n// This software is provided 'as-is', without any express or implied\n// warranty. In no event will the authors be held liable for any damages\n// arising from the use of this software.\n//\n// Permission is granted to anyone to use this software for any purpose,\n// including commercial applications, and to alter it and redistribute it\n// freely, subject to the following restrictions:\n//\n// 1. The origin of this software must not be misrepresented; you must not\n// claim that you wrote the original software. If you use this software\n// in a product, an acknowledgment in the product documentation would be\n// appreciated but is not required.\n// 2. Altered source versions must be plainly marked as such, and must not be\n// misrepresented as being the original software.\n// 3. This notice may not be removed or altered from any source distribution.\n\nvar constants$2 = {\n\n /* Allowed flush values; see deflate() and inflate() below for details */\n Z_NO_FLUSH: 0,\n Z_PARTIAL_FLUSH: 1,\n Z_SYNC_FLUSH: 2,\n Z_FULL_FLUSH: 3,\n Z_FINISH: 4,\n Z_BLOCK: 5,\n Z_TREES: 6,\n\n /* Return codes for the compression/decompression functions. Negative values\n * are errors, positive values are used for special but normal events.\n */\n Z_OK: 0,\n Z_STREAM_END: 1,\n Z_NEED_DICT: 2,\n Z_ERRNO: -1,\n Z_STREAM_ERROR: -2,\n Z_DATA_ERROR: -3,\n Z_MEM_ERROR: -4,\n Z_BUF_ERROR: -5,\n //Z_VERSION_ERROR: -6,\n\n /* compression levels */\n Z_NO_COMPRESSION: 0,\n Z_BEST_SPEED: 1,\n Z_BEST_COMPRESSION: 9,\n Z_DEFAULT_COMPRESSION: -1,\n\n\n Z_FILTERED: 1,\n Z_HUFFMAN_ONLY: 2,\n Z_RLE: 3,\n Z_FIXED: 4,\n Z_DEFAULT_STRATEGY: 0,\n\n /* Possible values of the data_type field (though see inflate()) */\n Z_BINARY: 0,\n Z_TEXT: 1,\n //Z_ASCII: 1, // = Z_TEXT (deprecated)\n Z_UNKNOWN: 2,\n\n /* The deflate compression method */\n Z_DEFLATED: 8\n //Z_NULL: null // Use -1 or null inline, depending on var type\n};\n\n// (C) 1995-2013 Jean-loup Gailly and Mark Adler\n// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin\n//\n// This software is provided 'as-is', without any express or implied\n// warranty. In no event will the authors be held liable for any damages\n// arising from the use of this software.\n//\n// Permission is granted to anyone to use this software for any purpose,\n// including commercial applications, and to alter it and redistribute it\n// freely, subject to the following restrictions:\n//\n// 1. The origin of this software must not be misrepresented; you must not\n// claim that you wrote the original software. If you use this software\n// in a product, an acknowledgment in the product documentation would be\n// appreciated but is not required.\n// 2. Altered source versions must be plainly marked as such, and must not be\n// misrepresented as being the original software.\n// 3. This notice may not be removed or altered from any source distribution.\n\nconst { _tr_init, _tr_stored_block, _tr_flush_block, _tr_tally, _tr_align } = trees;\n\n\n\n\n/* Public constants ==========================================================*/\n/* ===========================================================================*/\n\nconst {\n Z_NO_FLUSH: Z_NO_FLUSH$2, Z_PARTIAL_FLUSH, Z_FULL_FLUSH: Z_FULL_FLUSH$1, Z_FINISH: Z_FINISH$3, Z_BLOCK: Z_BLOCK$1,\n Z_OK: Z_OK$3, Z_STREAM_END: Z_STREAM_END$3, Z_STREAM_ERROR: Z_STREAM_ERROR$2, Z_DATA_ERROR: Z_DATA_ERROR$2, Z_BUF_ERROR: Z_BUF_ERROR$1,\n Z_DEFAULT_COMPRESSION: Z_DEFAULT_COMPRESSION$1,\n Z_FILTERED, Z_HUFFMAN_ONLY, Z_RLE, Z_FIXED, Z_DEFAULT_STRATEGY: Z_DEFAULT_STRATEGY$1,\n Z_UNKNOWN,\n Z_DEFLATED: Z_DEFLATED$2\n} = constants$2;\n\n/*============================================================================*/\n\n\nconst MAX_MEM_LEVEL = 9;\n/* Maximum value for memLevel in deflateInit2 */\nconst MAX_WBITS$1 = 15;\n/* 32K LZ77 window */\nconst DEF_MEM_LEVEL = 8;\n\n\nconst LENGTH_CODES = 29;\n/* number of length codes, not counting the special END_BLOCK code */\nconst LITERALS = 256;\n/* number of literal bytes 0..255 */\nconst L_CODES = LITERALS + 1 + LENGTH_CODES;\n/* number of Literal or Length codes, including the END_BLOCK code */\nconst D_CODES = 30;\n/* number of distance codes */\nconst BL_CODES = 19;\n/* number of codes used to transfer the bit lengths */\nconst HEAP_SIZE = 2 * L_CODES + 1;\n/* maximum heap size */\nconst MAX_BITS = 15;\n/* All codes must not exceed MAX_BITS bits */\n\nconst MIN_MATCH = 3;\nconst MAX_MATCH = 258;\nconst MIN_LOOKAHEAD = (MAX_MATCH + MIN_MATCH + 1);\n\nconst PRESET_DICT = 0x20;\n\nconst INIT_STATE = 42; /* zlib header -> BUSY_STATE */\n//#ifdef GZIP\nconst GZIP_STATE = 57; /* gzip header -> BUSY_STATE | EXTRA_STATE */\n//#endif\nconst EXTRA_STATE = 69; /* gzip extra block -> NAME_STATE */\nconst NAME_STATE = 73; /* gzip file name -> COMMENT_STATE */\nconst COMMENT_STATE = 91; /* gzip comment -> HCRC_STATE */\nconst HCRC_STATE = 103; /* gzip header CRC -> BUSY_STATE */\nconst BUSY_STATE = 113; /* deflate -> FINISH_STATE */\nconst FINISH_STATE = 666; /* stream complete */\n\nconst BS_NEED_MORE = 1; /* block not completed, need more input or more output */\nconst BS_BLOCK_DONE = 2; /* block flush performed */\nconst BS_FINISH_STARTED = 3; /* finish started, need only more output at next deflate */\nconst BS_FINISH_DONE = 4; /* finish done, accept no more input or output */\n\nconst OS_CODE = 0x03; // Unix :) . Don't detect, use this default.\n\nconst err = (strm, errorCode) => {\n strm.msg = messages[errorCode];\n return errorCode;\n};\n\nconst rank = (f) => {\n return ((f) * 2) - ((f) > 4 ? 9 : 0);\n};\n\nconst zero = (buf) => {\n let len = buf.length; while (--len >= 0) { buf[len] = 0; }\n};\n\n/* ===========================================================================\n * Slide the hash table when sliding the window down (could be avoided with 32\n * bit values at the expense of memory usage). We slide even when level == 0 to\n * keep the hash table consistent if we switch back to level > 0 later.\n */\nconst slide_hash = (s) => {\n let n, m;\n let p;\n let wsize = s.w_size;\n\n n = s.hash_size;\n p = n;\n do {\n m = s.head[--p];\n s.head[p] = (m >= wsize ? m - wsize : 0);\n } while (--n);\n n = wsize;\n//#ifndef FASTEST\n p = n;\n do {\n m = s.prev[--p];\n s.prev[p] = (m >= wsize ? m - wsize : 0);\n /* If n is not on any hash chain, prev[n] is garbage but\n * its value will never be used.\n */\n } while (--n);\n//#endif\n};\n\n/* eslint-disable new-cap */\nlet HASH_ZLIB = (s, prev, data) => ((prev << s.hash_shift) ^ data) & s.hash_mask;\n// This hash causes less collisions, https://github.com/nodeca/pako/issues/135\n// But breaks binary compatibility\n//let HASH_FAST = (s, prev, data) => ((prev << 8) + (prev >> 8) + (data << 4)) & s.hash_mask;\nlet HASH = HASH_ZLIB;\n\n\n/* =========================================================================\n * Flush as much pending output as possible. All deflate() output, except for\n * some deflate_stored() output, goes through this function so some\n * applications may wish to modify it to avoid allocating a large\n * strm->next_out buffer and copying into it. (See also read_buf()).\n */\nconst flush_pending = (strm) => {\n const s = strm.state;\n\n //_tr_flush_bits(s);\n let len = s.pending;\n if (len > strm.avail_out) {\n len = strm.avail_out;\n }\n if (len === 0) { return; }\n\n strm.output.set(s.pending_buf.subarray(s.pending_out, s.pending_out + len), strm.next_out);\n strm.next_out += len;\n s.pending_out += len;\n strm.total_out += len;\n strm.avail_out -= len;\n s.pending -= len;\n if (s.pending === 0) {\n s.pending_out = 0;\n }\n};\n\n\nconst flush_block_only = (s, last) => {\n _tr_flush_block(s, (s.block_start >= 0 ? s.block_start : -1), s.strstart - s.block_start, last);\n s.block_start = s.strstart;\n flush_pending(s.strm);\n};\n\n\nconst put_byte = (s, b) => {\n s.pending_buf[s.pending++] = b;\n};\n\n\n/* =========================================================================\n * Put a short in the pending buffer. The 16-bit value is put in MSB order.\n * IN assertion: the stream state is correct and there is enough room in\n * pending_buf.\n */\nconst putShortMSB = (s, b) => {\n\n // put_byte(s, (Byte)(b >> 8));\n// put_byte(s, (Byte)(b & 0xff));\n s.pending_buf[s.pending++] = (b >>> 8) & 0xff;\n s.pending_buf[s.pending++] = b & 0xff;\n};\n\n\n/* ===========================================================================\n * Read a new buffer from the current input stream, update the adler32\n * and total number of bytes read. All deflate() input goes through\n * this function so some applications may wish to modify it to avoid\n * allocating a large strm->input buffer and copying from it.\n * (See also flush_pending()).\n */\nconst read_buf = (strm, buf, start, size) => {\n\n let len = strm.avail_in;\n\n if (len > size) { len = size; }\n if (len === 0) { return 0; }\n\n strm.avail_in -= len;\n\n // zmemcpy(buf, strm->next_in, len);\n buf.set(strm.input.subarray(strm.next_in, strm.next_in + len), start);\n if (strm.state.wrap === 1) {\n strm.adler = adler32_1(strm.adler, buf, len, start);\n }\n\n else if (strm.state.wrap === 2) {\n strm.adler = crc32_1(strm.adler, buf, len, start);\n }\n\n strm.next_in += len;\n strm.total_in += len;\n\n return len;\n};\n\n\n/* ===========================================================================\n * Set match_start to the longest match starting at the given string and\n * return its length. Matches shorter or equal to prev_length are discarded,\n * in which case the result is equal to prev_length and match_start is\n * garbage.\n * IN assertions: cur_match is the head of the hash chain for the current\n * string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1\n * OUT assertion: the match length is not greater than s->lookahead.\n */\nconst longest_match = (s, cur_match) => {\n\n let chain_length = s.max_chain_length; /* max hash chain length */\n let scan = s.strstart; /* current string */\n let match; /* matched string */\n let len; /* length of current match */\n let best_len = s.prev_length; /* best match length so far */\n let nice_match = s.nice_match; /* stop if match long enough */\n const limit = (s.strstart > (s.w_size - MIN_LOOKAHEAD)) ?\n s.strstart - (s.w_size - MIN_LOOKAHEAD) : 0/*NIL*/;\n\n const _win = s.window; // shortcut\n\n const wmask = s.w_mask;\n const prev = s.prev;\n\n /* Stop when cur_match becomes <= limit. To simplify the code,\n * we prevent matches with the string of window index 0.\n */\n\n const strend = s.strstart + MAX_MATCH;\n let scan_end1 = _win[scan + best_len - 1];\n let scan_end = _win[scan + best_len];\n\n /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16.\n * It is easy to get rid of this optimization if necessary.\n */\n // Assert(s->hash_bits >= 8 && MAX_MATCH == 258, \"Code too clever\");\n\n /* Do not waste too much time if we already have a good match: */\n if (s.prev_length >= s.good_match) {\n chain_length >>= 2;\n }\n /* Do not look for matches beyond the end of the input. This is necessary\n * to make deflate deterministic.\n */\n if (nice_match > s.lookahead) { nice_match = s.lookahead; }\n\n // Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, \"need lookahead\");\n\n do {\n // Assert(cur_match < s->strstart, \"no future\");\n match = cur_match;\n\n /* Skip to next match if the match length cannot increase\n * or if the match length is less than 2. Note that the checks below\n * for insufficient lookahead only occur occasionally for performance\n * reasons. Therefore uninitialized memory will be accessed, and\n * conditional jumps will be made that depend on those values.\n * However the length of the match is limited to the lookahead, so\n * the output of deflate is not affected by the uninitialized values.\n */\n\n if (_win[match + best_len] !== scan_end ||\n _win[match + best_len - 1] !== scan_end1 ||\n _win[match] !== _win[scan] ||\n _win[++match] !== _win[scan + 1]) {\n continue;\n }\n\n /* The check at best_len-1 can be removed because it will be made\n * again later. (This heuristic is not always a win.)\n * It is not necessary to compare scan[2] and match[2] since they\n * are always equal when the other bytes match, given that\n * the hash keys are equal and that HASH_BITS >= 8.\n */\n scan += 2;\n match++;\n // Assert(*scan == *match, \"match[2]?\");\n\n /* We check for insufficient lookahead only every 8th comparison;\n * the 256th check will be made at strstart+258.\n */\n do {\n /*jshint noempty:false*/\n } while (_win[++scan] === _win[++match] && _win[++scan] === _win[++match] &&\n _win[++scan] === _win[++match] && _win[++scan] === _win[++match] &&\n _win[++scan] === _win[++match] && _win[++scan] === _win[++match] &&\n _win[++scan] === _win[++match] && _win[++scan] === _win[++match] &&\n scan < strend);\n\n // Assert(scan <= s->window+(unsigned)(s->window_size-1), \"wild scan\");\n\n len = MAX_MATCH - (strend - scan);\n scan = strend - MAX_MATCH;\n\n if (len > best_len) {\n s.match_start = cur_match;\n best_len = len;\n if (len >= nice_match) {\n break;\n }\n scan_end1 = _win[scan + best_len - 1];\n scan_end = _win[scan + best_len];\n }\n } while ((cur_match = prev[cur_match & wmask]) > limit && --chain_length !== 0);\n\n if (best_len <= s.lookahead) {\n return best_len;\n }\n return s.lookahead;\n};\n\n\n/* ===========================================================================\n * Fill the window when the lookahead becomes insufficient.\n * Updates strstart and lookahead.\n *\n * IN assertion: lookahead < MIN_LOOKAHEAD\n * OUT assertions: strstart <= window_size-MIN_LOOKAHEAD\n * At least one byte has been read, or avail_in == 0; reads are\n * performed for at least two bytes (required for the zip translate_eol\n * option -- not supported here).\n */\nconst fill_window = (s) => {\n\n const _w_size = s.w_size;\n let n, more, str;\n\n //Assert(s->lookahead < MIN_LOOKAHEAD, \"already enough lookahead\");\n\n do {\n more = s.window_size - s.lookahead - s.strstart;\n\n // JS ints have 32 bit, block below not needed\n /* Deal with !@#$% 64K limit: */\n //if (sizeof(int) <= 2) {\n // if (more == 0 && s->strstart == 0 && s->lookahead == 0) {\n // more = wsize;\n //\n // } else if (more == (unsigned)(-1)) {\n // /* Very unlikely, but possible on 16 bit machine if\n // * strstart == 0 && lookahead == 1 (input done a byte at time)\n // */\n // more--;\n // }\n //}\n\n\n /* If the window is almost full and there is insufficient lookahead,\n * move the upper half to the lower one to make room in the upper half.\n */\n if (s.strstart >= _w_size + (_w_size - MIN_LOOKAHEAD)) {\n\n s.window.set(s.window.subarray(_w_size, _w_size + _w_size - more), 0);\n s.match_start -= _w_size;\n s.strstart -= _w_size;\n /* we now have strstart >= MAX_DIST */\n s.block_start -= _w_size;\n if (s.insert > s.strstart) {\n s.insert = s.strstart;\n }\n slide_hash(s);\n more += _w_size;\n }\n if (s.strm.avail_in === 0) {\n break;\n }\n\n /* If there was no sliding:\n * strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 &&\n * more == window_size - lookahead - strstart\n * => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1)\n * => more >= window_size - 2*WSIZE + 2\n * In the BIG_MEM or MMAP case (not yet supported),\n * window_size == input_size + MIN_LOOKAHEAD &&\n * strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD.\n * Otherwise, window_size == 2*WSIZE so more >= 2.\n * If there was sliding, more >= WSIZE. So in all cases, more >= 2.\n */\n //Assert(more >= 2, \"more < 2\");\n n = read_buf(s.strm, s.window, s.strstart + s.lookahead, more);\n s.lookahead += n;\n\n /* Initialize the hash value now that we have some input: */\n if (s.lookahead + s.insert >= MIN_MATCH) {\n str = s.strstart - s.insert;\n s.ins_h = s.window[str];\n\n /* UPDATE_HASH(s, s->ins_h, s->window[str + 1]); */\n s.ins_h = HASH(s, s.ins_h, s.window[str + 1]);\n//#if MIN_MATCH != 3\n// Call update_hash() MIN_MATCH-3 more times\n//#endif\n while (s.insert) {\n /* UPDATE_HASH(s, s->ins_h, s->window[str + MIN_MATCH-1]); */\n s.ins_h = HASH(s, s.ins_h, s.window[str + MIN_MATCH - 1]);\n\n s.prev[str & s.w_mask] = s.head[s.ins_h];\n s.head[s.ins_h] = str;\n str++;\n s.insert--;\n if (s.lookahead + s.insert < MIN_MATCH) {\n break;\n }\n }\n }\n /* If the whole input has less than MIN_MATCH bytes, ins_h is garbage,\n * but this is not important since only literal bytes will be emitted.\n */\n\n } while (s.lookahead < MIN_LOOKAHEAD && s.strm.avail_in !== 0);\n\n /* If the WIN_INIT bytes after the end of the current data have never been\n * written, then zero those bytes in order to avoid memory check reports of\n * the use of uninitialized (or uninitialised as Julian writes) bytes by\n * the longest match routines. Update the high water mark for the next\n * time through here. WIN_INIT is set to MAX_MATCH since the longest match\n * routines allow scanning to strstart + MAX_MATCH, ignoring lookahead.\n */\n// if (s.high_water < s.window_size) {\n// const curr = s.strstart + s.lookahead;\n// let init = 0;\n//\n// if (s.high_water < curr) {\n// /* Previous high water mark below current data -- zero WIN_INIT\n// * bytes or up to end of window, whichever is less.\n// */\n// init = s.window_size - curr;\n// if (init > WIN_INIT)\n// init = WIN_INIT;\n// zmemzero(s->window + curr, (unsigned)init);\n// s->high_water = curr + init;\n// }\n// else if (s->high_water < (ulg)curr + WIN_INIT) {\n// /* High water mark at or above current data, but below current data\n// * plus WIN_INIT -- zero out to current data plus WIN_INIT, or up\n// * to end of window, whichever is less.\n// */\n// init = (ulg)curr + WIN_INIT - s->high_water;\n// if (init > s->window_size - s->high_water)\n// init = s->window_size - s->high_water;\n// zmemzero(s->window + s->high_water, (unsigned)init);\n// s->high_water += init;\n// }\n// }\n//\n// Assert((ulg)s->strstart <= s->window_size - MIN_LOOKAHEAD,\n// \"not enough room for search\");\n};\n\n/* ===========================================================================\n * Copy without compression as much as possible from the input stream, return\n * the current block state.\n *\n * In case deflateParams() is used to later switch to a non-zero compression\n * level, s->matches (otherwise unused when storing) keeps track of the number\n * of hash table slides to perform. If s->matches is 1, then one hash table\n * slide will be done when switching. If s->matches is 2, the maximum value\n * allowed here, then the hash table will be cleared, since two or more slides\n * is the same as a clear.\n *\n * deflate_stored() is written to minimize the number of times an input byte is\n * copied. It is most efficient with large input and output buffers, which\n * maximizes the opportunites to have a single copy from next_in to next_out.\n */\nconst deflate_stored = (s, flush) => {\n\n /* Smallest worthy block size when not flushing or finishing. By default\n * this is 32K. This can be as small as 507 bytes for memLevel == 1. For\n * large input and output buffers, the stored block size will be larger.\n */\n let min_block = s.pending_buf_size - 5 > s.w_size ? s.w_size : s.pending_buf_size - 5;\n\n /* Copy as many min_block or larger stored blocks directly to next_out as\n * possible. If flushing, copy the remaining available input to next_out as\n * stored blocks, if there is enough space.\n */\n let len, left, have, last = 0;\n let used = s.strm.avail_in;\n do {\n /* Set len to the maximum size block that we can copy directly with the\n * available input data and output space. Set left to how much of that\n * would be copied from what's left in the window.\n */\n len = 65535/* MAX_STORED */; /* maximum deflate stored block length */\n have = (s.bi_valid + 42) >> 3; /* number of header bytes */\n if (s.strm.avail_out < have) { /* need room for header */\n break;\n }\n /* maximum stored block length that will fit in avail_out: */\n have = s.strm.avail_out - have;\n left = s.strstart - s.block_start; /* bytes left in window */\n if (len > left + s.strm.avail_in) {\n len = left + s.strm.avail_in; /* limit len to the input */\n }\n if (len > have) {\n len = have; /* limit len to the output */\n }\n\n /* If the stored block would be less than min_block in length, or if\n * unable to copy all of the available input when flushing, then try\n * copying to the window and the pending buffer instead. Also don't\n * write an empty block when flushing -- deflate() does that.\n */\n if (len < min_block && ((len === 0 && flush !== Z_FINISH$3) ||\n flush === Z_NO_FLUSH$2 ||\n len !== left + s.strm.avail_in)) {\n break;\n }\n\n /* Make a dummy stored block in pending to get the header bytes,\n * including any pending bits. This also updates the debugging counts.\n */\n last = flush === Z_FINISH$3 && len === left + s.strm.avail_in ? 1 : 0;\n _tr_stored_block(s, 0, 0, last);\n\n /* Replace the lengths in the dummy stored block with len. */\n s.pending_buf[s.pending - 4] = len;\n s.pending_buf[s.pending - 3] = len >> 8;\n s.pending_buf[s.pending - 2] = ~len;\n s.pending_buf[s.pending - 1] = ~len >> 8;\n\n /* Write the stored block header bytes. */\n flush_pending(s.strm);\n\n//#ifdef ZLIB_DEBUG\n// /* Update debugging counts for the data about to be copied. */\n// s->compressed_len += len << 3;\n// s->bits_sent += len << 3;\n//#endif\n\n /* Copy uncompressed bytes from the window to next_out. */\n if (left) {\n if (left > len) {\n left = len;\n }\n //zmemcpy(s->strm->next_out, s->window + s->block_start, left);\n s.strm.output.set(s.window.subarray(s.block_start, s.block_start + left), s.strm.next_out);\n s.strm.next_out += left;\n s.strm.avail_out -= left;\n s.strm.total_out += left;\n s.block_start += left;\n len -= left;\n }\n\n /* Copy uncompressed bytes directly from next_in to next_out, updating\n * the check value.\n */\n if (len) {\n read_buf(s.strm, s.strm.output, s.strm.next_out, len);\n s.strm.next_out += len;\n s.strm.avail_out -= len;\n s.strm.total_out += len;\n }\n } while (last === 0);\n\n /* Update the sliding window with the last s->w_size bytes of the copied\n * data, or append all of the copied data to the existing window if less\n * than s->w_size bytes were copied. Also update the number of bytes to\n * insert in the hash tables, in the event that deflateParams() switches to\n * a non-zero compression level.\n */\n used -= s.strm.avail_in; /* number of input bytes directly copied */\n if (used) {\n /* If any input was used, then no unused input remains in the window,\n * therefore s->block_start == s->strstart.\n */\n if (used >= s.w_size) { /* supplant the previous history */\n s.matches = 2; /* clear hash */\n //zmemcpy(s->window, s->strm->next_in - s->w_size, s->w_size);\n s.window.set(s.strm.input.subarray(s.strm.next_in - s.w_size, s.strm.next_in), 0);\n s.strstart = s.w_size;\n s.insert = s.strstart;\n }\n else {\n if (s.window_size - s.strstart <= used) {\n /* Slide the window down. */\n s.strstart -= s.w_size;\n //zmemcpy(s->window, s->window + s->w_size, s->strstart);\n s.window.set(s.window.subarray(s.w_size, s.w_size + s.strstart), 0);\n if (s.matches < 2) {\n s.matches++; /* add a pending slide_hash() */\n }\n if (s.insert > s.strstart) {\n s.insert = s.strstart;\n }\n }\n //zmemcpy(s->window + s->strstart, s->strm->next_in - used, used);\n s.window.set(s.strm.input.subarray(s.strm.next_in - used, s.strm.next_in), s.strstart);\n s.strstart += used;\n s.insert += used > s.w_size - s.insert ? s.w_size - s.insert : used;\n }\n s.block_start = s.strstart;\n }\n if (s.high_water < s.strstart) {\n s.high_water = s.strstart;\n }\n\n /* If the last block was written to next_out, then done. */\n if (last) {\n return BS_FINISH_DONE;\n }\n\n /* If flushing and all input has been consumed, then done. */\n if (flush !== Z_NO_FLUSH$2 && flush !== Z_FINISH$3 &&\n s.strm.avail_in === 0 && s.strstart === s.block_start) {\n return BS_BLOCK_DONE;\n }\n\n /* Fill the window with any remaining input. */\n have = s.window_size - s.strstart;\n if (s.strm.avail_in > have && s.block_start >= s.w_size) {\n /* Slide the window down. */\n s.block_start -= s.w_size;\n s.strstart -= s.w_size;\n //zmemcpy(s->window, s->window + s->w_size, s->strstart);\n s.window.set(s.window.subarray(s.w_size, s.w_size + s.strstart), 0);\n if (s.matches < 2) {\n s.matches++; /* add a pending slide_hash() */\n }\n have += s.w_size; /* more space now */\n if (s.insert > s.strstart) {\n s.insert = s.strstart;\n }\n }\n if (have > s.strm.avail_in) {\n have = s.strm.avail_in;\n }\n if (have) {\n read_buf(s.strm, s.window, s.strstart, have);\n s.strstart += have;\n s.insert += have > s.w_size - s.insert ? s.w_size - s.insert : have;\n }\n if (s.high_water < s.strstart) {\n s.high_water = s.strstart;\n }\n\n /* There was not enough avail_out to write a complete worthy or flushed\n * stored block to next_out. Write a stored block to pending instead, if we\n * have enough input for a worthy block, or if flushing and there is enough\n * room for the remaining input as a stored block in the pending buffer.\n */\n have = (s.bi_valid + 42) >> 3; /* number of header bytes */\n /* maximum stored block length that will fit in pending: */\n have = s.pending_buf_size - have > 65535/* MAX_STORED */ ? 65535/* MAX_STORED */ : s.pending_buf_size - have;\n min_block = have > s.w_size ? s.w_size : have;\n left = s.strstart - s.block_start;\n if (left >= min_block ||\n ((left || flush === Z_FINISH$3) && flush !== Z_NO_FLUSH$2 &&\n s.strm.avail_in === 0 && left <= have)) {\n len = left > have ? have : left;\n last = flush === Z_FINISH$3 && s.strm.avail_in === 0 &&\n len === left ? 1 : 0;\n _tr_stored_block(s, s.block_start, len, last);\n s.block_start += len;\n flush_pending(s.strm);\n }\n\n /* We've done all we can with the available input and output. */\n return last ? BS_FINISH_STARTED : BS_NEED_MORE;\n};\n\n\n/* ===========================================================================\n * Compress as much as possible from the input stream, return the current\n * block state.\n * This function does not perform lazy evaluation of matches and inserts\n * new strings in the dictionary only for unmatched strings or for short\n * matches. It is used only for the fast compression options.\n */\nconst deflate_fast = (s, flush) => {\n\n let hash_head; /* head of the hash chain */\n let bflush; /* set if current block must be flushed */\n\n for (;;) {\n /* Make sure that we always have enough lookahead, except\n * at the end of the input file. We need MAX_MATCH bytes\n * for the next match, plus MIN_MATCH bytes to insert the\n * string following the next match.\n */\n if (s.lookahead < MIN_LOOKAHEAD) {\n fill_window(s);\n if (s.lookahead < MIN_LOOKAHEAD && flush === Z_NO_FLUSH$2) {\n return BS_NEED_MORE;\n }\n if (s.lookahead === 0) {\n break; /* flush the current block */\n }\n }\n\n /* Insert the string window[strstart .. strstart+2] in the\n * dictionary, and set hash_head to the head of the hash chain:\n */\n hash_head = 0/*NIL*/;\n if (s.lookahead >= MIN_MATCH) {\n /*** INSERT_STRING(s, s.strstart, hash_head); ***/\n s.ins_h = HASH(s, s.ins_h, s.window[s.strstart + MIN_MATCH - 1]);\n hash_head = s.prev[s.strstart & s.w_mask] = s.head[s.ins_h];\n s.head[s.ins_h] = s.strstart;\n /***/\n }\n\n /* Find the longest match, discarding those <= prev_length.\n * At this point we have always match_length < MIN_MATCH\n */\n if (hash_head !== 0/*NIL*/ && ((s.strstart - hash_head) <= (s.w_size - MIN_LOOKAHEAD))) {\n /* To simplify the code, we prevent matches with the string\n * of window index 0 (in particular we have to avoid a match\n * of the string with itself at the start of the input file).\n */\n s.match_length = longest_match(s, hash_head);\n /* longest_match() sets match_start */\n }\n if (s.match_length >= MIN_MATCH) {\n // check_match(s, s.strstart, s.match_start, s.match_length); // for debug only\n\n /*** _tr_tally_dist(s, s.strstart - s.match_start,\n s.match_length - MIN_MATCH, bflush); ***/\n bflush = _tr_tally(s, s.strstart - s.match_start, s.match_length - MIN_MATCH);\n\n s.lookahead -= s.match_length;\n\n /* Insert new strings in the hash table only if the match length\n * is not too large. This saves time but degrades compression.\n */\n if (s.match_length <= s.max_lazy_match/*max_insert_length*/ && s.lookahead >= MIN_MATCH) {\n s.match_length--; /* string at strstart already in table */\n do {\n s.strstart++;\n /*** INSERT_STRING(s, s.strstart, hash_head); ***/\n s.ins_h = HASH(s, s.ins_h, s.window[s.strstart + MIN_MATCH - 1]);\n hash_head = s.prev[s.strstart & s.w_mask] = s.head[s.ins_h];\n s.head[s.ins_h] = s.strstart;\n /***/\n /* strstart never exceeds WSIZE-MAX_MATCH, so there are\n * always MIN_MATCH bytes ahead.\n */\n } while (--s.match_length !== 0);\n s.strstart++;\n } else\n {\n s.strstart += s.match_length;\n s.match_length = 0;\n s.ins_h = s.window[s.strstart];\n /* UPDATE_HASH(s, s.ins_h, s.window[s.strstart+1]); */\n s.ins_h = HASH(s, s.ins_h, s.window[s.strstart + 1]);\n\n//#if MIN_MATCH != 3\n// Call UPDATE_HASH() MIN_MATCH-3 more times\n//#endif\n /* If lookahead < MIN_MATCH, ins_h is garbage, but it does not\n * matter since it will be recomputed at next deflate call.\n */\n }\n } else {\n /* No match, output a literal byte */\n //Tracevv((stderr,\"%c\", s.window[s.strstart]));\n /*** _tr_tally_lit(s, s.window[s.strstart], bflush); ***/\n bflush = _tr_tally(s, 0, s.window[s.strstart]);\n\n s.lookahead--;\n s.strstart++;\n }\n if (bflush) {\n /*** FLUSH_BLOCK(s, 0); ***/\n flush_block_only(s, false);\n if (s.strm.avail_out === 0) {\n return BS_NEED_MORE;\n }\n /***/\n }\n }\n s.insert = ((s.strstart < (MIN_MATCH - 1)) ? s.strstart : MIN_MATCH - 1);\n if (flush === Z_FINISH$3) {\n /*** FLUSH_BLOCK(s, 1); ***/\n flush_block_only(s, true);\n if (s.strm.avail_out === 0) {\n return BS_FINISH_STARTED;\n }\n /***/\n return BS_FINISH_DONE;\n }\n if (s.sym_next) {\n /*** FLUSH_BLOCK(s, 0); ***/\n flush_block_only(s, false);\n if (s.strm.avail_out === 0) {\n return BS_NEED_MORE;\n }\n /***/\n }\n return BS_BLOCK_DONE;\n};\n\n/* ===========================================================================\n * Same as above, but achieves better compression. We use a lazy\n * evaluation for matches: a match is finally adopted only if there is\n * no better match at the next window position.\n */\nconst deflate_slow = (s, flush) => {\n\n let hash_head; /* head of hash chain */\n let bflush; /* set if current block must be flushed */\n\n let max_insert;\n\n /* Process the input block. */\n for (;;) {\n /* Make sure that we always have enough lookahead, except\n * at the end of the input file. We need MAX_MATCH bytes\n * for the next match, plus MIN_MATCH bytes to insert the\n * string following the next match.\n */\n if (s.lookahead < MIN_LOOKAHEAD) {\n fill_window(s);\n if (s.lookahead < MIN_LOOKAHEAD && flush === Z_NO_FLUSH$2) {\n return BS_NEED_MORE;\n }\n if (s.lookahead === 0) { break; } /* flush the current block */\n }\n\n /* Insert the string window[strstart .. strstart+2] in the\n * dictionary, and set hash_head to the head of the hash chain:\n */\n hash_head = 0/*NIL*/;\n if (s.lookahead >= MIN_MATCH) {\n /*** INSERT_STRING(s, s.strstart, hash_head); ***/\n s.ins_h = HASH(s, s.ins_h, s.window[s.strstart + MIN_MATCH - 1]);\n hash_head = s.prev[s.strstart & s.w_mask] = s.head[s.ins_h];\n s.head[s.ins_h] = s.strstart;\n /***/\n }\n\n /* Find the longest match, discarding those <= prev_length.\n */\n s.prev_length = s.match_length;\n s.prev_match = s.match_start;\n s.match_length = MIN_MATCH - 1;\n\n if (hash_head !== 0/*NIL*/ && s.prev_length < s.max_lazy_match &&\n s.strstart - hash_head <= (s.w_size - MIN_LOOKAHEAD)/*MAX_DIST(s)*/) {\n /* To simplify the code, we prevent matches with the string\n * of window index 0 (in particular we have to avoid a match\n * of the string with itself at the start of the input file).\n */\n s.match_length = longest_match(s, hash_head);\n /* longest_match() sets match_start */\n\n if (s.match_length <= 5 &&\n (s.strategy === Z_FILTERED || (s.match_length === MIN_MATCH && s.strstart - s.match_start > 4096/*TOO_FAR*/))) {\n\n /* If prev_match is also MIN_MATCH, match_start is garbage\n * but we will ignore the current match anyway.\n */\n s.match_length = MIN_MATCH - 1;\n }\n }\n /* If there was a match at the previous step and the current\n * match is not better, output the previous match:\n */\n if (s.prev_length >= MIN_MATCH && s.match_length <= s.prev_length) {\n max_insert = s.strstart + s.lookahead - MIN_MATCH;\n /* Do not insert strings in hash table beyond this. */\n\n //check_match(s, s.strstart-1, s.prev_match, s.prev_length);\n\n /***_tr_tally_dist(s, s.strstart - 1 - s.prev_match,\n s.prev_length - MIN_MATCH, bflush);***/\n bflush = _tr_tally(s, s.strstart - 1 - s.prev_match, s.prev_length - MIN_MATCH);\n /* Insert in hash table all strings up to the end of the match.\n * strstart-1 and strstart are already inserted. If there is not\n * enough lookahead, the last two strings are not inserted in\n * the hash table.\n */\n s.lookahead -= s.prev_length - 1;\n s.prev_length -= 2;\n do {\n if (++s.strstart <= max_insert) {\n /*** INSERT_STRING(s, s.strstart, hash_head); ***/\n s.ins_h = HASH(s, s.ins_h, s.window[s.strstart + MIN_MATCH - 1]);\n hash_head = s.prev[s.strstart & s.w_mask] = s.head[s.ins_h];\n s.head[s.ins_h] = s.strstart;\n /***/\n }\n } while (--s.prev_length !== 0);\n s.match_available = 0;\n s.match_length = MIN_MATCH - 1;\n s.strstart++;\n\n if (bflush) {\n /*** FLUSH_BLOCK(s, 0); ***/\n flush_block_only(s, false);\n if (s.strm.avail_out === 0) {\n return BS_NEED_MORE;\n }\n /***/\n }\n\n } else if (s.match_available) {\n /* If there was no match at the previous position, output a\n * single literal. If there was a match but the current match\n * is longer, truncate the previous match to a single literal.\n */\n //Tracevv((stderr,\"%c\", s->window[s->strstart-1]));\n /*** _tr_tally_lit(s, s.window[s.strstart-1], bflush); ***/\n bflush = _tr_tally(s, 0, s.window[s.strstart - 1]);\n\n if (bflush) {\n /*** FLUSH_BLOCK_ONLY(s, 0) ***/\n flush_block_only(s, false);\n /***/\n }\n s.strstart++;\n s.lookahead--;\n if (s.strm.avail_out === 0) {\n return BS_NEED_MORE;\n }\n } else {\n /* There is no previous match to compare with, wait for\n * the next step to decide.\n */\n s.match_available = 1;\n s.strstart++;\n s.lookahead--;\n }\n }\n //Assert (flush != Z_NO_FLUSH, \"no flush?\");\n if (s.match_available) {\n //Tracevv((stderr,\"%c\", s->window[s->strstart-1]));\n /*** _tr_tally_lit(s, s.window[s.strstart-1], bflush); ***/\n bflush = _tr_tally(s, 0, s.window[s.strstart - 1]);\n\n s.match_available = 0;\n }\n s.insert = s.strstart < MIN_MATCH - 1 ? s.strstart : MIN_MATCH - 1;\n if (flush === Z_FINISH$3) {\n /*** FLUSH_BLOCK(s, 1); ***/\n flush_block_only(s, true);\n if (s.strm.avail_out === 0) {\n return BS_FINISH_STARTED;\n }\n /***/\n return BS_FINISH_DONE;\n }\n if (s.sym_next) {\n /*** FLUSH_BLOCK(s, 0); ***/\n flush_block_only(s, false);\n if (s.strm.avail_out === 0) {\n return BS_NEED_MORE;\n }\n /***/\n }\n\n return BS_BLOCK_DONE;\n};\n\n\n/* ===========================================================================\n * For Z_RLE, simply look for runs of bytes, generate matches only of distance\n * one. Do not maintain a hash table. (It will be regenerated if this run of\n * deflate switches away from Z_RLE.)\n */\nconst deflate_rle = (s, flush) => {\n\n let bflush; /* set if current block must be flushed */\n let prev; /* byte at distance one to match */\n let scan, strend; /* scan goes up to strend for length of run */\n\n const _win = s.window;\n\n for (;;) {\n /* Make sure that we always have enough lookahead, except\n * at the end of the input file. We need MAX_MATCH bytes\n * for the longest run, plus one for the unrolled loop.\n */\n if (s.lookahead <= MAX_MATCH) {\n fill_window(s);\n if (s.lookahead <= MAX_MATCH && flush === Z_NO_FLUSH$2) {\n return BS_NEED_MORE;\n }\n if (s.lookahead === 0) { break; } /* flush the current block */\n }\n\n /* See how many times the previous byte repeats */\n s.match_length = 0;\n if (s.lookahead >= MIN_MATCH && s.strstart > 0) {\n scan = s.strstart - 1;\n prev = _win[scan];\n if (prev === _win[++scan] && prev === _win[++scan] && prev === _win[++scan]) {\n strend = s.strstart + MAX_MATCH;\n do {\n /*jshint noempty:false*/\n } while (prev === _win[++scan] && prev === _win[++scan] &&\n prev === _win[++scan] && prev === _win[++scan] &&\n prev === _win[++scan] && prev === _win[++scan] &&\n prev === _win[++scan] && prev === _win[++scan] &&\n scan < strend);\n s.match_length = MAX_MATCH - (strend - scan);\n if (s.match_length > s.lookahead) {\n s.match_length = s.lookahead;\n }\n }\n //Assert(scan <= s->window+(uInt)(s->window_size-1), \"wild scan\");\n }\n\n /* Emit match if have run of MIN_MATCH or longer, else emit literal */\n if (s.match_length >= MIN_MATCH) {\n //check_match(s, s.strstart, s.strstart - 1, s.match_length);\n\n /*** _tr_tally_dist(s, 1, s.match_length - MIN_MATCH, bflush); ***/\n bflush = _tr_tally(s, 1, s.match_length - MIN_MATCH);\n\n s.lookahead -= s.match_length;\n s.strstart += s.match_length;\n s.match_length = 0;\n } else {\n /* No match, output a literal byte */\n //Tracevv((stderr,\"%c\", s->window[s->strstart]));\n /*** _tr_tally_lit(s, s.window[s.strstart], bflush); ***/\n bflush = _tr_tally(s, 0, s.window[s.strstart]);\n\n s.lookahead--;\n s.strstart++;\n }\n if (bflush) {\n /*** FLUSH_BLOCK(s, 0); ***/\n flush_block_only(s, false);\n if (s.strm.avail_out === 0) {\n return BS_NEED_MORE;\n }\n /***/\n }\n }\n s.insert = 0;\n if (flush === Z_FINISH$3) {\n /*** FLUSH_BLOCK(s, 1); ***/\n flush_block_only(s, true);\n if (s.strm.avail_out === 0) {\n return BS_FINISH_STARTED;\n }\n /***/\n return BS_FINISH_DONE;\n }\n if (s.sym_next) {\n /*** FLUSH_BLOCK(s, 0); ***/\n flush_block_only(s, false);\n if (s.strm.avail_out === 0) {\n return BS_NEED_MORE;\n }\n /***/\n }\n return BS_BLOCK_DONE;\n};\n\n/* ===========================================================================\n * For Z_HUFFMAN_ONLY, do not look for matches. Do not maintain a hash table.\n * (It will be regenerated if this run of deflate switches away from Huffman.)\n */\nconst deflate_huff = (s, flush) => {\n\n let bflush; /* set if current block must be flushed */\n\n for (;;) {\n /* Make sure that we have a literal to write. */\n if (s.lookahead === 0) {\n fill_window(s);\n if (s.lookahead === 0) {\n if (flush === Z_NO_FLUSH$2) {\n return BS_NEED_MORE;\n }\n break; /* flush the current block */\n }\n }\n\n /* Output a literal byte */\n s.match_length = 0;\n //Tracevv((stderr,\"%c\", s->window[s->strstart]));\n /*** _tr_tally_lit(s, s.window[s.strstart], bflush); ***/\n bflush = _tr_tally(s, 0, s.window[s.strstart]);\n s.lookahead--;\n s.strstart++;\n if (bflush) {\n /*** FLUSH_BLOCK(s, 0); ***/\n flush_block_only(s, false);\n if (s.strm.avail_out === 0) {\n return BS_NEED_MORE;\n }\n /***/\n }\n }\n s.insert = 0;\n if (flush === Z_FINISH$3) {\n /*** FLUSH_BLOCK(s, 1); ***/\n flush_block_only(s, true);\n if (s.strm.avail_out === 0) {\n return BS_FINISH_STARTED;\n }\n /***/\n return BS_FINISH_DONE;\n }\n if (s.sym_next) {\n /*** FLUSH_BLOCK(s, 0); ***/\n flush_block_only(s, false);\n if (s.strm.avail_out === 0) {\n return BS_NEED_MORE;\n }\n /***/\n }\n return BS_BLOCK_DONE;\n};\n\n/* Values for max_lazy_match, good_match and max_chain_length, depending on\n * the desired pack level (0..9). The values given below have been tuned to\n * exclude worst case performance for pathological files. Better values may be\n * found for specific files.\n */\nfunction Config(good_length, max_lazy, nice_length, max_chain, func) {\n\n this.good_length = good_length;\n this.max_lazy = max_lazy;\n this.nice_length = nice_length;\n this.max_chain = max_chain;\n this.func = func;\n}\n\nconst configuration_table = [\n /* good lazy nice chain */\n new Config(0, 0, 0, 0, deflate_stored), /* 0 store only */\n new Config(4, 4, 8, 4, deflate_fast), /* 1 max speed, no lazy matches */\n new Config(4, 5, 16, 8, deflate_fast), /* 2 */\n new Config(4, 6, 32, 32, deflate_fast), /* 3 */\n\n new Config(4, 4, 16, 16, deflate_slow), /* 4 lazy matches */\n new Config(8, 16, 32, 32, deflate_slow), /* 5 */\n new Config(8, 16, 128, 128, deflate_slow), /* 6 */\n new Config(8, 32, 128, 256, deflate_slow), /* 7 */\n new Config(32, 128, 258, 1024, deflate_slow), /* 8 */\n new Config(32, 258, 258, 4096, deflate_slow) /* 9 max compression */\n];\n\n\n/* ===========================================================================\n * Initialize the \"longest match\" routines for a new zlib stream\n */\nconst lm_init = (s) => {\n\n s.window_size = 2 * s.w_size;\n\n /*** CLEAR_HASH(s); ***/\n zero(s.head); // Fill with NIL (= 0);\n\n /* Set the default configuration parameters:\n */\n s.max_lazy_match = configuration_table[s.level].max_lazy;\n s.good_match = configuration_table[s.level].good_length;\n s.nice_match = configuration_table[s.level].nice_length;\n s.max_chain_length = configuration_table[s.level].max_chain;\n\n s.strstart = 0;\n s.block_start = 0;\n s.lookahead = 0;\n s.insert = 0;\n s.match_length = s.prev_length = MIN_MATCH - 1;\n s.match_available = 0;\n s.ins_h = 0;\n};\n\n\nfunction DeflateState() {\n this.strm = null; /* pointer back to this zlib stream */\n this.status = 0; /* as the name implies */\n this.pending_buf = null; /* output still pending */\n this.pending_buf_size = 0; /* size of pending_buf */\n this.pending_out = 0; /* next pending byte to output to the stream */\n this.pending = 0; /* nb of bytes in the pending buffer */\n this.wrap = 0; /* bit 0 true for zlib, bit 1 true for gzip */\n this.gzhead = null; /* gzip header information to write */\n this.gzindex = 0; /* where in extra, name, or comment */\n this.method = Z_DEFLATED$2; /* can only be DEFLATED */\n this.last_flush = -1; /* value of flush param for previous deflate call */\n\n this.w_size = 0; /* LZ77 window size (32K by default) */\n this.w_bits = 0; /* log2(w_size) (8..16) */\n this.w_mask = 0; /* w_size - 1 */\n\n this.window = null;\n /* Sliding window. Input bytes are read into the second half of the window,\n * and move to the first half later to keep a dictionary of at least wSize\n * bytes. With this organization, matches are limited to a distance of\n * wSize-MAX_MATCH bytes, but this ensures that IO is always\n * performed with a length multiple of the block size.\n */\n\n this.window_size = 0;\n /* Actual size of window: 2*wSize, except when the user input buffer\n * is directly used as sliding window.\n */\n\n this.prev = null;\n /* Link to older string with same hash index. To limit the size of this\n * array to 64K, this link is maintained only for the last 32K strings.\n * An index in this array is thus a window index modulo 32K.\n */\n\n this.head = null; /* Heads of the hash chains or NIL. */\n\n this.ins_h = 0; /* hash index of string to be inserted */\n this.hash_size = 0; /* number of elements in hash table */\n this.hash_bits = 0; /* log2(hash_size) */\n this.hash_mask = 0; /* hash_size-1 */\n\n this.hash_shift = 0;\n /* Number of bits by which ins_h must be shifted at each input\n * step. It must be such that after MIN_MATCH steps, the oldest\n * byte no longer takes part in the hash key, that is:\n * hash_shift * MIN_MATCH >= hash_bits\n */\n\n this.block_start = 0;\n /* Window position at the beginning of the current output block. Gets\n * negative when the window is moved backwards.\n */\n\n this.match_length = 0; /* length of best match */\n this.prev_match = 0; /* previous match */\n this.match_available = 0; /* set if previous match exists */\n this.strstart = 0; /* start of string to insert */\n this.match_start = 0; /* start of matching string */\n this.lookahead = 0; /* number of valid bytes ahead in window */\n\n this.prev_length = 0;\n /* Length of the best match at previous step. Matches not greater than this\n * are discarded. This is used in the lazy match evaluation.\n */\n\n this.max_chain_length = 0;\n /* To speed up deflation, hash chains are never searched beyond this\n * length. A higher limit improves compression ratio but degrades the\n * speed.\n */\n\n this.max_lazy_match = 0;\n /* Attempt to find a better match only when the current match is strictly\n * smaller than this value. This mechanism is used only for compression\n * levels >= 4.\n */\n // That's alias to max_lazy_match, don't use directly\n //this.max_insert_length = 0;\n /* Insert new strings in the hash table only if the match length is not\n * greater than this length. This saves time but degrades compression.\n * max_insert_length is used only for compression levels <= 3.\n */\n\n this.level = 0; /* compression level (1..9) */\n this.strategy = 0; /* favor or force Huffman coding*/\n\n this.good_match = 0;\n /* Use a faster search when the previous match is longer than this */\n\n this.nice_match = 0; /* Stop searching when current match exceeds this */\n\n /* used by trees.c: */\n\n /* Didn't use ct_data typedef below to suppress compiler warning */\n\n // struct ct_data_s dyn_ltree[HEAP_SIZE]; /* literal and length tree */\n // struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */\n // struct ct_data_s bl_tree[2*BL_CODES+1]; /* Huffman tree for bit lengths */\n\n // Use flat array of DOUBLE size, with interleaved fata,\n // because JS does not support effective\n this.dyn_ltree = new Uint16Array(HEAP_SIZE * 2);\n this.dyn_dtree = new Uint16Array((2 * D_CODES + 1) * 2);\n this.bl_tree = new Uint16Array((2 * BL_CODES + 1) * 2);\n zero(this.dyn_ltree);\n zero(this.dyn_dtree);\n zero(this.bl_tree);\n\n this.l_desc = null; /* desc. for literal tree */\n this.d_desc = null; /* desc. for distance tree */\n this.bl_desc = null; /* desc. for bit length tree */\n\n //ush bl_count[MAX_BITS+1];\n this.bl_count = new Uint16Array(MAX_BITS + 1);\n /* number of codes at each bit length for an optimal tree */\n\n //int heap[2*L_CODES+1]; /* heap used to build the Huffman trees */\n this.heap = new Uint16Array(2 * L_CODES + 1); /* heap used to build the Huffman trees */\n zero(this.heap);\n\n this.heap_len = 0; /* number of elements in the heap */\n this.heap_max = 0; /* element of largest frequency */\n /* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used.\n * The same heap array is used to build all trees.\n */\n\n this.depth = new Uint16Array(2 * L_CODES + 1); //uch depth[2*L_CODES+1];\n zero(this.depth);\n /* Depth of each subtree used as tie breaker for trees of equal frequency\n */\n\n this.sym_buf = 0; /* buffer for distances and literals/lengths */\n\n this.lit_bufsize = 0;\n /* Size of match buffer for literals/lengths. There are 4 reasons for\n * limiting lit_bufsize to 64K:\n * - frequencies can be kept in 16 bit counters\n * - if compression is not successful for the first block, all input\n * data is still in the window so we can still emit a stored block even\n * when input comes from standard input. (This can also be done for\n * all blocks if lit_bufsize is not greater than 32K.)\n * - if compression is not successful for a file smaller than 64K, we can\n * even emit a stored file instead of a stored block (saving 5 bytes).\n * This is applicable only for zip (not gzip or zlib).\n * - creating new Huffman trees less frequently may not provide fast\n * adaptation to changes in the input data statistics. (Take for\n * example a binary file with poorly compressible code followed by\n * a highly compressible string table.) Smaller buffer sizes give\n * fast adaptation but have of course the overhead of transmitting\n * trees more frequently.\n * - I can't count above 4\n */\n\n this.sym_next = 0; /* running index in sym_buf */\n this.sym_end = 0; /* symbol table full when sym_next reaches this */\n\n this.opt_len = 0; /* bit length of current block with optimal trees */\n this.static_len = 0; /* bit length of current block with static trees */\n this.matches = 0; /* number of string matches in current block */\n this.insert = 0; /* bytes at end of window left to insert */\n\n\n this.bi_buf = 0;\n /* Output buffer. bits are inserted starting at the bottom (least\n * significant bits).\n */\n this.bi_valid = 0;\n /* Number of valid bits in bi_buf. All bits above the last valid bit\n * are always zero.\n */\n\n // Used for window memory init. We safely ignore it for JS. That makes\n // sense only for pointers and memory check tools.\n //this.high_water = 0;\n /* High water mark offset in window for initialized bytes -- bytes above\n * this are set to zero in order to avoid memory check warnings when\n * longest match routines access bytes past the input. This is then\n * updated to the new high water mark.\n */\n}\n\n\n/* =========================================================================\n * Check for a valid deflate stream state. Return 0 if ok, 1 if not.\n */\nconst deflateStateCheck = (strm) => {\n\n if (!strm) {\n return 1;\n }\n const s = strm.state;\n if (!s || s.strm !== strm || (s.status !== INIT_STATE &&\n//#ifdef GZIP\n s.status !== GZIP_STATE &&\n//#endif\n s.status !== EXTRA_STATE &&\n s.status !== NAME_STATE &&\n s.status !== COMMENT_STATE &&\n s.status !== HCRC_STATE &&\n s.status !== BUSY_STATE &&\n s.status !== FINISH_STATE)) {\n return 1;\n }\n return 0;\n};\n\n\nconst deflateResetKeep = (strm) => {\n\n if (deflateStateCheck(strm)) {\n return err(strm, Z_STREAM_ERROR$2);\n }\n\n strm.total_in = strm.total_out = 0;\n strm.data_type = Z_UNKNOWN;\n\n const s = strm.state;\n s.pending = 0;\n s.pending_out = 0;\n\n if (s.wrap < 0) {\n s.wrap = -s.wrap;\n /* was made negative by deflate(..., Z_FINISH); */\n }\n s.status =\n//#ifdef GZIP\n s.wrap === 2 ? GZIP_STATE :\n//#endif\n s.wrap ? INIT_STATE : BUSY_STATE;\n strm.adler = (s.wrap === 2) ?\n 0 // crc32(0, Z_NULL, 0)\n :\n 1; // adler32(0, Z_NULL, 0)\n s.last_flush = -2;\n _tr_init(s);\n return Z_OK$3;\n};\n\n\nconst deflateReset = (strm) => {\n\n const ret = deflateResetKeep(strm);\n if (ret === Z_OK$3) {\n lm_init(strm.state);\n }\n return ret;\n};\n\n\nconst deflateSetHeader = (strm, head) => {\n\n if (deflateStateCheck(strm) || strm.state.wrap !== 2) {\n return Z_STREAM_ERROR$2;\n }\n strm.state.gzhead = head;\n return Z_OK$3;\n};\n\n\nconst deflateInit2 = (strm, level, method, windowBits, memLevel, strategy) => {\n\n if (!strm) { // === Z_NULL\n return Z_STREAM_ERROR$2;\n }\n let wrap = 1;\n\n if (level === Z_DEFAULT_COMPRESSION$1) {\n level = 6;\n }\n\n if (windowBits < 0) { /* suppress zlib wrapper */\n wrap = 0;\n windowBits = -windowBits;\n }\n\n else if (windowBits > 15) {\n wrap = 2; /* write gzip wrapper instead */\n windowBits -= 16;\n }\n\n\n if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || method !== Z_DEFLATED$2 ||\n windowBits < 8 || windowBits > 15 || level < 0 || level > 9 ||\n strategy < 0 || strategy > Z_FIXED || (windowBits === 8 && wrap !== 1)) {\n return err(strm, Z_STREAM_ERROR$2);\n }\n\n\n if (windowBits === 8) {\n windowBits = 9;\n }\n /* until 256-byte window bug fixed */\n\n const s = new DeflateState();\n\n strm.state = s;\n s.strm = strm;\n s.status = INIT_STATE; /* to pass state test in deflateReset() */\n\n s.wrap = wrap;\n s.gzhead = null;\n s.w_bits = windowBits;\n s.w_size = 1 << s.w_bits;\n s.w_mask = s.w_size - 1;\n\n s.hash_bits = memLevel + 7;\n s.hash_size = 1 << s.hash_bits;\n s.hash_mask = s.hash_size - 1;\n s.hash_shift = ~~((s.hash_bits + MIN_MATCH - 1) / MIN_MATCH);\n\n s.window = new Uint8Array(s.w_size * 2);\n s.head = new Uint16Array(s.hash_size);\n s.prev = new Uint16Array(s.w_size);\n\n // Don't need mem init magic for JS.\n //s.high_water = 0; /* nothing written to s->window yet */\n\n s.lit_bufsize = 1 << (memLevel + 6); /* 16K elements by default */\n\n /* We overlay pending_buf and sym_buf. This works since the average size\n * for length/distance pairs over any compressed block is assured to be 31\n * bits or less.\n *\n * Analysis: The longest fixed codes are a length code of 8 bits plus 5\n * extra bits, for lengths 131 to 257. The longest fixed distance codes are\n * 5 bits plus 13 extra bits, for distances 16385 to 32768. The longest\n * possible fixed-codes length/distance pair is then 31 bits total.\n *\n * sym_buf starts one-fourth of the way into pending_buf. So there are\n * three bytes in sym_buf for every four bytes in pending_buf. Each symbol\n * in sym_buf is three bytes -- two for the distance and one for the\n * literal/length. As each symbol is consumed, the pointer to the next\n * sym_buf value to read moves forward three bytes. From that symbol, up to\n * 31 bits are written to pending_buf. The closest the written pending_buf\n * bits gets to the next sym_buf symbol to read is just before the last\n * code is written. At that time, 31*(n-2) bits have been written, just\n * after 24*(n-2) bits have been consumed from sym_buf. sym_buf starts at\n * 8*n bits into pending_buf. (Note that the symbol buffer fills when n-1\n * symbols are written.) The closest the writing gets to what is unread is\n * then n+14 bits. Here n is lit_bufsize, which is 16384 by default, and\n * can range from 128 to 32768.\n *\n * Therefore, at a minimum, there are 142 bits of space between what is\n * written and what is read in the overlain buffers, so the symbols cannot\n * be overwritten by the compressed data. That space is actually 139 bits,\n * due to the three-bit fixed-code block header.\n *\n * That covers the case where either Z_FIXED is specified, forcing fixed\n * codes, or when the use of fixed codes is chosen, because that choice\n * results in a smaller compressed block than dynamic codes. That latter\n * condition then assures that the above analysis also covers all dynamic\n * blocks. A dynamic-code block will only be chosen to be emitted if it has\n * fewer bits than a fixed-code block would for the same set of symbols.\n * Therefore its average symbol length is assured to be less than 31. So\n * the compressed data for a dynamic block also cannot overwrite the\n * symbols from which it is being constructed.\n */\n\n s.pending_buf_size = s.lit_bufsize * 4;\n s.pending_buf = new Uint8Array(s.pending_buf_size);\n\n // It is offset from `s.pending_buf` (size is `s.lit_bufsize * 2`)\n //s->sym_buf = s->pending_buf + s->lit_bufsize;\n s.sym_buf = s.lit_bufsize;\n\n //s->sym_end = (s->lit_bufsize - 1) * 3;\n s.sym_end = (s.lit_bufsize - 1) * 3;\n /* We avoid equality with lit_bufsize*3 because of wraparound at 64K\n * on 16 bit machines and because stored blocks are restricted to\n * 64K-1 bytes.\n */\n\n s.level = level;\n s.strategy = strategy;\n s.method = method;\n\n return deflateReset(strm);\n};\n\nconst deflateInit = (strm, level) => {\n\n return deflateInit2(strm, level, Z_DEFLATED$2, MAX_WBITS$1, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY$1);\n};\n\n\n/* ========================================================================= */\nconst deflate$2 = (strm, flush) => {\n\n if (deflateStateCheck(strm) || flush > Z_BLOCK$1 || flush < 0) {\n return strm ? err(strm, Z_STREAM_ERROR$2) : Z_STREAM_ERROR$2;\n }\n\n const s = strm.state;\n\n if (!strm.output ||\n (strm.avail_in !== 0 && !strm.input) ||\n (s.status === FINISH_STATE && flush !== Z_FINISH$3)) {\n return err(strm, (strm.avail_out === 0) ? Z_BUF_ERROR$1 : Z_STREAM_ERROR$2);\n }\n\n const old_flush = s.last_flush;\n s.last_flush = flush;\n\n /* Flush as much pending output as possible */\n if (s.pending !== 0) {\n flush_pending(strm);\n if (strm.avail_out === 0) {\n /* Since avail_out is 0, deflate will be called again with\n * more output space, but possibly with both pending and\n * avail_in equal to zero. There won't be anything to do,\n * but this is not an error situation so make sure we\n * return OK instead of BUF_ERROR at next call of deflate:\n */\n s.last_flush = -1;\n return Z_OK$3;\n }\n\n /* Make sure there is something to do and avoid duplicate consecutive\n * flushes. For repeated and useless calls with Z_FINISH, we keep\n * returning Z_STREAM_END instead of Z_BUF_ERROR.\n */\n } else if (strm.avail_in === 0 && rank(flush) <= rank(old_flush) &&\n flush !== Z_FINISH$3) {\n return err(strm, Z_BUF_ERROR$1);\n }\n\n /* User must not provide more input after the first FINISH: */\n if (s.status === FINISH_STATE && strm.avail_in !== 0) {\n return err(strm, Z_BUF_ERROR$1);\n }\n\n /* Write the header */\n if (s.status === INIT_STATE && s.wrap === 0) {\n s.status = BUSY_STATE;\n }\n if (s.status === INIT_STATE) {\n /* zlib header */\n let header = (Z_DEFLATED$2 + ((s.w_bits - 8) << 4)) << 8;\n let level_flags = -1;\n\n if (s.strategy >= Z_HUFFMAN_ONLY || s.level < 2) {\n level_flags = 0;\n } else if (s.level < 6) {\n level_flags = 1;\n } else if (s.level === 6) {\n level_flags = 2;\n } else {\n level_flags = 3;\n }\n header |= (level_flags << 6);\n if (s.strstart !== 0) { header |= PRESET_DICT; }\n header += 31 - (header % 31);\n\n putShortMSB(s, header);\n\n /* Save the adler32 of the preset dictionary: */\n if (s.strstart !== 0) {\n putShortMSB(s, strm.adler >>> 16);\n putShortMSB(s, strm.adler & 0xffff);\n }\n strm.adler = 1; // adler32(0L, Z_NULL, 0);\n s.status = BUSY_STATE;\n\n /* Compression must start with an empty pending buffer */\n flush_pending(strm);\n if (s.pending !== 0) {\n s.last_flush = -1;\n return Z_OK$3;\n }\n }\n//#ifdef GZIP\n if (s.status === GZIP_STATE) {\n /* gzip header */\n strm.adler = 0; //crc32(0L, Z_NULL, 0);\n put_byte(s, 31);\n put_byte(s, 139);\n put_byte(s, 8);\n if (!s.gzhead) { // s->gzhead == Z_NULL\n put_byte(s, 0);\n put_byte(s, 0);\n put_byte(s, 0);\n put_byte(s, 0);\n put_byte(s, 0);\n put_byte(s, s.level === 9 ? 2 :\n (s.strategy >= Z_HUFFMAN_ONLY || s.level < 2 ?\n 4 : 0));\n put_byte(s, OS_CODE);\n s.status = BUSY_STATE;\n\n /* Compression must start with an empty pending buffer */\n flush_pending(strm);\n if (s.pending !== 0) {\n s.last_flush = -1;\n return Z_OK$3;\n }\n }\n else {\n put_byte(s, (s.gzhead.text ? 1 : 0) +\n (s.gzhead.hcrc ? 2 : 0) +\n (!s.gzhead.extra ? 0 : 4) +\n (!s.gzhead.name ? 0 : 8) +\n (!s.gzhead.comment ? 0 : 16)\n );\n put_byte(s, s.gzhead.time & 0xff);\n put_byte(s, (s.gzhead.time >> 8) & 0xff);\n put_byte(s, (s.gzhead.time >> 16) & 0xff);\n put_byte(s, (s.gzhead.time >> 24) & 0xff);\n put_byte(s, s.level === 9 ? 2 :\n (s.strategy >= Z_HUFFMAN_ONLY || s.level < 2 ?\n 4 : 0));\n put_byte(s, s.gzhead.os & 0xff);\n if (s.gzhead.extra && s.gzhead.extra.length) {\n put_byte(s, s.gzhead.extra.length & 0xff);\n put_byte(s, (s.gzhead.extra.length >> 8) & 0xff);\n }\n if (s.gzhead.hcrc) {\n strm.adler = crc32_1(strm.adler, s.pending_buf, s.pending, 0);\n }\n s.gzindex = 0;\n s.status = EXTRA_STATE;\n }\n }\n if (s.status === EXTRA_STATE) {\n if (s.gzhead.extra/* != Z_NULL*/) {\n let beg = s.pending; /* start of bytes to update crc */\n let left = (s.gzhead.extra.length & 0xffff) - s.gzindex;\n while (s.pending + left > s.pending_buf_size) {\n let copy = s.pending_buf_size - s.pending;\n // zmemcpy(s.pending_buf + s.pending,\n // s.gzhead.extra + s.gzindex, copy);\n s.pending_buf.set(s.gzhead.extra.subarray(s.gzindex, s.gzindex + copy), s.pending);\n s.pending = s.pending_buf_size;\n //--- HCRC_UPDATE(beg) ---//\n if (s.gzhead.hcrc && s.pending > beg) {\n strm.adler = crc32_1(strm.adler, s.pending_buf, s.pending - beg, beg);\n }\n //---//\n s.gzindex += copy;\n flush_pending(strm);\n if (s.pending !== 0) {\n s.last_flush = -1;\n return Z_OK$3;\n }\n beg = 0;\n left -= copy;\n }\n // JS specific: s.gzhead.extra may be TypedArray or Array for backward compatibility\n // TypedArray.slice and TypedArray.from don't exist in IE10-IE11\n let gzhead_extra = new Uint8Array(s.gzhead.extra);\n // zmemcpy(s->pending_buf + s->pending,\n // s->gzhead->extra + s->gzindex, left);\n s.pending_buf.set(gzhead_extra.subarray(s.gzindex, s.gzindex + left), s.pending);\n s.pending += left;\n //--- HCRC_UPDATE(beg) ---//\n if (s.gzhead.hcrc && s.pending > beg) {\n strm.adler = crc32_1(strm.adler, s.pending_buf, s.pending - beg, beg);\n }\n //---//\n s.gzindex = 0;\n }\n s.status = NAME_STATE;\n }\n if (s.status === NAME_STATE) {\n if (s.gzhead.name/* != Z_NULL*/) {\n let beg = s.pending; /* start of bytes to update crc */\n let val;\n do {\n if (s.pending === s.pending_buf_size) {\n //--- HCRC_UPDATE(beg) ---//\n if (s.gzhead.hcrc && s.pending > beg) {\n strm.adler = crc32_1(strm.adler, s.pending_buf, s.pending - beg, beg);\n }\n //---//\n flush_pending(strm);\n if (s.pending !== 0) {\n s.last_flush = -1;\n return Z_OK$3;\n }\n beg = 0;\n }\n // JS specific: little magic to add zero terminator to end of string\n if (s.gzindex < s.gzhead.name.length) {\n val = s.gzhead.name.charCodeAt(s.gzindex++) & 0xff;\n } else {\n val = 0;\n }\n put_byte(s, val);\n } while (val !== 0);\n //--- HCRC_UPDATE(beg) ---//\n if (s.gzhead.hcrc && s.pending > beg) {\n strm.adler = crc32_1(strm.adler, s.pending_buf, s.pending - beg, beg);\n }\n //---//\n s.gzindex = 0;\n }\n s.status = COMMENT_STATE;\n }\n if (s.status === COMMENT_STATE) {\n if (s.gzhead.comment/* != Z_NULL*/) {\n let beg = s.pending; /* start of bytes to update crc */\n let val;\n do {\n if (s.pending === s.pending_buf_size) {\n //--- HCRC_UPDATE(beg) ---//\n if (s.gzhead.hcrc && s.pending > beg) {\n strm.adler = crc32_1(strm.adler, s.pending_buf, s.pending - beg, beg);\n }\n //---//\n flush_pending(strm);\n if (s.pending !== 0) {\n s.last_flush = -1;\n return Z_OK$3;\n }\n beg = 0;\n }\n // JS specific: little magic to add zero terminator to end of string\n if (s.gzindex < s.gzhead.comment.length) {\n val = s.gzhead.comment.charCodeAt(s.gzindex++) & 0xff;\n } else {\n val = 0;\n }\n put_byte(s, val);\n } while (val !== 0);\n //--- HCRC_UPDATE(beg) ---//\n if (s.gzhead.hcrc && s.pending > beg) {\n strm.adler = crc32_1(strm.adler, s.pending_buf, s.pending - beg, beg);\n }\n //---//\n }\n s.status = HCRC_STATE;\n }\n if (s.status === HCRC_STATE) {\n if (s.gzhead.hcrc) {\n if (s.pending + 2 > s.pending_buf_size) {\n flush_pending(strm);\n if (s.pending !== 0) {\n s.last_flush = -1;\n return Z_OK$3;\n }\n }\n put_byte(s, strm.adler & 0xff);\n put_byte(s, (strm.adler >> 8) & 0xff);\n strm.adler = 0; //crc32(0L, Z_NULL, 0);\n }\n s.status = BUSY_STATE;\n\n /* Compression must start with an empty pending buffer */\n flush_pending(strm);\n if (s.pending !== 0) {\n s.last_flush = -1;\n return Z_OK$3;\n }\n }\n//#endif\n\n /* Start a new block or continue the current one.\n */\n if (strm.avail_in !== 0 || s.lookahead !== 0 ||\n (flush !== Z_NO_FLUSH$2 && s.status !== FINISH_STATE)) {\n let bstate = s.level === 0 ? deflate_stored(s, flush) :\n s.strategy === Z_HUFFMAN_ONLY ? deflate_huff(s, flush) :\n s.strategy === Z_RLE ? deflate_rle(s, flush) :\n configuration_table[s.level].func(s, flush);\n\n if (bstate === BS_FINISH_STARTED || bstate === BS_FINISH_DONE) {\n s.status = FINISH_STATE;\n }\n if (bstate === BS_NEED_MORE || bstate === BS_FINISH_STARTED) {\n if (strm.avail_out === 0) {\n s.last_flush = -1;\n /* avoid BUF_ERROR next call, see above */\n }\n return Z_OK$3;\n /* If flush != Z_NO_FLUSH && avail_out == 0, the next call\n * of deflate should use the same flush parameter to make sure\n * that the flush is complete. So we don't have to output an\n * empty block here, this will be done at next call. This also\n * ensures that for a very small output buffer, we emit at most\n * one empty block.\n */\n }\n if (bstate === BS_BLOCK_DONE) {\n if (flush === Z_PARTIAL_FLUSH) {\n _tr_align(s);\n }\n else if (flush !== Z_BLOCK$1) { /* FULL_FLUSH or SYNC_FLUSH */\n\n _tr_stored_block(s, 0, 0, false);\n /* For a full flush, this empty block will be recognized\n * as a special marker by inflate_sync().\n */\n if (flush === Z_FULL_FLUSH$1) {\n /*** CLEAR_HASH(s); ***/ /* forget history */\n zero(s.head); // Fill with NIL (= 0);\n\n if (s.lookahead === 0) {\n s.strstart = 0;\n s.block_start = 0;\n s.insert = 0;\n }\n }\n }\n flush_pending(strm);\n if (strm.avail_out === 0) {\n s.last_flush = -1; /* avoid BUF_ERROR at next call, see above */\n return Z_OK$3;\n }\n }\n }\n\n if (flush !== Z_FINISH$3) { return Z_OK$3; }\n if (s.wrap <= 0) { return Z_STREAM_END$3; }\n\n /* Write the trailer */\n if (s.wrap === 2) {\n put_byte(s, strm.adler & 0xff);\n put_byte(s, (strm.adler >> 8) & 0xff);\n put_byte(s, (strm.adler >> 16) & 0xff);\n put_byte(s, (strm.adler >> 24) & 0xff);\n put_byte(s, strm.total_in & 0xff);\n put_byte(s, (strm.total_in >> 8) & 0xff);\n put_byte(s, (strm.total_in >> 16) & 0xff);\n put_byte(s, (strm.total_in >> 24) & 0xff);\n }\n else\n {\n putShortMSB(s, strm.adler >>> 16);\n putShortMSB(s, strm.adler & 0xffff);\n }\n\n flush_pending(strm);\n /* If avail_out is zero, the application will call deflate again\n * to flush the rest.\n */\n if (s.wrap > 0) { s.wrap = -s.wrap; }\n /* write the trailer only once! */\n return s.pending !== 0 ? Z_OK$3 : Z_STREAM_END$3;\n};\n\n\nconst deflateEnd = (strm) => {\n\n if (deflateStateCheck(strm)) {\n return Z_STREAM_ERROR$2;\n }\n\n const status = strm.state.status;\n\n strm.state = null;\n\n return status === BUSY_STATE ? err(strm, Z_DATA_ERROR$2) : Z_OK$3;\n};\n\n\n/* =========================================================================\n * Initializes the compression dictionary from the given byte\n * sequence without producing any compressed output.\n */\nconst deflateSetDictionary = (strm, dictionary) => {\n\n let dictLength = dictionary.length;\n\n if (deflateStateCheck(strm)) {\n return Z_STREAM_ERROR$2;\n }\n\n const s = strm.state;\n const wrap = s.wrap;\n\n if (wrap === 2 || (wrap === 1 && s.status !== INIT_STATE) || s.lookahead) {\n return Z_STREAM_ERROR$2;\n }\n\n /* when using zlib wrappers, compute Adler-32 for provided dictionary */\n if (wrap === 1) {\n /* adler32(strm->adler, dictionary, dictLength); */\n strm.adler = adler32_1(strm.adler, dictionary, dictLength, 0);\n }\n\n s.wrap = 0; /* avoid computing Adler-32 in read_buf */\n\n /* if dictionary would fill window, just replace the history */\n if (dictLength >= s.w_size) {\n if (wrap === 0) { /* already empty otherwise */\n /*** CLEAR_HASH(s); ***/\n zero(s.head); // Fill with NIL (= 0);\n s.strstart = 0;\n s.block_start = 0;\n s.insert = 0;\n }\n /* use the tail */\n // dictionary = dictionary.slice(dictLength - s.w_size);\n let tmpDict = new Uint8Array(s.w_size);\n tmpDict.set(dictionary.subarray(dictLength - s.w_size, dictLength), 0);\n dictionary = tmpDict;\n dictLength = s.w_size;\n }\n /* insert dictionary into window and hash */\n const avail = strm.avail_in;\n const next = strm.next_in;\n const input = strm.input;\n strm.avail_in = dictLength;\n strm.next_in = 0;\n strm.input = dictionary;\n fill_window(s);\n while (s.lookahead >= MIN_MATCH) {\n let str = s.strstart;\n let n = s.lookahead - (MIN_MATCH - 1);\n do {\n /* UPDATE_HASH(s, s->ins_h, s->window[str + MIN_MATCH-1]); */\n s.ins_h = HASH(s, s.ins_h, s.window[str + MIN_MATCH - 1]);\n\n s.prev[str & s.w_mask] = s.head[s.ins_h];\n\n s.head[s.ins_h] = str;\n str++;\n } while (--n);\n s.strstart = str;\n s.lookahead = MIN_MATCH - 1;\n fill_window(s);\n }\n s.strstart += s.lookahead;\n s.block_start = s.strstart;\n s.insert = s.lookahead;\n s.lookahead = 0;\n s.match_length = s.prev_length = MIN_MATCH - 1;\n s.match_available = 0;\n strm.next_in = next;\n strm.input = input;\n strm.avail_in = avail;\n s.wrap = wrap;\n return Z_OK$3;\n};\n\n\nvar deflateInit_1 = deflateInit;\nvar deflateInit2_1 = deflateInit2;\nvar deflateReset_1 = deflateReset;\nvar deflateResetKeep_1 = deflateResetKeep;\nvar deflateSetHeader_1 = deflateSetHeader;\nvar deflate_2$1 = deflate$2;\nvar deflateEnd_1 = deflateEnd;\nvar deflateSetDictionary_1 = deflateSetDictionary;\nvar deflateInfo = 'pako deflate (from Nodeca project)';\n\n/* Not implemented\nmodule.exports.deflateBound = deflateBound;\nmodule.exports.deflateCopy = deflateCopy;\nmodule.exports.deflateGetDictionary = deflateGetDictionary;\nmodule.exports.deflateParams = deflateParams;\nmodule.exports.deflatePending = deflatePending;\nmodule.exports.deflatePrime = deflatePrime;\nmodule.exports.deflateTune = deflateTune;\n*/\n\nvar deflate_1$2 = {\n\tdeflateInit: deflateInit_1,\n\tdeflateInit2: deflateInit2_1,\n\tdeflateReset: deflateReset_1,\n\tdeflateResetKeep: deflateResetKeep_1,\n\tdeflateSetHeader: deflateSetHeader_1,\n\tdeflate: deflate_2$1,\n\tdeflateEnd: deflateEnd_1,\n\tdeflateSetDictionary: deflateSetDictionary_1,\n\tdeflateInfo: deflateInfo\n};\n\nconst _has = (obj, key) => {\n return Object.prototype.hasOwnProperty.call(obj, key);\n};\n\nvar assign = function (obj /*from1, from2, from3, ...*/) {\n const sources = Array.prototype.slice.call(arguments, 1);\n while (sources.length) {\n const source = sources.shift();\n if (!source) { continue; }\n\n if (typeof source !== 'object') {\n throw new TypeError(source + 'must be non-object');\n }\n\n for (const p in source) {\n if (_has(source, p)) {\n obj[p] = source[p];\n }\n }\n }\n\n return obj;\n};\n\n\n// Join array of chunks to single array.\nvar flattenChunks = (chunks) => {\n // calculate data length\n let len = 0;\n\n for (let i = 0, l = chunks.length; i < l; i++) {\n len += chunks[i].length;\n }\n\n // join chunks\n const result = new Uint8Array(len);\n\n for (let i = 0, pos = 0, l = chunks.length; i < l; i++) {\n let chunk = chunks[i];\n result.set(chunk, pos);\n pos += chunk.length;\n }\n\n return result;\n};\n\nvar common = {\n\tassign: assign,\n\tflattenChunks: flattenChunks\n};\n\n// String encode/decode helpers\n\n\n// Quick check if we can use fast array to bin string conversion\n//\n// - apply(Array) can fail on Android 2.2\n// - apply(Uint8Array) can fail on iOS 5.1 Safari\n//\nlet STR_APPLY_UIA_OK = true;\n\ntry { String.fromCharCode.apply(null, new Uint8Array(1)); } catch (__) { STR_APPLY_UIA_OK = false; }\n\n\n// Table with utf8 lengths (calculated by first byte of sequence)\n// Note, that 5 & 6-byte values and some 4-byte values can not be represented in JS,\n// because max possible codepoint is 0x10ffff\nconst _utf8len = new Uint8Array(256);\nfor (let q = 0; q < 256; q++) {\n _utf8len[q] = (q >= 252 ? 6 : q >= 248 ? 5 : q >= 240 ? 4 : q >= 224 ? 3 : q >= 192 ? 2 : 1);\n}\n_utf8len[254] = _utf8len[254] = 1; // Invalid sequence start\n\n\n// convert string to array (typed, when possible)\nvar string2buf = (str) => {\n if (typeof TextEncoder === 'function' && TextEncoder.prototype.encode) {\n return new TextEncoder().encode(str);\n }\n\n let buf, c, c2, m_pos, i, str_len = str.length, buf_len = 0;\n\n // count binary size\n for (m_pos = 0; m_pos < str_len; m_pos++) {\n c = str.charCodeAt(m_pos);\n if ((c & 0xfc00) === 0xd800 && (m_pos + 1 < str_len)) {\n c2 = str.charCodeAt(m_pos + 1);\n if ((c2 & 0xfc00) === 0xdc00) {\n c = 0x10000 + ((c - 0xd800) << 10) + (c2 - 0xdc00);\n m_pos++;\n }\n }\n buf_len += c < 0x80 ? 1 : c < 0x800 ? 2 : c < 0x10000 ? 3 : 4;\n }\n\n // allocate buffer\n buf = new Uint8Array(buf_len);\n\n // convert\n for (i = 0, m_pos = 0; i < buf_len; m_pos++) {\n c = str.charCodeAt(m_pos);\n if ((c & 0xfc00) === 0xd800 && (m_pos + 1 < str_len)) {\n c2 = str.charCodeAt(m_pos + 1);\n if ((c2 & 0xfc00) === 0xdc00) {\n c = 0x10000 + ((c - 0xd800) << 10) + (c2 - 0xdc00);\n m_pos++;\n }\n }\n if (c < 0x80) {\n /* one byte */\n buf[i++] = c;\n } else if (c < 0x800) {\n /* two bytes */\n buf[i++] = 0xC0 | (c >>> 6);\n buf[i++] = 0x80 | (c & 0x3f);\n } else if (c < 0x10000) {\n /* three bytes */\n buf[i++] = 0xE0 | (c >>> 12);\n buf[i++] = 0x80 | (c >>> 6 & 0x3f);\n buf[i++] = 0x80 | (c & 0x3f);\n } else {\n /* four bytes */\n buf[i++] = 0xf0 | (c >>> 18);\n buf[i++] = 0x80 | (c >>> 12 & 0x3f);\n buf[i++] = 0x80 | (c >>> 6 & 0x3f);\n buf[i++] = 0x80 | (c & 0x3f);\n }\n }\n\n return buf;\n};\n\n// Helper\nconst buf2binstring = (buf, len) => {\n // On Chrome, the arguments in a function call that are allowed is `65534`.\n // If the length of the buffer is smaller than that, we can use this optimization,\n // otherwise we will take a slower path.\n if (len < 65534) {\n if (buf.subarray && STR_APPLY_UIA_OK) {\n return String.fromCharCode.apply(null, buf.length === len ? buf : buf.subarray(0, len));\n }\n }\n\n let result = '';\n for (let i = 0; i < len; i++) {\n result += String.fromCharCode(buf[i]);\n }\n return result;\n};\n\n\n// convert array to string\nvar buf2string = (buf, max) => {\n const len = max || buf.length;\n\n if (typeof TextDecoder === 'function' && TextDecoder.prototype.decode) {\n return new TextDecoder().decode(buf.subarray(0, max));\n }\n\n let i, out;\n\n // Reserve max possible length (2 words per char)\n // NB: by unknown reasons, Array is significantly faster for\n // String.fromCharCode.apply than Uint16Array.\n const utf16buf = new Array(len * 2);\n\n for (out = 0, i = 0; i < len;) {\n let c = buf[i++];\n // quick process ascii\n if (c < 0x80) { utf16buf[out++] = c; continue; }\n\n let c_len = _utf8len[c];\n // skip 5 & 6 byte codes\n if (c_len > 4) { utf16buf[out++] = 0xfffd; i += c_len - 1; continue; }\n\n // apply mask on first byte\n c &= c_len === 2 ? 0x1f : c_len === 3 ? 0x0f : 0x07;\n // join the rest\n while (c_len > 1 && i < len) {\n c = (c << 6) | (buf[i++] & 0x3f);\n c_len--;\n }\n\n // terminated by end of string?\n if (c_len > 1) { utf16buf[out++] = 0xfffd; continue; }\n\n if (c < 0x10000) {\n utf16buf[out++] = c;\n } else {\n c -= 0x10000;\n utf16buf[out++] = 0xd800 | ((c >> 10) & 0x3ff);\n utf16buf[out++] = 0xdc00 | (c & 0x3ff);\n }\n }\n\n return buf2binstring(utf16buf, out);\n};\n\n\n// Calculate max possible position in utf8 buffer,\n// that will not break sequence. If that's not possible\n// - (very small limits) return max size as is.\n//\n// buf[] - utf8 bytes array\n// max - length limit (mandatory);\nvar utf8border = (buf, max) => {\n\n max = max || buf.length;\n if (max > buf.length) { max = buf.length; }\n\n // go back from last position, until start of sequence found\n let pos = max - 1;\n while (pos >= 0 && (buf[pos] & 0xC0) === 0x80) { pos--; }\n\n // Very small and broken sequence,\n // return max, because we should return something anyway.\n if (pos < 0) { return max; }\n\n // If we came to start of buffer - that means buffer is too small,\n // return max too.\n if (pos === 0) { return max; }\n\n return (pos + _utf8len[buf[pos]] > max) ? pos : max;\n};\n\nvar strings = {\n\tstring2buf: string2buf,\n\tbuf2string: buf2string,\n\tutf8border: utf8border\n};\n\n// (C) 1995-2013 Jean-loup Gailly and Mark Adler\n// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin\n//\n// This software is provided 'as-is', without any express or implied\n// warranty. In no event will the authors be held liable for any damages\n// arising from the use of this software.\n//\n// Permission is granted to anyone to use this software for any purpose,\n// including commercial applications, and to alter it and redistribute it\n// freely, subject to the following restrictions:\n//\n// 1. The origin of this software must not be misrepresented; you must not\n// claim that you wrote the original software. If you use this software\n// in a product, an acknowledgment in the product documentation would be\n// appreciated but is not required.\n// 2. Altered source versions must be plainly marked as such, and must not be\n// misrepresented as being the original software.\n// 3. This notice may not be removed or altered from any source distribution.\n\nfunction ZStream() {\n /* next input byte */\n this.input = null; // JS specific, because we have no pointers\n this.next_in = 0;\n /* number of bytes available at input */\n this.avail_in = 0;\n /* total number of input bytes read so far */\n this.total_in = 0;\n /* next output byte should be put there */\n this.output = null; // JS specific, because we have no pointers\n this.next_out = 0;\n /* remaining free space at output */\n this.avail_out = 0;\n /* total number of bytes output so far */\n this.total_out = 0;\n /* last error message, NULL if no error */\n this.msg = ''/*Z_NULL*/;\n /* not visible by applications */\n this.state = null;\n /* best guess about the data type: binary or text */\n this.data_type = 2/*Z_UNKNOWN*/;\n /* adler32 value of the uncompressed data */\n this.adler = 0;\n}\n\nvar zstream = ZStream;\n\nconst toString$1 = Object.prototype.toString;\n\n/* Public constants ==========================================================*/\n/* ===========================================================================*/\n\nconst {\n Z_NO_FLUSH: Z_NO_FLUSH$1, Z_SYNC_FLUSH, Z_FULL_FLUSH, Z_FINISH: Z_FINISH$2,\n Z_OK: Z_OK$2, Z_STREAM_END: Z_STREAM_END$2,\n Z_DEFAULT_COMPRESSION,\n Z_DEFAULT_STRATEGY,\n Z_DEFLATED: Z_DEFLATED$1\n} = constants$2;\n\n/* ===========================================================================*/\n\n\n/**\n * class Deflate\n *\n * Generic JS-style wrapper for zlib calls. If you don't need\n * streaming behaviour - use more simple functions: [[deflate]],\n * [[deflateRaw]] and [[gzip]].\n **/\n\n/* internal\n * Deflate.chunks -> Array\n *\n * Chunks of output data, if [[Deflate#onData]] not overridden.\n **/\n\n/**\n * Deflate.result -> Uint8Array\n *\n * Compressed result, generated by default [[Deflate#onData]]\n * and [[Deflate#onEnd]] handlers. Filled after you push last chunk\n * (call [[Deflate#push]] with `Z_FINISH` / `true` param).\n **/\n\n/**\n * Deflate.err -> Number\n *\n * Error code after deflate finished. 0 (Z_OK) on success.\n * You will not need it in real life, because deflate errors\n * are possible only on wrong options or bad `onData` / `onEnd`\n * custom handlers.\n **/\n\n/**\n * Deflate.msg -> String\n *\n * Error message, if [[Deflate.err]] != 0\n **/\n\n\n/**\n * new Deflate(options)\n * - options (Object): zlib deflate options.\n *\n * Creates new deflator instance with specified params. Throws exception\n * on bad params. Supported options:\n *\n * - `level`\n * - `windowBits`\n * - `memLevel`\n * - `strategy`\n * - `dictionary`\n *\n * [http://zlib.net/manual.html#Advanced](http://zlib.net/manual.html#Advanced)\n * for more information on these.\n *\n * Additional options, for internal needs:\n *\n * - `chunkSize` - size of generated data chunks (16K by default)\n * - `raw` (Boolean) - do raw deflate\n * - `gzip` (Boolean) - create gzip wrapper\n * - `header` (Object) - custom header for gzip\n * - `text` (Boolean) - true if compressed data believed to be text\n * - `time` (Number) - modification time, unix timestamp\n * - `os` (Number) - operation system code\n * - `extra` (Array) - array of bytes with extra data (max 65536)\n * - `name` (String) - file name (binary string)\n * - `comment` (String) - comment (binary string)\n * - `hcrc` (Boolean) - true if header crc should be added\n *\n * ##### Example:\n *\n * ```javascript\n * const pako = require('pako')\n * , chunk1 = new Uint8Array([1,2,3,4,5,6,7,8,9])\n * , chunk2 = new Uint8Array([10,11,12,13,14,15,16,17,18,19]);\n *\n * const deflate = new pako.Deflate({ level: 3});\n *\n * deflate.push(chunk1, false);\n * deflate.push(chunk2, true); // true -> last chunk\n *\n * if (deflate.err) { throw new Error(deflate.err); }\n *\n * console.log(deflate.result);\n * ```\n **/\nfunction Deflate$1(options) {\n this.options = common.assign({\n level: Z_DEFAULT_COMPRESSION,\n method: Z_DEFLATED$1,\n chunkSize: 16384,\n windowBits: 15,\n memLevel: 8,\n strategy: Z_DEFAULT_STRATEGY\n }, options || {});\n\n let opt = this.options;\n\n if (opt.raw && (opt.windowBits > 0)) {\n opt.windowBits = -opt.windowBits;\n }\n\n else if (opt.gzip && (opt.windowBits > 0) && (opt.windowBits < 16)) {\n opt.windowBits += 16;\n }\n\n this.err = 0; // error code, if happens (0 = Z_OK)\n this.msg = ''; // error message\n this.ended = false; // used to avoid multiple onEnd() calls\n this.chunks = []; // chunks of compressed data\n\n this.strm = new zstream();\n this.strm.avail_out = 0;\n\n let status = deflate_1$2.deflateInit2(\n this.strm,\n opt.level,\n opt.method,\n opt.windowBits,\n opt.memLevel,\n opt.strategy\n );\n\n if (status !== Z_OK$2) {\n throw new Error(messages[status]);\n }\n\n if (opt.header) {\n deflate_1$2.deflateSetHeader(this.strm, opt.header);\n }\n\n if (opt.dictionary) {\n let dict;\n // Convert data if needed\n if (typeof opt.dictionary === 'string') {\n // If we need to compress text, change encoding to utf8.\n dict = strings.string2buf(opt.dictionary);\n } else if (toString$1.call(opt.dictionary) === '[object ArrayBuffer]') {\n dict = new Uint8Array(opt.dictionary);\n } else {\n dict = opt.dictionary;\n }\n\n status = deflate_1$2.deflateSetDictionary(this.strm, dict);\n\n if (status !== Z_OK$2) {\n throw new Error(messages[status]);\n }\n\n this._dict_set = true;\n }\n}\n\n/**\n * Deflate#push(data[, flush_mode]) -> Boolean\n * - data (Uint8Array|ArrayBuffer|String): input data. Strings will be\n * converted to utf8 byte sequence.\n * - flush_mode (Number|Boolean): 0..6 for corresponding Z_NO_FLUSH..Z_TREE modes.\n * See constants. Skipped or `false` means Z_NO_FLUSH, `true` means Z_FINISH.\n *\n * Sends input data to deflate pipe, generating [[Deflate#onData]] calls with\n * new compressed chunks. Returns `true` on success. The last data block must\n * have `flush_mode` Z_FINISH (or `true`). That will flush internal pending\n * buffers and call [[Deflate#onEnd]].\n *\n * On fail call [[Deflate#onEnd]] with error code and return false.\n *\n * ##### Example\n *\n * ```javascript\n * push(chunk, false); // push one of data chunks\n * ...\n * push(chunk, true); // push last chunk\n * ```\n **/\nDeflate$1.prototype.push = function (data, flush_mode) {\n const strm = this.strm;\n const chunkSize = this.options.chunkSize;\n let status, _flush_mode;\n\n if (this.ended) { return false; }\n\n if (flush_mode === ~~flush_mode) _flush_mode = flush_mode;\n else _flush_mode = flush_mode === true ? Z_FINISH$2 : Z_NO_FLUSH$1;\n\n // Convert data if needed\n if (typeof data === 'string') {\n // If we need to compress text, change encoding to utf8.\n strm.input = strings.string2buf(data);\n } else if (toString$1.call(data) === '[object ArrayBuffer]') {\n strm.input = new Uint8Array(data);\n } else {\n strm.input = data;\n }\n\n strm.next_in = 0;\n strm.avail_in = strm.input.length;\n\n for (;;) {\n if (strm.avail_out === 0) {\n strm.output = new Uint8Array(chunkSize);\n strm.next_out = 0;\n strm.avail_out = chunkSize;\n }\n\n // Make sure avail_out > 6 to avoid repeating markers\n if ((_flush_mode === Z_SYNC_FLUSH || _flush_mode === Z_FULL_FLUSH) && strm.avail_out <= 6) {\n this.onData(strm.output.subarray(0, strm.next_out));\n strm.avail_out = 0;\n continue;\n }\n\n status = deflate_1$2.deflate(strm, _flush_mode);\n\n // Ended => flush and finish\n if (status === Z_STREAM_END$2) {\n if (strm.next_out > 0) {\n this.onData(strm.output.subarray(0, strm.next_out));\n }\n status = deflate_1$2.deflateEnd(this.strm);\n this.onEnd(status);\n this.ended = true;\n return status === Z_OK$2;\n }\n\n // Flush if out buffer full\n if (strm.avail_out === 0) {\n this.onData(strm.output);\n continue;\n }\n\n // Flush if requested and has data\n if (_flush_mode > 0 && strm.next_out > 0) {\n this.onData(strm.output.subarray(0, strm.next_out));\n strm.avail_out = 0;\n continue;\n }\n\n if (strm.avail_in === 0) break;\n }\n\n return true;\n};\n\n\n/**\n * Deflate#onData(chunk) -> Void\n * - chunk (Uint8Array): output data.\n *\n * By default, stores data blocks in `chunks[]` property and glue\n * those in `onEnd`. Override this handler, if you need another behaviour.\n **/\nDeflate$1.prototype.onData = function (chunk) {\n this.chunks.push(chunk);\n};\n\n\n/**\n * Deflate#onEnd(status) -> Void\n * - status (Number): deflate status. 0 (Z_OK) on success,\n * other if not.\n *\n * Called once after you tell deflate that the input stream is\n * complete (Z_FINISH). By default - join collected chunks,\n * free memory and fill `results` / `err` properties.\n **/\nDeflate$1.prototype.onEnd = function (status) {\n // On success - join\n if (status === Z_OK$2) {\n this.result = common.flattenChunks(this.chunks);\n }\n this.chunks = [];\n this.err = status;\n this.msg = this.strm.msg;\n};\n\n\n/**\n * deflate(data[, options]) -> Uint8Array\n * - data (Uint8Array|ArrayBuffer|String): input data to compress.\n * - options (Object): zlib deflate options.\n *\n * Compress `data` with deflate algorithm and `options`.\n *\n * Supported options are:\n *\n * - level\n * - windowBits\n * - memLevel\n * - strategy\n * - dictionary\n *\n * [http://zlib.net/manual.html#Advanced](http://zlib.net/manual.html#Advanced)\n * for more information on these.\n *\n * Sugar (options):\n *\n * - `raw` (Boolean) - say that we work with raw stream, if you don't wish to specify\n * negative windowBits implicitly.\n *\n * ##### Example:\n *\n * ```javascript\n * const pako = require('pako')\n * const data = new Uint8Array([1,2,3,4,5,6,7,8,9]);\n *\n * console.log(pako.deflate(data));\n * ```\n **/\nfunction deflate$1(input, options) {\n const deflator = new Deflate$1(options);\n\n deflator.push(input, true);\n\n // That will never happens, if you don't cheat with options :)\n if (deflator.err) { throw deflator.msg || messages[deflator.err]; }\n\n return deflator.result;\n}\n\n\n/**\n * deflateRaw(data[, options]) -> Uint8Array\n * - data (Uint8Array|ArrayBuffer|String): input data to compress.\n * - options (Object): zlib deflate options.\n *\n * The same as [[deflate]], but creates raw data, without wrapper\n * (header and adler32 crc).\n **/\nfunction deflateRaw$1(input, options) {\n options = options || {};\n options.raw = true;\n return deflate$1(input, options);\n}\n\n\n/**\n * gzip(data[, options]) -> Uint8Array\n * - data (Uint8Array|ArrayBuffer|String): input data to compress.\n * - options (Object): zlib deflate options.\n *\n * The same as [[deflate]], but create gzip wrapper instead of\n * deflate one.\n **/\nfunction gzip$1(input, options) {\n options = options || {};\n options.gzip = true;\n return deflate$1(input, options);\n}\n\n\nvar Deflate_1$1 = Deflate$1;\nvar deflate_2 = deflate$1;\nvar deflateRaw_1$1 = deflateRaw$1;\nvar gzip_1$1 = gzip$1;\nvar constants$1 = constants$2;\n\nvar deflate_1$1 = {\n\tDeflate: Deflate_1$1,\n\tdeflate: deflate_2,\n\tdeflateRaw: deflateRaw_1$1,\n\tgzip: gzip_1$1,\n\tconstants: constants$1\n};\n\n// (C) 1995-2013 Jean-loup Gailly and Mark Adler\n// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin\n//\n// This software is provided 'as-is', without any express or implied\n// warranty. In no event will the authors be held liable for any damages\n// arising from the use of this software.\n//\n// Permission is granted to anyone to use this software for any purpose,\n// including commercial applications, and to alter it and redistribute it\n// freely, subject to the following restrictions:\n//\n// 1. The origin of this software must not be misrepresented; you must not\n// claim that you wrote the original software. If you use this software\n// in a product, an acknowledgment in the product documentation would be\n// appreciated but is not required.\n// 2. Altered source versions must be plainly marked as such, and must not be\n// misrepresented as being the original software.\n// 3. This notice may not be removed or altered from any source distribution.\n\n// See state defs from inflate.js\nconst BAD$1 = 16209; /* got a data error -- remain here until reset */\nconst TYPE$1 = 16191; /* i: waiting for type bits, including last-flag bit */\n\n/*\n Decode literal, length, and distance codes and write out the resulting\n literal and match bytes until either not enough input or output is\n available, an end-of-block is encountered, or a data error is encountered.\n When large enough input and output buffers are supplied to inflate(), for\n example, a 16K input buffer and a 64K output buffer, more than 95% of the\n inflate execution time is spent in this routine.\n\n Entry assumptions:\n\n state.mode === LEN\n strm.avail_in >= 6\n strm.avail_out >= 258\n start >= strm.avail_out\n state.bits < 8\n\n On return, state.mode is one of:\n\n LEN -- ran out of enough output space or enough available input\n TYPE -- reached end of block code, inflate() to interpret next block\n BAD -- error in block data\n\n Notes:\n\n - The maximum input bits used by a length/distance pair is 15 bits for the\n length code, 5 bits for the length extra, 15 bits for the distance code,\n and 13 bits for the distance extra. This totals 48 bits, or six bytes.\n Therefore if strm.avail_in >= 6, then there is enough input to avoid\n checking for available input while decoding.\n\n - The maximum bytes that a single length/distance pair can output is 258\n bytes, which is the maximum length that can be coded. inflate_fast()\n requires strm.avail_out >= 258 for each loop to avoid checking for\n output space.\n */\nvar inffast = function inflate_fast(strm, start) {\n let _in; /* local strm.input */\n let last; /* have enough input while in < last */\n let _out; /* local strm.output */\n let beg; /* inflate()'s initial strm.output */\n let end; /* while out < end, enough space available */\n//#ifdef INFLATE_STRICT\n let dmax; /* maximum distance from zlib header */\n//#endif\n let wsize; /* window size or zero if not using window */\n let whave; /* valid bytes in the window */\n let wnext; /* window write index */\n // Use `s_window` instead `window`, avoid conflict with instrumentation tools\n let s_window; /* allocated sliding window, if wsize != 0 */\n let hold; /* local strm.hold */\n let bits; /* local strm.bits */\n let lcode; /* local strm.lencode */\n let dcode; /* local strm.distcode */\n let lmask; /* mask for first level of length codes */\n let dmask; /* mask for first level of distance codes */\n let here; /* retrieved table entry */\n let op; /* code bits, operation, extra bits, or */\n /* window position, window bytes to copy */\n let len; /* match length, unused bytes */\n let dist; /* match distance */\n let from; /* where to copy match from */\n let from_source;\n\n\n let input, output; // JS specific, because we have no pointers\n\n /* copy state to local variables */\n const state = strm.state;\n //here = state.here;\n _in = strm.next_in;\n input = strm.input;\n last = _in + (strm.avail_in - 5);\n _out = strm.next_out;\n output = strm.output;\n beg = _out - (start - strm.avail_out);\n end = _out + (strm.avail_out - 257);\n//#ifdef INFLATE_STRICT\n dmax = state.dmax;\n//#endif\n wsize = state.wsize;\n whave = state.whave;\n wnext = state.wnext;\n s_window = state.window;\n hold = state.hold;\n bits = state.bits;\n lcode = state.lencode;\n dcode = state.distcode;\n lmask = (1 << state.lenbits) - 1;\n dmask = (1 << state.distbits) - 1;\n\n\n /* decode literals and length/distances until end-of-block or not enough\n input data or output space */\n\n top:\n do {\n if (bits < 15) {\n hold += input[_in++] << bits;\n bits += 8;\n hold += input[_in++] << bits;\n bits += 8;\n }\n\n here = lcode[hold & lmask];\n\n dolen:\n for (;;) { // Goto emulation\n op = here >>> 24/*here.bits*/;\n hold >>>= op;\n bits -= op;\n op = (here >>> 16) & 0xff/*here.op*/;\n if (op === 0) { /* literal */\n //Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ?\n // \"inflate: literal '%c'\\n\" :\n // \"inflate: literal 0x%02x\\n\", here.val));\n output[_out++] = here & 0xffff/*here.val*/;\n }\n else if (op & 16) { /* length base */\n len = here & 0xffff/*here.val*/;\n op &= 15; /* number of extra bits */\n if (op) {\n if (bits < op) {\n hold += input[_in++] << bits;\n bits += 8;\n }\n len += hold & ((1 << op) - 1);\n hold >>>= op;\n bits -= op;\n }\n //Tracevv((stderr, \"inflate: length %u\\n\", len));\n if (bits < 15) {\n hold += input[_in++] << bits;\n bits += 8;\n hold += input[_in++] << bits;\n bits += 8;\n }\n here = dcode[hold & dmask];\n\n dodist:\n for (;;) { // goto emulation\n op = here >>> 24/*here.bits*/;\n hold >>>= op;\n bits -= op;\n op = (here >>> 16) & 0xff/*here.op*/;\n\n if (op & 16) { /* distance base */\n dist = here & 0xffff/*here.val*/;\n op &= 15; /* number of extra bits */\n if (bits < op) {\n hold += input[_in++] << bits;\n bits += 8;\n if (bits < op) {\n hold += input[_in++] << bits;\n bits += 8;\n }\n }\n dist += hold & ((1 << op) - 1);\n//#ifdef INFLATE_STRICT\n if (dist > dmax) {\n strm.msg = 'invalid distance too far back';\n state.mode = BAD$1;\n break top;\n }\n//#endif\n hold >>>= op;\n bits -= op;\n //Tracevv((stderr, \"inflate: distance %u\\n\", dist));\n op = _out - beg; /* max distance in output */\n if (dist > op) { /* see if copy from window */\n op = dist - op; /* distance back in window */\n if (op > whave) {\n if (state.sane) {\n strm.msg = 'invalid distance too far back';\n state.mode = BAD$1;\n break top;\n }\n\n// (!) This block is disabled in zlib defaults,\n// don't enable it for binary compatibility\n//#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR\n// if (len <= op - whave) {\n// do {\n// output[_out++] = 0;\n// } while (--len);\n// continue top;\n// }\n// len -= op - whave;\n// do {\n// output[_out++] = 0;\n// } while (--op > whave);\n// if (op === 0) {\n// from = _out - dist;\n// do {\n// output[_out++] = output[from++];\n// } while (--len);\n// continue top;\n// }\n//#endif\n }\n from = 0; // window index\n from_source = s_window;\n if (wnext === 0) { /* very common case */\n from += wsize - op;\n if (op < len) { /* some from window */\n len -= op;\n do {\n output[_out++] = s_window[from++];\n } while (--op);\n from = _out - dist; /* rest from output */\n from_source = output;\n }\n }\n else if (wnext < op) { /* wrap around window */\n from += wsize + wnext - op;\n op -= wnext;\n if (op < len) { /* some from end of window */\n len -= op;\n do {\n output[_out++] = s_window[from++];\n } while (--op);\n from = 0;\n if (wnext < len) { /* some from start of window */\n op = wnext;\n len -= op;\n do {\n output[_out++] = s_window[from++];\n } while (--op);\n from = _out - dist; /* rest from output */\n from_source = output;\n }\n }\n }\n else { /* contiguous in window */\n from += wnext - op;\n if (op < len) { /* some from window */\n len -= op;\n do {\n output[_out++] = s_window[from++];\n } while (--op);\n from = _out - dist; /* rest from output */\n from_source = output;\n }\n }\n while (len > 2) {\n output[_out++] = from_source[from++];\n output[_out++] = from_source[from++];\n output[_out++] = from_source[from++];\n len -= 3;\n }\n if (len) {\n output[_out++] = from_source[from++];\n if (len > 1) {\n output[_out++] = from_source[from++];\n }\n }\n }\n else {\n from = _out - dist; /* copy direct from output */\n do { /* minimum length is three */\n output[_out++] = output[from++];\n output[_out++] = output[from++];\n output[_out++] = output[from++];\n len -= 3;\n } while (len > 2);\n if (len) {\n output[_out++] = output[from++];\n if (len > 1) {\n output[_out++] = output[from++];\n }\n }\n }\n }\n else if ((op & 64) === 0) { /* 2nd level distance code */\n here = dcode[(here & 0xffff)/*here.val*/ + (hold & ((1 << op) - 1))];\n continue dodist;\n }\n else {\n strm.msg = 'invalid distance code';\n state.mode = BAD$1;\n break top;\n }\n\n break; // need to emulate goto via \"continue\"\n }\n }\n else if ((op & 64) === 0) { /* 2nd level length code */\n here = lcode[(here & 0xffff)/*here.val*/ + (hold & ((1 << op) - 1))];\n continue dolen;\n }\n else if (op & 32) { /* end-of-block */\n //Tracevv((stderr, \"inflate: end of block\\n\"));\n state.mode = TYPE$1;\n break top;\n }\n else {\n strm.msg = 'invalid literal/length code';\n state.mode = BAD$1;\n break top;\n }\n\n break; // need to emulate goto via \"continue\"\n }\n } while (_in < last && _out < end);\n\n /* return unused bytes (on entry, bits < 8, so in won't go too far back) */\n len = bits >> 3;\n _in -= len;\n bits -= len << 3;\n hold &= (1 << bits) - 1;\n\n /* update state and return */\n strm.next_in = _in;\n strm.next_out = _out;\n strm.avail_in = (_in < last ? 5 + (last - _in) : 5 - (_in - last));\n strm.avail_out = (_out < end ? 257 + (end - _out) : 257 - (_out - end));\n state.hold = hold;\n state.bits = bits;\n return;\n};\n\n// (C) 1995-2013 Jean-loup Gailly and Mark Adler\n// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin\n//\n// This software is provided 'as-is', without any express or implied\n// warranty. In no event will the authors be held liable for any damages\n// arising from the use of this software.\n//\n// Permission is granted to anyone to use this software for any purpose,\n// including commercial applications, and to alter it and redistribute it\n// freely, subject to the following restrictions:\n//\n// 1. The origin of this software must not be misrepresented; you must not\n// claim that you wrote the original software. If you use this software\n// in a product, an acknowledgment in the product documentation would be\n// appreciated but is not required.\n// 2. Altered source versions must be plainly marked as such, and must not be\n// misrepresented as being the original software.\n// 3. This notice may not be removed or altered from any source distribution.\n\nconst MAXBITS = 15;\nconst ENOUGH_LENS$1 = 852;\nconst ENOUGH_DISTS$1 = 592;\n//const ENOUGH = (ENOUGH_LENS+ENOUGH_DISTS);\n\nconst CODES$1 = 0;\nconst LENS$1 = 1;\nconst DISTS$1 = 2;\n\nconst lbase = new Uint16Array([ /* Length codes 257..285 base */\n 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,\n 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0\n]);\n\nconst lext = new Uint8Array([ /* Length codes 257..285 extra */\n 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18,\n 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 72, 78\n]);\n\nconst dbase = new Uint16Array([ /* Distance codes 0..29 base */\n 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,\n 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,\n 8193, 12289, 16385, 24577, 0, 0\n]);\n\nconst dext = new Uint8Array([ /* Distance codes 0..29 extra */\n 16, 16, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22,\n 23, 23, 24, 24, 25, 25, 26, 26, 27, 27,\n 28, 28, 29, 29, 64, 64\n]);\n\nconst inflate_table = (type, lens, lens_index, codes, table, table_index, work, opts) =>\n{\n const bits = opts.bits;\n //here = opts.here; /* table entry for duplication */\n\n let len = 0; /* a code's length in bits */\n let sym = 0; /* index of code symbols */\n let min = 0, max = 0; /* minimum and maximum code lengths */\n let root = 0; /* number of index bits for root table */\n let curr = 0; /* number of index bits for current table */\n let drop = 0; /* code bits to drop for sub-table */\n let left = 0; /* number of prefix codes available */\n let used = 0; /* code entries in table used */\n let huff = 0; /* Huffman code */\n let incr; /* for incrementing code, index */\n let fill; /* index for replicating entries */\n let low; /* low bits for current root entry */\n let mask; /* mask for low root bits */\n let next; /* next available space in table */\n let base = null; /* base value table to use */\n// let shoextra; /* extra bits table to use */\n let match; /* use base and extra for symbol >= match */\n const count = new Uint16Array(MAXBITS + 1); //[MAXBITS+1]; /* number of codes of each length */\n const offs = new Uint16Array(MAXBITS + 1); //[MAXBITS+1]; /* offsets in table for each length */\n let extra = null;\n\n let here_bits, here_op, here_val;\n\n /*\n Process a set of code lengths to create a canonical Huffman code. The\n code lengths are lens[0..codes-1]. Each length corresponds to the\n symbols 0..codes-1. The Huffman code is generated by first sorting the\n symbols by length from short to long, and retaining the symbol order\n for codes with equal lengths. Then the code starts with all zero bits\n for the first code of the shortest length, and the codes are integer\n increments for the same length, and zeros are appended as the length\n increases. For the deflate format, these bits are stored backwards\n from their more natural integer increment ordering, and so when the\n decoding tables are built in the large loop below, the integer codes\n are incremented backwards.\n\n This routine assumes, but does not check, that all of the entries in\n lens[] are in the range 0..MAXBITS. The caller must assure this.\n 1..MAXBITS is interpreted as that code length. zero means that that\n symbol does not occur in this code.\n\n The codes are sorted by computing a count of codes for each length,\n creating from that a table of starting indices for each length in the\n sorted table, and then entering the symbols in order in the sorted\n table. The sorted table is work[], with that space being provided by\n the caller.\n\n The length counts are used for other purposes as well, i.e. finding\n the minimum and maximum length codes, determining if there are any\n codes at all, checking for a valid set of lengths, and looking ahead\n at length counts to determine sub-table sizes when building the\n decoding tables.\n */\n\n /* accumulate lengths for codes (assumes lens[] all in 0..MAXBITS) */\n for (len = 0; len <= MAXBITS; len++) {\n count[len] = 0;\n }\n for (sym = 0; sym < codes; sym++) {\n count[lens[lens_index + sym]]++;\n }\n\n /* bound code lengths, force root to be within code lengths */\n root = bits;\n for (max = MAXBITS; max >= 1; max--) {\n if (count[max] !== 0) { break; }\n }\n if (root > max) {\n root = max;\n }\n if (max === 0) { /* no symbols to code at all */\n //table.op[opts.table_index] = 64; //here.op = (var char)64; /* invalid code marker */\n //table.bits[opts.table_index] = 1; //here.bits = (var char)1;\n //table.val[opts.table_index++] = 0; //here.val = (var short)0;\n table[table_index++] = (1 << 24) | (64 << 16) | 0;\n\n\n //table.op[opts.table_index] = 64;\n //table.bits[opts.table_index] = 1;\n //table.val[opts.table_index++] = 0;\n table[table_index++] = (1 << 24) | (64 << 16) | 0;\n\n opts.bits = 1;\n return 0; /* no symbols, but wait for decoding to report error */\n }\n for (min = 1; min < max; min++) {\n if (count[min] !== 0) { break; }\n }\n if (root < min) {\n root = min;\n }\n\n /* check for an over-subscribed or incomplete set of lengths */\n left = 1;\n for (len = 1; len <= MAXBITS; len++) {\n left <<= 1;\n left -= count[len];\n if (left < 0) {\n return -1;\n } /* over-subscribed */\n }\n if (left > 0 && (type === CODES$1 || max !== 1)) {\n return -1; /* incomplete set */\n }\n\n /* generate offsets into symbol table for each length for sorting */\n offs[1] = 0;\n for (len = 1; len < MAXBITS; len++) {\n offs[len + 1] = offs[len] + count[len];\n }\n\n /* sort symbols by length, by symbol order within each length */\n for (sym = 0; sym < codes; sym++) {\n if (lens[lens_index + sym] !== 0) {\n work[offs[lens[lens_index + sym]]++] = sym;\n }\n }\n\n /*\n Create and fill in decoding tables. In this loop, the table being\n filled is at next and has curr index bits. The code being used is huff\n with length len. That code is converted to an index by dropping drop\n bits off of the bottom. For codes where len is less than drop + curr,\n those top drop + curr - len bits are incremented through all values to\n fill the table with replicated entries.\n\n root is the number of index bits for the root table. When len exceeds\n root, sub-tables are created pointed to by the root entry with an index\n of the low root bits of huff. This is saved in low to check for when a\n new sub-table should be started. drop is zero when the root table is\n being filled, and drop is root when sub-tables are being filled.\n\n When a new sub-table is needed, it is necessary to look ahead in the\n code lengths to determine what size sub-table is needed. The length\n counts are used for this, and so count[] is decremented as codes are\n entered in the tables.\n\n used keeps track of how many table entries have been allocated from the\n provided *table space. It is checked for LENS and DIST tables against\n the constants ENOUGH_LENS and ENOUGH_DISTS to guard against changes in\n the initial root table size constants. See the comments in inftrees.h\n for more information.\n\n sym increments through all symbols, and the loop terminates when\n all codes of length max, i.e. all codes, have been processed. This\n routine permits incomplete codes, so another loop after this one fills\n in the rest of the decoding tables with invalid code markers.\n */\n\n /* set up for code type */\n // poor man optimization - use if-else instead of switch,\n // to avoid deopts in old v8\n if (type === CODES$1) {\n base = extra = work; /* dummy value--not used */\n match = 20;\n\n } else if (type === LENS$1) {\n base = lbase;\n extra = lext;\n match = 257;\n\n } else { /* DISTS */\n base = dbase;\n extra = dext;\n match = 0;\n }\n\n /* initialize opts for loop */\n huff = 0; /* starting code */\n sym = 0; /* starting code symbol */\n len = min; /* starting code length */\n next = table_index; /* current table to fill in */\n curr = root; /* current table index bits */\n drop = 0; /* current bits to drop from code for index */\n low = -1; /* trigger new sub-table when len > root */\n used = 1 << root; /* use root table entries */\n mask = used - 1; /* mask for comparing low */\n\n /* check available table space */\n if ((type === LENS$1 && used > ENOUGH_LENS$1) ||\n (type === DISTS$1 && used > ENOUGH_DISTS$1)) {\n return 1;\n }\n\n /* process all codes and make table entries */\n for (;;) {\n /* create table entry */\n here_bits = len - drop;\n if (work[sym] + 1 < match) {\n here_op = 0;\n here_val = work[sym];\n }\n else if (work[sym] >= match) {\n here_op = extra[work[sym] - match];\n here_val = base[work[sym] - match];\n }\n else {\n here_op = 32 + 64; /* end of block */\n here_val = 0;\n }\n\n /* replicate for those indices with low len bits equal to huff */\n incr = 1 << (len - drop);\n fill = 1 << curr;\n min = fill; /* save offset to next table */\n do {\n fill -= incr;\n table[next + (huff >> drop) + fill] = (here_bits << 24) | (here_op << 16) | here_val |0;\n } while (fill !== 0);\n\n /* backwards increment the len-bit code huff */\n incr = 1 << (len - 1);\n while (huff & incr) {\n incr >>= 1;\n }\n if (incr !== 0) {\n huff &= incr - 1;\n huff += incr;\n } else {\n huff = 0;\n }\n\n /* go to next symbol, update count, len */\n sym++;\n if (--count[len] === 0) {\n if (len === max) { break; }\n len = lens[lens_index + work[sym]];\n }\n\n /* create new sub-table if needed */\n if (len > root && (huff & mask) !== low) {\n /* if first time, transition to sub-tables */\n if (drop === 0) {\n drop = root;\n }\n\n /* increment past last table */\n next += min; /* here min is 1 << curr */\n\n /* determine length of next table */\n curr = len - drop;\n left = 1 << curr;\n while (curr + drop < max) {\n left -= count[curr + drop];\n if (left <= 0) { break; }\n curr++;\n left <<= 1;\n }\n\n /* check for enough space */\n used += 1 << curr;\n if ((type === LENS$1 && used > ENOUGH_LENS$1) ||\n (type === DISTS$1 && used > ENOUGH_DISTS$1)) {\n return 1;\n }\n\n /* point entry in root table to sub-table */\n low = huff & mask;\n /*table.op[low] = curr;\n table.bits[low] = root;\n table.val[low] = next - opts.table_index;*/\n table[low] = (root << 24) | (curr << 16) | (next - table_index) |0;\n }\n }\n\n /* fill in remaining table entry if code is incomplete (guaranteed to have\n at most one remaining entry, since if the code is incomplete, the\n maximum code length that was allowed to get this far is one bit) */\n if (huff !== 0) {\n //table.op[next + huff] = 64; /* invalid code marker */\n //table.bits[next + huff] = len - drop;\n //table.val[next + huff] = 0;\n table[next + huff] = ((len - drop) << 24) | (64 << 16) |0;\n }\n\n /* set return parameters */\n //opts.table_index += used;\n opts.bits = root;\n return 0;\n};\n\n\nvar inftrees = inflate_table;\n\n// (C) 1995-2013 Jean-loup Gailly and Mark Adler\n// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin\n//\n// This software is provided 'as-is', without any express or implied\n// warranty. In no event will the authors be held liable for any damages\n// arising from the use of this software.\n//\n// Permission is granted to anyone to use this software for any purpose,\n// including commercial applications, and to alter it and redistribute it\n// freely, subject to the following restrictions:\n//\n// 1. The origin of this software must not be misrepresented; you must not\n// claim that you wrote the original software. If you use this software\n// in a product, an acknowledgment in the product documentation would be\n// appreciated but is not required.\n// 2. Altered source versions must be plainly marked as such, and must not be\n// misrepresented as being the original software.\n// 3. This notice may not be removed or altered from any source distribution.\n\n\n\n\n\n\nconst CODES = 0;\nconst LENS = 1;\nconst DISTS = 2;\n\n/* Public constants ==========================================================*/\n/* ===========================================================================*/\n\nconst {\n Z_FINISH: Z_FINISH$1, Z_BLOCK, Z_TREES,\n Z_OK: Z_OK$1, Z_STREAM_END: Z_STREAM_END$1, Z_NEED_DICT: Z_NEED_DICT$1, Z_STREAM_ERROR: Z_STREAM_ERROR$1, Z_DATA_ERROR: Z_DATA_ERROR$1, Z_MEM_ERROR: Z_MEM_ERROR$1, Z_BUF_ERROR,\n Z_DEFLATED\n} = constants$2;\n\n\n/* STATES ====================================================================*/\n/* ===========================================================================*/\n\n\nconst HEAD = 16180; /* i: waiting for magic header */\nconst FLAGS = 16181; /* i: waiting for method and flags (gzip) */\nconst TIME = 16182; /* i: waiting for modification time (gzip) */\nconst OS = 16183; /* i: waiting for extra flags and operating system (gzip) */\nconst EXLEN = 16184; /* i: waiting for extra length (gzip) */\nconst EXTRA = 16185; /* i: waiting for extra bytes (gzip) */\nconst NAME = 16186; /* i: waiting for end of file name (gzip) */\nconst COMMENT = 16187; /* i: waiting for end of comment (gzip) */\nconst HCRC = 16188; /* i: waiting for header crc (gzip) */\nconst DICTID = 16189; /* i: waiting for dictionary check value */\nconst DICT = 16190; /* waiting for inflateSetDictionary() call */\nconst TYPE = 16191; /* i: waiting for type bits, including last-flag bit */\nconst TYPEDO = 16192; /* i: same, but skip check to exit inflate on new block */\nconst STORED = 16193; /* i: waiting for stored size (length and complement) */\nconst COPY_ = 16194; /* i/o: same as COPY below, but only first time in */\nconst COPY = 16195; /* i/o: waiting for input or output to copy stored block */\nconst TABLE = 16196; /* i: waiting for dynamic block table lengths */\nconst LENLENS = 16197; /* i: waiting for code length code lengths */\nconst CODELENS = 16198; /* i: waiting for length/lit and distance code lengths */\nconst LEN_ = 16199; /* i: same as LEN below, but only first time in */\nconst LEN = 16200; /* i: waiting for length/lit/eob code */\nconst LENEXT = 16201; /* i: waiting for length extra bits */\nconst DIST = 16202; /* i: waiting for distance code */\nconst DISTEXT = 16203; /* i: waiting for distance extra bits */\nconst MATCH = 16204; /* o: waiting for output space to copy string */\nconst LIT = 16205; /* o: waiting for output space to write literal */\nconst CHECK = 16206; /* i: waiting for 32-bit check value */\nconst LENGTH = 16207; /* i: waiting for 32-bit length (gzip) */\nconst DONE = 16208; /* finished check, done -- remain here until reset */\nconst BAD = 16209; /* got a data error -- remain here until reset */\nconst MEM = 16210; /* got an inflate() memory error -- remain here until reset */\nconst SYNC = 16211; /* looking for synchronization bytes to restart inflate() */\n\n/* ===========================================================================*/\n\n\n\nconst ENOUGH_LENS = 852;\nconst ENOUGH_DISTS = 592;\n//const ENOUGH = (ENOUGH_LENS+ENOUGH_DISTS);\n\nconst MAX_WBITS = 15;\n/* 32K LZ77 window */\nconst DEF_WBITS = MAX_WBITS;\n\n\nconst zswap32 = (q) => {\n\n return (((q >>> 24) & 0xff) +\n ((q >>> 8) & 0xff00) +\n ((q & 0xff00) << 8) +\n ((q & 0xff) << 24));\n};\n\n\nfunction InflateState() {\n this.strm = null; /* pointer back to this zlib stream */\n this.mode = 0; /* current inflate mode */\n this.last = false; /* true if processing last block */\n this.wrap = 0; /* bit 0 true for zlib, bit 1 true for gzip,\n bit 2 true to validate check value */\n this.havedict = false; /* true if dictionary provided */\n this.flags = 0; /* gzip header method and flags (0 if zlib), or\n -1 if raw or no header yet */\n this.dmax = 0; /* zlib header max distance (INFLATE_STRICT) */\n this.check = 0; /* protected copy of check value */\n this.total = 0; /* protected copy of output count */\n // TODO: may be {}\n this.head = null; /* where to save gzip header information */\n\n /* sliding window */\n this.wbits = 0; /* log base 2 of requested window size */\n this.wsize = 0; /* window size or zero if not using window */\n this.whave = 0; /* valid bytes in the window */\n this.wnext = 0; /* window write index */\n this.window = null; /* allocated sliding window, if needed */\n\n /* bit accumulator */\n this.hold = 0; /* input bit accumulator */\n this.bits = 0; /* number of bits in \"in\" */\n\n /* for string and stored block copying */\n this.length = 0; /* literal or length of data to copy */\n this.offset = 0; /* distance back to copy string from */\n\n /* for table and code decoding */\n this.extra = 0; /* extra bits needed */\n\n /* fixed and dynamic code tables */\n this.lencode = null; /* starting table for length/literal codes */\n this.distcode = null; /* starting table for distance codes */\n this.lenbits = 0; /* index bits for lencode */\n this.distbits = 0; /* index bits for distcode */\n\n /* dynamic table building */\n this.ncode = 0; /* number of code length code lengths */\n this.nlen = 0; /* number of length code lengths */\n this.ndist = 0; /* number of distance code lengths */\n this.have = 0; /* number of code lengths in lens[] */\n this.next = null; /* next available space in codes[] */\n\n this.lens = new Uint16Array(320); /* temporary storage for code lengths */\n this.work = new Uint16Array(288); /* work area for code table building */\n\n /*\n because we don't have pointers in js, we use lencode and distcode directly\n as buffers so we don't need codes\n */\n //this.codes = new Int32Array(ENOUGH); /* space for code tables */\n this.lendyn = null; /* dynamic table for length/literal codes (JS specific) */\n this.distdyn = null; /* dynamic table for distance codes (JS specific) */\n this.sane = 0; /* if false, allow invalid distance too far */\n this.back = 0; /* bits back of last unprocessed length/lit */\n this.was = 0; /* initial length of match */\n}\n\n\nconst inflateStateCheck = (strm) => {\n\n if (!strm) {\n return 1;\n }\n const state = strm.state;\n if (!state || state.strm !== strm ||\n state.mode < HEAD || state.mode > SYNC) {\n return 1;\n }\n return 0;\n};\n\n\nconst inflateResetKeep = (strm) => {\n\n if (inflateStateCheck(strm)) { return Z_STREAM_ERROR$1; }\n const state = strm.state;\n strm.total_in = strm.total_out = state.total = 0;\n strm.msg = ''; /*Z_NULL*/\n if (state.wrap) { /* to support ill-conceived Java test suite */\n strm.adler = state.wrap & 1;\n }\n state.mode = HEAD;\n state.last = 0;\n state.havedict = 0;\n state.flags = -1;\n state.dmax = 32768;\n state.head = null/*Z_NULL*/;\n state.hold = 0;\n state.bits = 0;\n //state.lencode = state.distcode = state.next = state.codes;\n state.lencode = state.lendyn = new Int32Array(ENOUGH_LENS);\n state.distcode = state.distdyn = new Int32Array(ENOUGH_DISTS);\n\n state.sane = 1;\n state.back = -1;\n //Tracev((stderr, \"inflate: reset\\n\"));\n return Z_OK$1;\n};\n\n\nconst inflateReset = (strm) => {\n\n if (inflateStateCheck(strm)) { return Z_STREAM_ERROR$1; }\n const state = strm.state;\n state.wsize = 0;\n state.whave = 0;\n state.wnext = 0;\n return inflateResetKeep(strm);\n\n};\n\n\nconst inflateReset2 = (strm, windowBits) => {\n let wrap;\n\n /* get the state */\n if (inflateStateCheck(strm)) { return Z_STREAM_ERROR$1; }\n const state = strm.state;\n\n /* extract wrap request from windowBits parameter */\n if (windowBits < 0) {\n wrap = 0;\n windowBits = -windowBits;\n }\n else {\n wrap = (windowBits >> 4) + 5;\n if (windowBits < 48) {\n windowBits &= 15;\n }\n }\n\n /* set number of window bits, free window if different */\n if (windowBits && (windowBits < 8 || windowBits > 15)) {\n return Z_STREAM_ERROR$1;\n }\n if (state.window !== null && state.wbits !== windowBits) {\n state.window = null;\n }\n\n /* update state and reset the rest of it */\n state.wrap = wrap;\n state.wbits = windowBits;\n return inflateReset(strm);\n};\n\n\nconst inflateInit2 = (strm, windowBits) => {\n\n if (!strm) { return Z_STREAM_ERROR$1; }\n //strm.msg = Z_NULL; /* in case we return an error */\n\n const state = new InflateState();\n\n //if (state === Z_NULL) return Z_MEM_ERROR;\n //Tracev((stderr, \"inflate: allocated\\n\"));\n strm.state = state;\n state.strm = strm;\n state.window = null/*Z_NULL*/;\n state.mode = HEAD; /* to pass state test in inflateReset2() */\n const ret = inflateReset2(strm, windowBits);\n if (ret !== Z_OK$1) {\n strm.state = null/*Z_NULL*/;\n }\n return ret;\n};\n\n\nconst inflateInit = (strm) => {\n\n return inflateInit2(strm, DEF_WBITS);\n};\n\n\n/*\n Return state with length and distance decoding tables and index sizes set to\n fixed code decoding. Normally this returns fixed tables from inffixed.h.\n If BUILDFIXED is defined, then instead this routine builds the tables the\n first time it's called, and returns those tables the first time and\n thereafter. This reduces the size of the code by about 2K bytes, in\n exchange for a little execution time. However, BUILDFIXED should not be\n used for threaded applications, since the rewriting of the tables and virgin\n may not be thread-safe.\n */\nlet virgin = true;\n\nlet lenfix, distfix; // We have no pointers in JS, so keep tables separate\n\n\nconst fixedtables = (state) => {\n\n /* build fixed huffman tables if first call (may not be thread safe) */\n if (virgin) {\n lenfix = new Int32Array(512);\n distfix = new Int32Array(32);\n\n /* literal/length table */\n let sym = 0;\n while (sym < 144) { state.lens[sym++] = 8; }\n while (sym < 256) { state.lens[sym++] = 9; }\n while (sym < 280) { state.lens[sym++] = 7; }\n while (sym < 288) { state.lens[sym++] = 8; }\n\n inftrees(LENS, state.lens, 0, 288, lenfix, 0, state.work, { bits: 9 });\n\n /* distance table */\n sym = 0;\n while (sym < 32) { state.lens[sym++] = 5; }\n\n inftrees(DISTS, state.lens, 0, 32, distfix, 0, state.work, { bits: 5 });\n\n /* do this just once */\n virgin = false;\n }\n\n state.lencode = lenfix;\n state.lenbits = 9;\n state.distcode = distfix;\n state.distbits = 5;\n};\n\n\n/*\n Update the window with the last wsize (normally 32K) bytes written before\n returning. If window does not exist yet, create it. This is only called\n when a window is already in use, or when output has been written during this\n inflate call, but the end of the deflate stream has not been reached yet.\n It is also called to create a window for dictionary data when a dictionary\n is loaded.\n\n Providing output buffers larger than 32K to inflate() should provide a speed\n advantage, since only the last 32K of output is copied to the sliding window\n upon return from inflate(), and since all distances after the first 32K of\n output will fall in the output data, making match copies simpler and faster.\n The advantage may be dependent on the size of the processor's data caches.\n */\nconst updatewindow = (strm, src, end, copy) => {\n\n let dist;\n const state = strm.state;\n\n /* if it hasn't been done already, allocate space for the window */\n if (state.window === null) {\n state.wsize = 1 << state.wbits;\n state.wnext = 0;\n state.whave = 0;\n\n state.window = new Uint8Array(state.wsize);\n }\n\n /* copy state->wsize or less output bytes into the circular window */\n if (copy >= state.wsize) {\n state.window.set(src.subarray(end - state.wsize, end), 0);\n state.wnext = 0;\n state.whave = state.wsize;\n }\n else {\n dist = state.wsize - state.wnext;\n if (dist > copy) {\n dist = copy;\n }\n //zmemcpy(state->window + state->wnext, end - copy, dist);\n state.window.set(src.subarray(end - copy, end - copy + dist), state.wnext);\n copy -= dist;\n if (copy) {\n //zmemcpy(state->window, end - copy, copy);\n state.window.set(src.subarray(end - copy, end), 0);\n state.wnext = copy;\n state.whave = state.wsize;\n }\n else {\n state.wnext += dist;\n if (state.wnext === state.wsize) { state.wnext = 0; }\n if (state.whave < state.wsize) { state.whave += dist; }\n }\n }\n return 0;\n};\n\n\nconst inflate$2 = (strm, flush) => {\n\n let state;\n let input, output; // input/output buffers\n let next; /* next input INDEX */\n let put; /* next output INDEX */\n let have, left; /* available input and output */\n let hold; /* bit buffer */\n let bits; /* bits in bit buffer */\n let _in, _out; /* save starting available input and output */\n let copy; /* number of stored or match bytes to copy */\n let from; /* where to copy match bytes from */\n let from_source;\n let here = 0; /* current decoding table entry */\n let here_bits, here_op, here_val; // paked \"here\" denormalized (JS specific)\n //let last; /* parent table entry */\n let last_bits, last_op, last_val; // paked \"last\" denormalized (JS specific)\n let len; /* length to copy for repeats, bits to drop */\n let ret; /* return code */\n const hbuf = new Uint8Array(4); /* buffer for gzip header crc calculation */\n let opts;\n\n let n; // temporary variable for NEED_BITS\n\n const order = /* permutation of code lengths */\n new Uint8Array([ 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 ]);\n\n\n if (inflateStateCheck(strm) || !strm.output ||\n (!strm.input && strm.avail_in !== 0)) {\n return Z_STREAM_ERROR$1;\n }\n\n state = strm.state;\n if (state.mode === TYPE) { state.mode = TYPEDO; } /* skip check */\n\n\n //--- LOAD() ---\n put = strm.next_out;\n output = strm.output;\n left = strm.avail_out;\n next = strm.next_in;\n input = strm.input;\n have = strm.avail_in;\n hold = state.hold;\n bits = state.bits;\n //---\n\n _in = have;\n _out = left;\n ret = Z_OK$1;\n\n inf_leave: // goto emulation\n for (;;) {\n switch (state.mode) {\n case HEAD:\n if (state.wrap === 0) {\n state.mode = TYPEDO;\n break;\n }\n //=== NEEDBITS(16);\n while (bits < 16) {\n if (have === 0) { break inf_leave; }\n have--;\n hold += input[next++] << bits;\n bits += 8;\n }\n //===//\n if ((state.wrap & 2) && hold === 0x8b1f) { /* gzip header */\n if (state.wbits === 0) {\n state.wbits = 15;\n }\n state.check = 0/*crc32(0L, Z_NULL, 0)*/;\n //=== CRC2(state.check, hold);\n hbuf[0] = hold & 0xff;\n hbuf[1] = (hold >>> 8) & 0xff;\n state.check = crc32_1(state.check, hbuf, 2, 0);\n //===//\n\n //=== INITBITS();\n hold = 0;\n bits = 0;\n //===//\n state.mode = FLAGS;\n break;\n }\n if (state.head) {\n state.head.done = false;\n }\n if (!(state.wrap & 1) || /* check if zlib header allowed */\n (((hold & 0xff)/*BITS(8)*/ << 8) + (hold >> 8)) % 31) {\n strm.msg = 'incorrect header check';\n state.mode = BAD;\n break;\n }\n if ((hold & 0x0f)/*BITS(4)*/ !== Z_DEFLATED) {\n strm.msg = 'unknown compression method';\n state.mode = BAD;\n break;\n }\n //--- DROPBITS(4) ---//\n hold >>>= 4;\n bits -= 4;\n //---//\n len = (hold & 0x0f)/*BITS(4)*/ + 8;\n if (state.wbits === 0) {\n state.wbits = len;\n }\n if (len > 15 || len > state.wbits) {\n strm.msg = 'invalid window size';\n state.mode = BAD;\n break;\n }\n\n // !!! pako patch. Force use `options.windowBits` if passed.\n // Required to always use max window size by default.\n state.dmax = 1 << state.wbits;\n //state.dmax = 1 << len;\n\n state.flags = 0; /* indicate zlib header */\n //Tracev((stderr, \"inflate: zlib header ok\\n\"));\n strm.adler = state.check = 1/*adler32(0L, Z_NULL, 0)*/;\n state.mode = hold & 0x200 ? DICTID : TYPE;\n //=== INITBITS();\n hold = 0;\n bits = 0;\n //===//\n break;\n case FLAGS:\n //=== NEEDBITS(16); */\n while (bits < 16) {\n if (have === 0) { break inf_leave; }\n have--;\n hold += input[next++] << bits;\n bits += 8;\n }\n //===//\n state.flags = hold;\n if ((state.flags & 0xff) !== Z_DEFLATED) {\n strm.msg = 'unknown compression method';\n state.mode = BAD;\n break;\n }\n if (state.flags & 0xe000) {\n strm.msg = 'unknown header flags set';\n state.mode = BAD;\n break;\n }\n if (state.head) {\n state.head.text = ((hold >> 8) & 1);\n }\n if ((state.flags & 0x0200) && (state.wrap & 4)) {\n //=== CRC2(state.check, hold);\n hbuf[0] = hold & 0xff;\n hbuf[1] = (hold >>> 8) & 0xff;\n state.check = crc32_1(state.check, hbuf, 2, 0);\n //===//\n }\n //=== INITBITS();\n hold = 0;\n bits = 0;\n //===//\n state.mode = TIME;\n /* falls through */\n case TIME:\n //=== NEEDBITS(32); */\n while (bits < 32) {\n if (have === 0) { break inf_leave; }\n have--;\n hold += input[next++] << bits;\n bits += 8;\n }\n //===//\n if (state.head) {\n state.head.time = hold;\n }\n if ((state.flags & 0x0200) && (state.wrap & 4)) {\n //=== CRC4(state.check, hold)\n hbuf[0] = hold & 0xff;\n hbuf[1] = (hold >>> 8) & 0xff;\n hbuf[2] = (hold >>> 16) & 0xff;\n hbuf[3] = (hold >>> 24) & 0xff;\n state.check = crc32_1(state.check, hbuf, 4, 0);\n //===\n }\n //=== INITBITS();\n hold = 0;\n bits = 0;\n //===//\n state.mode = OS;\n /* falls through */\n case OS:\n //=== NEEDBITS(16); */\n while (bits < 16) {\n if (have === 0) { break inf_leave; }\n have--;\n hold += input[next++] << bits;\n bits += 8;\n }\n //===//\n if (state.head) {\n state.head.xflags = (hold & 0xff);\n state.head.os = (hold >> 8);\n }\n if ((state.flags & 0x0200) && (state.wrap & 4)) {\n //=== CRC2(state.check, hold);\n hbuf[0] = hold & 0xff;\n hbuf[1] = (hold >>> 8) & 0xff;\n state.check = crc32_1(state.check, hbuf, 2, 0);\n //===//\n }\n //=== INITBITS();\n hold = 0;\n bits = 0;\n //===//\n state.mode = EXLEN;\n /* falls through */\n case EXLEN:\n if (state.flags & 0x0400) {\n //=== NEEDBITS(16); */\n while (bits < 16) {\n if (have === 0) { break inf_leave; }\n have--;\n hold += input[next++] << bits;\n bits += 8;\n }\n //===//\n state.length = hold;\n if (state.head) {\n state.head.extra_len = hold;\n }\n if ((state.flags & 0x0200) && (state.wrap & 4)) {\n //=== CRC2(state.check, hold);\n hbuf[0] = hold & 0xff;\n hbuf[1] = (hold >>> 8) & 0xff;\n state.check = crc32_1(state.check, hbuf, 2, 0);\n //===//\n }\n //=== INITBITS();\n hold = 0;\n bits = 0;\n //===//\n }\n else if (state.head) {\n state.head.extra = null/*Z_NULL*/;\n }\n state.mode = EXTRA;\n /* falls through */\n case EXTRA:\n if (state.flags & 0x0400) {\n copy = state.length;\n if (copy > have) { copy = have; }\n if (copy) {\n if (state.head) {\n len = state.head.extra_len - state.length;\n if (!state.head.extra) {\n // Use untyped array for more convenient processing later\n state.head.extra = new Uint8Array(state.head.extra_len);\n }\n state.head.extra.set(\n input.subarray(\n next,\n // extra field is limited to 65536 bytes\n // - no need for additional size check\n next + copy\n ),\n /*len + copy > state.head.extra_max - len ? state.head.extra_max : copy,*/\n len\n );\n //zmemcpy(state.head.extra + len, next,\n // len + copy > state.head.extra_max ?\n // state.head.extra_max - len : copy);\n }\n if ((state.flags & 0x0200) && (state.wrap & 4)) {\n state.check = crc32_1(state.check, input, copy, next);\n }\n have -= copy;\n next += copy;\n state.length -= copy;\n }\n if (state.length) { break inf_leave; }\n }\n state.length = 0;\n state.mode = NAME;\n /* falls through */\n case NAME:\n if (state.flags & 0x0800) {\n if (have === 0) { break inf_leave; }\n copy = 0;\n do {\n // TODO: 2 or 1 bytes?\n len = input[next + copy++];\n /* use constant limit because in js we should not preallocate memory */\n if (state.head && len &&\n (state.length < 65536 /*state.head.name_max*/)) {\n state.head.name += String.fromCharCode(len);\n }\n } while (len && copy < have);\n\n if ((state.flags & 0x0200) && (state.wrap & 4)) {\n state.check = crc32_1(state.check, input, copy, next);\n }\n have -= copy;\n next += copy;\n if (len) { break inf_leave; }\n }\n else if (state.head) {\n state.head.name = null;\n }\n state.length = 0;\n state.mode = COMMENT;\n /* falls through */\n case COMMENT:\n if (state.flags & 0x1000) {\n if (have === 0) { break inf_leave; }\n copy = 0;\n do {\n len = input[next + copy++];\n /* use constant limit because in js we should not preallocate memory */\n if (state.head && len &&\n (state.length < 65536 /*state.head.comm_max*/)) {\n state.head.comment += String.fromCharCode(len);\n }\n } while (len && copy < have);\n if ((state.flags & 0x0200) && (state.wrap & 4)) {\n state.check = crc32_1(state.check, input, copy, next);\n }\n have -= copy;\n next += copy;\n if (len) { break inf_leave; }\n }\n else if (state.head) {\n state.head.comment = null;\n }\n state.mode = HCRC;\n /* falls through */\n case HCRC:\n if (state.flags & 0x0200) {\n //=== NEEDBITS(16); */\n while (bits < 16) {\n if (have === 0) { break inf_leave; }\n have--;\n hold += input[next++] << bits;\n bits += 8;\n }\n //===//\n if ((state.wrap & 4) && hold !== (state.check & 0xffff)) {\n strm.msg = 'header crc mismatch';\n state.mode = BAD;\n break;\n }\n //=== INITBITS();\n hold = 0;\n bits = 0;\n //===//\n }\n if (state.head) {\n state.head.hcrc = ((state.flags >> 9) & 1);\n state.head.done = true;\n }\n strm.adler = state.check = 0;\n state.mode = TYPE;\n break;\n case DICTID:\n //=== NEEDBITS(32); */\n while (bits < 32) {\n if (have === 0) { break inf_leave; }\n have--;\n hold += input[next++] << bits;\n bits += 8;\n }\n //===//\n strm.adler = state.check = zswap32(hold);\n //=== INITBITS();\n hold = 0;\n bits = 0;\n //===//\n state.mode = DICT;\n /* falls through */\n case DICT:\n if (state.havedict === 0) {\n //--- RESTORE() ---\n strm.next_out = put;\n strm.avail_out = left;\n strm.next_in = next;\n strm.avail_in = have;\n state.hold = hold;\n state.bits = bits;\n //---\n return Z_NEED_DICT$1;\n }\n strm.adler = state.check = 1/*adler32(0L, Z_NULL, 0)*/;\n state.mode = TYPE;\n /* falls through */\n case TYPE:\n if (flush === Z_BLOCK || flush === Z_TREES) { break inf_leave; }\n /* falls through */\n case TYPEDO:\n if (state.last) {\n //--- BYTEBITS() ---//\n hold >>>= bits & 7;\n bits -= bits & 7;\n //---//\n state.mode = CHECK;\n break;\n }\n //=== NEEDBITS(3); */\n while (bits < 3) {\n if (have === 0) { break inf_leave; }\n have--;\n hold += input[next++] << bits;\n bits += 8;\n }\n //===//\n state.last = (hold & 0x01)/*BITS(1)*/;\n //--- DROPBITS(1) ---//\n hold >>>= 1;\n bits -= 1;\n //---//\n\n switch ((hold & 0x03)/*BITS(2)*/) {\n case 0: /* stored block */\n //Tracev((stderr, \"inflate: stored block%s\\n\",\n // state.last ? \" (last)\" : \"\"));\n state.mode = STORED;\n break;\n case 1: /* fixed block */\n fixedtables(state);\n //Tracev((stderr, \"inflate: fixed codes block%s\\n\",\n // state.last ? \" (last)\" : \"\"));\n state.mode = LEN_; /* decode codes */\n if (flush === Z_TREES) {\n //--- DROPBITS(2) ---//\n hold >>>= 2;\n bits -= 2;\n //---//\n break inf_leave;\n }\n break;\n case 2: /* dynamic block */\n //Tracev((stderr, \"inflate: dynamic codes block%s\\n\",\n // state.last ? \" (last)\" : \"\"));\n state.mode = TABLE;\n break;\n case 3:\n strm.msg = 'invalid block type';\n state.mode = BAD;\n }\n //--- DROPBITS(2) ---//\n hold >>>= 2;\n bits -= 2;\n //---//\n break;\n case STORED:\n //--- BYTEBITS() ---// /* go to byte boundary */\n hold >>>= bits & 7;\n bits -= bits & 7;\n //---//\n //=== NEEDBITS(32); */\n while (bits < 32) {\n if (have === 0) { break inf_leave; }\n have--;\n hold += input[next++] << bits;\n bits += 8;\n }\n //===//\n if ((hold & 0xffff) !== ((hold >>> 16) ^ 0xffff)) {\n strm.msg = 'invalid stored block lengths';\n state.mode = BAD;\n break;\n }\n state.length = hold & 0xffff;\n //Tracev((stderr, \"inflate: stored length %u\\n\",\n // state.length));\n //=== INITBITS();\n hold = 0;\n bits = 0;\n //===//\n state.mode = COPY_;\n if (flush === Z_TREES) { break inf_leave; }\n /* falls through */\n case COPY_:\n state.mode = COPY;\n /* falls through */\n case COPY:\n copy = state.length;\n if (copy) {\n if (copy > have) { copy = have; }\n if (copy > left) { copy = left; }\n if (copy === 0) { break inf_leave; }\n //--- zmemcpy(put, next, copy); ---\n output.set(input.subarray(next, next + copy), put);\n //---//\n have -= copy;\n next += copy;\n left -= copy;\n put += copy;\n state.length -= copy;\n break;\n }\n //Tracev((stderr, \"inflate: stored end\\n\"));\n state.mode = TYPE;\n break;\n case TABLE:\n //=== NEEDBITS(14); */\n while (bits < 14) {\n if (have === 0) { break inf_leave; }\n have--;\n hold += input[next++] << bits;\n bits += 8;\n }\n //===//\n state.nlen = (hold & 0x1f)/*BITS(5)*/ + 257;\n //--- DROPBITS(5) ---//\n hold >>>= 5;\n bits -= 5;\n //---//\n state.ndist = (hold & 0x1f)/*BITS(5)*/ + 1;\n //--- DROPBITS(5) ---//\n hold >>>= 5;\n bits -= 5;\n //---//\n state.ncode = (hold & 0x0f)/*BITS(4)*/ + 4;\n //--- DROPBITS(4) ---//\n hold >>>= 4;\n bits -= 4;\n //---//\n//#ifndef PKZIP_BUG_WORKAROUND\n if (state.nlen > 286 || state.ndist > 30) {\n strm.msg = 'too many length or distance symbols';\n state.mode = BAD;\n break;\n }\n//#endif\n //Tracev((stderr, \"inflate: table sizes ok\\n\"));\n state.have = 0;\n state.mode = LENLENS;\n /* falls through */\n case LENLENS:\n while (state.have < state.ncode) {\n //=== NEEDBITS(3);\n while (bits < 3) {\n if (have === 0) { break inf_leave; }\n have--;\n hold += input[next++] << bits;\n bits += 8;\n }\n //===//\n state.lens[order[state.have++]] = (hold & 0x07);//BITS(3);\n //--- DROPBITS(3) ---//\n hold >>>= 3;\n bits -= 3;\n //---//\n }\n while (state.have < 19) {\n state.lens[order[state.have++]] = 0;\n }\n // We have separate tables & no pointers. 2 commented lines below not needed.\n //state.next = state.codes;\n //state.lencode = state.next;\n // Switch to use dynamic table\n state.lencode = state.lendyn;\n state.lenbits = 7;\n\n opts = { bits: state.lenbits };\n ret = inftrees(CODES, state.lens, 0, 19, state.lencode, 0, state.work, opts);\n state.lenbits = opts.bits;\n\n if (ret) {\n strm.msg = 'invalid code lengths set';\n state.mode = BAD;\n break;\n }\n //Tracev((stderr, \"inflate: code lengths ok\\n\"));\n state.have = 0;\n state.mode = CODELENS;\n /* falls through */\n case CODELENS:\n while (state.have < state.nlen + state.ndist) {\n for (;;) {\n here = state.lencode[hold & ((1 << state.lenbits) - 1)];/*BITS(state.lenbits)*/\n here_bits = here >>> 24;\n here_op = (here >>> 16) & 0xff;\n here_val = here & 0xffff;\n\n if ((here_bits) <= bits) { break; }\n //--- PULLBYTE() ---//\n if (have === 0) { break inf_leave; }\n have--;\n hold += input[next++] << bits;\n bits += 8;\n //---//\n }\n if (here_val < 16) {\n //--- DROPBITS(here.bits) ---//\n hold >>>= here_bits;\n bits -= here_bits;\n //---//\n state.lens[state.have++] = here_val;\n }\n else {\n if (here_val === 16) {\n //=== NEEDBITS(here.bits + 2);\n n = here_bits + 2;\n while (bits < n) {\n if (have === 0) { break inf_leave; }\n have--;\n hold += input[next++] << bits;\n bits += 8;\n }\n //===//\n //--- DROPBITS(here.bits) ---//\n hold >>>= here_bits;\n bits -= here_bits;\n //---//\n if (state.have === 0) {\n strm.msg = 'invalid bit length repeat';\n state.mode = BAD;\n break;\n }\n len = state.lens[state.have - 1];\n copy = 3 + (hold & 0x03);//BITS(2);\n //--- DROPBITS(2) ---//\n hold >>>= 2;\n bits -= 2;\n //---//\n }\n else if (here_val === 17) {\n //=== NEEDBITS(here.bits + 3);\n n = here_bits + 3;\n while (bits < n) {\n if (have === 0) { break inf_leave; }\n have--;\n hold += input[next++] << bits;\n bits += 8;\n }\n //===//\n //--- DROPBITS(here.bits) ---//\n hold >>>= here_bits;\n bits -= here_bits;\n //---//\n len = 0;\n copy = 3 + (hold & 0x07);//BITS(3);\n //--- DROPBITS(3) ---//\n hold >>>= 3;\n bits -= 3;\n //---//\n }\n else {\n //=== NEEDBITS(here.bits + 7);\n n = here_bits + 7;\n while (bits < n) {\n if (have === 0) { break inf_leave; }\n have--;\n hold += input[next++] << bits;\n bits += 8;\n }\n //===//\n //--- DROPBITS(here.bits) ---//\n hold >>>= here_bits;\n bits -= here_bits;\n //---//\n len = 0;\n copy = 11 + (hold & 0x7f);//BITS(7);\n //--- DROPBITS(7) ---//\n hold >>>= 7;\n bits -= 7;\n //---//\n }\n if (state.have + copy > state.nlen + state.ndist) {\n strm.msg = 'invalid bit length repeat';\n state.mode = BAD;\n break;\n }\n while (copy--) {\n state.lens[state.have++] = len;\n }\n }\n }\n\n /* handle error breaks in while */\n if (state.mode === BAD) { break; }\n\n /* check for end-of-block code (better have one) */\n if (state.lens[256] === 0) {\n strm.msg = 'invalid code -- missing end-of-block';\n state.mode = BAD;\n break;\n }\n\n /* build code tables -- note: do not change the lenbits or distbits\n values here (9 and 6) without reading the comments in inftrees.h\n concerning the ENOUGH constants, which depend on those values */\n state.lenbits = 9;\n\n opts = { bits: state.lenbits };\n ret = inftrees(LENS, state.lens, 0, state.nlen, state.lencode, 0, state.work, opts);\n // We have separate tables & no pointers. 2 commented lines below not needed.\n // state.next_index = opts.table_index;\n state.lenbits = opts.bits;\n // state.lencode = state.next;\n\n if (ret) {\n strm.msg = 'invalid literal/lengths set';\n state.mode = BAD;\n break;\n }\n\n state.distbits = 6;\n //state.distcode.copy(state.codes);\n // Switch to use dynamic table\n state.distcode = state.distdyn;\n opts = { bits: state.distbits };\n ret = inftrees(DISTS, state.lens, state.nlen, state.ndist, state.distcode, 0, state.work, opts);\n // We have separate tables & no pointers. 2 commented lines below not needed.\n // state.next_index = opts.table_index;\n state.distbits = opts.bits;\n // state.distcode = state.next;\n\n if (ret) {\n strm.msg = 'invalid distances set';\n state.mode = BAD;\n break;\n }\n //Tracev((stderr, 'inflate: codes ok\\n'));\n state.mode = LEN_;\n if (flush === Z_TREES) { break inf_leave; }\n /* falls through */\n case LEN_:\n state.mode = LEN;\n /* falls through */\n case LEN:\n if (have >= 6 && left >= 258) {\n //--- RESTORE() ---\n strm.next_out = put;\n strm.avail_out = left;\n strm.next_in = next;\n strm.avail_in = have;\n state.hold = hold;\n state.bits = bits;\n //---\n inffast(strm, _out);\n //--- LOAD() ---\n put = strm.next_out;\n output = strm.output;\n left = strm.avail_out;\n next = strm.next_in;\n input = strm.input;\n have = strm.avail_in;\n hold = state.hold;\n bits = state.bits;\n //---\n\n if (state.mode === TYPE) {\n state.back = -1;\n }\n break;\n }\n state.back = 0;\n for (;;) {\n here = state.lencode[hold & ((1 << state.lenbits) - 1)]; /*BITS(state.lenbits)*/\n here_bits = here >>> 24;\n here_op = (here >>> 16) & 0xff;\n here_val = here & 0xffff;\n\n if (here_bits <= bits) { break; }\n //--- PULLBYTE() ---//\n if (have === 0) { break inf_leave; }\n have--;\n hold += input[next++] << bits;\n bits += 8;\n //---//\n }\n if (here_op && (here_op & 0xf0) === 0) {\n last_bits = here_bits;\n last_op = here_op;\n last_val = here_val;\n for (;;) {\n here = state.lencode[last_val +\n ((hold & ((1 << (last_bits + last_op)) - 1))/*BITS(last.bits + last.op)*/ >> last_bits)];\n here_bits = here >>> 24;\n here_op = (here >>> 16) & 0xff;\n here_val = here & 0xffff;\n\n if ((last_bits + here_bits) <= bits) { break; }\n //--- PULLBYTE() ---//\n if (have === 0) { break inf_leave; }\n have--;\n hold += input[next++] << bits;\n bits += 8;\n //---//\n }\n //--- DROPBITS(last.bits) ---//\n hold >>>= last_bits;\n bits -= last_bits;\n //---//\n state.back += last_bits;\n }\n //--- DROPBITS(here.bits) ---//\n hold >>>= here_bits;\n bits -= here_bits;\n //---//\n state.back += here_bits;\n state.length = here_val;\n if (here_op === 0) {\n //Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ?\n // \"inflate: literal '%c'\\n\" :\n // \"inflate: literal 0x%02x\\n\", here.val));\n state.mode = LIT;\n break;\n }\n if (here_op & 32) {\n //Tracevv((stderr, \"inflate: end of block\\n\"));\n state.back = -1;\n state.mode = TYPE;\n break;\n }\n if (here_op & 64) {\n strm.msg = 'invalid literal/length code';\n state.mode = BAD;\n break;\n }\n state.extra = here_op & 15;\n state.mode = LENEXT;\n /* falls through */\n case LENEXT:\n if (state.extra) {\n //=== NEEDBITS(state.extra);\n n = state.extra;\n while (bits < n) {\n if (have === 0) { break inf_leave; }\n have--;\n hold += input[next++] << bits;\n bits += 8;\n }\n //===//\n state.length += hold & ((1 << state.extra) - 1)/*BITS(state.extra)*/;\n //--- DROPBITS(state.extra) ---//\n hold >>>= state.extra;\n bits -= state.extra;\n //---//\n state.back += state.extra;\n }\n //Tracevv((stderr, \"inflate: length %u\\n\", state.length));\n state.was = state.length;\n state.mode = DIST;\n /* falls through */\n case DIST:\n for (;;) {\n here = state.distcode[hold & ((1 << state.distbits) - 1)];/*BITS(state.distbits)*/\n here_bits = here >>> 24;\n here_op = (here >>> 16) & 0xff;\n here_val = here & 0xffff;\n\n if ((here_bits) <= bits) { break; }\n //--- PULLBYTE() ---//\n if (have === 0) { break inf_leave; }\n have--;\n hold += input[next++] << bits;\n bits += 8;\n //---//\n }\n if ((here_op & 0xf0) === 0) {\n last_bits = here_bits;\n last_op = here_op;\n last_val = here_val;\n for (;;) {\n here = state.distcode[last_val +\n ((hold & ((1 << (last_bits + last_op)) - 1))/*BITS(last.bits + last.op)*/ >> last_bits)];\n here_bits = here >>> 24;\n here_op = (here >>> 16) & 0xff;\n here_val = here & 0xffff;\n\n if ((last_bits + here_bits) <= bits) { break; }\n //--- PULLBYTE() ---//\n if (have === 0) { break inf_leave; }\n have--;\n hold += input[next++] << bits;\n bits += 8;\n //---//\n }\n //--- DROPBITS(last.bits) ---//\n hold >>>= last_bits;\n bits -= last_bits;\n //---//\n state.back += last_bits;\n }\n //--- DROPBITS(here.bits) ---//\n hold >>>= here_bits;\n bits -= here_bits;\n //---//\n state.back += here_bits;\n if (here_op & 64) {\n strm.msg = 'invalid distance code';\n state.mode = BAD;\n break;\n }\n state.offset = here_val;\n state.extra = (here_op) & 15;\n state.mode = DISTEXT;\n /* falls through */\n case DISTEXT:\n if (state.extra) {\n //=== NEEDBITS(state.extra);\n n = state.extra;\n while (bits < n) {\n if (have === 0) { break inf_leave; }\n have--;\n hold += input[next++] << bits;\n bits += 8;\n }\n //===//\n state.offset += hold & ((1 << state.extra) - 1)/*BITS(state.extra)*/;\n //--- DROPBITS(state.extra) ---//\n hold >>>= state.extra;\n bits -= state.extra;\n //---//\n state.back += state.extra;\n }\n//#ifdef INFLATE_STRICT\n if (state.offset > state.dmax) {\n strm.msg = 'invalid distance too far back';\n state.mode = BAD;\n break;\n }\n//#endif\n //Tracevv((stderr, \"inflate: distance %u\\n\", state.offset));\n state.mode = MATCH;\n /* falls through */\n case MATCH:\n if (left === 0) { break inf_leave; }\n copy = _out - left;\n if (state.offset > copy) { /* copy from window */\n copy = state.offset - copy;\n if (copy > state.whave) {\n if (state.sane) {\n strm.msg = 'invalid distance too far back';\n state.mode = BAD;\n break;\n }\n// (!) This block is disabled in zlib defaults,\n// don't enable it for binary compatibility\n//#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR\n// Trace((stderr, \"inflate.c too far\\n\"));\n// copy -= state.whave;\n// if (copy > state.length) { copy = state.length; }\n// if (copy > left) { copy = left; }\n// left -= copy;\n// state.length -= copy;\n// do {\n// output[put++] = 0;\n// } while (--copy);\n// if (state.length === 0) { state.mode = LEN; }\n// break;\n//#endif\n }\n if (copy > state.wnext) {\n copy -= state.wnext;\n from = state.wsize - copy;\n }\n else {\n from = state.wnext - copy;\n }\n if (copy > state.length) { copy = state.length; }\n from_source = state.window;\n }\n else { /* copy from output */\n from_source = output;\n from = put - state.offset;\n copy = state.length;\n }\n if (copy > left) { copy = left; }\n left -= copy;\n state.length -= copy;\n do {\n output[put++] = from_source[from++];\n } while (--copy);\n if (state.length === 0) { state.mode = LEN; }\n break;\n case LIT:\n if (left === 0) { break inf_leave; }\n output[put++] = state.length;\n left--;\n state.mode = LEN;\n break;\n case CHECK:\n if (state.wrap) {\n //=== NEEDBITS(32);\n while (bits < 32) {\n if (have === 0) { break inf_leave; }\n have--;\n // Use '|' instead of '+' to make sure that result is signed\n hold |= input[next++] << bits;\n bits += 8;\n }\n //===//\n _out -= left;\n strm.total_out += _out;\n state.total += _out;\n if ((state.wrap & 4) && _out) {\n strm.adler = state.check =\n /*UPDATE_CHECK(state.check, put - _out, _out);*/\n (state.flags ? crc32_1(state.check, output, _out, put - _out) : adler32_1(state.check, output, _out, put - _out));\n\n }\n _out = left;\n // NB: crc32 stored as signed 32-bit int, zswap32 returns signed too\n if ((state.wrap & 4) && (state.flags ? hold : zswap32(hold)) !== state.check) {\n strm.msg = 'incorrect data check';\n state.mode = BAD;\n break;\n }\n //=== INITBITS();\n hold = 0;\n bits = 0;\n //===//\n //Tracev((stderr, \"inflate: check matches trailer\\n\"));\n }\n state.mode = LENGTH;\n /* falls through */\n case LENGTH:\n if (state.wrap && state.flags) {\n //=== NEEDBITS(32);\n while (bits < 32) {\n if (have === 0) { break inf_leave; }\n have--;\n hold += input[next++] << bits;\n bits += 8;\n }\n //===//\n if ((state.wrap & 4) && hold !== (state.total & 0xffffffff)) {\n strm.msg = 'incorrect length check';\n state.mode = BAD;\n break;\n }\n //=== INITBITS();\n hold = 0;\n bits = 0;\n //===//\n //Tracev((stderr, \"inflate: length matches trailer\\n\"));\n }\n state.mode = DONE;\n /* falls through */\n case DONE:\n ret = Z_STREAM_END$1;\n break inf_leave;\n case BAD:\n ret = Z_DATA_ERROR$1;\n break inf_leave;\n case MEM:\n return Z_MEM_ERROR$1;\n case SYNC:\n /* falls through */\n default:\n return Z_STREAM_ERROR$1;\n }\n }\n\n // inf_leave <- here is real place for \"goto inf_leave\", emulated via \"break inf_leave\"\n\n /*\n Return from inflate(), updating the total counts and the check value.\n If there was no progress during the inflate() call, return a buffer\n error. Call updatewindow() to create and/or update the window state.\n Note: a memory error from inflate() is non-recoverable.\n */\n\n //--- RESTORE() ---\n strm.next_out = put;\n strm.avail_out = left;\n strm.next_in = next;\n strm.avail_in = have;\n state.hold = hold;\n state.bits = bits;\n //---\n\n if (state.wsize || (_out !== strm.avail_out && state.mode < BAD &&\n (state.mode < CHECK || flush !== Z_FINISH$1))) {\n if (updatewindow(strm, strm.output, strm.next_out, _out - strm.avail_out)) ;\n }\n _in -= strm.avail_in;\n _out -= strm.avail_out;\n strm.total_in += _in;\n strm.total_out += _out;\n state.total += _out;\n if ((state.wrap & 4) && _out) {\n strm.adler = state.check = /*UPDATE_CHECK(state.check, strm.next_out - _out, _out);*/\n (state.flags ? crc32_1(state.check, output, _out, strm.next_out - _out) : adler32_1(state.check, output, _out, strm.next_out - _out));\n }\n strm.data_type = state.bits + (state.last ? 64 : 0) +\n (state.mode === TYPE ? 128 : 0) +\n (state.mode === LEN_ || state.mode === COPY_ ? 256 : 0);\n if (((_in === 0 && _out === 0) || flush === Z_FINISH$1) && ret === Z_OK$1) {\n ret = Z_BUF_ERROR;\n }\n return ret;\n};\n\n\nconst inflateEnd = (strm) => {\n\n if (inflateStateCheck(strm)) {\n return Z_STREAM_ERROR$1;\n }\n\n let state = strm.state;\n if (state.window) {\n state.window = null;\n }\n strm.state = null;\n return Z_OK$1;\n};\n\n\nconst inflateGetHeader = (strm, head) => {\n\n /* check state */\n if (inflateStateCheck(strm)) { return Z_STREAM_ERROR$1; }\n const state = strm.state;\n if ((state.wrap & 2) === 0) { return Z_STREAM_ERROR$1; }\n\n /* save header structure */\n state.head = head;\n head.done = false;\n return Z_OK$1;\n};\n\n\nconst inflateSetDictionary = (strm, dictionary) => {\n const dictLength = dictionary.length;\n\n let state;\n let dictid;\n let ret;\n\n /* check state */\n if (inflateStateCheck(strm)) { return Z_STREAM_ERROR$1; }\n state = strm.state;\n\n if (state.wrap !== 0 && state.mode !== DICT) {\n return Z_STREAM_ERROR$1;\n }\n\n /* check for correct dictionary identifier */\n if (state.mode === DICT) {\n dictid = 1; /* adler32(0, null, 0)*/\n /* dictid = adler32(dictid, dictionary, dictLength); */\n dictid = adler32_1(dictid, dictionary, dictLength, 0);\n if (dictid !== state.check) {\n return Z_DATA_ERROR$1;\n }\n }\n /* copy dictionary to window using updatewindow(), which will amend the\n existing dictionary if appropriate */\n ret = updatewindow(strm, dictionary, dictLength, dictLength);\n if (ret) {\n state.mode = MEM;\n return Z_MEM_ERROR$1;\n }\n state.havedict = 1;\n // Tracev((stderr, \"inflate: dictionary set\\n\"));\n return Z_OK$1;\n};\n\n\nvar inflateReset_1 = inflateReset;\nvar inflateReset2_1 = inflateReset2;\nvar inflateResetKeep_1 = inflateResetKeep;\nvar inflateInit_1 = inflateInit;\nvar inflateInit2_1 = inflateInit2;\nvar inflate_2$1 = inflate$2;\nvar inflateEnd_1 = inflateEnd;\nvar inflateGetHeader_1 = inflateGetHeader;\nvar inflateSetDictionary_1 = inflateSetDictionary;\nvar inflateInfo = 'pako inflate (from Nodeca project)';\n\n/* Not implemented\nmodule.exports.inflateCodesUsed = inflateCodesUsed;\nmodule.exports.inflateCopy = inflateCopy;\nmodule.exports.inflateGetDictionary = inflateGetDictionary;\nmodule.exports.inflateMark = inflateMark;\nmodule.exports.inflatePrime = inflatePrime;\nmodule.exports.inflateSync = inflateSync;\nmodule.exports.inflateSyncPoint = inflateSyncPoint;\nmodule.exports.inflateUndermine = inflateUndermine;\nmodule.exports.inflateValidate = inflateValidate;\n*/\n\nvar inflate_1$2 = {\n\tinflateReset: inflateReset_1,\n\tinflateReset2: inflateReset2_1,\n\tinflateResetKeep: inflateResetKeep_1,\n\tinflateInit: inflateInit_1,\n\tinflateInit2: inflateInit2_1,\n\tinflate: inflate_2$1,\n\tinflateEnd: inflateEnd_1,\n\tinflateGetHeader: inflateGetHeader_1,\n\tinflateSetDictionary: inflateSetDictionary_1,\n\tinflateInfo: inflateInfo\n};\n\n// (C) 1995-2013 Jean-loup Gailly and Mark Adler\n// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin\n//\n// This software is provided 'as-is', without any express or implied\n// warranty. In no event will the authors be held liable for any damages\n// arising from the use of this software.\n//\n// Permission is granted to anyone to use this software for any purpose,\n// including commercial applications, and to alter it and redistribute it\n// freely, subject to the following restrictions:\n//\n// 1. The origin of this software must not be misrepresented; you must not\n// claim that you wrote the original software. If you use this software\n// in a product, an acknowledgment in the product documentation would be\n// appreciated but is not required.\n// 2. Altered source versions must be plainly marked as such, and must not be\n// misrepresented as being the original software.\n// 3. This notice may not be removed or altered from any source distribution.\n\nfunction GZheader() {\n /* true if compressed data believed to be text */\n this.text = 0;\n /* modification time */\n this.time = 0;\n /* extra flags (not used when writing a gzip file) */\n this.xflags = 0;\n /* operating system */\n this.os = 0;\n /* pointer to extra field or Z_NULL if none */\n this.extra = null;\n /* extra field length (valid if extra != Z_NULL) */\n this.extra_len = 0; // Actually, we don't need it in JS,\n // but leave for few code modifications\n\n //\n // Setup limits is not necessary because in js we should not preallocate memory\n // for inflate use constant limit in 65536 bytes\n //\n\n /* space at extra (only when reading header) */\n // this.extra_max = 0;\n /* pointer to zero-terminated file name or Z_NULL */\n this.name = '';\n /* space at name (only when reading header) */\n // this.name_max = 0;\n /* pointer to zero-terminated comment or Z_NULL */\n this.comment = '';\n /* space at comment (only when reading header) */\n // this.comm_max = 0;\n /* true if there was or will be a header crc */\n this.hcrc = 0;\n /* true when done reading gzip header (not used when writing a gzip file) */\n this.done = false;\n}\n\nvar gzheader = GZheader;\n\nconst toString = Object.prototype.toString;\n\n/* Public constants ==========================================================*/\n/* ===========================================================================*/\n\nconst {\n Z_NO_FLUSH, Z_FINISH,\n Z_OK, Z_STREAM_END, Z_NEED_DICT, Z_STREAM_ERROR, Z_DATA_ERROR, Z_MEM_ERROR\n} = constants$2;\n\n/* ===========================================================================*/\n\n\n/**\n * class Inflate\n *\n * Generic JS-style wrapper for zlib calls. If you don't need\n * streaming behaviour - use more simple functions: [[inflate]]\n * and [[inflateRaw]].\n **/\n\n/* internal\n * inflate.chunks -> Array\n *\n * Chunks of output data, if [[Inflate#onData]] not overridden.\n **/\n\n/**\n * Inflate.result -> Uint8Array|String\n *\n * Uncompressed result, generated by default [[Inflate#onData]]\n * and [[Inflate#onEnd]] handlers. Filled after you push last chunk\n * (call [[Inflate#push]] with `Z_FINISH` / `true` param).\n **/\n\n/**\n * Inflate.err -> Number\n *\n * Error code after inflate finished. 0 (Z_OK) on success.\n * Should be checked if broken data possible.\n **/\n\n/**\n * Inflate.msg -> String\n *\n * Error message, if [[Inflate.err]] != 0\n **/\n\n\n/**\n * new Inflate(options)\n * - options (Object): zlib inflate options.\n *\n * Creates new inflator instance with specified params. Throws exception\n * on bad params. Supported options:\n *\n * - `windowBits`\n * - `dictionary`\n *\n * [http://zlib.net/manual.html#Advanced](http://zlib.net/manual.html#Advanced)\n * for more information on these.\n *\n * Additional options, for internal needs:\n *\n * - `chunkSize` - size of generated data chunks (16K by default)\n * - `raw` (Boolean) - do raw inflate\n * - `to` (String) - if equal to 'string', then result will be converted\n * from utf8 to utf16 (javascript) string. When string output requested,\n * chunk length can differ from `chunkSize`, depending on content.\n *\n * By default, when no options set, autodetect deflate/gzip data format via\n * wrapper header.\n *\n * ##### Example:\n *\n * ```javascript\n * const pako = require('pako')\n * const chunk1 = new Uint8Array([1,2,3,4,5,6,7,8,9])\n * const chunk2 = new Uint8Array([10,11,12,13,14,15,16,17,18,19]);\n *\n * const inflate = new pako.Inflate({ level: 3});\n *\n * inflate.push(chunk1, false);\n * inflate.push(chunk2, true); // true -> last chunk\n *\n * if (inflate.err) { throw new Error(inflate.err); }\n *\n * console.log(inflate.result);\n * ```\n **/\nfunction Inflate$1(options) {\n this.options = common.assign({\n chunkSize: 1024 * 64,\n windowBits: 15,\n to: ''\n }, options || {});\n\n const opt = this.options;\n\n // Force window size for `raw` data, if not set directly,\n // because we have no header for autodetect.\n if (opt.raw && (opt.windowBits >= 0) && (opt.windowBits < 16)) {\n opt.windowBits = -opt.windowBits;\n if (opt.windowBits === 0) { opt.windowBits = -15; }\n }\n\n // If `windowBits` not defined (and mode not raw) - set autodetect flag for gzip/deflate\n if ((opt.windowBits >= 0) && (opt.windowBits < 16) &&\n !(options && options.windowBits)) {\n opt.windowBits += 32;\n }\n\n // Gzip header has no info about windows size, we can do autodetect only\n // for deflate. So, if window size not set, force it to max when gzip possible\n if ((opt.windowBits > 15) && (opt.windowBits < 48)) {\n // bit 3 (16) -> gzipped data\n // bit 4 (32) -> autodetect gzip/deflate\n if ((opt.windowBits & 15) === 0) {\n opt.windowBits |= 15;\n }\n }\n\n this.err = 0; // error code, if happens (0 = Z_OK)\n this.msg = ''; // error message\n this.ended = false; // used to avoid multiple onEnd() calls\n this.chunks = []; // chunks of compressed data\n\n this.strm = new zstream();\n this.strm.avail_out = 0;\n\n let status = inflate_1$2.inflateInit2(\n this.strm,\n opt.windowBits\n );\n\n if (status !== Z_OK) {\n throw new Error(messages[status]);\n }\n\n this.header = new gzheader();\n\n inflate_1$2.inflateGetHeader(this.strm, this.header);\n\n // Setup dictionary\n if (opt.dictionary) {\n // Convert data if needed\n if (typeof opt.dictionary === 'string') {\n opt.dictionary = strings.string2buf(opt.dictionary);\n } else if (toString.call(opt.dictionary) === '[object ArrayBuffer]') {\n opt.dictionary = new Uint8Array(opt.dictionary);\n }\n if (opt.raw) { //In raw mode we need to set the dictionary early\n status = inflate_1$2.inflateSetDictionary(this.strm, opt.dictionary);\n if (status !== Z_OK) {\n throw new Error(messages[status]);\n }\n }\n }\n}\n\n/**\n * Inflate#push(data[, flush_mode]) -> Boolean\n * - data (Uint8Array|ArrayBuffer): input data\n * - flush_mode (Number|Boolean): 0..6 for corresponding Z_NO_FLUSH..Z_TREE\n * flush modes. See constants. Skipped or `false` means Z_NO_FLUSH,\n * `true` means Z_FINISH.\n *\n * Sends input data to inflate pipe, generating [[Inflate#onData]] calls with\n * new output chunks. Returns `true` on success. If end of stream detected,\n * [[Inflate#onEnd]] will be called.\n *\n * `flush_mode` is not needed for normal operation, because end of stream\n * detected automatically. You may try to use it for advanced things, but\n * this functionality was not tested.\n *\n * On fail call [[Inflate#onEnd]] with error code and return false.\n *\n * ##### Example\n *\n * ```javascript\n * push(chunk, false); // push one of data chunks\n * ...\n * push(chunk, true); // push last chunk\n * ```\n **/\nInflate$1.prototype.push = function (data, flush_mode) {\n const strm = this.strm;\n const chunkSize = this.options.chunkSize;\n const dictionary = this.options.dictionary;\n let status, _flush_mode, last_avail_out;\n\n if (this.ended) return false;\n\n if (flush_mode === ~~flush_mode) _flush_mode = flush_mode;\n else _flush_mode = flush_mode === true ? Z_FINISH : Z_NO_FLUSH;\n\n // Convert data if needed\n if (toString.call(data) === '[object ArrayBuffer]') {\n strm.input = new Uint8Array(data);\n } else {\n strm.input = data;\n }\n\n strm.next_in = 0;\n strm.avail_in = strm.input.length;\n\n for (;;) {\n if (strm.avail_out === 0) {\n strm.output = new Uint8Array(chunkSize);\n strm.next_out = 0;\n strm.avail_out = chunkSize;\n }\n\n status = inflate_1$2.inflate(strm, _flush_mode);\n\n if (status === Z_NEED_DICT && dictionary) {\n status = inflate_1$2.inflateSetDictionary(strm, dictionary);\n\n if (status === Z_OK) {\n status = inflate_1$2.inflate(strm, _flush_mode);\n } else if (status === Z_DATA_ERROR) {\n // Replace code with more verbose\n status = Z_NEED_DICT;\n }\n }\n\n // Skip snyc markers if more data follows and not raw mode\n while (strm.avail_in > 0 &&\n status === Z_STREAM_END &&\n strm.state.wrap > 0 &&\n data[strm.next_in] !== 0)\n {\n inflate_1$2.inflateReset(strm);\n status = inflate_1$2.inflate(strm, _flush_mode);\n }\n\n switch (status) {\n case Z_STREAM_ERROR:\n case Z_DATA_ERROR:\n case Z_NEED_DICT:\n case Z_MEM_ERROR:\n this.onEnd(status);\n this.ended = true;\n return false;\n }\n\n // Remember real `avail_out` value, because we may patch out buffer content\n // to align utf8 strings boundaries.\n last_avail_out = strm.avail_out;\n\n if (strm.next_out) {\n if (strm.avail_out === 0 || status === Z_STREAM_END) {\n\n if (this.options.to === 'string') {\n\n let next_out_utf8 = strings.utf8border(strm.output, strm.next_out);\n\n let tail = strm.next_out - next_out_utf8;\n let utf8str = strings.buf2string(strm.output, next_out_utf8);\n\n // move tail & realign counters\n strm.next_out = tail;\n strm.avail_out = chunkSize - tail;\n if (tail) strm.output.set(strm.output.subarray(next_out_utf8, next_out_utf8 + tail), 0);\n\n this.onData(utf8str);\n\n } else {\n this.onData(strm.output.length === strm.next_out ? strm.output : strm.output.subarray(0, strm.next_out));\n }\n }\n }\n\n // Must repeat iteration if out buffer is full\n if (status === Z_OK && last_avail_out === 0) continue;\n\n // Finalize if end of stream reached.\n if (status === Z_STREAM_END) {\n status = inflate_1$2.inflateEnd(this.strm);\n this.onEnd(status);\n this.ended = true;\n return true;\n }\n\n if (strm.avail_in === 0) break;\n }\n\n return true;\n};\n\n\n/**\n * Inflate#onData(chunk) -> Void\n * - chunk (Uint8Array|String): output data. When string output requested,\n * each chunk will be string.\n *\n * By default, stores data blocks in `chunks[]` property and glue\n * those in `onEnd`. Override this handler, if you need another behaviour.\n **/\nInflate$1.prototype.onData = function (chunk) {\n this.chunks.push(chunk);\n};\n\n\n/**\n * Inflate#onEnd(status) -> Void\n * - status (Number): inflate status. 0 (Z_OK) on success,\n * other if not.\n *\n * Called either after you tell inflate that the input stream is\n * complete (Z_FINISH). By default - join collected chunks,\n * free memory and fill `results` / `err` properties.\n **/\nInflate$1.prototype.onEnd = function (status) {\n // On success - join\n if (status === Z_OK) {\n if (this.options.to === 'string') {\n this.result = this.chunks.join('');\n } else {\n this.result = common.flattenChunks(this.chunks);\n }\n }\n this.chunks = [];\n this.err = status;\n this.msg = this.strm.msg;\n};\n\n\n/**\n * inflate(data[, options]) -> Uint8Array|String\n * - data (Uint8Array|ArrayBuffer): input data to decompress.\n * - options (Object): zlib inflate options.\n *\n * Decompress `data` with inflate/ungzip and `options`. Autodetect\n * format via wrapper header by default. That's why we don't provide\n * separate `ungzip` method.\n *\n * Supported options are:\n *\n * - windowBits\n *\n * [http://zlib.net/manual.html#Advanced](http://zlib.net/manual.html#Advanced)\n * for more information.\n *\n * Sugar (options):\n *\n * - `raw` (Boolean) - say that we work with raw stream, if you don't wish to specify\n * negative windowBits implicitly.\n * - `to` (String) - if equal to 'string', then result will be converted\n * from utf8 to utf16 (javascript) string. When string output requested,\n * chunk length can differ from `chunkSize`, depending on content.\n *\n *\n * ##### Example:\n *\n * ```javascript\n * const pako = require('pako');\n * const input = pako.deflate(new Uint8Array([1,2,3,4,5,6,7,8,9]));\n * let output;\n *\n * try {\n * output = pako.inflate(input);\n * } catch (err) {\n * console.log(err);\n * }\n * ```\n **/\nfunction inflate$1(input, options) {\n const inflator = new Inflate$1(options);\n\n inflator.push(input);\n\n // That will never happens, if you don't cheat with options :)\n if (inflator.err) throw inflator.msg || messages[inflator.err];\n\n return inflator.result;\n}\n\n\n/**\n * inflateRaw(data[, options]) -> Uint8Array|String\n * - data (Uint8Array|ArrayBuffer): input data to decompress.\n * - options (Object): zlib inflate options.\n *\n * The same as [[inflate]], but creates raw data, without wrapper\n * (header and adler32 crc).\n **/\nfunction inflateRaw$1(input, options) {\n options = options || {};\n options.raw = true;\n return inflate$1(input, options);\n}\n\n\n/**\n * ungzip(data[, options]) -> Uint8Array|String\n * - data (Uint8Array|ArrayBuffer): input data to decompress.\n * - options (Object): zlib inflate options.\n *\n * Just shortcut to [[inflate]], because it autodetects format\n * by header.content. Done for convenience.\n **/\n\n\nvar Inflate_1$1 = Inflate$1;\nvar inflate_2 = inflate$1;\nvar inflateRaw_1$1 = inflateRaw$1;\nvar ungzip$1 = inflate$1;\nvar constants = constants$2;\n\nvar inflate_1$1 = {\n\tInflate: Inflate_1$1,\n\tinflate: inflate_2,\n\tinflateRaw: inflateRaw_1$1,\n\tungzip: ungzip$1,\n\tconstants: constants\n};\n\nconst { Deflate, deflate, deflateRaw, gzip } = deflate_1$1;\n\nconst { Inflate, inflate, inflateRaw, ungzip } = inflate_1$1;\n\n\n\nvar Deflate_1 = Deflate;\nvar deflate_1 = deflate;\nvar deflateRaw_1 = deflateRaw;\nvar gzip_1 = gzip;\nvar Inflate_1 = Inflate;\nvar inflate_1 = inflate;\nvar inflateRaw_1 = inflateRaw;\nvar ungzip_1 = ungzip;\nvar constants_1 = constants$2;\n\nvar pako = {\n\tDeflate: Deflate_1,\n\tdeflate: deflate_1,\n\tdeflateRaw: deflateRaw_1,\n\tgzip: gzip_1,\n\tInflate: Inflate_1,\n\tinflate: inflate_1,\n\tinflateRaw: inflateRaw_1,\n\tungzip: ungzip_1,\n\tconstants: constants_1\n};\n\nexport { Deflate_1 as Deflate, Inflate_1 as Inflate, constants_1 as constants, pako as default, deflate_1 as deflate, deflateRaw_1 as deflateRaw, gzip_1 as gzip, inflate_1 as inflate, inflateRaw_1 as inflateRaw, ungzip_1 as ungzip };\n", "/**\n * COSE-based QR Code Compression and Encryption\n * Implements secure payload packing with CBOR, compression, and chunking\n */\n\nimport * as cbor from 'cbor-js';\nimport * as pako from 'pako';\nimport * as base64 from 'base64-js';\n\n// Base64URL encoding/decoding helpers\nfunction toBase64Url(uint8) {\n let b64 = base64.fromByteArray(uint8);\n return b64.replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=+$/, '');\n}\n\nfunction fromBase64Url(str) {\n str = str.replace(/-/g, '+').replace(/_/g, '/');\n while (str.length % 4) str += '=';\n return base64.toByteArray(str);\n}\n\n// Generate UUID for chunking\nfunction generateUUID() {\n return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, c => {\n const r = Math.random() * 16 | 0;\n const v = c === 'x' ? r : (r & 0x3 | 0x8);\n return v.toString(16);\n });\n}\n\n/**\n * Pack secure payload using COSE-like structure with compression\n * @param {Object} payloadObj - The data to pack\n * @param {CryptoKey} senderEcdsaPrivKey - Sender's signing key (optional)\n * @param {CryptoKey} recipientEcdhPubKey - Recipient's ECDH key (optional, null for broadcast)\n * @returns {Array} Array of QR code strings (chunks)\n */\nexport async function packSecurePayload(payloadObj, senderEcdsaPrivKey = null, recipientEcdhPubKey = null) {\n try {\n console.log('\uD83D\uDD10 Starting COSE packing...');\n \n // 1. Canonicalize payload (minified JSON)\n const payloadJson = JSON.stringify(payloadObj);\n console.log(`\uD83D\uDCCA Original payload size: ${payloadJson.length} characters`);\n \n // 2. Create ephemeral ECDH keypair (P-384) for encryption\n let ciphertextCose;\n let ephemeralRaw = null;\n \n if (recipientEcdhPubKey) {\n console.log('\uD83D\uDD10 Encrypting for specific recipient...');\n \n // Generate ephemeral ECDH keypair\n const ecdhPair = await crypto.subtle.generateKey(\n { name: \"ECDH\", namedCurve: \"P-384\" },\n true,\n [\"deriveKey\", \"deriveBits\"]\n );\n \n // Export ephemeral public key as raw bytes\n ephemeralRaw = new Uint8Array(await crypto.subtle.exportKey('raw', ecdhPair.publicKey));\n \n // Derive shared secret\n const sharedBits = await crypto.subtle.deriveBits(\n { name: \"ECDH\", public: recipientEcdhPubKey },\n ecdhPair.privateKey,\n 384\n );\n \n // HKDF-SHA384: derive AES-256-GCM key\n const hkdfKey = await crypto.subtle.importKey('raw', sharedBits, 'HKDF', false, ['deriveKey']);\n const cek = await crypto.subtle.deriveKey(\n {\n name: 'HKDF',\n hash: 'SHA-384',\n salt: new Uint8Array(0),\n info: new TextEncoder().encode('SecureBit QR ECDH AES key')\n },\n hkdfKey,\n { name: 'AES-GCM', length: 256 },\n true,\n ['encrypt', 'decrypt']\n );\n \n // AES-GCM encrypt payload\n const iv = crypto.getRandomValues(new Uint8Array(12));\n const enc = await crypto.subtle.encrypt(\n { name: 'AES-GCM', iv },\n cek,\n new TextEncoder().encode(payloadJson)\n );\n \n // Build COSE_Encrypt-like structure\n ciphertextCose = {\n protected: { alg: 'A256GCM' },\n unprotected: { epk: ephemeralRaw },\n ciphertext: new Uint8Array(enc),\n iv: iv\n };\n } else {\n console.log('\uD83D\uDD10 Using broadcast mode (no encryption)...');\n // Broadcast mode: not encrypted, include ephemeral key for future use\n ephemeralRaw = crypto.getRandomValues(new Uint8Array(97)); // P-384 uncompressed point size\n ciphertextCose = {\n plaintext: new TextEncoder().encode(payloadJson),\n epk: ephemeralRaw\n };\n }\n \n // 3. Wrap in COSE_Sign1 structure (sign if key provided)\n let coseSign1;\n const toSign = cbor.encode(ciphertextCose);\n \n if (senderEcdsaPrivKey) {\n console.log('\uD83D\uDD10 Signing payload...');\n // Sign using ECDSA P-384 SHA-384\n const signature = new Uint8Array(await crypto.subtle.sign(\n { name: 'ECDSA', hash: 'SHA-384' },\n senderEcdsaPrivKey,\n toSign\n ));\n \n // COSE_Sign1 as array: [protected, unprotected, payload, signature]\n const protectedHeader = cbor.encode({ alg: 'ES384' });\n const unprotectedHeader = { kid: 'securebit-sender' };\n coseSign1 = [protectedHeader, unprotectedHeader, toSign, signature];\n } else {\n console.log('\uD83D\uDD10 No signing key provided, using unsigned structure...');\n // COSE_Sign1 as array: [protected, unprotected, payload, signature]\n const protectedHeader = cbor.encode({ alg: 'none' });\n const unprotectedHeader = {};\n coseSign1 = [protectedHeader, unprotectedHeader, toSign, new Uint8Array(0)];\n }\n \n // 4. Final encode: CBOR -> deflate -> base64url\n const cborFinal = cbor.encode(coseSign1);\n const compressed = pako.deflate(cborFinal);\n const encoded = toBase64Url(compressed);\n \n console.log(`\uD83D\uDCCA Compressed size: ${encoded.length} characters (${Math.round((1 - encoded.length/payloadJson.length) * 100)}% reduction)`);\n \n // 5. Chunking for QR codes - \u0443\u043B\u0443\u0447\u0448\u0435\u043D\u043D\u043E\u0435 \u0440\u0430\u0437\u0431\u0438\u0435\u043D\u0438\u0435 \u0434\u043B\u044F \u043B\u0443\u0447\u0448\u0435\u0433\u043E \u0441\u043A\u0430\u043D\u0438\u0440\u043E\u0432\u0430\u043D\u0438\u044F\n const TARGET_CHUNKS = 10; // \u0426\u0435\u043B\u0435\u0432\u043E\u0435 \u043A\u043E\u043B\u0438\u0447\u0435\u0441\u0442\u0432\u043E \u0447\u0430\u0441\u0442\u0435\u0439\n const QR_MAX = Math.max(200, Math.floor(encoded.length / TARGET_CHUNKS)); // \u0414\u0438\u043D\u0430\u043C\u0438\u0447\u0435\u0441\u043A\u0438\u0439 \u0440\u0430\u0437\u043C\u0435\u0440 \u0447\u0430\u0441\u0442\u0438\n const chunks = [];\n \n if (encoded.length <= QR_MAX) {\n // Single chunk\n chunks.push(JSON.stringify({\n hdr: { v: 1, id: generateUUID(), seq: 1, total: 1 },\n body: encoded\n }));\n } else {\n // Multiple chunks - \u0440\u0430\u0437\u0431\u0438\u0432\u0430\u0435\u043C \u043D\u0430 \u0431\u043E\u043B\u044C\u0448\u0435 \u0447\u0430\u0441\u0442\u0435\u0439 \u0434\u043B\u044F \u043B\u0443\u0447\u0448\u0435\u0433\u043E \u0441\u043A\u0430\u043D\u0438\u0440\u043E\u0432\u0430\u043D\u0438\u044F\n const id = generateUUID();\n const totalChunks = Math.ceil(encoded.length / QR_MAX);\n \n console.log(`\uD83D\uDCCA COSE: Splitting ${encoded.length} chars into ${totalChunks} chunks (max ${QR_MAX} chars per chunk)`);\n \n for (let i = 0, seq = 1; i < encoded.length; i += QR_MAX, seq++) {\n const part = encoded.slice(i, i + QR_MAX);\n chunks.push(JSON.stringify({\n hdr: { v: 1, id, seq, total: totalChunks },\n body: part\n }));\n }\n }\n \n console.log(`\uD83D\uDCCA Generated ${chunks.length} QR chunk(s)`);\n return chunks;\n \n } catch (error) {\n console.error('\u274C Error in packSecurePayload:', error);\n throw error;\n }\n}\n\n/**\n * Receive and process COSE-packed QR data\n * @param {Array} qrStrings - Array of QR code strings\n * @param {CryptoKey} recipientEcdhPrivKey - Recipient's ECDH private key (optional)\n * @param {CryptoKey} trustedSenderPubKey - Trusted sender's public key (optional)\n * @returns {Array} Array of processed payloads\n */\nexport async function receiveAndProcess(qrStrings, recipientEcdhPrivKey = null, trustedSenderPubKey = null) {\n try {\n console.log('\uD83D\uDD13 Starting COSE processing...');\n \n // 1. Assemble chunks by ID\n console.log(`\uD83D\uDCCA Processing ${qrStrings.length} QR string(s)`);\n const assembled = await assembleFromQrStrings(qrStrings);\n if (!assembled.length) {\n console.error('\u274C No complete packets found after assembly');\n throw new Error('No complete packets found');\n }\n \n console.log(`\uD83D\uDCCA Assembled ${assembled.length} complete packet(s)`);\n console.log('\uD83D\uDCCA First assembled packet:', assembled[0]);\n \n const results = [];\n \n for (const pack of assembled) {\n try {\n const encoded = pack.jsonObj;\n \n // 2. Decode: base64url -> decompress -> CBOR decode\n const compressed = fromBase64Url(encoded.body || encoded);\n const cborBytes = pako.inflate(compressed);\n console.log('\uD83D\uDD13 Decompressed CBOR bytes length:', cborBytes.length);\n console.log('\uD83D\uDD13 CBOR bytes type:', typeof cborBytes, cborBytes.constructor.name);\n \n // Convert Uint8Array to ArrayBuffer for cbor-js\n const cborArrayBuffer = cborBytes.buffer.slice(cborBytes.byteOffset, cborBytes.byteOffset + cborBytes.byteLength);\n console.log('\uD83D\uDD13 Converted to ArrayBuffer, length:', cborArrayBuffer.byteLength);\n \n const coseSign1 = cbor.decode(cborArrayBuffer);\n \n console.log('\uD83D\uDD13 Decoded COSE structure');\n \n // Handle both array and object formats\n let protectedHeader, unprotectedHeader, payload, signature;\n if (Array.isArray(coseSign1)) {\n // Array format: [protected, unprotected, payload, signature]\n [protectedHeader, unprotectedHeader, payload, signature] = coseSign1;\n console.log('\uD83D\uDD13 COSE structure is array format');\n } else {\n // Object format (legacy)\n protectedHeader = coseSign1.protected;\n unprotectedHeader = coseSign1.unprotected;\n payload = coseSign1.payload;\n signature = coseSign1.signature;\n console.log('\uD83D\uDD13 COSE structure is object format (legacy)');\n }\n \n // 3. Verify signature (if key provided)\n if (trustedSenderPubKey && signature && signature.length > 0) {\n const toVerify = cbor.encode([protectedHeader, unprotectedHeader, payload]);\n const isValid = await crypto.subtle.verify(\n { name: 'ECDSA', hash: 'SHA-384' },\n trustedSenderPubKey,\n signature,\n toVerify\n );\n \n if (!isValid) {\n console.warn('\u26A0\uFE0F Signature verification failed');\n continue;\n }\n console.log('\u2705 Signature verified');\n }\n \n // 4. Decrypt payload\n let inner;\n if (payload instanceof Uint8Array) {\n // Payload is still encoded\n const innerArrayBuffer = payload.buffer.slice(payload.byteOffset, payload.byteOffset + payload.byteLength);\n inner = cbor.decode(innerArrayBuffer);\n } else {\n // Payload is already decoded\n inner = payload;\n }\n console.log('\uD83D\uDD13 Inner payload type:', typeof inner, inner.constructor.name);\n console.log('\uD83D\uDD13 Inner payload keys:', Object.keys(inner));\n console.log('\uD83D\uDD13 Inner payload full object:', inner);\n \n let payloadObj;\n \n if (inner.ciphertext && recipientEcdhPrivKey) {\n console.log('\uD83D\uDD13 Decrypting encrypted payload...');\n \n // Get ephemeral public key\n const epkRaw = inner.unprotected?.epk || inner.epk;\n \n // Import ephemeral public key\n const ephemeralPub = await crypto.subtle.importKey(\n 'raw',\n epkRaw,\n { name: 'ECDH', namedCurve: 'P-384' },\n true,\n []\n );\n \n // Derive shared secret\n const sharedBits = await crypto.subtle.deriveBits(\n { name: 'ECDH', public: ephemeralPub },\n recipientEcdhPrivKey,\n 384\n );\n \n // HKDF-SHA384 -> AES key\n const hkdfKey = await crypto.subtle.importKey('raw', sharedBits, 'HKDF', false, ['deriveKey']);\n const cek = await crypto.subtle.deriveKey(\n {\n name: 'HKDF',\n hash: 'SHA-384',\n salt: new Uint8Array(0),\n info: new TextEncoder().encode('SecureBit QR ECDH AES key')\n },\n hkdfKey,\n { name: 'AES-GCM', length: 256 },\n true,\n ['decrypt']\n );\n \n // Decrypt\n const plaintext = await crypto.subtle.decrypt(\n { name: 'AES-GCM', iv: inner.iv },\n cek,\n inner.ciphertext\n );\n \n const payloadJson = new TextDecoder().decode(plaintext);\n payloadObj = JSON.parse(payloadJson);\n \n } else if (inner.plaintext) {\n console.log('\uD83D\uDD13 Processing plaintext payload...');\n // Broadcast mode\n payloadObj = JSON.parse(new TextDecoder().decode(inner.plaintext));\n } else if (Object.keys(inner).length === 0) {\n console.log('\uD83D\uDD13 Empty inner payload, using alternative approach...');\n \n // Alternative: try to use the original assembled body\n try {\n const originalBody = encoded.body || encoded;\n console.log('\uD83D\uDD13 Trying to decode original body:', originalBody.substring(0, 50) + '...');\n \n // Decode base64url -> decompress -> CBOR decode -> extract JSON\n const compressed = fromBase64Url(originalBody);\n const decompressed = pako.inflate(compressed);\n console.log('\uD83D\uDD13 Decompressed length:', decompressed.length);\n \n // Convert to ArrayBuffer for CBOR decoding\n const decompressedArrayBuffer = decompressed.buffer.slice(decompressed.byteOffset, decompressed.byteOffset + decompressed.byteLength);\n const cborDecoded = cbor.decode(decompressedArrayBuffer);\n console.log('\uD83D\uDD13 CBOR decoded structure:', cborDecoded);\n \n // Handle both array and object formats\n let payload;\n if (Array.isArray(cborDecoded)) {\n // Array format: [protected, unprotected, payload, signature]\n console.log('\uD83D\uDD13 Alternative: COSE structure is array format');\n console.log('\uD83D\uDD13 Array length:', cborDecoded.length);\n console.log('\uD83D\uDD13 Array elements:', cborDecoded.map((el, i) => `${i}: ${typeof el} ${el.constructor.name}`));\n \n // Payload is at index 2\n payload = cborDecoded[2];\n console.log('\uD83D\uDD13 Payload at index 2:', payload);\n } else {\n // Object format (legacy)\n payload = cborDecoded.payload;\n console.log('\uD83D\uDD13 Alternative: COSE structure is object format (legacy)');\n }\n \n // Extract the actual payload from CBOR structure\n if (payload && payload instanceof Uint8Array) {\n const payloadArrayBuffer = payload.buffer.slice(payload.byteOffset, payload.byteOffset + payload.byteLength);\n const innerCbor = cbor.decode(payloadArrayBuffer);\n console.log('\uD83D\uDD13 Inner CBOR structure:', innerCbor);\n \n if (innerCbor.plaintext) {\n const jsonString = new TextDecoder().decode(innerCbor.plaintext);\n payloadObj = JSON.parse(jsonString);\n console.log('\uD83D\uDD13 Successfully decoded via alternative approach');\n console.log('\uD83D\uDD13 Alternative payloadObj:', payloadObj);\n } else {\n console.error('\u274C No plaintext found in inner CBOR structure');\n continue;\n }\n } else if (payload && typeof payload === 'object' && Object.keys(payload).length > 0) {\n // Payload is already a decoded object\n console.log('\uD83D\uDD13 Payload is already decoded object:', payload);\n if (payload.plaintext) {\n const jsonString = new TextDecoder().decode(payload.plaintext);\n payloadObj = JSON.parse(jsonString);\n console.log('\uD83D\uDD13 Successfully decoded from payload object');\n console.log('\uD83D\uDD13 Alternative payloadObj:', payloadObj);\n } else {\n console.error('\u274C No plaintext found in payload object');\n continue;\n }\n } else {\n console.error('\u274C No payload found in CBOR structure');\n console.log('\uD83D\uDD13 CBOR structure keys:', Object.keys(cborDecoded));\n console.log('\uD83D\uDD13 Payload type:', typeof payload);\n console.log('\uD83D\uDD13 Payload value:', payload);\n continue;\n }\n } catch (altError) {\n console.error('\u274C Alternative approach failed:', altError);\n continue;\n }\n } else {\n console.warn('\u26A0\uFE0F Unknown payload format:', inner);\n continue;\n }\n \n results.push({\n payloadObj,\n senderVerified: !!trustedSenderPubKey,\n encrypted: !!inner.ciphertext\n });\n \n } catch (packError) {\n console.error('\u274C Error processing packet:', packError);\n continue;\n }\n }\n \n console.log(`\u2705 Successfully processed ${results.length} payload(s)`);\n return results;\n \n } catch (error) {\n console.error('\u274C Error in receiveAndProcess:', error);\n throw error;\n }\n}\n\n/**\n * Assemble QR chunks into complete packets\n * @param {Array} qrStrings - Array of QR code strings\n * @returns {Array} Array of assembled packets\n */\nasync function assembleFromQrStrings(qrStrings) {\n const packets = new Map();\n \n console.log('\uD83D\uDD27 Starting assembly of QR strings...');\n \n for (const qrString of qrStrings) {\n try {\n console.log('\uD83D\uDD27 Parsing QR string:', qrString.substring(0, 100) + '...');\n const parsed = JSON.parse(qrString);\n console.log('\uD83D\uDD27 Parsed structure:', parsed);\n \n if (parsed.hdr && parsed.body) {\n const id = parsed.hdr.id;\n console.log(`\uD83D\uDD27 Processing packet ID: ${id}, seq: ${parsed.hdr.seq}, total: ${parsed.hdr.total}`);\n \n if (!packets.has(id)) {\n packets.set(id, {\n id: id,\n chunks: new Map(),\n total: parsed.hdr.total\n });\n console.log(`\uD83D\uDD27 Created new packet for ID: ${id}`);\n }\n \n const packet = packets.get(id);\n packet.chunks.set(parsed.hdr.seq, parsed.body);\n console.log(`\uD83D\uDD27 Added chunk ${parsed.hdr.seq} to packet ${id}. Current chunks: ${packet.chunks.size}/${packet.total}`);\n \n // Check if complete\n if (packet.chunks.size === packet.total) {\n console.log(`\uD83D\uDD27 Packet ${id} is complete! Assembling body...`);\n // Assemble body\n let assembledBody = '';\n for (let i = 1; i <= packet.total; i++) {\n assembledBody += packet.chunks.get(i);\n }\n \n packet.jsonObj = { body: assembledBody };\n packet.complete = true;\n console.log(`\uD83D\uDD27 Assembled body length: ${assembledBody.length} characters`);\n }\n } else {\n console.warn('\u26A0\uFE0F QR string missing hdr or body:', parsed);\n }\n } catch (error) {\n console.warn('\u26A0\uFE0F Failed to parse QR string:', error);\n continue;\n }\n }\n \n // Return only complete packets\n const completePackets = Array.from(packets.values()).filter(p => p.complete);\n console.log(`\uD83D\uDD27 Assembly complete. Found ${completePackets.length} complete packets`);\n return completePackets;\n}\n\n// Export for global use\nwindow.packSecurePayload = packSecurePayload;\nwindow.receiveAndProcess = receiveAndProcess;\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,MACj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GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC;AAAA,QAClC,WAAW,KAAK,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC;AAAA,QAClC,WAAW,KAAK,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC;AAAA,QAClC,WAAW,KAAK,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC;AAAA,QAClC,WAAW,KAAK,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC;AAAA,QAClC,WAAW,KAAK,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC;AAAA,QAClC,WAAW,KAAK,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC;AAAA,QAClC,WAAW,KAAK,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC;AAAA,QAClC,WAAW,KAAK,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC;AAAA,QAClC,WAAW,KAAK,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC;AAAA,QAClC,WAAW,KAAK,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC;AAAA,QAClC,WAAW,KAAK,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC;AAAA,QAClC,WAAW,KAAK,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC;AAAA,QAClC,WAAW,KAAK,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC;AAAA,QAClC,WAAW,KAAK,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC;AAAA,QAClC,WAAW,KAAK,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC;AAAA,QAClC,WAAW,KAAK,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC;AAAA,QAClC,WAAW,KAAK,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC;AAAA,QAClC,WAAW,KAAK,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC;AAAA,QAClC,WAAW,KAAK,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC;AAAA,QAClC,WAAW,KAAK,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC;AAAA,QAClC,WAAW,KAAK,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC;AAAA,QAClC,WAAW,KAAK,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC;AAAA,QAClC,WAAW,KAAK,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC;AAAA,QAClC,WAAW,KAAK,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC;AAAA,QAClC,WAAW,KAAK,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC;AAAA,QAClC,WAAW,KAAK,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC;AAAA,QAClC,WAAW,KAAK,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC;AAAA,QAClC,WAAW,KAAK,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC;AAAA,QAClC,WAAW,KAAK,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC;AAAA,QAClC,WAAW,KAAK,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC;AAAA,QAClC,WAAW,KAAK,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC;AAAA,QAClC,WAAW,KAAK,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC;AAAA,QAClC,WAAW,KAAK,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC;AAAA,QAClC,WAAW,KAAK,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC;AAAA,QAClC,WAAW,KAAK,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC;AAAA,QAClC,WAAW,KAAK,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC;AAAA,QAClC,WAAW,KAAK,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC;AAAA,QAClC,WAAW,KAAK,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC;AAAA,QAClC,WAAW,KAAK,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC;AAAA,QAClC,WAAW,KAAK,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC;AAAA,QAClC,WAAW,KAAK,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC;AAAA,QAClC,WAAW,KAAK,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC;AAAA,QAClC,WAAW,KAAK,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC;AAAA,QAClC,WAAW,KAAK,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC;AAAA,QAClC,WAAW,KAAK,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC;AAAA,QAClC,WAAW,KAAK,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC;AAAA,QAClC,WAAW,KAAK,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC;AAAA,QAClC,WAAW,KAAK,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC;AAAA,QAClC,WAAW,KAAK,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC;AAAA,QAClC,WAAW,KAAK,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC;AAAA,QAClC,WAAW,KAAK,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC;AAAA,QAClC,WAAW,KAAK,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC;AAAA,QAClC,WAAW,KAAK,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC;AAAA,QAClC,WAAW,KAAK,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC;AAAA,QAClC,WAAW,KAAK,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC;AAAA,QAClC,WAAW,KAAK,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC;AAAA,QAClC,WAAW,KAAK,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC;AAAA,QAClC,WAAW,KAAK,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC;AAAA,QAClC,WAAW,KAAK,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC;AAAA,QAClC,WAAW,KAAK,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC;AAAA,QAClC,WAAW,KAAK,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC;AAAA,QAClC,WAAW,KAAK,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC;AAAA,QAClC,WAAW,KAAK,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC;AAAA,QAClC,WAAW,KAAK,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC;AAAA,QAClC,WAAW,KAAK,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC;AAAA,QAClC,WAAW,KAAK,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC;AAAA,QAClC,WAAW,KAAK,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC;AAAA,QAClC,WAAW,KAAK,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC;AAAA,QAClC,WAAW,KAAK,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC;AAAA,QAClC,WAAW,KAAK,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC;AAAA,QAClC,WAAW,KAAK,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC;AAAA,QAClC,WAAW,KAAK,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC;AAAA,QAClC,WAAW,KAAK,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC;AAAA,QAClC,WAAW,KAAK,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC;AAAA,QAClC,WAAW,KAAK,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC;AAAA,QAClC,WAAW,KAAK,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC;AAAA,QAClC,WAAW,KAAK,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC;AAAA,QAClC,WAAW,KAAK,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC;AAAA,QAClC,WAAW,KAAK,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC;AAAA,QAClC,WAAW,KAAK,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC;AAAA,QAClC,WAAW,KAAK,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC;AAAA,QAClC,WAAW,KAAK,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC;AAAA,QAClC,WAAW,KAAK,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC;AAAA,QAClC,WAAW,KAAK,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC;AAAA,QAClC,WAAW,KAAK,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC;AAAA,QAClC,WAAW,KAAK,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC;AAAA,QAClC,WAAW,KAAK,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC;AAAA,QAClC,WAAW,KAAK,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC;AAAA,QAClC,WAAW,KAAK,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC;AAAA,QAClC,WAAW,KAAK,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC;AAAA,MACzC;AACA,oBAAc,mBAAmB;AACjC,oBAAc,0BAA0B;AACxC,oBAAc,aAAa;AAC3B,oBAAc,cAAc;AAC5B,oBAAc,cAAc;AAC5B,oBAAc,cAAc;AAC5B,oBAAc,aAAa;AAC3B,oBAAc,aAAa;AAC3B,oBAAc,aAAa;AAC3B,oBAAc,eAAe;AAC7B,oBAAc,eAAe;AAC7B,oBAAc,eAAe;AAC7B,oBAAc,eAAe;AAC7B,oBAAc,eAAe;AAC7B,oBAAc,YAAY;AAAA,MAQ1B,MAAM,qBAAqB,WAAW;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QA4BlC,YAAY,kBAAkB,OAAO,eAAe,OAAO;AACvD,gBAAM;AACN,eAAK,kBAAkB;AACvB,eAAK,eAAe;AACpB,eAAK,kBAAkB;AACvB,eAAK,WAAW,IAAI,WAAW,CAAC;AAAA,QACpC;AAAA,QACA,UAAU,WAAW,KAAK,OAAO;AAC7B,cAAI,cAAc,KAAK;AACvB,sBAAY,KAAK,CAAC;AAClB,eAAK,kBAAkB;AACvB,cAAI,QAAQ,aAAa,oBAAoB,KAAK,WAAW;AAE7D,cAAI,YAAY,IAAI,WAAW,MAAM,CAAC,CAAC;AACvC,cAAI,MAAM,IAAI,QAAQ;AACtB,cAAI;AACJ,cAAI;AACJ,aAAG;AACC,yBAAa,cAAc,KAAK,WAAW,WAAW;AACtD,gBAAI,UAAU,aAAa,oBAAoB,WAAW;AAC1D,gBAAI,UAAU,GAAG;AACb,oBAAM,IAAI,kBAAkB;AAAA,YAChC;AACA,0BAAc,aAAa,cAAc,OAAO;AAChD,iBAAK,mBAAmB;AACxB,wBAAY;AACZ,qBAAS,WAAW,aAAa;AAC7B,2BAAa;AAAA,YACjB;AAEA,wBAAY,IAAI,WAAW,SAAS;AAAA,UACxC,SAAS,gBAAgB;AACzB,eAAK,kBAAkB,KAAK,gBAAgB,UAAU,GAAG,KAAK,gBAAgB,SAAS,CAAC;AAExF,cAAI,kBAAkB;AACtB,mBAAS,WAAW,aAAa;AAC7B,+BAAmB;AAAA,UACvB;AACA,cAAI,qBAAqB,YAAY,YAAY;AAGjD,cAAI,cAAc,OAAQ,qBAAqB,IAAK,iBAAiB;AACjE,kBAAM,IAAI,kBAAkB;AAAA,UAChC;AACA,cAAI,KAAK,iBAAiB;AACtB,gBAAI,MAAM,KAAK,gBAAgB,SAAS;AACxC,gBAAI,QAAQ;AACZ,qBAAS,IAAI,GAAG,IAAI,KAAK,KAAK;AAC1B,uBAAS,aAAa,gBAAgB,QAAQ,KAAK,gBAAgB,OAAO,CAAC,CAAC;AAAA,YAChF;AACA,gBAAI,KAAK,gBAAgB,OAAO,GAAG,MAAM,aAAa,gBAAgB,OAAO,QAAQ,EAAE,GAAG;AACtF,oBAAM,IAAI,kBAAkB;AAAA,YAChC;AACA,iBAAK,kBAAkB,KAAK,gBAAgB,UAAU,GAAG,GAAG;AAAA,UAChE;AACA,cAAI,KAAK,gBAAgB,WAAW,GAAG;AAEnC,kBAAM,IAAI,kBAAkB;AAAA,UAChC;AACA,cAAI;AACJ,cAAI,KAAK,cAAc;AACnB,2BAAe,aAAa,eAAe,KAAK,eAAe;AAAA,UACnE,OACK;AACD,2BAAe,KAAK;AAAA,UACxB;AACA,cAAI,QAAQ,MAAM,CAAC,IAAI,MAAM,CAAC,KAAK;AACnC,cAAI,QAAQ,YAAY,kBAAkB;AAC1C,iBAAO,IAAI,OAAO,cAAc,MAAM,GAAG,CAAC,IAAI,YAAY,MAAM,SAAS,GAAG,IAAI,YAAY,OAAO,SAAS,CAAC,GAAG,gBAAgB,UAAS,oBAAI,KAAK,GAAE,QAAQ,CAAC;AAAA,QACjK;AAAA,QACA,OAAO,oBAAoB,KAAK,UAAU;AACtC,cAAI,QAAQ,IAAI,QAAQ;AACxB,cAAI,YAAY,IAAI,WAAW,CAAC;AAChC,cAAI,kBAAkB;AACtB,cAAI,eAAe;AACnB,cAAI,UAAU;AACd,cAAI,gBAAgB,SAAS;AAC7B,mBAAS,IAAI,WAAW,IAAI,OAAO,KAAK;AACpC,gBAAI,IAAI,IAAI,CAAC,MAAM,SAAS;AACxB,uBAAS,eAAe;AAAA,YAC5B,OACK;AACD,kBAAI,oBAAoB,gBAAgB,GAAG;AAEvC,oBAAI,KAAK,oBAAoB,QAAQ,MAAM,aAAa,qBACpD,IAAI,QAAQ,KAAK,IAAI,GAAG,eAAe,KAAK,OAAO,IAAI,gBAAgB,CAAC,CAAC,GAAG,cAAc,KAAK,GAAG;AAClG,yBAAO,CAAC,cAAc,CAAC;AAAA,gBAC3B;AACA,gCAAgB,SAAS,CAAC,IAAI,SAAS,CAAC;AACxC,yBAAS,WAAW,GAAG,GAAG,IAAI,kBAAkB,CAAC;AACjD,yBAAS,kBAAkB,CAAC,IAAI;AAChC,yBAAS,eAAe,IAAI;AAC5B;AAAA,cACJ,OACK;AACD;AAAA,cACJ;AACA,uBAAS,eAAe,IAAI;AAC5B,wBAAU,CAAC;AAAA,YACf;AAAA,UACJ;AACA,gBAAM,IAAI,kBAAkB;AAAA,QAChC;AAAA;AAAA;AAAA,QAGA,OAAO,oBAAoB,UAAU;AACjC,cAAI,cAAc,SAAS;AAC3B,cAAI,mBAAmB;AACvB,cAAI;AACJ,aAAG;AACC,gBAAI,aAAa;AACjB,qBAAS,WAAW,UAAU;AAC1B,kBAAI,UAAU,cAAc,UAAU,kBAAkB;AACpD,6BAAa;AAAA,cACjB;AAAA,YACJ;AACA,+BAAmB;AACnB,2BAAe;AACf,gBAAI,yBAAyB;AAC7B,gBAAI,UAAU;AACd,qBAAS,IAAI,GAAG,IAAI,aAAa,KAAK;AAClC,kBAAI,UAAU,SAAS,CAAC;AACxB,kBAAI,UAAU,kBAAkB;AAC5B,2BAAW,KAAM,cAAc,IAAI;AACnC;AACA,0CAA0B;AAAA,cAC9B;AAAA,YACJ;AACA,gBAAI,iBAAiB,GAAG;AAIpB,uBAAS,IAAI,GAAG,IAAI,eAAe,eAAe,GAAG,KAAK;AACtD,oBAAI,UAAU,SAAS,CAAC;AACxB,oBAAI,UAAU,kBAAkB;AAC5B;AAEA,sBAAK,UAAU,KAAM,wBAAwB;AACzC,2BAAO;AAAA,kBACX;AAAA,gBACJ;AAAA,cACJ;AACA,qBAAO;AAAA,YACX;AAAA,UACJ,SAAS,eAAe;AACxB,iBAAO;AAAA,QACX;AAAA,QACA,OAAO,cAAc,SAAS;AAC1B,mBAAS,IAAI,GAAG,IAAI,aAAa,oBAAoB,QAAQ,KAAK;AAC9D,gBAAI,aAAa,oBAAoB,CAAC,MAAM,SAAS;AACjD,qBAAO,aAAa,gBAAgB,OAAO,CAAC;AAAA,YAChD;AAAA,UACJ;AACA,cAAI,YAAY,aAAa,mBAAmB;AAC5C,mBAAO;AAAA,UACX;AACA,gBAAM,IAAI,kBAAkB;AAAA,QAChC;AAAA,QACA,OAAO,eAAe,SAAS;AAC3B,cAAI,SAAS,QAAQ;AACrB,cAAI,UAAU;AACd,mBAAS,IAAI,GAAG,IAAI,QAAQ,KAAK;AAC7B,gBAAI,IAAI,QAAQ,OAAO,CAAC;AACxB,gBAAI,MAAM,OAAO,MAAM,OAAO,MAAM,OAAO,MAAM,KAAK;AAClD,kBAAI,OAAO,QAAQ,OAAO,IAAI,CAAC;AAC/B,kBAAI,cAAc;AAClB,sBAAQ,GAAG;AAAA,gBACP,KAAK;AAED,sBAAI,QAAQ,OAAO,QAAQ,KAAK;AAC5B,kCAAc,OAAO,aAAa,KAAK,WAAW,CAAC,IAAI,EAAE;AAAA,kBAC7D,OACK;AACD,0BAAM,IAAI,gBAAgB;AAAA,kBAC9B;AACA;AAAA,gBACJ,KAAK;AAED,sBAAI,QAAQ,OAAO,QAAQ,KAAK;AAC5B,kCAAc,OAAO,aAAa,KAAK,WAAW,CAAC,IAAI,EAAE;AAAA,kBAC7D,OACK;AACD,0BAAM,IAAI,gBAAgB;AAAA,kBAC9B;AACA;AAAA,gBACJ,KAAK;AAED,sBAAI,QAAQ,OAAO,QAAQ,KAAK;AAC5B,kCAAc,OAAO,aAAa,KAAK,WAAW,CAAC,IAAI,EAAE;AAAA,kBAC7D,WACS,QAAQ,OAAO,QAAQ,KAAK;AACjC,kCAAc,OAAO,aAAa,KAAK,WAAW,CAAC,IAAI,EAAE;AAAA,kBAC7D,WACS,QAAQ,OAAO,QAAQ,KAAK;AACjC,kCAAc,OAAO,aAAa,KAAK,WAAW,CAAC,IAAI,EAAE;AAAA,kBAC7D,WACS,QAAQ,OAAO,QAAQ,KAAK;AACjC,kCAAc,OAAO,aAAa,KAAK,WAAW,CAAC,IAAI,EAAE;AAAA,kBAC7D,WACS,SAAS,KAAK;AACnB,kCAAc;AAAA,kBAClB,WACS,SAAS,KAAK;AACnB,kCAAc;AAAA,kBAClB,WACS,SAAS,KAAK;AACnB,kCAAc;AAAA,kBAClB,WACS,SAAS,OAAO,SAAS,OAAO,SAAS,KAAK;AACnD,kCAAc;AAAA,kBAClB,OACK;AACD,0BAAM,IAAI,gBAAgB;AAAA,kBAC9B;AACA;AAAA,gBACJ,KAAK;AAED,sBAAI,QAAQ,OAAO,QAAQ,KAAK;AAC5B,kCAAc,OAAO,aAAa,KAAK,WAAW,CAAC,IAAI,EAAE;AAAA,kBAC7D,WACS,SAAS,KAAK;AACnB,kCAAc;AAAA,kBAClB,OACK;AACD,0BAAM,IAAI,gBAAgB;AAAA,kBAC9B;AACA;AAAA,cACR;AACA,yBAAW;AAEX;AAAA,YACJ,OACK;AACD,yBAAW;AAAA,YACf;AAAA,UACJ;AACA,iBAAO;AAAA,QACX;AAAA,MACJ;AACA,mBAAa,kBAAkB;AAM/B,mBAAa,sBAAsB;AAAA,QAC/B;AAAA,QAAO;AAAA,QAAO;AAAA,QAAO;AAAA,QAAO;AAAA,QAAO;AAAA,QAAO;AAAA,QAAO;AAAA,QAAO;AAAA,QAAO;AAAA,QAC/D;AAAA,QAAO;AAAA,QAAO;AAAA,QAAO;AAAA,QAAO;AAAA,QAAO;AAAA,QAAO;AAAA,QAAO;AAAA,QAAO;AAAA,QAAO;AAAA,QAC/D;AAAA,QAAO;AAAA,QAAO;AAAA,QAAO;AAAA,QAAO;AAAA,QAAO;AAAA,QAAO;AAAA,QAAO;AAAA,QAAO;AAAA,QAAO;AAAA,QAC/D;AAAA,QAAO;AAAA,QAAO;AAAA,QAAO;AAAA,QAAO;AAAA,QAAO;AAAA,QAAO;AAAA,QAAO;AAAA,QAAO;AAAA,QAAO;AAAA,QAC/D;AAAA,QAAO;AAAA,QAAO;AAAA;AAAA,MAClB;AACA,mBAAa,oBAAoB;AAAA,MAOjC,MAAM,kBAAkB,WAAW;AAAA,QAC/B,cAAc;AAIV,gBAAM,GAAG,SAAS;AAElB,eAAK,kBAAkB;AAAA,QAC3B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAQA,UAAU,WAAW,KAAK,OAAO;AAE7B,cAAI,aAAa,KAAK,YAAY,GAAG;AACrC,cAAI,WAAW,KAAK,UAAU,GAAG;AACjC,cAAI,SAAS,IAAI,cAAc;AAC/B,oBAAU,aAAa,KAAK,WAAW,CAAC,GAAG,SAAS,CAAC,GAAG,MAAM;AAC9D,cAAI,eAAe,OAAO,SAAS;AACnC,cAAI,iBAAiB;AACrB,cAAI,SAAS,MAAM;AACf,6BAAiB,MAAM,IAAI,iBAAiB,eAAe;AAAA,UAC/D;AACA,cAAI,kBAAkB,MAAM;AACxB,6BAAiB,UAAU;AAAA,UAC/B;AAGA,cAAI,SAAS,aAAa;AAC1B,cAAI,WAAW;AACf,cAAI,mBAAmB;AACvB,mBAAS,SAAS,gBAAgB;AAC9B,gBAAI,WAAW,OAAO;AAClB,yBAAW;AACX;AAAA,YACJ;AACA,gBAAI,QAAQ,kBAAkB;AAC1B,iCAAmB;AAAA,YACvB;AAAA,UACJ;AACA,cAAI,CAAC,YAAY,SAAS,kBAAkB;AACxC,uBAAW;AAAA,UACf;AACA,cAAI,CAAC,UAAU;AACX,kBAAM,IAAI,gBAAgB;AAAA,UAC9B;AACA,gBAAM,SAAS,CAAC,IAAI,YAAY,WAAW,CAAC,GAAG,SAAS,GAAG,IAAI,YAAY,SAAS,CAAC,GAAG,SAAS,CAAC;AAClG,cAAI,eAAe,IAAI;AAAA,YAAO;AAAA,YAAc;AAAA;AAAA,YAC5C;AAAA,YAAG;AAAA,YAAQ,gBAAgB;AAAA,aAAK,oBAAI,KAAK,GAAE,QAAQ;AAAA,UAAC;AACpD,iBAAO;AAAA,QACX;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAQA,OAAO,aAAa,KAAK,cAAc,YAAY,cAAc;AAM7D,cAAI,mBAAmB,IAAI,WAAW,EAAE;AACxC,cAAI,eAAe,IAAI,WAAW,CAAC;AACnC,cAAI,eAAe,IAAI,WAAW,CAAC;AACnC,2BAAiB,KAAK,CAAC;AACvB,uBAAa,KAAK,CAAC;AACnB,uBAAa,KAAK,CAAC;AACnB,iBAAO,eAAe,YAAY;AAE9B,uBAAW,cAAc,KAAK,cAAc,gBAAgB;AAE5D,qBAAS,IAAI,GAAG,IAAI,GAAG,KAAK;AACxB,kBAAI,OAAO,IAAI;AACf,2BAAa,CAAC,IAAI,iBAAiB,IAAI;AACvC,2BAAa,CAAC,IAAI,iBAAiB,OAAO,CAAC;AAAA,YAC/C;AACA,gBAAI,YAAY,UAAU,YAAY,YAAY;AAClD,yBAAa,OAAO,UAAU,SAAS,CAAC;AACxC,wBAAY,KAAK,YAAY,YAAY;AACzC,yBAAa,OAAO,UAAU,SAAS,CAAC;AACxC,6BAAiB,QAAQ,SAAU,cAAc;AAC7C,8BAAgB;AAAA,YACpB,CAAC;AAAA,UACL;AAAA,QACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAQA,YAAY,KAAK;AACb,cAAI,WAAW,UAAU,eAAe,GAAG;AAC3C,cAAI,eAAe,UAAU,iBAAiB,KAAK,UAAU,UAAU,aAAa;AAIpF,eAAK,mBAAmB,aAAa,CAAC,IAAI,aAAa,CAAC,KAAK;AAC7D,eAAK,kBAAkB,KAAK,aAAa,CAAC,CAAC;AAC3C,iBAAO;AAAA,QACX;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAgBA,kBAAkB,KAAK,cAAc;AACjC,cAAI,aAAa,KAAK,kBAAkB;AAExC,uBAAa,aAAa,eAAe,aAAa;AACtD,mBAAS,IAAI,eAAe,GAAG,aAAa,KAAK,KAAK,GAAG,KAAK;AAC1D,gBAAI,IAAI,IAAI,CAAC,GAAG;AACZ;AAAA,YACJ;AACA;AAAA,UACJ;AACA,cAAI,eAAe,GAAG;AAElB,kBAAM,IAAI,kBAAkB;AAAA,UAChC;AAAA,QACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QASA,OAAO,eAAe,KAAK;AACvB,gBAAM,QAAQ,IAAI,QAAQ;AAC1B,gBAAM,WAAW,IAAI,WAAW,CAAC;AACjC,cAAI,aAAa,OAAO;AACpB,kBAAM,IAAI,kBAAkB;AAAA,UAChC;AACA,iBAAO;AAAA,QACX;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAQA,UAAU,KAAK;AAGX,cAAI,QAAQ;AACZ,cAAI;AACA,gBAAI,WAAW,UAAU,eAAe,GAAG;AAC3C,gBAAI;AACJ,gBAAI;AACA,2BAAa,UAAU,iBAAiB,KAAK,UAAU,UAAU,qBAAqB,CAAC,CAAC;AAAA,YAC5F,SACO,OAAO;AACV,kBAAI,iBAAiB,mBAAmB;AACpC,6BAAa,UAAU,iBAAiB,KAAK,UAAU,UAAU,qBAAqB,CAAC,CAAC;AAAA,cAC5F;AAAA,YACJ;AAIA,iBAAK,kBAAkB,KAAK,WAAW,CAAC,CAAC;AAIzC,gBAAI,OAAO,WAAW,CAAC;AACvB,uBAAW,CAAC,IAAI,IAAI,QAAQ,IAAI,WAAW,CAAC;AAC5C,uBAAW,CAAC,IAAI,IAAI,QAAQ,IAAI;AAChC,mBAAO;AAAA,UACX,UACA;AAEI,gBAAI,QAAQ;AAAA,UAChB;AAAA,QACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAWA,OAAO,iBAAiB,KAAK,WAAW,SAAS;AAC7C,cAAI,gBAAgB,QAAQ;AAC5B,cAAI,WAAW,IAAI,WAAW,aAAa;AAC3C,cAAI,QAAQ,IAAI,QAAQ;AACxB,cAAI,UAAU;AACd,cAAI,kBAAkB;AACtB,cAAI,eAAe;AACnB,mBAAS,KAAK,CAAC;AACf,mBAAS,IAAI,WAAW,IAAI,OAAO,KAAK;AACpC,gBAAI,IAAI,IAAI,CAAC,MAAM,SAAS;AACxB,uBAAS,eAAe;AAAA,YAC5B,OACK;AACD,kBAAI,oBAAoB,gBAAgB,GAAG;AACvC,oBAAI,WAAW,qBAAqB,UAAU,SAAS,UAAU,uBAAuB,IAAI,UAAU,kBAAkB;AACpH,yBAAO,CAAC,cAAc,CAAC;AAAA,gBAC3B;AACA,gCAAgB,SAAS,CAAC,IAAI,SAAS,CAAC;AACxC,uBAAO,UAAU,UAAU,GAAG,UAAU,GAAG,kBAAkB,CAAC;AAC9D,yBAAS,kBAAkB,CAAC,IAAI;AAChC,yBAAS,eAAe,IAAI;AAC5B;AAAA,cACJ,OACK;AACD;AAAA,cACJ;AACA,uBAAS,eAAe,IAAI;AAC5B,wBAAU,CAAC;AAAA,YACf;AAAA,UACJ;AACA,gBAAM,IAAI,kBAAkB;AAAA,QAChC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QASA,OAAO,YAAY,UAAU;AACzB,cAAI,eAAe,UAAU;AAC7B,cAAI,YAAY;AAChB,cAAI,MAAM,UAAU,SAAS;AAC7B,mBAAS,IAAI,GAAG,IAAI,KAAK,KAAK;AAC1B,gBAAI,UAAU,UAAU,SAAS,CAAC;AAClC,gBAAI,WAAW,WAAW,qBAAqB,UAAU,SAAS,UAAU,uBAAuB;AACnG,gBAAI,WAAW,cAAc;AACzB,6BAAe;AACf,0BAAY;AAAA,YAChB,WACS,aAAa,cAAc;AAEhC,0BAAY;AAAA,YAChB;AAAA,UACJ;AACA,cAAI,aAAa,GAAG;AAChB,mBAAO,YAAY;AAAA,UACvB,OACK;AACD,kBAAM,IAAI,kBAAkB;AAAA,UAChC;AAAA,QACJ;AAAA,MACJ;AACA,gBAAU,WAAW;AAAA,QACjB,WAAW,KAAK,CAAC,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC;AAAA,QAC/B,WAAW,KAAK,CAAC,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC;AAAA,QAC/B,WAAW,KAAK,CAAC,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC;AAAA,QAC/B,WAAW,KAAK,CAAC,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC;AAAA,QAC/B,WAAW,KAAK,CAAC,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC;AAAA,QAC/B,WAAW,KAAK,CAAC,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC;AAAA,QAC/B,WAAW,KAAK,CAAC,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC;AAAA,QAC/B,WAAW,KAAK,CAAC,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC;AAAA,QAC/B,WAAW,KAAK,CAAC,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC;AAAA,QAC/B,WAAW,KAAK,CAAC,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC;AAAA,QAC/B,WAAW,KAAK,CAAC,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC;AAAA,QAC/B,WAAW,KAAK,CAAC,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC;AAAA,QAC/B,WAAW,KAAK,CAAC,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC;AAAA,QAC/B,WAAW,KAAK,CAAC,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC;AAAA,QAC/B,WAAW,KAAK,CAAC,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC;AAAA,QAC/B,WAAW,KAAK,CAAC,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC;AAAA,QAC/B,WAAW,KAAK,CAAC,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC;AAAA,QAC/B,WAAW,KAAK,CAAC,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC;AAAA,QAC/B,WAAW,KAAK,CAAC,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC;AAAA,QAC/B,WAAW,KAAK,CAAC,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC;AAAA;AAAA,MACnC;AACA,gBAAU,mBAAmB;AAC7B,gBAAU,0BAA0B;AAEpC,gBAAU,0BAA0B,CAAC,GAAG,GAAG,IAAI,IAAI,EAAE;AAOrD,gBAAU,gBAAgB,WAAW,KAAK,CAAC,GAAG,GAAG,GAAG,CAAC,CAAC;AACtD,gBAAU,uBAAuB;AAAA,QAC7B,WAAW,KAAK,CAAC,GAAG,GAAG,CAAC,CAAC;AAAA,QACzB,WAAW,KAAK,CAAC,GAAG,GAAG,CAAC,CAAC;AAAA;AAAA,MAC7B;AAAA,MAUA,MAAM,6BAA6B,WAAW;AAAA,QAC1C,cAAc;AACV,gBAAM,GAAG,SAAS;AAClB,eAAK,wBAAwB;AAAA,QACjC;AAAA,QAEA,OAAO,sBAAsB,KAAK;AAC9B,cAAI,aAAa;AACjB,cAAI;AACJ,cAAI,YAAY;AAChB,cAAI,WAAW,WAAW,KAAK,CAAC,GAAG,GAAG,CAAC,CAAC;AACxC,iBAAO,CAAC,YAAY;AAChB,uBAAW,WAAW,KAAK,CAAC,GAAG,GAAG,CAAC,CAAC;AACpC,yBAAa,qBAAqB,iBAAiB,KAAK,WAAW,OAAO,KAAK,mBAAmB,QAAQ;AAC1G,gBAAI,QAAQ,WAAW,CAAC;AACxB,wBAAY,WAAW,CAAC;AACxB,gBAAI,aAAa,SAAS,YAAY;AACtC,gBAAI,cAAc,GAAG;AACjB,2BAAa,IAAI,QAAQ,YAAY,OAAO,KAAK;AAAA,YACrD;AAAA,UACJ;AACA,iBAAO;AAAA,QACX;AAAA,QACA,OAAO,cAAc,GAAG;AACpB,iBAAO,qBAAqB,4BAA4B,CAAC;AAAA,QAC7D;AAAA,QACA,OAAO,4BAA4B,GAAG;AAClC,cAAI,SAAS,EAAE;AACf,cAAI,WAAW;AACX,mBAAO;AACX,cAAI,QAAQ,SAAS,EAAE,OAAO,SAAS,CAAC,GAAG,EAAE;AAC7C,iBAAO,qBAAqB,0BAA0B,EAAE,UAAU,GAAG,SAAS,CAAC,CAAC,MAAM;AAAA,QAC1F;AAAA,QACA,OAAO,0BAA0B,GAAG;AAChC,cAAI,SAAS,EAAE;AACf,cAAI,MAAM;AACV,mBAAS,IAAI,SAAS,GAAG,KAAK,GAAG,KAAK,GAAG;AACrC,gBAAI,QAAQ,EAAE,OAAO,CAAC,EAAE,WAAW,CAAC,IAAI,IAAI,WAAW,CAAC;AACxD,gBAAI,QAAQ,KAAK,QAAQ,GAAG;AACxB,oBAAM,IAAI,gBAAgB;AAAA,YAC9B;AACA,mBAAO;AAAA,UACX;AACA,iBAAO;AACP,mBAAS,IAAI,SAAS,GAAG,KAAK,GAAG,KAAK,GAAG;AACrC,gBAAI,QAAQ,EAAE,OAAO,CAAC,EAAE,WAAW,CAAC,IAAI,IAAI,WAAW,CAAC;AACxD,gBAAI,QAAQ,KAAK,QAAQ,GAAG;AACxB,oBAAM,IAAI,gBAAgB;AAAA,YAC9B;AACA,mBAAO;AAAA,UACX;AACA,kBAAQ,MAAO,OAAO;AAAA,QAC1B;AAAA,QACA,OAAO,UAAU,KAAK,UAAU;AAC5B,iBAAO,qBAAqB,iBAAiB,KAAK,UAAU,OAAO,qBAAqB,mBAAmB,IAAI,WAAW,qBAAqB,kBAAkB,MAAM,EAAE,KAAK,CAAC,CAAC;AAAA,QACpL;AAAA;AAAA;AAAA;AAAA,QAIA,OAAO,gCAAgC,KAAK,WAAW,YAAY,SAAS;AACxE,iBAAO,KAAK,iBAAiB,KAAK,WAAW,YAAY,SAAS,IAAI,WAAW,QAAQ,MAAM,CAAC;AAAA,QACpG;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAYA,OAAO,iBAAiB,KAAK,WAAW,YAAY,SAAS,UAAU;AACnE,cAAI,QAAQ,IAAI,QAAQ;AACxB,sBAAY,aAAa,IAAI,aAAa,SAAS,IAAI,IAAI,WAAW,SAAS;AAC/E,cAAI,kBAAkB;AACtB,cAAI,eAAe;AACnB,cAAI,gBAAgB,QAAQ;AAC5B,cAAI,UAAU;AACd,mBAAS,IAAI,WAAW,IAAI,OAAO,KAAK;AACpC,gBAAI,IAAI,IAAI,CAAC,MAAM,SAAS;AACxB,uBAAS,eAAe;AAAA,YAC5B,OACK;AACD,kBAAI,oBAAoB,gBAAgB,GAAG;AACvC,oBAAI,WAAW,qBAAqB,UAAU,SAAS,qBAAqB,uBAAuB,IAAI,qBAAqB,kBAAkB;AAC1I,yBAAO,WAAW,KAAK,CAAC,cAAc,CAAC,CAAC;AAAA,gBAC5C;AACA,gCAAgB,SAAS,CAAC,IAAI,SAAS,CAAC;AACxC,oBAAI,QAAQ,SAAS,MAAM,GAAG,SAAS,SAAS,CAAC;AACjD,yBAAS,IAAI,GAAG,IAAI,kBAAkB,GAAG,KAAK;AAC1C,2BAAS,CAAC,IAAI,MAAM,CAAC;AAAA,gBACzB;AACA,yBAAS,kBAAkB,CAAC,IAAI;AAChC,yBAAS,eAAe,IAAI;AAC5B;AAAA,cACJ,OACK;AACD;AAAA,cACJ;AACA,uBAAS,eAAe,IAAI;AAC5B,wBAAU,CAAC;AAAA,YACf;AAAA,UACJ;AACA,gBAAM,IAAI,kBAAkB;AAAA,QAChC;AAAA,QACA,OAAO,YAAY,KAAK,UAAU,WAAW,UAAU;AACnD,eAAK,cAAc,KAAK,WAAW,QAAQ;AAC3C,cAAI,eAAe,KAAK;AACxB,cAAI,YAAY;AAChB,cAAI,MAAM,SAAS;AACnB,mBAAS,IAAI,GAAG,IAAI,KAAK,KAAK;AAC1B,gBAAI,UAAU,SAAS,CAAC;AACxB,gBAAI,WAAW,WAAW,qBAAqB,UAAU,SAAS,qBAAqB,uBAAuB;AAC9G,gBAAI,WAAW,cAAc;AACzB,6BAAe;AACf,0BAAY;AAAA,YAChB;AAAA,UACJ;AACA,cAAI,aAAa,GAAG;AAChB,mBAAO;AAAA,UACX,OACK;AACD,kBAAM,IAAI,kBAAkB;AAAA,UAChC;AAAA,QACJ;AAAA,MACJ;AAIA,2BAAqB,mBAAmB;AACxC,2BAAqB,0BAA0B;AAI/C,2BAAqB,oBAAoB,WAAW,KAAK,CAAC,GAAG,GAAG,CAAC,CAAC;AAIlE,2BAAqB,iBAAiB,WAAW,KAAK,CAAC,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC;AAIrE,2BAAqB,cAAc,WAAW,KAAK,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC;AAIrE,2BAAqB,aAAa;AAAA,QAC9B,WAAW,KAAK,CAAC,GAAG,GAAG,GAAG,CAAC,CAAC;AAAA,QAC5B,WAAW,KAAK,CAAC,GAAG,GAAG,GAAG,CAAC,CAAC;AAAA,QAC5B,WAAW,KAAK,CAAC,GAAG,GAAG,GAAG,CAAC,CAAC;AAAA,QAC5B,WAAW,KAAK,CAAC,GAAG,GAAG,GAAG,CAAC,CAAC;AAAA,QAC5B,WAAW,KAAK,CAAC,GAAG,GAAG,GAAG,CAAC,CAAC;AAAA,QAC5B,WAAW,KAAK,CAAC,GAAG,GAAG,GAAG,CAAC,CAAC;AAAA,QAC5B,WAAW,KAAK,CAAC,GAAG,GAAG,GAAG,CAAC,CAAC;AAAA,QAC5B,WAAW,KAAK,CAAC,GAAG,GAAG,GAAG,CAAC,CAAC;AAAA,QAC5B,WAAW,KAAK,CAAC,GAAG,GAAG,GAAG,CAAC,CAAC;AAAA,QAC5B,WAAW,KAAK,CAAC,GAAG,GAAG,GAAG,CAAC,CAAC;AAAA,MAChC;AAAA,MAKA,MAAM,wBAAwB;AAAA,QAC1B,cAAc;AACV,eAAK,wBAAwB,CAAC,IAAM,IAAM,IAAM,IAAM,IAAM,GAAM,GAAM,IAAM,GAAM,CAAI;AACxF,eAAK,uBAAuB,WAAW,KAAK,CAAC,GAAG,GAAG,GAAG,CAAC,CAAC;AACxD,eAAK,wBAAwB;AAAA,QACjC;AAAA,QACA,UAAU,WAAW,KAAK,qBAAqB;AAC3C,cAAI,SAAS,KAAK;AAClB,cAAI,MAAM,KAAK,aAAa,KAAK,qBAAqB,MAAM;AAC5D,cAAI,eAAe,OAAO,SAAS;AACnC,cAAI,gBAAgB,wBAAwB,qBAAqB,YAAY;AAC7E,cAAI,eAAe;AAAA,YACf,IAAI,aAAa,oBAAoB,CAAC,IAAI,oBAAoB,CAAC,KAAK,GAAK,SAAS;AAAA,YAClF,IAAI,YAAY,KAAK,SAAS;AAAA,UAClC;AACA,cAAI,kBAAkB,IAAI,OAAO,cAAc,MAAM,GAAG,cAAc,gBAAgB,oBAAmB,oBAAI,KAAK,GAAE,QAAQ,CAAC;AAC7H,cAAI,iBAAiB,MAAM;AACvB,4BAAgB,eAAe,aAAa;AAAA,UAChD;AACA,iBAAO;AAAA,QACX;AAAA,QACA,aAAa,KAAK,YAAY,cAAc;AACxC,cAAI,WAAW,KAAK;AACpB,mBAAS,CAAC,IAAI;AACd,mBAAS,CAAC,IAAI;AACd,mBAAS,CAAC,IAAI;AACd,mBAAS,CAAC,IAAI;AACd,cAAI,MAAM,IAAI,QAAQ;AACtB,cAAI,YAAY,WAAW,CAAC;AAC5B,cAAI,iBAAiB;AACrB,mBAAS,IAAI,GAAG,IAAI,KAAK,YAAY,KAAK,KAAK;AAC3C,gBAAI,YAAY,qBAAqB;AAAA,cACjC;AAAA,cACA;AAAA,cACA;AAAA,cACA,qBAAqB;AAAA,YAAgB;AACzC,4BAAgB,OAAO,aAAc,IAAI,WAAW,CAAC,IAAI,YAAY,EAAG;AACxE,qBAAS,WAAW,UAAU;AAC1B,2BAAa;AAAA,YACjB;AACA,gBAAI,aAAa,IAAI;AACjB,gCAAkB,KAAM,IAAI;AAAA,YAChC;AACA,gBAAI,MAAM,GAAG;AAET,0BAAY,IAAI,WAAW,SAAS;AACpC,0BAAY,IAAI,aAAa,SAAS;AAAA,YAC1C;AAAA,UACJ;AACA,cAAI,aAAa,WAAW,GAAG;AAC3B,kBAAM,IAAI,kBAAkB;AAAA,UAChC;AACA,cAAI,aAAa,KAAK,oBAAoB,cAAc;AACxD,cAAI,wBAAwB,kBAAkB,aAAa,SAAS,CAAC,MAAM,YAAY;AACnF,kBAAM,IAAI,kBAAkB;AAAA,UAChC;AACA,iBAAO;AAAA,QACX;AAAA,QACA,OAAO,kBAAkB,GAAG;AACxB,cAAI,SAAS,EAAE;AACf,cAAI,MAAM;AACV,mBAAS,IAAI,SAAS,GAAG,KAAK,GAAG,KAAK,GAAG;AACrC,mBAAO,EAAE,OAAO,CAAC,EAAE,WAAW,CAAC,IAAI,IAAI,WAAW,CAAC;AAAA,UACvD;AACA,iBAAO;AACP,mBAAS,IAAI,SAAS,GAAG,KAAK,GAAG,KAAK,GAAG;AACrC,mBAAO,EAAE,OAAO,CAAC,EAAE,WAAW,CAAC,IAAI,IAAI,WAAW,CAAC;AAAA,UACvD;AACA,iBAAO;AACP,iBAAO,MAAM;AAAA,QACjB;AAAA,QACA,oBAAoB,gBAAgB;AAChC,mBAAS,IAAI,GAAG,IAAI,IAAI,KAAK;AACzB,gBAAI,mBAAmB,KAAK,sBAAsB,CAAC,GAAG;AAClD,qBAAO;AAAA,YACX;AAAA,UACJ;AACA,gBAAM,IAAI,kBAAkB;AAAA,QAChC;AAAA,QACA,OAAO,qBAAqB,KAAK;AAC7B,cAAI,IAAI,WAAW,GAAG;AAClB,mBAAO;AAAA,UACX;AACA,cAAI,QAAQ,wBAAwB,sBAAsB,GAAG;AAC7D,cAAI,SAAS,MAAM;AACf,mBAAO;AAAA,UACX;AACA,iBAAO,oBAAI,IAAI,CAAC,CAAC,qBAAqB,iBAAiB,KAAK,CAAC,CAAC;AAAA,QAClE;AAAA,QACA,OAAO,sBAAsB,KAAK;AAC9B,cAAI;AACJ,kBAAQ,IAAI,OAAO,CAAC,GAAG;AAAA,YACnB,KAAK;AACD,yBAAW;AACX;AAAA,YACJ,KAAK;AACD,yBAAW;AACX;AAAA,YACJ,KAAK;AAED,sBAAQ,KAAK;AAAA,gBACT,KAAK;AAED,yBAAO;AAAA,gBACX,KAAK;AAED,yBAAO;AAAA,gBACX,KAAK;AACD,yBAAO;AAAA,cACf;AAEA,yBAAW;AACX;AAAA,YACJ;AACI,yBAAW;AACX;AAAA,UACR;AACA,cAAI,YAAY,SAAS,IAAI,UAAU,CAAC,CAAC;AACzC,cAAI,eAAe,YAAY,KAAK,SAAS;AAC7C,cAAI,aAAa,YAAY;AAC7B,cAAI,mBAAmB,aAAa,KAAK,MAAM,aAAa,WAAW,SAAS;AAChF,iBAAO,WAAW,cAAc,MAAM;AAAA,QAC1C;AAAA,MACJ;AAAA,MAKA,MAAM,wBAAwB;AAAA,QAC1B,cAAc;AACV,eAAK,uBAAuB,WAAW,KAAK,CAAC,GAAG,GAAG,GAAG,CAAC,CAAC;AACxD,eAAK,wBAAwB;AAAA,QACjC;AAAA,QACA,UAAU,WAAW,KAAK,qBAAqB;AAC3C,cAAI,SAAS,KAAK;AAClB,cAAI,MAAM,KAAK,aAAa,KAAK,qBAAqB,MAAM;AAC5D,cAAI,eAAe,OAAO,SAAS;AACnC,cAAI,gBAAgB,wBAAwB,qBAAqB,YAAY;AAC7E,cAAI,eAAe;AAAA,YACf,IAAI,aAAa,oBAAoB,CAAC,IAAI,oBAAoB,CAAC,KAAK,GAAK,SAAS;AAAA,YAClF,IAAI,YAAY,KAAK,SAAS;AAAA,UAClC;AACA,cAAI,kBAAkB,IAAI,OAAO,cAAc,MAAM,GAAG,cAAc,gBAAgB,oBAAmB,oBAAI,KAAK,GAAE,QAAQ,CAAC;AAC7H,cAAI,iBAAiB,MAAM;AACvB,4BAAgB,eAAe,aAAa;AAAA,UAChD;AACA,iBAAO;AAAA,QACX;AAAA,QACA,aAAa,KAAK,YAAY,cAAc;AACxC,cAAI,WAAW,KAAK;AACpB,mBAAS,CAAC,IAAI;AACd,mBAAS,CAAC,IAAI;AACd,mBAAS,CAAC,IAAI;AACd,mBAAS,CAAC,IAAI;AACd,cAAI,MAAM,IAAI,QAAQ;AACtB,cAAI,YAAY,WAAW,CAAC;AAC5B,cAAI,cAAc;AAClB,mBAAS,IAAI,GAAG,IAAI,KAAK,YAAY,KAAK,KAAK;AAC3C,gBAAI,YAAY,qBAAqB,YAAY,KAAK,UAAU,WAAW,qBAAqB,gBAAgB;AAChH,4BAAgB,OAAO,aAAc,IAAI,WAAW,CAAC,IAAI,YAAY,EAAG;AACxE,qBAAS,WAAW,UAAU;AAC1B,2BAAa;AAAA,YACjB;AACA,gBAAI,aAAa,IAAI;AACjB,6BAAe,KAAM,IAAI;AAAA,YAC7B;AACA,gBAAI,MAAM,GAAG;AAET,0BAAY,IAAI,WAAW,SAAS;AACpC,0BAAY,IAAI,aAAa,SAAS;AAAA,YAC1C;AAAA,UACJ;AACA,cAAI,aAAa,WAAW,GAAG;AAC3B,kBAAM,IAAI,kBAAkB;AAAA,UAChC;AACA,cAAI,SAAS,aAAa,SAAS,CAAC,IAAI,MAAM,aAAa;AACvD,kBAAM,IAAI,kBAAkB;AAAA,UAChC;AACA,iBAAO;AAAA,QACX;AAAA,QACA,OAAO,qBAAqB,KAAK;AAC7B,cAAI,IAAI,WAAW,GAAG;AAClB,mBAAO;AAAA,UACX;AACA,iBAAO,oBAAI,IAAI,CAAC,CAAC,qBAAqB,cAAc,SAAS,GAAG,CAAC,CAAC,CAAC;AAAA,QACvE;AAAA,MACJ;AAAA,MAEA,MAAM,uBAAuB;AAAA,QACzB,OAAO,UAAU,WAAW,KAAK,WAAW;AACxC,cAAI,sBAAsB,qBAAqB;AAAA,YAC3C;AAAA,YACA;AAAA,YACA;AAAA,YACA,KAAK;AAAA,YACL,IAAI,WAAW,KAAK,wBAAwB,MAAM,EAAE,KAAK,CAAC;AAAA,UAAC;AAC/D,cAAI;AAEA,gBAAI,cAAc,IAAI,wBAAwB;AAC9C,mBAAO,YAAY,UAAU,WAAW,KAAK,mBAAmB;AAAA,UACpE,SACOL,MAAK;AAER,gBAAI,aAAa,IAAI,wBAAwB;AAC7C,mBAAO,WAAW,UAAU,WAAW,KAAK,mBAAmB;AAAA,UACnE;AAAA,QACJ;AAAA,MACJ;AACA,6BAAuB,0BAA0B,WAAW,KAAK,CAAC,GAAG,GAAG,CAAC,CAAC;AAAA,MAU1E,MAAM,qBAAqB,qBAAqB;AAAA,QAC5C,cAAc;AACV,gBAAM;AACN,eAAK,wBAAwB;AAC7B,uBAAa,mBAAmB,aAAa,WAAW,IAAI,SAAO,WAAW,KAAK,GAAG,CAAC;AACvF,mBAAS,IAAI,IAAI,IAAI,IAAI,KAAK;AAC1B,gBAAI,SAAS,aAAa,WAAW,IAAI,EAAE;AAC3C,gBAAI,iBAAiB,IAAI,WAAW,OAAO,MAAM;AACjD,qBAAS,IAAI,GAAG,IAAI,OAAO,QAAQ,KAAK;AACpC,6BAAe,CAAC,IAAI,OAAO,OAAO,SAAS,IAAI,CAAC;AAAA,YACpD;AACA,yBAAa,iBAAiB,CAAC,IAAI;AAAA,UACvC;AAAA,QACJ;AAAA,QACA,UAAU,WAAW,KAAK,OAAO;AAC7B,cAAI,kBAAkB,aAAa,sBAAsB,GAAG;AAC5D,cAAI,sBAAsB,SAAS,OAAO,OAAO,MAAM,IAAI,iBAAiB,0BAA0B;AACtG,cAAI,uBAAuB,MAAM;AAC7B,kBAAMM,eAAc,IAAI,aAAa,gBAAgB,CAAC,IAAI,gBAAgB,CAAC,KAAK,GAAK,SAAS;AAC9F,gCAAoB,yBAAyBA,YAAW;AAAA,UAC5D;AACA,cAAI,UAAU,KAAK,aAAa,KAAK,iBAAiB,KAAK,qBAAqB;AAChF,cAAI,WAAW,QAAQ;AACvB,cAAI,SAAS,QAAQ;AACrB,cAAI,uBAAuB,MAAM;AAC7B,kBAAMA,eAAc,IAAI,YAAY,UAAU,SAAS;AACvD,gCAAoB,yBAAyBA,YAAW;AAAA,UAC5D;AACA,cAAI,WAAW,KAAK,UAAU,KAAK,QAAQ;AAC3C,cAAI,uBAAuB,MAAM;AAC7B,kBAAMA,eAAc,IAAI,aAAa,SAAS,CAAC,IAAI,SAAS,CAAC,KAAK,GAAK,SAAS;AAChF,gCAAoB,yBAAyBA,YAAW;AAAA,UAC5D;AAGA,cAAI,MAAM,SAAS,CAAC;AACpB,cAAI,WAAW,OAAO,MAAM,SAAS,CAAC;AACtC,cAAI,YAAY,IAAI,QAAQ,KAAK,CAAC,IAAI,QAAQ,KAAK,UAAU,KAAK,GAAG;AACjE,kBAAM,IAAI,kBAAkB;AAAA,UAChC;AACA,cAAI,eAAe,OAAO,SAAS;AAEnC,cAAI,aAAa,SAAS,GAAG;AACzB,kBAAM,IAAI,gBAAgB;AAAA,UAC9B;AACA,cAAI,CAAC,aAAa,cAAc,YAAY,GAAG;AAC3C,kBAAM,IAAI,kBAAkB;AAAA,UAChC;AACA,cAAI,QAAQ,gBAAgB,CAAC,IAAI,gBAAgB,CAAC,KAAK;AACvD,cAAI,SAAS,SAAS,CAAC,IAAI,SAAS,CAAC,KAAK;AAC1C,cAAI,SAAS,KAAK,iBAAiB;AACnC,cAAI,cAAc,CAAC,IAAI,YAAY,MAAM,SAAS,GAAG,IAAI,YAAY,OAAO,SAAS,CAAC;AACtF,cAAI,eAAe,IAAI,OAAO,cAAc,MAAM,GAAG,aAAa,SAAQ,oBAAI,KAAK,GAAE,QAAQ,CAAC;AAC9F,cAAI,kBAAkB;AACtB,cAAI;AACA,gBAAI,kBAAkB,uBAAuB,UAAU,WAAW,KAAK,SAAS,CAAC,CAAC;AAClF,yBAAa,YAAY,qBAAqB,mBAAmB,gBAAgB,QAAQ,CAAC;AAC1F,yBAAa,eAAe,gBAAgB,kBAAkB,CAAC;AAC/D,yBAAa,gBAAgB,gBAAgB,gBAAgB,CAAC;AAC9D,8BAAkB,gBAAgB,QAAQ,EAAE;AAAA,UAChD,SACO,aAAa;AAAA,UAAC;AACrB,cAAI,oBAAoB,SAAS,OAAO,OAAO,MAAM,IAAI,iBAAiB,sBAAsB;AAChG,cAAI,qBAAqB,MAAM;AAC3B,gBAAI,QAAQ;AACZ,qBAAS,UAAU,mBAAmB;AAClC,kBAAI,gBAAgB,SAAS,MAAM,QAAQ;AACvC,wBAAQ;AACR;AAAA,cACJ;AAAA,YACJ;AACA,gBAAI,CAAC,OAAO;AACR,oBAAM,IAAI,kBAAkB;AAAA,YAChC;AAAA,UACJ;AACA,iBAAO;AAAA,QACX;AAAA,QACA,UAAU,KAAK,UAAU;AACrB,iBAAO,aAAa;AAAA,YAChB;AAAA,YAAK;AAAA,YAAU;AAAA,YAAO,aAAa;AAAA,YACnC,IAAI,WAAW,aAAa,kBAAkB,MAAM,EAAE,KAAK,CAAC;AAAA,UAAC;AAAA,QACrE;AAAA,QACA,OAAO,cAAc,GAAG;AACpB,iBAAO,aAAa,4BAA4B,CAAC;AAAA,QACrD;AAAA,QACA,OAAO,4BAA4B,GAAG;AAClC,cAAI,SAAS,EAAE;AACf,cAAI,WAAW;AACX,mBAAO;AACX,cAAI,QAAQ,SAAS,EAAE,OAAO,SAAS,CAAC,GAAG,EAAE;AAC7C,iBAAO,aAAa,0BAA0B,EAAE,UAAU,GAAG,SAAS,CAAC,CAAC,MAAM;AAAA,QAClF;AAAA,QACA,OAAO,0BAA0B,GAAG;AAChC,cAAI,SAAS,EAAE;AACf,cAAI,MAAM;AACV,mBAAS,IAAI,SAAS,GAAG,KAAK,GAAG,KAAK,GAAG;AACrC,gBAAI,QAAQ,EAAE,OAAO,CAAC,EAAE,WAAW,CAAC,IAAI,IAAI,WAAW,CAAC;AACxD,gBAAI,QAAQ,KAAK,QAAQ,GAAG;AACxB,oBAAM,IAAI,gBAAgB;AAAA,YAC9B;AACA,mBAAO;AAAA,UACX;AACA,iBAAO;AACP,mBAAS,IAAI,SAAS,GAAG,KAAK,GAAG,KAAK,GAAG;AACrC,gBAAI,QAAQ,EAAE,OAAO,CAAC,EAAE,WAAW,CAAC,IAAI,IAAI,WAAW,CAAC;AACxD,gBAAI,QAAQ,KAAK,QAAQ,GAAG;AACxB,oBAAM,IAAI,gBAAgB;AAAA,YAC9B;AACA,mBAAO;AAAA,UACX;AACA,kBAAQ,MAAO,OAAO;AAAA,QAC1B;AAAA,MACJ;AAAA,MASA,MAAM,oBAAoB,aAAa;AAAA,QACnC,cAAc;AACV,gBAAM;AACN,eAAK,uBAAuB,WAAW,KAAK,CAAC,GAAG,GAAG,GAAG,CAAC,CAAC;AAAA,QAC5D;AAAA,QACA,aAAa,KAAK,YAAY,cAAc;AACxC,cAAI,WAAW,KAAK;AACpB,mBAAS,CAAC,IAAI;AACd,mBAAS,CAAC,IAAI;AACd,mBAAS,CAAC,IAAI;AACd,mBAAS,CAAC,IAAI;AACd,cAAI,MAAM,IAAI,QAAQ;AACtB,cAAI,YAAY,WAAW,CAAC;AAC5B,cAAI,iBAAiB;AACrB,mBAAS,IAAI,GAAG,IAAI,KAAK,YAAY,KAAK,KAAK;AAC3C,gBAAI,YAAY,aAAa,YAAY,KAAK,UAAU,WAAW,aAAa,gBAAgB;AAChG,4BAAgB,OAAO,aAAc,IAAI,WAAW,CAAC,IAAI,YAAY,EAAG;AACxE,qBAAS,WAAW,UAAU;AAC1B,2BAAa;AAAA,YACjB;AACA,gBAAI,aAAa,IAAI;AACjB,gCAAkB,KAAM,IAAI;AAAA,YAChC;AAAA,UACJ;AACA,yBAAe,YAAY,oBAAoB,cAAc,cAAc;AAC3E,cAAI,cAAc,aAAa;AAAA,YAC3B;AAAA,YACA;AAAA,YACA;AAAA,YACA,aAAa;AAAA,YACb,IAAI,WAAW,aAAa,eAAe,MAAM,EAAE,KAAK,CAAC;AAAA,UAAC;AAC9D,sBAAY,YAAY,CAAC;AACzB,mBAAS,IAAI,GAAG,IAAI,KAAK,YAAY,KAAK,KAAK;AAC3C,gBAAI,YAAY,aAAa,YAAY,KAAK,UAAU,WAAW,aAAa,UAAU;AAC1F,4BAAgB,OAAO,aAAc,IAAI,WAAW,CAAC,IAAI,SAAU;AACnE,qBAAS,WAAW,UAAU;AAC1B,2BAAa;AAAA,YACjB;AAAA,UACJ;AACA,iBAAO,EAAE,WAAW,aAAa;AAAA,QACrC;AAAA,QACA,mBAAmB;AACf,iBAAO,gBAAgB;AAAA,QAC3B;AAAA,QACA,OAAO,oBAAoB,cAAc,gBAAgB;AACrD,mBAAS,IAAI,GAAG,IAAI,IAAI,KAAK;AACzB,gBAAI,mBAAmB,KAAK,sBAAsB,CAAC,GAAG;AAClD,6BAAe,OAAO,aAAc,IAAI,WAAW,CAAC,IAAI,CAAE,IAAI;AAC9D,qBAAO;AAAA,YACX;AAAA,UACJ;AACA,gBAAM,IAAI,kBAAkB;AAAA,QAChC;AAAA,MACJ;AACA,kBAAY,wBAAwB,CAAC,GAAM,IAAM,IAAM,IAAK,IAAM,IAAM,IAAM,IAAM,IAAM,EAAI;AAAA,MAO9F,MAAM,mBAAmB,aAAa;AAAA,QAClC,cAAc;AACV,gBAAM;AACN,eAAK,uBAAuB,WAAW,KAAK,CAAC,GAAG,GAAG,GAAG,CAAC,CAAC;AAAA,QAC5D;AAAA,QACA,aAAa,KAAK,YAAY,cAAc;AACxC,gBAAM,WAAW,KAAK;AACtB,mBAAS,CAAC,IAAI;AACd,mBAAS,CAAC,IAAI;AACd,mBAAS,CAAC,IAAI;AACd,mBAAS,CAAC,IAAI;AACd,cAAI,MAAM,IAAI,QAAQ;AACtB,cAAI,YAAY,WAAW,CAAC;AAC5B,mBAAS,IAAI,GAAG,IAAI,KAAK,YAAY,KAAK,KAAK;AAC3C,gBAAI,YAAY,aAAa,YAAY,KAAK,UAAU,WAAW,aAAa,UAAU;AAC1F,4BAAgB,OAAO,aAAc,IAAI,WAAW,CAAC,IAAI,SAAU;AACnE,qBAAS,WAAW,UAAU;AAC1B,2BAAa;AAAA,YACjB;AAAA,UACJ;AACA,cAAI,cAAc,aAAa,iBAAiB,KAAK,WAAW,MAAM,aAAa,gBAAgB,IAAI,WAAW,aAAa,eAAe,MAAM,EAAE,KAAK,CAAC,CAAC;AAC7J,sBAAY,YAAY,CAAC;AACzB,mBAAS,IAAI,GAAG,IAAI,KAAK,YAAY,KAAK,KAAK;AAC3C,gBAAI,YAAY,aAAa,YAAY,KAAK,UAAU,WAAW,aAAa,UAAU;AAC1F,4BAAgB,OAAO,aAAc,IAAI,WAAW,CAAC,IAAI,SAAU;AACnE,qBAAS,WAAW,UAAU;AAC1B,2BAAa;AAAA,YACjB;AAAA,UACJ;AACA,iBAAO,EAAE,WAAW,aAAa;AAAA,QACrC;AAAA,QACA,mBAAmB;AACf,iBAAO,gBAAgB;AAAA,QAC3B;AAAA,MACJ;AAAA,MAcA,MAAM,mBAAmB,aAAa;AAAA,QAClC,cAAc;AACV,gBAAM,GAAG,SAAS;AAClB,eAAK,cAAc,IAAI,YAAY;AAAA,QACvC;AAAA;AAAA,QAEA,mBAAmB;AACf,iBAAO,gBAAgB;AAAA,QAC3B;AAAA;AAAA;AAAA,QAGA,OAAO,OAAO,OAAO;AACjB,iBAAO,KAAK,kBAAkB,KAAK,YAAY,OAAO,KAAK,CAAC;AAAA,QAChE;AAAA;AAAA,QAEA,UAAU,WAAW,KAAK,OAAO;AAC7B,iBAAO,KAAK,kBAAkB,KAAK,YAAY,UAAU,WAAW,KAAK,KAAK,CAAC;AAAA,QACnF;AAAA;AAAA,QAEA,aAAa,KAAK,YAAY,cAAc;AACxC,iBAAO,KAAK,YAAY,aAAa,KAAK,YAAY,YAAY;AAAA,QACtE;AAAA,QACA,kBAAkB,QAAQ;AACtB,cAAI,OAAO,OAAO,QAAQ;AAC1B,cAAI,KAAK,OAAO,CAAC,MAAM,KAAK;AACxB,gBAAI,aAAa,IAAI,OAAO,KAAK,UAAU,CAAC,GAAG,MAAM,MAAM,OAAO,gBAAgB,GAAG,gBAAgB,KAAK;AAC1G,gBAAI,OAAO,kBAAkB,KAAK,MAAM;AACpC,yBAAW,eAAe,OAAO,kBAAkB,CAAC;AAAA,YACxD;AACA,mBAAO;AAAA,UACX,OACK;AACD,kBAAM,IAAI,kBAAkB;AAAA,UAChC;AAAA,QACJ;AAAA,QACA,QAAQ;AACJ,eAAK,YAAY,MAAM;AAAA,QAC3B;AAAA,MACJ;AAAA,MAaY,MAAM,mBAAmB,aAAa;AAAA,QAC9C,cAAc;AACV,gBAAM;AACN,eAAK,uBAAuB,IAAI,WAAW,CAAC;AAAA,QAChD;AAAA;AAAA;AAAA;AAAA;AAAA,QAKA,aAAa,KAAK,YAAY,QAAQ;AAClC,gBAAM,WAAW,KAAK,qBAAqB,IAAI,OAAK,CAAC;AACrD,mBAAS,CAAC,IAAI;AACd,mBAAS,CAAC,IAAI;AACd,mBAAS,CAAC,IAAI;AACd,mBAAS,CAAC,IAAI;AACd,gBAAM,MAAM,IAAI,QAAQ;AACxB,cAAI,YAAY,WAAW,CAAC;AAC5B,cAAI,iBAAiB;AACrB,mBAAS,IAAI,GAAG,IAAI,KAAK,YAAY,KAAK,KAAK;AAC3C,kBAAM,YAAY,WAAW;AAAA,cACzB;AAAA,cAAK;AAAA,cAAU;AAAA,cAAW,WAAW;AAAA,YAAgB;AACzD,sBAAU,OAAO,aAAc,IAAI,WAAW,CAAC,IAAK,YAAY,EAAI;AACpE,qBAAS,WAAW,UAAU;AAC1B,2BAAa;AAAA,YACjB;AACA,gBAAI,aAAa,IAAI;AACjB,gCAAmB,KAAM,IAAI;AAAA,YACjC;AAAA,UACJ;AACA,cAAI,eAAe,WAAW;AAAA,YAC1B;AAAA,YAAQ;AAAA,UAAc;AAC1B,iBAAO,EAAC,WAAW,aAAY;AAAA,QACnC;AAAA;AAAA;AAAA;AAAA;AAAA,QAKA,UAAU,KAAK,UAAU;AACrB,iBAAO,WAAW;AAAA,YACd;AAAA,YAAK;AAAA,YAAU;AAAA,YAAM,WAAW;AAAA,UAAkB;AAAA,QAC1D;AAAA;AAAA;AAAA;AAAA;AAAA,QAKA,cAAc,GAAG;AACb,iBAAO,aAAa,cAAc,WAAW,kBAAkB,CAAC,CAAC;AAAA,QACrE;AAAA;AAAA;AAAA;AAAA,QAIA,OAAO,6BAA6B,cAAc,gBAAgB;AAC9D,mBAAS,SAAS,GAAG,UAAU,GAAG,UAAU;AACxC,qBAAS,IAAI,GAAG,IAAI,IAAI,KAAK;AACzB,kBAAI,mBAAmB,KAAK,gCAAgC,MAAM,EAAE,CAAC,GAAG;AACpE,oBAAI,SAAS,OAAO,aAAa,IAAI,WAAW,CAAC,IAAI,MAAM;AAC3D,oBAAI,SAAS,OAAO,aAAa,IAAI,WAAW,CAAC,IAAI,CAAC;AACtD,uBAAO,SAAS,eAAe;AAAA,cACnC;AAAA,YACJ;AAAA,UACJ;AACA,gBAAM,kBAAkB,oBAAoB;AAAA,QAChD;AAAA;AAAA,QAEA,mBAAmB;AACf,iBAAO,gBAAgB;AAAA,QAC3B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAOA,OAAO,kBAAkB,MAAM;AAE3B,gBAAM,YAAY,KAAK,MAAM,GAAG,CAAC,EAAE,MAAM,EAAE,EAAE,IAAI,OAAK,EAAE,WAAW,CAAC,CAAC;AACrE,gBAAM,SAAS,IAAI;AAAA;AAAA,UAAqB;AACxC,iBAAO,OAAO,KAAK,OAAO,CAAC,CAAC;AAC5B,cAAI,WAAW,UAAU,CAAC;AAC1B,kBAAQ,UAAU;AAAA,YACd,KAAK;AAAA,YACL,KAAK;AAAA,YACL,KAAK;AACD,qBAAO,YAAY,WAAW,GAAG,CAAC;AAClC,qBAAO,OAAO,QAAQ;AACtB,qBAAO,OAAO,MAAM;AACpB,qBAAO,YAAY,WAAW,GAAG,CAAC;AAClC;AAAA,YACJ,KAAK;AACD,qBAAO,YAAY,WAAW,GAAG,CAAC;AAClC,qBAAO,OAAO,OAAO;AACrB,qBAAO,YAAY,WAAW,GAAG,CAAC;AAClC;AAAA,YACJ,KAAK;AACD,qBAAO,YAAY,WAAW,GAAG,CAAC;AAClC,qBAAO,OAAO,OAAO;AACrB,qBAAO,OAAO,UAAU,CAAC,CAAC;AAC1B;AAAA,YACJ;AACI,qBAAO,YAAY,WAAW,GAAG,CAAC;AAClC,qBAAO,OAAO,MAAM;AACpB,qBAAO,OAAO,QAAQ;AACtB;AAAA,UACR;AAEA,cAAI,KAAK,UAAU,GAAG;AAClB,mBAAO,OAAO,KAAK,OAAO,CAAC,CAAC;AAAA,UAChC;AACA,iBAAO,OAAO,SAAS;AAAA,QAC3B;AAAA,MACJ;AAKA,iBAAW,qBAAqB,WAAW,KAAK,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC;AA6BlE,iBAAW,kCAAkC;AAAA,QACzC,WAAW,KAAK,CAAC,IAAM,IAAM,IAAM,IAAM,IAAM,IAAM,IAAM,IAAM,IAAM,EAAI,CAAC;AAAA,QAC5E,WAAW,KAAK,CAAC,GAAM,IAAM,IAAM,IAAM,IAAM,IAAM,IAAM,IAAM,IAAM,EAAI,CAAC;AAAA,MAChF;AAAA,MASA,MAAM,gCAAgC,WAAW;AAAA,QAC7C,YAAY,OAAO;AACf,gBAAM;AACN,cAAI,kBAAkB,SAAS,OAAO,OAAO,MAAM,IAAI,iBAAiB,gBAAgB;AACxF,cAAI,UAAU,CAAC;AACf,cAAI,CAAChB,mBAAkB,eAAe,GAAG;AACrC,gBAAI,gBAAgB,QAAQ,gBAAgB,MAAM,IAAI,IAAI;AACtD,sBAAQ,KAAK,IAAI,YAAY,CAAC;AAAA,YAClC;AACA,gBAAI,gBAAgB,QAAQ,gBAAgB,KAAK,IAAI,IAAI;AACrD,sBAAQ,KAAK,IAAI,WAAW,CAAC;AAAA,YACjC;AACA,gBAAI,gBAAgB,QAAQ,gBAAgB,KAAK,IAAI,IAAI;AACrD,sBAAQ,KAAK,IAAI,WAAW,CAAC;AAAA,YACjC;AACA,gBAAI,gBAAgB,QAAQ,gBAAgB,KAAK,IAAI,IAAI;AACrD,sBAAQ,KAAK,IAAI,WAAW,CAAC;AAAA,YACjC;AAAA,UACJ,OAAO;AAEH,oBAAQ,KAAK,IAAI,YAAY,CAAC;AAC9B,oBAAQ,KAAK,IAAI,WAAW,CAAC;AAC7B,oBAAQ,KAAK,IAAI,WAAW,CAAC;AAC7B,oBAAQ,KAAK,IAAI,WAAW,CAAC;AAAA,UACjC;AACA,eAAK,UAAU;AAAA,QACnB;AAAA,QACA,UAAU,WAAW,KAAK,OAAO;AAC7B,mBAAS,UAAU,KAAK,SAAS;AAC7B,gBAAI;AAEA,oBAAM,SAAS,OAAO,UAAU,WAAW,KAAK,KAAK;AAarD,oBAAM,iBAAiB,OAAO,iBAAiB,MAAM,gBAAgB,UACjE,OAAO,QAAQ,EAAE,OAAO,CAAC,MAAM;AAEnC,oBAAM,kBAAkB,SAAS,OAAO,OAAO,MAAM,IAAI,iBAAiB,gBAAgB;AAC1F,oBAAM,gBAAgB,mBAAmB,QAAQ,gBAAgB,SAAS,gBAAgB,KAAK;AAC/F,kBAAI,kBAAkB,eAAe;AACjC,sBAAM,WAAW,OAAO,YAAY;AAEpC,sBAAM,aAAa,IAAI;AAAA,kBACnB,OAAO,QAAQ,EAAE,UAAU,CAAC;AAAA,kBAC5B;AAAA,kBACC,WAAW,SAAS,SAAS;AAAA,kBAC9B,OAAO,gBAAgB;AAAA,kBACvB,gBAAgB;AAAA,gBAAK;AACzB,2BAAW,eAAe,OAAO,kBAAkB,CAAC;AACpD,uBAAO;AAAA,cACX;AACA,qBAAO;AAAA,YACX,SACOU,MAAK;AAAA,YAEZ;AAAA,UACJ;AACA,gBAAM,IAAI,kBAAkB;AAAA,QAChC;AAAA,QACA,QAAQ;AACJ,mBAAS,UAAU,KAAK,SAAS;AAC7B,mBAAO,MAAM;AAAA,UACjB;AAAA,QACJ;AAAA,MACJ;AAAA,MAIA,MAAM,0BAA0B,WAAW;AAAA,QACvC,cAAc;AACV,gBAAM;AACN,eAAK,uBAAuB,IAAI,WAAW,CAAC;AAC5C,eAAK,wBAAwB,IAAI,WAAW,CAAC;AAC7C,eAAK,oBAAoB,IAAI,MAAM,CAAC;AACpC,eAAK,qBAAqB,IAAI,MAAM,CAAC;AACrC,eAAK,YAAY,IAAI,MAAM,KAAK,sBAAsB,SAAS,CAAC;AAChE,eAAK,aAAa,IAAI,MAAM,KAAK,sBAAsB,SAAS,CAAC;AAAA,QACrE;AAAA,QACA,0BAA0B;AACtB,iBAAO,KAAK;AAAA,QAChB;AAAA,QACA,2BAA2B;AACvB,iBAAO,KAAK;AAAA,QAChB;AAAA,QACA,uBAAuB;AACnB,iBAAO,KAAK;AAAA,QAChB;AAAA,QACA,wBAAwB;AACpB,iBAAO,KAAK;AAAA,QAChB;AAAA,QACA,eAAe;AACX,iBAAO,KAAK;AAAA,QAChB;AAAA,QACA,gBAAgB;AACZ,iBAAO,KAAK;AAAA,QAChB;AAAA,QACA,iBAAiB,UAAU,gBAAgB;AACvC,mBAAS,QAAQ,GAAG,QAAQ,eAAe,QAAQ,SAAS;AACxD,gBAAI,WAAW,qBAAqB,UAAU,eAAe,KAAK,GAAG,kBAAkB,uBAAuB,IAAI,kBAAkB,kBAAkB;AAClJ,qBAAO;AAAA,YACX;AAAA,UACJ;AACA,gBAAM,IAAI,kBAAkB;AAAA,QAChC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAMA,OAAO,MAAM,OAAO;AAChB,iBAAO,UAAU,IAAI,IAAI,WAAW,KAAK,CAAC;AAAA,QAC9C;AAAA,QACA,OAAO,UAAU,OAAO,QAAQ;AAC5B,cAAI,QAAQ;AACZ,cAAI,eAAe,OAAO,CAAC;AAC3B,mBAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;AACnC,gBAAI,OAAO,CAAC,IAAI,cAAc;AAC1B,6BAAe,OAAO,CAAC;AACvB,sBAAQ;AAAA,YACZ;AAAA,UACJ;AACA,gBAAM,KAAK;AAAA,QACf;AAAA,QACA,OAAO,UAAU,OAAO,QAAQ;AAC5B,cAAI,QAAQ;AACZ,cAAI,eAAe,OAAO,CAAC;AAC3B,mBAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;AACnC,gBAAI,OAAO,CAAC,IAAI,cAAc;AAC1B,6BAAe,OAAO,CAAC;AACvB,sBAAQ;AAAA,YACZ;AAAA,UACJ;AACA,gBAAM,KAAK;AAAA,QACf;AAAA,QACA,OAAO,gBAAgB,UAAU;AAC7B,cAAI,cAAc,SAAS,CAAC,IAAI,SAAS,CAAC;AAC1C,cAAI,MAAM,cAAc,SAAS,CAAC,IAAI,SAAS,CAAC;AAChD,cAAI,QAAQ,cAAc;AAC1B,cAAI,SAAS,kBAAkB,4BAA4B,SAAS,kBAAkB,0BAA0B;AAE5G,gBAAI,aAAa,OAAO;AACxB,gBAAI,aAAa,OAAO;AACxB,qBAAS,WAAW,UAAU;AAC1B,kBAAI,UAAU,YAAY;AACtB,6BAAa;AAAA,cACjB;AACA,kBAAI,UAAU,YAAY;AACtB,6BAAa;AAAA,cACjB;AAAA,YACJ;AACA,mBAAO,aAAa,KAAK;AAAA,UAC7B;AACA,iBAAO;AAAA,QACX;AAAA,MACJ;AACA,wBAAkB,mBAAmB;AACrC,wBAAkB,0BAA0B;AAC5C,wBAAkB,2BAA2B,MAAM;AACnD,wBAAkB,2BAA2B,OAAO;AAAA,MAEpD,MAAM,cAAc;AAAA,QAChB,YAAY,OAAO,iBAAiB;AAChC,eAAK,QAAQ;AACb,eAAK,kBAAkB;AAAA,QAC3B;AAAA,QACA,WAAW;AACP,iBAAO,KAAK;AAAA,QAChB;AAAA,QACA,qBAAqB;AACjB,iBAAO,KAAK;AAAA,QAChB;AAAA,QACA,WAAW;AACP,iBAAO,KAAK,QAAQ,MAAM,KAAK,kBAAkB;AAAA,QACrD;AAAA,QACA,OAAO,GAAG;AACN,cAAI,EAAE,aAAa,gBAAgB;AAC/B,mBAAO;AAAA,UACX;AACA,gBAAM,OAAO;AACb,iBAAO,KAAK,UAAU,KAAK,SAAS,KAAK,oBAAoB,KAAK;AAAA,QACtE;AAAA,QACA,WAAW;AACP,iBAAO,KAAK,QAAQ,KAAK;AAAA,QAC7B;AAAA,MACJ;AAAA,MAEA,MAAM,cAAc;AAAA,QAChB,YAAY,OAAO,UAAU,OAAO,KAAK,WAAW;AAChD,eAAK,QAAQ;AACb,eAAK,WAAW;AAChB,eAAK,QAAQ;AACb,eAAK,WAAW;AAChB,eAAK,eAAe,IAAI,MAAM;AAC9B,eAAK,aAAa,KAAK,IAAI,YAAY,OAAO,SAAS,CAAC;AACxD,eAAK,aAAa,KAAK,IAAI,YAAY,KAAK,SAAS,CAAC;AAAA,QAC1D;AAAA,QACA,WAAW;AACP,iBAAO,KAAK;AAAA,QAChB;AAAA,QACA,cAAc;AACV,iBAAO,KAAK;AAAA,QAChB;AAAA,QACA,kBAAkB;AACd,iBAAO,KAAK;AAAA,QAChB;AAAA,QACA,OAAO,GAAG;AACN,cAAI,EAAE,aAAa,gBAAgB;AAC/B,mBAAO;AAAA,UACX;AACA,gBAAM,OAAO;AACb,iBAAO,KAAK,UAAU,KAAK;AAAA,QAC/B;AAAA,QACA,WAAW;AACP,iBAAO,KAAK;AAAA,QAChB;AAAA,MACJ;AAAA,MAKA,MAAM,SAAS;AAAA,QACX,cAAc;AAAA,QAAE;AAAA,QAChB,OAAO,YAAY,QAAQ,UAAU,UAAU;AAC3C,cAAI,IAAI;AACR,mBAAS,SAAS,QAAQ;AACtB,iBAAK;AAAA,UACT;AACA,cAAI,MAAM;AACV,cAAI,aAAa;AACjB,cAAI,WAAW,OAAO;AACtB,mBAAS,MAAM,GAAG,MAAM,WAAW,GAAG,OAAO;AACzC,gBAAI;AACJ,iBAAK,WAAW,GAAG,cAAc,KAAK,KAAK,WAAW,OAAO,GAAG,GAAG,YAAY,cAAc,EAAE,KAAK,MAAM;AACtG,kBAAI,SAAS,SAAS,QAAQ,IAAI,WAAW,GAAG,WAAW,MAAM,CAAC;AAClE,kBAAI,YAAa,eAAe,KAAO,IAAI,YAAY,WAAW,MAAM,MAAM,WAAW,MAAM,GAAI;AAC/F,0BAAU,SAAS,QAAQ,IAAI,YAAY,WAAW,MAAM,WAAW,MAAM,CAAC;AAAA,cAClF;AACA,kBAAI,WAAW,MAAM,IAAI,GAAG;AACxB,oBAAI,UAAU;AACd,yBAAS,aAAa,IAAI,YAAY,WAAW,MAAM,IAAI,aAAa,UAAU,cAAc;AAC5F,6BAAW,SAAS,QAAQ,IAAI,WAAW,aAAa,GAAG,WAAW,MAAM,CAAC;AAAA,gBACjF;AACA,0BAAU,WAAW,WAAW,IAAI;AAAA,cACxC,WACS,IAAI,WAAW,UAAU;AAC9B;AAAA,cACJ;AACA,qBAAO;AAAA,YACX;AACA,iBAAK;AAAA,UACT;AACA,iBAAO;AAAA,QACX;AAAA,QACA,OAAO,QAAQ,GAAG,GAAG;AACjB,cAAI;AACJ,cAAI;AACJ,cAAI,IAAI,IAAI,GAAG;AACX,uBAAW;AACX,uBAAW,IAAI;AAAA,UACnB,OACK;AACD,uBAAW,IAAI;AACf,uBAAW;AAAA,UACf;AACA,cAAI,MAAM;AACV,cAAI,IAAI;AACR,mBAAS,IAAI,GAAG,IAAI,UAAU,KAAK;AAC/B,mBAAO;AACP,gBAAI,KAAK,UAAU;AACf,qBAAO;AACP;AAAA,YACJ;AAAA,UACJ;AACA,iBAAQ,KAAK,UAAW;AACpB,mBAAO;AACP;AAAA,UACJ;AACA,iBAAO;AAAA,QACX;AAAA,MACJ;AAAA,MAEA,MAAM,gBAAgB;AAAA,QAClB,OAAO,cAAc,OAAO;AACxB,cAAI,aAAc,MAAM,SAAS,IAAK;AACtC,cAAI,MAAM,MAAM,SAAS,CAAC,EAAE,aAAa,KAAK,MAAM;AAChD,0BAAc;AAAA,UAClB;AACA,cAAI,OAAO,KAAK;AAChB,cAAI,SAAS,IAAI,SAAS,IAAI;AAC9B,cAAI,SAAS;AACb,cAAI,YAAY,MAAM,CAAC;AACvB,cAAI,aAAa,UAAU,aAAa,EAAE,SAAS;AACnD,mBAAS,IAAI,IAAI,KAAK,GAAG,EAAE,GAAG;AAC1B,iBAAK,aAAc,KAAK,MAAO,GAAG;AAC9B,qBAAO,IAAI,MAAM;AAAA,YACrB;AACA;AAAA,UACJ;AACA,mBAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,EAAE,GAAG;AACnC,gBAAI,cAAc,MAAM,CAAC;AACzB,gBAAI,YAAY,YAAY,YAAY,EAAE,SAAS;AACnD,qBAAS,IAAI,IAAI,KAAK,GAAG,EAAE,GAAG;AAC1B,mBAAK,YAAa,KAAK,MAAO,GAAG;AAC7B,uBAAO,IAAI,MAAM;AAAA,cACrB;AACA;AAAA,YACJ;AACA,gBAAI,YAAY,aAAa,KAAK,MAAM;AACpC,kBAAI,aAAa,YAAY,aAAa,EAAE,SAAS;AACrD,uBAAS,IAAI,IAAI,KAAK,GAAG,EAAE,GAAG;AAC1B,qBAAK,aAAc,KAAK,MAAO,GAAG;AAC9B,yBAAO,IAAI,MAAM;AAAA,gBACrB;AACA;AAAA,cACJ;AAAA,YACJ;AAAA,UACJ;AACA,iBAAO;AAAA,QACX;AAAA,MACJ;AAAA,MAEA,MAAM,kBAAkB;AAAA,QACpB,YAAY,UAAU,oBAAoB;AACtC,cAAI,oBAAoB;AACpB,iBAAK,qBAAqB;AAAA,UAC9B,OACK;AACD,iBAAK,WAAW;AAChB,iBAAK,qBAAqB;AAAA,UAC9B;AAAA,QACJ;AAAA,QACA,wBAAwB;AACpB,iBAAO,KAAK;AAAA,QAChB;AAAA,QACA,aAAa;AACT,iBAAO,KAAK;AAAA,QAChB;AAAA,MACJ;AAAA,MAEA,MAAM,cAAc;AAAA,QAChB,YAAY,aAAa;AACrB,eAAK,cAAc;AAAA,QACvB;AAAA,QACA,iBAAiB;AACb,iBAAO,KAAK;AAAA,QAChB;AAAA,MACJ;AAAA,MAEA,MAAM,oBAAoB,cAAc;AAAA,QACpC,YAAY,aAAa,OAAO;AAC5B,gBAAM,WAAW;AACjB,eAAK,QAAQ;AAAA,QACjB;AAAA,QACA,WAAW;AACP,iBAAO,KAAK;AAAA,QAChB;AAAA,QACA,SAAS;AACL,iBAAO,KAAK,UAAU,YAAY;AAAA,QACtC;AAAA,MACJ;AACA,kBAAY,OAAO;AAAA,MAEnB,MAAM,2BAA2B,cAAc;AAAA,QAC3C,YAAY,aAAa,WAAW,gBAAgB;AAChD,gBAAM,WAAW;AACjB,cAAI,gBAAgB;AAChB,iBAAK,YAAY;AACjB,iBAAK,iBAAiB,KAAK;AAAA,UAC/B,OACK;AACD,iBAAK,YAAY;AACjB,iBAAK,iBAAiB;AAAA,UAC1B;AACA,eAAK,YAAY;AAAA,QACrB;AAAA,QACA,eAAe;AACX,iBAAO,KAAK;AAAA,QAChB;AAAA,QACA,cAAc;AACV,iBAAO,KAAK;AAAA,QAChB;AAAA,QACA,oBAAoB;AAChB,iBAAO,KAAK;AAAA,QAChB;AAAA,MACJ;AAAA,MAEA,MAAM,uBAAuB,cAAc;AAAA,QACvC,YAAY,aAAa,YAAY,aAAa;AAC9C,gBAAM,WAAW;AACjB,cAAI,aAAa,KAAK,aAAa,MAAM,cAAc,KAAK,cAAc,IAAI;AAC1E,kBAAM,IAAI,gBAAgB;AAAA,UAC9B;AACA,eAAK,aAAa;AAClB,eAAK,cAAc;AAAA,QACvB;AAAA,QACA,gBAAgB;AACZ,iBAAO,KAAK;AAAA,QAChB;AAAA,QACA,iBAAiB;AACb,iBAAO,KAAK;AAAA,QAChB;AAAA,QACA,WAAW;AACP,iBAAO,KAAK,aAAa,KAAK,KAAK;AAAA,QACvC;AAAA,QACA,mBAAmB;AACf,iBAAO,KAAK,eAAe,eAAe;AAAA,QAC9C;AAAA,QACA,oBAAoB;AAChB,iBAAO,KAAK,gBAAgB,eAAe;AAAA,QAC/C;AAAA,QACA,YAAY;AACR,iBAAO,KAAK,eAAe,eAAe,QAAQ,KAAK,gBAAgB,eAAe;AAAA,QAC1F;AAAA,MACJ;AACA,qBAAe,OAAO;AAAA,MAEtB,MAAM,YAAY;AAAA,QACd,cAAc;AAAA,QACd;AAAA,QACA,OAAO,4BAA4B,gBAAgB;AAC/C,cAAI,CAAC,gBAAgB;AACjB,mBAAO;AAAA,UACX;AAEA,cAAI,eAAe,SAAS,GAAG;AAC3B,kBAAM,IAAI,kBAAkB;AAAA,UAChC;AACA,cAAI,iBAAiB,eAAe,UAAU,GAAG,CAAC;AAClD,mBAAS,cAAc,YAAY,uBAAuB;AACtD,gBAAI,WAAW,CAAC,MAAM,gBAAgB;AAClC,kBAAI,WAAW,CAAC,MAAM,YAAY,iBAAiB;AAC/C,uBAAO,YAAY,kBAAkB,GAAG,WAAW,CAAC,GAAG,cAAc;AAAA,cACzE;AACA,qBAAO,YAAY,eAAe,GAAG,WAAW,CAAC,GAAG,cAAc;AAAA,YACtE;AAAA,UACJ;AACA,cAAI,eAAe,SAAS,GAAG;AAC3B,kBAAM,IAAI,kBAAkB;AAAA,UAChC;AACA,cAAI,mBAAmB,eAAe,UAAU,GAAG,CAAC;AACpD,mBAAS,cAAc,YAAY,yBAAyB;AACxD,gBAAI,WAAW,CAAC,MAAM,kBAAkB;AACpC,kBAAI,WAAW,CAAC,MAAM,YAAY,iBAAiB;AAC/C,uBAAO,YAAY,kBAAkB,GAAG,WAAW,CAAC,GAAG,cAAc;AAAA,cACzE;AACA,qBAAO,YAAY,eAAe,GAAG,WAAW,CAAC,GAAG,cAAc;AAAA,YACtE;AAAA,UACJ;AACA,mBAAS,cAAc,YAAY,oCAAoC;AACnE,gBAAI,WAAW,CAAC,MAAM,kBAAkB;AACpC,kBAAI,WAAW,CAAC,MAAM,YAAY,iBAAiB;AAC/C,uBAAO,YAAY,kBAAkB,GAAG,WAAW,CAAC,GAAG,cAAc;AAAA,cACzE;AACA,qBAAO,YAAY,eAAe,GAAG,WAAW,CAAC,GAAG,cAAc;AAAA,YACtE;AAAA,UACJ;AACA,cAAI,eAAe,SAAS,GAAG;AAC3B,kBAAM,IAAI,kBAAkB;AAAA,UAChC;AACA,cAAI,kBAAkB,eAAe,UAAU,GAAG,CAAC;AACnD,mBAAS,cAAc,YAAY,wBAAwB;AACvD,gBAAI,WAAW,CAAC,MAAM,iBAAiB;AACnC,kBAAI,WAAW,CAAC,MAAM,YAAY,iBAAiB;AAC/C,uBAAO,YAAY,kBAAkB,GAAG,WAAW,CAAC,GAAG,cAAc;AAAA,cACzE;AACA,qBAAO,YAAY,eAAe,GAAG,WAAW,CAAC,GAAG,cAAc;AAAA,YACtE;AAAA,UACJ;AACA,gBAAM,IAAI,kBAAkB;AAAA,QAChC;AAAA,QACA,OAAO,eAAe,QAAQ,WAAW,gBAAgB;AACrD,cAAI,eAAe,SAAS,QAAQ;AAChC,kBAAM,IAAI,kBAAkB;AAAA,UAChC;AACA,cAAI,KAAK,eAAe,UAAU,GAAG,MAAM;AAC3C,cAAI,eAAe,SAAS,SAAS,WAAW;AAC5C,kBAAM,IAAI,kBAAkB;AAAA,UAChC;AACA,cAAI,QAAQ,eAAe,UAAU,QAAQ,SAAS,SAAS;AAC/D,cAAI,YAAY,eAAe,UAAU,SAAS,SAAS;AAC3D,cAAI,SAAS,MAAM,KAAK,MAAM;AAC9B,cAAI,WAAW,YAAY,4BAA4B,SAAS;AAChE,iBAAO,YAAY,OAAO,SAAS,SAAS;AAAA,QAChD;AAAA,QACA,OAAO,kBAAkB,QAAQ,mBAAmB,gBAAgB;AAChE,cAAI,KAAK,eAAe,UAAU,GAAG,MAAM;AAC3C,cAAI;AACJ,cAAI,eAAe,SAAS,SAAS,mBAAmB;AACpD,sBAAU,eAAe;AAAA,UAC7B,OACK;AACD,sBAAU,SAAS;AAAA,UACvB;AACA,cAAI,QAAQ,eAAe,UAAU,QAAQ,OAAO;AACpD,cAAI,YAAY,eAAe,UAAU,OAAO;AAChD,cAAI,SAAS,MAAM,KAAK,MAAM;AAC9B,cAAI,WAAW,YAAY,4BAA4B,SAAS;AAChE,iBAAO,YAAY,OAAO,SAAS,SAAS;AAAA,QAChD;AAAA,MACJ;AACA,kBAAY,kBAAkB,CAAC;AAC/B,kBAAY,wBAAwB;AAAA,QAChC,CAAC,MAAM,EAAE;AAAA,QACT,CAAC,MAAM,EAAE;AAAA,QACT,CAAC,MAAM,EAAE;AAAA,QACT,CAAC,MAAM,YAAY,iBAAiB,EAAE;AAAA,QACtC,CAAC,MAAM,CAAC;AAAA,QACR,CAAC,MAAM,CAAC;AAAA,QACR,CAAC,MAAM,CAAC;AAAA,QACR,CAAC,MAAM,CAAC;AAAA,QACR,CAAC,MAAM,CAAC;AAAA,QACR,CAAC,MAAM,CAAC;AAAA,QACR,CAAC,MAAM,YAAY,iBAAiB,EAAE;AAAA,QACtC,CAAC,MAAM,YAAY,iBAAiB,EAAE;AAAA,QACtC,CAAC,MAAM,YAAY,iBAAiB,CAAC;AAAA,QACrC,CAAC,MAAM,YAAY,iBAAiB,CAAC;AAAA;AAAA,QAErC,CAAC,MAAM,YAAY,iBAAiB,EAAE;AAAA,QACtC,CAAC,MAAM,YAAY,iBAAiB,EAAE;AAAA,QACtC,CAAC,MAAM,YAAY,iBAAiB,EAAE;AAAA,QACtC,CAAC,MAAM,YAAY,iBAAiB,EAAE;AAAA,QACtC,CAAC,MAAM,YAAY,iBAAiB,EAAE;AAAA,QACtC,CAAC,MAAM,YAAY,iBAAiB,EAAE;AAAA,QACtC,CAAC,MAAM,YAAY,iBAAiB,EAAE;AAAA,QACtC,CAAC,MAAM,YAAY,iBAAiB,CAAC;AAAA,QACrC,CAAC,MAAM,YAAY,iBAAiB,EAAE;AAAA,QACtC,CAAC,MAAM,YAAY,iBAAiB,EAAE;AAAA,MAC1C;AACA,kBAAY,0BAA0B;AAAA;AAAA,QAElC,CAAC,OAAO,YAAY,iBAAiB,EAAE;AAAA,QACvC,CAAC,OAAO,YAAY,iBAAiB,EAAE;AAAA,QACvC,CAAC,OAAO,YAAY,iBAAiB,CAAC;AAAA,QACtC,CAAC,OAAO,YAAY,iBAAiB,EAAE;AAAA,QACvC,CAAC,OAAO,YAAY,iBAAiB,EAAE;AAAA,QACvC,CAAC,OAAO,YAAY,iBAAiB,EAAE;AAAA,QACvC,CAAC,OAAO,YAAY,iBAAiB,EAAE;AAAA,QACvC,CAAC,OAAO,YAAY,iBAAiB,EAAE;AAAA,QACvC,CAAC,OAAO,YAAY,iBAAiB,EAAE;AAAA,QACvC,CAAC,OAAO,EAAE;AAAA,QACV,CAAC,OAAO,YAAY,iBAAiB,EAAE;AAAA,QACvC,CAAC,OAAO,EAAE;AAAA,QACV,CAAC,OAAO,EAAE;AAAA,QACV,CAAC,OAAO,EAAE;AAAA,QACV,CAAC,OAAO,EAAE;AAAA,QACV,CAAC,OAAO,EAAE;AAAA,QACV,CAAC,OAAO,YAAY,iBAAiB,EAAE;AAAA,QACvC,CAAC,OAAO,YAAY,iBAAiB,EAAE;AAAA,QACvC,CAAC,OAAO,CAAC;AAAA,QACT,CAAC,OAAO,YAAY,iBAAiB,EAAE;AAAA,QACvC,CAAC,OAAO,CAAC;AAAA,QACT,CAAC,OAAO,CAAC;AAAA,QACT,CAAC,OAAO,CAAC;AAAA,MACb;AACA,kBAAY,qCAAqC;AAAA;AAAA,QAE7C,CAAC,OAAO,CAAC;AAAA,QACT,CAAC,OAAO,CAAC;AAAA,QACT,CAAC,OAAO,CAAC;AAAA,QACT,CAAC,OAAO,CAAC;AAAA,QACT,CAAC,OAAO,CAAC;AAAA,QACT,CAAC,OAAO,CAAC;AAAA,QACT,CAAC,OAAO,CAAC;AAAA,QACT,CAAC,OAAO,CAAC;AAAA,QACT,CAAC,OAAO,CAAC;AAAA,QACT,CAAC,OAAO,CAAC;AAAA,QACT,CAAC,OAAO,CAAC;AAAA,QACT,CAAC,OAAO,CAAC;AAAA,QACT,CAAC,OAAO,CAAC;AAAA,QACT,CAAC,OAAO,CAAC;AAAA,QACT,CAAC,OAAO,CAAC;AAAA,QACT,CAAC,OAAO,CAAC;AAAA,QACT,CAAC,OAAO,CAAC;AAAA,QACT,CAAC,OAAO,CAAC;AAAA,QACT,CAAC,OAAO,CAAC;AAAA,QACT,CAAC,OAAO,CAAC;AAAA,QACT,CAAC,OAAO,CAAC;AAAA,QACT,CAAC,OAAO,CAAC;AAAA,QACT,CAAC,OAAO,CAAC;AAAA,QACT,CAAC,OAAO,CAAC;AAAA,QACT,CAAC,OAAO,CAAC;AAAA,QACT,CAAC,OAAO,CAAC;AAAA,QACT,CAAC,OAAO,CAAC;AAAA,QACT,CAAC,OAAO,CAAC;AAAA,QACT,CAAC,OAAO,CAAC;AAAA,QACT,CAAC,OAAO,CAAC;AAAA,QACT,CAAC,OAAO,CAAC;AAAA,QACT,CAAC,OAAO,CAAC;AAAA,QACT,CAAC,OAAO,CAAC;AAAA,QACT,CAAC,OAAO,CAAC;AAAA,QACT,CAAC,OAAO,CAAC;AAAA,QACT,CAAC,OAAO,CAAC;AAAA,QACT,CAAC,OAAO,CAAC;AAAA,QACT,CAAC,OAAO,CAAC;AAAA,QACT,CAAC,OAAO,CAAC;AAAA,QACT,CAAC,OAAO,CAAC;AAAA,QACT,CAAC,OAAO,CAAC;AAAA,QACT,CAAC,OAAO,CAAC;AAAA,QACT,CAAC,OAAO,CAAC;AAAA,QACT,CAAC,OAAO,CAAC;AAAA,QACT,CAAC,OAAO,CAAC;AAAA,QACT,CAAC,OAAO,CAAC;AAAA,QACT,CAAC,OAAO,CAAC;AAAA,QACT,CAAC,OAAO,CAAC;AAAA,QACT,CAAC,OAAO,CAAC;AAAA,QACT,CAAC,OAAO,CAAC;AAAA,QACT,CAAC,OAAO,CAAC;AAAA,QACT,CAAC,OAAO,CAAC;AAAA,QACT,CAAC,OAAO,YAAY,iBAAiB,EAAE;AAAA,QACvC,CAAC,OAAO,YAAY,iBAAiB,EAAE;AAAA,QACvC,CAAC,OAAO,YAAY,iBAAiB,EAAE;AAAA,QACvC,CAAC,OAAO,YAAY,iBAAiB,EAAE;AAAA,QACvC,CAAC,OAAO,YAAY,iBAAiB,EAAE;AAAA,MAC3C;AACA,kBAAY,yBAAyB;AAAA;AAAA,QAEjC,CAAC,QAAQ,EAAE;AAAA,QACX,CAAC,QAAQ,YAAY,iBAAiB,EAAE;AAAA,QACxC,CAAC,QAAQ,EAAE;AAAA,QACX,CAAC,QAAQ,EAAE;AAAA,QACX,CAAC,QAAQ,YAAY,iBAAiB,EAAE;AAAA,QACxC,CAAC,QAAQ,YAAY,iBAAiB,EAAE;AAAA,QACxC,CAAC,QAAQ,YAAY,iBAAiB,EAAE;AAAA,QACxC,CAAC,QAAQ,CAAC;AAAA,QACV,CAAC,QAAQ,EAAE;AAAA,QACX,CAAC,QAAQ,YAAY,iBAAiB,EAAE;AAAA,QACxC,CAAC,QAAQ,YAAY,iBAAiB,EAAE;AAAA,QACxC,CAAC,QAAQ,EAAE;AAAA,QACX,CAAC,QAAQ,YAAY,iBAAiB,EAAE;AAAA,QACxC,CAAC,QAAQ,CAAC;AAAA,QACV,CAAC,QAAQ,EAAE;AAAA,QACX,CAAC,QAAQ,CAAC;AAAA,QACV,CAAC,QAAQ,YAAY,iBAAiB,EAAE;AAAA,QACxC,CAAC,QAAQ,YAAY,iBAAiB,EAAE;AAAA,MAC5C;AAAA,MAEA,MAAM,oBAAoB;AAAA,QACtB,YAAY,aAAa;AACrB,eAAK,SAAS,IAAI,cAAc;AAChC,eAAK,cAAc;AAAA,QACvB;AAAA,QACA,eAAe,MAAM,iBAAiB;AAClC,cAAI,kBAAkB;AACtB,cAAI,YAAY;AAChB,aAAG;AACC,gBAAI,OAAO,KAAK,0BAA0B,iBAAiB,SAAS;AACpE,gBAAI,eAAe,YAAY,4BAA4B,KAAK,aAAa,CAAC;AAC9E,gBAAI,gBAAgB,MAAM;AACtB,mBAAK,OAAO,YAAY;AAAA,YAC5B;AACA,gBAAI,KAAK,YAAY,GAAG;AACpB,0BAAY,KAAK,KAAK,kBAAkB;AAAA,YAC5C,OACK;AACD,0BAAY;AAAA,YAChB;AACA,gBAAI,oBAAoB,KAAK,eAAe,GAAG;AAC3C;AAAA,YACJ;AACA,8BAAkB,KAAK,eAAe;AAAA,UAC1C,SAAS;AACT,iBAAO,KAAK,SAAS;AAAA,QACzB;AAAA,QACA,eAAe,KAAK;AAGhB,cAAI,MAAM,IAAI,KAAK,YAAY,QAAQ,GAAG;AACtC,mBAAO,MAAM,KAAK,KAAK,YAAY,QAAQ;AAAA,UAC/C;AACA,mBAAS,IAAI,KAAK,IAAI,MAAM,GAAG,EAAE,GAAG;AAChC,gBAAI,KAAK,YAAY,IAAI,CAAC,GAAG;AACzB,qBAAO;AAAA,YACX;AAAA,UACJ;AACA,iBAAO,KAAK,YAAY,IAAI,MAAM,CAAC;AAAA,QACvC;AAAA,QACA,cAAc,KAAK;AACf,cAAI,MAAM,IAAI,KAAK,YAAY,QAAQ,GAAG;AACtC,gBAAIO,WAAU,KAAK,gCAAgC,KAAK,CAAC;AACzD,gBAAIA,aAAY,GAAG;AACf,qBAAO,IAAI,eAAe,KAAK,YAAY,QAAQ,GAAG,eAAe,MAAM,eAAe,IAAI;AAAA,YAClG;AACA,mBAAO,IAAI,eAAe,KAAK,YAAY,QAAQ,GAAGA,WAAU,GAAG,eAAe,IAAI;AAAA,UAC1F;AACA,cAAI,UAAU,KAAK,gCAAgC,KAAK,CAAC;AACzD,cAAI,UAAU,UAAU,KAAK;AAC7B,cAAI,UAAU,UAAU,KAAK;AAC7B,iBAAO,IAAI,eAAe,MAAM,GAAG,QAAQ,MAAM;AAAA,QACrD;AAAA,QACA,gCAAgC,KAAK,MAAM;AACvC,iBAAO,oBAAoB,gCAAgC,KAAK,aAAa,KAAK,IAAI;AAAA,QAC1F;AAAA,QACA,OAAO,gCAAgC,aAAa,KAAK,MAAM;AAC3D,cAAI,QAAQ;AACZ,mBAAS,IAAI,GAAG,IAAI,MAAM,EAAE,GAAG;AAC3B,gBAAI,YAAY,IAAI,MAAM,CAAC,GAAG;AAC1B,uBAAS,KAAM,OAAO,IAAI;AAAA,YAC9B;AAAA,UACJ;AACA,iBAAO;AAAA,QACX;AAAA,QACA,0BAA0B,KAAK,WAAW;AAEtC,eAAK,OAAO,gBAAgB;AAC5B,cAAI,aAAa,MAAM;AACnB,iBAAK,OAAO,OAAO,SAAS;AAAA,UAChC;AACA,eAAK,QAAQ,YAAY,GAAG;AAC5B,cAAI,cAAc,KAAK,YAAY;AACnC,cAAI,eAAe,QAAQ,YAAY,YAAY,GAAG;AAClD,mBAAO,IAAI,mBAAmB,KAAK,QAAQ,YAAY,GAAG,KAAK,OAAO,SAAS,GAAG,YAAY,kBAAkB,CAAC;AAAA,UACrH;AACA,iBAAO,IAAI,mBAAmB,KAAK,QAAQ,YAAY,GAAG,KAAK,OAAO,SAAS,CAAC;AAAA,QACpF;AAAA,QACA,cAAc;AACV,cAAI;AACJ,cAAI;AACJ,aAAG;AACC,gBAAI,kBAAkB,KAAK,QAAQ,YAAY;AAC/C,gBAAI,KAAK,QAAQ,QAAQ,GAAG;AACxB,uBAAS,KAAK,gBAAgB;AAC9B,2BAAa,OAAO,WAAW;AAAA,YACnC,WACS,KAAK,QAAQ,YAAY,GAAG;AACjC,uBAAS,KAAK,oBAAoB;AAClC,2BAAa,OAAO,WAAW;AAAA,YACnC,OACK;AACD,uBAAS,KAAK,kBAAkB;AAChC,2BAAa,OAAO,WAAW;AAAA,YACnC;AACA,gBAAI,kBAAkB,oBAAoB,KAAK,QAAQ,YAAY;AACnE,gBAAI,CAAC,mBAAmB,CAAC,YAAY;AACjC;AAAA,YACJ;AAAA,UACJ,SAAS,CAAC;AACV,iBAAO,OAAO,sBAAsB;AAAA,QACxC;AAAA,QACA,oBAAoB;AAChB,iBAAO,KAAK,eAAe,KAAK,QAAQ,YAAY,CAAC,GAAG;AACpD,gBAAI,UAAU,KAAK,cAAc,KAAK,QAAQ,YAAY,CAAC;AAC3D,iBAAK,QAAQ,YAAY,QAAQ,eAAe,CAAC;AACjD,gBAAI,QAAQ,iBAAiB,GAAG;AAC5B,kBAAI;AACJ,kBAAI,QAAQ,kBAAkB,GAAG;AAC7B,8BAAc,IAAI,mBAAmB,KAAK,QAAQ,YAAY,GAAG,KAAK,OAAO,SAAS,CAAC;AAAA,cAC3F,OACK;AACD,8BAAc,IAAI,mBAAmB,KAAK,QAAQ,YAAY,GAAG,KAAK,OAAO,SAAS,GAAG,QAAQ,eAAe,CAAC;AAAA,cACrH;AACA,qBAAO,IAAI,kBAAkB,MAAM,WAAW;AAAA,YAClD;AACA,iBAAK,OAAO,OAAO,QAAQ,cAAc,CAAC;AAC1C,gBAAI,QAAQ,kBAAkB,GAAG;AAC7B,kBAAI,cAAc,IAAI,mBAAmB,KAAK,QAAQ,YAAY,GAAG,KAAK,OAAO,SAAS,CAAC;AAC3F,qBAAO,IAAI,kBAAkB,MAAM,WAAW;AAAA,YAClD;AACA,iBAAK,OAAO,OAAO,QAAQ,eAAe,CAAC;AAAA,UAC/C;AACA,cAAI,KAAK,6BAA6B,KAAK,QAAQ,YAAY,CAAC,GAAG;AAC/D,iBAAK,QAAQ,SAAS;AACtB,iBAAK,QAAQ,kBAAkB,CAAC;AAAA,UACpC;AACA,iBAAO,IAAI,kBAAkB,KAAK;AAAA,QACtC;AAAA,QACA,sBAAsB;AAClB,iBAAO,KAAK,iBAAiB,KAAK,QAAQ,YAAY,CAAC,GAAG;AACtD,gBAAI,MAAM,KAAK,gBAAgB,KAAK,QAAQ,YAAY,CAAC;AACzD,iBAAK,QAAQ,YAAY,IAAI,eAAe,CAAC;AAC7C,gBAAI,IAAI,OAAO,GAAG;AACd,kBAAI,cAAc,IAAI,mBAAmB,KAAK,QAAQ,YAAY,GAAG,KAAK,OAAO,SAAS,CAAC;AAC3F,qBAAO,IAAI,kBAAkB,MAAM,WAAW;AAAA,YAClD;AACA,iBAAK,OAAO,OAAO,IAAI,SAAS,CAAC;AAAA,UACrC;AACA,cAAI,KAAK,2BAA2B,KAAK,QAAQ,YAAY,CAAC,GAAG;AAC7D,iBAAK,QAAQ,kBAAkB,CAAC;AAChC,iBAAK,QAAQ,WAAW;AAAA,UAC5B,WACS,KAAK,yBAAyB,KAAK,QAAQ,YAAY,CAAC,GAAG;AAChE,gBAAI,KAAK,QAAQ,YAAY,IAAI,IAAI,KAAK,YAAY,QAAQ,GAAG;AAC7D,mBAAK,QAAQ,kBAAkB,CAAC;AAAA,YACpC,OACK;AACD,mBAAK,QAAQ,YAAY,KAAK,YAAY,QAAQ,CAAC;AAAA,YACvD;AACA,iBAAK,QAAQ,SAAS;AAAA,UAC1B;AACA,iBAAO,IAAI,kBAAkB,KAAK;AAAA,QACtC;AAAA,QACA,kBAAkB;AACd,iBAAO,KAAK,aAAa,KAAK,QAAQ,YAAY,CAAC,GAAG;AAClD,gBAAI,QAAQ,KAAK,mBAAmB,KAAK,QAAQ,YAAY,CAAC;AAC9D,iBAAK,QAAQ,YAAY,MAAM,eAAe,CAAC;AAC/C,gBAAI,MAAM,OAAO,GAAG;AAChB,kBAAI,cAAc,IAAI,mBAAmB,KAAK,QAAQ,YAAY,GAAG,KAAK,OAAO,SAAS,CAAC;AAC3F,qBAAO,IAAI,kBAAkB,MAAM,WAAW;AAAA,YAClD;AACA,iBAAK,OAAO,OAAO,MAAM,SAAS,CAAC;AAAA,UACvC;AACA,cAAI,KAAK,2BAA2B,KAAK,QAAQ,YAAY,CAAC,GAAG;AAC7D,iBAAK,QAAQ,kBAAkB,CAAC;AAChC,iBAAK,QAAQ,WAAW;AAAA,UAC5B,WACS,KAAK,yBAAyB,KAAK,QAAQ,YAAY,CAAC,GAAG;AAChE,gBAAI,KAAK,QAAQ,YAAY,IAAI,IAAI,KAAK,YAAY,QAAQ,GAAG;AAC7D,mBAAK,QAAQ,kBAAkB,CAAC;AAAA,YACpC,OACK;AACD,mBAAK,QAAQ,YAAY,KAAK,YAAY,QAAQ,CAAC;AAAA,YACvD;AACA,iBAAK,QAAQ,aAAa;AAAA,UAC9B;AACA,iBAAO,IAAI,kBAAkB,KAAK;AAAA,QACtC;AAAA,QACA,iBAAiB,KAAK;AAClB,cAAI,MAAM,IAAI,KAAK,YAAY,QAAQ,GAAG;AACtC,mBAAO;AAAA,UACX;AACA,cAAI,eAAe,KAAK,gCAAgC,KAAK,CAAC;AAC9D,cAAI,gBAAgB,KAAK,eAAe,IAAI;AACxC,mBAAO;AAAA,UACX;AACA,cAAI,MAAM,IAAI,KAAK,YAAY,QAAQ,GAAG;AACtC,mBAAO;AAAA,UACX;AACA,cAAI,gBAAgB,KAAK,gCAAgC,KAAK,CAAC;AAC/D,cAAI,iBAAiB,MAAM,gBAAgB,KAAK;AAC5C,mBAAO;AAAA,UACX;AACA,cAAI,MAAM,IAAI,KAAK,YAAY,QAAQ,GAAG;AACtC,mBAAO;AAAA,UACX;AACA,cAAI,gBAAgB,KAAK,gCAAgC,KAAK,CAAC;AAC/D,iBAAO,iBAAiB,OAAO,gBAAgB;AAAA,QACnD;AAAA,QACA,gBAAgB,KAAK;AACjB,cAAI,eAAe,KAAK,gCAAgC,KAAK,CAAC;AAC9D,cAAI,iBAAiB,IAAI;AACrB,mBAAO,IAAI,YAAY,MAAM,GAAG,YAAY,IAAI;AAAA,UACpD;AACA,cAAI,gBAAgB,KAAK,eAAe,IAAI;AACxC,mBAAO,IAAI,YAAY,MAAM,GAAI,OAAO,eAAe,EAAG;AAAA,UAC9D;AACA,cAAI,gBAAgB,KAAK,gCAAgC,KAAK,CAAC;AAC/D,cAAI,iBAAiB,MAAM,gBAAgB,IAAI;AAC3C,mBAAO,IAAI,YAAY,MAAM,GAAI,MAAM,gBAAgB,EAAG;AAAA,UAC9D;AACA,cAAI,iBAAiB,MAAM,gBAAgB,KAAK;AAC5C,mBAAO,IAAI,YAAY,MAAM,GAAI,MAAM,gBAAgB,EAAG;AAAA,UAC9D;AACA,cAAI,gBAAgB,KAAK,gCAAgC,KAAK,CAAC;AAC/D,cAAI;AACJ,kBAAQ,eAAe;AAAA,YACnB,KAAK;AACD,kBAAI;AACJ;AAAA,YACJ,KAAK;AACD,kBAAI;AACJ;AAAA,YACJ,KAAK;AACD,kBAAI;AACJ;AAAA,YACJ,KAAK;AACD,kBAAI;AACJ;AAAA,YACJ,KAAK;AACD,kBAAI;AACJ;AAAA,YACJ,KAAK;AACD,kBAAI;AACJ;AAAA,YACJ,KAAK;AACD,kBAAI;AACJ;AAAA,YACJ,KAAK;AACD,kBAAI;AACJ;AAAA,YACJ,KAAK;AACD,kBAAI;AACJ;AAAA,YACJ,KAAK;AACD,kBAAI;AACJ;AAAA,YACJ,KAAK;AACD,kBAAI;AACJ;AAAA,YACJ,KAAK;AACD,kBAAI;AACJ;AAAA,YACJ,KAAK;AACD,kBAAI;AACJ;AAAA,YACJ,KAAK;AACD,kBAAI;AACJ;AAAA,YACJ,KAAK;AACD,kBAAI;AACJ;AAAA,YACJ,KAAK;AACD,kBAAI;AACJ;AAAA,YACJ,KAAK;AACD,kBAAI;AACJ;AAAA,YACJ,KAAK;AACD,kBAAI;AACJ;AAAA,YACJ,KAAK;AACD,kBAAI;AACJ;AAAA,YACJ,KAAK;AACD,kBAAI;AACJ;AAAA,YACJ,KAAK;AACD,kBAAI;AACJ;AAAA,YACJ;AACI,oBAAM,IAAI,gBAAgB;AAAA,UAClC;AACA,iBAAO,IAAI,YAAY,MAAM,GAAG,CAAC;AAAA,QACrC;AAAA,QACA,aAAa,KAAK;AACd,cAAI,MAAM,IAAI,KAAK,YAAY,QAAQ,GAAG;AACtC,mBAAO;AAAA,UACX;AAEA,cAAI,eAAe,KAAK,gCAAgC,KAAK,CAAC;AAC9D,cAAI,gBAAgB,KAAK,eAAe,IAAI;AACxC,mBAAO;AAAA,UACX;AACA,cAAI,MAAM,IAAI,KAAK,YAAY,QAAQ,GAAG;AACtC,mBAAO;AAAA,UACX;AACA,cAAI,cAAc,KAAK,gCAAgC,KAAK,CAAC;AAC7D,iBAAO,eAAe,MAAM,cAAc;AAAA,QAC9C;AAAA,QACA,mBAAmB,KAAK;AACpB,cAAI,eAAe,KAAK,gCAAgC,KAAK,CAAC;AAC9D,cAAI,iBAAiB,IAAI;AACrB,mBAAO,IAAI,YAAY,MAAM,GAAG,YAAY,IAAI;AAAA,UACpD;AACA,cAAI,gBAAgB,KAAK,eAAe,IAAI;AACxC,mBAAO,IAAI,YAAY,MAAM,GAAI,OAAO,eAAe,EAAG;AAAA,UAC9D;AACA,cAAI,cAAc,KAAK,gCAAgC,KAAK,CAAC;AAC7D,cAAI,eAAe,MAAM,cAAc,IAAI;AACvC,mBAAO,IAAI,YAAY,MAAM,GAAI,MAAM,cAAc,GAAI;AAAA,UAC7D;AACA,cAAI;AACJ,kBAAQ,aAAa;AAAA,YACjB,KAAK;AACD,kBAAI;AACJ;AAAA,YACJ,KAAK;AACD,kBAAI;AACJ;AAAA,YACJ,KAAK;AACD,kBAAI;AACJ;AAAA,YACJ,KAAK;AACD,kBAAI;AACJ;AAAA,YACJ,KAAK;AACD,kBAAI;AACJ;AAAA,YACJ;AACI,oBAAM,IAAI,sBAAsB,0CAA0C,WAAW;AAAA,UAC7F;AACA,iBAAO,IAAI,YAAY,MAAM,GAAG,CAAC;AAAA,QACrC;AAAA,QACA,yBAAyB,KAAK;AAC1B,cAAI,MAAM,IAAI,KAAK,YAAY,QAAQ,GAAG;AACtC,mBAAO;AAAA,UACX;AACA,mBAAS,IAAI,GAAG,IAAI,KAAK,IAAI,MAAM,KAAK,YAAY,QAAQ,GAAG,EAAE,GAAG;AAChE,gBAAI,MAAM,GAAG;AACT,kBAAI,CAAC,KAAK,YAAY,IAAI,MAAM,CAAC,GAAG;AAChC,uBAAO;AAAA,cACX;AAAA,YACJ,WACS,KAAK,YAAY,IAAI,MAAM,CAAC,GAAG;AACpC,qBAAO;AAAA,YACX;AAAA,UACJ;AACA,iBAAO;AAAA,QACX;AAAA,QACA,2BAA2B,KAAK;AAE5B,cAAI,MAAM,IAAI,KAAK,YAAY,QAAQ,GAAG;AACtC,mBAAO;AAAA,UACX;AACA,mBAAS,IAAI,KAAK,IAAI,MAAM,GAAG,EAAE,GAAG;AAChC,gBAAI,KAAK,YAAY,IAAI,CAAC,GAAG;AACzB,qBAAO;AAAA,YACX;AAAA,UACJ;AACA,iBAAO;AAAA,QACX;AAAA,QACA,6BAA6B,KAAK;AAG9B,cAAI,MAAM,IAAI,KAAK,YAAY,QAAQ,GAAG;AACtC,mBAAO;AAAA,UACX;AACA,mBAAS,IAAI,GAAG,IAAI,KAAK,IAAI,MAAM,KAAK,YAAY,QAAQ,GAAG,EAAE,GAAG;AAChE,gBAAI,KAAK,YAAY,IAAI,MAAM,CAAC,GAAG;AAC/B,qBAAO;AAAA,YACX;AAAA,UACJ;AACA,iBAAO;AAAA,QACX;AAAA,MACJ;AAAA,MAEA,MAAM,wBAAwB;AAAA,QAC1B,YAAY,aAAa;AACrB,eAAK,cAAc;AACnB,eAAK,iBAAiB,IAAI,oBAAoB,WAAW;AAAA,QAC7D;AAAA,QACA,iBAAiB;AACb,iBAAO,KAAK;AAAA,QAChB;AAAA,QACA,oBAAoB;AAChB,iBAAO,KAAK;AAAA,QAChB;AAAA,MACJ;AAAA,MAEA,MAAM,oBAAoB,wBAAwB;AAAA,QAC9C,YAAY,aAAa;AACrB,gBAAM,WAAW;AAAA,QACrB;AAAA,QACA,qBAAqB,KAAK,YAAY;AAClC,cAAI,OAAO,MAAM;AACjB,cAAI,kBAAkB,IAAI,OAAO;AACjC,cAAI,OAAO,GAAG;AACd,eAAK,8BAA8B,KAAK,YAAY,eAAe;AAAA,QACvE;AAAA,QACA,8BAA8B,KAAK,YAAY,uBAAuB;AAClE,mBAAS,IAAI,GAAG,IAAI,GAAG,EAAE,GAAG;AACxB,gBAAI,eAAe,KAAK,kBAAkB,EAAE,gCAAgC,aAAa,KAAK,GAAG,EAAE;AACnG,gBAAI,eAAe,QAAQ,GAAG;AAC1B,kBAAI,OAAO,GAAG;AAAA,YAClB;AACA,gBAAI,eAAe,OAAO,GAAG;AACzB,kBAAI,OAAO,GAAG;AAAA,YAClB;AACA,gBAAI,OAAO,YAAY;AAAA,UAC3B;AACA,sBAAY,iBAAiB,KAAK,qBAAqB;AAAA,QAC3D;AAAA,QACA,OAAO,iBAAiB,KAAK,YAAY;AACrC,cAAI,aAAa;AACjB,mBAAS,IAAI,GAAG,IAAI,IAAI,KAAK;AAGzB,gBAAI,QAAQ,IAAI,OAAO,IAAI,UAAU,EAAE,WAAW,CAAC,IAAI,IAAI,WAAW,CAAC;AACvE,2BAAe,IAAI,OAAU,IAAI,IAAI,QAAQ;AAAA,UACjD;AACA,uBAAa,KAAM,aAAa;AAChC,cAAI,eAAe,IAAI;AACnB,yBAAa;AAAA,UACjB;AACA,cAAI,OAAO,UAAU;AAAA,QACzB;AAAA,MACJ;AACA,kBAAY,YAAY;AAAA,MAExB,MAAM,wBAAwB,YAAY;AAAA;AAAA,QAEtC,YAAY,aAAa;AACrB,gBAAM,WAAW;AAAA,QACrB;AAAA,QACA,mBAAmB;AACf,cAAI,OAAO,IAAI,cAAc;AAC7B,eAAK,OAAO,MAAM;AAClB,cAAI,sBAAsB,KAAK,OAAO;AACtC,cAAI,iBAAiB,KAAK,kBAAkB,EAAE,gCAAgC,gBAAgB,aAAa,CAAC;AAC5G,eAAK,OAAO,cAAc;AAC1B,eAAK,8BAA8B,MAAM,gBAAgB,cAAc,GAAG,mBAAmB;AAC7F,iBAAO,KAAK,kBAAkB,EAAE,eAAe,MAAM,gBAAgB,cAAc,EAAE;AAAA,QACzF;AAAA,MACJ;AACA,sBAAgB,cAAc,IAAI,IAAI;AAAA,MAEtC,MAAM,qBAAqB,wBAAwB;AAAA,QAC/C,YAAY,aAAa;AACrB,gBAAM,WAAW;AAAA,QACrB;AAAA,QACA,mBAAmB;AACf,cAAI,MAAM,IAAI,cAAc;AAC5B,iBAAO,KAAK,kBAAkB,EAAE,eAAe,KAAK,aAAa,WAAW;AAAA,QAChF;AAAA,MACJ;AACA,mBAAa,cAAc,IAAI,IAAI;AAAA,MAEnC,MAAM,0BAA0B,YAAY;AAAA,QACxC,YAAY,aAAa;AACrB,gBAAM,WAAW;AAAA,QACrB;AAAA,QACA,uBAAuB,KAAK,YAAY,YAAY;AAChD,cAAI,wBAAwB,KAAK,kBAAkB,EAAE,gCAAgC,YAAY,UAAU;AAC3G,eAAK,cAAc,KAAK,qBAAqB;AAC7C,cAAI,gBAAgB,KAAK,YAAY,qBAAqB;AAC1D,cAAI,iBAAiB;AACrB,mBAAS,IAAI,GAAG,IAAI,GAAG,EAAE,GAAG;AACxB,gBAAI,gBAAgB,mBAAmB,GAAG;AACtC,kBAAI,OAAO,GAAG;AAAA,YAClB;AACA,8BAAkB;AAAA,UACtB;AACA,cAAI,OAAO,aAAa;AAAA,QAC5B;AAAA,MACJ;AAAA,MAEA,MAAM,wBAAwB,kBAAkB;AAAA,QAC5C,YAAY,aAAa;AACrB,gBAAM,WAAW;AAAA,QACrB;AAAA,QACA,mBAAmB;AACf,cAAI,KAAK,eAAe,EAAE,QAAQ,KAAK,gBAAgB,cAAc,kBAAkB,YAAY,gBAAgB,aAAa;AAC5H,kBAAM,IAAI,kBAAkB;AAAA,UAChC;AACA,cAAI,MAAM,IAAI,cAAc;AAC5B,eAAK,qBAAqB,KAAK,gBAAgB,WAAW;AAC1D,eAAK,uBAAuB,KAAK,gBAAgB,cAAc,kBAAkB,WAAW,gBAAgB,WAAW;AACvH,iBAAO,IAAI,SAAS;AAAA,QACxB;AAAA,MACJ;AACA,sBAAgB,cAAc,IAAI;AAClC,sBAAgB,cAAc;AAAA,MAE9B,MAAM,wBAAwB,gBAAgB;AAAA,QAC1C,YAAY,aAAa;AACrB,gBAAM,WAAW;AAAA,QACrB;AAAA,QACA,cAAc,KAAK,QAAQ;AACvB,cAAI,OAAO,QAAQ;AAAA,QACvB;AAAA,QACA,YAAY,QAAQ;AAChB,iBAAO;AAAA,QACX;AAAA,MACJ;AAAA,MAEA,MAAM,wBAAwB,gBAAgB;AAAA,QAC1C,YAAY,aAAa;AACrB,gBAAM,WAAW;AAAA,QACrB;AAAA,QACA,cAAc,KAAK,QAAQ;AACvB,cAAI,SAAS,KAAO;AAChB,gBAAI,OAAO,QAAQ;AAAA,UACvB,OACK;AACD,gBAAI,OAAO,QAAQ;AAAA,UACvB;AAAA,QACJ;AAAA,QACA,YAAY,QAAQ;AAChB,cAAI,SAAS,KAAO;AAChB,mBAAO;AAAA,UACX;AACA,iBAAO,SAAS;AAAA,QACpB;AAAA,MACJ;AAAA,MAEA,MAAM,wBAAwB,YAAY;AAAA,QACtC,YAAY,aAAa;AACrB,gBAAM,WAAW;AAAA,QACrB;AAAA,QACA,mBAAmB;AACf,cAAI,KAAK,eAAe,EAAE,QAAQ,IAAI,gBAAgB,cAAc,YAAY,WAAW;AACvF,kBAAM,IAAI,kBAAkB;AAAA,UAChC;AACA,cAAI,MAAM,IAAI,cAAc;AAC5B,eAAK,qBAAqB,KAAK,gBAAgB,WAAW;AAC1D,cAAI,cAAc,KAAK,kBAAkB,EAAE,gCAAgC,gBAAgB,cAAc,YAAY,WAAW,gBAAgB,eAAe;AAC/J,cAAI,OAAO,MAAM;AACjB,cAAI,OAAO,WAAW;AACtB,cAAI,OAAO,GAAG;AACd,cAAI,qBAAqB,KAAK,kBAAkB,EAAE,0BAA0B,gBAAgB,cAAc,YAAY,YAAY,gBAAgB,iBAAiB,IAAI;AACvK,cAAI,OAAO,mBAAmB,aAAa,CAAC;AAC5C,iBAAO,IAAI,SAAS;AAAA,QACxB;AAAA,MACJ;AACA,sBAAgB,cAAc,IAAI,IAAI;AACtC,sBAAgB,kBAAkB;AAAA,MAElC,MAAM,wBAAwB,YAAY;AAAA,QACtC,YAAY,aAAa;AACrB,gBAAM,WAAW;AAAA,QACrB;AAAA,QACA,mBAAmB;AACf,cAAI,KAAK,eAAe,EAAE,QAAQ,IAAI,gBAAgB,cAAc,YAAY,WAAW;AACvF,kBAAM,IAAI,kBAAkB;AAAA,UAChC;AACA,cAAI,MAAM,IAAI,cAAc;AAC5B,eAAK,qBAAqB,KAAK,gBAAgB,WAAW;AAC1D,cAAI,cAAc,KAAK,kBAAkB,EAAE,gCAAgC,gBAAgB,cAAc,YAAY,WAAW,gBAAgB,eAAe;AAC/J,cAAI,OAAO,MAAM;AACjB,cAAI,OAAO,WAAW;AACtB,cAAI,OAAO,GAAG;AACd,cAAI,mBAAmB,KAAK,kBAAkB,EAAE,gCAAgC,gBAAgB,cAAc,YAAY,YAAY,gBAAgB,iBAAiB,gBAAgB,uBAAuB;AAC9M,cAAI,mBAAmB,OAAO,GAAG;AAC7B,gBAAI,OAAO,GAAG;AAAA,UAClB;AACA,cAAI,mBAAmB,MAAM,GAAG;AAC5B,gBAAI,OAAO,GAAG;AAAA,UAClB;AACA,cAAI,OAAO,gBAAgB;AAC3B,cAAI,qBAAqB,KAAK,kBAAkB,EAAE,0BAA0B,gBAAgB,cAAc,YAAY,YAAY,gBAAgB,kBAAkB,gBAAgB,yBAAyB,IAAI;AACjN,cAAI,OAAO,mBAAmB,aAAa,CAAC;AAC5C,iBAAO,IAAI,SAAS;AAAA,QACxB;AAAA,MACJ;AACA,sBAAgB,cAAc,IAAI,IAAI;AACtC,sBAAgB,kBAAkB;AAClC,sBAAgB,0BAA0B;AAAA,MAE1C,MAAM,0BAA0B,kBAAkB;AAAA,QAC9C,YAAY,aAAa,eAAe,UAAU;AAC9C,gBAAM,WAAW;AACjB,eAAK,WAAW;AAChB,eAAK,gBAAgB;AAAA,QACzB;AAAA,QACA,mBAAmB;AACf,cAAI,KAAK,eAAe,EAAE,QAAQ,KAAK,kBAAkB,cAAc,kBAAkB,YAAY,kBAAkB,cAAc,kBAAkB,WAAW;AAC9J,kBAAM,IAAI,kBAAkB;AAAA,UAChC;AACA,cAAI,MAAM,IAAI,cAAc;AAC5B,eAAK,qBAAqB,KAAK,kBAAkB,WAAW;AAC5D,eAAK,uBAAuB,KAAK,kBAAkB,cAAc,kBAAkB,WAAW,kBAAkB,WAAW;AAC3H,eAAK,qBAAqB,KAAK,kBAAkB,cAAc,kBAAkB,YAAY,kBAAkB,WAAW;AAC1H,iBAAO,IAAI,SAAS;AAAA,QACxB;AAAA,QACA,qBAAqB,KAAK,YAAY;AAClC,cAAI,cAAc,KAAK,kBAAkB,EAAE,gCAAgC,YAAY,kBAAkB,SAAS;AAClH,cAAI,eAAe,OAAO;AACtB;AAAA,UACJ;AACA,cAAI,OAAO,GAAG;AACd,cAAI,OAAO,KAAK,QAAQ;AACxB,cAAI,OAAO,GAAG;AACd,cAAI,MAAM,cAAc;AACxB,yBAAe;AACf,cAAI,QAAQ,cAAc,KAAK;AAC/B,yBAAe;AACf,cAAI,OAAO;AACX,cAAI,OAAO,MAAM,GAAG;AAChB,gBAAI,OAAO,GAAG;AAAA,UAClB;AACA,cAAI,OAAO,IAAI;AACf,cAAI,QAAQ,MAAM,GAAG;AACjB,gBAAI,OAAO,GAAG;AAAA,UAClB;AACA,cAAI,OAAO,KAAK;AAChB,cAAI,MAAM,MAAM,GAAG;AACf,gBAAI,OAAO,GAAG;AAAA,UAClB;AACA,cAAI,OAAO,GAAG;AAAA,QAClB;AAAA,QACA,cAAc,KAAK,QAAQ;AACvB,cAAI,OAAO,GAAG;AACd,cAAI,OAAO,KAAK,aAAa;AAC7B,cAAI,OAAO,SAAS,GAAM;AAC1B,cAAI,OAAO,GAAG;AAAA,QAClB;AAAA,QACA,YAAY,QAAQ;AAChB,iBAAO,SAAS;AAAA,QACpB;AAAA,MACJ;AACA,wBAAkB,cAAc,IAAI;AACpC,wBAAkB,cAAc;AAChC,wBAAkB,YAAY;AAE9B,eAAS,cAAc,aAAa;AAChC,YAAI;AACA,cAAI,YAAY,IAAI,CAAC,GAAG;AACpB,mBAAO,IAAI,gBAAgB,WAAW;AAAA,UAC1C;AACA,cAAI,CAAC,YAAY,IAAI,CAAC,GAAG;AACrB,mBAAO,IAAI,aAAa,WAAW;AAAA,UACvC;AACA,cAAI,0BAA0B,oBAAoB,gCAAgC,aAAa,GAAG,CAAC;AACnG,kBAAQ,yBAAyB;AAAA,YAC7B,KAAK;AAAG,qBAAO,IAAI,gBAAgB,WAAW;AAAA,YAC9C,KAAK;AAAG,qBAAO,IAAI,gBAAgB,WAAW;AAAA,UAClD;AACA,cAAI,0BAA0B,oBAAoB,gCAAgC,aAAa,GAAG,CAAC;AACnG,kBAAQ,yBAAyB;AAAA,YAC7B,KAAK;AAAI,qBAAO,IAAI,gBAAgB,WAAW;AAAA,YAC/C,KAAK;AAAI,qBAAO,IAAI,gBAAgB,WAAW;AAAA,UACnD;AACA,cAAI,2BAA2B,oBAAoB,gCAAgC,aAAa,GAAG,CAAC;AACpG,kBAAQ,0BAA0B;AAAA,YAC9B,KAAK;AAAI,qBAAO,IAAI,kBAAkB,aAAa,OAAO,IAAI;AAAA,YAC9D,KAAK;AAAI,qBAAO,IAAI,kBAAkB,aAAa,OAAO,IAAI;AAAA,YAC9D,KAAK;AAAI,qBAAO,IAAI,kBAAkB,aAAa,OAAO,IAAI;AAAA,YAC9D,KAAK;AAAI,qBAAO,IAAI,kBAAkB,aAAa,OAAO,IAAI;AAAA,YAC9D,KAAK;AAAI,qBAAO,IAAI,kBAAkB,aAAa,OAAO,IAAI;AAAA,YAC9D,KAAK;AAAI,qBAAO,IAAI,kBAAkB,aAAa,OAAO,IAAI;AAAA,YAC9D,KAAK;AAAI,qBAAO,IAAI,kBAAkB,aAAa,OAAO,IAAI;AAAA,YAC9D,KAAK;AAAI,qBAAO,IAAI,kBAAkB,aAAa,OAAO,IAAI;AAAA,UAClE;AAAA,QACJ,SACO,GAAG;AACN,kBAAQ,IAAI,CAAC;AACb,gBAAM,IAAI,sBAAsB,sBAAsB,WAAW;AAAA,QACrE;AAAA,MACJ;AAAA,MAEA,MAAM,aAAa;AAAA,QACf,YAAY,UAAU,WAAW,cAAc,WAAW;AACtD,eAAK,WAAW;AAChB,eAAK,YAAY;AACjB,eAAK,gBAAgB;AACrB,eAAK,YAAY;AAAA,QACrB;AAAA,QACA,YAAY;AACR,iBAAO,KAAK;AAAA,QAChB;AAAA,QACA,cAAc;AACV,iBAAO,KAAK;AAAA,QAChB;AAAA,QACA,eAAe;AACX,iBAAO,KAAK;AAAA,QAChB;AAAA,QACA,mBAAmB;AACf,iBAAO,KAAK;AAAA,QAChB;AAAA,QACA,aAAa;AACT,iBAAO,KAAK,aAAa;AAAA,QAC7B;AAAA,QACA,WAAW;AACP,iBAAO,OAAO,KAAK,WAAW,OAAO,KAAK,YAAY,SAAS,KAAK,iBAAiB,OAAO,SAAS,KAAK,cAAc,SAAS,KAAK;AAAA,QAC1I;AAAA,QACA,OAAO,OAAO,IAAI,IAAI;AAClB,cAAI,EAAE,cAAc,eAAe;AAC/B,mBAAO;AAAA,UACX;AACA,iBAAO,aAAa,aAAa,GAAG,UAAU,GAAG,QAAQ,KACrD,aAAa,aAAa,GAAG,WAAW,GAAG,SAAS,KACpD,aAAa,aAAa,GAAG,eAAe,GAAG,aAAa;AAAA,QACpE;AAAA,QACA,OAAO,aAAa,IAAI,IAAI;AACxB,iBAAO,OAAO,OAAO,OAAO,OAAO,aAAa,OAAO,IAAI,EAAE;AAAA,QACjE;AAAA,QACA,WAAW;AAEP,cAAI,QAAQ,KAAK,SAAS,SAAS,IAAI,KAAK,UAAU,SAAS,IAAI,KAAK,cAAc,SAAS;AAC/F,iBAAO;AAAA,QACX;AAAA,MACJ;AAAA,MAEA,MAAM,YAAY;AAAA,QACd,YAAY,OAAO,WAAW,aAAa;AACvC,eAAK,QAAQ;AACb,eAAK,YAAY;AACjB,eAAK,cAAc;AAAA,QACvB;AAAA,QACA,WAAW;AACP,iBAAO,KAAK;AAAA,QAChB;AAAA,QACA,eAAe;AACX,iBAAO,KAAK;AAAA,QAChB;AAAA,QACA,aAAa;AACT,iBAAO,KAAK;AAAA,QAChB;AAAA;AAAA,QAEA,aAAa,YAAY;AACrB,iBAAO,KAAK,gBAAgB,MAAM,UAAU;AAAA,QAChD;AAAA;AAAA,QAEA,WAAW;AACP,iBAAO,OAAO,KAAK,QAAQ;AAAA,QAC/B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAMA,OAAO,IAAI,IAAI;AACX,cAAI,EAAE,cAAc,cAAc;AAC9B,mBAAO;AAAA,UACX;AACA,iBAAO,KAAK,gBAAgB,IAAI,EAAE,KAAK,GAAG,gBAAgB,GAAG;AAAA,QACjE;AAAA,QACA,gBAAgB,OAAO,OAAO;AAC1B,cAAI,CAAC,SAAS,CAAC;AACX;AACJ,cAAI;AACJ,gBAAM,QAAQ,CAAC,IAAI,MAAM;AACrB,kBAAM,QAAQ,QAAM;AAChB,kBAAI,GAAG,YAAY,EAAE,SAAS,MAAM,GAAG,YAAY,EAAE,SAAS,KAAK,GAAG,aAAa,EAAE,SAAS,MAAM,GAAG,aAAa,EAAE,SAAS,KAAK,GAAG,gBAAgB,EAAE,SAAS,MAAM,GAAG,gBAAgB,EAAE,SAAS,GAAG;AACrM,yBAAS;AAAA,cACb;AAAA,YACJ,CAAC;AAAA,UACL,CAAC;AACD,iBAAO;AAAA,QACX;AAAA,MACJ;AAAA,MAOA,MAAM,0BAA0B,kBAAkB;AAAA,QAC9C,YAAY,SAAS;AACjB,gBAAM,GAAG,SAAS;AAClB,eAAK,QAAQ,IAAI,MAAM,kBAAkB,SAAS;AAClD,eAAK,OAAO,IAAI,MAAM;AACtB,eAAK,WAAW,CAAC,CAAC;AAClB,eAAK,UAAW,YAAY;AAAA,QAChC;AAAA,QACA,UAAU,WAAW,KAAK,OAAO;AAI7B,eAAK,MAAM,SAAS;AACpB,eAAK,gBAAgB;AACrB,cAAI;AACA,mBAAO,kBAAkB,gBAAgB,KAAK,gBAAgB,WAAW,GAAG,CAAC;AAAA,UACjF,SACO,GAAG;AAEN,gBAAI,KAAK,SAAS;AACd,sBAAQ,IAAI,CAAC;AAAA,YACjB;AAAA,UACJ;AACA,eAAK,MAAM,SAAS;AACpB,eAAK,gBAAgB;AACrB,iBAAO,kBAAkB,gBAAgB,KAAK,gBAAgB,WAAW,GAAG,CAAC;AAAA,QACjF;AAAA,QACA,QAAQ;AACJ,eAAK,MAAM,SAAS;AACpB,eAAK,KAAK,SAAS;AAAA,QACvB;AAAA;AAAA,QAEA,gBAAgB,WAAW,KAAK;AAC5B,cAAI,OAAO;AACX,iBAAO,CAAC,MAAM;AACV,gBAAI;AACA,mBAAK,MAAM,KAAK,KAAK,iBAAiB,KAAK,KAAK,OAAO,SAAS,CAAC;AAAA,YACrE,SACO,OAAO;AACV,kBAAI,iBAAiB,mBAAmB;AACpC,oBAAI,CAAC,KAAK,MAAM,QAAQ;AACpB,wBAAM,IAAI,kBAAkB;AAAA,gBAChC;AAEA,uBAAO;AAAA,cACX;AAAA,YACJ;AAAA,UACJ;AAEA,cAAI,KAAK,cAAc,GAAG;AACtB,mBAAO,KAAK;AAAA,UAChB;AACA,cAAI;AACJ,cAAI,KAAK,KAAK,QAAQ;AAClB,+BAAmB;AAAA,UACvB,OACK;AACD,+BAAmB;AAAA,UACvB;AAEA,eAAK,SAAS,WAAW,KAAK;AAC9B,cAAI,kBAAkB;AAGlB,gBAAI,KAAK,KAAK,iBAAiB,KAAK;AACpC,gBAAI,MAAM,MAAM;AACZ,qBAAO;AAAA,YACX;AACA,iBAAK,KAAK,iBAAiB,IAAI;AAC/B,gBAAI,MAAM,MAAM;AACZ,qBAAO;AAAA,YACX;AAAA,UACJ;AACA,gBAAM,IAAI,kBAAkB;AAAA,QAChC;AAAA;AAAA,QAEA,iBAAiB,SAAS;AAItB,cAAI,KAAK,KAAK,SAAS,IAAI;AACvB,iBAAK,KAAK,SAAS;AACnB,mBAAO;AAAA,UACX;AACA,eAAK,MAAM,SAAS;AACpB,cAAI,SAAS;AACT,iBAAK,OAAO,KAAK,KAAK,QAAQ;AAAA,UAElC;AACA,cAAI,KAAK;AACT,cAAI;AACA,iBAAK,KAAK,UAAU,IAAI,MAAM,GAAG,CAAC;AAAA,UACtC,SACO,GAAG;AAEN,gBAAI,KAAK,SAAS;AACd,sBAAQ,IAAI,CAAC;AAAA,YACjB;AAAA,UACJ;AACA,cAAI,SAAS;AACT,iBAAK,OAAO,KAAK,KAAK,QAAQ;AAAA,UAElC;AACA,iBAAO;AAAA,QACX;AAAA;AAAA;AAAA,QAGA,UAAU,eAAe,YAAY;AACjC,mBAAS,IAAI,YAAY,IAAI,KAAK,KAAK,QAAQ,KAAK;AAChD,gBAAI,MAAM,KAAK,KAAK,CAAC;AACrB,iBAAK,MAAM,SAAS;AACpB,qBAAS,gBAAgB,eAAe;AACpC,mBAAK,MAAM,KAAK,aAAa,SAAS,CAAC;AAAA,YAC3C;AACA,iBAAK,MAAM,KAAK,IAAI,SAAS,CAAC;AAC9B,gBAAI,CAAC,kBAAkB,gBAAgB,KAAK,KAAK,GAAG;AAChD;AAAA,YACJ;AACA,gBAAI,KAAK,cAAc,GAAG;AACtB,qBAAO,KAAK;AAAA,YAChB;AACA,gBAAI,KAAK,IAAI,MAAM,aAAa;AAChC,eAAG,KAAK,GAAG;AACX,gBAAI;AAEA,qBAAO,KAAK,UAAU,IAAI,IAAI,CAAC;AAAA,YACnC,SACO,GAAG;AAEN,kBAAI,KAAK,SAAS;AACd,wBAAQ,IAAI,CAAC;AAAA,cACjB;AAAA,YACJ;AAAA,UACJ;AACA,gBAAM,IAAI,kBAAkB;AAAA,QAChC;AAAA;AAAA;AAAA,QAGA,OAAO,gBAAgB,OAAO;AAC1B,mBAAS,YAAY,kBAAkB,0BAA0B;AAC7D,gBAAI,MAAM,SAAS,SAAS,QAAQ;AAChC;AAAA,YACJ;AACA,gBAAI,OAAO;AACX,qBAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;AACnC,kBAAI,MAAM,CAAC,EAAE,iBAAiB,EAAE,SAAS,KAAK,SAAS,CAAC,GAAG;AACvD,uBAAO;AACP;AAAA,cACJ;AAAA,YACJ;AACA,gBAAI,MAAM;AACN,qBAAO;AAAA,YACX;AAAA,UACJ;AACA,iBAAO;AAAA,QACX;AAAA,QACA,SAAS,WAAW,aAAa;AAE7B,cAAI,YAAY;AAChB,cAAI,aAAa;AACjB,cAAI,aAAa;AACjB,iBAAO,YAAY,KAAK,KAAK,QAAQ;AACjC,gBAAI,OAAO,KAAK,KAAK,SAAS;AAC9B,gBAAI,KAAK,aAAa,IAAI,WAAW;AACjC,2BAAa,KAAK,aAAa,KAAK,KAAK;AACzC;AAAA,YACJ;AACA,yBAAa,KAAK,aAAa,KAAK,KAAK;AACzC;AAAA,UACJ;AACA,cAAI,cAAc,YAAY;AAC1B;AAAA,UACJ;AAKA,cAAI,kBAAkB,aAAa,KAAK,OAAO,KAAK,IAAI,GAAG;AACvD;AAAA,UACJ;AACA,eAAK,KAAK,KAAK,WAAW,IAAI,YAAY,KAAK,OAAO,WAAW,WAAW,CAAC;AAC7E,eAAK,kBAAkB,KAAK,OAAO,KAAK,IAAI;AAAA,QAChD;AAAA;AAAA,QAEA,kBAAkB,OAAO,MAAM;AAyB3B,mBAAS,OAAO,MAAM;AAClB,gBAAI,IAAI,SAAS,EAAE,WAAW,MAAM,QAAQ;AACxC;AAAA,YACJ;AACA,qBAAS,KAAK,IAAI,SAAS,GAAG;AAC1B,uBAAS,MAAM,OAAO;AAClB,oBAAI,aAAa,OAAO,GAAG,EAAE,GAAG;AAC5B;AAAA,gBACJ;AAAA,cACJ;AAAA,YACJ;AAAA,UACJ;AAAA,QACJ;AAAA;AAAA,QAEA,OAAO,aAAa,OAAO,MAAM;AAC7B,mBAAS,KAAK,MAAM;AAChB,gBAAI,WAAW;AACf,qBAAS,KAAK,OAAO;AACjB,kBAAI,QAAQ;AACZ,uBAAS,MAAM,EAAE,SAAS,GAAG;AACzB,oBAAI,EAAE,OAAO,EAAE,GAAG;AACd,0BAAQ;AACR;AAAA,gBACJ;AAAA,cACJ;AACA,kBAAI,CAAC,OAAO;AACR,2BAAW;AACX;AAAA,cACJ;AAAA,YACJ;AACA,gBAAI,UAAU;AAEV,qBAAO;AAAA,YACX;AAAA,UACJ;AACA,iBAAO;AAAA,QACX;AAAA;AAAA,QAEA,UAAU;AACN,iBAAO,KAAK;AAAA,QAChB;AAAA;AAAA,QAEA,OAAO,gBAAgB,OAAO;AAC1B,cAAI,SAAS,gBAAgB,cAAc,KAAK;AAChD,cAAI,UAAU,cAAc,MAAM;AAClC,cAAI,kBAAkB,QAAQ,iBAAiB;AAC/C,cAAI,cAAc,MAAM,CAAC,EAAE,iBAAiB,EAAE,gBAAgB;AAC9D,cAAI,aAAa,MAAM,MAAM,SAAS,CAAC,EAAE,iBAAiB,EAAE,gBAAgB;AAC5E,cAAI,SAAS,CAAC,YAAY,CAAC,GAAG,YAAY,CAAC,GAAG,WAAW,CAAC,GAAG,WAAW,CAAC,CAAC;AAC1E,iBAAO,IAAI,OAAO,iBAAiB,MAAM,MAAM,QAAQ,gBAAgB,cAAc,IAAI;AAAA,QAC7F;AAAA,QACA,gBAAgB;AACZ,cAAI,YAAY,KAAK,MAAM,IAAI,CAAC;AAChC,cAAI,iBAAiB,UAAU,YAAY;AAC3C,cAAI,iBAAiB,UAAU,aAAa;AAC5C,cAAI,kBAAkB,MAAM;AACxB,mBAAO;AAAA,UACX;AACA,cAAI,WAAW,eAAe,mBAAmB;AACjD,cAAI,IAAI;AACR,mBAAS,IAAI,GAAG,IAAI,KAAK,MAAM,KAAK,GAAG,EAAE,GAAG;AACxC,gBAAI,cAAc,KAAK,MAAM,IAAI,CAAC;AAClC,wBAAY,YAAY,YAAY,EAAE,mBAAmB;AACzD;AACA,gBAAI,mBAAmB,YAAY,aAAa;AAChD,gBAAI,oBAAoB,MAAM;AAC1B,0BAAY,iBAAiB,mBAAmB;AAChD;AAAA,YACJ;AAAA,UACJ;AACA,sBAAY;AACZ,cAAI,sBAAsB,OAAO,IAAI,KAAK;AAC1C,iBAAO,uBAAuB,eAAe,SAAS;AAAA,QAC1D;AAAA,QACA,OAAO,iBAAiB,KAAK,YAAY;AACrC,cAAI;AACJ,cAAI,IAAI,IAAI,UAAU,GAAG;AACrB,yBAAa,IAAI,aAAa,UAAU;AACxC,yBAAa,IAAI,WAAW,UAAU;AAAA,UAC1C,OACK;AACD,yBAAa,IAAI,WAAW,UAAU;AACtC,yBAAa,IAAI,aAAa,UAAU;AAAA,UAC5C;AACA,iBAAO;AAAA,QACX;AAAA;AAAA,QAEA,iBAAiB,KAAK,eAAe,WAAW;AAC5C,cAAI,eAAe,cAAc,SAAS,KAAK;AAC/C,cAAI,KAAK,eAAe;AACpB,2BAAe,CAAC;AAAA,UACpB;AACA,cAAI;AACJ,cAAI,cAAc;AAClB,cAAI,eAAe;AACnB,aAAG;AACC,iBAAK,aAAa,KAAK,eAAe,YAAY;AAClD,sBAAU,KAAK,wBAAwB,KAAK,WAAW,YAAY;AACnE,gBAAI,WAAW,MAAM;AACjB,6BAAe,kBAAkB,iBAAiB,KAAK,KAAK,SAAS,CAAC,CAAC;AAAA,YAC3E,OACK;AACD,4BAAc;AAAA,YAClB;AAAA,UACJ,SAAS;AAGT,cAAI,WAAW,KAAK,oBAAoB,KAAK,SAAS,cAAc,IAAI;AACxE,cAAI,CAAC,KAAK,YAAY,aAAa,KAAK,cAAc,cAAc,SAAS,CAAC,EAAE,WAAW,GAAG;AAC1F,kBAAM,IAAI,kBAAkB;AAAA,UAChC;AACA,cAAI;AACJ,cAAI;AACA,wBAAY,KAAK,oBAAoB,KAAK,SAAS,cAAc,KAAK;AAAA,UAC1E,SACO,GAAG;AACN,wBAAY;AACZ,gBAAI,KAAK,SAAS;AACd,sBAAQ,IAAI,CAAC;AAAA,YACjB;AAAA,UACJ;AACA,iBAAO,IAAI,aAAa,UAAU,WAAW,SAAS,IAAI;AAAA,QAC9D;AAAA,QACA,YAAY,OAAO;AACf,cAAI,MAAM,WAAW,GAAG;AACpB,mBAAO;AAAA,UACX;AACA,iBAAO;AAAA,QACX;AAAA,QACA,aAAa,KAAK,eAAe,cAAc;AAC3C,cAAI,WAAW,KAAK,wBAAwB;AAC5C,mBAAS,CAAC,IAAI;AACd,mBAAS,CAAC,IAAI;AACd,mBAAS,CAAC,IAAI;AACd,mBAAS,CAAC,IAAI;AACd,cAAI,QAAQ,IAAI,QAAQ;AACxB,cAAI;AACJ,cAAI,gBAAgB,GAAG;AACnB,wBAAY;AAAA,UAChB,WACS,KAAK,YAAY,aAAa,GAAG;AACtC,wBAAY;AAAA,UAChB,OACK;AACD,gBAAI,WAAW,cAAc,cAAc,SAAS,CAAC;AACrD,wBAAY,SAAS,iBAAiB,EAAE,YAAY,EAAE,CAAC;AAAA,UAC3D;AACA,cAAI,oBAAoB,cAAc,SAAS,KAAK;AACpD,cAAI,KAAK,eAAe;AACpB,gCAAoB,CAAC;AAAA,UACzB;AACA,cAAI,UAAU;AACd,iBAAO,YAAY,OAAO;AACtB,sBAAU,CAAC,IAAI,IAAI,SAAS;AAC5B,gBAAI,CAAC,SAAS;AACV;AAAA,YACJ;AACA;AAAA,UACJ;AACA,cAAI,kBAAkB;AACtB,cAAI,eAAe;AACnB,mBAAS,IAAI,WAAW,IAAI,OAAO,KAAK;AACpC,gBAAI,IAAI,IAAI,CAAC,KAAK,SAAS;AACvB,uBAAS,eAAe;AAAA,YAC5B,OACK;AACD,kBAAI,mBAAmB,GAAG;AACtB,oBAAI,mBAAmB;AACnB,oCAAkB,gBAAgB,QAAQ;AAAA,gBAC9C;AACA,oBAAI,kBAAkB,gBAAgB,QAAQ,GAAG;AAC7C,uBAAK,SAAS,CAAC,IAAI;AACnB,uBAAK,SAAS,CAAC,IAAI;AACnB;AAAA,gBACJ;AACA,oBAAI,mBAAmB;AACnB,oCAAkB,gBAAgB,QAAQ;AAAA,gBAC9C;AACA,gCAAgB,SAAS,CAAC,IAAI,SAAS,CAAC;AACxC,yBAAS,CAAC,IAAI,SAAS,CAAC;AACxB,yBAAS,CAAC,IAAI,SAAS,CAAC;AACxB,yBAAS,CAAC,IAAI;AACd,yBAAS,CAAC,IAAI;AACd;AAAA,cACJ,OACK;AACD;AAAA,cACJ;AACA,uBAAS,eAAe,IAAI;AAC5B,wBAAU,CAAC;AAAA,YACf;AAAA,UACJ;AACA,gBAAM,IAAI,kBAAkB;AAAA,QAChC;AAAA,QACA,OAAO,gBAAgB,UAAU;AAC7B,cAAI,SAAS,SAAS;AACtB,mBAAS,IAAI,GAAG,IAAI,SAAS,GAAG,EAAE,GAAG;AACjC,gBAAI,MAAM,SAAS,CAAC;AACpB,qBAAS,CAAC,IAAI,SAAS,SAAS,IAAI,CAAC;AACrC,qBAAS,SAAS,IAAI,CAAC,IAAI;AAAA,UAC/B;AAAA,QACJ;AAAA,QACA,wBAAwB,KAAK,WAAW,YAAY;AAEhD,cAAI;AACJ,cAAI;AACJ,cAAI;AACJ,cAAI,YAAY;AAEZ,gBAAI,oBAAoB,KAAK,SAAS,CAAC,IAAI;AAE3C,mBAAO,qBAAqB,KAAK,CAAC,IAAI,IAAI,iBAAiB,GAAG;AAC1D;AAAA,YACJ;AACA;AACA,2BAAe,KAAK,SAAS,CAAC,IAAI;AAClC,oBAAQ;AACR,kBAAM,KAAK,SAAS,CAAC;AAAA,UACzB,OACK;AAED,oBAAQ,KAAK,SAAS,CAAC;AACvB,kBAAM,IAAI,aAAa,KAAK,SAAS,CAAC,IAAI,CAAC;AAC3C,2BAAe,MAAM,KAAK,SAAS,CAAC;AAAA,UACxC;AAEA,cAAI,WAAW,KAAK,wBAAwB;AAC5C,iBAAO,UAAU,UAAU,GAAG,UAAU,GAAG,SAAS,SAAS,CAAC;AAC9D,mBAAS,CAAC,IAAI;AACd,cAAI;AACJ,cAAI;AACA,oBAAQ,KAAK,iBAAiB,UAAU,kBAAkB,eAAe;AAAA,UAC7E,SACO,GAAG;AACN,mBAAO;AAAA,UACX;AAEA,iBAAO,IAAI,cAAc,OAAO,CAAC,OAAO,GAAG,GAAG,OAAO,KAAK,SAAS;AAAA,QACvE;AAAA,QACA,oBAAoB,KAAK,SAAS,cAAc,UAAU;AACtD,cAAI,WAAW,KAAK,yBAAyB;AAC7C,mBAAS,IAAI,GAAG,IAAI,SAAS,QAAQ,KAAK;AACtC,qBAAS,CAAC,IAAI;AAAA,UAClB;AACA,cAAI,UAAU;AACV,8BAAkB,uBAAuB,KAAK,QAAQ,YAAY,EAAE,CAAC,GAAG,QAAQ;AAAA,UACpF,OACK;AACD,8BAAkB,cAAc,KAAK,QAAQ,YAAY,EAAE,CAAC,GAAG,QAAQ;AAEvE,qBAAS,IAAI,GAAG,IAAI,SAAS,SAAS,GAAG,IAAI,GAAG,KAAK,KAAK;AACtD,kBAAI,OAAO,SAAS,CAAC;AACrB,uBAAS,CAAC,IAAI,SAAS,CAAC;AACxB,uBAAS,CAAC,IAAI;AAAA,YAClB;AAAA,UACJ;AACA,cAAI,aAAa;AACjB,cAAI,eAAe,UAAU,IAAI,IAAI,WAAW,QAAQ,CAAC,IAAI;AAE7D,cAAI,wBAAwB,QAAQ,YAAY,EAAE,CAAC,IAAI,QAAQ,YAAY,EAAE,CAAC,KAAK;AACnF,cAAI,KAAK,IAAI,eAAe,oBAAoB,IAAI,uBAAuB,KAAK;AAC5E,kBAAM,IAAI,kBAAkB;AAAA,UAChC;AACA,cAAI,YAAY,KAAK,aAAa;AAClC,cAAI,aAAa,KAAK,cAAc;AACpC,cAAI,oBAAoB,KAAK,qBAAqB;AAClD,cAAI,qBAAqB,KAAK,sBAAsB;AACpD,mBAAS,IAAI,GAAG,IAAI,SAAS,QAAQ,KAAK;AACtC,gBAAIC,SAAQ,IAAM,SAAS,CAAC,IAAI;AAChC,gBAAI,QAAQA,SAAQ;AACpB,gBAAI,QAAQ,GAAG;AACX,kBAAIA,SAAQ,KAAK;AACb,sBAAM,IAAI,kBAAkB;AAAA,cAChC;AACA,sBAAQ;AAAA,YACZ,WACS,QAAQ,GAAG;AAChB,kBAAIA,SAAQ,KAAK;AACb,sBAAM,IAAI,kBAAkB;AAAA,cAChC;AACA,sBAAQ;AAAA,YACZ;AACA,gBAAI,SAAS,IAAI;AACjB,iBAAK,IAAI,MAAS,GAAG;AACjB,wBAAU,MAAM,IAAI;AACpB,gCAAkB,MAAM,IAAIA,SAAQ;AAAA,YACxC,OACK;AACD,yBAAW,MAAM,IAAI;AACrB,iCAAmB,MAAM,IAAIA,SAAQ;AAAA,YACzC;AAAA,UACJ;AACA,eAAK,oBAAoB,UAAU;AACnC,cAAI,kBAAkB,IAAI,QAAQ,SAAS,KAAK,eAAe,IAAI,MAAM,WAAW,IAAI,KAAK;AAC7F,cAAI,SAAS;AACb,cAAI,qBAAqB;AACzB,mBAAS,IAAI,UAAU,SAAS,GAAG,KAAK,GAAG,KAAK;AAC5C,gBAAI,kBAAkB,YAAY,SAAS,cAAc,QAAQ,GAAG;AAChE,kBAAI,SAAS,kBAAkB,QAAQ,eAAe,EAAE,IAAI,CAAC;AAC7D,oCAAsB,UAAU,CAAC,IAAI;AAAA,YACzC;AACA,sBAAU,UAAU,CAAC;AAAA,UACzB;AACA,cAAI,sBAAsB;AAE1B,mBAAS,IAAI,WAAW,SAAS,GAAG,KAAK,GAAG,KAAK;AAC7C,gBAAI,kBAAkB,YAAY,SAAS,cAAc,QAAQ,GAAG;AAChE,kBAAI,SAAS,kBAAkB,QAAQ,eAAe,EAAE,IAAI,IAAI,CAAC;AACjE,qCAAuB,WAAW,CAAC,IAAI;AAAA,YAC3C;AAAA,UAEJ;AACA,cAAI,kBAAkB,qBAAqB;AAC3C,eAAK,SAAS,MAAS,KAAK,SAAS,MAAM,SAAS,GAAG;AACnD,kBAAM,IAAI,kBAAkB;AAAA,UAChC;AACA,cAAI,SAAS,KAAK,UAAU;AAC5B,cAAI,YAAY,kBAAkB,cAAc,KAAK;AACrD,cAAI,aAAa,IAAI;AACrB,cAAI,OAAO,SAAS,YAAY,WAAW,WAAW,IAAI;AAC1D,cAAI,QAAQ,SAAS,YAAY,YAAY,YAAY,KAAK;AAC9D,cAAI,QAAQ,kBAAkB,kBAAkB,KAAK;AACrD,cAAI,OAAO,kBAAkB,KAAK,KAAK;AACvC,cAAI,QAAQ,OAAO,QAAQ,QAAQ;AACnC,iBAAO,IAAI,cAAc,OAAO,eAAe;AAAA,QACnD;AAAA,QACA,OAAO,YAAY,SAAS,cAAc,UAAU;AAEhD,iBAAO,EAAE,QAAQ,SAAS,KAAK,KAAK,gBAAgB;AAAA,QACxD;AAAA,QACA,oBAAoB,YAAY;AAC5B,cAAI,SAAS,UAAU,IAAI,IAAI,WAAW,KAAK,aAAa,CAAC,CAAC;AAC9D,cAAI,UAAU,UAAU,IAAI,IAAI,WAAW,KAAK,cAAc,CAAC,CAAC;AAChE,cAAI,eAAe;AACnB,cAAI,eAAe;AACnB,cAAI,SAAS,IAAI;AACb,2BAAe;AAAA,UACnB,WACS,SAAS,GAAG;AACjB,2BAAe;AAAA,UACnB;AACA,cAAI,gBAAgB;AACpB,cAAI,gBAAgB;AACpB,cAAI,UAAU,IAAI;AACd,4BAAgB;AAAA,UACpB,WACS,UAAU,GAAG;AAClB,4BAAgB;AAAA,UACpB;AACA,cAAI,WAAW,SAAS,UAAU;AAClC,cAAI,gBAAgB,SAAS,MAAS;AACtC,cAAI,iBAAiB,UAAU,MAAS;AACxC,cAAI,YAAY,GAAG;AACf,gBAAI,cAAc;AACd,kBAAI,eAAe;AACf,sBAAM,IAAI,kBAAkB;AAAA,cAChC;AACA,6BAAe;AAAA,YACnB,OACK;AACD,kBAAI,CAAC,eAAe;AAChB,sBAAM,IAAI,kBAAkB;AAAA,cAChC;AACA,8BAAgB;AAAA,YACpB;AAAA,UACJ,WACS,YAAY,IAAI;AACrB,gBAAI,cAAc;AACd,kBAAI,eAAe;AACf,sBAAM,IAAI,kBAAkB;AAAA,cAChC;AACA,6BAAe;AAAA,YACnB,OACK;AACD,kBAAI,CAAC,eAAe;AAChB,sBAAM,IAAI,kBAAkB;AAAA,cAChC;AACA,8BAAgB;AAAA,YACpB;AAAA,UACJ,WACS,YAAY,GAAG;AACpB,gBAAI,cAAc;AACd,kBAAI,CAAC,eAAe;AAChB,sBAAM,IAAI,kBAAkB;AAAA,cAChC;AAEA,kBAAI,SAAS,SAAS;AAClB,+BAAe;AACf,gCAAgB;AAAA,cACpB,OACK;AACD,+BAAe;AACf,gCAAgB;AAAA,cACpB;AAAA,YACJ,OACK;AACD,kBAAI,eAAe;AACf,sBAAM,IAAI,kBAAkB;AAAA,cAChC;AAAA,YAEJ;AAAA,UACJ,OACK;AACD,kBAAM,IAAI,kBAAkB;AAAA,UAChC;AACA,cAAI,cAAc;AACd,gBAAI,cAAc;AACd,oBAAM,IAAI,kBAAkB;AAAA,YAChC;AACA,8BAAkB,UAAU,KAAK,aAAa,GAAG,KAAK,qBAAqB,CAAC;AAAA,UAChF;AACA,cAAI,cAAc;AACd,8BAAkB,UAAU,KAAK,aAAa,GAAG,KAAK,qBAAqB,CAAC;AAAA,UAChF;AACA,cAAI,eAAe;AACf,gBAAI,eAAe;AACf,oBAAM,IAAI,kBAAkB;AAAA,YAChC;AACA,8BAAkB,UAAU,KAAK,cAAc,GAAG,KAAK,qBAAqB,CAAC;AAAA,UACjF;AACA,cAAI,eAAe;AACf,8BAAkB,UAAU,KAAK,cAAc,GAAG,KAAK,sBAAsB,CAAC;AAAA,UAClF;AAAA,QACJ;AAAA,MACJ;AACA,wBAAkB,gBAAgB,CAAC,GAAG,GAAG,GAAG,GAAG,CAAC;AAChD,wBAAkB,oBAAoB,CAAC,GAAG,IAAI,IAAI,KAAK,GAAG;AAC1D,wBAAkB,OAAO,CAAC,GAAG,KAAK,MAAM,MAAM,IAAI;AAClD,wBAAkB,kBAAkB;AAAA,QAChC,WAAW,KAAK,CAAC,GAAG,GAAG,GAAG,CAAC,CAAC;AAAA,QAC5B,WAAW,KAAK,CAAC,GAAG,GAAG,GAAG,CAAC,CAAC;AAAA,QAC5B,WAAW,KAAK,CAAC,GAAG,GAAG,GAAG,CAAC,CAAC;AAAA,QAC5B,WAAW,KAAK,CAAC,GAAG,GAAG,GAAG,CAAC,CAAC;AAAA,QAC5B,WAAW,KAAK,CAAC,GAAG,GAAG,GAAG,CAAC,CAAC;AAAA,QAC5B,WAAW,KAAK,CAAC,GAAG,GAAG,GAAG,CAAC,CAAC;AAAA;AAAA,MAChC;AACA,wBAAkB,UAAU;AAAA,QACxB,CAAC,GAAG,GAAG,GAAG,IAAI,IAAI,IAAI,IAAI,EAAE;AAAA,QAC5B,CAAC,IAAI,IAAI,KAAK,KAAK,KAAK,GAAG,IAAI,EAAE;AAAA,QACjC,CAAC,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,KAAK,GAAG;AAAA,QACrC,CAAC,KAAK,KAAK,IAAI,KAAK,IAAI,IAAI,KAAK,EAAE;AAAA,QACnC,CAAC,IAAI,KAAK,KAAK,KAAK,KAAK,IAAI,IAAI,GAAG;AAAA,QACpC,CAAC,KAAK,KAAK,KAAK,KAAK,GAAG,IAAI,IAAI,GAAG;AAAA,QACnC,CAAC,KAAK,KAAK,KAAK,IAAI,IAAI,IAAI,IAAI,EAAE;AAAA,QAClC,CAAC,KAAK,IAAI,IAAI,IAAI,KAAK,KAAK,IAAI,GAAG;AAAA,QACnC,CAAC,IAAI,KAAK,KAAK,KAAK,KAAK,KAAK,KAAK,GAAG;AAAA,QACtC,CAAC,IAAI,IAAI,IAAI,KAAK,IAAI,KAAK,KAAK,GAAG;AAAA,QACnC,CAAC,IAAI,KAAK,KAAK,KAAK,KAAK,KAAK,KAAK,GAAG;AAAA,QACtC,CAAC,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,IAAI,GAAG;AAAA,QACjC,CAAC,KAAK,KAAK,KAAK,KAAK,KAAK,KAAK,KAAK,GAAG;AAAA,QACvC,CAAC,IAAI,KAAK,KAAK,KAAK,KAAK,KAAK,KAAK,GAAG;AAAA,QACtC,CAAC,KAAK,KAAK,KAAK,IAAI,IAAI,IAAI,KAAK,GAAG;AAAA,QACpC,CAAC,KAAK,IAAI,IAAI,KAAK,KAAK,IAAI,IAAI,CAAC;AAAA,QACjC,CAAC,GAAG,IAAI,IAAI,KAAK,IAAI,KAAK,KAAK,EAAE;AAAA,QACjC,CAAC,KAAK,KAAK,IAAI,IAAI,IAAI,IAAI,KAAK,GAAG;AAAA,QACnC,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,KAAK,KAAK,GAAG;AAAA,QAClC,CAAC,KAAK,IAAI,IAAI,IAAI,KAAK,KAAK,KAAK,GAAG;AAAA,QACpC,CAAC,KAAK,IAAI,KAAK,KAAK,KAAK,IAAI,IAAI,GAAG;AAAA,QACpC,CAAC,IAAI,KAAK,IAAI,GAAG,IAAI,IAAI,GAAG,EAAE;AAAA,QAC9B,CAAC,IAAI,KAAK,KAAK,KAAK,IAAI,KAAK,KAAK,EAAE;AAAA,MACxC;AACA,wBAAkB,eAAe;AACjC,wBAAkB,eAAe;AACjC,wBAAkB,eAAe;AACjC,wBAAkB,eAAe;AACjC,wBAAkB,eAAe;AACjC,wBAAkB,eAAe;AACjC,wBAAkB,2BAA2B;AAAA,QACzC,CAAC,kBAAkB,cAAc,kBAAkB,YAAY;AAAA,QAC/D,CAAC,kBAAkB,cAAc,kBAAkB,cAAc,kBAAkB,YAAY;AAAA,QAC/F,CAAC,kBAAkB,cAAc,kBAAkB,cAAc,kBAAkB,cAAc,kBAAkB,YAAY;AAAA,QAC/H,CAAC,kBAAkB,cAAc,kBAAkB,cAAc,kBAAkB,cAAc,kBAAkB,cAAc,kBAAkB,YAAY;AAAA,QAC/J,CAAC,kBAAkB,cAAc,kBAAkB,cAAc,kBAAkB,cAAc,kBAAkB,cAAc,kBAAkB,cAAc,kBAAkB,YAAY;AAAA,QAC/L,CAAC,kBAAkB,cAAc,kBAAkB,cAAc,kBAAkB,cAAc,kBAAkB,cAAc,kBAAkB,cAAc,kBAAkB,cAAc,kBAAkB,YAAY;AAAA,QAC/N,CAAC,kBAAkB,cAAc,kBAAkB,cAAc,kBAAkB,cAAc,kBAAkB,cAAc,kBAAkB,cAAc,kBAAkB,cAAc,kBAAkB,cAAc,kBAAkB,YAAY;AAAA,QAC/P,CAAC,kBAAkB,cAAc,kBAAkB,cAAc,kBAAkB,cAAc,kBAAkB,cAAc,kBAAkB,cAAc,kBAAkB,cAAc,kBAAkB,cAAc,kBAAkB,cAAc,kBAAkB,YAAY;AAAA,QAC/R,CAAC,kBAAkB,cAAc,kBAAkB,cAAc,kBAAkB,cAAc,kBAAkB,cAAc,kBAAkB,cAAc,kBAAkB,cAAc,kBAAkB,cAAc,kBAAkB,cAAc,kBAAkB,cAAc,kBAAkB,YAAY;AAAA,QAC/T,CAAC,kBAAkB,cAAc,kBAAkB,cAAc,kBAAkB,cAAc,kBAAkB,cAAc,kBAAkB,cAAc,kBAAkB,cAAc,kBAAkB,cAAc,kBAAkB,cAAc,kBAAkB,cAAc,kBAAkB,cAAc,kBAAkB,YAAY;AAAA,MACnW;AACA,wBAAkB,YAAY;AAAA,MAE9B,MAAM,aAAa,cAAc;AAAA,QAC7B,YAAY,OAAO,iBAAiB,eAAe;AAC/C,gBAAM,OAAO,eAAe;AAC5B,eAAK,QAAQ;AACb,eAAK,gBAAgB;AAAA,QACzB;AAAA,QACA,mBAAmB;AACf,iBAAO,KAAK;AAAA,QAChB;AAAA,QACA,WAAW;AACP,iBAAO,KAAK;AAAA,QAChB;AAAA,QACA,iBAAiB;AACb,eAAK;AAAA,QACT;AAAA,MACJ;AAAA,MAEA,MAAM,oBAAoB,kBAAkB;AAAA,QACxC,cAAc;AACV,gBAAM,GAAG,SAAS;AAClB,eAAK,oBAAoB,CAAC;AAC1B,eAAK,qBAAqB,CAAC;AAAA,QAC/B;AAAA,QACA,UAAU,WAAW,KAAK,OAAO;AAC7B,gBAAM,WAAW,KAAK,WAAW,KAAK,OAAO,WAAW,KAAK;AAC7D,sBAAY,WAAW,KAAK,mBAAmB,QAAQ;AACvD,cAAI,QAAQ;AACZ,cAAI,YAAY,KAAK,WAAW,KAAK,MAAM,WAAW,KAAK;AAC3D,sBAAY,WAAW,KAAK,oBAAoB,SAAS;AACzD,cAAI,QAAQ;AACZ,mBAAS,QAAQ,KAAK,mBAAmB;AACrC,gBAAI,KAAK,SAAS,IAAI,GAAG;AACrB,uBAAS,SAAS,KAAK,oBAAoB;AACvC,oBAAI,MAAM,SAAS,IAAI,KAAK,YAAY,cAAc,MAAM,KAAK,GAAG;AAChE,yBAAO,YAAY,gBAAgB,MAAM,KAAK;AAAA,gBAClD;AAAA,cACJ;AAAA,YACJ;AAAA,UACJ;AACA,gBAAM,IAAI,kBAAkB;AAAA,QAChC;AAAA,QACA,OAAO,WAAW,eAAe,MAAM;AACnC,cAAI,QAAQ,MAAM;AACd;AAAA,UACJ;AACA,cAAI,QAAQ;AACZ,mBAAS,SAAS,eAAe;AAC7B,gBAAI,MAAM,SAAS,MAAM,KAAK,SAAS,GAAG;AACtC,oBAAM,eAAe;AACrB,sBAAQ;AACR;AAAA,YACJ;AAAA,UACJ;AACA,cAAI,CAAC,OAAO;AACR,0BAAc,KAAK,IAAI;AAAA,UAC3B;AAAA,QACJ;AAAA,QACA,QAAQ;AACJ,eAAK,kBAAkB,SAAS;AAChC,eAAK,mBAAmB,SAAS;AAAA,QACrC;AAAA,QACA,OAAO,gBAAgB,UAAU,WAAW;AACxC,cAAI,cAAc,UAAU,SAAS,SAAS,IAAI,UAAU,SAAS;AACrE,cAAI,OAAO,IAAI,OAAO,WAAW,EAAE,SAAS;AAC5C,cAAI,SAAS,IAAI,cAAc;AAC/B,mBAAS,IAAI,KAAK,KAAK,QAAQ,IAAI,GAAG,KAAK;AACvC,mBAAO,OAAO,GAAG;AAAA,UACrB;AACA,iBAAO,OAAO,IAAI;AAClB,cAAI,aAAa;AACjB,mBAAS,IAAI,GAAG,IAAI,IAAI,KAAK;AACzB,gBAAI,QAAQ,OAAO,OAAO,CAAC,EAAE,WAAW,CAAC,IAAI,IAAI,WAAW,CAAC;AAC7D,2BAAgB,IAAI,OAAU,IAAK,IAAI,QAAQ;AAAA,UACnD;AACA,uBAAa,KAAM,aAAa;AAChC,cAAI,eAAe,IAAI;AACnB,yBAAa;AAAA,UACjB;AACA,iBAAO,OAAO,WAAW,SAAS,CAAC;AACnC,cAAI,aAAa,SAAS,iBAAiB,EAAE,gBAAgB;AAC7D,cAAI,cAAc,UAAU,iBAAiB,EAAE,gBAAgB;AAC/D,iBAAO,IAAI,OAAO,OAAO,SAAS,GAAG,MAAM,GAAG,CAAC,WAAW,CAAC,GAAG,WAAW,CAAC,GAAG,YAAY,CAAC,GAAG,YAAY,CAAC,CAAC,GAAG,gBAAgB,SAAQ,oBAAI,KAAK,GAAE,QAAQ,CAAC;AAAA,QAC9J;AAAA,QACA,OAAO,cAAc,UAAU,WAAW;AACtC,cAAI,cAAc,SAAS,mBAAmB,IAAI,KAAK,UAAU,mBAAmB,KAAK;AACzF,cAAI,mBAAmB,IAAI,SAAS,iBAAiB,EAAE,SAAS,IAAI,UAAU,iBAAiB,EAAE,SAAS;AAC1G,cAAI,mBAAmB,IAAI;AACvB;AAAA,UACJ;AACA,cAAI,mBAAmB,GAAG;AACtB;AAAA,UACJ;AACA,iBAAO,eAAe;AAAA,QAC1B;AAAA,QACA,WAAW,KAAK,OAAO,WAAW,OAAO;AACrC,cAAI;AACA,gBAAI,WAAW,KAAK,kBAAkB,KAAK,KAAK;AAChD,gBAAI,UAAU,KAAK,wBAAwB,KAAK,WAAW,OAAO,QAAQ;AAC1E,gBAAI,sBAAsB,SAAS,OAAO,OAAO,MAAM,IAAI,iBAAiB,0BAA0B;AACtG,gBAAI,uBAAuB,MAAM;AAC7B,kBAAI,UAAU,SAAS,CAAC,IAAI,SAAS,CAAC,KAAK;AAC3C,kBAAI,OAAO;AAEP,yBAAS,IAAI,QAAQ,IAAI,IAAI;AAAA,cACjC;AACA,kCAAoB,yBAAyB,IAAI,YAAY,QAAQ,SAAS,CAAC;AAAA,YACnF;AACA,gBAAI,UAAU,KAAK,oBAAoB,KAAK,SAAS,IAAI;AACzD,gBAAI,SAAS,KAAK,oBAAoB,KAAK,SAAS,KAAK;AACzD,mBAAO,IAAI,KAAK,OAAO,QAAQ,SAAS,IAAI,OAAO,SAAS,GAAG,QAAQ,mBAAmB,IAAI,IAAI,OAAO,mBAAmB,GAAG,OAAO;AAAA,UAC1I,SACOR,MAAK;AACR,mBAAO;AAAA,UACX;AAAA,QACJ;AAAA,QACA,oBAAoB,KAAK,SAAS,aAAa;AAC3C,cAAI,WAAW,KAAK,yBAAyB;AAC7C,mBAAS,IAAI,GAAG,IAAI,SAAS,QAAQ,KAAK;AACtC,qBAAS,CAAC,IAAI;AAAA,UAClB;AACA,cAAI,aAAa;AACb,uBAAW,uBAAuB,KAAK,QAAQ,YAAY,EAAE,CAAC,GAAG,QAAQ;AAAA,UAC7E,OACK;AACD,uBAAW,cAAc,KAAK,QAAQ,YAAY,EAAE,CAAC,IAAI,GAAG,QAAQ;AAEpE,qBAAS,IAAI,GAAG,IAAI,SAAS,SAAS,GAAG,IAAI,GAAG,KAAK,KAAK;AACtD,kBAAI,OAAO,SAAS,CAAC;AACrB,uBAAS,CAAC,IAAI,SAAS,CAAC;AACxB,uBAAS,CAAC,IAAI;AAAA,YAClB;AAAA,UACJ;AACA,cAAI,aAAa,cAAc,KAAK;AACpC,cAAI,eAAe,UAAU,IAAI,IAAI,WAAW,QAAQ,CAAC,IAAI;AAC7D,cAAI,YAAY,KAAK,aAAa;AAClC,cAAI,aAAa,KAAK,cAAc;AACpC,cAAI,oBAAoB,KAAK,qBAAqB;AAClD,cAAI,qBAAqB,KAAK,sBAAsB;AACpD,mBAAS,IAAI,GAAG,IAAI,SAAS,QAAQ,KAAK;AACtC,gBAAI,QAAQ,SAAS,CAAC,IAAI;AAC1B,gBAAI,QAAQ,KAAK,MAAM,QAAQ,GAAG;AAClC,gBAAI,QAAQ,GAAG;AACX,sBAAQ;AAAA,YACZ,WACS,QAAQ,GAAG;AAChB,sBAAQ;AAAA,YACZ;AACA,gBAAI,SAAS,KAAK,MAAM,IAAI,CAAC;AAC7B,iBAAK,IAAI,OAAU,GAAG;AAClB,wBAAU,MAAM,IAAI;AACpB,gCAAkB,MAAM,IAAI,QAAQ;AAAA,YACxC,OACK;AACD,yBAAW,MAAM,IAAI;AACrB,iCAAmB,MAAM,IAAI,QAAQ;AAAA,YACzC;AAAA,UACJ;AACA,eAAK,oBAAoB,aAAa,UAAU;AAChD,cAAI,SAAS;AACb,cAAI,qBAAqB;AACzB,mBAAS,IAAI,UAAU,SAAS,GAAG,KAAK,GAAG,KAAK;AAC5C,kCAAsB;AACtB,kCAAsB,UAAU,CAAC;AACjC,sBAAU,UAAU,CAAC;AAAA,UACzB;AACA,cAAI,sBAAsB;AAC1B,cAAI,UAAU;AACd,mBAAS,IAAI,WAAW,SAAS,GAAG,KAAK,GAAG,KAAK;AAC7C,mCAAuB;AACvB,mCAAuB,WAAW,CAAC;AACnC,uBAAW,WAAW,CAAC;AAAA,UAC3B;AACA,cAAI,kBAAkB,qBAAqB,IAAI;AAC/C,cAAI,aAAa;AACb,iBAAK,SAAS,OAAU,KAAK,SAAS,MAAM,SAAS,GAAG;AACpD,oBAAM,IAAI,kBAAkB;AAAA,YAChC;AACA,gBAAI,SAAS,KAAK,UAAU;AAC5B,gBAAI,YAAY,YAAY,mBAAmB,KAAK;AACpD,gBAAI,aAAa,IAAI;AACrB,gBAAI,OAAO,SAAS,YAAY,WAAW,WAAW,KAAK;AAC3D,gBAAI,QAAQ,SAAS,YAAY,YAAY,YAAY,IAAI;AAC7D,gBAAI,QAAQ,YAAY,0BAA0B,KAAK;AACvD,gBAAI,OAAO,YAAY,aAAa,KAAK;AACzC,mBAAO,IAAI,cAAc,OAAO,QAAQ,QAAQ,MAAM,eAAe;AAAA,UACzE,OACK;AACD,iBAAK,UAAU,OAAU,KAAK,UAAU,MAAM,UAAU,GAAG;AACvD,oBAAM,IAAI,kBAAkB;AAAA,YAChC;AACA,gBAAI,SAAS,KAAK,WAAW;AAC7B,gBAAI,YAAY,YAAY,kBAAkB,KAAK;AACnD,gBAAI,aAAa,IAAI;AACrB,gBAAI,OAAO,SAAS,YAAY,WAAW,WAAW,IAAI;AAC1D,gBAAI,QAAQ,SAAS,YAAY,YAAY,YAAY,KAAK;AAC9D,gBAAI,OAAO,YAAY,wBAAwB,KAAK;AACpD,gBAAI,OAAO,YAAY,YAAY,KAAK;AACxC,mBAAO,IAAI,cAAc,QAAQ,OAAO,OAAO,MAAM,eAAe;AAAA,UACxE;AAAA,QACJ;AAAA,QACA,kBAAkB,KAAK,oBAAoB;AACvC,cAAI,WAAW,KAAK,wBAAwB;AAC5C,mBAAS,CAAC,IAAI;AACd,mBAAS,CAAC,IAAI;AACd,mBAAS,CAAC,IAAI;AACd,mBAAS,CAAC,IAAI;AACd,cAAI,QAAQ,IAAI,QAAQ;AACxB,cAAI,UAAU;AACd,cAAI,YAAY;AAChB,iBAAO,YAAY,OAAO;AACtB,sBAAU,CAAC,IAAI,IAAI,SAAS;AAC5B,gBAAI,uBAAuB,SAAS;AAEhC;AAAA,YACJ;AACA;AAAA,UACJ;AACA,cAAI,kBAAkB;AACtB,cAAI,eAAe;AACnB,mBAAS,IAAI,WAAW,IAAI,OAAO,KAAK;AACpC,gBAAI,IAAI,IAAI,CAAC,MAAM,SAAS;AACxB,uBAAS,eAAe;AAAA,YAC5B,OACK;AACD,kBAAI,oBAAoB,GAAG;AACvB,oBAAI,kBAAkB,gBAAgB,QAAQ,GAAG;AAC7C,yBAAO,CAAC,cAAc,CAAC;AAAA,gBAC3B;AACA,gCAAgB,SAAS,CAAC,IAAI,SAAS,CAAC;AACxC,yBAAS,CAAC,IAAI,SAAS,CAAC;AACxB,yBAAS,CAAC,IAAI,SAAS,CAAC;AACxB,yBAAS,CAAC,IAAI;AACd,yBAAS,CAAC,IAAI;AACd;AAAA,cACJ,OACK;AACD;AAAA,cACJ;AACA,uBAAS,eAAe,IAAI;AAC5B,wBAAU,CAAC;AAAA,YACf;AAAA,UACJ;AACA,gBAAM,IAAI,kBAAkB;AAAA,QAChC;AAAA,QACA,wBAAwB,KAAK,WAAW,OAAO,UAAU;AAErD,cAAI,eAAe,IAAI,IAAI,SAAS,CAAC,CAAC;AACtC,cAAI,oBAAoB,SAAS,CAAC,IAAI;AAEtC,iBAAO,qBAAqB,KAAK,iBAAiB,IAAI,IAAI,iBAAiB,GAAG;AAC1E;AAAA,UACJ;AACA;AACA,gBAAM,eAAe,SAAS,CAAC,IAAI;AAEnC,gBAAM,WAAW,KAAK,wBAAwB;AAC9C,gBAAM,OAAO,IAAI,WAAW,SAAS,MAAM;AAC3C,iBAAO,UAAU,UAAU,GAAG,MAAM,GAAG,SAAS,SAAS,CAAC;AAC1D,eAAK,CAAC,IAAI;AACV,gBAAM,QAAQ,KAAK,iBAAiB,MAAM,YAAY,eAAe;AACrE,cAAI,QAAQ;AACZ,cAAI,MAAM,SAAS,CAAC;AACpB,cAAI,OAAO;AAEP,oBAAQ,IAAI,QAAQ,IAAI,IAAI;AAC5B,kBAAM,IAAI,QAAQ,IAAI,IAAI;AAAA,UAC9B;AACA,iBAAO,IAAI,cAAc,OAAO,CAAC,mBAAmB,SAAS,CAAC,CAAC,GAAG,OAAO,KAAK,SAAS;AAAA,QAC3F;AAAA,QACA,oBAAoB,aAAa,YAAY;AACzC,cAAI,SAAS,UAAU,IAAI,IAAI,WAAW,KAAK,aAAa,CAAC,CAAC;AAC9D,cAAI,UAAU,UAAU,IAAI,IAAI,WAAW,KAAK,cAAc,CAAC,CAAC;AAChE,cAAI,eAAe;AACnB,cAAI,eAAe;AACnB,cAAI,gBAAgB;AACpB,cAAI,gBAAgB;AACpB,cAAI,aAAa;AACb,gBAAI,SAAS,IAAI;AACb,6BAAe;AAAA,YACnB,WACS,SAAS,GAAG;AACjB,6BAAe;AAAA,YACnB;AACA,gBAAI,UAAU,IAAI;AACd,8BAAgB;AAAA,YACpB,WACS,UAAU,GAAG;AAClB,8BAAgB;AAAA,YACpB;AAAA,UACJ,OACK;AACD,gBAAI,SAAS,IAAI;AACb,6BAAe;AAAA,YACnB,WACS,SAAS,GAAG;AACjB,6BAAe;AAAA,YACnB;AACA,gBAAI,UAAU,IAAI;AACd,8BAAgB;AAAA,YACpB,WACS,UAAU,GAAG;AAClB,8BAAgB;AAAA,YACpB;AAAA,UACJ;AACA,cAAI,WAAW,SAAS,UAAU;AAClC,cAAI,gBAAgB,SAAS,QAAW,cAAc,IAAI;AAC1D,cAAI,iBAAiB,UAAU,OAAU;AACzC,cAAI,aAAa,GAAG;AAChB,gBAAI,cAAc;AACd,kBAAI,eAAe;AACf,sBAAM,IAAI,kBAAkB;AAAA,cAChC;AACA,6BAAe;AAAA,YACnB,OACK;AACD,kBAAI,CAAC,eAAe;AAChB,sBAAM,IAAI,kBAAkB;AAAA,cAChC;AACA,8BAAgB;AAAA,YACpB;AAAA,UACJ,WACS,aAAa,IAAI;AACtB,gBAAI,cAAc;AACd,kBAAI,eAAe;AACf,sBAAM,IAAI,kBAAkB;AAAA,cAChC;AACA,6BAAe;AAAA,YACnB,OACK;AACD,kBAAI,CAAC,eAAe;AAChB,sBAAM,IAAI,kBAAkB;AAAA,cAChC;AACA,8BAAgB;AAAA,YACpB;AAAA,UACJ,WACS,aAAa,GAAG;AACrB,gBAAI,cAAc;AACd,kBAAI,CAAC,eAAe;AAChB,sBAAM,IAAI,kBAAkB;AAAA,cAChC;AAEA,kBAAI,SAAS,SAAS;AAClB,+BAAe;AACf,gCAAgB;AAAA,cACpB,OACK;AACD,+BAAe;AACf,gCAAgB;AAAA,cACpB;AAAA,YACJ,OACK;AACD,kBAAI,eAAe;AACf,sBAAM,IAAI,kBAAkB;AAAA,cAChC;AAAA,YAEJ;AAAA,UACJ,OACK;AACD,kBAAM,IAAI,kBAAkB;AAAA,UAChC;AACA,cAAI,cAAc;AACd,gBAAI,cAAc;AACd,oBAAM,IAAI,kBAAkB;AAAA,YAChC;AACA,8BAAkB,UAAU,KAAK,aAAa,GAAG,KAAK,qBAAqB,CAAC;AAAA,UAChF;AACA,cAAI,cAAc;AACd,8BAAkB,UAAU,KAAK,aAAa,GAAG,KAAK,qBAAqB,CAAC;AAAA,UAChF;AACA,cAAI,eAAe;AACf,gBAAI,eAAe;AACf,oBAAM,IAAI,kBAAkB;AAAA,YAChC;AACA,8BAAkB,UAAU,KAAK,cAAc,GAAG,KAAK,qBAAqB,CAAC;AAAA,UACjF;AACA,cAAI,eAAe;AACf,8BAAkB,UAAU,KAAK,cAAc,GAAG,KAAK,sBAAsB,CAAC;AAAA,UAClF;AAAA,QACJ;AAAA,MACJ;AACA,kBAAY,4BAA4B,CAAC,GAAG,IAAI,IAAI,IAAI,GAAG;AAC3D,kBAAY,0BAA0B,CAAC,GAAG,IAAI,IAAI,EAAE;AACpD,kBAAY,eAAe,CAAC,GAAG,KAAK,KAAK,MAAM,IAAI;AACnD,kBAAY,cAAc,CAAC,GAAG,KAAK,MAAM,IAAI;AAC7C,kBAAY,qBAAqB,CAAC,GAAG,GAAG,GAAG,GAAG,CAAC;AAC/C,kBAAY,oBAAoB,CAAC,GAAG,GAAG,GAAG,CAAC;AAC3C,kBAAY,kBAAkB;AAAA,QAC1B,WAAW,KAAK,CAAC,GAAG,GAAG,GAAG,CAAC,CAAC;AAAA,QAC5B,WAAW,KAAK,CAAC,GAAG,GAAG,GAAG,CAAC,CAAC;AAAA,QAC5B,WAAW,KAAK,CAAC,GAAG,GAAG,GAAG,CAAC,CAAC;AAAA,QAC5B,WAAW,KAAK,CAAC,GAAG,GAAG,GAAG,CAAC,CAAC;AAAA,QAC5B,WAAW,KAAK,CAAC,GAAG,GAAG,GAAG,CAAC,CAAC;AAAA,QAC5B,WAAW,KAAK,CAAC,GAAG,GAAG,GAAG,CAAC,CAAC;AAAA,QAC5B,WAAW,KAAK,CAAC,GAAG,GAAG,GAAG,CAAC,CAAC;AAAA,QAC5B,WAAW,KAAK,CAAC,GAAG,GAAG,GAAG,CAAC,CAAC;AAAA,QAC5B,WAAW,KAAK,CAAC,GAAG,GAAG,GAAG,CAAC,CAAC;AAAA,MAChC;AAAA,MAMA,MAAM,8BAA8B,WAAW;AAAA,QAC3C,YAAY,OAAO,SAAS;AACxB,gBAAM;AACN,eAAK,UAAU,CAAC;AAChB,eAAK,UAAW,YAAY;AAC5B,gBAAM,kBAAkB,CAAC,QAAQ,OAAO,MAAM,IAAI,iBAAiB,gBAAgB;AACnF,gBAAM,sBAAsB,SAAS,MAAM,IAAI,iBAAiB,0BAA0B,MAAM;AAChG,cAAI,iBAAiB;AACjB,gBAAI,gBAAgB,SAAS,gBAAgB,MAAM,KAC/C,gBAAgB,SAAS,gBAAgB,KAAK,KAC9C,gBAAgB,SAAS,gBAAgB,KAAK,KAC9C,gBAAgB,SAAS,gBAAgB,KAAK,GAAG;AACjD,mBAAK,QAAQ,KAAK,IAAI,wBAAwB,KAAK,CAAC;AAAA,YACxD;AACA,gBAAI,gBAAgB,SAAS,gBAAgB,OAAO,GAAG;AACnD,mBAAK,QAAQ,KAAK,IAAI,aAAa,mBAAmB,CAAC;AAAA,YAC3D;AAIA,gBAAI,gBAAgB,SAAS,gBAAgB,QAAQ,GAAG;AACpD,mBAAK,QAAQ,KAAK,IAAI,cAAc,CAAC;AAAA,YACzC;AACA,gBAAI,gBAAgB,SAAS,gBAAgB,GAAG,GAAG;AAC/C,mBAAK,QAAQ,KAAK,IAAI,UAAU,CAAC;AAAA,YACrC;AAIA,gBAAI,gBAAgB,SAAS,gBAAgB,MAAM,GAAG;AAClD,mBAAK,QAAQ,KAAK,IAAI,YAAY,CAAC;AAAA,YACvC;AACA,gBAAI,gBAAgB,SAAS,gBAAgB,YAAY,GAAG;AACxD,mBAAK,QAAQ,KAAK,IAAI,kBAAkB,KAAK,OAAO,CAAC;AAAA,YACzD;AAAA,UACJ,OAAO;AAEH,iBAAK,QAAQ,KAAK,IAAI,wBAAwB,KAAK,CAAC;AACpD,iBAAK,QAAQ,KAAK,IAAI,aAAa,CAAC;AAGpC,iBAAK,QAAQ,KAAK,IAAI,wBAAwB,KAAK,CAAC;AACpD,iBAAK,QAAQ,KAAK,IAAI,cAAc,CAAC;AACrC,iBAAK,QAAQ,KAAK,IAAI,UAAU,CAAC;AACjC,iBAAK,QAAQ,KAAK,IAAI,YAAY,CAAC;AACnC,iBAAK,QAAQ,KAAK,IAAI,kBAAkB,KAAK,OAAO,CAAC;AAAA,UACzD;AAAA,QACJ;AAAA;AAAA,QAEA,UAAU,WAAW,KAAK,OAAO;AAC7B,mBAAS,IAAI,GAAG,IAAI,KAAK,QAAQ,QAAQ,KAAK;AAC1C,gBAAI;AACA,qBAAO,KAAK,QAAQ,CAAC,EAAE,UAAU,WAAW,KAAK,KAAK;AAAA,YAC1D,SACO,IAAI;AAAA,YAEX;AAAA,UACJ;AACA,gBAAM,IAAI,kBAAkB;AAAA,QAChC;AAAA;AAAA,QAEA,QAAQ;AACJ,eAAK,QAAQ,QAAQ,YAAU,OAAO,MAAM,CAAC;AAAA,QACjD;AAAA,MACJ;AAAA,MAOA,MAAM,6BAA6B,kBAAkB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAMjD,YAAY,yBAAyB,KAAK,OAAO;AAC7C,gBAAM,IAAI,sBAAsB,KAAK,GAAG,wBAAwB,KAAK;AAAA,QACzE;AAAA,MACJ;AAAA,MAuBA,MAAM,SAAS;AAAA,QACX,YAAY,aAAa,WAAW,WAAW;AAC3C,eAAK,cAAc;AACnB,eAAK,WAAW,CAAC,SAAS;AAC1B,uBAAa,KAAK,SAAS,KAAK,SAAS;AAAA,QAC7C;AAAA,QACA,iBAAiB;AACb,iBAAO,KAAK;AAAA,QAChB;AAAA,QACA,cAAc;AACV,iBAAO,KAAK;AAAA,QAChB;AAAA,MACJ;AAAA,MAMA,MAAM,IAAI;AAAA,QACN,YAAY,OAAO,eAAe;AAC9B,eAAK,QAAQ;AACb,eAAK,gBAAgB;AAAA,QACzB;AAAA,QACA,WAAW;AACP,iBAAO,KAAK;AAAA,QAChB;AAAA,QACA,mBAAmB;AACf,iBAAO,KAAK;AAAA,QAChB;AAAA,MACJ;AAAA,MAOA,MAAM,QAAQ;AAAA,QACV,YAAY,eAAe,gBAAgB,mBAAmB,oBAAoB,uBAAuB,UAAU;AAC/G,eAAK,gBAAgB;AACrB,eAAK,iBAAiB;AACtB,eAAK,oBAAoB;AACzB,eAAK,qBAAqB;AAC1B,eAAK,wBAAwB;AAC7B,eAAK,WAAW;AAEhB,cAAI,QAAQ;AACZ,gBAAM,cAAc,SAAS,eAAe;AAC5C,gBAAM,WAAW,SAAS,YAAY;AACtC,mBAAS,WAAW,UAAU;AAC1B,qBAAS,QAAQ,SAAS,KAAK,QAAQ,iBAAiB,IAAI;AAAA,UAChE;AACA,eAAK,iBAAiB;AAAA,QAC1B;AAAA,QACA,mBAAmB;AACf,iBAAO,KAAK;AAAA,QAChB;AAAA,QACA,oBAAoB;AAChB,iBAAO,KAAK;AAAA,QAChB;AAAA,QACA,uBAAuB;AACnB,iBAAO,KAAK;AAAA,QAChB;AAAA,QACA,wBAAwB;AACpB,iBAAO,KAAK;AAAA,QAChB;AAAA,QACA,2BAA2B;AACvB,iBAAO,KAAK;AAAA,QAChB;AAAA,QACA,oBAAoB;AAChB,iBAAO,KAAK;AAAA,QAChB;AAAA,QACA,cAAc;AACV,iBAAO,KAAK;AAAA,QAChB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QASA,OAAO,wBAAwB,SAAS,YAAY;AAChD,eAAK,UAAU,OAAU,MAAM,aAAa,OAAU,GAAG;AACrD,kBAAM,IAAI,gBAAgB;AAAA,UAC9B;AACA,mBAAS,WAAW,QAAQ,UAAU;AAClC,gBAAI,QAAQ,mBAAmB,WAAW,QAAQ,sBAAsB,YAAY;AAChF,qBAAO;AAAA,YACX;AAAA,UACJ;AACA,gBAAM,IAAI,gBAAgB;AAAA,QAC9B;AAAA;AAAA,QAEA,WAAW;AACP,iBAAO,KAAK,KAAK;AAAA,QACrB;AAAA;AAAA;AAAA;AAAA,QAIA,OAAO,gBAAgB;AACnB,iBAAO;AAAA,YACH,IAAI,QAAQ,GAAG,IAAI,IAAI,GAAG,GAAG,IAAI,SAAS,GAAG,IAAI,IAAI,GAAG,CAAC,CAAC,CAAC;AAAA,YAC3D,IAAI,QAAQ,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,SAAS,GAAG,IAAI,IAAI,GAAG,CAAC,CAAC,CAAC;AAAA,YAC7D,IAAI,QAAQ,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,SAAS,IAAI,IAAI,IAAI,GAAG,CAAC,CAAC,CAAC;AAAA,YAC9D,IAAI,QAAQ,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,SAAS,IAAI,IAAI,IAAI,GAAG,EAAE,CAAC,CAAC;AAAA,YAC/D,IAAI,QAAQ,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,SAAS,IAAI,IAAI,IAAI,GAAG,EAAE,CAAC,CAAC;AAAA,YAC/D,IAAI,QAAQ,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,SAAS,IAAI,IAAI,IAAI,GAAG,EAAE,CAAC,CAAC;AAAA,YAC/D,IAAI,QAAQ,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,SAAS,IAAI,IAAI,IAAI,GAAG,EAAE,CAAC,CAAC;AAAA,YAC/D,IAAI,QAAQ,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,SAAS,IAAI,IAAI,IAAI,GAAG,EAAE,CAAC,CAAC;AAAA,YAC/D,IAAI,QAAQ,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,SAAS,IAAI,IAAI,IAAI,GAAG,EAAE,CAAC,CAAC;AAAA,YAC/D,IAAI,QAAQ,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,SAAS,IAAI,IAAI,IAAI,GAAG,EAAE,CAAC,CAAC;AAAA,YAChE,IAAI,QAAQ,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,SAAS,IAAI,IAAI,IAAI,GAAG,EAAE,CAAC,CAAC;AAAA,YAChE,IAAI,QAAQ,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,SAAS,IAAI,IAAI,IAAI,GAAG,GAAG,CAAC,CAAC;AAAA,YACjE,IAAI,QAAQ,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,SAAS,IAAI,IAAI,IAAI,GAAG,GAAG,CAAC,CAAC;AAAA,YACjE,IAAI,QAAQ,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,SAAS,IAAI,IAAI,IAAI,GAAG,GAAG,CAAC,CAAC;AAAA,YACjE,IAAI,QAAQ,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,SAAS,IAAI,IAAI,IAAI,GAAG,GAAG,CAAC,CAAC;AAAA,YACjE,IAAI,QAAQ,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,SAAS,IAAI,IAAI,IAAI,GAAG,GAAG,CAAC,CAAC;AAAA,YACjE,IAAI,QAAQ,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,SAAS,IAAI,IAAI,IAAI,GAAG,EAAE,CAAC,CAAC;AAAA,YAChE,IAAI,QAAQ,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,SAAS,IAAI,IAAI,IAAI,GAAG,GAAG,CAAC,CAAC;AAAA,YACjE,IAAI,QAAQ,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,SAAS,IAAI,IAAI,IAAI,GAAG,GAAG,CAAC,CAAC;AAAA,YACjE,IAAI,QAAQ,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,SAAS,IAAI,IAAI,IAAI,GAAG,GAAG,CAAC,CAAC;AAAA,YACjE,IAAI,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,IAAI,SAAS,IAAI,IAAI,IAAI,GAAG,GAAG,CAAC,CAAC;AAAA,YACnE,IAAI,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,IAAI,SAAS,IAAI,IAAI,IAAI,GAAG,GAAG,CAAC,CAAC;AAAA,YACnE,IAAI,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,IAAI,SAAS,IAAI,IAAI,IAAI,GAAG,GAAG,CAAC,CAAC;AAAA,YACnE,IAAI,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,IAAI,SAAS,IAAI,IAAI,IAAI,GAAG,GAAG,GAAG,IAAI,IAAI,GAAG,GAAG,CAAC,CAAC;AAAA,YACpF,IAAI,QAAQ,IAAI,GAAG,IAAI,GAAG,IAAI,IAAI,SAAS,GAAG,IAAI,IAAI,GAAG,CAAC,CAAC,CAAC;AAAA,YAC5D,IAAI,QAAQ,IAAI,GAAG,IAAI,GAAG,IAAI,IAAI,SAAS,IAAI,IAAI,IAAI,GAAG,EAAE,CAAC,CAAC;AAAA,YAC9D,IAAI,QAAQ,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,SAAS,IAAI,IAAI,IAAI,GAAG,EAAE,CAAC,CAAC;AAAA,YAChE,IAAI,QAAQ,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,SAAS,IAAI,IAAI,IAAI,GAAG,EAAE,CAAC,CAAC;AAAA,YAChE,IAAI,QAAQ,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,SAAS,IAAI,IAAI,IAAI,GAAG,EAAE,CAAC,CAAC;AAAA,YAChE,IAAI,QAAQ,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,SAAS,IAAI,IAAI,IAAI,GAAG,EAAE,CAAC,CAAC;AAAA,UACpE;AAAA,QACJ;AAAA,MACJ;AACA,cAAQ,WAAW,QAAQ,cAAc;AAAA,MAoBzC,MAAM,gBAAgB;AAAA;AAAA;AAAA;AAAA;AAAA,QAKlB,YAAY,WAAW;AACnB,gBAAM,YAAY,UAAU,UAAU;AACtC,cAAI,YAAY,KAAK,YAAY,QAAQ,YAAY,OAAU,GAAG;AAC9D,kBAAM,IAAI,gBAAgB;AAAA,UAC9B;AACA,eAAK,UAAU,gBAAgB,YAAY,SAAS;AACpD,eAAK,mBAAmB,KAAK,kBAAkB,SAAS;AACxD,eAAK,oBAAoB,IAAI,UAAU,KAAK,iBAAiB,SAAS,GAAG,KAAK,iBAAiB,UAAU,CAAC;AAAA,QAC9G;AAAA,QACA,aAAa;AACT,iBAAO,KAAK;AAAA,QAChB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAYA,OAAO,YAAY,WAAW;AAC1B,gBAAM,UAAU,UAAU,UAAU;AACpC,gBAAM,aAAa,UAAU,SAAS;AACtC,iBAAO,QAAQ,wBAAwB,SAAS,UAAU;AAAA,QAC9D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QASA,gBAAgB;AACZ,gBAAM,SAAS,IAAI,UAAU,KAAK,QAAQ,kBAAkB,CAAC;AAC7D,cAAI,eAAe;AACnB,cAAI,MAAM;AACV,cAAI,SAAS;AACb,gBAAM,UAAU,KAAK,iBAAiB,UAAU;AAChD,gBAAM,aAAa,KAAK,iBAAiB,SAAS;AAClD,cAAI,cAAc;AAClB,cAAI,cAAc;AAClB,cAAI,cAAc;AAClB,cAAI,cAAc;AAElB,aAAG;AAEC,gBAAK,QAAQ,WAAa,WAAW,KAAM,CAAC,aAAa;AACrD,qBAAO,cAAc,IAAI,KAAK,YAAY,SAAS,UAAU,IAAI;AACjE,qBAAO;AACP,wBAAU;AACV,4BAAc;AAAA,YAClB,WACU,QAAQ,UAAU,KAAO,WAAW,MAAQ,aAAa,OAAU,KAAM,CAAC,aAAa;AAC7F,qBAAO,cAAc,IAAI,KAAK,YAAY,SAAS,UAAU,IAAI;AACjE,qBAAO;AACP,wBAAU;AACV,4BAAc;AAAA,YAClB,WACU,QAAQ,UAAU,KAAO,WAAW,MAAQ,aAAa,OAAU,KAAM,CAAC,aAAa;AAC7F,qBAAO,cAAc,IAAI,KAAK,YAAY,SAAS,UAAU,IAAI;AACjE,qBAAO;AACP,wBAAU;AACV,4BAAc;AAAA,YAClB,WACU,QAAQ,UAAU,KAAO,WAAW,MAAQ,aAAa,OAAU,KAAM,CAAC,aAAa;AAC7F,qBAAO,cAAc,IAAI,KAAK,YAAY,SAAS,UAAU,IAAI;AACjE,qBAAO;AACP,wBAAU;AACV,4BAAc;AAAA,YAClB,OACK;AAED,iBAAG;AACC,oBAAK,MAAM,WAAa,UAAU,KAAM,CAAC,KAAK,kBAAkB,IAAI,QAAQ,GAAG,GAAG;AAC9E,yBAAO,cAAc,IAAI,KAAK,SAAS,KAAK,QAAQ,SAAS,UAAU,IAAI;AAAA,gBAC/E;AACA,uBAAO;AACP,0BAAU;AAAA,cACd,SAAU,OAAO,KAAO,SAAS;AACjC,qBAAO;AACP,wBAAU;AAEV,iBAAG;AACC,oBAAK,OAAO,KAAO,SAAS,cAAe,CAAC,KAAK,kBAAkB,IAAI,QAAQ,GAAG,GAAG;AACjF,yBAAO,cAAc,IAAI,KAAK,SAAS,KAAK,QAAQ,SAAS,UAAU,IAAI;AAAA,gBAC/E;AACA,uBAAO;AACP,0BAAU;AAAA,cACd,SAAU,MAAM,WAAa,UAAU;AACvC,qBAAO;AACP,wBAAU;AAAA,YACd;AAAA,UACJ,SAAU,MAAM,WAAa,SAAS;AACtC,cAAI,iBAAiB,KAAK,QAAQ,kBAAkB,GAAG;AACnD,kBAAM,IAAI,gBAAgB;AAAA,UAC9B;AACA,iBAAO;AAAA,QACX;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAUA,WAAW,KAAK,QAAQ,SAAS,YAAY;AAEzC,cAAI,MAAM,GAAG;AACT,mBAAO;AACP,sBAAU,KAAM,UAAU,IAAK;AAAA,UACnC;AACA,cAAI,SAAS,GAAG;AACZ,sBAAU;AACV,mBAAO,KAAM,aAAa,IAAK;AAAA,UACnC;AACA,eAAK,kBAAkB,IAAI,QAAQ,GAAG;AACtC,iBAAO,KAAK,iBAAiB,IAAI,QAAQ,GAAG;AAAA,QAChD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAYA,SAAS,KAAK,QAAQ,SAAS,YAAY;AACvC,cAAI,cAAc;AAClB,cAAI,KAAK,WAAW,MAAM,GAAG,SAAS,GAAG,SAAS,UAAU,GAAG;AAC3D,2BAAe;AAAA,UACnB;AACA,0BAAgB;AAChB,cAAI,KAAK,WAAW,MAAM,GAAG,SAAS,GAAG,SAAS,UAAU,GAAG;AAC3D,2BAAe;AAAA,UACnB;AACA,0BAAgB;AAChB,cAAI,KAAK,WAAW,MAAM,GAAG,SAAS,GAAG,SAAS,UAAU,GAAG;AAC3D,2BAAe;AAAA,UACnB;AACA,0BAAgB;AAChB,cAAI,KAAK,WAAW,MAAM,GAAG,SAAS,GAAG,SAAS,UAAU,GAAG;AAC3D,2BAAe;AAAA,UACnB;AACA,0BAAgB;AAChB,cAAI,KAAK,WAAW,MAAM,GAAG,QAAQ,SAAS,UAAU,GAAG;AACvD,2BAAe;AAAA,UACnB;AACA,0BAAgB;AAChB,cAAI,KAAK,WAAW,KAAK,SAAS,GAAG,SAAS,UAAU,GAAG;AACvD,2BAAe;AAAA,UACnB;AACA,0BAAgB;AAChB,cAAI,KAAK,WAAW,KAAK,SAAS,GAAG,SAAS,UAAU,GAAG;AACvD,2BAAe;AAAA,UACnB;AACA,0BAAgB;AAChB,cAAI,KAAK,WAAW,KAAK,QAAQ,SAAS,UAAU,GAAG;AACnD,2BAAe;AAAA,UACnB;AACA,iBAAO;AAAA,QACX;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAUA,YAAY,SAAS,YAAY;AAC7B,cAAI,cAAc;AAClB,cAAI,KAAK,WAAW,UAAU,GAAG,GAAG,SAAS,UAAU,GAAG;AACtD,2BAAe;AAAA,UACnB;AACA,0BAAgB;AAChB,cAAI,KAAK,WAAW,UAAU,GAAG,GAAG,SAAS,UAAU,GAAG;AACtD,2BAAe;AAAA,UACnB;AACA,0BAAgB;AAChB,cAAI,KAAK,WAAW,UAAU,GAAG,GAAG,SAAS,UAAU,GAAG;AACtD,2BAAe;AAAA,UACnB;AACA,0BAAgB;AAChB,cAAI,KAAK,WAAW,GAAG,aAAa,GAAG,SAAS,UAAU,GAAG;AACzD,2BAAe;AAAA,UACnB;AACA,0BAAgB;AAChB,cAAI,KAAK,WAAW,GAAG,aAAa,GAAG,SAAS,UAAU,GAAG;AACzD,2BAAe;AAAA,UACnB;AACA,0BAAgB;AAChB,cAAI,KAAK,WAAW,GAAG,aAAa,GAAG,SAAS,UAAU,GAAG;AACzD,2BAAe;AAAA,UACnB;AACA,0BAAgB;AAChB,cAAI,KAAK,WAAW,GAAG,aAAa,GAAG,SAAS,UAAU,GAAG;AACzD,2BAAe;AAAA,UACnB;AACA,0BAAgB;AAChB,cAAI,KAAK,WAAW,GAAG,aAAa,GAAG,SAAS,UAAU,GAAG;AACzD,2BAAe;AAAA,UACnB;AACA,iBAAO;AAAA,QACX;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAUA,YAAY,SAAS,YAAY;AAC7B,cAAI,cAAc;AAClB,cAAI,KAAK,WAAW,UAAU,GAAG,GAAG,SAAS,UAAU,GAAG;AACtD,2BAAe;AAAA,UACnB;AACA,0BAAgB;AAChB,cAAI,KAAK,WAAW,UAAU,GAAG,GAAG,SAAS,UAAU,GAAG;AACtD,2BAAe;AAAA,UACnB;AACA,0BAAgB;AAChB,cAAI,KAAK,WAAW,UAAU,GAAG,GAAG,SAAS,UAAU,GAAG;AACtD,2BAAe;AAAA,UACnB;AACA,0BAAgB;AAChB,cAAI,KAAK,WAAW,GAAG,aAAa,GAAG,SAAS,UAAU,GAAG;AACzD,2BAAe;AAAA,UACnB;AACA,0BAAgB;AAChB,cAAI,KAAK,WAAW,GAAG,aAAa,GAAG,SAAS,UAAU,GAAG;AACzD,2BAAe;AAAA,UACnB;AACA,0BAAgB;AAChB,cAAI,KAAK,WAAW,GAAG,aAAa,GAAG,SAAS,UAAU,GAAG;AACzD,2BAAe;AAAA,UACnB;AACA,0BAAgB;AAChB,cAAI,KAAK,WAAW,GAAG,aAAa,GAAG,SAAS,UAAU,GAAG;AACzD,2BAAe;AAAA,UACnB;AACA,0BAAgB;AAChB,cAAI,KAAK,WAAW,GAAG,aAAa,GAAG,SAAS,UAAU,GAAG;AACzD,2BAAe;AAAA,UACnB;AACA,iBAAO;AAAA,QACX;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAUA,YAAY,SAAS,YAAY;AAC7B,cAAI,cAAc;AAClB,cAAI,KAAK,WAAW,UAAU,GAAG,GAAG,SAAS,UAAU,GAAG;AACtD,2BAAe;AAAA,UACnB;AACA,0BAAgB;AAChB,cAAI,KAAK,WAAW,UAAU,GAAG,aAAa,GAAG,SAAS,UAAU,GAAG;AACnE,2BAAe;AAAA,UACnB;AACA,0BAAgB;AAChB,cAAI,KAAK,WAAW,GAAG,aAAa,GAAG,SAAS,UAAU,GAAG;AACzD,2BAAe;AAAA,UACnB;AACA,0BAAgB;AAChB,cAAI,KAAK,WAAW,GAAG,aAAa,GAAG,SAAS,UAAU,GAAG;AACzD,2BAAe;AAAA,UACnB;AACA,0BAAgB;AAChB,cAAI,KAAK,WAAW,GAAG,aAAa,GAAG,SAAS,UAAU,GAAG;AACzD,2BAAe;AAAA,UACnB;AACA,0BAAgB;AAChB,cAAI,KAAK,WAAW,GAAG,aAAa,GAAG,SAAS,UAAU,GAAG;AACzD,2BAAe;AAAA,UACnB;AACA,0BAAgB;AAChB,cAAI,KAAK,WAAW,GAAG,aAAa,GAAG,SAAS,UAAU,GAAG;AACzD,2BAAe;AAAA,UACnB;AACA,0BAAgB;AAChB,cAAI,KAAK,WAAW,GAAG,aAAa,GAAG,SAAS,UAAU,GAAG;AACzD,2BAAe;AAAA,UACnB;AACA,iBAAO;AAAA,QACX;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAUA,YAAY,SAAS,YAAY;AAC7B,cAAI,cAAc;AAClB,cAAI,KAAK,WAAW,UAAU,GAAG,GAAG,SAAS,UAAU,GAAG;AACtD,2BAAe;AAAA,UACnB;AACA,0BAAgB;AAChB,cAAI,KAAK,WAAW,UAAU,GAAG,GAAG,SAAS,UAAU,GAAG;AACtD,2BAAe;AAAA,UACnB;AACA,0BAAgB;AAChB,cAAI,KAAK,WAAW,UAAU,GAAG,GAAG,SAAS,UAAU,GAAG;AACtD,2BAAe;AAAA,UACnB;AACA,0BAAgB;AAChB,cAAI,KAAK,WAAW,GAAG,aAAa,GAAG,SAAS,UAAU,GAAG;AACzD,2BAAe;AAAA,UACnB;AACA,0BAAgB;AAChB,cAAI,KAAK,WAAW,GAAG,aAAa,GAAG,SAAS,UAAU,GAAG;AACzD,2BAAe;AAAA,UACnB;AACA,0BAAgB;AAChB,cAAI,KAAK,WAAW,GAAG,aAAa,GAAG,SAAS,UAAU,GAAG;AACzD,2BAAe;AAAA,UACnB;AACA,0BAAgB;AAChB,cAAI,KAAK,WAAW,GAAG,aAAa,GAAG,SAAS,UAAU,GAAG;AACzD,2BAAe;AAAA,UACnB;AACA,0BAAgB;AAChB,cAAI,KAAK,WAAW,GAAG,aAAa,GAAG,SAAS,UAAU,GAAG;AACzD,2BAAe;AAAA,UACnB;AACA,iBAAO;AAAA,QACX;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAQA,kBAAkB,WAAW;AACzB,gBAAM,iBAAiB,KAAK,QAAQ,kBAAkB;AACtD,gBAAM,oBAAoB,KAAK,QAAQ,qBAAqB;AAC5D,cAAI,UAAU,UAAU,MAAM,gBAAgB;AAC1C,kBAAM,IAAI,yBAAyB,oDAAoD;AAAA,UAC3F;AACA,gBAAM,qBAAqB,KAAK,QAAQ,sBAAsB;AAC9D,gBAAM,wBAAwB,KAAK,QAAQ,yBAAyB;AACpE,gBAAM,oBAAoB,iBAAiB,qBAAqB;AAChE,gBAAM,uBAAuB,oBAAoB,wBAAwB;AACzE,gBAAM,oBAAoB,oBAAoB;AAC9C,gBAAM,uBAAuB,uBAAuB;AACpD,gBAAM,4BAA4B,IAAI,UAAU,sBAAsB,iBAAiB;AACvF,mBAAS,gBAAgB,GAAG,gBAAgB,mBAAmB,EAAE,eAAe;AAC5E,kBAAM,sBAAsB,gBAAgB;AAC5C,qBAAS,mBAAmB,GAAG,mBAAmB,sBAAsB,EAAE,kBAAkB;AACxF,oBAAM,yBAAyB,mBAAmB;AAClD,uBAAS,IAAI,GAAG,IAAI,oBAAoB,EAAE,GAAG;AACzC,sBAAM,gBAAgB,iBAAiB,qBAAqB,KAAK,IAAI;AACrE,sBAAM,iBAAiB,sBAAsB;AAC7C,yBAAS,IAAI,GAAG,IAAI,uBAAuB,EAAE,GAAG;AAC5C,wBAAM,mBAAmB,oBAAoB,wBAAwB,KAAK,IAAI;AAC9E,sBAAI,UAAU,IAAI,kBAAkB,aAAa,GAAG;AAChD,0BAAM,oBAAoB,yBAAyB;AACnD,8CAA0B,IAAI,mBAAmB,cAAc;AAAA,kBACnE;AAAA,gBACJ;AAAA,cACJ;AAAA,YACJ;AAAA,UACJ;AACA,iBAAO;AAAA,QACX;AAAA,MACJ;AAAA,MASA,MAAM,UAAU;AAAA,QACZ,YAAY,kBAAkB,WAAW;AACrC,eAAK,mBAAmB;AACxB,eAAK,YAAY;AAAA,QACrB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAWA,OAAO,cAAc,cAAc,SAAS;AAExC,gBAAM,WAAW,QAAQ,YAAY;AAErC,cAAI,cAAc;AAClB,gBAAM,eAAe,SAAS,YAAY;AAC1C,mBAAS,WAAW,cAAc;AAC9B,2BAAe,QAAQ,SAAS;AAAA,UACpC;AAEA,gBAAM,SAAS,IAAI,MAAM,WAAW;AACpC,cAAI,kBAAkB;AACtB,mBAAS,WAAW,cAAc;AAC9B,qBAAS,IAAI,GAAG,IAAI,QAAQ,SAAS,GAAG,KAAK;AACzC,oBAAM,mBAAmB,QAAQ,iBAAiB;AAClD,oBAAM,oBAAoB,SAAS,eAAe,IAAI;AACtD,qBAAO,iBAAiB,IAAI,IAAI,UAAU,kBAAkB,IAAI,WAAW,iBAAiB,CAAC;AAAA,YACjG;AAAA,UACJ;AAIA,gBAAM,6BAA6B,OAAO,CAAC,EAAE,UAAU;AAEvD,gBAAM,+BAA+B,6BAA6B,SAAS,eAAe;AAC1F,gBAAM,gCAAgC,+BAA+B;AAGrE,cAAI,qBAAqB;AACzB,mBAAS,IAAI,GAAG,IAAI,+BAA+B,KAAK;AACpD,qBAAS,IAAI,GAAG,IAAI,iBAAiB,KAAK;AACtC,qBAAO,CAAC,EAAE,UAAU,CAAC,IAAI,aAAa,oBAAoB;AAAA,YAC9D;AAAA,UACJ;AAEA,gBAAM,iBAAiB,QAAQ,iBAAiB,MAAM;AACtD,gBAAM,kBAAkB,iBAAiB,IAAI;AAC7C,mBAAS,IAAI,GAAG,IAAI,iBAAiB,KAAK;AACtC,mBAAO,CAAC,EAAE,UAAU,+BAA+B,CAAC,IAAI,aAAa,oBAAoB;AAAA,UAC7F;AAEA,gBAAM,MAAM,OAAO,CAAC,EAAE,UAAU;AAChC,mBAAS,IAAI,8BAA8B,IAAI,KAAK,KAAK;AACrD,qBAAS,IAAI,GAAG,IAAI,iBAAiB,KAAK;AACtC,oBAAM,UAAU,kBAAkB,IAAI,KAAK,kBAAkB;AAC7D,oBAAM,UAAU,kBAAkB,UAAU,IAAI,IAAI,IAAI;AACxD,qBAAO,OAAO,EAAE,UAAU,OAAO,IAAI,aAAa,oBAAoB;AAAA,YAC1E;AAAA,UACJ;AACA,cAAI,uBAAuB,aAAa,QAAQ;AAC5C,kBAAM,IAAI,yBAAyB;AAAA,UACvC;AACA,iBAAO;AAAA,QACX;AAAA,QACA,sBAAsB;AAClB,iBAAO,KAAK;AAAA,QAChB;AAAA,QACA,eAAe;AACX,iBAAO,KAAK;AAAA,QAChB;AAAA,MACJ;AAAA,MA0BA,MAAM,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA,QAKZ,YAAY,OAAO;AACf,eAAK,QAAQ;AACb,eAAK,aAAa;AAClB,eAAK,YAAY;AAAA,QACrB;AAAA;AAAA;AAAA;AAAA,QAIA,eAAe;AACX,iBAAO,KAAK;AAAA,QAChB;AAAA;AAAA;AAAA;AAAA,QAIA,gBAAgB;AACZ,iBAAO,KAAK;AAAA,QAChB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAOA,SAAS,SAAiB;AACtB,cAAI,UAAU,KAAK,UAAU,MAAM,UAAU,KAAK,UAAU,GAAG;AAC3D,kBAAM,IAAI,yBAAyB,KAAK,OAAO;AAAA,UACnD;AACA,cAAI,SAAS;AACb,cAAI,YAAY,KAAK;AACrB,cAAI,aAAa,KAAK;AACtB,gBAAM,QAAQ,KAAK;AAEnB,cAAI,YAAY,GAAG;AACf,kBAAM,WAAW,IAAI;AACrB,kBAAM,SAAS,UAAU,WAAW,UAAU;AAC9C,kBAAM,gBAAgB,WAAW;AACjC,kBAAM,OAAQ,OAAS,IAAI,UAAY;AACvC,sBAAU,MAAM,UAAU,IAAI,SAAS;AACvC,uBAAW;AACX,yBAAa;AACb,gBAAI,cAAc,GAAG;AACjB,0BAAY;AACZ;AAAA,YACJ;AAAA,UACJ;AAEA,cAAI,UAAU,GAAG;AACb,mBAAO,WAAW,GAAG;AACjB,uBAAU,UAAU,IAAM,MAAM,UAAU,IAAI;AAC9C;AACA,yBAAW;AAAA,YACf;AAEA,gBAAI,UAAU,GAAG;AACb,oBAAM,gBAAgB,IAAI;AAC1B,oBAAM,OAAQ,OAAQ,iBAAkB;AACxC,uBAAU,UAAU,WAAa,MAAM,UAAU,IAAI,SAAS;AAC9D,2BAAa;AAAA,YACjB;AAAA,UACJ;AACA,eAAK,YAAY;AACjB,eAAK,aAAa;AAClB,iBAAO;AAAA,QACX;AAAA;AAAA;AAAA;AAAA,QAIA,YAAY;AACR,iBAAO,KAAK,KAAK,MAAM,SAAS,KAAK,cAAc,KAAK;AAAA,QAC5D;AAAA,MACJ;AAEA,UAAI;AACJ,OAAC,SAAUS,OAAM;AACb,QAAAA,MAAKA,MAAK,YAAY,IAAI,CAAC,IAAI;AAC/B,QAAAA,MAAKA,MAAK,cAAc,IAAI,CAAC,IAAI;AACjC,QAAAA,MAAKA,MAAK,YAAY,IAAI,CAAC,IAAI;AAC/B,QAAAA,MAAKA,MAAK,aAAa,IAAI,CAAC,IAAI;AAChC,QAAAA,MAAKA,MAAK,gBAAgB,IAAI,CAAC,IAAI;AACnC,QAAAA,MAAKA,MAAK,gBAAgB,IAAI,CAAC,IAAI;AACnC,QAAAA,MAAKA,MAAK,gBAAgB,IAAI,CAAC,IAAI;AAAA,MACvC,GAAG,SAAS,OAAO,CAAC,EAAE;AAAA,MAUtB,MAAM,uBAAuB;AAAA,QACzB,OAAO,OAAO,OAAO;AACjB,gBAAM,OAAO,IAAI,UAAU,KAAK;AAChC,gBAAM,SAAS,IAAI,cAAc;AACjC,gBAAM,gBAAgB,IAAI,cAAc;AACxC,gBAAM,eAAe,IAAI,MAAM;AAC/B,cAAI,OAAO,KAAK;AAChB,aAAG;AACC,gBAAI,SAAS,KAAK,cAAc;AAC5B,qBAAO,KAAK,mBAAmB,MAAM,QAAQ,aAAa;AAAA,YAC9D,OACK;AACD,sBAAQ,MAAM;AAAA,gBACV,KAAK,KAAK;AACN,uBAAK,iBAAiB,MAAM,MAAM;AAClC;AAAA,gBACJ,KAAK,KAAK;AACN,uBAAK,kBAAkB,MAAM,MAAM;AACnC;AAAA,gBACJ,KAAK,KAAK;AACN,uBAAK,qBAAqB,MAAM,MAAM;AACtC;AAAA,gBACJ,KAAK,KAAK;AACN,uBAAK,qBAAqB,MAAM,MAAM;AACtC;AAAA,gBACJ,KAAK,KAAK;AACN,uBAAK,qBAAqB,MAAM,QAAQ,YAAY;AACpD;AAAA,gBACJ;AACI,wBAAM,IAAI,gBAAgB;AAAA,cAClC;AACA,qBAAO,KAAK;AAAA,YAChB;AAAA,UACJ,SAAS,SAAS,KAAK,cAAc,KAAK,UAAU,IAAI;AACxD,cAAI,cAAc,OAAO,IAAI,GAAG;AAC5B,mBAAO,OAAO,cAAc,SAAS,CAAC;AAAA,UAC1C;AACA,iBAAO,IAAI,cAAc,OAAO,OAAO,SAAS,GAAG,aAAa,WAAW,IAAI,OAAO,cAAc,IAAI;AAAA,QAC5G;AAAA;AAAA;AAAA;AAAA,QAIA,OAAO,mBAAmB,MAAM,QAAQ,eAAe;AACnD,cAAI,aAAa;AACjB,aAAG;AACC,gBAAI,UAAU,KAAK,SAAS,CAAC;AAC7B,gBAAI,YAAY,GAAG;AACf,oBAAM,IAAI,gBAAgB;AAAA,YAC9B,WACS,WAAW,KAAK;AACrB,kBAAI,YAAY;AACZ,2BAAW;AAAA,cAEf;AACA,qBAAO,OAAO,OAAO,aAAa,UAAU,CAAC,CAAC;AAC9C,qBAAO,KAAK;AAAA,YAChB,WACS,YAAY,KAAK;AACtB,qBAAO,KAAK;AAAA,YAChB,WACS,WAAW,KAAK;AACrB,oBAAM,QAAQ,UAAU;AACxB,kBAAI,QAAQ,IAAI;AACZ,uBAAO,OAAO,GAAG;AAAA,cACrB;AACA,qBAAO,OAAO,KAAK,KAAK;AAAA,YAC5B,OACK;AACD,sBAAQ,SAAS;AAAA,gBACb,KAAK;AACD,yBAAO,KAAK;AAAA,gBAChB,KAAK;AACD,yBAAO,KAAK;AAAA,gBAChB,KAAK;AACD,yBAAO,OAAO,OAAO,aAAa,EAAE,CAAC;AACrC;AAAA,gBACJ,KAAK;AAAA;AAAA,gBACL,KAAK;AAGD;AAAA,gBACJ,KAAK;AACD,+BAAa;AACb;AAAA,gBACJ,KAAK;AACD,yBAAO,OAAO,SAAmB;AACjC,gCAAc,OAAO,GAAG,IAAc;AACtC;AAAA,gBACJ,KAAK;AACD,yBAAO,OAAO,SAAmB;AACjC,gCAAc,OAAO,GAAG,IAAc;AACtC;AAAA,gBACJ,KAAK;AACD,yBAAO,KAAK;AAAA,gBAChB,KAAK;AACD,yBAAO,KAAK;AAAA,gBAChB,KAAK;AACD,yBAAO,KAAK;AAAA,gBAChB,KAAK;AAID;AAAA,gBACJ;AAGI,sBAAI,YAAY,OAAO,KAAK,UAAU,MAAM,GAAG;AAC3C,0BAAM,IAAI,gBAAgB;AAAA,kBAC9B;AACA;AAAA,cACR;AAAA,YACJ;AAAA,UACJ,SAAS,KAAK,UAAU,IAAI;AAC5B,iBAAO,KAAK;AAAA,QAChB;AAAA;AAAA;AAAA;AAAA,QAIA,OAAO,iBAAiB,MAAM,QAAQ;AAIlC,cAAI,aAAa;AACjB,gBAAM,UAAU,CAAC;AACjB,cAAI,QAAQ;AACZ,aAAG;AAEC,gBAAI,KAAK,UAAU,MAAM,GAAG;AACxB;AAAA,YACJ;AACA,kBAAM,YAAY,KAAK,SAAS,CAAC;AACjC,gBAAI,cAAc,KAAK;AACnB;AAAA,YACJ;AACA,iBAAK,cAAc,WAAW,KAAK,SAAS,CAAC,GAAG,OAAO;AACvD,qBAAS,IAAI,GAAG,IAAI,GAAG,KAAK;AACxB,oBAAM,SAAS,QAAQ,CAAC;AACxB,sBAAQ,OAAO;AAAA,gBACX,KAAK;AACD,sBAAI,SAAS,GAAG;AACZ,4BAAQ,SAAS;AAAA,kBACrB,WACS,SAAS,KAAK,oBAAoB,QAAQ;AAC/C,0BAAM,UAAU,KAAK,oBAAoB,MAAM;AAC/C,wBAAI,YAAY;AACZ,6BAAO,OAAO,OAAO,aAAa,QAAQ,WAAW,CAAC,IAAI,GAAG,CAAC;AAC9D,mCAAa;AAAA,oBACjB,OACK;AACD,6BAAO,OAAO,OAAO;AAAA,oBACzB;AAAA,kBACJ,OACK;AACD,0BAAM,IAAI,gBAAgB;AAAA,kBAC9B;AACA;AAAA,gBACJ,KAAK;AACD,sBAAI,YAAY;AACZ,2BAAO,OAAO,OAAO,aAAa,SAAS,GAAG,CAAC;AAC/C,iCAAa;AAAA,kBACjB,OACK;AACD,2BAAO,OAAO,OAAO,aAAa,MAAM,CAAC;AAAA,kBAC7C;AACA,0BAAQ;AACR;AAAA,gBACJ,KAAK;AACD,sBAAI,SAAS,KAAK,qBAAqB,QAAQ;AAC3C,0BAAM,UAAU,KAAK,qBAAqB,MAAM;AAChD,wBAAI,YAAY;AACZ,6BAAO,OAAO,OAAO,aAAa,QAAQ,WAAW,CAAC,IAAI,GAAG,CAAC;AAC9D,mCAAa;AAAA,oBACjB,OACK;AACD,6BAAO,OAAO,OAAO;AAAA,oBACzB;AAAA,kBACJ,OACK;AACD,4BAAQ,QAAQ;AAAA,sBACZ,KAAK;AACD,+BAAO,OAAO,OAAO,aAAa,EAAE,CAAC;AACrC;AAAA,sBACJ,KAAK;AACD,qCAAa;AACb;AAAA,sBACJ;AACI,8BAAM,IAAI,gBAAgB;AAAA,oBAClC;AAAA,kBACJ;AACA,0BAAQ;AACR;AAAA,gBACJ,KAAK;AACD,sBAAI,YAAY;AACZ,2BAAO,OAAO,OAAO,aAAa,SAAS,GAAG,CAAC;AAC/C,iCAAa;AAAA,kBACjB,OACK;AACD,2BAAO,OAAO,OAAO,aAAa,SAAS,EAAE,CAAC;AAAA,kBAClD;AACA,0BAAQ;AACR;AAAA,gBACJ;AACI,wBAAM,IAAI,gBAAgB;AAAA,cAClC;AAAA,YACJ;AAAA,UACJ,SAAS,KAAK,UAAU,IAAI;AAAA,QAChC;AAAA;AAAA;AAAA;AAAA,QAIA,OAAO,kBAAkB,MAAM,QAAQ;AAInC,cAAI,aAAa;AACjB,cAAI,UAAU,CAAC;AACf,cAAI,QAAQ;AACZ,aAAG;AAEC,gBAAI,KAAK,UAAU,MAAM,GAAG;AACxB;AAAA,YACJ;AACA,kBAAM,YAAY,KAAK,SAAS,CAAC;AACjC,gBAAI,cAAc,KAAK;AACnB;AAAA,YACJ;AACA,iBAAK,cAAc,WAAW,KAAK,SAAS,CAAC,GAAG,OAAO;AACvD,qBAAS,IAAI,GAAG,IAAI,GAAG,KAAK;AACxB,oBAAM,SAAS,QAAQ,CAAC;AACxB,sBAAQ,OAAO;AAAA,gBACX,KAAK;AACD,sBAAI,SAAS,GAAG;AACZ,4BAAQ,SAAS;AAAA,kBACrB,WACS,SAAS,KAAK,qBAAqB,QAAQ;AAChD,0BAAM,WAAW,KAAK,qBAAqB,MAAM;AACjD,wBAAI,YAAY;AACZ,6BAAO,OAAO,OAAO,aAAa,SAAS,WAAW,CAAC,IAAI,GAAG,CAAC;AAC/D,mCAAa;AAAA,oBACjB,OACK;AACD,6BAAO,OAAO,QAAQ;AAAA,oBAC1B;AAAA,kBACJ,OACK;AACD,0BAAM,IAAI,gBAAgB;AAAA,kBAC9B;AACA;AAAA,gBACJ,KAAK;AACD,sBAAI,YAAY;AACZ,2BAAO,OAAO,OAAO,aAAa,SAAS,GAAG,CAAC;AAC/C,iCAAa;AAAA,kBACjB,OACK;AACD,2BAAO,OAAO,OAAO,aAAa,MAAM,CAAC;AAAA,kBAC7C;AACA,0BAAQ;AACR;AAAA,gBACJ,KAAK;AAED,sBAAI,SAAS,KAAK,sBAAsB,QAAQ;AAC5C,0BAAM,WAAW,KAAK,sBAAsB,MAAM;AAClD,wBAAI,YAAY;AACZ,6BAAO,OAAO,OAAO,aAAa,SAAS,WAAW,CAAC,IAAI,GAAG,CAAC;AAC/D,mCAAa;AAAA,oBACjB,OACK;AACD,6BAAO,OAAO,QAAQ;AAAA,oBAC1B;AAAA,kBACJ,OACK;AACD,4BAAQ,QAAQ;AAAA,sBACZ,KAAK;AACD,+BAAO,OAAO,OAAO,aAAa,EAAE,CAAC;AACrC;AAAA,sBACJ,KAAK;AACD,qCAAa;AACb;AAAA,sBACJ;AACI,8BAAM,IAAI,gBAAgB;AAAA,oBAClC;AAAA,kBACJ;AACA,0BAAQ;AACR;AAAA,gBACJ,KAAK;AACD,sBAAI,SAAS,KAAK,sBAAsB,QAAQ;AAC5C,0BAAM,WAAW,KAAK,sBAAsB,MAAM;AAClD,wBAAI,YAAY;AACZ,6BAAO,OAAO,OAAO,aAAa,SAAS,WAAW,CAAC,IAAI,GAAG,CAAC;AAC/D,mCAAa;AAAA,oBACjB,OACK;AACD,6BAAO,OAAO,QAAQ;AAAA,oBAC1B;AACA,4BAAQ;AAAA,kBACZ,OACK;AACD,0BAAM,IAAI,gBAAgB;AAAA,kBAC9B;AACA;AAAA,gBACJ;AACI,wBAAM,IAAI,gBAAgB;AAAA,cAClC;AAAA,YACJ;AAAA,UACJ,SAAS,KAAK,UAAU,IAAI;AAAA,QAChC;AAAA;AAAA;AAAA;AAAA,QAIA,OAAO,qBAAqB,MAAM,QAAQ;AAGtC,gBAAM,UAAU,CAAC;AACjB,aAAG;AAEC,gBAAI,KAAK,UAAU,MAAM,GAAG;AACxB;AAAA,YACJ;AACA,kBAAM,YAAY,KAAK,SAAS,CAAC;AACjC,gBAAI,cAAc,KAAK;AACnB;AAAA,YACJ;AACA,iBAAK,cAAc,WAAW,KAAK,SAAS,CAAC,GAAG,OAAO;AACvD,qBAAS,IAAI,GAAG,IAAI,GAAG,KAAK;AACxB,oBAAM,SAAS,QAAQ,CAAC;AACxB,sBAAQ,QAAQ;AAAA,gBACZ,KAAK;AACD,yBAAO,OAAO,IAAI;AAClB;AAAA,gBACJ,KAAK;AACD,yBAAO,OAAO,GAAG;AACjB;AAAA,gBACJ,KAAK;AACD,yBAAO,OAAO,GAAG;AACjB;AAAA,gBACJ,KAAK;AACD,yBAAO,OAAO,GAAG;AACjB;AAAA,gBACJ;AACI,sBAAI,SAAS,IAAI;AACb,2BAAO,OAAO,OAAO,aAAa,SAAS,EAAE,CAAC;AAAA,kBAClD,WACS,SAAS,IAAI;AAClB,2BAAO,OAAO,OAAO,aAAa,SAAS,EAAE,CAAC;AAAA,kBAClD,OACK;AACD,0BAAM,IAAI,gBAAgB;AAAA,kBAC9B;AACA;AAAA,cACR;AAAA,YACJ;AAAA,UACJ,SAAS,KAAK,UAAU,IAAI;AAAA,QAChC;AAAA,QACA,OAAO,cAAc,WAAW,YAAY,QAAQ;AAChD,cAAI,gBAAgB,aAAa,KAAK,aAAa;AACnD,cAAI,OAAO,KAAK,MAAM,eAAe,IAAI;AACzC,iBAAO,CAAC,IAAI;AACZ,0BAAgB,OAAO;AACvB,iBAAO,KAAK,MAAM,eAAe,EAAE;AACnC,iBAAO,CAAC,IAAI;AACZ,iBAAO,CAAC,IAAI,eAAe,OAAO;AAAA,QACtC;AAAA;AAAA;AAAA;AAAA,QAIA,OAAO,qBAAqB,MAAM,QAAQ;AACtC,aAAG;AAEC,gBAAI,KAAK,UAAU,KAAK,IAAI;AACxB;AAAA,YACJ;AACA,qBAAS,IAAI,GAAG,IAAI,GAAG,KAAK;AACxB,kBAAI,eAAe,KAAK,SAAS,CAAC;AAElC,kBAAI,iBAAiB,IAAM;AAEvB,sBAAM,WAAW,IAAI,KAAK,aAAa;AACvC,oBAAI,aAAa,GAAG;AAChB,uBAAK,SAAS,QAAQ;AAAA,gBAC1B;AACA;AAAA,cACJ;AACA,mBAAK,eAAe,QAAU,GAAG;AAC7B,gCAAgB;AAAA,cACpB;AACA,qBAAO,OAAO,OAAO,aAAa,YAAY,CAAC;AAAA,YACnD;AAAA,UACJ,SAAS,KAAK,UAAU,IAAI;AAAA,QAChC;AAAA;AAAA;AAAA;AAAA,QAIA,OAAO,qBAAqB,MAAM,QAAQ,cAAc;AAEpD,cAAI,mBAAmB,IAAI,KAAK,cAAc;AAC9C,gBAAM,KAAK,KAAK,oBAAoB,KAAK,SAAS,CAAC,GAAG,kBAAkB;AACxE,cAAI;AACJ,cAAI,OAAO,GAAG;AACV,oBAAQ,KAAK,UAAU,IAAI,IAAI;AAAA,UACnC,WACS,KAAK,KAAK;AACf,oBAAQ;AAAA,UACZ,OACK;AACD,oBAAQ,OAAO,KAAK,OAAO,KAAK,oBAAoB,KAAK,SAAS,CAAC,GAAG,kBAAkB;AAAA,UAC5F;AAEA,cAAI,QAAQ,GAAG;AACX,kBAAM,IAAI,gBAAgB;AAAA,UAC9B;AACA,gBAAM,QAAQ,IAAI,WAAW,KAAK;AAClC,mBAAS,IAAI,GAAG,IAAI,OAAO,KAAK;AAG5B,gBAAI,KAAK,UAAU,IAAI,GAAG;AACtB,oBAAM,IAAI,gBAAgB;AAAA,YAC9B;AACA,kBAAM,CAAC,IAAI,KAAK,oBAAoB,KAAK,SAAS,CAAC,GAAG,kBAAkB;AAAA,UAC5E;AACA,uBAAa,KAAK,KAAK;AACvB,cAAI;AACA,mBAAO,OAAO,eAAe,OAAO,OAAO,YAAY,QAAQ,CAAC;AAAA,UACpE,SACO,KAAK;AACR,kBAAM,IAAI,sBAAsB,kDAAkD,IAAI,OAAO;AAAA,UACjG;AAAA,QACJ;AAAA;AAAA;AAAA;AAAA,QAIA,OAAO,oBAAoB,2BAA2B,yBAAyB;AAC3E,gBAAM,qBAAuB,MAAM,0BAA2B,MAAO;AACrE,gBAAM,eAAe,4BAA4B;AACjD,iBAAO,gBAAgB,IAAI,eAAe,eAAe;AAAA,QAC7D;AAAA,MACJ;AAKA,6BAAuB,sBAAsB;AAAA,QACzC;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QACjE;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QACjE;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,MAC3D;AACA,6BAAuB,uBAAuB;AAAA,QAC1C;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAClE;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,MACjE;AAKA,6BAAuB,uBAAuB;AAAA,QAC1C;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QACjE;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QACjE;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,MAC3D;AAEA,6BAAuB,wBAAwB,uBAAuB;AACtE,6BAAuB,wBAAwB;AAAA,QAC3C;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QACtE;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK,OAAO,aAAa,GAAG;AAAA,MAC3G;AAAA,MAuBA,MAAM,UAAU;AAAA,QACZ,cAAc;AACV,eAAK,YAAY,IAAI,mBAAmB,UAAU,qBAAqB;AAAA,QAC3E;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAUA,OAAO,MAAM;AAET,gBAAM,SAAS,IAAI,gBAAgB,IAAI;AACvC,gBAAM,UAAU,OAAO,WAAW;AAElC,gBAAM,YAAY,OAAO,cAAc;AAEvC,gBAAM,aAAa,UAAU,cAAc,WAAW,OAAO;AAE7D,cAAI,aAAa;AACjB,mBAAS,MAAM,YAAY;AACvB,0BAAc,GAAG,oBAAoB;AAAA,UACzC;AACA,gBAAM,cAAc,IAAI,WAAW,UAAU;AAC7C,gBAAM,kBAAkB,WAAW;AAEnC,mBAAS,IAAI,GAAG,IAAI,iBAAiB,KAAK;AACtC,kBAAM,YAAY,WAAW,CAAC;AAC9B,kBAAM,gBAAgB,UAAU,aAAa;AAC7C,kBAAM,mBAAmB,UAAU,oBAAoB;AACvD,iBAAK,cAAc,eAAe,gBAAgB;AAClD,qBAAS,IAAI,GAAG,IAAI,kBAAkB,KAAK;AAEvC,0BAAY,IAAI,kBAAkB,CAAC,IAAI,cAAc,CAAC;AAAA,YAC1D;AAAA,UACJ;AAEA,iBAAO,uBAAuB,OAAO,WAAW;AAAA,QACpD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QASA,cAAc,eAAe,kBAAkB;AAG3C,gBAAM,gBAAgB,IAAI,WAAW,aAAa;AAIlD,cAAI;AACA,iBAAK,UAAU,OAAO,eAAe,cAAc,SAAS,gBAAgB;AAAA,UAChF,SACO,SAAoC;AACvC,kBAAM,IAAI,kBAAkB;AAAA,UAChC;AAGA,mBAAS,IAAI,GAAG,IAAI,kBAAkB,KAAK;AACvC,0BAAc,CAAC,IAAI,cAAc,CAAC;AAAA,UACtC;AAAA,QACJ;AAAA,MACJ;AAAA,MAQA,MAAM,WAAW;AAAA,QACb,YAAY,OAAO;AACf,eAAK,QAAQ;AACb,eAAK,oBAAoB,IAAI,uBAAuB,KAAK,KAAK;AAAA,QAClE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAOA,SAAS;AACL,gBAAM,eAAe,KAAK,kBAAkB,OAAO;AACnD,cAAI,SAAS,KAAK,aAAa,YAAY;AAC3C,mBAAS,KAAK,aAAa,MAAM;AACjC,iBAAO,CAAC,IAAI,KAAK,gBAAgB,MAAM;AACvC,cAAI,CAAC,OAAO,CAAC,GAAG;AACZ,kBAAM,IAAI,kBAAkB;AAAA,UAChC;AACA,mBAAS,KAAK,oBAAoB,MAAM;AACxC,gBAAM,UAAU,OAAO,CAAC;AACxB,gBAAM,aAAa,OAAO,CAAC;AAC3B,gBAAM,cAAc,OAAO,CAAC;AAC5B,gBAAM,WAAW,OAAO,CAAC;AACzB,cAAI,eAAe,KAAK,mBAAmB,SAAS,QAAQ,IAAI;AAChE,cAAI,iBAAiB,KAAK,mBAAmB,aAAa,QAAQ,IAAI;AACtE,eAAK,eAAe,OAAU,GAAG;AAC7B,4BAAgB;AAAA,UACpB;AACA,eAAK,iBAAiB,OAAU,GAAG;AAC/B,8BAAkB;AAAA,UACtB;AACA,cAAI,IAAI,eAAe,IAAI,kBAAkB,IAAI,iBAAiB,IAAI,cAAc;AAEhF,2BAAe,iBAAiB,KAAK,IAAI,cAAc,cAAc;AAAA,UACzE;AACA,cAAI,OAAO,WAAW,WAAW,KAAK,OAAO,SAAS,YAAY,aAAa,UAAU,cAAc,cAAc;AACrH,iBAAO,IAAI,eAAe,MAAM,CAAC,SAAS,YAAY,aAAa,QAAQ,CAAC;AAAA,QAChF;AAAA,QACA,OAAO,WAAW,OAAO,IAAI,KAAK;AAC9B,cAAI,KAAK,GAAG,KAAK,IAAI,MAAM,KAAK,MAAM,MAAM;AAC5C,cAAI,KAAK,GAAG,KAAK,IAAI,MAAM,KAAK,MAAM,MAAM;AAC5C,iBAAO,IAAI,YAAY,MAAM,KAAK,IAAI,GAAG,MAAM,KAAK,IAAI,CAAC;AAAA,QAC7D;AAAA,QACA,OAAO,SAAS,OAAO,OAAO,OAAO;AACjC,cAAI,IAAI,MAAM,KAAK;AACnB,cAAI,IAAI,MAAM,KAAK;AACnB,cAAI,IAAI,OAAO;AACX,iBAAK;AAAA,UACT,OACK;AACD,iBAAK;AAAA,UACT;AACA,cAAI,IAAI,OAAO;AACX,iBAAK;AAAA,UACT,OACK;AACD,iBAAK;AAAA,UACT;AACA,iBAAO,IAAI,YAAY,GAAG,CAAC;AAAA,QAC/B;AAAA;AAAA;AAAA;AAAA,QAIA,aAAa,cAAc;AAGvB,cAAI,SAAS,aAAa,CAAC;AAC3B,cAAI,SAAS,aAAa,CAAC;AAC3B,cAAI,SAAS,aAAa,CAAC;AAC3B,cAAI,SAAS,aAAa,CAAC;AAC3B,cAAI,OAAO,KAAK,mBAAmB,QAAQ,MAAM;AACjD,cAAI,OAAO,KAAK,mBAAmB,QAAQ,MAAM;AACjD,cAAI,OAAO,KAAK,mBAAmB,QAAQ,MAAM;AACjD,cAAI,OAAO,KAAK,mBAAmB,QAAQ,MAAM;AAIjD,cAAI,MAAM;AACV,cAAI,SAAS,CAAC,QAAQ,QAAQ,QAAQ,MAAM;AAC5C,cAAI,MAAM,MAAM;AACZ,kBAAM;AACN,mBAAO,CAAC,IAAI;AACZ,mBAAO,CAAC,IAAI;AACZ,mBAAO,CAAC,IAAI;AACZ,mBAAO,CAAC,IAAI;AAAA,UAChB;AACA,cAAI,MAAM,MAAM;AACZ,kBAAM;AACN,mBAAO,CAAC,IAAI;AACZ,mBAAO,CAAC,IAAI;AACZ,mBAAO,CAAC,IAAI;AACZ,mBAAO,CAAC,IAAI;AAAA,UAChB;AACA,cAAI,MAAM,MAAM;AACZ,mBAAO,CAAC,IAAI;AACZ,mBAAO,CAAC,IAAI;AACZ,mBAAO,CAAC,IAAI;AACZ,mBAAO,CAAC,IAAI;AAAA,UAChB;AACA,iBAAO;AAAA,QACX;AAAA;AAAA;AAAA;AAAA,QAIA,aAAa,QAAQ;AAIjB,cAAI,SAAS,OAAO,CAAC;AACrB,cAAI,SAAS,OAAO,CAAC;AACrB,cAAI,SAAS,OAAO,CAAC;AACrB,cAAI,SAAS,OAAO,CAAC;AAGrB,cAAI,KAAK,KAAK,mBAAmB,QAAQ,MAAM;AAC/C,cAAI,UAAU,WAAW,WAAW,QAAQ,SAAS,KAAK,KAAK,CAAC;AAChE,cAAI,UAAU,WAAW,WAAW,QAAQ,SAAS,KAAK,KAAK,CAAC;AAChE,cAAI,OAAO,KAAK,mBAAmB,SAAS,MAAM;AAClD,cAAI,OAAO,KAAK,mBAAmB,SAAS,MAAM;AAIlD,cAAI,OAAO,MAAM;AAEb,mBAAO,CAAC,IAAI;AACZ,mBAAO,CAAC,IAAI;AACZ,mBAAO,CAAC,IAAI;AACZ,mBAAO,CAAC,IAAI;AAAA,UAChB,OACK;AAED,mBAAO,CAAC,IAAI;AACZ,mBAAO,CAAC,IAAI;AACZ,mBAAO,CAAC,IAAI;AACZ,mBAAO,CAAC,IAAI;AAAA,UAChB;AACA,iBAAO;AAAA,QACX;AAAA;AAAA;AAAA;AAAA,QAIA,gBAAgB,QAAQ;AAIpB,cAAI,SAAS,OAAO,CAAC;AACrB,cAAI,SAAS,OAAO,CAAC;AACrB,cAAI,SAAS,OAAO,CAAC;AACrB,cAAI,SAAS,OAAO,CAAC;AAErB,cAAI,QAAQ,KAAK,mBAAmB,QAAQ,MAAM;AAClD,cAAI,UAAU,KAAK,mBAAmB,QAAQ,MAAM;AACpD,cAAI,UAAU,WAAW,WAAW,QAAQ,SAAS,UAAU,KAAK,CAAC;AACrE,cAAI,UAAU,WAAW,WAAW,QAAQ,SAAS,QAAQ,KAAK,CAAC;AACnE,kBAAQ,KAAK,mBAAmB,SAAS,MAAM;AAC/C,oBAAU,KAAK,mBAAmB,SAAS,MAAM;AACjD,cAAI,aAAa,IAAI,YAAY,OAAO,KAAK,KAAK,OAAO,KAAK,IAAI,OAAO,KAAK,MAAM,QAAQ,IAAI,OAAO,KAAK,KAAK,OAAO,KAAK,IAAI,OAAO,KAAK,MAAM,QAAQ,EAAE;AAC7J,cAAI,aAAa,IAAI,YAAY,OAAO,KAAK,KAAK,OAAO,KAAK,IAAI,OAAO,KAAK,MAAM,UAAU,IAAI,OAAO,KAAK,KAAK,OAAO,KAAK,IAAI,OAAO,KAAK,MAAM,UAAU,EAAE;AACjK,cAAI,CAAC,KAAK,QAAQ,UAAU,GAAG;AAC3B,gBAAI,KAAK,QAAQ,UAAU,GAAG;AAC1B,qBAAO;AAAA,YACX;AACA,mBAAO;AAAA,UACX;AACA,cAAI,CAAC,KAAK,QAAQ,UAAU,GAAG;AAC3B,mBAAO;AAAA,UACX;AACA,cAAI,QAAQ,KAAK,mBAAmB,SAAS,UAAU,IAAI,KAAK,mBAAmB,SAAS,UAAU;AACtG,cAAI,QAAQ,KAAK,mBAAmB,SAAS,UAAU,IAAI,KAAK,mBAAmB,SAAS,UAAU;AACtG,cAAI,QAAQ,OAAO;AACf,mBAAO;AAAA,UACX,OACK;AACD,mBAAO;AAAA,UACX;AAAA,QACJ;AAAA;AAAA;AAAA;AAAA,QAIA,oBAAoB,QAAQ;AAIxB,cAAI,SAAS,OAAO,CAAC;AACrB,cAAI,SAAS,OAAO,CAAC;AACrB,cAAI,SAAS,OAAO,CAAC;AACrB,cAAI,SAAS,OAAO,CAAC;AAErB,cAAI,OAAO,KAAK,mBAAmB,QAAQ,MAAM,IAAI;AACrD,cAAI,OAAO,KAAK,mBAAmB,QAAQ,MAAM,IAAI;AAErD,cAAI,UAAU,WAAW,WAAW,QAAQ,QAAQ,OAAO,CAAC;AAC5D,cAAI,UAAU,WAAW,WAAW,QAAQ,QAAQ,OAAO,CAAC;AAE5D,iBAAO,KAAK,mBAAmB,SAAS,MAAM,IAAI;AAClD,iBAAO,KAAK,mBAAmB,SAAS,MAAM,IAAI;AAClD,eAAK,OAAO,OAAU,GAAG;AACrB,oBAAQ;AAAA,UACZ;AACA,eAAK,OAAO,OAAU,GAAG;AACrB,oBAAQ;AAAA,UACZ;AAGA,cAAI,WAAW,OAAO,KAAK,IAAI,OAAO,KAAK,IAAI,OAAO,KAAK,IAAI,OAAO,KAAK,KAAK;AAChF,cAAI,WAAW,OAAO,KAAK,IAAI,OAAO,KAAK,IAAI,OAAO,KAAK,IAAI,OAAO,KAAK,KAAK;AAChF,mBAAS,WAAW,SAAS,QAAQ,SAAS,OAAO;AACrD,mBAAS,WAAW,SAAS,QAAQ,SAAS,OAAO;AACrD,mBAAS,WAAW,SAAS,QAAQ,SAAS,OAAO;AACrD,mBAAS,WAAW,SAAS,QAAQ,SAAS,OAAO;AACrD,cAAI;AACJ,cAAI;AAEJ,oBAAU,WAAW,WAAW,QAAQ,QAAQ,OAAO,CAAC;AACxD,oBAAU,WAAW,WAAW,SAAS,QAAQ,OAAO,CAAC;AACzD,oBAAU,WAAW,WAAW,QAAQ,QAAQ,OAAO,CAAC;AACxD,oBAAU,WAAW,WAAW,SAAS,QAAQ,OAAO,CAAC;AACzD,oBAAU,WAAW,WAAW,QAAQ,QAAQ,OAAO,CAAC;AACxD,oBAAU,WAAW,WAAW,SAAS,QAAQ,OAAO,CAAC;AACzD,oBAAU,WAAW,WAAW,QAAQ,QAAQ,OAAO,CAAC;AACxD,oBAAU,WAAW,WAAW,SAAS,QAAQ,OAAO,CAAC;AACzD,iBAAO,CAAC,SAAS,SAAS,SAAS,OAAO;AAAA,QAC9C;AAAA,QACA,QAAQ,GAAG;AACP,iBAAO,EAAE,KAAK,KAAK,KAAK,EAAE,KAAK,IAAI,KAAK,MAAM,SAAS,KAAK,EAAE,KAAK,IAAI,KAAK,EAAE,KAAK,IAAI,KAAK,MAAM,UAAU;AAAA,QAChH;AAAA,QACA,OAAO,WAAW,OAAO,SAAS,YAAY,aAAa,UAAU,YAAY,YAAY;AACzF,gBAAM,UAAU,oBAAoB,YAAY;AAChD,iBAAO,QAAQ,WAAW,OAAO,YAAY,YAAY,KAAK,KAAK,aAAa,KAAK,KAAK,aAAa,KAAK,aAAa,KAAK,KAAK,aAAa,KAAK,QAAQ,KAAK,GAAG,QAAQ,KAAK,GAAG,SAAS,KAAK,GAAG,SAAS,KAAK,GAAG,YAAY,KAAK,GAAG,YAAY,KAAK,GAAG,WAAW,KAAK,GAAG,WAAW,KAAK,CAAC;AAAA,QACvS;AAAA;AAAA;AAAA;AAAA,QAIA,mBAAmB,MAAM,IAAI;AAEzB,cAAI,QAAQ,KAAK,MAAM,KAAK,KAAK,CAAC;AAClC,cAAI,QAAQ,KAAK,MAAM,KAAK,KAAK,CAAC;AAClC,cAAI,MAAM,KAAK,MAAM,GAAG,KAAK,CAAC;AAC9B,cAAI,MAAM,KAAK,MAAM,GAAG,KAAK,CAAC;AAC9B,cAAI,QAAQ,KAAK,IAAI,MAAM,KAAK,IAAI,KAAK,IAAI,MAAM,KAAK;AACxD,cAAI,OAAO;AACP,gBAAI,OAAO;AACX,oBAAQ;AACR,oBAAQ;AACR,mBAAO;AACP,kBAAM;AACN,kBAAM;AAAA,UACV;AACA,cAAI,KAAK,KAAK,IAAI,MAAM,KAAK;AAC7B,cAAI,KAAK,KAAK,IAAI,MAAM,KAAK;AAC7B,cAAI,QAAQ,CAAC,KAAK;AAClB,cAAI,QAAQ,QAAQ,MAAM,IAAI;AAC9B,cAAI,QAAQ,QAAQ,MAAM,IAAI;AAC9B,cAAI,cAAc;AAClB,cAAI,UAAU,KAAK,MAAM,IAAI,QAAQ,QAAQ,OAAO,QAAQ,QAAQ,KAAK;AACzE,mBAAS,IAAI,OAAO,IAAI,OAAO,MAAM,KAAK,KAAK,OAAO;AAClD,gBAAI,UAAU,KAAK,MAAM,IAAI,QAAQ,IAAI,GAAG,QAAQ,IAAI,CAAC;AACzD,gBAAI,YAAY,SAAS;AACrB;AACA,wBAAU;AAAA,YACd;AACA,qBAAS;AACT,gBAAI,QAAQ,GAAG;AACX,kBAAI,MAAM,KAAK;AACX;AAAA,cACJ;AACA,mBAAK;AACL,uBAAS;AAAA,YACb;AAAA,UACJ;AACA,iBAAO;AAAA,QACX;AAAA,MACJ;AAAA,MAsBA,MAAM,iBAAiB;AAAA,QACnB,cAAc;AACV,eAAK,UAAU,IAAI,UAAU;AAAA,QACjC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAcA,OAAO,OAAO,QAAQ,MAAM;AACxB,cAAI;AACJ,cAAI;AACJ,cAAI,SAAS,QAAQ,MAAM,IAAI,iBAAiB,YAAY,GAAG;AAC3D,kBAAM,OAAO,iBAAiB,gBAAgB,MAAM,eAAe,CAAC;AACpE,4BAAgB,KAAK,QAAQ,OAAO,IAAI;AACxC,qBAAS,iBAAiB;AAAA,UAC9B,OACK;AACD,kBAAM,iBAAiB,IAAI,WAAW,MAAM,eAAe,CAAC,EAAE,OAAO;AACrE,4BAAgB,KAAK,QAAQ,OAAO,eAAe,QAAQ,CAAC;AAC5D,qBAAS,eAAe,UAAU;AAAA,UACtC;AACA,gBAAM,WAAW,cAAc,YAAY;AAC3C,gBAAM,SAAS,IAAI,OAAO,cAAc,QAAQ,GAAG,UAAU,IAAI,SAAS,QAAQ,QAAQ,gBAAgB,aAAa,OAAO,kBAAkB,CAAC;AACjJ,gBAAM,eAAe,cAAc,gBAAgB;AACnD,cAAI,gBAAgB,MAAM;AACtB,mBAAO,YAAY,qBAAqB,eAAe,YAAY;AAAA,UACvE;AACA,gBAAM,UAAU,cAAc,WAAW;AACzC,cAAI,WAAW,MAAM;AACjB,mBAAO,YAAY,qBAAqB,wBAAwB,OAAO;AAAA,UAC3E;AACA,iBAAO;AAAA,QACX;AAAA;AAAA,QAEA,QAAQ;AAAA,QAER;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QASA,OAAO,gBAAgB,OAAO;AAC1B,gBAAM,eAAe,MAAM,gBAAgB;AAC3C,gBAAM,mBAAmB,MAAM,oBAAoB;AACnD,cAAI,gBAAgB,QAAQ,oBAAoB,MAAM;AAClD,kBAAM,IAAI,kBAAkB;AAAA,UAChC;AACA,gBAAM,aAAa,KAAK,WAAW,cAAc,KAAK;AACtD,cAAI,MAAM,aAAa,CAAC;AACxB,gBAAM,SAAS,iBAAiB,CAAC;AACjC,cAAI,OAAO,aAAa,CAAC;AACzB,gBAAM,QAAQ,iBAAiB,CAAC;AAChC,gBAAM,eAAe,QAAQ,OAAO,KAAK;AACzC,gBAAM,gBAAgB,SAAS,MAAM,KAAK;AAC1C,cAAI,eAAe,KAAK,gBAAgB,GAAG;AACvC,kBAAM,IAAI,kBAAkB;AAAA,UAChC;AAIA,gBAAM,QAAQ,aAAa;AAC3B,iBAAO;AACP,kBAAQ;AAER,gBAAM,OAAO,IAAI,UAAU,aAAa,YAAY;AACpD,mBAAS,IAAI,GAAG,IAAI,cAAc,KAAK;AACnC,kBAAM,UAAU,MAAM,IAAI;AAC1B,qBAAS,IAAI,GAAG,IAAI,aAAa,KAAK;AAClC,kBAAI,MAAM,IAAI,OAAO,IAAI,YAAY,OAAO,GAAG;AAC3C,qBAAK,IAAI,GAAG,CAAC;AAAA,cACjB;AAAA,YACJ;AAAA,UACJ;AACA,iBAAO;AAAA,QACX;AAAA,QACA,OAAO,WAAW,cAAc,OAAO;AACnC,gBAAM,QAAQ,MAAM,SAAS;AAC7B,cAAI,IAAI,aAAa,CAAC;AACtB,gBAAM,IAAI,aAAa,CAAC;AACxB,iBAAO,IAAI,SAAS,MAAM,IAAI,GAAG,CAAC,GAAG;AACjC;AAAA,UACJ;AACA,cAAI,MAAM,OAAO;AACb,kBAAM,IAAI,kBAAkB;AAAA,UAChC;AACA,gBAAM,aAAa,IAAI,aAAa,CAAC;AACrC,cAAI,eAAe,GAAG;AAClB,kBAAM,IAAI,kBAAkB;AAAA,UAChC;AACA,iBAAO;AAAA,QACX;AAAA,MACJ;AACA,uBAAiB,YAAY,CAAC;AAAA,MAO9B,MAAM,oCAAoC,kBAAkB;AAAA;AAAA;AAAA;AAAA;AAAA,QAKxD,YAAY,yBAAyB,KAAK;AACtC,gBAAM,IAAI,iBAAiB,GAAG,sBAAsB;AAAA,QACxD;AAAA,MACJ;AAiBA,UAAI;AACJ,OAAC,SAAUC,6BAA4B;AACnC,QAAAA,4BAA2BA,4BAA2B,GAAG,IAAI,CAAC,IAAI;AAClE,QAAAA,4BAA2BA,4BAA2B,GAAG,IAAI,CAAC,IAAI;AAClE,QAAAA,4BAA2BA,4BAA2B,GAAG,IAAI,CAAC,IAAI;AAClE,QAAAA,4BAA2BA,4BAA2B,GAAG,IAAI,CAAC,IAAI;AAAA,MACtE,GAAG,+BAA+B,6BAA6B,CAAC,EAAE;AAAA,MAOlE,MAAM,qBAAqB;AAAA,QACvB,YAAY,OAAO,aAAa,MAAc;AAC1C,eAAK,QAAQ;AACb,eAAK,cAAc;AACnB,eAAK,OAAO;AACZ,+BAAqB,SAAS,IAAI,MAAM,IAAI;AAC5C,+BAAqB,UAAU,IAAI,OAAO,IAAI;AAAA,QAClD;AAAA,QACA,WAAW;AACP,iBAAO,KAAK;AAAA,QAChB;AAAA,QACA,UAAU;AACN,iBAAO,KAAK;AAAA,QAChB;AAAA,QACA,OAAO,WAAW,GAAG;AACjB,kBAAQ,GAAG;AAAA,YACP,KAAK;AAAK,qBAAO,qBAAqB;AAAA,YACtC,KAAK;AAAK,qBAAO,qBAAqB;AAAA,YACtC,KAAK;AAAK,qBAAO,qBAAqB;AAAA,YACtC,KAAK;AAAK,qBAAO,qBAAqB;AAAA,YACtC;AAAS,oBAAM,IAAI,kBAAkB,IAAI,eAAe;AAAA,UAC5D;AAAA,QACJ;AAAA,QACA,WAAW;AACP,iBAAO,KAAK;AAAA,QAChB;AAAA,QACA,OAAO,GAAG;AACN,cAAI,EAAE,aAAa,uBAAuB;AACtC,mBAAO;AAAA,UACX;AACA,gBAAM,QAAQ;AACd,iBAAO,KAAK,UAAU,MAAM;AAAA,QAChC;AAAA;AAAA;AAAA;AAAA;AAAA,QAKA,OAAO,QAAQ,MAAc;AACzB,cAAI,OAAO,KAAK,QAAQ,qBAAqB,SAAS,MAAM;AACxD,kBAAM,IAAI,yBAAyB;AAAA,UACvC;AACA,iBAAO,qBAAqB,SAAS,IAAI,IAAI;AAAA,QACjD;AAAA,MACJ;AACA,2BAAqB,WAAW,oBAAI,IAAI;AACxC,2BAAqB,YAAY,oBAAI,IAAI;AAEzC,2BAAqB,IAAI,IAAI,qBAAqB,2BAA2B,GAAG,KAAK,CAAI;AAEzF,2BAAqB,IAAI,IAAI,qBAAqB,2BAA2B,GAAG,KAAK,CAAI;AAEzF,2BAAqB,IAAI,IAAI,qBAAqB,2BAA2B,GAAG,KAAK,CAAI;AAEzF,2BAAqB,IAAI,IAAI,qBAAqB,2BAA2B,GAAG,KAAK,CAAI;AAAA,MAyBzF,MAAM,kBAAkB;AAAA,QACpB,YAAY,YAAoB;AAE5B,eAAK,uBAAuB,qBAAqB,QAAS,cAAc,IAAK,CAAI;AAEjF,eAAK;AAAA,UAAwB,aAAa;AAAA,QAC9C;AAAA,QACA,OAAO,iBAAiB,GAAW,GAAW;AAC1C,iBAAO,QAAQ,SAAS,IAAI,CAAC;AAAA,QACjC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAQA,OAAO,wBAAwB,mBAA2B,mBAA2B;AACjF,gBAAM,aAAa,kBAAkB,0BAA0B,mBAAmB,iBAAiB;AACnG,cAAI,eAAe,MAAM;AACrB,mBAAO;AAAA,UACX;AAIA,iBAAO,kBAAkB,0BAA0B,oBAAoB,kBAAkB,qBAAqB,oBAAoB,kBAAkB,mBAAmB;AAAA,QAC3K;AAAA,QACA,OAAO,0BAA0B,mBAA2B,mBAA2B;AAEnF,cAAI,iBAAiB,OAAO;AAC5B,cAAI,iBAAiB;AACrB,qBAAW,cAAc,kBAAkB,2BAA2B;AAClE,kBAAM,aAAa,WAAW,CAAC;AAC/B,gBAAI,eAAe,qBAAqB,eAAe,mBAAmB;AAEtE,qBAAO,IAAI,kBAAkB,WAAW,CAAC,CAAC;AAAA,YAC9C;AACA,gBAAI,iBAAiB,kBAAkB,iBAAiB,mBAAmB,UAAU;AACrF,gBAAI,iBAAiB,gBAAgB;AACjC,+BAAiB,WAAW,CAAC;AAC7B,+BAAiB;AAAA,YACrB;AACA,gBAAI,sBAAsB,mBAAmB;AAEzC,+BAAiB,kBAAkB,iBAAiB,mBAAmB,UAAU;AACjF,kBAAI,iBAAiB,gBAAgB;AACjC,iCAAiB,WAAW,CAAC;AAC7B,iCAAiB;AAAA,cACrB;AAAA,YACJ;AAAA,UACJ;AAGA,cAAI,kBAAkB,GAAG;AACrB,mBAAO,IAAI,kBAAkB,cAAc;AAAA,UAC/C;AACA,iBAAO;AAAA,QACX;AAAA,QACA,0BAA0B;AACtB,iBAAO,KAAK;AAAA,QAChB;AAAA,QACA,cAAc;AACV,iBAAO,KAAK;AAAA,QAChB;AAAA;AAAA,QAEA,WAAW;AACP,iBAAQ,KAAK,qBAAqB,QAAQ,KAAK,IAAK,KAAK;AAAA,QAC7D;AAAA;AAAA,QAEA,OAAO,GAAG;AACN,cAAI,EAAE,aAAa,oBAAoB;AACnC,mBAAO;AAAA,UACX;AACA,gBAAM,QAAQ;AACd,iBAAO,KAAK,yBAAyB,MAAM,wBACvC,KAAK,aAAa,MAAM;AAAA,QAChC;AAAA,MACJ;AACA,wBAAkB,sBAAsB;AAIxC,wBAAkB,4BAA4B;AAAA,QAC1C,WAAW,KAAK,CAAC,OAAQ,CAAI,CAAC;AAAA,QAC9B,WAAW,KAAK,CAAC,OAAQ,CAAI,CAAC;AAAA,QAC9B,WAAW,KAAK,CAAC,OAAQ,CAAI,CAAC;AAAA,QAC9B,WAAW,KAAK,CAAC,OAAQ,CAAI,CAAC;AAAA,QAC9B,WAAW,KAAK,CAAC,OAAQ,CAAI,CAAC;AAAA,QAC9B,WAAW,KAAK,CAAC,OAAQ,CAAI,CAAC;AAAA,QAC9B,WAAW,KAAK,CAAC,OAAQ,CAAI,CAAC;AAAA,QAC9B,WAAW,KAAK,CAAC,OAAQ,CAAI,CAAC;AAAA,QAC9B,WAAW,KAAK,CAAC,OAAQ,CAAI,CAAC;AAAA,QAC9B,WAAW,KAAK,CAAC,OAAQ,CAAI,CAAC;AAAA,QAC9B,WAAW,KAAK,CAAC,OAAQ,EAAI,CAAC;AAAA,QAC9B,WAAW,KAAK,CAAC,OAAQ,EAAI,CAAC;AAAA,QAC9B,WAAW,KAAK,CAAC,OAAQ,EAAI,CAAC;AAAA,QAC9B,WAAW,KAAK,CAAC,OAAQ,EAAI,CAAC;AAAA,QAC9B,WAAW,KAAK,CAAC,OAAQ,EAAI,CAAC;AAAA,QAC9B,WAAW,KAAK,CAAC,OAAQ,EAAI,CAAC;AAAA,QAC9B,WAAW,KAAK,CAAC,MAAQ,EAAI,CAAC;AAAA,QAC9B,WAAW,KAAK,CAAC,MAAQ,EAAI,CAAC;AAAA,QAC9B,WAAW,KAAK,CAAC,MAAQ,EAAI,CAAC;AAAA,QAC9B,WAAW,KAAK,CAAC,MAAQ,EAAI,CAAC;AAAA,QAC9B,WAAW,KAAK,CAAC,MAAQ,EAAI,CAAC;AAAA,QAC9B,WAAW,KAAK,CAAC,KAAQ,EAAI,CAAC;AAAA,QAC9B,WAAW,KAAK,CAAC,MAAQ,EAAI,CAAC;AAAA,QAC9B,WAAW,KAAK,CAAC,MAAQ,EAAI,CAAC;AAAA,QAC9B,WAAW,KAAK,CAAC,OAAQ,EAAI,CAAC;AAAA,QAC9B,WAAW,KAAK,CAAC,OAAQ,EAAI,CAAC;AAAA,QAC9B,WAAW,KAAK,CAAC,OAAQ,EAAI,CAAC;AAAA,QAC9B,WAAW,KAAK,CAAC,OAAQ,EAAI,CAAC;AAAA,QAC9B,WAAW,KAAK,CAAC,MAAQ,EAAI,CAAC;AAAA,QAC9B,WAAW,KAAK,CAAC,MAAQ,EAAI,CAAC;AAAA,QAC9B,WAAW,KAAK,CAAC,OAAQ,EAAI,CAAC;AAAA,QAC9B,WAAW,KAAK,CAAC,OAAQ,EAAI,CAAC;AAAA,MAClC;AAAA,MAQA,MAAM,WAAW;AAAA,QACb,YAAY,wBAAgC,UAAU;AAClD,eAAK,sBAAsB;AAC3B,eAAK,WAAW;AAAA,QACpB;AAAA,QACA,yBAAyB;AACrB,iBAAO,KAAK;AAAA,QAChB;AAAA,QACA,eAAe;AACX,cAAI,QAAQ;AACZ,gBAAM,WAAW,KAAK;AACtB,qBAAW,WAAW,UAAU;AAC5B,qBAAS,QAAQ,SAAS;AAAA,UAC9B;AACA,iBAAO;AAAA,QACX;AAAA,QACA,sBAAsB;AAClB,iBAAO,KAAK,sBAAsB,KAAK,aAAa;AAAA,QACxD;AAAA,QACA,cAAc;AACV,iBAAO,KAAK;AAAA,QAChB;AAAA,MACJ;AAAA,MAOA,MAAM,MAAM;AAAA,QACR,YAAY,OAAe,eAAuB;AAC9C,eAAK,QAAQ;AACb,eAAK,gBAAgB;AAAA,QACzB;AAAA,QACA,WAAW;AACP,iBAAO,KAAK;AAAA,QAChB;AAAA,QACA,mBAAmB;AACf,iBAAO,KAAK;AAAA,QAChB;AAAA,MACJ;AAAA,MAsBA,MAAM,UAAU;AAAA,QACZ,YAAY,eAAuB,4BAA4B,UAAU;AACrE,eAAK,gBAAgB;AACrB,eAAK,0BAA0B;AAC/B,eAAK,WAAW;AAChB,cAAI,QAAQ;AACZ,gBAAM,cAAc,SAAS,CAAC,EAAE,uBAAuB;AACvD,gBAAM,WAAW,SAAS,CAAC,EAAE,YAAY;AACzC,qBAAW,WAAW,UAAU;AAC5B,qBAAS,QAAQ,SAAS,KAAK,QAAQ,iBAAiB,IAAI;AAAA,UAChE;AACA,eAAK,iBAAiB;AAAA,QAC1B;AAAA,QACA,mBAAmB;AACf,iBAAO,KAAK;AAAA,QAChB;AAAA,QACA,6BAA6B;AACzB,iBAAO,KAAK;AAAA,QAChB;AAAA,QACA,oBAAoB;AAChB,iBAAO,KAAK;AAAA,QAChB;AAAA,QACA,yBAAyB;AACrB,iBAAO,KAAK,IAAI,KAAK;AAAA,QACzB;AAAA,QACA,oBAAoB,SAAS;AACzB,iBAAO,KAAK,SAAS,QAAQ,SAAS,CAAC;AAAA,QAG3C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAQA,OAAO,kCAAkC,WAAmB;AACxD,cAAI,YAAY,MAAM,GAAG;AACrB,kBAAM,IAAI,gBAAgB;AAAA,UAC9B;AACA,cAAI;AACA,mBAAO,KAAK,qBAAqB,YAAY,MAAM,CAAC;AAAA,UACxD,SACO,SAAwC;AAC3C,kBAAM,IAAI,gBAAgB;AAAA,UAC9B;AAAA,QACJ;AAAA,QACA,OAAO,oBAAoB,eAAuB;AAC9C,cAAI,gBAAgB,KAAK,gBAAgB,IAAI;AACzC,kBAAM,IAAI,yBAAyB;AAAA,UACvC;AACA,iBAAO,UAAU,SAAS,gBAAgB,CAAC;AAAA,QAC/C;AAAA,QACA,OAAO,yBAAyB,aAAqB;AACjD,cAAI,iBAAiB,OAAO;AAC5B,cAAI,cAAc;AAClB,mBAAS,IAAI,GAAG,IAAI,UAAU,oBAAoB,QAAQ,KAAK;AAC3D,kBAAM,gBAAgB,UAAU,oBAAoB,CAAC;AAErD,gBAAI,kBAAkB,aAAa;AAC/B,qBAAO,UAAU,oBAAoB,IAAI,CAAC;AAAA,YAC9C;AAGA,kBAAM,iBAAiB,kBAAkB,iBAAiB,aAAa,aAAa;AACpF,gBAAI,iBAAiB,gBAAgB;AACjC,4BAAc,IAAI;AAClB,+BAAiB;AAAA,YACrB;AAAA,UACJ;AAGA,cAAI,kBAAkB,GAAG;AACrB,mBAAO,UAAU,oBAAoB,WAAW;AAAA,UACpD;AAEA,iBAAO;AAAA,QACX;AAAA;AAAA;AAAA;AAAA,QAIA,uBAAuB;AACnB,gBAAM,YAAY,KAAK,uBAAuB;AAC9C,gBAAM,YAAY,IAAI,UAAU,SAAS;AAEzC,oBAAU,UAAU,GAAG,GAAG,GAAG,CAAC;AAE9B,oBAAU,UAAU,YAAY,GAAG,GAAG,GAAG,CAAC;AAE1C,oBAAU,UAAU,GAAG,YAAY,GAAG,GAAG,CAAC;AAE1C,gBAAM,MAAM,KAAK,wBAAwB;AACzC,mBAAS,IAAI,GAAG,IAAI,KAAK,KAAK;AAC1B,kBAAM,IAAI,KAAK,wBAAwB,CAAC,IAAI;AAC5C,qBAAS,IAAI,GAAG,IAAI,KAAK,KAAK;AAC1B,kBAAK,MAAM,MAAM,MAAM,KAAK,MAAM,MAAM,MAAQ,MAAM,MAAM,KAAK,MAAM,GAAI;AAEvE;AAAA,cACJ;AACA,wBAAU,UAAU,KAAK,wBAAwB,CAAC,IAAI,GAAG,GAAG,GAAG,CAAC;AAAA,YACpE;AAAA,UACJ;AAEA,oBAAU,UAAU,GAAG,GAAG,GAAG,YAAY,EAAE;AAE3C,oBAAU,UAAU,GAAG,GAAG,YAAY,IAAI,CAAC;AAC3C,cAAI,KAAK,gBAAgB,GAAG;AAExB,sBAAU,UAAU,YAAY,IAAI,GAAG,GAAG,CAAC;AAE3C,sBAAU,UAAU,GAAG,YAAY,IAAI,GAAG,CAAC;AAAA,UAC/C;AACA,iBAAO;AAAA,QACX;AAAA;AAAA,QAEA,WAAW;AACP,iBAAO,KAAK,KAAK;AAAA,QACrB;AAAA,MACJ;AAKA,gBAAU,sBAAsB,WAAW,KAAK;AAAA,QAC5C;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACpC;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACpC;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACpC;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACpC;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACpC;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACpC;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,MAC/B,CAAC;AAID,gBAAU,WAAW;AAAA,QACjB,IAAI,UAAU,GAAG,IAAI,WAAW,CAAC,GAAG,IAAI,WAAW,GAAG,IAAI,MAAM,GAAG,EAAE,CAAC,GAAG,IAAI,WAAW,IAAI,IAAI,MAAM,GAAG,EAAE,CAAC,GAAG,IAAI,WAAW,IAAI,IAAI,MAAM,GAAG,EAAE,CAAC,GAAG,IAAI,WAAW,IAAI,IAAI,MAAM,GAAG,CAAC,CAAC,CAAC;AAAA,QACxL,IAAI,UAAU,GAAG,WAAW,KAAK,CAAC,GAAG,EAAE,CAAC,GAAG,IAAI,WAAW,IAAI,IAAI,MAAM,GAAG,EAAE,CAAC,GAAG,IAAI,WAAW,IAAI,IAAI,MAAM,GAAG,EAAE,CAAC,GAAG,IAAI,WAAW,IAAI,IAAI,MAAM,GAAG,EAAE,CAAC,GAAG,IAAI,WAAW,IAAI,IAAI,MAAM,GAAG,EAAE,CAAC,CAAC;AAAA,QACjM,IAAI,UAAU,GAAG,WAAW,KAAK,CAAC,GAAG,EAAE,CAAC,GAAG,IAAI,WAAW,IAAI,IAAI,MAAM,GAAG,EAAE,CAAC,GAAG,IAAI,WAAW,IAAI,IAAI,MAAM,GAAG,EAAE,CAAC,GAAG,IAAI,WAAW,IAAI,IAAI,MAAM,GAAG,EAAE,CAAC,GAAG,IAAI,WAAW,IAAI,IAAI,MAAM,GAAG,EAAE,CAAC,CAAC;AAAA,QACjM,IAAI,UAAU,GAAG,WAAW,KAAK,CAAC,GAAG,EAAE,CAAC,GAAG,IAAI,WAAW,IAAI,IAAI,MAAM,GAAG,EAAE,CAAC,GAAG,IAAI,WAAW,IAAI,IAAI,MAAM,GAAG,EAAE,CAAC,GAAG,IAAI,WAAW,IAAI,IAAI,MAAM,GAAG,EAAE,CAAC,GAAG,IAAI,WAAW,IAAI,IAAI,MAAM,GAAG,CAAC,CAAC,CAAC;AAAA,QAChM,IAAI,UAAU,GAAG,WAAW,KAAK,CAAC,GAAG,EAAE,CAAC,GAAG,IAAI,WAAW,IAAI,IAAI,MAAM,GAAG,GAAG,CAAC,GAAG,IAAI,WAAW,IAAI,IAAI,MAAM,GAAG,EAAE,CAAC,GAAG,IAAI,WAAW,IAAI,IAAI,MAAM,GAAG,EAAE,GAAG,IAAI,MAAM,GAAG,EAAE,CAAC,GAAG,IAAI,WAAW,IAAI,IAAI,MAAM,GAAG,EAAE,GAAG,IAAI,MAAM,GAAG,EAAE,CAAC,CAAC;AAAA,QACtO,IAAI,UAAU,GAAG,WAAW,KAAK,CAAC,GAAG,EAAE,CAAC,GAAG,IAAI,WAAW,IAAI,IAAI,MAAM,GAAG,EAAE,CAAC,GAAG,IAAI,WAAW,IAAI,IAAI,MAAM,GAAG,EAAE,CAAC,GAAG,IAAI,WAAW,IAAI,IAAI,MAAM,GAAG,EAAE,CAAC,GAAG,IAAI,WAAW,IAAI,IAAI,MAAM,GAAG,EAAE,CAAC,CAAC;AAAA,QACjM,IAAI,UAAU,GAAG,WAAW,KAAK,CAAC,GAAG,IAAI,EAAE,CAAC,GAAG,IAAI,WAAW,IAAI,IAAI,MAAM,GAAG,EAAE,CAAC,GAAG,IAAI,WAAW,IAAI,IAAI,MAAM,GAAG,EAAE,CAAC,GAAG,IAAI,WAAW,IAAI,IAAI,MAAM,GAAG,EAAE,GAAG,IAAI,MAAM,GAAG,EAAE,CAAC,GAAG,IAAI,WAAW,IAAI,IAAI,MAAM,GAAG,EAAE,GAAG,IAAI,MAAM,GAAG,EAAE,CAAC,CAAC;AAAA,QACzO,IAAI,UAAU,GAAG,WAAW,KAAK,CAAC,GAAG,IAAI,EAAE,CAAC,GAAG,IAAI,WAAW,IAAI,IAAI,MAAM,GAAG,EAAE,CAAC,GAAG,IAAI,WAAW,IAAI,IAAI,MAAM,GAAG,EAAE,GAAG,IAAI,MAAM,GAAG,EAAE,CAAC,GAAG,IAAI,WAAW,IAAI,IAAI,MAAM,GAAG,EAAE,GAAG,IAAI,MAAM,GAAG,EAAE,CAAC,GAAG,IAAI,WAAW,IAAI,IAAI,MAAM,GAAG,EAAE,GAAG,IAAI,MAAM,GAAG,EAAE,CAAC,CAAC;AAAA,QAC3P,IAAI,UAAU,GAAG,WAAW,KAAK,CAAC,GAAG,IAAI,EAAE,CAAC,GAAG,IAAI,WAAW,IAAI,IAAI,MAAM,GAAG,GAAG,CAAC,GAAG,IAAI,WAAW,IAAI,IAAI,MAAM,GAAG,EAAE,GAAG,IAAI,MAAM,GAAG,EAAE,CAAC,GAAG,IAAI,WAAW,IAAI,IAAI,MAAM,GAAG,EAAE,GAAG,IAAI,MAAM,GAAG,EAAE,CAAC,GAAG,IAAI,WAAW,IAAI,IAAI,MAAM,GAAG,EAAE,GAAG,IAAI,MAAM,GAAG,EAAE,CAAC,CAAC;AAAA,QAC5P,IAAI,UAAU,IAAI,WAAW,KAAK,CAAC,GAAG,IAAI,EAAE,CAAC,GAAG,IAAI,WAAW,IAAI,IAAI,MAAM,GAAG,EAAE,GAAG,IAAI,MAAM,GAAG,EAAE,CAAC,GAAG,IAAI,WAAW,IAAI,IAAI,MAAM,GAAG,EAAE,GAAG,IAAI,MAAM,GAAG,EAAE,CAAC,GAAG,IAAI,WAAW,IAAI,IAAI,MAAM,GAAG,EAAE,GAAG,IAAI,MAAM,GAAG,EAAE,CAAC,GAAG,IAAI,WAAW,IAAI,IAAI,MAAM,GAAG,EAAE,GAAG,IAAI,MAAM,GAAG,EAAE,CAAC,CAAC;AAAA,QAC9Q,IAAI,UAAU,IAAI,WAAW,KAAK,CAAC,GAAG,IAAI,EAAE,CAAC,GAAG,IAAI,WAAW,IAAI,IAAI,MAAM,GAAG,EAAE,CAAC,GAAG,IAAI,WAAW,IAAI,IAAI,MAAM,GAAG,EAAE,GAAG,IAAI,MAAM,GAAG,EAAE,CAAC,GAAG,IAAI,WAAW,IAAI,IAAI,MAAM,GAAG,EAAE,GAAG,IAAI,MAAM,GAAG,EAAE,CAAC,GAAG,IAAI,WAAW,IAAI,IAAI,MAAM,GAAG,EAAE,GAAG,IAAI,MAAM,GAAG,EAAE,CAAC,CAAC;AAAA,QAC5P,IAAI,UAAU,IAAI,WAAW,KAAK,CAAC,GAAG,IAAI,EAAE,CAAC,GAAG,IAAI,WAAW,IAAI,IAAI,MAAM,GAAG,EAAE,GAAG,IAAI,MAAM,GAAG,EAAE,CAAC,GAAG,IAAI,WAAW,IAAI,IAAI,MAAM,GAAG,EAAE,GAAG,IAAI,MAAM,GAAG,EAAE,CAAC,GAAG,IAAI,WAAW,IAAI,IAAI,MAAM,GAAG,EAAE,GAAG,IAAI,MAAM,GAAG,EAAE,CAAC,GAAG,IAAI,WAAW,IAAI,IAAI,MAAM,GAAG,EAAE,GAAG,IAAI,MAAM,GAAG,EAAE,CAAC,CAAC;AAAA,QAC9Q,IAAI,UAAU,IAAI,WAAW,KAAK,CAAC,GAAG,IAAI,EAAE,CAAC,GAAG,IAAI,WAAW,IAAI,IAAI,MAAM,GAAG,GAAG,CAAC,GAAG,IAAI,WAAW,IAAI,IAAI,MAAM,GAAG,EAAE,GAAG,IAAI,MAAM,GAAG,EAAE,CAAC,GAAG,IAAI,WAAW,IAAI,IAAI,MAAM,GAAG,EAAE,GAAG,IAAI,MAAM,GAAG,EAAE,CAAC,GAAG,IAAI,WAAW,IAAI,IAAI,MAAM,IAAI,EAAE,GAAG,IAAI,MAAM,GAAG,EAAE,CAAC,CAAC;AAAA,QAC9P,IAAI,UAAU,IAAI,WAAW,KAAK,CAAC,GAAG,IAAI,IAAI,EAAE,CAAC,GAAG,IAAI,WAAW,IAAI,IAAI,MAAM,GAAG,GAAG,GAAG,IAAI,MAAM,GAAG,GAAG,CAAC,GAAG,IAAI,WAAW,IAAI,IAAI,MAAM,GAAG,EAAE,GAAG,IAAI,MAAM,GAAG,EAAE,CAAC,GAAG,IAAI,WAAW,IAAI,IAAI,MAAM,IAAI,EAAE,GAAG,IAAI,MAAM,GAAG,EAAE,CAAC,GAAG,IAAI,WAAW,IAAI,IAAI,MAAM,IAAI,EAAE,GAAG,IAAI,MAAM,GAAG,EAAE,CAAC,CAAC;AAAA,QACtR,IAAI,UAAU,IAAI,WAAW,KAAK,CAAC,GAAG,IAAI,IAAI,EAAE,CAAC,GAAG,IAAI,WAAW,IAAI,IAAI,MAAM,GAAG,EAAE,GAAG,IAAI,MAAM,GAAG,EAAE,CAAC,GAAG,IAAI,WAAW,IAAI,IAAI,MAAM,GAAG,EAAE,GAAG,IAAI,MAAM,GAAG,EAAE,CAAC,GAAG,IAAI,WAAW,IAAI,IAAI,MAAM,GAAG,EAAE,GAAG,IAAI,MAAM,GAAG,EAAE,CAAC,GAAG,IAAI,WAAW,IAAI,IAAI,MAAM,IAAI,EAAE,GAAG,IAAI,MAAM,GAAG,EAAE,CAAC,CAAC;AAAA,QACnR,IAAI,UAAU,IAAI,WAAW,KAAK,CAAC,GAAG,IAAI,IAAI,EAAE,CAAC,GAAG,IAAI,WAAW,IAAI,IAAI,MAAM,GAAG,EAAE,GAAG,IAAI,MAAM,GAAG,EAAE,CAAC,GAAG,IAAI,WAAW,IAAI,IAAI,MAAM,GAAG,EAAE,GAAG,IAAI,MAAM,GAAG,EAAE,CAAC,GAAG,IAAI,WAAW,IAAI,IAAI,MAAM,IAAI,EAAE,GAAG,IAAI,MAAM,GAAG,EAAE,CAAC,GAAG,IAAI,WAAW,IAAI,IAAI,MAAM,GAAG,EAAE,GAAG,IAAI,MAAM,IAAI,EAAE,CAAC,CAAC;AAAA,QACpR,IAAI,UAAU,IAAI,WAAW,KAAK,CAAC,GAAG,IAAI,IAAI,EAAE,CAAC,GAAG,IAAI,WAAW,IAAI,IAAI,MAAM,GAAG,GAAG,GAAG,IAAI,MAAM,GAAG,GAAG,CAAC,GAAG,IAAI,WAAW,IAAI,IAAI,MAAM,IAAI,EAAE,GAAG,IAAI,MAAM,GAAG,EAAE,CAAC,GAAG,IAAI,WAAW,IAAI,IAAI,MAAM,GAAG,EAAE,GAAG,IAAI,MAAM,IAAI,EAAE,CAAC,GAAG,IAAI,WAAW,IAAI,IAAI,MAAM,GAAG,EAAE,GAAG,IAAI,MAAM,IAAI,EAAE,CAAC,CAAC;AAAA,QACvR,IAAI,UAAU,IAAI,WAAW,KAAK,CAAC,GAAG,IAAI,IAAI,EAAE,CAAC,GAAG,IAAI,WAAW,IAAI,IAAI,MAAM,GAAG,GAAG,GAAG,IAAI,MAAM,GAAG,GAAG,CAAC,GAAG,IAAI,WAAW,IAAI,IAAI,MAAM,GAAG,EAAE,GAAG,IAAI,MAAM,GAAG,EAAE,CAAC,GAAG,IAAI,WAAW,IAAI,IAAI,MAAM,IAAI,EAAE,GAAG,IAAI,MAAM,GAAG,EAAE,CAAC,GAAG,IAAI,WAAW,IAAI,IAAI,MAAM,GAAG,EAAE,GAAG,IAAI,MAAM,IAAI,EAAE,CAAC,CAAC;AAAA,QACtR,IAAI,UAAU,IAAI,WAAW,KAAK,CAAC,GAAG,IAAI,IAAI,EAAE,CAAC,GAAG,IAAI,WAAW,IAAI,IAAI,MAAM,GAAG,GAAG,GAAG,IAAI,MAAM,GAAG,GAAG,CAAC,GAAG,IAAI,WAAW,IAAI,IAAI,MAAM,GAAG,EAAE,GAAG,IAAI,MAAM,IAAI,EAAE,CAAC,GAAG,IAAI,WAAW,IAAI,IAAI,MAAM,IAAI,EAAE,GAAG,IAAI,MAAM,GAAG,EAAE,CAAC,GAAG,IAAI,WAAW,IAAI,IAAI,MAAM,GAAG,EAAE,GAAG,IAAI,MAAM,IAAI,EAAE,CAAC,CAAC;AAAA,QACvR,IAAI,UAAU,IAAI,WAAW,KAAK,CAAC,GAAG,IAAI,IAAI,EAAE,CAAC,GAAG,IAAI,WAAW,IAAI,IAAI,MAAM,GAAG,GAAG,GAAG,IAAI,MAAM,GAAG,GAAG,CAAC,GAAG,IAAI,WAAW,IAAI,IAAI,MAAM,GAAG,EAAE,GAAG,IAAI,MAAM,IAAI,EAAE,CAAC,GAAG,IAAI,WAAW,IAAI,IAAI,MAAM,IAAI,EAAE,GAAG,IAAI,MAAM,GAAG,EAAE,CAAC,GAAG,IAAI,WAAW,IAAI,IAAI,MAAM,IAAI,EAAE,GAAG,IAAI,MAAM,IAAI,EAAE,CAAC,CAAC;AAAA,QACxR,IAAI,UAAU,IAAI,WAAW,KAAK,CAAC,GAAG,IAAI,IAAI,IAAI,EAAE,CAAC,GAAG,IAAI,WAAW,IAAI,IAAI,MAAM,GAAG,GAAG,GAAG,IAAI,MAAM,GAAG,GAAG,CAAC,GAAG,IAAI,WAAW,IAAI,IAAI,MAAM,IAAI,EAAE,CAAC,GAAG,IAAI,WAAW,IAAI,IAAI,MAAM,IAAI,EAAE,GAAG,IAAI,MAAM,GAAG,EAAE,CAAC,GAAG,IAAI,WAAW,IAAI,IAAI,MAAM,IAAI,EAAE,GAAG,IAAI,MAAM,GAAG,EAAE,CAAC,CAAC;AAAA,QACzQ,IAAI,UAAU,IAAI,WAAW,KAAK,CAAC,GAAG,IAAI,IAAI,IAAI,EAAE,CAAC,GAAG,IAAI,WAAW,IAAI,IAAI,MAAM,GAAG,GAAG,GAAG,IAAI,MAAM,GAAG,GAAG,CAAC,GAAG,IAAI,WAAW,IAAI,IAAI,MAAM,IAAI,EAAE,CAAC,GAAG,IAAI,WAAW,IAAI,IAAI,MAAM,GAAG,EAAE,GAAG,IAAI,MAAM,IAAI,EAAE,CAAC,GAAG,IAAI,WAAW,IAAI,IAAI,MAAM,IAAI,EAAE,CAAC,CAAC;AAAA,QACvP,IAAI,UAAU,IAAI,WAAW,KAAK,CAAC,GAAG,IAAI,IAAI,IAAI,GAAG,CAAC,GAAG,IAAI,WAAW,IAAI,IAAI,MAAM,GAAG,GAAG,GAAG,IAAI,MAAM,GAAG,GAAG,CAAC,GAAG,IAAI,WAAW,IAAI,IAAI,MAAM,GAAG,EAAE,GAAG,IAAI,MAAM,IAAI,EAAE,CAAC,GAAG,IAAI,WAAW,IAAI,IAAI,MAAM,IAAI,EAAE,GAAG,IAAI,MAAM,IAAI,EAAE,CAAC,GAAG,IAAI,WAAW,IAAI,IAAI,MAAM,IAAI,EAAE,GAAG,IAAI,MAAM,IAAI,EAAE,CAAC,CAAC;AAAA,QAC9R,IAAI,UAAU,IAAI,WAAW,KAAK,CAAC,GAAG,IAAI,IAAI,IAAI,GAAG,CAAC,GAAG,IAAI,WAAW,IAAI,IAAI,MAAM,GAAG,GAAG,GAAG,IAAI,MAAM,GAAG,GAAG,CAAC,GAAG,IAAI,WAAW,IAAI,IAAI,MAAM,GAAG,EAAE,GAAG,IAAI,MAAM,IAAI,EAAE,CAAC,GAAG,IAAI,WAAW,IAAI,IAAI,MAAM,IAAI,EAAE,GAAG,IAAI,MAAM,IAAI,EAAE,CAAC,GAAG,IAAI,WAAW,IAAI,IAAI,MAAM,IAAI,EAAE,GAAG,IAAI,MAAM,GAAG,EAAE,CAAC,CAAC;AAAA,QAC7R,IAAI,UAAU,IAAI,WAAW,KAAK,CAAC,GAAG,IAAI,IAAI,IAAI,GAAG,CAAC,GAAG,IAAI,WAAW,IAAI,IAAI,MAAM,GAAG,GAAG,GAAG,IAAI,MAAM,GAAG,GAAG,CAAC,GAAG,IAAI,WAAW,IAAI,IAAI,MAAM,GAAG,EAAE,GAAG,IAAI,MAAM,IAAI,EAAE,CAAC,GAAG,IAAI,WAAW,IAAI,IAAI,MAAM,GAAG,EAAE,GAAG,IAAI,MAAM,IAAI,EAAE,CAAC,GAAG,IAAI,WAAW,IAAI,IAAI,MAAM,IAAI,EAAE,GAAG,IAAI,MAAM,IAAI,EAAE,CAAC,CAAC;AAAA,QAC7R,IAAI,UAAU,IAAI,WAAW,KAAK,CAAC,GAAG,IAAI,IAAI,IAAI,GAAG,CAAC,GAAG,IAAI,WAAW,IAAI,IAAI,MAAM,IAAI,GAAG,GAAG,IAAI,MAAM,GAAG,GAAG,CAAC,GAAG,IAAI,WAAW,IAAI,IAAI,MAAM,IAAI,EAAE,GAAG,IAAI,MAAM,GAAG,EAAE,CAAC,GAAG,IAAI,WAAW,IAAI,IAAI,MAAM,IAAI,EAAE,GAAG,IAAI,MAAM,GAAG,EAAE,CAAC,GAAG,IAAI,WAAW,IAAI,IAAI,MAAM,IAAI,EAAE,GAAG,IAAI,MAAM,GAAG,EAAE,CAAC,CAAC;AAAA,QAC7R,IAAI,UAAU,IAAI,WAAW,KAAK,CAAC,GAAG,IAAI,IAAI,IAAI,GAAG,CAAC,GAAG,IAAI,WAAW,IAAI,IAAI,MAAM,GAAG,GAAG,GAAG,IAAI,MAAM,GAAG,GAAG,CAAC,GAAG,IAAI,WAAW,IAAI,IAAI,MAAM,IAAI,EAAE,GAAG,IAAI,MAAM,GAAG,EAAE,CAAC,GAAG,IAAI,WAAW,IAAI,IAAI,MAAM,GAAG,EAAE,GAAG,IAAI,MAAM,IAAI,EAAE,CAAC,GAAG,IAAI,WAAW,IAAI,IAAI,MAAM,IAAI,EAAE,GAAG,IAAI,MAAM,IAAI,EAAE,CAAC,CAAC;AAAA,QAC7R,IAAI,UAAU,IAAI,WAAW,KAAK,CAAC,GAAG,IAAI,IAAI,IAAI,IAAI,GAAG,CAAC,GAAG,IAAI,WAAW,IAAI,IAAI,MAAM,GAAG,GAAG,GAAG,IAAI,MAAM,IAAI,GAAG,CAAC,GAAG,IAAI,WAAW,IAAI,IAAI,MAAM,GAAG,EAAE,GAAG,IAAI,MAAM,IAAI,EAAE,CAAC,GAAG,IAAI,WAAW,IAAI,IAAI,MAAM,GAAG,EAAE,GAAG,IAAI,MAAM,IAAI,EAAE,CAAC,GAAG,IAAI,WAAW,IAAI,IAAI,MAAM,IAAI,EAAE,GAAG,IAAI,MAAM,IAAI,EAAE,CAAC,CAAC;AAAA,QAClS,IAAI,UAAU,IAAI,WAAW,KAAK,CAAC,GAAG,IAAI,IAAI,IAAI,KAAK,GAAG,CAAC,GAAG,IAAI,WAAW,IAAI,IAAI,MAAM,GAAG,GAAG,GAAG,IAAI,MAAM,GAAG,GAAG,CAAC,GAAG,IAAI,WAAW,IAAI,IAAI,MAAM,IAAI,EAAE,GAAG,IAAI,MAAM,GAAG,EAAE,CAAC,GAAG,IAAI,WAAW,IAAI,IAAI,MAAM,GAAG,EAAE,GAAG,IAAI,MAAM,IAAI,EAAE,CAAC,GAAG,IAAI,WAAW,IAAI,IAAI,MAAM,IAAI,EAAE,GAAG,IAAI,MAAM,IAAI,EAAE,CAAC,CAAC;AAAA,QAClS,IAAI,UAAU,IAAI,WAAW,KAAK,CAAC,GAAG,IAAI,IAAI,IAAI,KAAK,GAAG,CAAC,GAAG,IAAI,WAAW,IAAI,IAAI,MAAM,GAAG,GAAG,GAAG,IAAI,MAAM,IAAI,GAAG,CAAC,GAAG,IAAI,WAAW,IAAI,IAAI,MAAM,IAAI,EAAE,GAAG,IAAI,MAAM,IAAI,EAAE,CAAC,GAAG,IAAI,WAAW,IAAI,IAAI,MAAM,IAAI,EAAE,GAAG,IAAI,MAAM,IAAI,EAAE,CAAC,GAAG,IAAI,WAAW,IAAI,IAAI,MAAM,IAAI,EAAE,GAAG,IAAI,MAAM,IAAI,EAAE,CAAC,CAAC;AAAA,QACrS,IAAI,UAAU,IAAI,WAAW,KAAK,CAAC,GAAG,IAAI,IAAI,IAAI,KAAK,GAAG,CAAC,GAAG,IAAI,WAAW,IAAI,IAAI,MAAM,IAAI,GAAG,GAAG,IAAI,MAAM,GAAG,GAAG,CAAC,GAAG,IAAI,WAAW,IAAI,IAAI,MAAM,GAAG,EAAE,GAAG,IAAI,MAAM,IAAI,EAAE,CAAC,GAAG,IAAI,WAAW,IAAI,IAAI,MAAM,IAAI,EAAE,GAAG,IAAI,MAAM,GAAG,EAAE,CAAC,GAAG,IAAI,WAAW,IAAI,IAAI,MAAM,IAAI,EAAE,GAAG,IAAI,MAAM,IAAI,EAAE,CAAC,CAAC;AAAA,QACnS,IAAI,UAAU,IAAI,WAAW,KAAK,CAAC,GAAG,IAAI,IAAI,IAAI,KAAK,GAAG,CAAC,GAAG,IAAI,WAAW,IAAI,IAAI,MAAM,IAAI,GAAG,CAAC,GAAG,IAAI,WAAW,IAAI,IAAI,MAAM,IAAI,EAAE,GAAG,IAAI,MAAM,IAAI,EAAE,CAAC,GAAG,IAAI,WAAW,IAAI,IAAI,MAAM,IAAI,EAAE,GAAG,IAAI,MAAM,IAAI,EAAE,CAAC,GAAG,IAAI,WAAW,IAAI,IAAI,MAAM,IAAI,EAAE,GAAG,IAAI,MAAM,IAAI,EAAE,CAAC,CAAC;AAAA,QAClR,IAAI,UAAU,IAAI,WAAW,KAAK,CAAC,GAAG,IAAI,IAAI,IAAI,KAAK,GAAG,CAAC,GAAG,IAAI,WAAW,IAAI,IAAI,MAAM,IAAI,GAAG,GAAG,IAAI,MAAM,GAAG,GAAG,CAAC,GAAG,IAAI,WAAW,IAAI,IAAI,MAAM,IAAI,EAAE,GAAG,IAAI,MAAM,IAAI,EAAE,CAAC,GAAG,IAAI,WAAW,IAAI,IAAI,MAAM,IAAI,EAAE,GAAG,IAAI,MAAM,IAAI,EAAE,CAAC,GAAG,IAAI,WAAW,IAAI,IAAI,MAAM,IAAI,EAAE,GAAG,IAAI,MAAM,IAAI,EAAE,CAAC,CAAC;AAAA,QACrS,IAAI,UAAU,IAAI,WAAW,KAAK,CAAC,GAAG,IAAI,IAAI,IAAI,KAAK,GAAG,CAAC,GAAG,IAAI,WAAW,IAAI,IAAI,MAAM,IAAI,GAAG,GAAG,IAAI,MAAM,GAAG,GAAG,CAAC,GAAG,IAAI,WAAW,IAAI,IAAI,MAAM,IAAI,EAAE,GAAG,IAAI,MAAM,IAAI,EAAE,CAAC,GAAG,IAAI,WAAW,IAAI,IAAI,MAAM,IAAI,EAAE,GAAG,IAAI,MAAM,GAAG,EAAE,CAAC,GAAG,IAAI,WAAW,IAAI,IAAI,MAAM,IAAI,EAAE,GAAG,IAAI,MAAM,GAAG,EAAE,CAAC,CAAC;AAAA,QACnS,IAAI,UAAU,IAAI,WAAW,KAAK,CAAC,GAAG,IAAI,IAAI,IAAI,KAAK,KAAK,GAAG,CAAC,GAAG,IAAI,WAAW,IAAI,IAAI,MAAM,IAAI,GAAG,GAAG,IAAI,MAAM,GAAG,GAAG,CAAC,GAAG,IAAI,WAAW,IAAI,IAAI,MAAM,IAAI,EAAE,GAAG,IAAI,MAAM,IAAI,EAAE,CAAC,GAAG,IAAI,WAAW,IAAI,IAAI,MAAM,IAAI,EAAE,GAAG,IAAI,MAAM,IAAI,EAAE,CAAC,GAAG,IAAI,WAAW,IAAI,IAAI,MAAM,IAAI,EAAE,GAAG,IAAI,MAAM,IAAI,EAAE,CAAC,CAAC;AAAA,QAC1S,IAAI,UAAU,IAAI,WAAW,KAAK,CAAC,GAAG,IAAI,IAAI,IAAI,KAAK,KAAK,GAAG,CAAC,GAAG,IAAI,WAAW,IAAI,IAAI,MAAM,GAAG,GAAG,GAAG,IAAI,MAAM,IAAI,GAAG,CAAC,GAAG,IAAI,WAAW,IAAI,IAAI,MAAM,GAAG,EAAE,GAAG,IAAI,MAAM,IAAI,EAAE,CAAC,GAAG,IAAI,WAAW,IAAI,IAAI,MAAM,IAAI,EAAE,GAAG,IAAI,MAAM,IAAI,EAAE,CAAC,GAAG,IAAI,WAAW,IAAI,IAAI,MAAM,GAAG,EAAE,GAAG,IAAI,MAAM,IAAI,EAAE,CAAC,CAAC;AAAA,QACxS,IAAI,UAAU,IAAI,WAAW,KAAK,CAAC,GAAG,IAAI,IAAI,IAAI,KAAK,KAAK,GAAG,CAAC,GAAG,IAAI,WAAW,IAAI,IAAI,MAAM,IAAI,GAAG,GAAG,IAAI,MAAM,GAAG,GAAG,CAAC,GAAG,IAAI,WAAW,IAAI,IAAI,MAAM,IAAI,EAAE,GAAG,IAAI,MAAM,IAAI,EAAE,CAAC,GAAG,IAAI,WAAW,IAAI,IAAI,MAAM,IAAI,EAAE,GAAG,IAAI,MAAM,IAAI,EAAE,CAAC,GAAG,IAAI,WAAW,IAAI,IAAI,MAAM,IAAI,EAAE,GAAG,IAAI,MAAM,IAAI,EAAE,CAAC,CAAC;AAAA,QAC1S,IAAI,UAAU,IAAI,WAAW,KAAK,CAAC,GAAG,IAAI,IAAI,IAAI,KAAK,KAAK,GAAG,CAAC,GAAG,IAAI,WAAW,IAAI,IAAI,MAAM,GAAG,GAAG,GAAG,IAAI,MAAM,IAAI,GAAG,CAAC,GAAG,IAAI,WAAW,IAAI,IAAI,MAAM,IAAI,EAAE,GAAG,IAAI,MAAM,IAAI,EAAE,CAAC,GAAG,IAAI,WAAW,IAAI,IAAI,MAAM,IAAI,EAAE,GAAG,IAAI,MAAM,IAAI,EAAE,CAAC,GAAG,IAAI,WAAW,IAAI,IAAI,MAAM,IAAI,EAAE,GAAG,IAAI,MAAM,IAAI,EAAE,CAAC,CAAC;AAAA,QAC1S,IAAI,UAAU,IAAI,WAAW,KAAK,CAAC,GAAG,IAAI,IAAI,IAAI,KAAK,KAAK,GAAG,CAAC,GAAG,IAAI,WAAW,IAAI,IAAI,MAAM,IAAI,GAAG,GAAG,IAAI,MAAM,GAAG,GAAG,CAAC,GAAG,IAAI,WAAW,IAAI,IAAI,MAAM,IAAI,EAAE,GAAG,IAAI,MAAM,GAAG,EAAE,CAAC,GAAG,IAAI,WAAW,IAAI,IAAI,MAAM,IAAI,EAAE,GAAG,IAAI,MAAM,IAAI,EAAE,CAAC,GAAG,IAAI,WAAW,IAAI,IAAI,MAAM,IAAI,EAAE,GAAG,IAAI,MAAM,IAAI,EAAE,CAAC,CAAC;AAAA,QACzS,IAAI,UAAU,IAAI,WAAW,KAAK,CAAC,GAAG,IAAI,IAAI,IAAI,KAAK,KAAK,GAAG,CAAC,GAAG,IAAI,WAAW,IAAI,IAAI,MAAM,IAAI,GAAG,GAAG,IAAI,MAAM,GAAG,GAAG,CAAC,GAAG,IAAI,WAAW,IAAI,IAAI,MAAM,IAAI,EAAE,GAAG,IAAI,MAAM,IAAI,EAAE,CAAC,GAAG,IAAI,WAAW,IAAI,IAAI,MAAM,IAAI,EAAE,GAAG,IAAI,MAAM,IAAI,EAAE,CAAC,GAAG,IAAI,WAAW,IAAI,IAAI,MAAM,IAAI,EAAE,GAAG,IAAI,MAAM,IAAI,EAAE,CAAC,CAAC;AAAA,MAC9S;AAiBA,UAAI;AACJ,OAAC,SAAUC,iBAAgB;AACvB,QAAAA,gBAAeA,gBAAe,eAAe,IAAI,CAAC,IAAI;AACtD,QAAAA,gBAAeA,gBAAe,eAAe,IAAI,CAAC,IAAI;AACtD,QAAAA,gBAAeA,gBAAe,eAAe,IAAI,CAAC,IAAI;AACtD,QAAAA,gBAAeA,gBAAe,eAAe,IAAI,CAAC,IAAI;AACtD,QAAAA,gBAAeA,gBAAe,eAAe,IAAI,CAAC,IAAI;AACtD,QAAAA,gBAAeA,gBAAe,eAAe,IAAI,CAAC,IAAI;AACtD,QAAAA,gBAAeA,gBAAe,eAAe,IAAI,CAAC,IAAI;AACtD,QAAAA,gBAAeA,gBAAe,eAAe,IAAI,CAAC,IAAI;AAAA,MAC1D,GAAG,mBAAmB,iBAAiB,CAAC,EAAE;AAAA,MAY1C,MAAM,SAAS;AAAA;AAAA,QAEX,YAAY,OAAO,UAAU;AACzB,eAAK,QAAQ;AACb,eAAK,WAAW;AAAA,QACpB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QASA,gBAAgB,MAAM,WAAmB;AACrC,mBAAS,IAAI,GAAG,IAAI,WAAW,KAAK;AAChC,qBAAS,IAAI,GAAG,IAAI,WAAW,KAAK;AAChC,kBAAI,KAAK,SAAS,GAAG,CAAC,GAAG;AACrB,qBAAK,KAAK,GAAG,CAAC;AAAA,cAClB;AAAA,YACJ;AAAA,UACJ;AAAA,QACJ;AAAA,MACJ;AACA,eAAS,SAAS,oBAAI,IAAI;AAAA;AAAA;AAAA;AAAA,QAItB,CAAC,eAAe,eAAe,IAAI,SAAS,eAAe,eAAe,CAAC,GAAW,MAAc;AAAE,kBAAS,IAAI,IAAK,OAAU;AAAA,QAAG,CAAC,CAAC;AAAA;AAAA;AAAA;AAAA,QAIvI,CAAC,eAAe,eAAe,IAAI,SAAS,eAAe,eAAe,CAAC,GAAW,MAAc;AAAE,kBAAQ,IAAI,OAAU;AAAA,QAAG,CAAC,CAAC;AAAA;AAAA;AAAA;AAAA,QAIjI,CAAC,eAAe,eAAe,IAAI,SAAS,eAAe,eAAe,CAAC,GAAW,MAAc;AAAE,iBAAO,IAAI,MAAM;AAAA,QAAG,CAAC,CAAC;AAAA;AAAA;AAAA;AAAA,QAI5H,CAAC,eAAe,eAAe,IAAI,SAAS,eAAe,eAAe,CAAC,GAAW,MAAc;AAAE,kBAAQ,IAAI,KAAK,MAAM;AAAA,QAAG,CAAC,CAAC;AAAA;AAAA;AAAA;AAAA,QAIlI,CAAC,eAAe,eAAe,IAAI,SAAS,eAAe,eAAe,CAAC,GAAW,MAAc;AAAE,kBAAS,KAAK,MAAM,IAAI,CAAC,IAAI,KAAK,MAAM,IAAI,CAAC,IAAK,OAAU;AAAA,QAAG,CAAC,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA,QAKvK,CAAC,eAAe,eAAe,IAAI,SAAS,eAAe,eAAe,CAAC,GAAW,MAAc;AAAE,iBAAQ,IAAI,IAAK,MAAM;AAAA,QAAG,CAAC,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA,QAKlI,CAAC,eAAe,eAAe,IAAI,SAAS,eAAe,eAAe,CAAC,GAAW,MAAc;AAAE,iBAAS,IAAI,IAAK,IAAK;AAAA,QAAG,CAAC,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA,QAKlI,CAAC,eAAe,eAAe,IAAI,SAAS,eAAe,eAAe,CAAC,GAAW,MAAc;AAAE,kBAAS,IAAI,IAAM,IAAI,IAAK,IAAM,OAAU;AAAA,QAAG,CAAC,CAAC;AAAA,MAC3J,CAAC;AAAA,MAoBD,MAAM,kBAAkB;AAAA;AAAA;AAAA;AAAA;AAAA,QAKpB,YAAY,WAAW;AACnB,gBAAM,YAAY,UAAU,UAAU;AACtC,cAAI,YAAY,OAAO,YAAY,OAAU,GAAG;AAC5C,kBAAM,IAAI,gBAAgB;AAAA,UAC9B;AACA,eAAK,YAAY;AAAA,QACrB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAQA,wBAAwB;AACpB,cAAI,KAAK,qBAAqB,QAAQ,KAAK,qBAAqB,QAAW;AACvE,mBAAO,KAAK;AAAA,UAChB;AAEA,cAAI,kBAAkB;AACtB,mBAAS,IAAI,GAAG,IAAI,GAAG,KAAK;AACxB,8BAAkB,KAAK,QAAQ,GAAG,GAAG,eAAe;AAAA,UACxD;AAEA,4BAAkB,KAAK,QAAQ,GAAG,GAAG,eAAe;AACpD,4BAAkB,KAAK,QAAQ,GAAG,GAAG,eAAe;AACpD,4BAAkB,KAAK,QAAQ,GAAG,GAAG,eAAe;AAEpD,mBAAS,IAAI,GAAG,KAAK,GAAG,KAAK;AACzB,8BAAkB,KAAK,QAAQ,GAAG,GAAG,eAAe;AAAA,UACxD;AAEA,gBAAM,YAAY,KAAK,UAAU,UAAU;AAC3C,cAAI,kBAAkB;AACtB,gBAAM,OAAO,YAAY;AACzB,mBAAS,IAAI,YAAY,GAAG,KAAK,MAAM,KAAK;AACxC,8BAAkB,KAAK,QAAQ,GAAG,GAAG,eAAe;AAAA,UACxD;AACA,mBAAS,IAAI,YAAY,GAAG,IAAI,WAAW,KAAK;AAC5C,8BAAkB,KAAK,QAAQ,GAAG,GAAG,eAAe;AAAA,UACxD;AACA,eAAK,mBAAmB,kBAAkB,wBAAwB,iBAAiB,eAAe;AAClG,cAAI,KAAK,qBAAqB,MAAM;AAChC,mBAAO,KAAK;AAAA,UAChB;AACA,gBAAM,IAAI,gBAAgB;AAAA,QAC9B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAQA,cAAc;AACV,cAAI,KAAK,kBAAkB,QAAQ,KAAK,kBAAkB,QAAW;AACjE,mBAAO,KAAK;AAAA,UAChB;AACA,gBAAM,YAAY,KAAK,UAAU,UAAU;AAC3C,gBAAM,qBAAqB,KAAK,OAAO,YAAY,MAAM,CAAC;AAC1D,cAAI,sBAAsB,GAAG;AACzB,mBAAO,UAAU,oBAAoB,kBAAkB;AAAA,UAC3D;AAEA,cAAI,cAAc;AAClB,gBAAM,QAAQ,YAAY;AAC1B,mBAAS,IAAI,GAAG,KAAK,GAAG,KAAK;AACzB,qBAAS,IAAI,YAAY,GAAG,KAAK,OAAO,KAAK;AACzC,4BAAc,KAAK,QAAQ,GAAG,GAAG,WAAW;AAAA,YAChD;AAAA,UACJ;AACA,cAAI,mBAAmB,UAAU,yBAAyB,WAAW;AACrE,cAAI,qBAAqB,QAAQ,iBAAiB,uBAAuB,MAAM,WAAW;AACtF,iBAAK,gBAAgB;AACrB,mBAAO;AAAA,UACX;AAEA,wBAAc;AACd,mBAAS,IAAI,GAAG,KAAK,GAAG,KAAK;AACzB,qBAAS,IAAI,YAAY,GAAG,KAAK,OAAO,KAAK;AACzC,4BAAc,KAAK,QAAQ,GAAG,GAAG,WAAW;AAAA,YAChD;AAAA,UACJ;AACA,6BAAmB,UAAU,yBAAyB,WAAW;AACjE,cAAI,qBAAqB,QAAQ,iBAAiB,uBAAuB,MAAM,WAAW;AACtF,iBAAK,gBAAgB;AACrB,mBAAO;AAAA,UACX;AACA,gBAAM,IAAI,gBAAgB;AAAA,QAC9B;AAAA,QACA,QAAQ,GAAW,GAAW,aAAqB;AAC/C,gBAAM,MAAM,KAAK,WAAW,KAAK,UAAU,IAAI,GAAG,CAAC,IAAI,KAAK,UAAU,IAAI,GAAG,CAAC;AAC9E,iBAAO,MAAO,eAAe,IAAK,IAAM,eAAe;AAAA,QAC3D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QASA,gBAAgB;AACZ,gBAAM,aAAa,KAAK,sBAAsB;AAC9C,gBAAM,UAAU,KAAK,YAAY;AAGjC,gBAAM,WAAW,SAAS,OAAO,IAAI,WAAW,YAAY,CAAC;AAC7D,gBAAM,YAAY,KAAK,UAAU,UAAU;AAC3C,mBAAS,gBAAgB,KAAK,WAAW,SAAS;AAClD,gBAAM,kBAAkB,QAAQ,qBAAqB;AACrD,cAAI,YAAY;AAChB,gBAAM,SAAS,IAAI,WAAW,QAAQ,kBAAkB,CAAC;AACzD,cAAI,eAAe;AACnB,cAAI,cAAc;AAClB,cAAI,WAAW;AAEf,mBAAS,IAAI,YAAY,GAAG,IAAI,GAAG,KAAK,GAAG;AACvC,gBAAI,MAAM,GAAG;AAGT;AAAA,YACJ;AAEA,qBAAS,QAAQ,GAAG,QAAQ,WAAW,SAAS;AAC5C,oBAAM,IAAI,YAAY,YAAY,IAAI,QAAQ;AAC9C,uBAAS,MAAM,GAAG,MAAM,GAAG,OAAO;AAE9B,oBAAI,CAAC,gBAAgB,IAAI,IAAI,KAAK,CAAC,GAAG;AAElC;AACA,kCAAgB;AAChB,sBAAI,KAAK,UAAU,IAAI,IAAI,KAAK,CAAC,GAAG;AAChC,mCAAe;AAAA,kBACnB;AAEA,sBAAI,aAAa,GAAG;AAChB,2BAAO,cAAc;AAAA,oBAAgB;AACrC,+BAAW;AACX,kCAAc;AAAA,kBAClB;AAAA,gBACJ;AAAA,cACJ;AAAA,YACJ;AACA,wBAAY,CAAC;AAAA,UACjB;AACA,cAAI,iBAAiB,QAAQ,kBAAkB,GAAG;AAC9C,kBAAM,IAAI,gBAAgB;AAAA,UAC9B;AACA,iBAAO;AAAA,QACX;AAAA;AAAA;AAAA;AAAA,QAIA,SAAS;AACL,cAAI,KAAK,qBAAqB,MAAM;AAChC;AAAA,UACJ;AACA,gBAAM,WAAW,SAAS,OAAO,KAAK,iBAAiB,YAAY,CAAC;AACpE,gBAAM,YAAY,KAAK,UAAU,UAAU;AAC3C,mBAAS,gBAAgB,KAAK,WAAW,SAAS;AAAA,QACtD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QASA,UAAU,UAAU;AAChB,eAAK,gBAAgB;AACrB,eAAK,mBAAmB;AACxB,eAAK,WAAW;AAAA,QACpB;AAAA;AAAA,QAEA,SAAS;AACL,gBAAM,YAAY,KAAK;AACvB,mBAAS,IAAI,GAAG,QAAQ,UAAU,SAAS,GAAG,IAAI,OAAO,KAAK;AAC1D,qBAAS,IAAI,IAAI,GAAG,SAAS,UAAU,UAAU,GAAG,IAAI,QAAQ,KAAK;AACjE,kBAAI,UAAU,IAAI,GAAG,CAAC,MAAM,UAAU,IAAI,GAAG,CAAC,GAAG;AAC7C,0BAAU,KAAK,GAAG,CAAC;AACnB,0BAAU,KAAK,GAAG,CAAC;AAAA,cACvB;AAAA,YACJ;AAAA,UACJ;AAAA,QACJ;AAAA,MACJ;AAAA,MAwBA,MAAM,YAAY;AAAA,QACd,YAAY,kBAA0B,WAAW;AAC7C,eAAK,mBAAmB;AACxB,eAAK,YAAY;AAAA,QACrB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAYA,OAAO,cAAc,cAAc,SAAS,SAAS;AACjD,cAAI,aAAa,WAAW,QAAQ,kBAAkB,GAAG;AACrD,kBAAM,IAAI,yBAAyB;AAAA,UACvC;AAGA,gBAAM,WAAW,QAAQ,oBAAoB,OAAO;AAEpD,cAAI,cAAc;AAClB,gBAAM,eAAe,SAAS,YAAY;AAC1C,qBAAW,WAAW,cAAc;AAChC,2BAAe,QAAQ,SAAS;AAAA,UACpC;AAEA,gBAAM,SAAS,IAAI,MAAM,WAAW;AACpC,cAAI,kBAAkB;AACtB,qBAAW,WAAW,cAAc;AAChC,qBAAS,IAAI,GAAG,IAAI,QAAQ,SAAS,GAAG,KAAK;AACzC,oBAAM,mBAAmB,QAAQ,iBAAiB;AAClD,oBAAM,oBAAoB,SAAS,uBAAuB,IAAI;AAC9D,qBAAO,iBAAiB,IAAI,IAAI,YAAY,kBAAkB,IAAI,WAAW,iBAAiB,CAAC;AAAA,YACnG;AAAA,UACJ;AAGA,gBAAM,8BAA8B,OAAO,CAAC,EAAE,UAAU;AACxD,cAAI,sBAAsB,OAAO,SAAS;AAE1C,iBAAO,uBAAuB,GAAG;AAC7B,kBAAM,eAAe,OAAO,mBAAmB,EAAE,UAAU;AAC3D,gBAAI,iBAAiB,6BAA6B;AAC9C;AAAA,YACJ;AACA;AAAA,UACJ;AACA;AACA,gBAAM,gCAAgC,8BAA8B,SAAS,uBAAuB;AAGpG,cAAI,qBAAqB;AACzB,mBAAS,IAAI,GAAG,IAAI,+BAA+B,KAAK;AACpD,qBAAS,IAAI,GAAG,IAAI,iBAAiB,KAAK;AACtC,qBAAO,CAAC,EAAE,UAAU,CAAC,IAAI,aAAa,oBAAoB;AAAA,YAC9D;AAAA,UACJ;AAEA,mBAAS,IAAI,qBAAqB,IAAI,iBAAiB,KAAK;AACxD,mBAAO,CAAC,EAAE,UAAU,6BAA6B,IAAI,aAAa,oBAAoB;AAAA,UAC1F;AAEA,gBAAM,MAAM,OAAO,CAAC,EAAE,UAAU;AAChC,mBAAS,IAAI,+BAA+B,IAAI,KAAK,KAAK;AACtD,qBAAS,IAAI,GAAG,IAAI,iBAAiB,KAAK;AACtC,oBAAM,UAAU,IAAI,sBAAsB,IAAI,IAAI;AAClD,qBAAO,CAAC,EAAE,UAAU,OAAO,IAAI,aAAa,oBAAoB;AAAA,YACpE;AAAA,UACJ;AACA,iBAAO;AAAA,QACX;AAAA,QACA,sBAAsB;AAClB,iBAAO,KAAK;AAAA,QAChB;AAAA,QACA,eAAe;AACX,iBAAO,KAAK;AAAA,QAChB;AAAA,MACJ;AAiBA,UAAI;AACJ,OAAC,SAAUC,aAAY;AACnB,QAAAA,YAAWA,YAAW,YAAY,IAAI,CAAC,IAAI;AAC3C,QAAAA,YAAWA,YAAW,SAAS,IAAI,CAAC,IAAI;AACxC,QAAAA,YAAWA,YAAW,cAAc,IAAI,CAAC,IAAI;AAC7C,QAAAA,YAAWA,YAAW,mBAAmB,IAAI,CAAC,IAAI;AAClD,QAAAA,YAAWA,YAAW,MAAM,IAAI,CAAC,IAAI;AACrC,QAAAA,YAAWA,YAAW,KAAK,IAAI,CAAC,IAAI;AACpC,QAAAA,YAAWA,YAAW,OAAO,IAAI,CAAC,IAAI;AACtC,QAAAA,YAAWA,YAAW,qBAAqB,IAAI,CAAC,IAAI;AACpD,QAAAA,YAAWA,YAAW,sBAAsB,IAAI,CAAC,IAAI;AAErD,QAAAA,YAAWA,YAAW,OAAO,IAAI,CAAC,IAAI;AAAA,MAC1C,GAAG,eAAe,aAAa,CAAC,EAAE;AAAA,MAOlC,MAAM,OAAO;AAAA,QACT,YAAY,OAAO,aAAa,+BAA+B,MAAc;AACzE,eAAK,QAAQ;AACb,eAAK,cAAc;AACnB,eAAK,gCAAgC;AACrC,eAAK,OAAO;AACZ,iBAAO,SAAS,IAAI,MAAM,IAAI;AAC9B,iBAAO,UAAU,IAAI,OAAO,IAAI;AAAA,QACpC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAMA,OAAO,QAAQ,MAAc;AACzB,gBAAM,OAAO,OAAO,SAAS,IAAI,IAAI;AACrC,cAAI,WAAc,MAAM;AACpB,kBAAM,IAAI,yBAAyB;AAAA,UACvC;AACA,iBAAO;AAAA,QACX;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAMA,sBAAsB,SAAS;AAC3B,gBAAM,gBAAgB,QAAQ,iBAAiB;AAC/C,cAAI;AACJ,cAAI,iBAAiB,GAAG;AACpB,qBAAS;AAAA,UACb,WACS,iBAAiB,IAAI;AAC1B,qBAAS;AAAA,UACb,OACK;AACD,qBAAS;AAAA,UACb;AACA,iBAAO,KAAK,8BAA8B,MAAM;AAAA,QACpD;AAAA,QACA,WAAW;AACP,iBAAO,KAAK;AAAA,QAChB;AAAA,QACA,UAAU;AACN,iBAAO,KAAK;AAAA,QAChB;AAAA,QACA,OAAO,GAAG;AACN,cAAI,EAAE,aAAa,SAAS;AACxB,mBAAO;AAAA,UACX;AACA,gBAAM,QAAQ;AACd,iBAAO,KAAK,UAAU,MAAM;AAAA,QAChC;AAAA,QACA,WAAW;AACP,iBAAO,KAAK;AAAA,QAChB;AAAA,MACJ;AACA,aAAO,WAAW,oBAAI,IAAI;AAC1B,aAAO,YAAY,oBAAI,IAAI;AAC3B,aAAO,aAAa,IAAI,OAAO,WAAW,YAAY,cAAc,WAAW,KAAK,CAAC,GAAG,GAAG,CAAC,CAAC,GAAG,CAAI;AACpG,aAAO,UAAU,IAAI,OAAO,WAAW,SAAS,WAAW,WAAW,KAAK,CAAC,IAAI,IAAI,EAAE,CAAC,GAAG,CAAI;AAC9F,aAAO,eAAe,IAAI,OAAO,WAAW,cAAc,gBAAgB,WAAW,KAAK,CAAC,GAAG,IAAI,EAAE,CAAC,GAAG,CAAI;AAC5G,aAAO,oBAAoB,IAAI,OAAO,WAAW,mBAAmB,qBAAqB,WAAW,KAAK,CAAC,GAAG,GAAG,CAAC,CAAC,GAAG,CAAI;AACzH,aAAO,OAAO,IAAI,OAAO,WAAW,MAAM,QAAQ,WAAW,KAAK,CAAC,GAAG,IAAI,EAAE,CAAC,GAAG,CAAI;AACpF,aAAO,MAAM,IAAI,OAAO,WAAW,KAAK,OAAO,WAAW,KAAK,CAAC,GAAG,GAAG,CAAC,CAAC,GAAG,CAAI;AAC/E,aAAO,QAAQ,IAAI,OAAO,WAAW,OAAO,SAAS,WAAW,KAAK,CAAC,GAAG,IAAI,EAAE,CAAC,GAAG,CAAI;AACvF,aAAO,sBAAsB,IAAI,OAAO,WAAW,qBAAqB,uBAAuB,WAAW,KAAK,CAAC,GAAG,GAAG,CAAC,CAAC,GAAG,CAAI;AAC/H,aAAO,uBAAuB,IAAI,OAAO,WAAW,sBAAsB,wBAAwB,WAAW,KAAK,CAAC,GAAG,GAAG,CAAC,CAAC,GAAG,CAAI;AAElI,aAAO,QAAQ,IAAI,OAAO,WAAW,OAAO,SAAS,WAAW,KAAK,CAAC,GAAG,IAAI,EAAE,CAAC,GAAG,EAAI;AAAA,MA8BvF,MAAM,yBAAyB;AAAA,QAC3B,OAAO,OAAO,OAAO,SAAS,SAAS,OAAO;AAC1C,gBAAM,OAAO,IAAI,UAAU,KAAK;AAChC,cAAI,SAAS,IAAI,cAAc;AAC/B,gBAAM,eAAe,IAAI,MAAM;AAE/B,cAAI,iBAAiB;AACrB,cAAI,aAAa;AACjB,cAAI;AACA,gBAAI,yBAAyB;AAC7B,gBAAI,cAAc;AAClB,gBAAI;AACJ,eAAG;AAEC,kBAAI,KAAK,UAAU,IAAI,GAAG;AAEtB,uBAAO,OAAO;AAAA,cAClB,OACK;AACD,sBAAM,WAAW,KAAK,SAAS,CAAC;AAChC,uBAAO,OAAO,QAAQ,QAAQ;AAAA,cAClC;AACA,sBAAQ,MAAM;AAAA,gBACV,KAAK,OAAO;AACR;AAAA,gBACJ,KAAK,OAAO;AAAA,gBACZ,KAAK,OAAO;AAER,gCAAc;AACd;AAAA,gBACJ,KAAK,OAAO;AACR,sBAAI,KAAK,UAAU,IAAI,IAAI;AACvB,0BAAM,IAAI,gBAAgB;AAAA,kBAC9B;AAGA,mCAAiB,KAAK,SAAS,CAAC;AAChC,+BAAa,KAAK,SAAS,CAAC;AAC5B;AAAA,gBACJ,KAAK,OAAO;AAER,wBAAM,QAAQ,yBAAyB,cAAc,IAAI;AACzD,2CAAyB,gBAAgB,0BAA0B,KAAK;AACxE,sBAAI,2BAA2B,MAAM;AACjC,0BAAM,IAAI,gBAAgB;AAAA,kBAC9B;AACA;AAAA,gBACJ,KAAK,OAAO;AAGR,wBAAM,SAAS,KAAK,SAAS,CAAC;AAC9B,wBAAM,aAAa,KAAK,SAAS,KAAK,sBAAsB,OAAO,CAAC;AACpE,sBAAI,WAAW,yBAAyB,eAAe;AACnD,6CAAyB,mBAAmB,MAAM,QAAQ,UAAU;AAAA,kBACxE;AACA;AAAA,gBACJ;AAGI,wBAAM,QAAQ,KAAK,SAAS,KAAK,sBAAsB,OAAO,CAAC;AAC/D,0BAAQ,MAAM;AAAA,oBACV,KAAK,OAAO;AACR,+CAAyB,qBAAqB,MAAM,QAAQ,KAAK;AACjE;AAAA,oBACJ,KAAK,OAAO;AACR,+CAAyB,0BAA0B,MAAM,QAAQ,OAAO,WAAW;AACnF;AAAA,oBACJ,KAAK,OAAO;AACR,+CAAyB,kBAAkB,MAAM,QAAQ,OAAO,wBAAwB,cAAc,KAAK;AAC3G;AAAA,oBACJ,KAAK,OAAO;AACR,+CAAyB,mBAAmB,MAAM,QAAQ,KAAK;AAC/D;AAAA,oBACJ;AACI,4BAAM,IAAI,gBAAgB;AAAA,kBAClC;AACA;AAAA,cACR;AAAA,YACJ,SAAS,SAAS,OAAO;AAAA,UAC7B,SACO,KAAoC;AAEvC,kBAAM,IAAI,gBAAgB;AAAA,UAC9B;AACA,iBAAO,IAAI,cAAc,OAAO,OAAO,SAAS,GAAG,aAAa,WAAW,IAAI,OAAO,cAAc,YAAY,OAAO,OAAO,QAAQ,SAAS,GAAG,gBAAgB,UAAU;AAAA,QAChL;AAAA;AAAA;AAAA;AAAA,QAIA,OAAO,mBAAmB,MAAM,QAAQ,OAAe;AAEnD,cAAI,QAAQ,KAAK,KAAK,UAAU,GAAG;AAC/B,kBAAM,IAAI,gBAAgB;AAAA,UAC9B;AAGA,gBAAM,SAAS,IAAI,WAAW,IAAI,KAAK;AACvC,cAAI,SAAS;AACb,iBAAO,QAAQ,GAAG;AAEd,kBAAM,WAAW,KAAK,SAAS,EAAE;AACjC,gBAAI,oBAAuB,WAAW,MAAU,IAAK,aAAe,WAAW;AAC/E,gBAAI,oBAAoB,KAAS;AAE7B,mCAAqB;AAAA,YACzB,OACK;AAED,mCAAqB;AAAA,YACzB;AACA,mBAAO,MAAM;AAAA,YAAkB,qBAAqB,IAAK;AACzD,mBAAO,SAAS,CAAC;AAAA,YAAiB,oBAAoB;AACtD,sBAAU;AACV;AAAA,UACJ;AACA,cAAI;AACA,mBAAO,OAAO,eAAe,OAAO,QAAQ,YAAY,MAAM,CAAC;AAAA,UAEnE,SACO,SAA4C;AAC/C,kBAAM,IAAI,gBAAgB,OAAO;AAAA,UACrC;AAAA,QACJ;AAAA,QACA,OAAO,mBAAmB,MAAM,QAAQ,OAAe;AAEnD,cAAI,QAAQ,KAAK,KAAK,UAAU,GAAG;AAC/B,kBAAM,IAAI,gBAAgB;AAAA,UAC9B;AAGA,gBAAM,SAAS,IAAI,WAAW,IAAI,KAAK;AACvC,cAAI,SAAS;AACb,iBAAO,QAAQ,GAAG;AAEd,kBAAM,WAAW,KAAK,SAAS,EAAE;AACjC,gBAAI,oBAAuB,WAAW,OAAU,IAAK,aAAe,WAAW;AAC/E,gBAAI,oBAAoB,MAAS;AAE7B,mCAAqB;AAAA,YACzB,OACK;AAED,mCAAqB;AAAA,YACzB;AACA,mBAAO,MAAM;AAAA,YAAiB,qBAAqB;AACnD,mBAAO,SAAS,CAAC;AAAA,YAAgB;AACjC,sBAAU;AACV;AAAA,UACJ;AAEA,cAAI;AACA,mBAAO,OAAO,eAAe,OAAO,QAAQ,YAAY,SAAS,CAAC;AAAA,UAEtE,SACO,SAA4C;AAC/C,kBAAM,IAAI,gBAAgB,OAAO;AAAA,UACrC;AAAA,QACJ;AAAA,QACA,OAAO,kBAAkB,MAAM,QAAQ,OAAe,wBAAwB,cAAc,OAAO;AAE/F,cAAI,IAAI,QAAQ,KAAK,UAAU,GAAG;AAC9B,kBAAM,IAAI,gBAAgB;AAAA,UAC9B;AACA,gBAAM,YAAY,IAAI,WAAW,KAAK;AACtC,mBAAS,IAAI,GAAG,IAAI,OAAO,KAAK;AAC5B,sBAAU,CAAC;AAAA,YAAgB,KAAK,SAAS,CAAC;AAAA,UAC9C;AACA,cAAI;AACJ,cAAI,2BAA2B,MAAM;AAMjC,uBAAW,YAAY,cAAc,WAAW,KAAK;AAAA,UACzD,OACK;AACD,uBAAW,uBAAuB,QAAQ;AAAA,UAC9C;AACA,cAAI;AACA,mBAAO,OAAO,eAAe,OAAO,WAAW,QAAQ,CAAC;AAAA,UAC5D,SACO,SAA4C;AAC/C,kBAAM,IAAI,gBAAgB,OAAO;AAAA,UACrC;AACA,uBAAa,KAAK,SAAS;AAAA,QAC/B;AAAA,QACA,OAAO,mBAAmB,OAAe;AACrC,cAAI,SAAS,yBAAyB,mBAAmB,QAAQ;AAC7D,kBAAM,IAAI,gBAAgB;AAAA,UAC9B;AACA,iBAAO,yBAAyB,mBAAmB,KAAK;AAAA,QAC5D;AAAA,QACA,OAAO,0BAA0B,MAAM,QAAQ,OAAe,aAAa;AAEvE,gBAAM,QAAQ,OAAO,OAAO;AAC5B,iBAAO,QAAQ,GAAG;AACd,gBAAI,KAAK,UAAU,IAAI,IAAI;AACvB,oBAAM,IAAI,gBAAgB;AAAA,YAC9B;AACA,kBAAM,mBAAmB,KAAK,SAAS,EAAE;AACzC,mBAAO,OAAO,yBAAyB,mBAAmB,KAAK,MAAM,mBAAmB,EAAE,CAAC,CAAC;AAC5F,mBAAO,OAAO,yBAAyB,mBAAmB,mBAAmB,EAAE,CAAC;AAChF,qBAAS;AAAA,UACb;AACA,cAAI,UAAU,GAAG;AAEb,gBAAI,KAAK,UAAU,IAAI,GAAG;AACtB,oBAAM,IAAI,gBAAgB;AAAA,YAC9B;AACA,mBAAO,OAAO,yBAAyB,mBAAmB,KAAK,SAAS,CAAC,CAAC,CAAC;AAAA,UAC/E;AAEA,cAAI,aAAa;AAEb,qBAAS,IAAI,OAAO,IAAI,OAAO,OAAO,GAAG,KAAK;AAC1C,kBAAI,OAAO,OAAO,CAAC,MAAM,KAAK;AAC1B,oBAAI,IAAI,OAAO,OAAO,IAAI,KAAK,OAAO,OAAO,IAAI,CAAC,MAAM,KAAK;AAEzD,yBAAO,aAAa,IAAI,CAAC;AAAA,gBAC7B,OACK;AAED,yBAAO,UAAU,GAAG,OAAO,aAAa,EAAI,CAAC;AAAA,gBACjD;AAAA,cACJ;AAAA,YACJ;AAAA,UACJ;AAAA,QACJ;AAAA,QACA,OAAO,qBAAqB,MAAM,QAAQ,OAAe;AAErD,iBAAO,SAAS,GAAG;AAEf,gBAAI,KAAK,UAAU,IAAI,IAAI;AACvB,oBAAM,IAAI,gBAAgB;AAAA,YAC9B;AACA,kBAAM,kBAAkB,KAAK,SAAS,EAAE;AACxC,gBAAI,mBAAmB,KAAM;AACzB,oBAAM,IAAI,gBAAgB;AAAA,YAC9B;AACA,mBAAO,OAAO,yBAAyB,mBAAmB,KAAK,MAAM,kBAAkB,GAAG,CAAC,CAAC;AAC5F,mBAAO,OAAO,yBAAyB,mBAAmB,KAAK,MAAM,kBAAkB,EAAE,IAAI,EAAE,CAAC;AAChG,mBAAO,OAAO,yBAAyB,mBAAmB,kBAAkB,EAAE,CAAC;AAC/E,qBAAS;AAAA,UACb;AACA,cAAI,UAAU,GAAG;AAEb,gBAAI,KAAK,UAAU,IAAI,GAAG;AACtB,oBAAM,IAAI,gBAAgB;AAAA,YAC9B;AACA,kBAAM,gBAAgB,KAAK,SAAS,CAAC;AACrC,gBAAI,iBAAiB,KAAK;AACtB,oBAAM,IAAI,gBAAgB;AAAA,YAC9B;AACA,mBAAO,OAAO,yBAAyB,mBAAmB,KAAK,MAAM,gBAAgB,EAAE,CAAC,CAAC;AACzF,mBAAO,OAAO,yBAAyB,mBAAmB,gBAAgB,EAAE,CAAC;AAAA,UACjF,WACS,UAAU,GAAG;AAElB,gBAAI,KAAK,UAAU,IAAI,GAAG;AACtB,oBAAM,IAAI,gBAAgB;AAAA,YAC9B;AACA,kBAAM,YAAY,KAAK,SAAS,CAAC;AACjC,gBAAI,aAAa,IAAI;AACjB,oBAAM,IAAI,gBAAgB;AAAA,YAC9B;AACA,mBAAO,OAAO,yBAAyB,mBAAmB,SAAS,CAAC;AAAA,UACxE;AAAA,QACJ;AAAA,QACA,OAAO,cAAc,MAAM;AACvB,gBAAM,YAAY,KAAK,SAAS,CAAC;AACjC,eAAK,YAAY,SAAU,GAAG;AAE1B,mBAAO,YAAY;AAAA,UACvB;AACA,eAAK,YAAY,SAAU,KAAM;AAE7B,kBAAM,aAAa,KAAK,SAAS,CAAC;AAClC,oBAAU,YAAY,OAAS,IAAK,aAAc;AAAA,UACtD;AACA,eAAK,YAAY,SAAU,KAAM;AAE7B,kBAAM,mBAAmB,KAAK,SAAS,EAAE;AACzC,oBAAU,YAAY,OAAS,KAAM,aAAc;AAAA,UACvD;AACA,gBAAM,IAAI,gBAAgB;AAAA,QAC9B;AAAA,MACJ;AAIA,+BAAyB,qBAAqB;AAC9C,+BAAyB,gBAAgB;AAAA,MA+BzC,MAAM,sBAAsB;AAAA,QACxB,YAAY,UAAU;AAClB,eAAK,WAAW;AAAA,QACpB;AAAA;AAAA;AAAA;AAAA,QAIA,aAAa;AACT,iBAAO,KAAK;AAAA,QAChB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAMA,wBAAwB,QAAQ;AAC5B,cAAI,CAAC,KAAK,YAAY,WAAW,QAAQ,OAAO,SAAS,GAAG;AACxD;AAAA,UACJ;AACA,gBAAM,aAAa,OAAO,CAAC;AAC3B,iBAAO,CAAC,IAAI,OAAO,CAAC;AACpB,iBAAO,CAAC,IAAI;AAAA,QAEhB;AAAA,MACJ;AAAA,MAwBA,MAAM,UAAU;AAAA,QACZ,cAAc;AACV,eAAK,YAAY,IAAI,mBAAmB,UAAU,iBAAiB;AAAA,QACvE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAcA,mBAAmB,OAAO,OAAO;AAC7B,iBAAO,KAAK,gBAAgB,UAAU,sBAAsB,KAAK,GAAG,KAAK;AAAA,QAC7E;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAaA,gBAAgB,MAAM,OAAO;AAEzB,gBAAM,SAAS,IAAI,kBAAkB,IAAI;AACzC,cAAI,KAAK;AACT,cAAI;AACA,mBAAO,KAAK,sBAAsB,QAAQ,KAAK;AAAA,UACnD,SACO,GAA4C;AAC/C,iBAAK;AAAA,UACT;AACA,cAAI;AAEA,mBAAO,OAAO;AAEd,mBAAO,UAAU,IAAI;AAErB,mBAAO,YAAY;AAEnB,mBAAO,sBAAsB;AAQ7B,mBAAO,OAAO;AACd,kBAAM,SAAS,KAAK,sBAAsB,QAAQ,KAAK;AAEvD,mBAAO,SAAS,IAAI,sBAAsB,IAAI,CAAC;AAC/C,mBAAO;AAAA,UACX,SACO,GAA2C;AAE9C,gBAAI,OAAO,MAAM;AACb,oBAAM;AAAA,YACV;AACA,kBAAM;AAAA,UACV;AAAA,QACJ;AAAA,QACA,sBAAsB,QAAQ,OAAO;AACjC,gBAAM,UAAU,OAAO,YAAY;AACnC,gBAAM,UAAU,OAAO,sBAAsB,EAAE,wBAAwB;AAEvE,gBAAM,YAAY,OAAO,cAAc;AAEvC,gBAAM,aAAa,YAAY,cAAc,WAAW,SAAS,OAAO;AAExE,cAAI,aAAa;AACjB,qBAAW,aAAa,YAAY;AAChC,0BAAc,UAAU,oBAAoB;AAAA,UAChD;AACA,gBAAM,cAAc,IAAI,WAAW,UAAU;AAC7C,cAAI,eAAe;AAEnB,qBAAW,aAAa,YAAY;AAChC,kBAAM,gBAAgB,UAAU,aAAa;AAC7C,kBAAM,mBAAmB,UAAU,oBAAoB;AACvD,iBAAK,cAAc,eAAe,gBAAgB;AAClD,qBAAS,IAAI,GAAG,IAAI,kBAAkB,KAAK;AACvC,0BAAY,cAAc,IAAI,cAAc,CAAC;AAAA,YACjD;AAAA,UACJ;AAEA,iBAAO,yBAAyB,OAAO,aAAa,SAAS,SAAS,KAAK;AAAA,QAC/E;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QASA,cAAc,eAAe,kBAA0B;AAGnD,gBAAM,gBAAgB,IAAI,WAAW,aAAa;AAMlD,cAAI;AACA,iBAAK,UAAU,OAAO,eAAe,cAAc,SAAS,gBAAgB;AAAA,UAChF,SACO,SAAoC;AACvC,kBAAM,IAAI,kBAAkB;AAAA,UAChC;AAGA,mBAAS,IAAI,GAAG,IAAI,kBAAkB,KAAK;AACvC,0BAAc,CAAC;AAAA,YAAgB,cAAc,CAAC;AAAA,UAClD;AAAA,QACJ;AAAA,MACJ;AAAA,MAuBA,MAAM,yBAAyB,YAAY;AAAA,QACvC,YAAY,MAAgB,MAAgB,qBAA+B;AACvE,gBAAM,MAAM,IAAI;AAChB,eAAK,sBAAsB;AAAA,QAC/B;AAAA;AAAA;AAAA;AAAA;AAAA,QAKA,YAAY,YAAsB,GAAa,GAAa;AACxD,cAAI,KAAK,IAAI,IAAI,KAAK,KAAK,CAAC,KAAK,cAAc,KAAK,IAAI,IAAI,KAAK,KAAK,CAAC,KAAK,YAAY;AACpF,kBAAM,iBAAiB,KAAK,IAAI,aAAa,KAAK,mBAAmB;AACrE,mBAAO,kBAAkB,KAAO,kBAAkB,KAAK;AAAA,UAC3D;AACA,iBAAO;AAAA,QACX;AAAA;AAAA;AAAA;AAAA;AAAA,QAKA,gBAAgB,GAAa,GAAa,eAAyB;AAC/D,gBAAM,aAAa,KAAK,KAAK,IAAI,KAAK;AACtC,gBAAM,aAAa,KAAK,KAAK,IAAI,KAAK;AACtC,gBAAM,sBAAsB,KAAK,sBAAsB,iBAAiB;AACxE,iBAAO,IAAI,iBAAiB,WAAW,WAAW,kBAAkB;AAAA,QACxE;AAAA,MACJ;AAAA,MAiCA,MAAM,uBAAuB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAWzB,YAAY,OAAO,QAAgB,QAAgB,OAAe,QAAgB,YAAsB,qBAAqB;AACzH,eAAK,QAAQ;AACb,eAAK,SAAS;AACd,eAAK,SAAS;AACd,eAAK,QAAQ;AACb,eAAK,SAAS;AACd,eAAK,aAAa;AAClB,eAAK,sBAAsB;AAC3B,eAAK,kBAAkB,CAAC;AAExB,eAAK,uBAAuB,IAAI,WAAW,CAAC;AAAA,QAChD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAQA,OAAO;AACH,gBAAM,SAAS,KAAK;AACpB,gBAAM,SAAS,KAAK;AACpB,gBAAM,QAAQ,KAAK;AACnB,gBAAM,OAAO,SAAS;AACtB,gBAAM,UAAU,KAAK,SAAU,SAAS;AAGxC,gBAAM,aAAa,IAAI,WAAW,CAAC;AACnC,gBAAM,QAAQ,KAAK;AACnB,mBAAS,OAAO,GAAG,OAAO,QAAQ,QAAQ;AAEtC,kBAAM,IAAI,YAAY,OAAO,OAAU,IAAI,KAAK,OAAO,OAAO,KAAK,CAAC,IAAI,CAAC,KAAK,OAAO,OAAO,KAAK,CAAC;AAClG,uBAAW,CAAC,IAAI;AAChB,uBAAW,CAAC,IAAI;AAChB,uBAAW,CAAC,IAAI;AAChB,gBAAI,IAAI;AAIR,mBAAO,IAAI,QAAQ,CAAC,MAAM,IAAI,GAAG,CAAC,GAAG;AACjC;AAAA,YACJ;AACA,gBAAI,eAAe;AACnB,mBAAO,IAAI,MAAM;AACb,kBAAI,MAAM,IAAI,GAAG,CAAC,GAAG;AAEjB,oBAAI,iBAAiB,GAAG;AACpB,6BAAW,CAAC;AAAA,gBAChB,OACK;AACD,sBAAI,iBAAiB,GAAG;AACpB,wBAAI,KAAK,kBAAkB,UAAU,GAAG;AACpC,4BAAM,YAAY,KAAK,qBAAqB,YAAY,GAAG,CAAC;AAC5D,0BAAI,cAAc,MAAM;AACpB,+BAAO;AAAA,sBACX;AAAA,oBACJ;AACA,+BAAW,CAAC,IAAI,WAAW,CAAC;AAC5B,+BAAW,CAAC,IAAI;AAChB,+BAAW,CAAC,IAAI;AAChB,mCAAe;AAAA,kBACnB,OACK;AACD,+BAAW,EAAE,YAAY;AAAA,kBAC7B;AAAA,gBACJ;AAAA,cACJ,OACK;AACD,oBAAI,iBAAiB,GAAG;AACpB;AAAA,gBACJ;AACA,2BAAW,YAAY;AAAA,cAC3B;AACA;AAAA,YACJ;AACA,gBAAI,KAAK,kBAAkB,UAAU,GAAG;AACpC,oBAAM,YAAY,KAAK,qBAAqB,YAAY,GAAG,IAAI;AAC/D,kBAAI,cAAc,MAAM;AACpB,uBAAO;AAAA,cACX;AAAA,YACJ;AAAA,UACJ;AAGA,cAAI,KAAK,gBAAgB,WAAW,GAAG;AACnC,mBAAO,KAAK,gBAAgB,CAAC;AAAA,UACjC;AACA,gBAAM,IAAI,kBAAkB;AAAA,QAChC;AAAA;AAAA;AAAA;AAAA;AAAA,QAKA,OAAO,cAAc,YAAY,KAAa;AAC1C,iBAAQ,MAAM,WAAW,CAAC,IAAK,WAAW,CAAC,IAAI;AAAA,QACnD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAMA,kBAAkB,YAAY;AAC1B,gBAAM,aAAa,KAAK;AACxB,gBAAM,cAAc,aAAa;AACjC,mBAAS,IAAI,GAAG,IAAI,GAAG,KAAK;AACxB,gBAAI,KAAK,IAAI,aAAa,WAAW,CAAC,CAAC,KAAK,aAAa;AACrD,qBAAO;AAAA,YACX;AAAA,UACJ;AACA,iBAAO;AAAA,QACX;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAYA,mBAAmB,QAAgB,SAAiB,UAAkB,yBAAiC;AACnG,gBAAM,QAAQ,KAAK;AACnB,gBAAM,OAAO,MAAM,UAAU;AAC7B,gBAAM,aAAa,KAAK;AACxB,qBAAW,CAAC,IAAI;AAChB,qBAAW,CAAC,IAAI;AAChB,qBAAW,CAAC,IAAI;AAEhB,cAAI,IAAI;AACR,iBAAO,KAAK,KAAK,MAAM,IAAI,SAAS,CAAC,KAAK,WAAW,CAAC,KAAK,UAAU;AACjE,uBAAW,CAAC;AACZ;AAAA,UACJ;AAEA,cAAI,IAAI,KAAK,WAAW,CAAC,IAAI,UAAU;AACnC,mBAAO;AAAA,UACX;AACA,iBAAO,KAAK,KAAK,CAAC,MAAM,IAAI,SAAS,CAAC,KAAK,WAAW,CAAC,KAAK,UAAU;AAClE,uBAAW,CAAC;AACZ;AAAA,UACJ;AACA,cAAI,WAAW,CAAC,IAAI,UAAU;AAC1B,mBAAO;AAAA,UACX;AAEA,cAAI,SAAS;AACb,iBAAO,IAAI,QAAQ,MAAM,IAAI,SAAS,CAAC,KAAK,WAAW,CAAC,KAAK,UAAU;AACnE,uBAAW,CAAC;AACZ;AAAA,UACJ;AACA,cAAI,MAAM,QAAQ,WAAW,CAAC,IAAI,UAAU;AACxC,mBAAO;AAAA,UACX;AACA,iBAAO,IAAI,QAAQ,CAAC,MAAM,IAAI,SAAS,CAAC,KAAK,WAAW,CAAC,KAAK,UAAU;AACpE,uBAAW,CAAC;AACZ;AAAA,UACJ;AACA,cAAI,WAAW,CAAC,IAAI,UAAU;AAC1B,mBAAO;AAAA,UACX;AACA,gBAAM,kBAAkB,WAAW,CAAC,IAAI,WAAW,CAAC,IAAI,WAAW,CAAC;AACpE,cAAI,IAAI,KAAK,IAAI,kBAAkB,uBAAuB,KAAK,IAAI,yBAAyB;AACxF,mBAAO;AAAA,UACX;AACA,iBAAO,KAAK,kBAAkB,UAAU,IAAI,uBAAuB,cAAc,YAAY,CAAC,IAAI;AAAA,QACtG;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAYA,qBAAqB,YAAY,GAAW,GAAW;AACnD,gBAAM,kBAAkB,WAAW,CAAC,IAAI,WAAW,CAAC,IAAI,WAAW,CAAC;AACpE,gBAAM,UAAU,uBAAuB,cAAc,YAAY,CAAC;AAClE,gBAAM,UAAU,KAAK;AAAA,YAAmB;AAAA;AAAA,YAAc;AAAA,YAAS,IAAI,WAAW,CAAC;AAAA,YAAG;AAAA,UAAe;AACjG,cAAI,CAAC,MAAM,OAAO,GAAG;AACjB,kBAAM,uBAAuB,WAAW,CAAC,IAAI,WAAW,CAAC,IAAI,WAAW,CAAC,KAAK;AAC9E,uBAAW,UAAU,KAAK,iBAAiB;AAEvC,kBAAI,OAAO,YAAY,qBAAqB,SAAS,OAAO,GAAG;AAC3D,uBAAO,OAAO,gBAAgB,SAAS,SAAS,mBAAmB;AAAA,cACvE;AAAA,YACJ;AAEA,kBAAM,QAAQ,IAAI,iBAAiB,SAAS,SAAS,mBAAmB;AACxE,iBAAK,gBAAgB,KAAK,KAAK;AAC/B,gBAAI,KAAK,wBAAwB,QAAQ,KAAK,wBAAwB,QAAW;AAC7E,mBAAK,oBAAoB,yBAAyB,KAAK;AAAA,YAC3D;AAAA,UACJ;AACA,iBAAO;AAAA,QACX;AAAA,MACJ;AAAA,MAwBA,MAAM,wBAAwB,YAAY;AAAA;AAAA;AAAA;AAAA,QAItC,YAAY,MAAgB,MAAgB,qBAA+B,OAAe;AACtF,gBAAM,MAAM,IAAI;AAChB,eAAK,sBAAsB;AAC3B,eAAK,QAAQ;AACb,cAAI,WAAc,OAAO;AACrB,iBAAK,QAAQ;AAAA,UACjB;AAAA,QACJ;AAAA,QACA,yBAAyB;AACrB,iBAAO,KAAK;AAAA,QAChB;AAAA,QACA,WAAW;AACP,iBAAO,KAAK;AAAA,QAChB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAUA,YAAY,YAAsB,GAAa,GAAa;AACxD,cAAI,KAAK,IAAI,IAAI,KAAK,KAAK,CAAC,KAAK,cAAc,KAAK,IAAI,IAAI,KAAK,KAAK,CAAC,KAAK,YAAY;AACpF,kBAAM,iBAAiB,KAAK,IAAI,aAAa,KAAK,mBAAmB;AACrE,mBAAO,kBAAkB,KAAO,kBAAkB,KAAK;AAAA,UAC3D;AACA,iBAAO;AAAA,QACX;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAMA,gBAAgB,GAAa,GAAa,eAAyB;AAC/D,gBAAM,gBAAgB,KAAK,QAAQ;AACnC,gBAAM,aAAa,KAAK,QAAQ,KAAK,KAAK,IAAI,KAAK;AACnD,gBAAM,aAAa,KAAK,QAAQ,KAAK,KAAK,IAAI,KAAK;AACnD,gBAAM,sBAAsB,KAAK,QAAQ,KAAK,sBAAsB,iBAAiB;AACrF,iBAAO,IAAI,gBAAgB,WAAW,WAAW,oBAAoB,aAAa;AAAA,QACtF;AAAA,MACJ;AAAA,MAuBA,MAAM,kBAAkB;AAAA,QACpB,YAAY,gBAAgB;AACxB,eAAK,aAAa,eAAe,CAAC;AAClC,eAAK,UAAU,eAAe,CAAC;AAC/B,eAAK,WAAW,eAAe,CAAC;AAAA,QACpC;AAAA,QACA,gBAAgB;AACZ,iBAAO,KAAK;AAAA,QAChB;AAAA,QACA,aAAa;AACT,iBAAO,KAAK;AAAA,QAChB;AAAA,QACA,cAAc;AACV,iBAAO,KAAK;AAAA,QAChB;AAAA,MACJ;AAAA,MA+BA,MAAM,oBAAoB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAStB,YAAY,OAAO,qBAAqB;AACpC,eAAK,QAAQ;AACb,eAAK,sBAAsB;AAC3B,eAAK,kBAAkB,CAAC;AACxB,eAAK,uBAAuB,IAAI,WAAW,CAAC;AAC5C,eAAK,sBAAsB;AAAA,QAC/B;AAAA,QACA,WAAW;AACP,iBAAO,KAAK;AAAA,QAChB;AAAA,QACA,qBAAqB;AACjB,iBAAO,KAAK;AAAA,QAChB;AAAA,QACA,KAAK,OAAO;AACR,gBAAM,YAAa,UAAU,QAAQ,UAAU,UAAc,WAAc,MAAM,IAAI,iBAAiB,UAAU;AAChH,gBAAM,cAAe,UAAU,QAAQ,UAAU,UAAc,WAAc,MAAM,IAAI,iBAAiB,YAAY;AACpH,gBAAM,QAAQ,KAAK;AACnB,gBAAM,OAAO,MAAM,UAAU;AAC7B,gBAAM,OAAO,MAAM,SAAS;AAO5B,cAAI,QAAQ,KAAK,MAAO,IAAI,QAAS,IAAI,oBAAoB,YAAY;AACzE,cAAI,QAAQ,oBAAoB,YAAY,WAAW;AACnD,oBAAQ,oBAAoB;AAAA,UAChC;AACA,cAAI,OAAO;AACX,gBAAM,aAAa,IAAI,WAAW,CAAC;AACnC,mBAAS,IAAI,QAAQ,GAAG,IAAI,QAAQ,CAAC,MAAM,KAAK,OAAO;AAEnD,uBAAW,CAAC,IAAI;AAChB,uBAAW,CAAC,IAAI;AAChB,uBAAW,CAAC,IAAI;AAChB,uBAAW,CAAC,IAAI;AAChB,uBAAW,CAAC,IAAI;AAChB,gBAAI,eAAe;AACnB,qBAAS,IAAI,GAAG,IAAI,MAAM,KAAK;AAC3B,kBAAI,MAAM,IAAI,GAAG,CAAC,GAAG;AAEjB,qBAAK,eAAe,OAAO,GAAG;AAC1B;AAAA,gBACJ;AACA,2BAAW,YAAY;AAAA,cAC3B,OACK;AACD,qBAAK,eAAe,OAAO,GAAG;AAC1B,sBAAI,iBAAiB,GAAG;AACpB,wBAAI,oBAAoB,kBAAkB,UAAU,GAAG;AACnD,4BAAM,YAAY,KAAK,qBAAqB,YAAY,GAAG,GAAG,WAAW;AACzE,0BAAI,cAAc,MAAM;AAGpB,gCAAQ;AACR,4BAAI,KAAK,eAAe,MAAM;AAC1B,iCAAO,KAAK,6BAA6B;AAAA,wBAC7C,OACK;AACD,gCAAM,UAAU,KAAK,YAAY;AACjC,8BAAI,UAAU,WAAW,CAAC,GAAG;AAQzB,iCAAK,UAAU,WAAW,CAAC,IAAI;AAC/B,gCAAI,OAAO;AAAA,0BACf;AAAA,wBACJ;AAAA,sBACJ,OACK;AACD,mCAAW,CAAC,IAAI,WAAW,CAAC;AAC5B,mCAAW,CAAC,IAAI,WAAW,CAAC;AAC5B,mCAAW,CAAC,IAAI,WAAW,CAAC;AAC5B,mCAAW,CAAC,IAAI;AAChB,mCAAW,CAAC,IAAI;AAChB,uCAAe;AACf;AAAA,sBACJ;AAEA,qCAAe;AACf,iCAAW,CAAC,IAAI;AAChB,iCAAW,CAAC,IAAI;AAChB,iCAAW,CAAC,IAAI;AAChB,iCAAW,CAAC,IAAI;AAChB,iCAAW,CAAC,IAAI;AAAA,oBACpB,OACK;AACD,iCAAW,CAAC,IAAI,WAAW,CAAC;AAC5B,iCAAW,CAAC,IAAI,WAAW,CAAC;AAC5B,iCAAW,CAAC,IAAI,WAAW,CAAC;AAC5B,iCAAW,CAAC,IAAI;AAChB,iCAAW,CAAC,IAAI;AAChB,qCAAe;AAAA,oBACnB;AAAA,kBACJ,OACK;AACD,+BAAW,EAAE,YAAY;AAAA,kBAC7B;AAAA,gBACJ,OACK;AACD,6BAAW,YAAY;AAAA,gBAC3B;AAAA,cACJ;AAAA,YACJ;AACA,gBAAI,oBAAoB,kBAAkB,UAAU,GAAG;AACnD,oBAAM,YAAY,KAAK,qBAAqB,YAAY,GAAG,MAAM,WAAW;AAC5E,kBAAI,cAAc,MAAM;AACpB,wBAAQ,WAAW,CAAC;AACpB,oBAAI,KAAK,YAAY;AAEjB,yBAAO,KAAK,6BAA6B;AAAA,gBAC7C;AAAA,cACJ;AAAA,YACJ;AAAA,UACJ;AACA,gBAAM,cAAc,KAAK,mBAAmB;AAC5C,sBAAY,kBAAkB,WAAW;AACzC,iBAAO,IAAI,kBAAkB,WAAW;AAAA,QAC5C;AAAA;AAAA;AAAA;AAAA;AAAA,QAKA,OAAO,cAAc,YAAY,KAAa;AAC1C,iBAAQ,MAAM,WAAW,CAAC,IAAI,WAAW,CAAC,IAAK,WAAW,CAAC,IAAI;AAAA,QACnE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAMA,OAAO,kBAAkB,YAAY;AACjC,cAAI,kBAAkB;AACtB,mBAAS,IAAI,GAAG,IAAI,GAAG,KAAK;AACxB,kBAAM,QAAQ,WAAW,CAAC;AAC1B,gBAAI,UAAU,GAAG;AACb,qBAAO;AAAA,YACX;AACA,+BAAmB;AAAA,UACvB;AACA,cAAI,kBAAkB,GAAG;AACrB,mBAAO;AAAA,UACX;AACA,gBAAM,aAAa,kBAAkB;AACrC,gBAAM,cAAc,aAAa;AAEjC,iBAAO,KAAK,IAAI,aAAa,WAAW,CAAC,CAAC,IAAI,eAC1C,KAAK,IAAI,aAAa,WAAW,CAAC,CAAC,IAAI,eACvC,KAAK,IAAI,IAAM,aAAa,WAAW,CAAC,CAAC,IAAI,IAAI,eACjD,KAAK,IAAI,aAAa,WAAW,CAAC,CAAC,IAAI,eACvC,KAAK,IAAI,aAAa,WAAW,CAAC,CAAC,IAAI;AAAA,QAC/C;AAAA,QACA,0BAA0B;AACtB,gBAAM,uBAAuB,KAAK;AAClC,+BAAqB,CAAC,IAAI;AAC1B,+BAAqB,CAAC,IAAI;AAC1B,+BAAqB,CAAC,IAAI;AAC1B,+BAAqB,CAAC,IAAI;AAC1B,+BAAqB,CAAC,IAAI;AAC1B,iBAAO;AAAA,QACX;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAaA,mBAAmB,QAAgB,SAAiB,UAAkB,yBAAiC;AACnG,gBAAM,aAAa,KAAK,wBAAwB;AAEhD,cAAI,IAAI;AACR,gBAAM,QAAQ,KAAK;AACnB,iBAAO,UAAU,KAAK,WAAW,KAAK,MAAM,IAAI,UAAU,GAAG,SAAS,CAAC,GAAG;AACtE,uBAAW,CAAC;AACZ;AAAA,UACJ;AACA,cAAI,SAAS,KAAK,UAAU,GAAG;AAC3B,mBAAO;AAAA,UACX;AAEA,iBAAO,UAAU,KAAK,WAAW,KAAK,CAAC,MAAM,IAAI,UAAU,GAAG,SAAS,CAAC,KACpE,WAAW,CAAC,KAAK,UAAU;AAC3B,uBAAW,CAAC;AACZ;AAAA,UACJ;AAEA,cAAI,SAAS,KAAK,UAAU,KAAK,WAAW,CAAC,IAAI,UAAU;AACvD,mBAAO;AAAA,UACX;AAEA,iBAAO,UAAU,KAAK,WAAW,KAAK,MAAM,IAAI,UAAU,GAAG,SAAS,CAAC,KACnE,WAAW,CAAC,KAAK,UAAU;AAC3B,uBAAW,CAAC;AACZ;AAAA,UACJ;AACA,cAAI,WAAW,CAAC,IAAI,UAAU;AAC1B,mBAAO;AAAA,UACX;AACA,gBAAM,OAAO,MAAM,UAAU;AAC7B,gBAAM,OAAO,MAAM,SAAS;AAE5B,cAAI;AACJ,iBAAO,SAAS,IAAI,QAAQ,UAAU,IAAI,QAAQ,MAAM,IAAI,UAAU,GAAG,SAAS,CAAC,GAAG;AAClF,uBAAW,CAAC;AACZ;AAAA,UACJ;AAEA,cAAI,SAAS,KAAK,QAAQ,UAAU,KAAK,MAAM;AAC3C,mBAAO;AAAA,UACX;AACA,iBAAO,SAAS,IAAI,QAAQ,UAAU,IAAI,QAAQ,CAAC,MAAM,IAAI,UAAU,GAAG,SAAS,CAAC,KAChF,WAAW,CAAC,IAAI,UAAU;AAC1B,uBAAW,CAAC;AACZ;AAAA,UACJ;AACA,cAAI,SAAS,KAAK,QAAQ,UAAU,KAAK,QAAQ,WAAW,CAAC,KAAK,UAAU;AACxE,mBAAO;AAAA,UACX;AACA,iBAAO,SAAS,IAAI,QAAQ,UAAU,IAAI,QAAQ,MAAM,IAAI,UAAU,GAAG,SAAS,CAAC,KAC/E,WAAW,CAAC,IAAI,UAAU;AAC1B,uBAAW,CAAC;AACZ;AAAA,UACJ;AACA,cAAI,WAAW,CAAC,KAAK,UAAU;AAC3B,mBAAO;AAAA,UACX;AAGA,gBAAM,kBAAkB,WAAW,CAAC,IAAI,WAAW,CAAC,IAAI,WAAW,CAAC,IAAI,WAAW,CAAC,IAAI,WAAW,CAAC;AACpG,iBAAO,KAAK,IAAI,kBAAkB,uBAAuB,IAAI,IAAI,2BAC7D,oBAAoB,kBAAkB,UAAU;AAAA,QACxD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAYA,mBAAmB,QAAgB,SAAiB,UAAkB,yBAAiC;AACnG,gBAAM,QAAQ,KAAK;AACnB,gBAAM,OAAO,MAAM,UAAU;AAC7B,gBAAM,aAAa,KAAK,wBAAwB;AAEhD,cAAI,IAAI;AACR,iBAAO,KAAK,KAAK,MAAM,IAAI,SAAS,CAAC,GAAG;AACpC,uBAAW,CAAC;AACZ;AAAA,UACJ;AACA,cAAI,IAAI,GAAG;AACP,mBAAO;AAAA,UACX;AACA,iBAAO,KAAK,KAAK,CAAC,MAAM,IAAI,SAAS,CAAC,KAAK,WAAW,CAAC,KAAK,UAAU;AAClE,uBAAW,CAAC;AACZ;AAAA,UACJ;AAEA,cAAI,IAAI,KAAK,WAAW,CAAC,IAAI,UAAU;AACnC,mBAAO;AAAA,UACX;AACA,iBAAO,KAAK,KAAK,MAAM,IAAI,SAAS,CAAC,KAAK,WAAW,CAAC,KAAK,UAAU;AACjE,uBAAW,CAAC;AACZ;AAAA,UACJ;AACA,cAAI,WAAW,CAAC,IAAI,UAAU;AAC1B,mBAAO;AAAA,UACX;AAEA,cAAI,SAAS;AACb,iBAAO,IAAI,QAAQ,MAAM,IAAI,SAAS,CAAC,GAAG;AACtC,uBAAW,CAAC;AACZ;AAAA,UACJ;AACA,cAAI,MAAM,MAAM;AACZ,mBAAO;AAAA,UACX;AACA,iBAAO,IAAI,QAAQ,CAAC,MAAM,IAAI,SAAS,CAAC,KAAK,WAAW,CAAC,IAAI,UAAU;AACnE,uBAAW,CAAC;AACZ;AAAA,UACJ;AACA,cAAI,MAAM,QAAQ,WAAW,CAAC,KAAK,UAAU;AACzC,mBAAO;AAAA,UACX;AACA,iBAAO,IAAI,QAAQ,MAAM,IAAI,SAAS,CAAC,KAAK,WAAW,CAAC,IAAI,UAAU;AAClE,uBAAW,CAAC;AACZ;AAAA,UACJ;AACA,cAAI,WAAW,CAAC,KAAK,UAAU;AAC3B,mBAAO;AAAA,UACX;AAGA,gBAAM,kBAAkB,WAAW,CAAC,IAAI,WAAW,CAAC,IAAI,WAAW,CAAC,IAAI,WAAW,CAAC,IAChF,WAAW,CAAC;AAChB,cAAI,IAAI,KAAK,IAAI,kBAAkB,uBAAuB,KAAK,IAAI,yBAAyB;AACxF,mBAAO;AAAA,UACX;AACA,iBAAO,oBAAoB,kBAAkB,UAAU,IAAI,oBAAoB,cAAc,YAAY,CAAC,IAAI;AAAA,QAClH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAMA,qBAAqB,QAAgB,SAAiB,UAAkB,yBAAiC;AACrG,gBAAM,QAAQ,KAAK;AACnB,gBAAM,OAAO,MAAM,SAAS;AAC5B,gBAAM,aAAa,KAAK,wBAAwB;AAChD,cAAI,IAAI;AACR,iBAAO,KAAK,KAAK,MAAM,IAAI,GAAG,OAAO,GAAG;AACpC,uBAAW,CAAC;AACZ;AAAA,UACJ;AACA,cAAI,IAAI,GAAG;AACP,mBAAO;AAAA,UACX;AACA,iBAAO,KAAK,KAAK,CAAC,MAAM,IAAI,GAAG,OAAO,KAAK,WAAW,CAAC,KAAK,UAAU;AAClE,uBAAW,CAAC;AACZ;AAAA,UACJ;AACA,cAAI,IAAI,KAAK,WAAW,CAAC,IAAI,UAAU;AACnC,mBAAO;AAAA,UACX;AACA,iBAAO,KAAK,KAAK,MAAM,IAAI,GAAG,OAAO,KAAK,WAAW,CAAC,KAAK,UAAU;AACjE,uBAAW,CAAC;AACZ;AAAA,UACJ;AACA,cAAI,WAAW,CAAC,IAAI,UAAU;AAC1B,mBAAO;AAAA,UACX;AACA,cAAI,SAAS;AACb,iBAAO,IAAI,QAAQ,MAAM,IAAI,GAAG,OAAO,GAAG;AACtC,uBAAW,CAAC;AACZ;AAAA,UACJ;AACA,cAAI,MAAM,MAAM;AACZ,mBAAO;AAAA,UACX;AACA,iBAAO,IAAI,QAAQ,CAAC,MAAM,IAAI,GAAG,OAAO,KAAK,WAAW,CAAC,IAAI,UAAU;AACnE,uBAAW,CAAC;AACZ;AAAA,UACJ;AACA,cAAI,MAAM,QAAQ,WAAW,CAAC,KAAK,UAAU;AACzC,mBAAO;AAAA,UACX;AACA,iBAAO,IAAI,QAAQ,MAAM,IAAI,GAAG,OAAO,KAAK,WAAW,CAAC,IAAI,UAAU;AAClE,uBAAW,CAAC;AACZ;AAAA,UACJ;AACA,cAAI,WAAW,CAAC,KAAK,UAAU;AAC3B,mBAAO;AAAA,UACX;AAGA,gBAAM,kBAAkB,WAAW,CAAC,IAAI,WAAW,CAAC,IAAI,WAAW,CAAC,IAAI,WAAW,CAAC,IAChF,WAAW,CAAC;AAChB,cAAI,IAAI,KAAK,IAAI,kBAAkB,uBAAuB,KAAK,yBAAyB;AACpF,mBAAO;AAAA,UACX;AACA,iBAAO,oBAAoB,kBAAkB,UAAU,IAAI,oBAAoB,cAAc,YAAY,CAAC,IAAI;AAAA,QAClH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAmBA,qBAAqB,YAAY,GAAW,GAAW,aAAa;AAChE,gBAAM,kBAAkB,WAAW,CAAC,IAAI,WAAW,CAAC,IAAI,WAAW,CAAC,IAAI,WAAW,CAAC,IAChF,WAAW,CAAC;AAChB,cAAI,UAAU,oBAAoB,cAAc,YAAY,CAAC;AAC7D,cAAI,UAAU,KAAK;AAAA,YAAmB;AAAA;AAAA,YAAc,KAAK,MAAM,OAAO;AAAA,YAAG,WAAW,CAAC;AAAA,YAAG;AAAA,UAAe;AACvG,cAAI,CAAC,MAAM,OAAO,GAAG;AAEjB,sBAAU,KAAK;AAAA;AAAA,cAAgC,KAAK,MAAM,OAAO;AAAA;AAAA,cAAc,KAAK,MAAM,OAAO;AAAA,cAAG,WAAW,CAAC;AAAA,cAAG;AAAA,YAAe;AAClI,gBAAI,CAAC,MAAM,OAAO,MACb,CAAC,eAAe,KAAK;AAAA;AAAA,cAA8B,KAAK,MAAM,OAAO;AAAA;AAAA,cAAc,KAAK,MAAM,OAAO;AAAA,cAAG,WAAW,CAAC;AAAA,cAAG;AAAA,YAAe,IAAI;AAC3I,oBAAM,sBAAsB,kBAAkB;AAC9C,kBAAI,QAAQ;AACZ,oBAAM,kBAAkB,KAAK;AAC7B,uBAAS,QAAQ,GAAG,SAAS,gBAAgB,QAAQ,QAAQ,QAAQ,SAAS;AAC1E,sBAAM,SAAS,gBAAgB,KAAK;AAEpC,oBAAI,OAAO,YAAY,qBAAqB,SAAS,OAAO,GAAG;AAC3D,kCAAgB,KAAK,IAAI,OAAO,gBAAgB,SAAS,SAAS,mBAAmB;AACrF,0BAAQ;AACR;AAAA,gBACJ;AAAA,cACJ;AACA,kBAAI,CAAC,OAAO;AACR,sBAAM,QAAQ,IAAI,gBAAgB,SAAS,SAAS,mBAAmB;AACvE,gCAAgB,KAAK,KAAK;AAC1B,oBAAI,KAAK,wBAAwB,QAAQ,KAAK,wBAAwB,QAAW;AAC7E,uBAAK,oBAAoB,yBAAyB,KAAK;AAAA,gBAC3D;AAAA,cACJ;AACA,qBAAO;AAAA,YACX;AAAA,UACJ;AACA,iBAAO;AAAA,QACX;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAOA,cAAc;AACV,gBAAM,MAAM,KAAK,gBAAgB;AACjC,cAAI,OAAO,GAAG;AACV,mBAAO;AAAA,UACX;AACA,cAAI,uBAAuB;AAC3B,qBAAW,UAAU,KAAK,iBAAiB;AACvC,gBAAI,OAAO,SAAS,KAAK,oBAAoB,eAAe;AACxD,kBAAI,wBAAwB,MAAM;AAC9B,uCAAuB;AAAA,cAC3B,OACK;AAMD,qBAAK,aAAa;AAClB;AAAA;AAAA,kBAAkB,KAAK,OAAO,KAAK,IAAI,qBAAqB,KAAK,IAAI,OAAO,KAAK,CAAC,IAC9E,KAAK,IAAI,qBAAqB,KAAK,IAAI,OAAO,KAAK,CAAC,KAAK,CAAC;AAAA;AAAA,cAClE;AAAA,YACJ;AAAA,UACJ;AACA,iBAAO;AAAA,QACX;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAMA,+BAA+B;AAC3B,cAAI,iBAAiB;AACrB,cAAI,kBAAkB;AACtB,gBAAM,MAAM,KAAK,gBAAgB;AACjC,qBAAW,WAAW,KAAK,iBAAiB;AACxC,gBAAI,QAAQ,SAAS,KAAK,oBAAoB,eAAe;AACzD;AACA,iCAAmB,QAAQ,uBAAuB;AAAA,YACtD;AAAA,UACJ;AACA,cAAI,iBAAiB,GAAG;AACpB,mBAAO;AAAA,UACX;AAKA,gBAAM,UAAU,kBAAkB;AAClC,cAAI,iBAAiB;AACrB,qBAAW,WAAW,KAAK,iBAAiB;AACxC,8BAAkB,KAAK,IAAI,QAAQ,uBAAuB,IAAI,OAAO;AAAA,UACzE;AACA,iBAAO,kBAAkB,OAAO;AAAA,QACpC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAOA,qBAAqB;AACjB,gBAAM,YAAY,KAAK,gBAAgB;AACvC,cAAI,YAAY,GAAG;AAEf,kBAAM,IAAI,kBAAkB;AAAA,UAChC;AACA,gBAAM,kBAAkB,KAAK;AAC7B,cAAI;AAEJ,cAAI,YAAY,GAAG;AAEf,gBAAI,kBAAkB;AACtB,gBAAI,SAAS;AACb,uBAAW,UAAU,KAAK,iBAAiB;AACvC,oBAAM,OAAO,OAAO,uBAAuB;AAC3C,iCAAmB;AACnB,wBAAU,OAAO;AAAA,YACrB;AACA,sBAAU,kBAAkB;AAC5B,gBAAI,SAAS,KAAK,KAAK,SAAS,YAAY,UAAU,OAAO;AAC7D,4BAAgB;AAAA;AAAA;AAAA;AAAA;AAAA,cAKhB,CAAC,SAAS,YAAY;AAClB,sBAAM,KAAK,KAAK,IAAI,QAAQ,uBAAuB,IAAI,OAAO;AAC9D,sBAAM,KAAK,KAAK,IAAI,QAAQ,uBAAuB,IAAI,OAAO;AAC9D,uBAAO,KAAK,KAAK,KAAK,KAAK,KAAK,IAAI;AAAA,cACxC;AAAA,YAAC;AACD,kBAAM,QAAQ,KAAK,IAAI,MAAM,SAAS,MAAM;AAC5C,qBAAS,IAAI,GAAG,IAAI,gBAAgB,UAAU,gBAAgB,SAAS,GAAG,KAAK;AAC3E,oBAAM,UAAU,gBAAgB,CAAC;AACjC,kBAAI,KAAK,IAAI,QAAQ,uBAAuB,IAAI,OAAO,IAAI,OAAO;AAC9D,gCAAgB,OAAO,GAAG,CAAC;AAC3B;AAAA,cACJ;AAAA,YACJ;AAAA,UACJ;AACA,cAAI,gBAAgB,SAAS,GAAG;AAE5B,gBAAI,kBAAkB;AACtB,uBAAW,kBAAkB,iBAAiB;AAC1C,iCAAmB,eAAe,uBAAuB;AAAA,YAC7D;AACA,sBAAU,kBAAkB,gBAAgB;AAC5C,4BAAgB;AAAA;AAAA;AAAA;AAAA;AAAA,cAKhB,CAAC,SAAS,YAAY;AAClB,oBAAI,QAAQ,SAAS,MAAM,QAAQ,SAAS,GAAG;AAC3C,wBAAM,KAAK,KAAK,IAAI,QAAQ,uBAAuB,IAAI,OAAO;AAC9D,wBAAM,KAAK,KAAK,IAAI,QAAQ,uBAAuB,IAAI,OAAO;AAC9D,yBAAO,KAAK,KAAK,IAAI,KAAK,KAAK,KAAK;AAAA,gBACxC,OACK;AACD,yBAAO,QAAQ,SAAS,IAAI,QAAQ,SAAS;AAAA,gBACjD;AAAA,cACJ;AAAA,YAAC;AACD,4BAAgB,OAAO,CAAC;AAAA,UAC5B;AACA,iBAAO;AAAA,YACH,gBAAgB,CAAC;AAAA,YACjB,gBAAgB,CAAC;AAAA,YACjB,gBAAgB,CAAC;AAAA,UACrB;AAAA,QACJ;AAAA,MACJ;AACA,0BAAoB,gBAAgB;AACpC,0BAAoB,WAAW;AAC/B,0BAAoB,cAAc;AAAA,MAwBlC,MAAM,WAAW;AAAA,QACb,YAAY,OAAO;AACf,eAAK,QAAQ;AAAA,QACjB;AAAA,QACA,WAAW;AACP,iBAAO,KAAK;AAAA,QAChB;AAAA,QACA,yBAAyB;AACrB,iBAAO,KAAK;AAAA,QAChB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAmBA,OAAO,OAAO;AACV,eAAK,sBAAuB,UAAU,QAAQ,UAAU,SAAa;AAAA;AAAA,YACtC,MAAM,IAAI,iBAAiB,0BAA0B;AAAA;AACpF,gBAAM,SAAS,IAAI,oBAAoB,KAAK,OAAO,KAAK,mBAAmB;AAC3E,gBAAM,OAAO,OAAO,KAAK,KAAK;AAC9B,iBAAO,KAAK,yBAAyB,IAAI;AAAA,QAC7C;AAAA,QACA,yBAAyB,MAAM;AAC3B,gBAAM,UAAU,KAAK,WAAW;AAChC,gBAAM,WAAW,KAAK,YAAY;AAClC,gBAAM,aAAa,KAAK,cAAc;AACtC,gBAAM,aAAa,KAAK,oBAAoB,SAAS,UAAU,UAAU;AACzE,cAAI,aAAa,GAAK;AAClB,kBAAM,IAAI,kBAAkB,sCAAsC;AAAA,UACtE;AACA,gBAAM,YAAY,WAAW,iBAAiB,SAAS,UAAU,YAAY,UAAU;AACvF,gBAAM,qBAAqB,UAAU,kCAAkC,SAAS;AAChF,gBAAM,0BAA0B,mBAAmB,uBAAuB,IAAI;AAC9E,cAAI,mBAAmB;AAEvB,cAAI,mBAAmB,2BAA2B,EAAE,SAAS,GAAG;AAE5D,kBAAM,eAAe,SAAS,KAAK,IAAI,QAAQ,KAAK,IAAI,WAAW,KAAK;AACxE,kBAAM,eAAe,SAAS,KAAK,IAAI,QAAQ,KAAK,IAAI,WAAW,KAAK;AAGxE,kBAAM,sBAAsB,IAAM,IAAM;AACxC,kBAAM;AAAA;AAAA,cAA2B,KAAK,MAAM,QAAQ,KAAK,IAAI,uBAAuB,eAAe,QAAQ,KAAK,EAAE;AAAA;AAClH,kBAAM;AAAA;AAAA,cAA2B,KAAK,MAAM,QAAQ,KAAK,IAAI,uBAAuB,eAAe,QAAQ,KAAK,EAAE;AAAA;AAElH,qBAAS,IAAI,GAAG,KAAK,IAAI,MAAM,GAAG;AAC9B,kBAAI;AACA,mCAAmB,KAAK,sBAAsB,YAAY,eAAe,eAAe,CAAC;AACzF;AAAA,cACJ,SACO,IAA0B;AAC7B,oBAAI,EAAE,cAAc,oBAAoB;AACpC,wBAAM;AAAA,gBACV;AAAA,cAEJ;AAAA,YACJ;AAAA,UAEJ;AACA,gBAAM,YAAY,WAAW,gBAAgB,SAAS,UAAU,YAAY,kBAAkB,SAAS;AACvG,gBAAM,OAAO,WAAW,WAAW,KAAK,OAAO,WAAW,SAAS;AACnE,cAAI;AACJ,cAAI,qBAAqB,MAAM;AAC3B,qBAAS,CAAC,YAAY,SAAS,QAAQ;AAAA,UAC3C,OACK;AACD,qBAAS,CAAC,YAAY,SAAS,UAAU,gBAAgB;AAAA,UAC7D;AACA,iBAAO,IAAI,eAAe,MAAM,MAAM;AAAA,QAC1C;AAAA,QACA,OAAO,gBAAgB,SAAS,UAAU,YAAY,kBAAkB,WAAmB;AACvF,gBAAM,gBAAgB,YAAY;AAClC,cAAI;AACJ,cAAI;AACJ,cAAI;AACJ,cAAI;AACJ,cAAI,qBAAqB,MAAM;AAC3B,2BAAe,iBAAiB,KAAK;AACrC,2BAAe,iBAAiB,KAAK;AACrC,iCAAqB,gBAAgB;AACrC,iCAAqB;AAAA,UACzB,OACK;AAED,2BAAgB,SAAS,KAAK,IAAI,QAAQ,KAAK,IAAK,WAAW,KAAK;AACpE,2BAAgB,SAAS,KAAK,IAAI,QAAQ,KAAK,IAAK,WAAW,KAAK;AACpE,iCAAqB;AACrB,iCAAqB;AAAA,UACzB;AACA,iBAAO,qBAAqB,6BAA6B,KAAK,KAAK,eAAe,KAAK,oBAAoB,oBAAoB,KAAK,eAAe,QAAQ,KAAK,GAAG,QAAQ,KAAK,GAAG,SAAS,KAAK,GAAG,SAAS,KAAK,GAAG,cAAc,cAAc,WAAW,KAAK,GAAG,WAAW,KAAK,CAAC;AAAA,QACzR;AAAA,QACA,OAAO,WAAW,OAAO,WAAW,WAAmB;AACnD,gBAAM,UAAU,oBAAoB,YAAY;AAChD,iBAAO,QAAQ,wBAAwB,OAAO,WAAW,WAAW,SAAS;AAAA,QACjF;AAAA;AAAA;AAAA;AAAA;AAAA,QAKA,OAAO,iBAAiB,SAAS,UAAU,YAAY,YAAsB;AACzE,gBAAM,uBAAuB,UAAU,MAAM,YAAY,SAAS,SAAS,QAAQ,IAAI,UAAU;AACjG,gBAAM,uBAAuB,UAAU,MAAM,YAAY,SAAS,SAAS,UAAU,IAAI,UAAU;AACnG,cAAI,YAAY,KAAK,OAAO,uBAAuB,wBAAwB,CAAC,IAAI;AAChF,kBAAQ,YAAY,GAAM;AAAA;AAAA,YACtB,KAAK;AACD;AACA;AAAA;AAAA,YAEJ,KAAK;AACD;AACA;AAAA,YACJ,KAAK;AACD,oBAAM,IAAI,kBAAkB,gCAAgC;AAAA,UACpE;AACA,iBAAO;AAAA,QACX;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAUA,oBAAoB,SAAS,UAAU,YAAY;AAE/C,kBAAQ,KAAK,0BAA0B,SAAS,QAAQ,IACpD,KAAK,0BAA0B,SAAS,UAAU,KAAK;AAAA,QAC/D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAMA,0BAA0B,SAAS,cAAc;AAC7C,gBAAM,iBAAiB,KAAK;AAAA;AAAA,YAA4C,KAAK,MAAM,QAAQ,KAAK,CAAC;AAAA;AAAA,YACtF,KAAK,MAAM,QAAQ,KAAK,CAAC;AAAA;AAAA,YACzB,KAAK,MAAM,aAAa,KAAK,CAAC;AAAA;AAAA,YAC9B,KAAK,MAAM,aAAa,KAAK,CAAC;AAAA,UAAC;AAC1C,gBAAM,iBAAiB,KAAK;AAAA;AAAA,YAA4C,KAAK,MAAM,aAAa,KAAK,CAAC;AAAA;AAAA,YAC3F,KAAK,MAAM,aAAa,KAAK,CAAC;AAAA;AAAA,YAC9B,KAAK,MAAM,QAAQ,KAAK,CAAC;AAAA;AAAA,YACzB,KAAK,MAAM,QAAQ,KAAK,CAAC;AAAA,UAAC;AACrC,cAAI,MAAM,cAAc,GAAG;AACvB,mBAAO,iBAAiB;AAAA,UAC5B;AACA,cAAI,MAAM,cAAc,GAAG;AACvB,mBAAO,iBAAiB;AAAA,UAC5B;AAGA,kBAAQ,iBAAiB,kBAAkB;AAAA,QAC/C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAMA,iCAAiC,OAAe,OAAe,KAAa,KAAa;AACrF,cAAI,SAAS,KAAK,yBAAyB,OAAO,OAAO,KAAK,GAAG;AAEjE,cAAI,QAAQ;AACZ,cAAI,WAAW,SAAS,MAAM;AAC9B,cAAI,WAAW,GAAG;AACd,oBAAQ;AAAA,aAAsB,QAAQ;AACtC,uBAAW;AAAA,UACf,WACS,YAAY,KAAK,MAAM,SAAS,GAAG;AACxC,qBAAS,KAAK,MAAM,SAAS,IAAI,IAAI;AAAA,aAAuB,WAAW;AACvE,uBAAW,KAAK,MAAM,SAAS,IAAI;AAAA,UACvC;AACA,cAAI;AAAA;AAAA,YAAsB,KAAK,MAAM,SAAS,MAAM,SAAS,KAAK;AAAA;AAClE,kBAAQ;AACR,cAAI,WAAW,GAAG;AACd,oBAAQ;AAAA,aAAsB,QAAQ;AACtC,uBAAW;AAAA,UACf,WACS,YAAY,KAAK,MAAM,UAAU,GAAG;AACzC,qBAAS,KAAK,MAAM,UAAU,IAAI,IAAI;AAAA,aAAuB,WAAW;AACxE,uBAAW,KAAK,MAAM,UAAU,IAAI;AAAA,UACxC;AACA;AAAA,UAAsB,KAAK,MAAM,SAAS,WAAW,SAAS,KAAK;AACnE,oBAAU,KAAK,yBAAyB,OAAO,OAAO,UAAU,QAAQ;AAExE,iBAAO,SAAS;AAAA,QACpB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QASA,yBAAyB,OAAe,OAAe,KAAa,KAAa;AAG7E,gBAAM,QAAQ,KAAK,IAAI,MAAM,KAAK,IAAI,KAAK,IAAI,MAAM,KAAK;AAC1D,cAAI,OAAO;AACP,gBAAI,OAAO;AACX,oBAAQ;AACR,oBAAQ;AACR,mBAAO;AACP,kBAAM;AACN,kBAAM;AAAA,UACV;AACA,gBAAM,KAAK,KAAK,IAAI,MAAM,KAAK;AAC/B,gBAAM,KAAK,KAAK,IAAI,MAAM,KAAK;AAC/B,cAAI,QAAQ,CAAC,KAAK;AAClB,gBAAM,QAAQ,QAAQ,MAAM,IAAI;AAChC,gBAAM,QAAQ,QAAQ,MAAM,IAAI;AAEhC,cAAI,QAAQ;AAEZ,gBAAM,SAAS,MAAM;AACrB,mBAAS,IAAI,OAAO,IAAI,OAAO,MAAM,QAAQ,KAAK,OAAO;AACrD,kBAAM,QAAQ,QAAQ,IAAI;AAC1B,kBAAM,QAAQ,QAAQ,IAAI;AAI1B,gBAAK,UAAU,MAAO,KAAK,MAAM,IAAI,OAAO,KAAK,GAAG;AAChD,kBAAI,UAAU,GAAG;AACb,uBAAO,UAAU,SAAS,GAAG,GAAG,OAAO,KAAK;AAAA,cAChD;AACA;AAAA,YACJ;AACA,qBAAS;AACT,gBAAI,QAAQ,GAAG;AACX,kBAAI,MAAM,KAAK;AACX;AAAA,cACJ;AACA,mBAAK;AACL,uBAAS;AAAA,YACb;AAAA,UACJ;AAIA,cAAI,UAAU,GAAG;AACb,mBAAO,UAAU,SAAS,MAAM,OAAO,KAAK,OAAO,KAAK;AAAA,UAC5D;AAEA,iBAAO;AAAA,QACX;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAYA,sBAAsB,sBAAgC,eAAuB,eAAuB,iBAA2B;AAG3H,gBAAM;AAAA;AAAA,YAAuB,KAAK,MAAM,kBAAkB,oBAAoB;AAAA;AAC9E,gBAAM,qBAAqB,KAAK,IAAI,GAAG,gBAAgB,SAAS;AAChE,gBAAM,sBAAsB,KAAK,IAAI,KAAK,MAAM,SAAS,IAAI,GAAG,gBAAgB,SAAS;AACzF,cAAI,sBAAsB,qBAAqB,uBAAuB,GAAG;AACrE,kBAAM,IAAI,kBAAkB,8CAA8C;AAAA,UAC9E;AACA,gBAAM,oBAAoB,KAAK,IAAI,GAAG,gBAAgB,SAAS;AAC/D,gBAAM,uBAAuB,KAAK,IAAI,KAAK,MAAM,UAAU,IAAI,GAAG,gBAAgB,SAAS;AAC3F,cAAI,uBAAuB,oBAAoB,uBAAuB,GAAG;AACrE,kBAAM,IAAI,kBAAkB,iDAAiD;AAAA,UACjF;AACA,gBAAM,kBAAkB,IAAI,uBAAuB,KAAK,OAAO,oBAAoB,mBAAmB,sBAAsB,oBAAoB,uBAAuB,mBAAmB,sBAAsB,KAAK,mBAAmB;AACxO,iBAAO,gBAAgB,KAAK;AAAA,QAChC;AAAA,MACJ;AAAA,MAwBA,MAAM,aAAa;AAAA,QACf,cAAc;AACV,eAAK,UAAU,IAAI,UAAU;AAAA,QACjC;AAAA,QACA,aAAa;AACT,iBAAO,KAAK;AAAA,QAChB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAcA,OAAO,OAAO,OAAO;AACjB,cAAI;AACJ,cAAI;AACJ,cAAI,UAAU,UAAa,UAAU,QAAQ,WAAc,MAAM,IAAI,iBAAiB,YAAY,GAAG;AACjG,kBAAM,OAAO,aAAa,gBAAgB,MAAM,eAAe,CAAC;AAChE,4BAAgB,KAAK,QAAQ,gBAAgB,MAAM,KAAK;AACxD,qBAAS,aAAa;AAAA,UAC1B,OACK;AACD,kBAAM,iBAAiB,IAAI,WAAW,MAAM,eAAe,CAAC,EAAE,OAAO,KAAK;AAC1E,4BAAgB,KAAK,QAAQ,gBAAgB,eAAe,QAAQ,GAAG,KAAK;AAC5E,qBAAS,eAAe,UAAU;AAAA,UACtC;AAEA,cAAI,cAAc,SAAS,aAAa,uBAAuB;AAC3D,0BAAc,SAAS,EAAE,wBAAwB,MAAM;AAAA,UAC3D;AACA,gBAAM,SAAS,IAAI,OAAO,cAAc,QAAQ,GAAG,cAAc,YAAY,GAAG,QAAW,QAAQ,gBAAgB,SAAS,MAAS;AACrI,gBAAM,eAAe,cAAc,gBAAgB;AACnD,cAAI,iBAAiB,MAAM;AACvB,mBAAO,YAAY,qBAAqB,eAAe,YAAY;AAAA,UACvE;AACA,gBAAM,UAAU,cAAc,WAAW;AACzC,cAAI,YAAY,MAAM;AAClB,mBAAO,YAAY,qBAAqB,wBAAwB,OAAO;AAAA,UAC3E;AACA,cAAI,cAAc,oBAAoB,GAAG;AACrC,mBAAO,YAAY,qBAAqB,4BAA4B,cAAc,kCAAkC,CAAC;AACrH,mBAAO,YAAY,qBAAqB,0BAA0B,cAAc,0BAA0B,CAAC;AAAA,UAC/G;AACA,iBAAO;AAAA,QACX;AAAA;AAAA,QAEA,QAAQ;AAAA,QAER;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QASA,OAAO,gBAAgB,OAAO;AAC1B,gBAAM,eAAe,MAAM,gBAAgB;AAC3C,gBAAM,mBAAmB,MAAM,oBAAoB;AACnD,cAAI,iBAAiB,QAAQ,qBAAqB,MAAM;AACpD,kBAAM,IAAI,kBAAkB;AAAA,UAChC;AACA,gBAAM,aAAa,KAAK,WAAW,cAAc,KAAK;AACtD,cAAI,MAAM,aAAa,CAAC;AACxB,cAAI,SAAS,iBAAiB,CAAC;AAC/B,cAAI,OAAO,aAAa,CAAC;AACzB,cAAI,QAAQ,iBAAiB,CAAC;AAE9B,cAAI,QAAQ,SAAS,OAAO,QAAQ;AAChC,kBAAM,IAAI,kBAAkB;AAAA,UAChC;AACA,cAAI,SAAS,QAAQ,QAAQ,MAAM;AAG/B,oBAAQ,QAAQ,SAAS;AACzB,gBAAI,SAAS,MAAM,SAAS,GAAG;AAE3B,oBAAM,IAAI,kBAAkB;AAAA,YAChC;AAAA,UACJ;AACA,gBAAM,cAAc,KAAK,OAAO,QAAQ,OAAO,KAAK,UAAU;AAC9D,gBAAM,eAAe,KAAK,OAAO,SAAS,MAAM,KAAK,UAAU;AAC/D,cAAI,eAAe,KAAK,gBAAgB,GAAG;AACvC,kBAAM,IAAI,kBAAkB;AAAA,UAChC;AACA,cAAI,iBAAiB,aAAa;AAE9B,kBAAM,IAAI,kBAAkB;AAAA,UAChC;AAIA,gBAAM;AAAA;AAAA,YAAmB,KAAK,MAAM,aAAa,CAAG;AAAA;AACpD,iBAAO;AACP,kBAAQ;AAIR,gBAAM,oBAAoB;AAAA,UAAkB,KAAK,OAAO,cAAc,KAAK,UAAU,IAAI;AACzF,cAAI,oBAAoB,GAAG;AACvB,gBAAI,oBAAoB,OAAO;AAE3B,oBAAM,IAAI,kBAAkB;AAAA,YAChC;AACA,oBAAQ;AAAA,UACZ;AAEA,gBAAM,mBAAmB;AAAA,UAAiB,KAAK,OAAO,eAAe,KAAK,UAAU,IAAI;AACxF,cAAI,mBAAmB,GAAG;AACtB,gBAAI,mBAAmB,OAAO;AAE1B,oBAAM,IAAI,kBAAkB;AAAA,YAChC;AACA,mBAAO;AAAA,UACX;AAEA,gBAAM,OAAO,IAAI,UAAU,aAAa,YAAY;AACpD,mBAAS,IAAI,GAAG,IAAI,cAAc,KAAK;AACnC,kBAAM,UAAU;AAAA,YAAiB,KAAK,MAAM,IAAI,UAAU;AAC1D,qBAAS,IAAI,GAAG,IAAI,aAAa,KAAK;AAClC,kBAAI,MAAM,IAAI;AAAA,cAAkB,KAAK,MAAM,IAAI,UAAU,GAAG,OAAO,GAAG;AAClE,qBAAK,IAAI,GAAG,CAAC;AAAA,cACjB;AAAA,YACJ;AAAA,UACJ;AACA,iBAAO;AAAA,QACX;AAAA,QACA,OAAO,WAAW,cAAc,OAAO;AACnC,gBAAM,SAAS,MAAM,UAAU;AAC/B,gBAAM,QAAQ,MAAM,SAAS;AAC7B,cAAI,IAAI,aAAa,CAAC;AACtB,cAAI,IAAI,aAAa,CAAC;AACtB,cAAI,UAAU;AACd,cAAI,cAAc;AAClB,iBAAO,IAAI,SAAS,IAAI,QAAQ;AAC5B,gBAAI,YAAY,MAAM,IAAI,GAAG,CAAC,GAAG;AAC7B,kBAAI,EAAE,gBAAgB,GAAG;AACrB;AAAA,cACJ;AACA,wBAAU,CAAC;AAAA,YACf;AACA;AACA;AAAA,UACJ;AACA,cAAI,MAAM,SAAS,MAAM,QAAQ;AAC7B,kBAAM,IAAI,kBAAkB;AAAA,UAChC;AACA,kBAAQ,IAAI,aAAa,CAAC,KAAK;AAAA,QACnC;AAAA,MACJ;AACA,mBAAa,YAAY,IAAI,MAAM;AAAA,MAqBlB,MAAM,aAAa;AAAA,QAChC,eAAe;AAAA,QACf;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAOA,OAAO,eAAe,gBAAgB;AAClC,iBAAO,UAAU,IAAI,cAAc;AAAA,QACvC;AAAA,QACA,OAAO,WAAW,MAAM;AACpB,cAAI,QAAQ,QAAQ,CAAC,KAAK,QAAQ;AAC9B,mBAAO,aAAa;AAAA,UACxB;AACA,gBAAM,SAAS,IAAI,WAAW,KAAK,MAAM;AACzC,cAAI,IAAI;AACR,qBAAW,WAAW,MAAM;AACxB,mBAAO,GAAG,IAAI;AAAA,UAClB;AACA,iBAAO;AAAA,QACX;AAAA;AAAA;AAAA;AAAA;AAAA,QAKA,OAAO,YAAY,QAAgB;AAC/B,gBAAM,IAAI,OAAO,aAAa,aAAa,cAAc,SAAS,MAAO;AACzE,cAAI,IAAI,GAAG;AACP,mBAAO;AAAA,UACX;AACA,kBAAQ,aAAa,eAAe,CAAC,IAAI,KAAK,aAAa;AAAA,QAC/D;AAAA,MACJ;AACA,mBAAa,sBAAsB;AAEnC,mBAAa,2BAA2B,aAAa,sBAAsB;AAC3E,mBAAa,sBAAsB;AACnC,mBAAa,sBAAsB;AAGnC,mBAAa,sBAAsB;AACnC,mBAAa,0BAA0B;AACvC,mBAAa,iBAAiB;AAC9B,mBAAa,kBAAkB,IAAI,WAAW,CAAC,CAAC;AAMhD,mBAAa,eAAe,WAAW,KAAK;AAAA,QACxC;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QAAS;AAAA,QACnG;AAAA,QAAS;AAAA,QAAS;AAAA,MACtB,CAAC;AAID,mBAAa,iBAAiB,WAAW,KAAK;AAAA,QAC1C;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAC3G;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAC5G;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QACvG;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAC5G;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAC5G;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAC7G;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAC1G;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QACzG;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QACvG;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAC5G;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAC3G;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QACzG;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QACzG;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QACzG;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAC1G;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QACzG;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QACzG;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAC1G;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAC5G;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAC5G;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QACxG;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAC1G;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QACzG;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAC1G;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAC3G;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QACvG;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAC1G;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAC3G;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAC7G;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QACzG;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QACzG;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QACxG;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAC5G;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAC5G;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAC5G;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QACzG;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QACzG;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QACxG;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAI;AAAA,QAAI;AAAA,QAAM;AAAA,QAAI;AAAA,QAAM;AAAA,QAC5G;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAI;AAAA,QAAI;AAAA,QAAI;AAAA,QAAM;AAAA,QAAI;AAAA,QAAM;AAAA,QAAI;AAAA,QAAM;AAAA,QAAI;AAAA,QAAI;AAAA,QAAI;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QACxG;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAI;AAAA,QAAI;AAAA,QAAM;AAAA,QAAI;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAI;AAAA,QAAM;AAAA,QAAI;AAAA,QAAM;AAAA,QAAI;AAAA,QAAM;AAAA,QAAM;AAAA,QAAI;AAAA,QAC1G;AAAA,QAAM;AAAA,QAAI;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAI;AAAA,QAAM;AAAA,QAAI;AAAA,QAAM;AAAA,QAAI;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAI;AAAA,QAAI;AAAA,QAAM;AAAA,QAC5G;AAAA,QAAM;AAAA,QAAM;AAAA,QAAI;AAAA,QAAM;AAAA,QAAI;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAI;AAAA,QAAM;AAAA,QAAI;AAAA,QAAM;AAAA,QAAI;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAI;AAAA,QAAI;AAAA,QAAK;AAAA,QAC3G;AAAA,QAAK;AAAA,QAAK;AAAA,QAAI;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QACxG;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAC1G;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QACzG;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAC3G;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QACzG;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAC1G;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAC3G;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAC5G;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAC7G;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAC5G;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAC5G;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAC1G;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QACxG;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAC5G;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QACxG;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAC5G;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAC5G;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAC5G;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QACxG;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAC7G;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAC3G;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QACzG;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAC3G;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAC1G;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAC3G;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QACxG;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAC3G;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QACzG;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QACzG;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAC5G;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAC3G;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QACxG;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QACxG;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAC5G;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAC7G;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QACxG;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAC1G;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAC5G;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAI;AAAA,QAAI;AAAA,QAAM;AAAA,QAAI;AAAA,QAAM;AAAA,QAAI;AAAA,QAAM;AAAA,QAAI;AAAA,QAAI;AAAA,QAAI;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QACzG;AAAA,QAAM;AAAA,QAAI;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAI;AAAA,QAAI;AAAA,QAAM;AAAA,QAAI;AAAA,QAAM;AAAA,QAAI;AAAA,QAAM;AAAA,QAAM;AAAA,QAAI;AAAA,QAAI;AAAA,QAAI;AAAA,QAAM;AAAA,QAAI;AAAA,QAC5G;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAI;AAAA,QAAM;AAAA,QAAI;AAAA,QAAM;AAAA,QAAI;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAI;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAI;AAAA,QAC9G;AAAA,QAAM;AAAA,QAAG;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAI;AAAA,QAAM;AAAA,QAAI;AAAA,QAAM;AAAA,QAAI;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAI;AAAA,QAAK;AAAA,QAAI;AAAA,QAAI;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAC7G;AAAA,QAAI;AAAA,QAAK;AAAA,QAAI;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QACzG;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAC5G;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAC1G;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QACvG;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QACvG;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAC5G;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QACvG;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QACvG;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAC3G;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAC1G;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAC5G;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAC3G;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAC5G;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAC1G;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAC1G;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAC1G;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QACxG;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAC5G;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QACzG;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAC5G;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAC5G;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAI;AAAA,QAAI;AAAA,QAAI;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAI;AAAA,QAC5G;AAAA,QAAI;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAI;AAAA,QAAI;AAAA,QAAI;AAAA,QAAM;AAAA,QAAI;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAI;AAAA,QAAM;AAAA,QAAI;AAAA,QAC1G;AAAA,QAAI;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAI;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAG;AAAA,QAAM;AAAA,QAAG;AAAA,QAAM;AAAA,QAAG;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QACzG;AAAA,QAAK;AAAA,QAAK;AAAA,QAAI;AAAA,QAAI;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAI;AAAA,QAAK;AAAA,QAAI;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAC3G;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAC5G;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAC1G;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAC7G;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QACzG;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QACzG;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAC1G;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAC5G;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAC1G;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAC3G;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QACzG;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QACxG;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QACzG;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QACzG;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAI;AAAA,QAAM;AAAA,QAAI;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QACvG;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAAI;AAAA,QAAK;AAAA,QAAI;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAI;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QACzG;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAG;AAAA,QAAG;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAI;AAAA,QAAK;AAAA,QAAI;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QACxG;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAC3G;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QACzG;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAC1G;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QACxG;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAC5G;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAC3G;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAC1G;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAAI;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAK;AAAA,QAAG;AAAA,QAAK;AAAA,QAAG;AAAA,QAC1G;AAAA,QAAK;AAAA,QAAK;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;AAAA,QAAM;A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", "names": ["module", "encode", "toString", "require_utils", "QRCode", "global", "exports", "isNullOrUndefined", "__extends", "CustomError", "BinaryBitmap", "DecodeHintType", "CharacterSetValueIdentifiers", "localLuminances", "HybridBinarizer", "HTMLCanvasElementLuminanceSource", "__awaiter", "err", "BarcodeFormat", "ResultMetadataType", "Table", "cx", "cy", "resultPoint", "numeric", "value", "Mode", "ErrorCorrectionLevelValues", "DataMaskValues", "ModeValues", "column", "MultiFormatReader", "EncodeHintType", "QRCode", "SHIFT_TABLE", "CHAR_MAP", "add", "global", "undefined", "encode", "i", "value", "dataView", "decode", "toByteArray", "fromByteArray", "len", "i", "len2", "Html5QrcodeSupportedFormats", "DecodedTextType", "Html5QrcodeScanType", "Html5QrcodeConstants", "QrcodeResultFormat", "Html5QrcodeResultFactory", "Html5QrcodeErrorTypes", "Html5QrcodeErrorFactory", "BaseLoggger", "Html5QrcodeStrings", "Html5QrcodeScannerStrings", "LibraryInfoStrings", "VideoConstraintsUtil", "ZXingHtml5QrcodeDecoder", "BarcodeDetectorDelegate", "Html5QrcodeShim", "AbstractCameraCapability", "AbstractRangeCameraCapability", "ZoomFeatureImpl", "TorchFeatureImpl", "CameraCapabilitiesImpl", "RenderedCameraImpl", "CameraImpl", "CameraFactory", "CameraRetriever", "_i", "Html5QrcodeScannerState", "StateManagerImpl", "StateManagerProxy", "StateManagerFactory", "__extends", "Constants", "InternalHtml5QrcodeConfig", "Html5Qrcode", "PersistedDataFactory", "PersistedDataManager", "LibraryInfoDiv", "LibraryInfoIcon", "LibraryInfoContainer", "CameraPermissions", "ScanTypeSelector", "PublicUiElementIdAndClasses", "BaseUiElementFactory", "TorchController", "TorchButton", "__awaiter", "FileSelectionUi", "CameraSelectionUi", "CameraZoomUi", "Html5QrcodeScannerStatus", "Html5QrcodeScanner", "cameraId", "_", "rank", "cbor", "compressed", "payload"] } diff --git a/doc/API.md b/doc/API.md index a60dfec..e6694ca 100644 --- a/doc/API.md +++ b/doc/API.md @@ -1,1207 +1,41 @@ -# SecureBit.chat API Documentation +# API Notes -## 🏗️ Architecture Overview +## EnhancedSecureWebRTCManager -SecureBit.chat is built as a client-side application with no backend servers. The "API" consists of JavaScript classes and methods that handle cryptography, P2P connections. **Version 4.02.442 introduces complete ASN.1 validation for enhanced key security.** +### Verification -## 📋 Table of Contents +- `confirmVerification(userCode)` validates a manually entered SAS code. +- Verification succeeds only after both local and remote confirmations are present. +- Protocol version `4.1` is enforced during offer/answer processing. -1. [Core Classes](#-core-classes) - - [EnhancedSecureCryptoUtils](#-enhancedsecurecryptoutils) - - [EnhancedSecureWebRTCManager](#-enhancedsecurewebrtcmanager) -2. [Security Framework APIs](#-security-framework-apis) - - [SecureKeyManager](#-securekeymanager) - - [ConnectionMutexManager](#-connectionmutexmanager) - - [SecureLogger](#-securelogger) - - [ASN1Validator](#-asn1validator) (NEW) -3. [Testing and Examples](#testing-and-examples) -4. [Integration Examples](#integration-examples) +### Privacy mode -## 📚 Core Classes +- relay-only configuration sets WebRTC `iceTransportPolicy` to `"relay"`. +- TURN availability is checked before claiming IP protection. -### 🔐 EnhancedSecureCryptoUtils +### File transfer callbacks -Central cryptographic utilities class providing military-grade encryption with complete ASN.1 validation. +- `setFileTransferCallbacks(onProgress, onReceived, onError, onIncomingRequest)` updates manager fields and any live `EnhancedSecureFileTransfer` instance. +- Passing `null` values detaches callbacks from the active transfer system. -#### Key Generation +## EnhancedSecureFileTransfer -##### `generateECDHKeyPair()` -```javascript -static async generateECDHKeyPair(): Promise -Generates non-extractable ECDH P-384 key pair for secure key exchange. -Returns: CryptoKeyPair with P-384 keys -Throws: Error if key generation fails +### Incoming transfers -Example: -const keyPair = await EnhancedSecureCryptoUtils.generateECDHKeyPair(); -console.log(keyPair.privateKey.algorithm.namedCurve); // "P-384" -``` +- metadata is validated before prompting +- acceptance is explicit +- receive buffers are allocated only after consent +- file type acceptance is allowlist-based -##### `generateECDSAKeyPair()` -```javascript -static async generateECDSAKeyPair(): Promise -Generates non-extractable ECDSA P-384 key pair for digital signatures. -Returns: CryptoKeyPair for signing and verification -Throws: Error if key generation fails -``` +### Cleanup -#### Encryption/Decryption +- pending sender consent promises are rejected on cleanup +- consent timeouts are cleared immediately +- retained received buffers are bounded +- evicted download handles fail with a user-facing availability message -##### `encryptMessage()` -```javascript -static async encryptMessage( - message: string, - encryptionKey: CryptoKey, - macKey: CryptoKey, - metadataKey: CryptoKey, - messageId: string, - sequenceNumber: number = 0 -): Promise +## SecurePersistentKeyStorage -Encrypts a message with metadata protection and sequence numbers. - -Parameters: -- message - Plaintext message (max 2000 chars) -- encryptionKey - AES-GCM 256-bit key -- macKey - HMAC key for authentication -- metadataKey - Key for metadata encryption -- messageId - Unique message identifier -- sequenceNumber - Message sequence for replay protection - -Returns: -```typescript -interface EncryptedMessage { - messageIv: number[]; - messageData: number[]; - metadataIv: number[]; - metadataData: number[]; - mac: number[]; - version: string; -} -``` - -Example: -```javascript -const encrypted = await EnhancedSecureCryptoUtils.encryptMessage( - "Hello, secure world!", - encryptionKey, - macKey, - metadataKey, - "msg_12345", - 42 -); -``` - -##### `decryptMessage()` -```javascript -static async decryptMessage( - encryptedPayload: EncryptedMessage, - encryptionKey: CryptoKey, - macKey: CryptoKey, - metadataKey: CryptoKey, - expectedSequenceNumber?: number -): Promise - -Decrypts and verifies an encrypted message. - -Returns: -```typescript -interface DecryptedMessage { - message: string; - messageId: string; - timestamp: number; - sequenceNumber: number; -} -``` - -#### Key Exchange - -##### `deriveSharedKeys()` -```javascript -static async deriveSharedKeys( - privateKey: CryptoKey, - publicKey: CryptoKey, -``` - -## 🔒 ASN1Validator (NEW) - -Complete ASN.1 DER parser and validation system for cryptographic key security. - -### Overview -The `ASN1Validator` class provides comprehensive structural validation of all cryptographic keys according to PKCS standards and RFC specifications. - -### Constructor -```javascript -const asn1Validator = new ASN1Validator(); -``` - -### Methods - -#### `validateKeyStructure(keyData)` -```javascript -validateKeyStructure(keyData: ArrayBuffer): boolean - -Complete structural validation of cryptographic keys using ASN.1 DER parsing. - -Parameters: -- keyData: ArrayBuffer - Raw key data to validate - -Returns: -- boolean - True if validation passes, false otherwise - -Throws: -- Error - Detailed error message for validation failures - -Example: -const isValid = asn1Validator.validateKeyStructure(keyData); -if (!isValid) { - console.error('Key structure validation failed'); -} -``` - -#### `parseDER(data)` -```javascript -parseDER(data: ArrayBuffer): ASN1Structure - -Parses ASN.1 DER encoded data into structured format. - -Parameters: -- data: ArrayBuffer - DER encoded data - -Returns: -- ASN1Structure - Parsed ASN.1 structure - -Example: -const parsed = asn1Validator.parseDER(keyData); -console.log('Parsed structure:', parsed); -``` - -#### `validateSPKI(parsed)` -```javascript -validateSPKI(parsed: ASN1Structure): boolean - -Validates SubjectPublicKeyInfo structure according to RFC 5280. - -Parameters: -- parsed: ASN1Structure - Parsed ASN.1 structure - -Returns: -- boolean - True if SPKI structure is valid - -Example: -if (!asn1Validator.validateSPKI(parsed)) { - throw new Error('Invalid SPKI structure'); -} -``` - -#### `validateOID(parsed)` -```javascript -validateOID(parsed: ASN1Structure): string - -Validates algorithm OID and returns supported curve name. - -Parameters: -- parsed: ASN1Structure - Parsed ASN.1 structure - -Returns: -- string - Supported curve name ('P-256' or 'P-384') - -Throws: -- Error - If OID is not supported - -Example: -try { - const curve = asn1Validator.validateOID(parsed); - console.log('Supported curve:', curve); -} catch (error) { - console.error('Unsupported curve:', error.message); -} -``` - -#### `validateECPoint(parsed)` -```javascript -validateECPoint(parsed: ASN1Structure): boolean - -Validates elliptic curve point format and structure. - -Parameters: -- parsed: ASN1Structure - Parsed ASN.1 structure - -Returns: -- boolean - True if EC point is valid - -Throws: -- Error - If EC point format is invalid - -Example: -if (!asn1Validator.validateECPoint(parsed)) { - throw new Error('Invalid EC point format'); -} -``` - -### Properties - -#### `supportedOIDs` -```javascript -readonly supportedOIDs: Record - -Supported algorithm OIDs and their corresponding curve names. - -Example: -console.log(asn1Validator.supportedOIDs); -// Output: { -// '1.2.840.10045.3.1.7': 'P-256', -// '1.3.132.0.34': 'P-384' -// } -``` - -#### `maxKeySize` -```javascript -readonly maxKeySize: number - -Maximum allowed key size in bytes (2000). - -Example: -console.log('Max key size:', asn1Validator.maxKeySize); // 2000 -``` - -#### `minKeySize` -```javascript -readonly minKeySize: number - -Minimum allowed key size in bytes (50). - -Example: -console.log('Min key size:', asn1Validator.minKeySize); // 50 -``` - -### Integration Examples - -#### Enhanced Key Import -```javascript -// Enhanced key import with ASN.1 validation -const importKey = async (keyData, keyType) => { - // Validate key structure before processing - if (!asn1Validator.validateKeyStructure(keyData)) { - throw new Error('Key structure validation failed'); - } - - // Proceed with standard key import - return await crypto.subtle.importKey( - keyType, - keyData, - algorithm, - extractable, - keyUsages - ); -}; -``` - -#### Enhanced Key Export -```javascript -// Enhanced key export with validation -const exportKey = async (key, format) => { - const exported = await crypto.subtle.exportKey(format, key); - - // Validate exported key structure - if (format === 'spki' && !asn1Validator.validateKeyStructure(exported)) { - throw new Error('Exported key validation failed'); - } - - return exported; -}; -``` - -#### Real-time Validation -```javascript -// Continuous validation during operations -const validateOperation = (operation, keyData) => { - // Validate key structure before each operation - if (!asn1Validator.validateKeyStructure(keyData)) { - throw new Error('Key validation failed during operation'); - } - - return operation(keyData); -}; -``` - -### Error Handling - -#### Common Error Types -```javascript -// OID validation errors -try { - asn1Validator.validateOID(parsed); -} catch (error) { - if (error.message.includes('Unsupported curve')) { - console.error('Algorithm not supported'); - } -} - -// EC point format errors -try { - asn1Validator.validateECPoint(parsed); -} catch (error) { - if (error.message.includes('Only uncompressed')) { - console.error('Compressed EC points not supported'); - } - if (error.message.includes('Key size outside')) { - console.error('Key size limits exceeded'); - } -} - -// SPKI structure errors -try { - asn1Validator.validateSPKI(parsed); -} catch (error) { - if (error.message.includes('Invalid SPKI')) { - console.error('Key structure is invalid'); - } -} -``` - -### Performance Characteristics - -#### Validation Timing -```javascript -// Measure validation performance -const measureValidation = (keyData) => { - const start = performance.now(); - const isValid = asn1Validator.validateKeyStructure(keyData); - const duration = performance.now() - start; - - console.log(`Validation took ${duration.toFixed(2)}ms`); - console.log(`Validation result: ${isValid}`); - - return { isValid, duration }; -}; -``` - -#### Batch Validation -```javascript -// Validate multiple keys efficiently -const validateMultipleKeys = (keyArray) => { - const results = []; - const start = performance.now(); - - for (const keyData of keyArray) { - const result = asn1Validator.validateKeyStructure(keyData); - results.push({ keyData, isValid: result }); - } - - const totalTime = performance.now() - start; - const avgTime = totalTime / keyArray.length; - - console.log(`Validated ${keyArray.length} keys in ${totalTime.toFixed(2)}ms`); - console.log(`Average time per key: ${avgTime.toFixed(2)}ms`); - - return results; -}; -``` - -### Testing and Validation - -#### Unit Test Examples -```javascript -describe('ASN1Validator', () => { - let asn1Validator; - - beforeEach(() => { - asn1Validator = new ASN1Validator(); - }); - - test('validates correct P-384 key structure', () => { - const validKey = generateValidP384Key(); - expect(asn1Validator.validateKeyStructure(validKey)).toBe(true); - }); - - test('rejects modified key with valid header', () => { - const modifiedKey = modifyKeyData(validKey); - expect(asn1Validator.validateKeyStructure(modifiedKey)).toBe(false); - }); - - test('rejects unsupported curve OID', () => { - const invalidOIDKey = generateKeyWithInvalidOID(); - expect(() => asn1Validator.validateOID(invalidOIDKey)).toThrow(); - }); - - test('rejects compressed EC point format', () => { - const compressedKey = generateCompressedKey(); - expect(() => asn1Validator.validateECPoint(compressedKey)).toThrow(); - }); -}); -``` - -#### Performance Test Examples -```javascript -describe('ASN1Validator Performance', () => { - test('validation completes within 10ms', () => { - const start = performance.now(); - asn1Validator.validateKeyStructure(validKey); - const duration = performance.now() - start; - expect(duration).toBeLessThan(10); - }); - - test('handles high-frequency validation', () => { - const iterations = 1000; - const start = performance.now(); - - for (let i = 0; i < iterations; i++) { - asn1Validator.validateKeyStructure(validKey); - } - - const duration = performance.now() - start; - const avgTime = duration / iterations; - expect(avgTime).toBeLessThan(1); // < 1ms average - }); -}); -``` - -### Migration Guide - -#### From Version 4.01.x -```javascript -// Old code (v4.01.x) -const importKey = async (keyData, keyType) => { - return await crypto.subtle.importKey(keyType, keyData, algorithm, extractable, keyUsages); -}; - -// New code (v4.02.x) - Enhanced with ASN.1 validation -const importKey = async (keyData, keyType) => { - // Add ASN.1 validation - if (!asn1Validator.validateKeyStructure(keyData)) { - throw new Error('Key structure validation failed'); - } - - return await crypto.subtle.importKey(keyType, keyData, algorithm, extractable, keyUsages); -}; -``` - -#### Breaking Changes -- **Enhanced key validation** now performs complete ASN.1 parsing -- **Stricter key acceptance** criteria for improved security -- **New error types** for validation failures -- **Performance impact** minimal (< 10ms per validation) - -#### Backward Compatibility -- **Existing keys** are validated on next use -- **Valid key structures** continue to work unchanged -- **Fallback support** from P-384 to P-256 maintained -- **Error handling** provides clear feedback for invalid keys - ---- - -## 📚 Core Classes - -### 🔐 EnhancedSecureCryptoUtils - -Central cryptographic utilities class providing military-grade encryption. - -#### Key Generation - -##### `generateECDHKeyPair()` -``javascript -static async generateECDHKeyPair(): Promise -Generates non-extractable ECDH P-384 key pair for secure key exchange. -Returns: CryptoKeyPair with P-384 keys -Throws: Error if key generation fails -Example: -javascriptconst keyPair = await EnhancedSecureCryptoUtils.generateECDHKeyPair(); -console.log(keyPair.privateKey.algorithm.namedCurve); // "P-384" -generateECDSAKeyPair() -javascriptstatic async generateECDSAKeyPair(): Promise -Generates non-extractable ECDSA P-384 key pair for digital signatures. -Returns: CryptoKeyPair for signing and verification -Throws: Error if key generation fails -Encryption/Decryption -encryptMessage() -javascriptstatic async encryptMessage( - message: string, - encryptionKey: CryptoKey, - macKey: CryptoKey, - metadataKey: CryptoKey, - messageId: string, - sequenceNumber: number = 0 -): Promise -Encrypts a message with metadata protection and sequence numbers. -Parameters: - -message - Plaintext message (max 2000 chars) -encryptionKey - AES-GCM 256-bit key -macKey - HMAC key for authentication -metadataKey - Key for metadata encryption -messageId - Unique message identifier -sequenceNumber - Message sequence for replay protection - -Returns: -typescriptinterface EncryptedMessage { - messageIv: number[]; - messageData: number[]; - metadataIv: number[]; - metadataData: number[]; - mac: number[]; - version: string; -} -Example: -javascriptconst encrypted = await EnhancedSecureCryptoUtils.encryptMessage( - "Hello, secure world!", - encryptionKey, - macKey, - metadataKey, - "msg_12345", - 42 -); -decryptMessage() -javascriptstatic async decryptMessage( - encryptedPayload: EncryptedMessage, - encryptionKey: CryptoKey, - macKey: CryptoKey, - metadataKey: CryptoKey, - expectedSequenceNumber?: number -): Promise -Decrypts and verifies an encrypted message. -Returns: -typescriptinterface DecryptedMessage { - message: string; - messageId: string; - timestamp: number; - sequenceNumber: number; -} -Key Exchange -deriveSharedKeys() -javascriptstatic async deriveSharedKeys( - privateKey: CryptoKey, - publicKey: CryptoKey, - salt: Uint8Array -): Promise -Derives shared encryption keys using ECDH + HKDF. -Parameters: - -privateKey - Local ECDH private key -publicKey - Remote ECDH public key -salt - 64-byte cryptographic salt - -Returns: -typescriptinterface SharedKeys { - encryptionKey: CryptoKey; - macKey: CryptoKey; - metadataKey: CryptoKey; - fingerprint: string; - timestamp: number; - version: string; -} -Example: -javascriptconst salt = EnhancedSecureCryptoUtils.generateSalt(); -const sharedKeys = await EnhancedSecureCryptoUtils.deriveSharedKeys( - localPrivateKey, - remotePublicKey, - salt -); -console.log('Key fingerprint:', sharedKeys.fingerprint); -Digital Signatures -signData() -javascriptstatic async signData( - privateKey: CryptoKey, - data: string | Uint8Array -): Promise -Signs data with ECDSA P-384. -Parameters: - -privateKey - ECDSA private key -data - Data to sign - -Returns: Signature as byte array -Example: -javascriptconst signature = await EnhancedSecureCryptoUtils.signData( - ecdsaPrivateKey, - "Important message" -); -verifySignature() -javascriptstatic async verifySignature( - publicKey: CryptoKey, - signature: number[], - data: string | Uint8Array -): Promise -Verifies ECDSA signature. -Returns: true if signature is valid -Authentication -generateMutualAuthChallenge() -javascriptstatic generateMutualAuthChallenge(): AuthChallenge -Generates cryptographic challenge for mutual authentication. -Returns: -typescriptinterface AuthChallenge { - challenge: number[]; - timestamp: number; - nonce: number[]; - version: string; -} -createAuthProof() -javascriptstatic async createAuthProof( - challenge: AuthChallenge, - privateKey: CryptoKey, - publicKey: CryptoKey -): Promise -Creates cryptographic proof for challenge response. -Returns: -typescriptinterface AuthProof { - challenge: number[]; - timestamp: number; - nonce: number[]; - responseTimestamp: number; - publicKeyHash: string; - signature: number[]; - version: string; -} -verifyAuthProof() -javascriptstatic async verifyAuthProof( - proof: AuthProof, - challenge: AuthChallenge, - publicKey: CryptoKey -): Promise -Verifies authentication proof against challenge. -Utility Functions -generateSalt() -javascriptstatic generateSalt(): number[] -Generates 64-byte cryptographically secure salt. -sanitizeMessage() -javascriptstatic sanitizeMessage(message: string): string -Sanitizes user input to prevent XSS attacks. -Example: -javascriptconst clean = EnhancedSecureCryptoUtils.sanitizeMessage("Hello"); -// Returns: "Hello" -calculateSecurityLevel() -javascriptstatic async calculateSecurityLevel(securityManager: any): Promise -Calculates real-time security level based on active protections. -Returns: -typescriptinterface SecurityLevel { - level: 'HIGH' | 'MEDIUM' | 'LOW' | 'UNKNOWN'; - score: number; // 0-100 - color: 'green' | 'yellow' | 'red'; - verificationResults: Record; - timestamp: number; - details: string; -} - -interface VerificationResult { - passed: boolean; - details: string; -} -generateVerificationCode() -javascriptstatic generateVerificationCode(): string -Generates 6-character verification code for out-of-band authentication. -Returns: Code in format "AB-CD-EF" -calculateKeyFingerprint() -javascriptstatic async calculateKeyFingerprint(keyData: number[]): Promise -Calculates SHA-256 fingerprint of key data for MITM protection. -encryptData() / decryptData() -javascriptstatic async encryptData(data: any, password: string): Promise -static async decryptData(encryptedData: string, password: string): Promise -High-level encryption/decryption for offer/answer exchange. -Example: -javascriptconst password = EnhancedSecureCryptoUtils.generateSecurePassword(); -const encrypted = await EnhancedSecureCryptoUtils.encryptData( - { message: "secret data" }, - password -); -const decrypted = await EnhancedSecureCryptoUtils.decryptData(encrypted, password); -🌐 EnhancedSecureWebRTCManager -Manages P2P connections with enhanced security features. -Constructor -javascriptnew EnhancedSecureWebRTCManager( - onMessage: (message: string, type: string) => void, - onStatusChange: (status: string) => void, - onKeyExchange: (fingerprint: string) => void, - onVerificationRequired: (code: string) => void -) -Parameters: - -onMessage - Callback for received messages -onStatusChange - Callback for connection state changes -onKeyExchange - Callback when keys are exchanged -onVerificationRequired - Callback when verification code is generated - -Connection Management -createSecureOffer() -javascriptasync createSecureOffer(): Promise -Creates encrypted connection offer with ECDH keys and authentication. -Returns: -typescriptinterface SecureOffer { - type: 'enhanced_secure_offer'; - sdp: string; - ecdhPublicKey: SignedPublicKey; - ecdsaPublicKey: SignedPublicKey; - salt: number[]; - verificationCode: string; - authChallenge: AuthChallenge; - sessionId: string; - timestamp: number; - version: string; - securityLevel: SecurityLevel; -} - -interface SignedPublicKey { - keyType: 'ECDH' | 'ECDSA'; - keyData: number[]; - timestamp: number; - version: string; - signature: number[]; -} -Example: -javascriptconst webrtcManager = new EnhancedSecureWebRTCManager(/*...*/); -const offer = await webrtcManager.createSecureOffer(); -console.log('Verification code:', offer.verificationCode); -createSecureAnswer() -javascriptasync createSecureAnswer(offerData: SecureOffer): Promise -Creates encrypted response to connection offer. -Returns: -typescriptinterface SecureAnswer { - type: 'enhanced_secure_answer'; - sdp: string; - ecdhPublicKey: SignedPublicKey; - ecdsaPublicKey: SignedPublicKey; - authProof: AuthProof; - timestamp: number; - version: string; - securityLevel: SecurityLevel; -} -handleSecureAnswer() -javascriptasync handleSecureAnswer(answerData: SecureAnswer): Promise -Processes encrypted answer and establishes connection. -Throws: Error if answer is invalid or authentication fails -Message Handling -sendSecureMessage() -javascriptasync sendSecureMessage(message: string): Promise -Sends encrypted message through secure channel. -Parameters: - -message - Plaintext message (auto-sanitized) - -Features: - -Automatic encryption with metadata protection -Sequence number tracking -Rate limiting (60 messages/minute) -Perfect Forward Secrecy key rotation - -Example: -javascriptawait webrtcManager.sendSecureMessage("Hello, secure world!"); -Connection States -typescripttype ConnectionState = - | 'disconnected' // No connection - | 'connecting' // Establishing connection - | 'verifying' // Verifying security codes - | 'connected' // Fully connected and verified - | 'failed' // Connection failed - | 'reconnecting' // Attempting to reconnect - | 'peer_disconnected'; // Peer disconnected -Security Features -calculateSecurityLevel() -javascriptasync calculateSecurityLevel(): Promise -Real-time security assessment with verification of: - -✅ Encryption functionality -✅ ECDH key exchange -✅ ECDSA signatures -✅ Mutual authentication -✅ Metadata protection -✅ Replay protection -✅ Non-extractable keys -✅ Rate limiting -✅ Perfect Forward Secrecy - -shouldRotateKeys() -javascriptshouldRotateKeys(): boolean -Determines if PFS key rotation is needed (every 5 minutes or 100 messages). -isConnected() -javascriptisConnected(): boolean -Returns true if WebRTC data channel is open and ready. -getConnectionInfo() -javascriptgetConnectionInfo(): ConnectionInfo -Returns: -typescriptinterface ConnectionInfo { - fingerprint: string; - isConnected: boolean; - isVerified: boolean; - connectionState: string; - iceConnectionState: string; - verificationCode: string; -} -Perfect Forward Secrecy -rotateKeys() -javascriptasync rotateKeys(): Promise -Performs key rotation for Perfect Forward Secrecy. -Returns: true if rotation successful -getKeysForVersion() -javascriptgetKeysForVersion(version: number): KeySet | null -Retrieves keys for specific version (for decrypting old messages). -Returns: -typescriptinterface KeySet { - encryptionKey: CryptoKey; - macKey: CryptoKey; - metadataKey: CryptoKey; -} -Connection Control -disconnect() -javascriptdisconnect(): void -Cleanly disconnects and cleans up all resources. -confirmVerification() -javascriptconfirmVerification(): void -Confirms that verification codes match (called after manual verification). -🧪 Testing -Unit Testing Examples -javascript// Test encryption/decryption round-trip -async function testEncryptionRoundTrip() { - const originalMessage = 'Test message for encryption'; - const keys = await generateTestKeys(); - - const encrypted = await EnhancedSecureCryptoUtils.encryptMessage( - originalMessage, - keys.encryptionKey, - keys.macKey, - keys.metadataKey, - 'test-id', - 0 - ); - - const decrypted = await EnhancedSecureCryptoUtils.decryptMessage( - encrypted, - keys.encryptionKey, - keys.macKey, - keys.metadataKey - ); - - assert.equal(decrypted.message, originalMessage); - assert.equal(decrypted.messageId, 'test-id'); - assert.equal(decrypted.sequenceNumber, 0); -} - -// Test key generation -async function testKeyGeneration() { - const ecdhPair = await EnhancedSecureCryptoUtils.generateECDHKeyPair(); - const ecdsaPair = await EnhancedSecureCryptoUtils.generateECDSAKeyPair(); - - // Verify key properties - assert.equal(ecdhPair.privateKey.algorithm.name, 'ECDH'); - assert.equal(ecdhPair.privateKey.algorithm.namedCurve, 'P-384'); - assert.equal(ecdhPair.privateKey.extractable, false); - - assert.equal(ecdsaPair.privateKey.algorithm.name, 'ECDSA'); - assert.equal(ecdsaPair.privateKey.algorithm.namedCurve, 'P-384'); - assert.equal(ecdsaPair.privateKey.extractable, false); -} - -// Test signature verification -async function testSignatureVerification() { - const keyPair = await EnhancedSecureCryptoUtils.generateECDSAKeyPair(); - const data = 'Test data to sign'; - - const signature = await EnhancedSecureCryptoUtils.signData( - keyPair.privateKey, - data - ); - - const isValid = await EnhancedSecureCryptoUtils.verifySignature( - keyPair.publicKey, - signature, - data - ); - - assert.equal(isValid, true); - - // Test with wrong data - const invalidVerification = await EnhancedSecureCryptoUtils.verifySignature( - keyPair.publicKey, - signature, - 'Wrong data' - ); - - assert.equal(invalidVerification, false); -} - -// Helper function for tests -async function generateTestKeys() { - const ecdhPair = await EnhancedSecureCryptoUtils.generateECDHKeyPair(); - const salt = EnhancedSecureCryptoUtils.generateSalt(); - - // For testing, we'll create a mock "remote" key pair - const remotePair = await EnhancedSecureCryptoUtils.generateECDHKeyPair(); - - const sharedKeys = await EnhancedSecureCryptoUtils.deriveSharedKeys( - ecdhPair.privateKey, - remotePair.publicKey, - salt - ); - - return sharedKeys; -} -Integration Testing -javascript// Test full P2P connection flow -async function testP2PConnection() { - let manager1Messages = []; - let manager2Messages = []; - - const manager1 = new EnhancedSecureWebRTCManager( - (msg, type) => manager1Messages.push({msg, type}), - (status) => console.log('Manager1 status:', status), - (fingerprint) => console.log('Manager1 fingerprint:', fingerprint), - (code) => console.log('Manager1 verification:', code) - ); - - const manager2 = new EnhancedSecureWebRTCManager( - (msg, type) => manager2Messages.push({msg, type}), - (status) => console.log('Manager2 status:', status), - (fingerprint) => console.log('Manager2 fingerprint:', fingerprint), - (code) => console.log('Manager2 verification:', code) - ); - - // Create offer - const offer = await manager1.createSecureOffer(); - - // Create answer - const answer = await manager2.createSecureAnswer(offer); - - // Handle answer - await manager1.handleSecureAnswer(answer); - - // Wait for connection - await waitForConnection(manager1, manager2); - - // Verify both are connected - assert.equal(manager1.isConnected(), true); - assert.equal(manager2.isConnected(), true); - - // Test message exchange - await manager1.sendSecureMessage('Hello from manager1'); - await manager2.sendSecureMessage('Hello from manager2'); - - // Wait for messages to arrive - await new Promise(resolve => setTimeout(resolve, 1000)); - - // Verify messages were received - assert.equal(manager2Messages.length > 0, true); - assert.equal(manager1Messages.length > 0, true); -} - -async function waitForConnection(manager1, manager2, timeout = 10000) { - const start = Date.now(); - - while (Date.now() - start < timeout) { - if (manager1.isConnected() && manager2.isConnected()) { - return; - } - await new Promise(resolve => setTimeout(resolve, 100)); - } - - throw new Error('Connection timeout'); -} - ---- - -## 🔒 Security Framework APIs - -### 🔐 SecureKeyManager - -Manages cryptographic keys with WeakMap-based isolation and secure access methods. - -#### `_initializeSecureKeyStorage()` -```javascript -_initializeSecureKeyStorage(): void -Initializes secure key storage with WeakMap isolation. -Example: -javascriptconst keyManager = new SecureKeyManager(); -keyManager._initializeSecureKeyStorage(); -``` - -#### `_getSecureKey(keyName)` -```javascript -_getSecureKey(keyName: string): CryptoKey | ArrayBuffer | Uint8Array -Retrieves a key from secure storage with access tracking. -Parameters: -- keyName - Name of the key to retrieve -Returns: The stored key value -Throws: Error if key not found -Example: -javascriptconst encryptionKey = keyManager._getSecureKey('encryptionKey'); -``` - -#### `_setSecureKey(keyName, keyValue, options)` -```javascript -_setSecureKey( - keyName: string, - keyValue: CryptoKey | ArrayBuffer | Uint8Array, - options?: { validate?: boolean } -): void -Stores a key in secure storage with validation. -Parameters: -- keyName - Name for the key -- keyValue - The key to store -- options.validate - Whether to validate the key value -Example: -javascriptkeyManager._setSecureKey('encryptionKey', newKey, { validate: true }); -``` - -#### `_validateKeyValue(keyValue, keyName)` -```javascript -_validateKeyValue(keyValue: any, keyName: string): void -Validates key value for security requirements. -Throws: Error if validation fails -``` - -#### `_rotateKeys()` -```javascript -_rotateKeys(): void -Performs secure key rotation with new key generation. -``` - -#### `_emergencyKeyWipe()` -```javascript -_emergencyKeyWipe(): void -Immediately removes all keys from memory for threat response. -``` - -### 🔒 ConnectionMutexManager - -Manages connection operations with mutex-based race condition protection. - -#### `_withMutex(mutexName, operation, timeout)` -```javascript -_withMutex( - mutexName: string, - operation: () => Promise, - timeout?: number -): Promise -Executes an operation with mutex protection. -Parameters: -- mutexName - Name of the mutex lock -- operation - Async function to execute -- timeout - Timeout in milliseconds (default: 15000) -Returns: Result of the operation -Throws: Error if mutex is locked or operation fails -Example: -javascriptawait mutexManager._withMutex('connectionOperation', async () => { - await this._generateEncryptionKeys(); - await this._establishSecureChannel(); -}); -``` - -#### `_generateOperationId()` -```javascript -_generateOperationId(): string -Generates unique operation identifier for tracking. -Returns: Unique operation ID string -``` - -#### `_cleanupFailedOfferCreation(operationId)` -```javascript -_cleanupFailedOfferCreation(operationId: string): Promise -Performs cleanup for failed connection operations. -Parameters: -- operationId - ID of the failed operation -``` - -### 🛡️ SecureLogger - -Provides environment-aware logging with data sanitization. - -#### `_secureLog(level, message, data)` -```javascript -_secureLog( - level: 'debug' | 'info' | 'warn' | 'error', - message: string, - data?: any -): void -Logs message with data sanitization and environment detection. -Parameters: -- level - Log level -- message - Log message -- data - Optional data object (will be sanitized) -Example: -javascriptlogger._secureLog('debug', 'Connection established', { - userId: 'user123', - encryptionKey: new Uint8Array(32) -}); -// Production: No output -// Development: [SecureBit:DEBUG] Connection established { userId: 'user123', encryptionKey: '[REDACTED]' } -``` - -#### `debug(message, data)` -```javascript -debug(message: string, data?: any): void -Logs debug message (development only). -``` - -#### `info(message, data)` -```javascript -info(message: string, data?: any): void -Logs info message. -``` - -#### `warn(message, data)` -```javascript -warn(message: string, data?: any): void -Logs warning message. -``` - -#### `error(message, data)` -```javascript -error(message: string, data?: any): void -Logs error message. -``` - -### 🔐 Backward Compatibility - -#### Getters and Setters -```javascript -// Secure key access with backward compatibility -get encryptionKey(): CryptoKey { - return this._getSecureKey('encryptionKey'); -} - -set encryptionKey(value: CryptoKey) { - this._setSecureKey('encryptionKey', value, { validate: true }); -} - -get macKey(): CryptoKey { - return this._getSecureKey('macKey'); -} - -set macKey(value: CryptoKey) { - this._setSecureKey('macKey', value, { validate: true }); -} -``` - -### 🔒 Security Framework Usage Examples - -#### Complete Security Setup -```javascript -// Initialize security framework -const keyManager = new SecureKeyManager(); -const mutexManager = new ConnectionMutexManager(); -const logger = new SecureLogger(); - -// Secure connection establishment -await mutexManager._withMutex('connectionOperation', async () => { - logger.debug('Starting secure connection'); - - // Generate and store keys securely - const keyPair = await EnhancedSecureCryptoUtils.generateECDHKeyPair(); - keyManager._setSecureKey('privateKey', keyPair.privateKey, { validate: true }); - - // Establish connection - await this._establishSecureChannel(); - - logger.info('Secure connection established'); -}); -``` - -#### Emergency Security Response -```javascript -// Emergency key wipe in case of security threat -keyManager._emergencyKeyWipe(); -logger.warn('Emergency key wipe completed'); - -// Force cleanup -if (typeof gc === 'function') { - gc(); -} -``` +- metadata is encrypted before storage +- legacy plaintext records migrate lazily +- corrupted encrypted metadata is ignored safely diff --git a/doc/CONFIGURATION.md b/doc/CONFIGURATION.md new file mode 100644 index 0000000..2ac4767 --- /dev/null +++ b/doc/CONFIGURATION.md @@ -0,0 +1,63 @@ +# Configuration Guide + +## Requirements + +- modern browser with WebRTC and Web Crypto support +- Node.js 18+ for local development +- TURN service only when relay-only privacy mode is required + +## Local setup + +```bash +npm install +npm run build +npm run serve +``` + +## ICE server configuration + +SecureBit.chat keeps existing STUN support for ordinary WebRTC connectivity. Deployments that require relay-only privacy must provide their own TURN service credentials through deployment configuration; public TURN credentials are intentionally not bundled. + +### Privacy modes + +| Mode | Behavior | IP privacy | +| --- | --- | --- | +| default | standard WebRTC candidate gathering | direct candidates may expose IP addresses | +| relay-only | `iceTransportPolicy: "relay"` | requires TURN and avoids direct peer candidates when configured correctly | + +### Operational rules + +- STUN is not a privacy substitute for TURN. +- Relay-only mode without TURN cannot establish a working relay connection. +- The UI warns users when TURN is missing. +- Validate TURN deployment with browser WebRTC diagnostics before production rollout. + +## Verification flow + +Protocol `4.1` requires interactive SAS verification: + +1. both peers derive the same SAS from shared session material +2. users compare the code out of band +3. each user enters the matching code manually +4. the chat unlocks only after both confirmations succeed + +Three failed local attempts disconnect the session. + +## File-transfer policy + +Incoming file requests are validated before the consent prompt and require explicit user approval. + +Allowed categories: + +- common raster images +- PDF +- plain text +- ZIP archives + +Blocked examples: + +- `.exe`, `.bat`, `.cmd`, `.sh`, `.js` +- `.msi`, `.dmg`, `.app`, `.jar`, `.scr` +- `.ps1`, `.vbs`, `.html`, `.svg` + +Both MIME type and extension must be acceptable. Missing or unknown MIME types are treated as unsafe unless explicitly covered by policy. diff --git a/doc/CONTRIBUTING.md b/doc/CONTRIBUTING.md index 88fbc30..3be4bc0 100644 --- a/doc/CONTRIBUTING.md +++ b/doc/CONTRIBUTING.md @@ -1,6126 +1,42 @@ -# Contributing to SecureBit.chat +# Contributing -🎉 **Thank you for your interest in contributing to SecureBit.chat!** +## Development workflow - **Version 4.02.442 introduces complete ASN.1 validation for enhanced key security.** - -## 🌟 Ways to Contribute - -### 🐛 Bug Reports -Found a bug? Help us squash it! - -### 💡 Feature Requests -Have an idea for improvement? We'd love to hear it! - -### 🔒 Security Research -Help audit our cryptographic implementation and ASN.1 validation framework - -### 📖 Documentation -Improve guides, tutorials, and technical docs - -### 🌍 Translations -Help make SecureBit.chat accessible worldwide - -### 💻 Code Contributions -Submit pull requests for bug fixes and features - -## 🚀 Getting Started - -### Prerequisites -- **Browser:** Modern browser with WebRTC and WebCrypto support -- **Git:** For version control -- **Text Editor:** VS Code, Vim, or your favorite editor -- **Lightning Wallet:** For testing payment features (optional) - -### Development Setup ```bash -# 1. Fork the repository on GitHub -# 2. Clone your fork -git clone https://github.com/yourusername/securebit-chat.git -cd securebit-chat - -# 3. Create a development branch -git checkout -b feature/your-feature-name - -# 4. Start development server -python -m http.server 8000 -# or -npx serve . - -# 5. Open http://localhost:8000 -# Make your changes -# Test thoroughly -# Commit with descriptive messages -git commit -m "feat: add quantum-resistant key exchange - -- Implement CRYSTALS-Kyber for post-quantum security -- Add fallback to classical ECDH -- Update security level calculations -- Add comprehensive test suite - -Closes #123" -``` - -## 📋 Contribution Guidelines - -### 🔍 Before You Start - -- Check existing issues - avoid duplicate work -- Create an issue - discuss your idea first -- Get feedback - ensure alignment with project goals -- Fork and branch - work on a feature branch - -### 💻 Code Standards - -#### JavaScript Style -```javascript -// ✅ Good -const encryptionKey = await crypto.subtle.generateKey({ - name: 'AES-GCM', - length: 256 -}, false, ['encrypt', 'decrypt']); - -// ❌ Bad -var key=crypto.subtle.generateKey({name:'AES-GCM',length:256},false,['encrypt','decrypt']) -``` - -#### Naming Conventions - -- **Functions:** camelCase - `generateSecureKey()` -- **Classes:** PascalCase - `EnhancedSecureCryptoUtils` -- **Constants:** UPPER_SNAKE_CASE - `MAX_MESSAGE_LENGTH` -- **Files:** kebab-case - `crypto-utils.js` - -### 📖 Documentation - -## 🔒 Security Considerations - -### Critical Areas -These areas require extra careful review: - -- **Cryptographic functions** - All crypto code must be reviewed -- **Key generation** - Entropy and randomness -- **Message handling** - Input validation and sanitization -- **P2P communication** - WebRTC security -- **Lightning integration** - Payment verification -- **ASN.1 validation** - Key structure verification (NEW) - -### Security Checklist - -## 🔐 ASN.1 Validation Framework (NEW) - -### Overview -SecureBit.chat v4.02.442 implements a complete ASN.1 DER parser and validation system. This framework requires special attention when contributing to cryptographic code. - -### Key Components - -#### **ASN1Validator Class** -```javascript -// Core validation class for cryptographic keys -class ASN1Validator { - constructor() { - this.supportedOIDs = { - '1.2.840.10045.3.1.7': 'P-256', // secp256r1 - '1.3.132.0.34': 'P-384' // secp384r1 - }; - this.maxKeySize = 2000; // bytes - this.minKeySize = 50; // bytes - } - - // Complete DER parsing and validation - validateKeyStructure(keyData) { - // Implementation details... - } -} -``` - -#### **Integration Points** -- **Key import operations** - All keys must pass ASN.1 validation -- **Key export operations** - Exported keys are validated -- **Real-time validation** - Continuous validation during operations - -### Contributing to ASN.1 Framework - -#### **Adding New Curve Support** -```javascript -// To add support for a new elliptic curve: -const newCurveOID = '1.3.132.0.XX'; // Replace XX with actual OID -const curveName = 'P-XXX'; // Replace XXX with curve name - -// Add to supportedOIDs -this.supportedOIDs[newCurveOID] = curveName; - -// Update validation logic if needed -// Ensure proper EC point format validation -``` - -#### **Extending Validation Rules** -```javascript -// To add new validation rules: -validateCustomRule(parsed) { - // Implement your validation logic - if (!this.checkCustomCondition(parsed)) { - throw new Error('Custom validation failed'); - } - return true; -} - -// Integrate with main validation -validateKeyStructure(keyData) { - const parsed = this.parseDER(keyData); - - // Existing validations... - if (!this.validateSPKI(parsed)) return false; - if (!this.validateOID(parsed)) return false; - if (!this.validateECPoint(parsed)) return false; - - // New custom validation - if (!this.validateCustomRule(parsed)) return false; - - return true; -} -``` - -### Testing ASN.1 Validation - -#### **Unit Tests** -```javascript -describe('ASN.1 Validation Framework', () => { - test('Validates correct P-384 key structure', () => { - const validKey = generateValidP384Key(); - expect(asn1Validator.validateKeyStructure(validKey)).toBe(true); - }); - - test('Rejects modified key with valid header', () => { - const modifiedKey = modifyKeyData(validKey); - expect(asn1Validator.validateKeyStructure(modifiedKey)).toBe(false); - }); - - test('Rejects unsupported curve OID', () => { - const invalidOIDKey = generateKeyWithInvalidOID(); - expect(asn1Validator.validateKeyStructure(invalidOIDKey)).toBe(false); - }); -}); -``` - -#### **Performance Tests** -```javascript -describe('ASN.1 Validation Performance', () => { - test('Validation completes within 10ms', () => { - const start = performance.now(); - asn1Validator.validateKeyStructure(validKey); - const duration = performance.now() - start; - expect(duration).toBeLessThan(10); - }); -}); -``` - -### Security Guidelines for ASN.1 Contributions - -#### **Critical Requirements** -1. **Never bypass validation** - All keys must pass complete ASN.1 validation -2. **Maintain strict OID checking** - Only support verified, secure algorithms -3. **Preserve size limits** - Key size limits prevent DoS attacks -4. **Validate all structural elements** - Complete verification is mandatory - -#### **Common Pitfalls to Avoid** -```javascript -// ❌ DON'T: Skip validation for performance -const fastImport = (keyData) => { - // Bypassing validation for speed - return crypto.subtle.importKey('spki', keyData, algorithm, false, ['verify']); -}; - -// ✅ DO: Always validate before processing -const secureImport = async (keyData) => { - if (!asn1Validator.validateKeyStructure(keyData)) { - throw new Error('Key validation failed'); - } - return await crypto.subtle.importKey('spki', keyData, algorithm, false, ['verify']); -}; -``` - -#### **Validation Order** -1. **Parse DER** - Complete ASN.1 structure parsing -2. **Validate SPKI** - SubjectPublicKeyInfo structure -3. **Validate OID** - Algorithm and curve verification -4. **Validate EC Point** - Format and structure verification -5. **Apply custom rules** - Any additional validation requirements - -### Breaking Changes and Compatibility - -#### **Version 4.02.442 Changes** -- **Enhanced key validation** now performs complete ASN.1 parsing -- **Stricter key acceptance** criteria for improved security -- **Fallback support** from P-384 to P-256 maintained -- **Backward compatibility** for valid key structures - -#### **Migration Considerations** -- **Existing keys** are validated on next use -- **New keys** must pass complete validation -- **Invalid keys** are rejected with clear error messages -- **Performance impact** is minimal (< 10ms per validation) - -### Documentation Requirements - -#### **Code Documentation** -```javascript -/** - * Validates cryptographic key structure using complete ASN.1 DER parsing - * - * @param {ArrayBuffer} keyData - Raw key data to validate - * @returns {boolean} - True if validation passes, false otherwise - * @throws {Error} - Detailed error message for validation failures - * - * @example - * const isValid = asn1Validator.validateKeyStructure(keyData); - * if (!isValid) { - * console.error('Key validation failed'); - * } - */ -validateKeyStructure(keyData) { - // Implementation... -} -``` - -#### **API Documentation** -- **Function signatures** with parameter types -- **Return values** and error conditions -- **Usage examples** for common scenarios -- **Performance characteristics** and limitations - -### Contributing Guidelines Summary - -#### **For ASN.1 Framework Contributions** -1. **Understand the security model** - Complete validation is mandatory -2. **Follow validation order** - Parse → SPKI → OID → EC Point → Custom -3. **Maintain performance** - Keep validation time under 10ms -4. **Add comprehensive tests** - Unit, integration, and performance tests -5. **Document thoroughly** - Code comments, API docs, and examples -6. **Consider breaking changes** - Ensure backward compatibility where possible - -#### **Security Review Process** -1. **Code review** by cryptographic experts -2. **Security testing** for validation bypass attempts -3. **Performance validation** for timing attacks -4. **Compatibility testing** with existing key formats -5. **Documentation review** for accuracy and completeness - ---- - -## 🚀 Getting Started - -### Prerequisites -- **Browser:** Modern browser with WebRTC and WebCrypto support -- **Git:** For version control -- **Text Editor:** VS Code, Vim, or your favorite editor -- **Lightning Wallet:** For testing payment features (optional) - -### Development Setup -```bash -# 1. Fork the repository on GitHub -# 2. Clone your fork -git clone https://github.com/yourusername/securebit-chat.git -cd securebit-chat - -# 3. Create a development branch -git checkout -b feature/your-feature-name - -# 4. Start development server -python -m http.server 8000 -# or -npx serve . - -# 5. Open http://localhost:8000 -# Make your changes -# Test thoroughly -# Commit with descriptive messages -git commit -m "feat: add quantum-resistant key exchange - -- Implement CRYSTALS-Kyber for post-quantum security -- Add fallback to classical ECDH -- Update security level calculations -- Add comprehensive test suite - -Closes #123" -``` - -## 📋 Contribution Guidelines - -### 🔍 Before You Start - -- Check existing issues - avoid duplicate work -- Create an issue - discuss your idea first -- Get feedback - ensure alignment with project goals -- Fork and branch - work on a feature branch - -### 💻 Code Standards - -#### JavaScript Style -```javascript -// ✅ Good -const encryptionKey = await crypto.subtle.generateKey({ - name: 'AES-GCM', - length: 256 -}, false, ['encrypt', 'decrypt']); - -// ❌ Bad -var key=crypto.subtle.generateKey({name:'AES-GCM',length:256},false,['encrypt','decrypt']) -``` - -#### Naming Conventions - -- **Functions:** camelCase - `generateSecureKey()` -- **Classes:** PascalCase - `EnhancedSecureCryptoUtils` -- **Constants:** UPPER_SNAKE_CASE - `MAX_MESSAGE_LENGTH` -- **Files:** kebab-case - `crypto-utils.js` - -### 📖 Documentation - -## 🔒 Security Considerations - -### Critical Areas -These areas require extra careful review: - -- **Cryptographic functions** - All crypto code must be reviewed -- **Key generation** - Entropy and randomness -- **Message handling** - Input validation and sanitization -- **P2P communication** - WebRTC security -- **Lightning integration** - Payment verification -- **ASN.1 validation** - Key structure verification (NEW) - -### Security Checklist - -## 🔐 ASN.1 Validation Framework (NEW) - -### Overview -SecureBit.chat v4.02.442 implements a complete ASN.1 DER parser and validation system. This framework requires special attention when contributing to cryptographic code. - -### Key Components - -#### **ASN1Validator Class** -```javascript -// Core validation class for cryptographic keys -class ASN1Validator { - constructor() { - this.supportedOIDs = { - '1.2.840.10045.3.1.7': 'P-256', // secp256r1 - '1.3.132.0.34': 'P-384' // secp384r1 - }; - this.maxKeySize = 2000; // bytes - this.minKeySize = 50; // bytes - } - - // Complete DER parsing and validation - validateKeyStructure(keyData) { - // Implementation details... - } -} -``` - -#### **Integration Points** -- **Key import operations** - All keys must pass ASN.1 validation -- **Key export operations** - Exported keys are validated -- **Real-time validation** - Continuous validation during operations - -### Contributing to ASN.1 Framework - -#### **Adding New Curve Support** -```javascript -// To add support for a new elliptic curve: -const newCurveOID = '1.3.132.0.XX'; // Replace XX with actual OID -const curveName = 'P-XXX'; // Replace XXX with curve name - -// Add to supportedOIDs -this.supportedOIDs[newCurveOID] = curveName; - -// Update validation logic if needed -// Ensure proper EC point format validation -``` - -#### **Extending Validation Rules** -```javascript -// To add new validation rules: -validateCustomRule(parsed) { - // Implement your validation logic - if (!this.checkCustomCondition(parsed)) { - throw new Error('Custom validation failed'); - } - return true; -} - -// Integrate with main validation -validateKeyStructure(keyData) { - const parsed = this.parseDER(keyData); - - // Existing validations... - if (!this.validateSPKI(parsed)) return false; - if (!this.validateOID(parsed)) return false; - if (!this.validateECPoint(parsed)) return false; - - // New custom validation - if (!this.validateCustomRule(parsed)) return false; - - return true; -} -``` - -### Testing ASN.1 Validation - -#### **Unit Tests** -```javascript -describe('ASN.1 Validation Framework', () => { - test('Validates correct P-384 key structure', () => { - const validKey = generateValidP384Key(); - expect(asn1Validator.validateKeyStructure(validKey)).toBe(true); - }); - - test('Rejects modified key with valid header', () => { - const modifiedKey = modifyKeyData(validKey); - expect(asn1Validator.validateKeyStructure(modifiedKey)).toBe(false); - }); - - test('Rejects unsupported curve OID', () => { - const invalidOIDKey = generateKeyWithInvalidOID(); - expect(asn1Validator.validateKeyStructure(invalidOIDKey)).toBe(false); - }); -}); -``` - -#### **Performance Tests** -```javascript -describe('ASN.1 Validation Performance', () => { - test('Validation completes within 10ms', () => { - const start = performance.now(); - asn1Validator.validateKeyStructure(validKey); - const duration = performance.now() - start; - expect(duration).toBeLessThan(10); - }); -}); -``` - -### Security Guidelines for ASN.1 Contributions - -#### **Critical Requirements** -1. **Never bypass validation** - All keys must pass complete ASN.1 validation -2. **Maintain strict OID checking** - Only support verified, secure algorithms -3. **Preserve size limits** - Key size limits prevent DoS attacks -4. **Validate all structural elements** - Complete verification is mandatory - -#### **Common Pitfalls to Avoid** -```javascript -// ❌ DON'T: Skip validation for performance -const fastImport = (keyData) => { - // Bypassing validation for speed - return crypto.subtle.importKey('spki', keyData, algorithm, false, ['verify']); -}; - -// ✅ DO: Always validate before processing -const secureImport = async (keyData) => { - if (!asn1Validator.validateKeyStructure(keyData)) { - throw new Error('Key validation failed'); - } - return await crypto.subtle.importKey('spki', keyData, algorithm, false, ['verify']); -}; -``` - -#### **Validation Order** -1. **Parse DER** - Complete ASN.1 structure parsing -2. **Validate SPKI** - SubjectPublicKeyInfo structure -3. **Validate OID** - Algorithm and curve verification -4. **Validate EC Point** - Format and structure verification -5. **Apply custom rules** - Any additional validation requirements - -### Breaking Changes and Compatibility - -#### **Version 4.02.442 Changes** -- **Enhanced key validation** now performs complete ASN.1 parsing -- **Stricter key acceptance** criteria for improved security -- **Fallback support** from P-384 to P-256 maintained -- **Backward compatibility** for valid key structures - -#### **Migration Considerations** -- **Existing keys** are validated on next use -- **New keys** must pass complete validation -- **Invalid keys** are rejected with clear error messages -- **Performance impact** is minimal (< 10ms per validation) - -### Documentation Requirements - -#### **Code Documentation** -```javascript -/** - * Validates cryptographic key structure using complete ASN.1 DER parsing - * - * @param {ArrayBuffer} keyData - Raw key data to validate - * @returns {boolean} - True if validation passes, false otherwise - * @throws {Error} - Detailed error message for validation failures - * - * @example - * const isValid = asn1Validator.validateKeyStructure(keyData); - * if (!isValid) { - * console.error('Key validation failed'); - * } - */ -validateKeyStructure(keyData) { - // Implementation... -} -``` - -#### **API Documentation** -- **Function signatures** with parameter types -- **Return values** and error conditions -- **Usage examples** for common scenarios -- **Performance characteristics** and limitations - -### Contributing Guidelines Summary - -#### **For ASN.1 Framework Contributions** -1. **Understand the security model** - Complete validation is mandatory -2. **Follow validation order** - Parse → SPKI → OID → EC Point → Custom -3. **Maintain performance** - Keep validation time under 10ms -4. **Add comprehensive tests** - Unit, integration, and performance tests -5. **Document thoroughly** - Code comments, API docs, and examples -6. **Consider breaking changes** - Ensure backward compatibility where possible - -#### **Security Review Process** -1. **Code review** by cryptographic experts -2. **Security testing** for validation bypass attempts -3. **Performance validation** for timing attacks -4. **Compatibility testing** with existing key formats -5. **Documentation review** for accuracy and completeness - ---- - -## 🚀 Getting Started - -### Prerequisites -- **Browser:** Modern browser with WebRTC and WebCrypto support -- **Git:** For version control -- **Text Editor:** VS Code, Vim, or your favorite editor -- **Lightning Wallet:** For testing payment features (optional) - -### Development Setup -```bash -# 1. Fork the repository on GitHub -# 2. Clone your fork -git clone https://github.com/yourusername/securebit-chat.git -cd securebit-chat - -# 3. Create a development branch -git checkout -b feature/your-feature-name - -# 4. Start development server -python -m http.server 8000 -# or -npx serve . - -# 5. Open http://localhost:8000 -# Make your changes -# Test thoroughly -# Commit with descriptive messages -git commit -m "feat: add quantum-resistant key exchange - -- Implement CRYSTALS-Kyber for post-quantum security -- Add fallback to classical ECDH -- Update security level calculations -- Add comprehensive test suite - -Closes #123" -``` - -## 📋 Contribution Guidelines - -### 🔍 Before You Start - -- Check existing issues - avoid duplicate work -- Create an issue - discuss your idea first -- Get feedback - ensure alignment with project goals -- Fork and branch - work on a feature branch - -### 💻 Code Standards - -#### JavaScript Style -```javascript -// ✅ Good -const encryptionKey = await crypto.subtle.generateKey({ - name: 'AES-GCM', - length: 256 -}, false, ['encrypt', 'decrypt']); - -// ❌ Bad -var key=crypto.subtle.generateKey({name:'AES-GCM',length:256},false,['encrypt','decrypt']) -``` - -#### Naming Conventions - -- **Functions:** camelCase - `generateSecureKey()` -- **Classes:** PascalCase - `EnhancedSecureCryptoUtils` -- **Constants:** UPPER_SNAKE_CASE - `MAX_MESSAGE_LENGTH` -- **Files:** kebab-case - `crypto-utils.js` - -### 📖 Documentation - -## 🔒 Security Considerations - -### Critical Areas -These areas require extra careful review: - -- **Cryptographic functions** - All crypto code must be reviewed -- **Key generation** - Entropy and randomness -- **Message handling** - Input validation and sanitization -- **P2P communication** - WebRTC security -- **Lightning integration** - Payment verification -- **ASN.1 validation** - Key structure verification (NEW) - -### Security Checklist - -## 🔐 ASN.1 Validation Framework (NEW) - -### Overview -SecureBit.chat v4.02.442 implements a complete ASN.1 DER parser and validation system. This framework requires special attention when contributing to cryptographic code. - -### Key Components - -#### **ASN1Validator Class** -```javascript -// Core validation class for cryptographic keys -class ASN1Validator { - constructor() { - this.supportedOIDs = { - '1.2.840.10045.3.1.7': 'P-256', // secp256r1 - '1.3.132.0.34': 'P-384' // secp384r1 - }; - this.maxKeySize = 2000; // bytes - this.minKeySize = 50; // bytes - } - - // Complete DER parsing and validation - validateKeyStructure(keyData) { - // Implementation details... - } -} -``` - -#### **Integration Points** -- **Key import operations** - All keys must pass ASN.1 validation -- **Key export operations** - Exported keys are validated -- **Real-time validation** - Continuous validation during operations - -### Contributing to ASN.1 Framework - -#### **Adding New Curve Support** -```javascript -// To add support for a new elliptic curve: -const newCurveOID = '1.3.132.0.XX'; // Replace XX with actual OID -const curveName = 'P-XXX'; // Replace XXX with curve name - -// Add to supportedOIDs -this.supportedOIDs[newCurveOID] = curveName; - -// Update validation logic if needed -// Ensure proper EC point format validation -``` - -#### **Extending Validation Rules** -```javascript -// To add new validation rules: -validateCustomRule(parsed) { - // Implement your validation logic - if (!this.checkCustomCondition(parsed)) { - throw new Error('Custom validation failed'); - } - return true; -} - -// Integrate with main validation -validateKeyStructure(keyData) { - const parsed = this.parseDER(keyData); - - // Existing validations... - if (!this.validateSPKI(parsed)) return false; - if (!this.validateOID(parsed)) return false; - if (!this.validateECPoint(parsed)) return false; - - // New custom validation - if (!this.validateCustomRule(parsed)) return false; - - return true; -} -``` - -### Testing ASN.1 Validation - -#### **Unit Tests** -```javascript -describe('ASN.1 Validation Framework', () => { - test('Validates correct P-384 key structure', () => { - const validKey = generateValidP384Key(); - expect(asn1Validator.validateKeyStructure(validKey)).toBe(true); - }); - - test('Rejects modified key with valid header', () => { - const modifiedKey = modifyKeyData(validKey); - expect(asn1Validator.validateKeyStructure(modifiedKey)).toBe(false); - }); - - test('Rejects unsupported curve OID', () => { - const invalidOIDKey = generateKeyWithInvalidOID(); - expect(asn1Validator.validateKeyStructure(invalidOIDKey)).toBe(false); - }); -}); -``` - -#### **Performance Tests** -```javascript -describe('ASN.1 Validation Performance', () => { - test('Validation completes within 10ms', () => { - const start = performance.now(); - asn1Validator.validateKeyStructure(validKey); - const duration = performance.now() - start; - expect(duration).toBeLessThan(10); - }); -}); -``` - -### Security Guidelines for ASN.1 Contributions - -#### **Critical Requirements** -1. **Never bypass validation** - All keys must pass complete ASN.1 validation -2. **Maintain strict OID checking** - Only support verified, secure algorithms -3. **Preserve size limits** - Key size limits prevent DoS attacks -4. **Validate all structural elements** - Complete verification is mandatory - -#### **Common Pitfalls to Avoid** -```javascript -// ❌ DON'T: Skip validation for performance -const fastImport = (keyData) => { - // Bypassing validation for speed - return crypto.subtle.importKey('spki', keyData, algorithm, false, ['verify']); -}; - -// ✅ DO: Always validate before processing -const secureImport = async (keyData) => { - if (!asn1Validator.validateKeyStructure(keyData)) { - throw new Error('Key validation failed'); - } - return await crypto.subtle.importKey('spki', keyData, algorithm, false, ['verify']); -}; -``` - -#### **Validation Order** -1. **Parse DER** - Complete ASN.1 structure parsing -2. **Validate SPKI** - SubjectPublicKeyInfo structure -3. **Validate OID** - Algorithm and curve verification -4. **Validate EC Point** - Format and structure verification -5. **Apply custom rules** - Any additional validation requirements - -### Breaking Changes and Compatibility - -#### **Version 4.02.442 Changes** -- **Enhanced key validation** now performs complete ASN.1 parsing -- **Stricter key acceptance** criteria for improved security -- **Fallback support** from P-384 to P-256 maintained -- **Backward compatibility** for valid key structures - -#### **Migration Considerations** -- **Existing keys** are validated on next use -- **New keys** must pass complete validation -- **Invalid keys** are rejected with clear error messages -- **Performance impact** is minimal (< 10ms per validation) - -### Documentation Requirements - -#### **Code Documentation** -```javascript -/** - * Validates cryptographic key structure using complete ASN.1 DER parsing - * - * @param {ArrayBuffer} keyData - Raw key data to validate - * @returns {boolean} - True if validation passes, false otherwise - * @throws {Error} - Detailed error message for validation failures - * - * @example - * const isValid = asn1Validator.validateKeyStructure(keyData); - * if (!isValid) { - * console.error('Key validation failed'); - * } - */ -validateKeyStructure(keyData) { - // Implementation... -} -``` - -#### **API Documentation** -- **Function signatures** with parameter types -- **Return values** and error conditions -- **Usage examples** for common scenarios -- **Performance characteristics** and limitations - -### Contributing Guidelines Summary - -#### **For ASN.1 Framework Contributions** -1. **Understand the security model** - Complete validation is mandatory -2. **Follow validation order** - Parse → SPKI → OID → EC Point → Custom -3. **Maintain performance** - Keep validation time under 10ms -4. **Add comprehensive tests** - Unit, integration, and performance tests -5. **Document thoroughly** - Code comments, API docs, and examples -6. **Consider breaking changes** - Ensure backward compatibility where possible - -#### **Security Review Process** -1. **Code review** by cryptographic experts -2. **Security testing** for validation bypass attempts -3. **Performance validation** for timing attacks -4. **Compatibility testing** with existing key formats -5. **Documentation review** for accuracy and completeness - ---- - -## 🚀 Getting Started - -### Prerequisites -- **Browser:** Modern browser with WebRTC and WebCrypto support -- **Git:** For version control -- **Text Editor:** VS Code, Vim, or your favorite editor -- **Lightning Wallet:** For testing payment features (optional) - -### Development Setup -```bash -# 1. Fork the repository on GitHub -# 2. Clone your fork -git clone https://github.com/yourusername/securebit-chat.git -cd securebit-chat - -# 3. Create a development branch -git checkout -b feature/your-feature-name - -# 4. Start development server -python -m http.server 8000 -# or -npx serve . - -# 5. Open http://localhost:8000 -# Make your changes -# Test thoroughly -# Commit with descriptive messages -git commit -m "feat: add quantum-resistant key exchange - -- Implement CRYSTALS-Kyber for post-quantum security -- Add fallback to classical ECDH -- Update security level calculations -- Add comprehensive test suite - -Closes #123" -``` - -## 📋 Contribution Guidelines - -### 🔍 Before You Start - -- Check existing issues - avoid duplicate work -- Create an issue - discuss your idea first -- Get feedback - ensure alignment with project goals -- Fork and branch - work on a feature branch - -### 💻 Code Standards - -#### JavaScript Style -```javascript -// ✅ Good -const encryptionKey = await crypto.subtle.generateKey({ - name: 'AES-GCM', - length: 256 -}, false, ['encrypt', 'decrypt']); - -// ❌ Bad -var key=crypto.subtle.generateKey({name:'AES-GCM',length:256},false,['encrypt','decrypt']) -``` - -#### Naming Conventions - -- **Functions:** camelCase - `generateSecureKey()` -- **Classes:** PascalCase - `EnhancedSecureCryptoUtils` -- **Constants:** UPPER_SNAKE_CASE - `MAX_MESSAGE_LENGTH` -- **Files:** kebab-case - `crypto-utils.js` - -### 📖 Documentation - -## 🔒 Security Considerations - -### Critical Areas -These areas require extra careful review: - -- **Cryptographic functions** - All crypto code must be reviewed -- **Key generation** - Entropy and randomness -- **Message handling** - Input validation and sanitization -- **P2P communication** - WebRTC security -- **Lightning integration** - Payment verification -- **ASN.1 validation** - Key structure verification (NEW) - -### Security Checklist - -## 🔐 ASN.1 Validation Framework (NEW) - -### Overview -SecureBit.chat v4.02.442 implements a complete ASN.1 DER parser and validation system. This framework requires special attention when contributing to cryptographic code. - -### Key Components - -#### **ASN1Validator Class** -```javascript -// Core validation class for cryptographic keys -class ASN1Validator { - constructor() { - this.supportedOIDs = { - '1.2.840.10045.3.1.7': 'P-256', // secp256r1 - '1.3.132.0.34': 'P-384' // secp384r1 - }; - this.maxKeySize = 2000; // bytes - this.minKeySize = 50; // bytes - } - - // Complete DER parsing and validation - validateKeyStructure(keyData) { - // Implementation details... - } -} -``` - -#### **Integration Points** -- **Key import operations** - All keys must pass ASN.1 validation -- **Key export operations** - Exported keys are validated -- **Real-time validation** - Continuous validation during operations - -### Contributing to ASN.1 Framework - -#### **Adding New Curve Support** -```javascript -// To add support for a new elliptic curve: -const newCurveOID = '1.3.132.0.XX'; // Replace XX with actual OID -const curveName = 'P-XXX'; // Replace XXX with curve name - -// Add to supportedOIDs -this.supportedOIDs[newCurveOID] = curveName; - -// Update validation logic if needed -// Ensure proper EC point format validation -``` - -#### **Extending Validation Rules** -```javascript -// To add new validation rules: -validateCustomRule(parsed) { - // Implement your validation logic - if (!this.checkCustomCondition(parsed)) { - throw new Error('Custom validation failed'); - } - return true; -} - -// Integrate with main validation -validateKeyStructure(keyData) { - const parsed = this.parseDER(keyData); - - // Existing validations... - if (!this.validateSPKI(parsed)) return false; - if (!this.validateOID(parsed)) return false; - if (!this.validateECPoint(parsed)) return false; - - // New custom validation - if (!this.validateCustomRule(parsed)) return false; - - return true; -} -``` - -### Testing ASN.1 Validation - -#### **Unit Tests** -```javascript -describe('ASN.1 Validation Framework', () => { - test('Validates correct P-384 key structure', () => { - const validKey = generateValidP384Key(); - expect(asn1Validator.validateKeyStructure(validKey)).toBe(true); - }); - - test('Rejects modified key with valid header', () => { - const modifiedKey = modifyKeyData(validKey); - expect(asn1Validator.validateKeyStructure(modifiedKey)).toBe(false); - }); - - test('Rejects unsupported curve OID', () => { - const invalidOIDKey = generateKeyWithInvalidOID(); - expect(asn1Validator.validateKeyStructure(invalidOIDKey)).toBe(false); - }); -}); -``` - -#### **Performance Tests** -```javascript -describe('ASN.1 Validation Performance', () => { - test('Validation completes within 10ms', () => { - const start = performance.now(); - asn1Validator.validateKeyStructure(validKey); - const duration = performance.now() - start; - expect(duration).toBeLessThan(10); - }); -}); -``` - -### Security Guidelines for ASN.1 Contributions - -#### **Critical Requirements** -1. **Never bypass validation** - All keys must pass complete ASN.1 validation -2. **Maintain strict OID checking** - Only support verified, secure algorithms -3. **Preserve size limits** - Key size limits prevent DoS attacks -4. **Validate all structural elements** - Complete verification is mandatory - -#### **Common Pitfalls to Avoid** -```javascript -// ❌ DON'T: Skip validation for performance -const fastImport = (keyData) => { - // Bypassing validation for speed - return crypto.subtle.importKey('spki', keyData, algorithm, false, ['verify']); -}; - -// ✅ DO: Always validate before processing -const secureImport = async (keyData) => { - if (!asn1Validator.validateKeyStructure(keyData)) { - throw new Error('Key validation failed'); - } - return await crypto.subtle.importKey('spki', keyData, algorithm, false, ['verify']); -}; -``` - -#### **Validation Order** -1. **Parse DER** - Complete ASN.1 structure parsing -2. **Validate SPKI** - SubjectPublicKeyInfo structure -3. **Validate OID** - Algorithm and curve verification -4. **Validate EC Point** - Format and structure verification -5. **Apply custom rules** - Any additional validation requirements - -### Breaking Changes and Compatibility - -#### **Version 4.02.442 Changes** -- **Enhanced key validation** now performs complete ASN.1 parsing -- **Stricter key acceptance** criteria for improved security -- **Fallback support** from P-384 to P-256 maintained -- **Backward compatibility** for valid key structures - -#### **Migration Considerations** -- **Existing keys** are validated on next use -- **New keys** must pass complete validation -- **Invalid keys** are rejected with clear error messages -- **Performance impact** is minimal (< 10ms per validation) - -### Documentation Requirements - -#### **Code Documentation** -```javascript -/** - * Validates cryptographic key structure using complete ASN.1 DER parsing - * - * @param {ArrayBuffer} keyData - Raw key data to validate - * @returns {boolean} - True if validation passes, false otherwise - * @throws {Error} - Detailed error message for validation failures - * - * @example - * const isValid = asn1Validator.validateKeyStructure(keyData); - * if (!isValid) { - * console.error('Key validation failed'); - * } - */ -validateKeyStructure(keyData) { - // Implementation... -} -``` - -#### **API Documentation** -- **Function signatures** with parameter types -- **Return values** and error conditions -- **Usage examples** for common scenarios -- **Performance characteristics** and limitations - -### Contributing Guidelines Summary - -#### **For ASN.1 Framework Contributions** -1. **Understand the security model** - Complete validation is mandatory -2. **Follow validation order** - Parse → SPKI → OID → EC Point → Custom -3. **Maintain performance** - Keep validation time under 10ms -4. **Add comprehensive tests** - Unit, integration, and performance tests -5. **Document thoroughly** - Code comments, API docs, and examples -6. **Consider breaking changes** - Ensure backward compatibility where possible - -#### **Security Review Process** -1. **Code review** by cryptographic experts -2. **Security testing** for validation bypass attempts -3. **Performance validation** for timing attacks -4. **Compatibility testing** with existing key formats -5. **Documentation review** for accuracy and completeness - ---- - -## 🚀 Getting Started - -### Prerequisites -- **Browser:** Modern browser with WebRTC and WebCrypto support -- **Git:** For version control -- **Text Editor:** VS Code, Vim, or your favorite editor -- **Lightning Wallet:** For testing payment features (optional) - -### Development Setup -```bash -# 1. Fork the repository on GitHub -# 2. Clone your fork -git clone https://github.com/yourusername/securebit-chat.git -cd securebit-chat - -# 3. Create a development branch -git checkout -b feature/your-feature-name - -# 4. Start development server -python -m http.server 8000 -# or -npx serve . - -# 5. Open http://localhost:8000 -# Make your changes -# Test thoroughly -# Commit with descriptive messages -git commit -m "feat: add quantum-resistant key exchange - -- Implement CRYSTALS-Kyber for post-quantum security -- Add fallback to classical ECDH -- Update security level calculations -- Add comprehensive test suite - -Closes #123" -``` - -## 📋 Contribution Guidelines - -### 🔍 Before You Start - -- Check existing issues - avoid duplicate work -- Create an issue - discuss your idea first -- Get feedback - ensure alignment with project goals -- Fork and branch - work on a feature branch - -### 💻 Code Standards - -#### JavaScript Style -```javascript -// ✅ Good -const encryptionKey = await crypto.subtle.generateKey({ - name: 'AES-GCM', - length: 256 -}, false, ['encrypt', 'decrypt']); - -// ❌ Bad -var key=crypto.subtle.generateKey({name:'AES-GCM',length:256},false,['encrypt','decrypt']) -``` - -#### Naming Conventions - -- **Functions:** camelCase - `generateSecureKey()` -- **Classes:** PascalCase - `EnhancedSecureCryptoUtils` -- **Constants:** UPPER_SNAKE_CASE - `MAX_MESSAGE_LENGTH` -- **Files:** kebab-case - `crypto-utils.js` - -### 📖 Documentation - -## 🔒 Security Considerations - -### Critical Areas -These areas require extra careful review: - -- **Cryptographic functions** - All crypto code must be reviewed -- **Key generation** - Entropy and randomness -- **Message handling** - Input validation and sanitization -- **P2P communication** - WebRTC security -- **Lightning integration** - Payment verification -- **ASN.1 validation** - Key structure verification (NEW) - -### Security Checklist - -## 🔐 ASN.1 Validation Framework (NEW) - -### Overview -SecureBit.chat v4.02.442 implements a complete ASN.1 DER parser and validation system. This framework requires special attention when contributing to cryptographic code. - -### Key Components - -#### **ASN1Validator Class** -```javascript -// Core validation class for cryptographic keys -class ASN1Validator { - constructor() { - this.supportedOIDs = { - '1.2.840.10045.3.1.7': 'P-256', // secp256r1 - '1.3.132.0.34': 'P-384' // secp384r1 - }; - this.maxKeySize = 2000; // bytes - this.minKeySize = 50; // bytes - } - - // Complete DER parsing and validation - validateKeyStructure(keyData) { - // Implementation details... - } -} -``` - -#### **Integration Points** -- **Key import operations** - All keys must pass ASN.1 validation -- **Key export operations** - Exported keys are validated -- **Real-time validation** - Continuous validation during operations - -### Contributing to ASN.1 Framework - -#### **Adding New Curve Support** -```javascript -// To add support for a new elliptic curve: -const newCurveOID = '1.3.132.0.XX'; // Replace XX with actual OID -const curveName = 'P-XXX'; // Replace XXX with curve name - -// Add to supportedOIDs -this.supportedOIDs[newCurveOID] = curveName; - -// Update validation logic if needed -// Ensure proper EC point format validation -``` - -#### **Extending Validation Rules** -```javascript -// To add new validation rules: -validateCustomRule(parsed) { - // Implement your validation logic - if (!this.checkCustomCondition(parsed)) { - throw new Error('Custom validation failed'); - } - return true; -} - -// Integrate with main validation -validateKeyStructure(keyData) { - const parsed = this.parseDER(keyData); - - // Existing validations... - if (!this.validateSPKI(parsed)) return false; - if (!this.validateOID(parsed)) return false; - if (!this.validateECPoint(parsed)) return false; - - // New custom validation - if (!this.validateCustomRule(parsed)) return false; - - return true; -} -``` - -### Testing ASN.1 Validation - -#### **Unit Tests** -```javascript -describe('ASN.1 Validation Framework', () => { - test('Validates correct P-384 key structure', () => { - const validKey = generateValidP384Key(); - expect(asn1Validator.validateKeyStructure(validKey)).toBe(true); - }); - - test('Rejects modified key with valid header', () => { - const modifiedKey = modifyKeyData(validKey); - expect(asn1Validator.validateKeyStructure(modifiedKey)).toBe(false); - }); - - test('Rejects unsupported curve OID', () => { - const invalidOIDKey = generateKeyWithInvalidOID(); - expect(asn1Validator.validateKeyStructure(invalidOIDKey)).toBe(false); - }); -}); -``` - -#### **Performance Tests** -```javascript -describe('ASN.1 Validation Performance', () => { - test('Validation completes within 10ms', () => { - const start = performance.now(); - asn1Validator.validateKeyStructure(validKey); - const duration = performance.now() - start; - expect(duration).toBeLessThan(10); - }); -}); -``` - -### Security Guidelines for ASN.1 Contributions - -#### **Critical Requirements** -1. **Never bypass validation** - All keys must pass complete ASN.1 validation -2. **Maintain strict OID checking** - Only support verified, secure algorithms -3. **Preserve size limits** - Key size limits prevent DoS attacks -4. **Validate all structural elements** - Complete verification is mandatory - -#### **Common Pitfalls to Avoid** -```javascript -// ❌ DON'T: Skip validation for performance -const fastImport = (keyData) => { - // Bypassing validation for speed - return crypto.subtle.importKey('spki', keyData, algorithm, false, ['verify']); -}; - -// ✅ DO: Always validate before processing -const secureImport = async (keyData) => { - if (!asn1Validator.validateKeyStructure(keyData)) { - throw new Error('Key validation failed'); - } - return await crypto.subtle.importKey('spki', keyData, algorithm, false, ['verify']); -}; -``` - -#### **Validation Order** -1. **Parse DER** - Complete ASN.1 structure parsing -2. **Validate SPKI** - SubjectPublicKeyInfo structure -3. **Validate OID** - Algorithm and curve verification -4. **Validate EC Point** - Format and structure verification -5. **Apply custom rules** - Any additional validation requirements - -### Breaking Changes and Compatibility - -#### **Version 4.02.442 Changes** -- **Enhanced key validation** now performs complete ASN.1 parsing -- **Stricter key acceptance** criteria for improved security -- **Fallback support** from P-384 to P-256 maintained -- **Backward compatibility** for valid key structures - -#### **Migration Considerations** -- **Existing keys** are validated on next use -- **New keys** must pass complete validation -- **Invalid keys** are rejected with clear error messages -- **Performance impact** is minimal (< 10ms per validation) - -### Documentation Requirements - -#### **Code Documentation** -```javascript -/** - * Validates cryptographic key structure using complete ASN.1 DER parsing - * - * @param {ArrayBuffer} keyData - Raw key data to validate - * @returns {boolean} - True if validation passes, false otherwise - * @throws {Error} - Detailed error message for validation failures - * - * @example - * const isValid = asn1Validator.validateKeyStructure(keyData); - * if (!isValid) { - * console.error('Key validation failed'); - * } - */ -validateKeyStructure(keyData) { - // Implementation... -} -``` - -#### **API Documentation** -- **Function signatures** with parameter types -- **Return values** and error conditions -- **Usage examples** for common scenarios -- **Performance characteristics** and limitations - -### Contributing Guidelines Summary - -#### **For ASN.1 Framework Contributions** -1. **Understand the security model** - Complete validation is mandatory -2. **Follow validation order** - Parse → SPKI → OID → EC Point → Custom -3. **Maintain performance** - Keep validation time under 10ms -4. **Add comprehensive tests** - Unit, integration, and performance tests -5. **Document thoroughly** - Code comments, API docs, and examples -6. **Consider breaking changes** - Ensure backward compatibility where possible - -#### **Security Review Process** -1. **Code review** by cryptographic experts -2. **Security testing** for validation bypass attempts -3. **Performance validation** for timing attacks -4. **Compatibility testing** with existing key formats -5. **Documentation review** for accuracy and completeness - ---- - -## 🚀 Getting Started - -### Prerequisites -- **Browser:** Modern browser with WebRTC and WebCrypto support -- **Git:** For version control -- **Text Editor:** VS Code, Vim, or your favorite editor -- **Lightning Wallet:** For testing payment features (optional) - -### Development Setup -```bash -# 1. Fork the repository on GitHub -# 2. Clone your fork -git clone https://github.com/yourusername/securebit-chat.git -cd securebit-chat - -# 3. Create a development branch -git checkout -b feature/your-feature-name - -# 4. Start development server -python -m http.server 8000 -# or -npx serve . - -# 5. Open http://localhost:8000 -# Make your changes -# Test thoroughly -# Commit with descriptive messages -git commit -m "feat: add quantum-resistant key exchange - -- Implement CRYSTALS-Kyber for post-quantum security -- Add fallback to classical ECDH -- Update security level calculations -- Add comprehensive test suite - -Closes #123" -``` - -## 📋 Contribution Guidelines - -### 🔍 Before You Start - -- Check existing issues - avoid duplicate work -- Create an issue - discuss your idea first -- Get feedback - ensure alignment with project goals -- Fork and branch - work on a feature branch - -### 💻 Code Standards - -#### JavaScript Style -```javascript -// ✅ Good -const encryptionKey = await crypto.subtle.generateKey({ - name: 'AES-GCM', - length: 256 -}, false, ['encrypt', 'decrypt']); - -// ❌ Bad -var key=crypto.subtle.generateKey({name:'AES-GCM',length:256},false,['encrypt','decrypt']) -``` - -#### Naming Conventions - -- **Functions:** camelCase - `generateSecureKey()` -- **Classes:** PascalCase - `EnhancedSecureCryptoUtils` -- **Constants:** UPPER_SNAKE_CASE - `MAX_MESSAGE_LENGTH` -- **Files:** kebab-case - `crypto-utils.js` - -### 📖 Documentation - -## 🔒 Security Considerations - -### Critical Areas -These areas require extra careful review: - -- **Cryptographic functions** - All crypto code must be reviewed -- **Key generation** - Entropy and randomness -- **Message handling** - Input validation and sanitization -- **P2P communication** - WebRTC security -- **Lightning integration** - Payment verification -- **ASN.1 validation** - Key structure verification (NEW) - -### Security Checklist - -## 🔐 ASN.1 Validation Framework (NEW) - -### Overview -SecureBit.chat v4.02.442 implements a complete ASN.1 DER parser and validation system. This framework requires special attention when contributing to cryptographic code. - -### Key Components - -#### **ASN1Validator Class** -```javascript -// Core validation class for cryptographic keys -class ASN1Validator { - constructor() { - this.supportedOIDs = { - '1.2.840.10045.3.1.7': 'P-256', // secp256r1 - '1.3.132.0.34': 'P-384' // secp384r1 - }; - this.maxKeySize = 2000; // bytes - this.minKeySize = 50; // bytes - } - - // Complete DER parsing and validation - validateKeyStructure(keyData) { - // Implementation details... - } -} -``` - -#### **Integration Points** -- **Key import operations** - All keys must pass ASN.1 validation -- **Key export operations** - Exported keys are validated -- **Real-time validation** - Continuous validation during operations - -### Contributing to ASN.1 Framework - -#### **Adding New Curve Support** -```javascript -// To add support for a new elliptic curve: -const newCurveOID = '1.3.132.0.XX'; // Replace XX with actual OID -const curveName = 'P-XXX'; // Replace XXX with curve name - -// Add to supportedOIDs -this.supportedOIDs[newCurveOID] = curveName; - -// Update validation logic if needed -// Ensure proper EC point format validation -``` - -#### **Extending Validation Rules** -```javascript -// To add new validation rules: -validateCustomRule(parsed) { - // Implement your validation logic - if (!this.checkCustomCondition(parsed)) { - throw new Error('Custom validation failed'); - } - return true; -} - -// Integrate with main validation -validateKeyStructure(keyData) { - const parsed = this.parseDER(keyData); - - // Existing validations... - if (!this.validateSPKI(parsed)) return false; - if (!this.validateOID(parsed)) return false; - if (!this.validateECPoint(parsed)) return false; - - // New custom validation - if (!this.validateCustomRule(parsed)) return false; - - return true; -} -``` - -### Testing ASN.1 Validation - -#### **Unit Tests** -```javascript -describe('ASN.1 Validation Framework', () => { - test('Validates correct P-384 key structure', () => { - const validKey = generateValidP384Key(); - expect(asn1Validator.validateKeyStructure(validKey)).toBe(true); - }); - - test('Rejects modified key with valid header', () => { - const modifiedKey = modifyKeyData(validKey); - expect(asn1Validator.validateKeyStructure(modifiedKey)).toBe(false); - }); - - test('Rejects unsupported curve OID', () => { - const invalidOIDKey = generateKeyWithInvalidOID(); - expect(asn1Validator.validateKeyStructure(invalidOIDKey)).toBe(false); - }); -}); -``` - -#### **Performance Tests** -```javascript -describe('ASN.1 Validation Performance', () => { - test('Validation completes within 10ms', () => { - const start = performance.now(); - asn1Validator.validateKeyStructure(validKey); - const duration = performance.now() - start; - expect(duration).toBeLessThan(10); - }); -}); -``` - -### Security Guidelines for ASN.1 Contributions - -#### **Critical Requirements** -1. **Never bypass validation** - All keys must pass complete ASN.1 validation -2. **Maintain strict OID checking** - Only support verified, secure algorithms -3. **Preserve size limits** - Key size limits prevent DoS attacks -4. **Validate all structural elements** - Complete verification is mandatory - -#### **Common Pitfalls to Avoid** -```javascript -// ❌ DON'T: Skip validation for performance -const fastImport = (keyData) => { - // Bypassing validation for speed - return crypto.subtle.importKey('spki', keyData, algorithm, false, ['verify']); -}; - -// ✅ DO: Always validate before processing -const secureImport = async (keyData) => { - if (!asn1Validator.validateKeyStructure(keyData)) { - throw new Error('Key validation failed'); - } - return await crypto.subtle.importKey('spki', keyData, algorithm, false, ['verify']); -}; -``` - -#### **Validation Order** -1. **Parse DER** - Complete ASN.1 structure parsing -2. **Validate SPKI** - SubjectPublicKeyInfo structure -3. **Validate OID** - Algorithm and curve verification -4. **Validate EC Point** - Format and structure verification -5. **Apply custom rules** - Any additional validation requirements - -### Breaking Changes and Compatibility - -#### **Version 4.02.442 Changes** -- **Enhanced key validation** now performs complete ASN.1 parsing -- **Stricter key acceptance** criteria for improved security -- **Fallback support** from P-384 to P-256 maintained -- **Backward compatibility** for valid key structures - -#### **Migration Considerations** -- **Existing keys** are validated on next use -- **New keys** must pass complete validation -- **Invalid keys** are rejected with clear error messages -- **Performance impact** is minimal (< 10ms per validation) - -### Documentation Requirements - -#### **Code Documentation** -```javascript -/** - * Validates cryptographic key structure using complete ASN.1 DER parsing - * - * @param {ArrayBuffer} keyData - Raw key data to validate - * @returns {boolean} - True if validation passes, false otherwise - * @throws {Error} - Detailed error message for validation failures - * - * @example - * const isValid = asn1Validator.validateKeyStructure(keyData); - * if (!isValid) { - * console.error('Key validation failed'); - * } - */ -validateKeyStructure(keyData) { - // Implementation... -} -``` - -#### **API Documentation** -- **Function signatures** with parameter types -- **Return values** and error conditions -- **Usage examples** for common scenarios -- **Performance characteristics** and limitations - -### Contributing Guidelines Summary - -#### **For ASN.1 Framework Contributions** -1. **Understand the security model** - Complete validation is mandatory -2. **Follow validation order** - Parse → SPKI → OID → EC Point → Custom -3. **Maintain performance** - Keep validation time under 10ms -4. **Add comprehensive tests** - Unit, integration, and performance tests -5. **Document thoroughly** - Code comments, API docs, and examples -6. **Consider breaking changes** - Ensure backward compatibility where possible - -#### **Security Review Process** -1. **Code review** by cryptographic experts -2. **Security testing** for validation bypass attempts -3. **Performance validation** for timing attacks -4. **Compatibility testing** with existing key formats -5. **Documentation review** for accuracy and completeness - ---- - -## 🚀 Getting Started - -### Prerequisites -- **Browser:** Modern browser with WebRTC and WebCrypto support -- **Git:** For version control -- **Text Editor:** VS Code, Vim, or your favorite editor -- **Lightning Wallet:** For testing payment features (optional) - -### Development Setup -```bash -# 1. Fork the repository on GitHub -# 2. Clone your fork -git clone https://github.com/yourusername/securebit-chat.git -cd securebit-chat - -# 3. Create a development branch -git checkout -b feature/your-feature-name - -# 4. Start development server -python -m http.server 8000 -# or -npx serve . - -# 5. Open http://localhost:8000 -# Make your changes -# Test thoroughly -# Commit with descriptive messages -git commit -m "feat: add quantum-resistant key exchange - -- Implement CRYSTALS-Kyber for post-quantum security -- Add fallback to classical ECDH -- Update security level calculations -- Add comprehensive test suite - -Closes #123" -``` - -## 📋 Contribution Guidelines - -### 🔍 Before You Start - -- Check existing issues - avoid duplicate work -- Create an issue - discuss your idea first -- Get feedback - ensure alignment with project goals -- Fork and branch - work on a feature branch - -### 💻 Code Standards - -#### JavaScript Style -```javascript -// ✅ Good -const encryptionKey = await crypto.subtle.generateKey({ - name: 'AES-GCM', - length: 256 -}, false, ['encrypt', 'decrypt']); - -// ❌ Bad -var key=crypto.subtle.generateKey({name:'AES-GCM',length:256},false,['encrypt','decrypt']) -``` - -#### Naming Conventions - -- **Functions:** camelCase - `generateSecureKey()` -- **Classes:** PascalCase - `EnhancedSecureCryptoUtils` -- **Constants:** UPPER_SNAKE_CASE - `MAX_MESSAGE_LENGTH` -- **Files:** kebab-case - `crypto-utils.js` - -### 📖 Documentation - -## 🔒 Security Considerations - -### Critical Areas -These areas require extra careful review: - -- **Cryptographic functions** - All crypto code must be reviewed -- **Key generation** - Entropy and randomness -- **Message handling** - Input validation and sanitization -- **P2P communication** - WebRTC security -- **Lightning integration** - Payment verification -- **ASN.1 validation** - Key structure verification (NEW) - -### Security Checklist - -## 🔐 ASN.1 Validation Framework (NEW) - -### Overview -SecureBit.chat v4.02.442 implements a complete ASN.1 DER parser and validation system. This framework requires special attention when contributing to cryptographic code. - -### Key Components - -#### **ASN1Validator Class** -```javascript -// Core validation class for cryptographic keys -class ASN1Validator { - constructor() { - this.supportedOIDs = { - '1.2.840.10045.3.1.7': 'P-256', // secp256r1 - '1.3.132.0.34': 'P-384' // secp384r1 - }; - this.maxKeySize = 2000; // bytes - this.minKeySize = 50; // bytes - } - - // Complete DER parsing and validation - validateKeyStructure(keyData) { - // Implementation details... - } -} -``` - -#### **Integration Points** -- **Key import operations** - All keys must pass ASN.1 validation -- **Key export operations** - Exported keys are validated -- **Real-time validation** - Continuous validation during operations - -### Contributing to ASN.1 Framework - -#### **Adding New Curve Support** -```javascript -// To add support for a new elliptic curve: -const newCurveOID = '1.3.132.0.XX'; // Replace XX with actual OID -const curveName = 'P-XXX'; // Replace XXX with curve name - -// Add to supportedOIDs -this.supportedOIDs[newCurveOID] = curveName; - -// Update validation logic if needed -// Ensure proper EC point format validation -``` - -#### **Extending Validation Rules** -```javascript -// To add new validation rules: -validateCustomRule(parsed) { - // Implement your validation logic - if (!this.checkCustomCondition(parsed)) { - throw new Error('Custom validation failed'); - } - return true; -} - -// Integrate with main validation -validateKeyStructure(keyData) { - const parsed = this.parseDER(keyData); - - // Existing validations... - if (!this.validateSPKI(parsed)) return false; - if (!this.validateOID(parsed)) return false; - if (!this.validateECPoint(parsed)) return false; - - // New custom validation - if (!this.validateCustomRule(parsed)) return false; - - return true; -} -``` - -### Testing ASN.1 Validation - -#### **Unit Tests** -```javascript -describe('ASN.1 Validation Framework', () => { - test('Validates correct P-384 key structure', () => { - const validKey = generateValidP384Key(); - expect(asn1Validator.validateKeyStructure(validKey)).toBe(true); - }); - - test('Rejects modified key with valid header', () => { - const modifiedKey = modifyKeyData(validKey); - expect(asn1Validator.validateKeyStructure(modifiedKey)).toBe(false); - }); - - test('Rejects unsupported curve OID', () => { - const invalidOIDKey = generateKeyWithInvalidOID(); - expect(asn1Validator.validateKeyStructure(invalidOIDKey)).toBe(false); - }); -}); -``` - -#### **Performance Tests** -```javascript -describe('ASN.1 Validation Performance', () => { - test('Validation completes within 10ms', () => { - const start = performance.now(); - asn1Validator.validateKeyStructure(validKey); - const duration = performance.now() - start; - expect(duration).toBeLessThan(10); - }); -}); -``` - -### Security Guidelines for ASN.1 Contributions - -#### **Critical Requirements** -1. **Never bypass validation** - All keys must pass complete ASN.1 validation -2. **Maintain strict OID checking** - Only support verified, secure algorithms -3. **Preserve size limits** - Key size limits prevent DoS attacks -4. **Validate all structural elements** - Complete verification is mandatory - -#### **Common Pitfalls to Avoid** -```javascript -// ❌ DON'T: Skip validation for performance -const fastImport = (keyData) => { - // Bypassing validation for speed - return crypto.subtle.importKey('spki', keyData, algorithm, false, ['verify']); -}; - -// ✅ DO: Always validate before processing -const secureImport = async (keyData) => { - if (!asn1Validator.validateKeyStructure(keyData)) { - throw new Error('Key validation failed'); - } - return await crypto.subtle.importKey('spki', keyData, algorithm, false, ['verify']); -}; -``` - -#### **Validation Order** -1. **Parse DER** - Complete ASN.1 structure parsing -2. **Validate SPKI** - SubjectPublicKeyInfo structure -3. **Validate OID** - Algorithm and curve verification -4. **Validate EC Point** - Format and structure verification -5. **Apply custom rules** - Any additional validation requirements - -### Breaking Changes and Compatibility - -#### **Version 4.02.442 Changes** -- **Enhanced key validation** now performs complete ASN.1 parsing -- **Stricter key acceptance** criteria for improved security -- **Fallback support** from P-384 to P-256 maintained -- **Backward compatibility** for valid key structures - -#### **Migration Considerations** -- **Existing keys** are validated on next use -- **New keys** must pass complete validation -- **Invalid keys** are rejected with clear error messages -- **Performance impact** is minimal (< 10ms per validation) - -### Documentation Requirements - -#### **Code Documentation** -```javascript -/** - * Validates cryptographic key structure using complete ASN.1 DER parsing - * - * @param {ArrayBuffer} keyData - Raw key data to validate - * @returns {boolean} - True if validation passes, false otherwise - * @throws {Error} - Detailed error message for validation failures - * - * @example - * const isValid = asn1Validator.validateKeyStructure(keyData); - * if (!isValid) { - * console.error('Key validation failed'); - * } - */ -validateKeyStructure(keyData) { - // Implementation... -} -``` - -#### **API Documentation** -- **Function signatures** with parameter types -- **Return values** and error conditions -- **Usage examples** for common scenarios -- **Performance characteristics** and limitations - -### Contributing Guidelines Summary - -#### **For ASN.1 Framework Contributions** -1. **Understand the security model** - Complete validation is mandatory -2. **Follow validation order** - Parse → SPKI → OID → EC Point → Custom -3. **Maintain performance** - Keep validation time under 10ms -4. **Add comprehensive tests** - Unit, integration, and performance tests -5. **Document thoroughly** - Code comments, API docs, and examples -6. **Consider breaking changes** - Ensure backward compatibility where possible - -#### **Security Review Process** -1. **Code review** by cryptographic experts -2. **Security testing** for validation bypass attempts -3. **Performance validation** for timing attacks -4. **Compatibility testing** with existing key formats -5. **Documentation review** for accuracy and completeness - ---- - -## 🚀 Getting Started - -### Prerequisites -- **Browser:** Modern browser with WebRTC and WebCrypto support -- **Git:** For version control -- **Text Editor:** VS Code, Vim, or your favorite editor -- **Lightning Wallet:** For testing payment features (optional) - -### Development Setup -```bash -# 1. Fork the repository on GitHub -# 2. Clone your fork -git clone https://github.com/yourusername/securebit-chat.git -cd securebit-chat - -# 3. Create a development branch -git checkout -b feature/your-feature-name - -# 4. Start development server -python -m http.server 8000 -# or -npx serve . - -# 5. Open http://localhost:8000 -# Make your changes -# Test thoroughly -# Commit with descriptive messages -git commit -m "feat: add quantum-resistant key exchange - -- Implement CRYSTALS-Kyber for post-quantum security -- Add fallback to classical ECDH -- Update security level calculations -- Add comprehensive test suite - -Closes #123" -``` - -## 📋 Contribution Guidelines - -### 🔍 Before You Start - -- Check existing issues - avoid duplicate work -- Create an issue - discuss your idea first -- Get feedback - ensure alignment with project goals -- Fork and branch - work on a feature branch - -### 💻 Code Standards - -#### JavaScript Style -```javascript -// ✅ Good -const encryptionKey = await crypto.subtle.generateKey({ - name: 'AES-GCM', - length: 256 -}, false, ['encrypt', 'decrypt']); - -// ❌ Bad -var key=crypto.subtle.generateKey({name:'AES-GCM',length:256},false,['encrypt','decrypt']) -``` - -#### Naming Conventions - -- **Functions:** camelCase - `generateSecureKey()` -- **Classes:** PascalCase - `EnhancedSecureCryptoUtils` -- **Constants:** UPPER_SNAKE_CASE - `MAX_MESSAGE_LENGTH` -- **Files:** kebab-case - `crypto-utils.js` - -### 📖 Documentation - -## 🔒 Security Considerations - -### Critical Areas -These areas require extra careful review: - -- **Cryptographic functions** - All crypto code must be reviewed -- **Key generation** - Entropy and randomness -- **Message handling** - Input validation and sanitization -- **P2P communication** - WebRTC security -- **Lightning integration** - Payment verification -- **ASN.1 validation** - Key structure verification (NEW) - -### Security Checklist - -## 🔐 ASN.1 Validation Framework (NEW) - -### Overview -SecureBit.chat v4.02.442 implements a complete ASN.1 DER parser and validation system. This framework requires special attention when contributing to cryptographic code. - -### Key Components - -#### **ASN1Validator Class** -```javascript -// Core validation class for cryptographic keys -class ASN1Validator { - constructor() { - this.supportedOIDs = { - '1.2.840.10045.3.1.7': 'P-256', // secp256r1 - '1.3.132.0.34': 'P-384' // secp384r1 - }; - this.maxKeySize = 2000; // bytes - this.minKeySize = 50; // bytes - } - - // Complete DER parsing and validation - validateKeyStructure(keyData) { - // Implementation details... - } -} -``` - -#### **Integration Points** -- **Key import operations** - All keys must pass ASN.1 validation -- **Key export operations** - Exported keys are validated -- **Real-time validation** - Continuous validation during operations - -### Contributing to ASN.1 Framework - -#### **Adding New Curve Support** -```javascript -// To add support for a new elliptic curve: -const newCurveOID = '1.3.132.0.XX'; // Replace XX with actual OID -const curveName = 'P-XXX'; // Replace XXX with curve name - -// Add to supportedOIDs -this.supportedOIDs[newCurveOID] = curveName; - -// Update validation logic if needed -// Ensure proper EC point format validation -``` - -#### **Extending Validation Rules** -```javascript -// To add new validation rules: -validateCustomRule(parsed) { - // Implement your validation logic - if (!this.checkCustomCondition(parsed)) { - throw new Error('Custom validation failed'); - } - return true; -} - -// Integrate with main validation -validateKeyStructure(keyData) { - const parsed = this.parseDER(keyData); - - // Existing validations... - if (!this.validateSPKI(parsed)) return false; - if (!this.validateOID(parsed)) return false; - if (!this.validateECPoint(parsed)) return false; - - // New custom validation - if (!this.validateCustomRule(parsed)) return false; - - return true; -} -``` - -### Testing ASN.1 Validation - -#### **Unit Tests** -```javascript -describe('ASN.1 Validation Framework', () => { - test('Validates correct P-384 key structure', () => { - const validKey = generateValidP384Key(); - expect(asn1Validator.validateKeyStructure(validKey)).toBe(true); - }); - - test('Rejects modified key with valid header', () => { - const modifiedKey = modifyKeyData(validKey); - expect(asn1Validator.validateKeyStructure(modifiedKey)).toBe(false); - }); - - test('Rejects unsupported curve OID', () => { - const invalidOIDKey = generateKeyWithInvalidOID(); - expect(asn1Validator.validateKeyStructure(invalidOIDKey)).toBe(false); - }); -}); -``` - -#### **Performance Tests** -```javascript -describe('ASN.1 Validation Performance', () => { - test('Validation completes within 10ms', () => { - const start = performance.now(); - asn1Validator.validateKeyStructure(validKey); - const duration = performance.now() - start; - expect(duration).toBeLessThan(10); - }); -}); -``` - -### Security Guidelines for ASN.1 Contributions - -#### **Critical Requirements** -1. **Never bypass validation** - All keys must pass complete ASN.1 validation -2. **Maintain strict OID checking** - Only support verified, secure algorithms -3. **Preserve size limits** - Key size limits prevent DoS attacks -4. **Validate all structural elements** - Complete verification is mandatory - -#### **Common Pitfalls to Avoid** -```javascript -// ❌ DON'T: Skip validation for performance -const fastImport = (keyData) => { - // Bypassing validation for speed - return crypto.subtle.importKey('spki', keyData, algorithm, false, ['verify']); -}; - -// ✅ DO: Always validate before processing -const secureImport = async (keyData) => { - if (!asn1Validator.validateKeyStructure(keyData)) { - throw new Error('Key validation failed'); - } - return await crypto.subtle.importKey('spki', keyData, algorithm, false, ['verify']); -}; -``` - -#### **Validation Order** -1. **Parse DER** - Complete ASN.1 structure parsing -2. **Validate SPKI** - SubjectPublicKeyInfo structure -3. **Validate OID** - Algorithm and curve verification -4. **Validate EC Point** - Format and structure verification -5. **Apply custom rules** - Any additional validation requirements - -### Breaking Changes and Compatibility - -#### **Version 4.02.442 Changes** -- **Enhanced key validation** now performs complete ASN.1 parsing -- **Stricter key acceptance** criteria for improved security -- **Fallback support** from P-384 to P-256 maintained -- **Backward compatibility** for valid key structures - -#### **Migration Considerations** -- **Existing keys** are validated on next use -- **New keys** must pass complete validation -- **Invalid keys** are rejected with clear error messages -- **Performance impact** is minimal (< 10ms per validation) - -### Documentation Requirements - -#### **Code Documentation** -```javascript -/** - * Validates cryptographic key structure using complete ASN.1 DER parsing - * - * @param {ArrayBuffer} keyData - Raw key data to validate - * @returns {boolean} - True if validation passes, false otherwise - * @throws {Error} - Detailed error message for validation failures - * - * @example - * const isValid = asn1Validator.validateKeyStructure(keyData); - * if (!isValid) { - * console.error('Key validation failed'); - * } - */ -validateKeyStructure(keyData) { - // Implementation... -} -``` - -#### **API Documentation** -- **Function signatures** with parameter types -- **Return values** and error conditions -- **Usage examples** for common scenarios -- **Performance characteristics** and limitations - -### Contributing Guidelines Summary - -#### **For ASN.1 Framework Contributions** -1. **Understand the security model** - Complete validation is mandatory -2. **Follow validation order** - Parse → SPKI → OID → EC Point → Custom -3. **Maintain performance** - Keep validation time under 10ms -4. **Add comprehensive tests** - Unit, integration, and performance tests -5. **Document thoroughly** - Code comments, API docs, and examples -6. **Consider breaking changes** - Ensure backward compatibility where possible - -#### **Security Review Process** -1. **Code review** by cryptographic experts -2. **Security testing** for validation bypass attempts -3. **Performance validation** for timing attacks -4. **Compatibility testing** with existing key formats -5. **Documentation review** for accuracy and completeness - ---- - -## 🚀 Getting Started - -### Prerequisites -- **Browser:** Modern browser with WebRTC and WebCrypto support -- **Git:** For version control -- **Text Editor:** VS Code, Vim, or your favorite editor -- **Lightning Wallet:** For testing payment features (optional) - -### Development Setup -```bash -# 1. Fork the repository on GitHub -# 2. Clone your fork -git clone https://github.com/yourusername/securebit-chat.git -cd securebit-chat - -# 3. Create a development branch -git checkout -b feature/your-feature-name - -# 4. Start development server -python -m http.server 8000 -# or -npx serve . - -# 5. Open http://localhost:8000 -# Make your changes -# Test thoroughly -# Commit with descriptive messages -git commit -m "feat: add quantum-resistant key exchange - -- Implement CRYSTALS-Kyber for post-quantum security -- Add fallback to classical ECDH -- Update security level calculations -- Add comprehensive test suite - -Closes #123" -``` - -## 📋 Contribution Guidelines - -### 🔍 Before You Start - -- Check existing issues - avoid duplicate work -- Create an issue - discuss your idea first -- Get feedback - ensure alignment with project goals -- Fork and branch - work on a feature branch - -### 💻 Code Standards - -#### JavaScript Style -```javascript -// ✅ Good -const encryptionKey = await crypto.subtle.generateKey({ - name: 'AES-GCM', - length: 256 -}, false, ['encrypt', 'decrypt']); - -// ❌ Bad -var key=crypto.subtle.generateKey({name:'AES-GCM',length:256},false,['encrypt','decrypt']) -``` - -#### Naming Conventions - -- **Functions:** camelCase - `generateSecureKey()` -- **Classes:** PascalCase - `EnhancedSecureCryptoUtils` -- **Constants:** UPPER_SNAKE_CASE - `MAX_MESSAGE_LENGTH` -- **Files:** kebab-case - `crypto-utils.js` - -### 📖 Documentation - -## 🔒 Security Considerations - -### Critical Areas -These areas require extra careful review: - -- **Cryptographic functions** - All crypto code must be reviewed -- **Key generation** - Entropy and randomness -- **Message handling** - Input validation and sanitization -- **P2P communication** - WebRTC security -- **Lightning integration** - Payment verification -- **ASN.1 validation** - Key structure verification (NEW) - -### Security Checklist - -## 🔐 ASN.1 Validation Framework (NEW) - -### Overview -SecureBit.chat v4.02.442 implements a complete ASN.1 DER parser and validation system. This framework requires special attention when contributing to cryptographic code. - -### Key Components - -#### **ASN1Validator Class** -```javascript -// Core validation class for cryptographic keys -class ASN1Validator { - constructor() { - this.supportedOIDs = { - '1.2.840.10045.3.1.7': 'P-256', // secp256r1 - '1.3.132.0.34': 'P-384' // secp384r1 - }; - this.maxKeySize = 2000; // bytes - this.minKeySize = 50; // bytes - } - - // Complete DER parsing and validation - validateKeyStructure(keyData) { - // Implementation details... - } -} -``` - -#### **Integration Points** -- **Key import operations** - All keys must pass ASN.1 validation -- **Key export operations** - Exported keys are validated -- **Real-time validation** - Continuous validation during operations - -### Contributing to ASN.1 Framework - -#### **Adding New Curve Support** -```javascript -// To add support for a new elliptic curve: -const newCurveOID = '1.3.132.0.XX'; // Replace XX with actual OID -const curveName = 'P-XXX'; // Replace XXX with curve name - -// Add to supportedOIDs -this.supportedOIDs[newCurveOID] = curveName; - -// Update validation logic if needed -// Ensure proper EC point format validation -``` - -#### **Extending Validation Rules** -```javascript -// To add new validation rules: -validateCustomRule(parsed) { - // Implement your validation logic - if (!this.checkCustomCondition(parsed)) { - throw new Error('Custom validation failed'); - } - return true; -} - -// Integrate with main validation -validateKeyStructure(keyData) { - const parsed = this.parseDER(keyData); - - // Existing validations... - if (!this.validateSPKI(parsed)) return false; - if (!this.validateOID(parsed)) return false; - if (!this.validateECPoint(parsed)) return false; - - // New custom validation - if (!this.validateCustomRule(parsed)) return false; - - return true; -} -``` - -### Testing ASN.1 Validation - -#### **Unit Tests** -```javascript -describe('ASN.1 Validation Framework', () => { - test('Validates correct P-384 key structure', () => { - const validKey = generateValidP384Key(); - expect(asn1Validator.validateKeyStructure(validKey)).toBe(true); - }); - - test('Rejects modified key with valid header', () => { - const modifiedKey = modifyKeyData(validKey); - expect(asn1Validator.validateKeyStructure(modifiedKey)).toBe(false); - }); - - test('Rejects unsupported curve OID', () => { - const invalidOIDKey = generateKeyWithInvalidOID(); - expect(asn1Validator.validateKeyStructure(invalidOIDKey)).toBe(false); - }); -}); -``` - -#### **Performance Tests** -```javascript -describe('ASN.1 Validation Performance', () => { - test('Validation completes within 10ms', () => { - const start = performance.now(); - asn1Validator.validateKeyStructure(validKey); - const duration = performance.now() - start; - expect(duration).toBeLessThan(10); - }); -}); -``` - -### Security Guidelines for ASN.1 Contributions - -#### **Critical Requirements** -1. **Never bypass validation** - All keys must pass complete ASN.1 validation -2. **Maintain strict OID checking** - Only support verified, secure algorithms -3. **Preserve size limits** - Key size limits prevent DoS attacks -4. **Validate all structural elements** - Complete verification is mandatory - -#### **Common Pitfalls to Avoid** -```javascript -// ❌ DON'T: Skip validation for performance -const fastImport = (keyData) => { - // Bypassing validation for speed - return crypto.subtle.importKey('spki', keyData, algorithm, false, ['verify']); -}; - -// ✅ DO: Always validate before processing -const secureImport = async (keyData) => { - if (!asn1Validator.validateKeyStructure(keyData)) { - throw new Error('Key validation failed'); - } - return await crypto.subtle.importKey('spki', keyData, algorithm, false, ['verify']); -}; -``` - -#### **Validation Order** -1. **Parse DER** - Complete ASN.1 structure parsing -2. **Validate SPKI** - SubjectPublicKeyInfo structure -3. **Validate OID** - Algorithm and curve verification -4. **Validate EC Point** - Format and structure verification -5. **Apply custom rules** - Any additional validation requirements - -### Breaking Changes and Compatibility - -#### **Version 4.02.442 Changes** -- **Enhanced key validation** now performs complete ASN.1 parsing -- **Stricter key acceptance** criteria for improved security -- **Fallback support** from P-384 to P-256 maintained -- **Backward compatibility** for valid key structures - -#### **Migration Considerations** -- **Existing keys** are validated on next use -- **New keys** must pass complete validation -- **Invalid keys** are rejected with clear error messages -- **Performance impact** is minimal (< 10ms per validation) - -### Documentation Requirements - -#### **Code Documentation** -```javascript -/** - * Validates cryptographic key structure using complete ASN.1 DER parsing - * - * @param {ArrayBuffer} keyData - Raw key data to validate - * @returns {boolean} - True if validation passes, false otherwise - * @throws {Error} - Detailed error message for validation failures - * - * @example - * const isValid = asn1Validator.validateKeyStructure(keyData); - * if (!isValid) { - * console.error('Key validation failed'); - * } - */ -validateKeyStructure(keyData) { - // Implementation... -} -``` - -#### **API Documentation** -- **Function signatures** with parameter types -- **Return values** and error conditions -- **Usage examples** for common scenarios -- **Performance characteristics** and limitations - -### Contributing Guidelines Summary - -#### **For ASN.1 Framework Contributions** -1. **Understand the security model** - Complete validation is mandatory -2. **Follow validation order** - Parse → SPKI → OID → EC Point → Custom -3. **Maintain performance** - Keep validation time under 10ms -4. **Add comprehensive tests** - Unit, integration, and performance tests -5. **Document thoroughly** - Code comments, API docs, and examples -6. **Consider breaking changes** - Ensure backward compatibility where possible - -#### **Security Review Process** -1. **Code review** by cryptographic experts -2. **Security testing** for validation bypass attempts -3. **Performance validation** for timing attacks -4. **Compatibility testing** with existing key formats -5. **Documentation review** for accuracy and completeness - ---- - -## 🚀 Getting Started - -### Prerequisites -- **Browser:** Modern browser with WebRTC and WebCrypto support -- **Git:** For version control -- **Text Editor:** VS Code, Vim, or your favorite editor -- **Lightning Wallet:** For testing payment features (optional) - -### Development Setup -```bash -# 1. Fork the repository on GitHub -# 2. Clone your fork -git clone https://github.com/yourusername/securebit-chat.git -cd securebit-chat - -# 3. Create a development branch -git checkout -b feature/your-feature-name - -# 4. Start development server -python -m http.server 8000 -# or -npx serve . - -# 5. Open http://localhost:8000 -# Make your changes -# Test thoroughly -# Commit with descriptive messages -git commit -m "feat: add quantum-resistant key exchange - -- Implement CRYSTALS-Kyber for post-quantum security -- Add fallback to classical ECDH -- Update security level calculations -- Add comprehensive test suite - -Closes #123" -``` - -## 📋 Contribution Guidelines - -### 🔍 Before You Start - -- Check existing issues - avoid duplicate work -- Create an issue - discuss your idea first -- Get feedback - ensure alignment with project goals -- Fork and branch - work on a feature branch - -### 💻 Code Standards - -#### JavaScript Style -```javascript -// ✅ Good -const encryptionKey = await crypto.subtle.generateKey({ - name: 'AES-GCM', - length: 256 -}, false, ['encrypt', 'decrypt']); - -// ❌ Bad -var key=crypto.subtle.generateKey({name:'AES-GCM',length:256},false,['encrypt','decrypt']) -``` - -#### Naming Conventions - -- **Functions:** camelCase - `generateSecureKey()` -- **Classes:** PascalCase - `EnhancedSecureCryptoUtils` -- **Constants:** UPPER_SNAKE_CASE - `MAX_MESSAGE_LENGTH` -- **Files:** kebab-case - `crypto-utils.js` - -### 📖 Documentation - -## 🔒 Security Considerations - -### Critical Areas -These areas require extra careful review: - -- **Cryptographic functions** - All crypto code must be reviewed -- **Key generation** - Entropy and randomness -- **Message handling** - Input validation and sanitization -- **P2P communication** - WebRTC security -- **Lightning integration** - Payment verification -- **ASN.1 validation** - Key structure verification (NEW) - -### Security Checklist - -## 🔐 ASN.1 Validation Framework (NEW) - -### Overview -SecureBit.chat v4.02.442 implements a complete ASN.1 DER parser and validation system. This framework requires special attention when contributing to cryptographic code. - -### Key Components - -#### **ASN1Validator Class** -```javascript -// Core validation class for cryptographic keys -class ASN1Validator { - constructor() { - this.supportedOIDs = { - '1.2.840.10045.3.1.7': 'P-256', // secp256r1 - '1.3.132.0.34': 'P-384' // secp384r1 - }; - this.maxKeySize = 2000; // bytes - this.minKeySize = 50; // bytes - } - - // Complete DER parsing and validation - validateKeyStructure(keyData) { - // Implementation details... - } -} -``` - -#### **Integration Points** -- **Key import operations** - All keys must pass ASN.1 validation -- **Key export operations** - Exported keys are validated -- **Real-time validation** - Continuous validation during operations - -### Contributing to ASN.1 Framework - -#### **Adding New Curve Support** -```javascript -// To add support for a new elliptic curve: -const newCurveOID = '1.3.132.0.XX'; // Replace XX with actual OID -const curveName = 'P-XXX'; // Replace XXX with curve name - -// Add to supportedOIDs -this.supportedOIDs[newCurveOID] = curveName; - -// Update validation logic if needed -// Ensure proper EC point format validation -``` - -#### **Extending Validation Rules** -```javascript -// To add new validation rules: -validateCustomRule(parsed) { - // Implement your validation logic - if (!this.checkCustomCondition(parsed)) { - throw new Error('Custom validation failed'); - } - return true; -} - -// Integrate with main validation -validateKeyStructure(keyData) { - const parsed = this.parseDER(keyData); - - // Existing validations... - if (!this.validateSPKI(parsed)) return false; - if (!this.validateOID(parsed)) return false; - if (!this.validateECPoint(parsed)) return false; - - // New custom validation - if (!this.validateCustomRule(parsed)) return false; - - return true; -} -``` - -### Testing ASN.1 Validation - -#### **Unit Tests** -```javascript -describe('ASN.1 Validation Framework', () => { - test('Validates correct P-384 key structure', () => { - const validKey = generateValidP384Key(); - expect(asn1Validator.validateKeyStructure(validKey)).toBe(true); - }); - - test('Rejects modified key with valid header', () => { - const modifiedKey = modifyKeyData(validKey); - expect(asn1Validator.validateKeyStructure(modifiedKey)).toBe(false); - }); - - test('Rejects unsupported curve OID', () => { - const invalidOIDKey = generateKeyWithInvalidOID(); - expect(asn1Validator.validateKeyStructure(invalidOIDKey)).toBe(false); - }); -}); -``` - -#### **Performance Tests** -```javascript -describe('ASN.1 Validation Performance', () => { - test('Validation completes within 10ms', () => { - const start = performance.now(); - asn1Validator.validateKeyStructure(validKey); - const duration = performance.now() - start; - expect(duration).toBeLessThan(10); - }); -}); -``` - -### Security Guidelines for ASN.1 Contributions - -#### **Critical Requirements** -1. **Never bypass validation** - All keys must pass complete ASN.1 validation -2. **Maintain strict OID checking** - Only support verified, secure algorithms -3. **Preserve size limits** - Key size limits prevent DoS attacks -4. **Validate all structural elements** - Complete verification is mandatory - -#### **Common Pitfalls to Avoid** -```javascript -// ❌ DON'T: Skip validation for performance -const fastImport = (keyData) => { - // Bypassing validation for speed - return crypto.subtle.importKey('spki', keyData, algorithm, false, ['verify']); -}; - -// ✅ DO: Always validate before processing -const secureImport = async (keyData) => { - if (!asn1Validator.validateKeyStructure(keyData)) { - throw new Error('Key validation failed'); - } - return await crypto.subtle.importKey('spki', keyData, algorithm, false, ['verify']); -}; -``` - -#### **Validation Order** -1. **Parse DER** - Complete ASN.1 structure parsing -2. **Validate SPKI** - SubjectPublicKeyInfo structure -3. **Validate OID** - Algorithm and curve verification -4. **Validate EC Point** - Format and structure verification -5. **Apply custom rules** - Any additional validation requirements - -### Breaking Changes and Compatibility - -#### **Version 4.02.442 Changes** -- **Enhanced key validation** now performs complete ASN.1 parsing -- **Stricter key acceptance** criteria for improved security -- **Fallback support** from P-384 to P-256 maintained -- **Backward compatibility** for valid key structures - -#### **Migration Considerations** -- **Existing keys** are validated on next use -- **New keys** must pass complete validation -- **Invalid keys** are rejected with clear error messages -- **Performance impact** is minimal (< 10ms per validation) - -### Documentation Requirements - -#### **Code Documentation** -```javascript -/** - * Validates cryptographic key structure using complete ASN.1 DER parsing - * - * @param {ArrayBuffer} keyData - Raw key data to validate - * @returns {boolean} - True if validation passes, false otherwise - * @throws {Error} - Detailed error message for validation failures - * - * @example - * const isValid = asn1Validator.validateKeyStructure(keyData); - * if (!isValid) { - * console.error('Key validation failed'); - * } - */ -validateKeyStructure(keyData) { - // Implementation... -} -``` - -#### **API Documentation** -- **Function signatures** with parameter types -- **Return values** and error conditions -- **Usage examples** for common scenarios -- **Performance characteristics** and limitations - -### Contributing Guidelines Summary - -#### **For ASN.1 Framework Contributions** -1. **Understand the security model** - Complete validation is mandatory -2. **Follow validation order** - Parse → SPKI → OID → EC Point → Custom -3. **Maintain performance** - Keep validation time under 10ms -4. **Add comprehensive tests** - Unit, integration, and performance tests -5. **Document thoroughly** - Code comments, API docs, and examples -6. **Consider breaking changes** - Ensure backward compatibility where possible - -#### **Security Review Process** -1. **Code review** by cryptographic experts -2. **Security testing** for validation bypass attempts -3. **Performance validation** for timing attacks -4. **Compatibility testing** with existing key formats -5. **Documentation review** for accuracy and completeness - ---- - -## 🚀 Getting Started - -### Prerequisites -- **Browser:** Modern browser with WebRTC and WebCrypto support -- **Git:** For version control -- **Text Editor:** VS Code, Vim, or your favorite editor -- **Lightning Wallet:** For testing payment features (optional) - -### Development Setup -```bash -# 1. Fork the repository on GitHub -# 2. Clone your fork -git clone https://github.com/yourusername/securebit-chat.git -cd securebit-chat - -# 3. Create a development branch -git checkout -b feature/your-feature-name - -# 4. Start development server -python -m http.server 8000 -# or -npx serve . - -# 5. Open http://localhost:8000 -# Make your changes -# Test thoroughly -# Commit with descriptive messages -git commit -m "feat: add quantum-resistant key exchange - -- Implement CRYSTALS-Kyber for post-quantum security -- Add fallback to classical ECDH -- Update security level calculations -- Add comprehensive test suite - -Closes #123" -``` - -## 📋 Contribution Guidelines - -### 🔍 Before You Start - -- Check existing issues - avoid duplicate work -- Create an issue - discuss your idea first -- Get feedback - ensure alignment with project goals -- Fork and branch - work on a feature branch - -### 💻 Code Standards - -#### JavaScript Style -```javascript -// ✅ Good -const encryptionKey = await crypto.subtle.generateKey({ - name: 'AES-GCM', - length: 256 -}, false, ['encrypt', 'decrypt']); - -// ❌ Bad -var key=crypto.subtle.generateKey({name:'AES-GCM',length:256},false,['encrypt','decrypt']) -``` - -#### Naming Conventions - -- **Functions:** camelCase - `generateSecureKey()` -- **Classes:** PascalCase - `EnhancedSecureCryptoUtils` -- **Constants:** UPPER_SNAKE_CASE - `MAX_MESSAGE_LENGTH` -- **Files:** kebab-case - `crypto-utils.js` - -### 📖 Documentation - -## 🔒 Security Considerations - -### Critical Areas -These areas require extra careful review: - -- **Cryptographic functions** - All crypto code must be reviewed -- **Key generation** - Entropy and randomness -- **Message handling** - Input validation and sanitization -- **P2P communication** - WebRTC security -- **Lightning integration** - Payment verification -- **ASN.1 validation** - Key structure verification (NEW) - -### Security Checklist - -## 🔐 ASN.1 Validation Framework (NEW) - -### Overview -SecureBit.chat v4.02.442 implements a complete ASN.1 DER parser and validation system. This framework requires special attention when contributing to cryptographic code. - -### Key Components - -#### **ASN1Validator Class** -```javascript -// Core validation class for cryptographic keys -class ASN1Validator { - constructor() { - this.supportedOIDs = { - '1.2.840.10045.3.1.7': 'P-256', // secp256r1 - '1.3.132.0.34': 'P-384' // secp384r1 - }; - this.maxKeySize = 2000; // bytes - this.minKeySize = 50; // bytes - } - - // Complete DER parsing and validation - validateKeyStructure(keyData) { - // Implementation details... - } -} -``` - -#### **Integration Points** -- **Key import operations** - All keys must pass ASN.1 validation -- **Key export operations** - Exported keys are validated -- **Real-time validation** - Continuous validation during operations - -### Contributing to ASN.1 Framework - -#### **Adding New Curve Support** -```javascript -// To add support for a new elliptic curve: -const newCurveOID = '1.3.132.0.XX'; // Replace XX with actual OID -const curveName = 'P-XXX'; // Replace XXX with curve name - -// Add to supportedOIDs -this.supportedOIDs[newCurveOID] = curveName; - -// Update validation logic if needed -// Ensure proper EC point format validation -``` - -#### **Extending Validation Rules** -```javascript -// To add new validation rules: -validateCustomRule(parsed) { - // Implement your validation logic - if (!this.checkCustomCondition(parsed)) { - throw new Error('Custom validation failed'); - } - return true; -} - -// Integrate with main validation -validateKeyStructure(keyData) { - const parsed = this.parseDER(keyData); - - // Existing validations... - if (!this.validateSPKI(parsed)) return false; - if (!this.validateOID(parsed)) return false; - if (!this.validateECPoint(parsed)) return false; - - // New custom validation - if (!this.validateCustomRule(parsed)) return false; - - return true; -} -``` - -### Testing ASN.1 Validation - -#### **Unit Tests** -```javascript -describe('ASN.1 Validation Framework', () => { - test('Validates correct P-384 key structure', () => { - const validKey = generateValidP384Key(); - expect(asn1Validator.validateKeyStructure(validKey)).toBe(true); - }); - - test('Rejects modified key with valid header', () => { - const modifiedKey = modifyKeyData(validKey); - expect(asn1Validator.validateKeyStructure(modifiedKey)).toBe(false); - }); - - test('Rejects unsupported curve OID', () => { - const invalidOIDKey = generateKeyWithInvalidOID(); - expect(asn1Validator.validateKeyStructure(invalidOIDKey)).toBe(false); - }); -}); -``` - -#### **Performance Tests** -```javascript -describe('ASN.1 Validation Performance', () => { - test('Validation completes within 10ms', () => { - const start = performance.now(); - asn1Validator.validateKeyStructure(validKey); - const duration = performance.now() - start; - expect(duration).toBeLessThan(10); - }); -}); -``` - -### Security Guidelines for ASN.1 Contributions - -#### **Critical Requirements** -1. **Never bypass validation** - All keys must pass complete ASN.1 validation -2. **Maintain strict OID checking** - Only support verified, secure algorithms -3. **Preserve size limits** - Key size limits prevent DoS attacks -4. **Validate all structural elements** - Complete verification is mandatory - -#### **Common Pitfalls to Avoid** -```javascript -// ❌ DON'T: Skip validation for performance -const fastImport = (keyData) => { - // Bypassing validation for speed - return crypto.subtle.importKey('spki', keyData, algorithm, false, ['verify']); -}; - -// ✅ DO: Always validate before processing -const secureImport = async (keyData) => { - if (!asn1Validator.validateKeyStructure(keyData)) { - throw new Error('Key validation failed'); - } - return await crypto.subtle.importKey('spki', keyData, algorithm, false, ['verify']); -}; -``` - -#### **Validation Order** -1. **Parse DER** - Complete ASN.1 structure parsing -2. **Validate SPKI** - SubjectPublicKeyInfo structure -3. **Validate OID** - Algorithm and curve verification -4. **Validate EC Point** - Format and structure verification -5. **Apply custom rules** - Any additional validation requirements - -### Breaking Changes and Compatibility - -#### **Version 4.02.442 Changes** -- **Enhanced key validation** now performs complete ASN.1 parsing -- **Stricter key acceptance** criteria for improved security -- **Fallback support** from P-384 to P-256 maintained -- **Backward compatibility** for valid key structures - -#### **Migration Considerations** -- **Existing keys** are validated on next use -- **New keys** must pass complete validation -- **Invalid keys** are rejected with clear error messages -- **Performance impact** is minimal (< 10ms per validation) - -### Documentation Requirements - -#### **Code Documentation** -```javascript -/** - * Validates cryptographic key structure using complete ASN.1 DER parsing - * - * @param {ArrayBuffer} keyData - Raw key data to validate - * @returns {boolean} - True if validation passes, false otherwise - * @throws {Error} - Detailed error message for validation failures - * - * @example - * const isValid = asn1Validator.validateKeyStructure(keyData); - * if (!isValid) { - * console.error('Key validation failed'); - * } - */ -validateKeyStructure(keyData) { - // Implementation... -} -``` - -#### **API Documentation** -- **Function signatures** with parameter types -- **Return values** and error conditions -- **Usage examples** for common scenarios -- **Performance characteristics** and limitations - -### Contributing Guidelines Summary - -#### **For ASN.1 Framework Contributions** -1. **Understand the security model** - Complete validation is mandatory -2. **Follow validation order** - Parse → SPKI → OID → EC Point → Custom -3. **Maintain performance** - Keep validation time under 10ms -4. **Add comprehensive tests** - Unit, integration, and performance tests -5. **Document thoroughly** - Code comments, API docs, and examples -6. **Consider breaking changes** - Ensure backward compatibility where possible - -#### **Security Review Process** -1. **Code review** by cryptographic experts -2. **Security testing** for validation bypass attempts -3. **Performance validation** for timing attacks -4. **Compatibility testing** with existing key formats -5. **Documentation review** for accuracy and completeness - ---- - -## 🚀 Getting Started - -### Prerequisites -- **Browser:** Modern browser with WebRTC and WebCrypto support -- **Git:** For version control -- **Text Editor:** VS Code, Vim, or your favorite editor -- **Lightning Wallet:** For testing payment features (optional) - -### Development Setup -```bash -# 1. Fork the repository on GitHub -# 2. Clone your fork -git clone https://github.com/yourusername/securebit-chat.git -cd securebit-chat - -# 3. Create a development branch -git checkout -b feature/your-feature-name - -# 4. Start development server -python -m http.server 8000 -# or -npx serve . - -# 5. Open http://localhost:8000 -# Make your changes -# Test thoroughly -# Commit with descriptive messages -git commit -m "feat: add quantum-resistant key exchange - -- Implement CRYSTALS-Kyber for post-quantum security -- Add fallback to classical ECDH -- Update security level calculations -- Add comprehensive test suite - -Closes #123" -``` - -## 📋 Contribution Guidelines - -### 🔍 Before You Start - -- Check existing issues - avoid duplicate work -- Create an issue - discuss your idea first -- Get feedback - ensure alignment with project goals -- Fork and branch - work on a feature branch - -### 💻 Code Standards - -#### JavaScript Style -```javascript -// ✅ Good -const encryptionKey = await crypto.subtle.generateKey({ - name: 'AES-GCM', - length: 256 -}, false, ['encrypt', 'decrypt']); - -// ❌ Bad -var key=crypto.subtle.generateKey({name:'AES-GCM',length:256},false,['encrypt','decrypt']) -``` - -#### Naming Conventions - -- **Functions:** camelCase - `generateSecureKey()` -- **Classes:** PascalCase - `EnhancedSecureCryptoUtils` -- **Constants:** UPPER_SNAKE_CASE - `MAX_MESSAGE_LENGTH` -- **Files:** kebab-case - `crypto-utils.js` - -### 📖 Documentation - -## 🔒 Security Considerations - -### Critical Areas -These areas require extra careful review: - -- **Cryptographic functions** - All crypto code must be reviewed -- **Key generation** - Entropy and randomness -- **Message handling** - Input validation and sanitization -- **P2P communication** - WebRTC security -- **Lightning integration** - Payment verification -- **ASN.1 validation** - Key structure verification (NEW) - -### Security Checklist - -## 🔐 ASN.1 Validation Framework (NEW) - -### Overview -SecureBit.chat v4.02.442 implements a complete ASN.1 DER parser and validation system. This framework requires special attention when contributing to cryptographic code. - -### Key Components - -#### **ASN1Validator Class** -```javascript -// Core validation class for cryptographic keys -class ASN1Validator { - constructor() { - this.supportedOIDs = { - '1.2.840.10045.3.1.7': 'P-256', // secp256r1 - '1.3.132.0.34': 'P-384' // secp384r1 - }; - this.maxKeySize = 2000; // bytes - this.minKeySize = 50; // bytes - } - - // Complete DER parsing and validation - validateKeyStructure(keyData) { - // Implementation details... - } -} -``` - -#### **Integration Points** -- **Key import operations** - All keys must pass ASN.1 validation -- **Key export operations** - Exported keys are validated -- **Real-time validation** - Continuous validation during operations - -### Contributing to ASN.1 Framework - -#### **Adding New Curve Support** -```javascript -// To add support for a new elliptic curve: -const newCurveOID = '1.3.132.0.XX'; // Replace XX with actual OID -const curveName = 'P-XXX'; // Replace XXX with curve name - -// Add to supportedOIDs -this.supportedOIDs[newCurveOID] = curveName; - -// Update validation logic if needed -// Ensure proper EC point format validation -``` - -#### **Extending Validation Rules** -```javascript -// To add new validation rules: -validateCustomRule(parsed) { - // Implement your validation logic - if (!this.checkCustomCondition(parsed)) { - throw new Error('Custom validation failed'); - } - return true; -} - -// Integrate with main validation -validateKeyStructure(keyData) { - const parsed = this.parseDER(keyData); - - // Existing validations... - if (!this.validateSPKI(parsed)) return false; - if (!this.validateOID(parsed)) return false; - if (!this.validateECPoint(parsed)) return false; - - // New custom validation - if (!this.validateCustomRule(parsed)) return false; - - return true; -} -``` - -### Testing ASN.1 Validation - -#### **Unit Tests** -```javascript -describe('ASN.1 Validation Framework', () => { - test('Validates correct P-384 key structure', () => { - const validKey = generateValidP384Key(); - expect(asn1Validator.validateKeyStructure(validKey)).toBe(true); - }); - - test('Rejects modified key with valid header', () => { - const modifiedKey = modifyKeyData(validKey); - expect(asn1Validator.validateKeyStructure(modifiedKey)).toBe(false); - }); - - test('Rejects unsupported curve OID', () => { - const invalidOIDKey = generateKeyWithInvalidOID(); - expect(asn1Validator.validateKeyStructure(invalidOIDKey)).toBe(false); - }); -}); -``` - -#### **Performance Tests** -```javascript -describe('ASN.1 Validation Performance', () => { - test('Validation completes within 10ms', () => { - const start = performance.now(); - asn1Validator.validateKeyStructure(validKey); - const duration = performance.now() - start; - expect(duration).toBeLessThan(10); - }); -}); -``` - -### Security Guidelines for ASN.1 Contributions - -#### **Critical Requirements** -1. **Never bypass validation** - All keys must pass complete ASN.1 validation -2. **Maintain strict OID checking** - Only support verified, secure algorithms -3. **Preserve size limits** - Key size limits prevent DoS attacks -4. **Validate all structural elements** - Complete verification is mandatory - -#### **Common Pitfalls to Avoid** -```javascript -// ❌ DON'T: Skip validation for performance -const fastImport = (keyData) => { - // Bypassing validation for speed - return crypto.subtle.importKey('spki', keyData, algorithm, false, ['verify']); -}; - -// ✅ DO: Always validate before processing -const secureImport = async (keyData) => { - if (!asn1Validator.validateKeyStructure(keyData)) { - throw new Error('Key validation failed'); - } - return await crypto.subtle.importKey('spki', keyData, algorithm, false, ['verify']); -}; -``` - -#### **Validation Order** -1. **Parse DER** - Complete ASN.1 structure parsing -2. **Validate SPKI** - SubjectPublicKeyInfo structure -3. **Validate OID** - Algorithm and curve verification -4. **Validate EC Point** - Format and structure verification -5. **Apply custom rules** - Any additional validation requirements - -### Breaking Changes and Compatibility - -#### **Version 4.02.442 Changes** -- **Enhanced key validation** now performs complete ASN.1 parsing -- **Stricter key acceptance** criteria for improved security -- **Fallback support** from P-384 to P-256 maintained -- **Backward compatibility** for valid key structures - -#### **Migration Considerations** -- **Existing keys** are validated on next use -- **New keys** must pass complete validation -- **Invalid keys** are rejected with clear error messages -- **Performance impact** is minimal (< 10ms per validation) - -### Documentation Requirements - -#### **Code Documentation** -```javascript -/** - * Validates cryptographic key structure using complete ASN.1 DER parsing - * - * @param {ArrayBuffer} keyData - Raw key data to validate - * @returns {boolean} - True if validation passes, false otherwise - * @throws {Error} - Detailed error message for validation failures - * - * @example - * const isValid = asn1Validator.validateKeyStructure(keyData); - * if (!isValid) { - * console.error('Key validation failed'); - * } - */ -validateKeyStructure(keyData) { - // Implementation... -} -``` - -#### **API Documentation** -- **Function signatures** with parameter types -- **Return values** and error conditions -- **Usage examples** for common scenarios -- **Performance characteristics** and limitations - -### Contributing Guidelines Summary - -#### **For ASN.1 Framework Contributions** -1. **Understand the security model** - Complete validation is mandatory -2. **Follow validation order** - Parse → SPKI → OID → EC Point → Custom -3. **Maintain performance** - Keep validation time under 10ms -4. **Add comprehensive tests** - Unit, integration, and performance tests -5. **Document thoroughly** - Code comments, API docs, and examples -6. **Consider breaking changes** - Ensure backward compatibility where possible - -#### **Security Review Process** -1. **Code review** by cryptographic experts -2. **Security testing** for validation bypass attempts -3. **Performance validation** for timing attacks -4. **Compatibility testing** with existing key formats -5. **Documentation review** for accuracy and completeness - ---- - -## 🚀 Getting Started - -### Prerequisites -- **Browser:** Modern browser with WebRTC and WebCrypto support -- **Git:** For version control -- **Text Editor:** VS Code, Vim, or your favorite editor -- **Lightning Wallet:** For testing payment features (optional) - -### Development Setup -```bash -# 1. Fork the repository on GitHub -# 2. Clone your fork -git clone https://github.com/yourusername/securebit-chat.git -cd securebit-chat - -# 3. Create a development branch -git checkout -b feature/your-feature-name - -# 4. Start development server -python -m http.server 8000 -# or -npx serve . - -# 5. Open http://localhost:8000 -# Make your changes -# Test thoroughly -# Commit with descriptive messages -git commit -m "feat: add quantum-resistant key exchange - -- Implement CRYSTALS-Kyber for post-quantum security -- Add fallback to classical ECDH -- Update security level calculations -- Add comprehensive test suite - -Closes #123" -``` - -## 📋 Contribution Guidelines - -### 🔍 Before You Start - -- Check existing issues - avoid duplicate work -- Create an issue - discuss your idea first -- Get feedback - ensure alignment with project goals -- Fork and branch - work on a feature branch - -### 💻 Code Standards - -#### JavaScript Style -```javascript -// ✅ Good -const encryptionKey = await crypto.subtle.generateKey({ - name: 'AES-GCM', - length: 256 -}, false, ['encrypt', 'decrypt']); - -// ❌ Bad -var key=crypto.subtle.generateKey({name:'AES-GCM',length:256},false,['encrypt','decrypt']) -``` - -#### Naming Conventions - -- **Functions:** camelCase - `generateSecureKey()` -- **Classes:** PascalCase - `EnhancedSecureCryptoUtils` -- **Constants:** UPPER_SNAKE_CASE - `MAX_MESSAGE_LENGTH` -- **Files:** kebab-case - `crypto-utils.js` - -### 📖 Documentation - -## 🔒 Security Considerations - -### Critical Areas -These areas require extra careful review: - -- **Cryptographic functions** - All crypto code must be reviewed -- **Key generation** - Entropy and randomness -- **Message handling** - Input validation and sanitization -- **P2P communication** - WebRTC security -- **Lightning integration** - Payment verification -- **ASN.1 validation** - Key structure verification (NEW) - -### Security Checklist - -## 🔐 ASN.1 Validation Framework (NEW) - -### Overview -SecureBit.chat v4.02.442 implements a complete ASN.1 DER parser and validation system. This framework requires special attention when contributing to cryptographic code. - -### Key Components - -#### **ASN1Validator Class** -```javascript -// Core validation class for cryptographic keys -class ASN1Validator { - constructor() { - this.supportedOIDs = { - '1.2.840.10045.3.1.7': 'P-256', // secp256r1 - '1.3.132.0.34': 'P-384' // secp384r1 - }; - this.maxKeySize = 2000; // bytes - this.minKeySize = 50; // bytes - } - - // Complete DER parsing and validation - validateKeyStructure(keyData) { - // Implementation details... - } -} -``` - -#### **Integration Points** -- **Key import operations** - All keys must pass ASN.1 validation -- **Key export operations** - Exported keys are validated -- **Real-time validation** - Continuous validation during operations - -### Contributing to ASN.1 Framework - -#### **Adding New Curve Support** -```javascript -// To add support for a new elliptic curve: -const newCurveOID = '1.3.132.0.XX'; // Replace XX with actual OID -const curveName = 'P-XXX'; // Replace XXX with curve name - -// Add to supportedOIDs -this.supportedOIDs[newCurveOID] = curveName; - -// Update validation logic if needed -// Ensure proper EC point format validation -``` - -#### **Extending Validation Rules** -```javascript -// To add new validation rules: -validateCustomRule(parsed) { - // Implement your validation logic - if (!this.checkCustomCondition(parsed)) { - throw new Error('Custom validation failed'); - } - return true; -} - -// Integrate with main validation -validateKeyStructure(keyData) { - const parsed = this.parseDER(keyData); - - // Existing validations... - if (!this.validateSPKI(parsed)) return false; - if (!this.validateOID(parsed)) return false; - if (!this.validateECPoint(parsed)) return false; - - // New custom validation - if (!this.validateCustomRule(parsed)) return false; - - return true; -} -``` - -### Testing ASN.1 Validation - -#### **Unit Tests** -```javascript -describe('ASN.1 Validation Framework', () => { - test('Validates correct P-384 key structure', () => { - const validKey = generateValidP384Key(); - expect(asn1Validator.validateKeyStructure(validKey)).toBe(true); - }); - - test('Rejects modified key with valid header', () => { - const modifiedKey = modifyKeyData(validKey); - expect(asn1Validator.validateKeyStructure(modifiedKey)).toBe(false); - }); - - test('Rejects unsupported curve OID', () => { - const invalidOIDKey = generateKeyWithInvalidOID(); - expect(asn1Validator.validateKeyStructure(invalidOIDKey)).toBe(false); - }); -}); -``` - -#### **Performance Tests** -```javascript -describe('ASN.1 Validation Performance', () => { - test('Validation completes within 10ms', () => { - const start = performance.now(); - asn1Validator.validateKeyStructure(validKey); - const duration = performance.now() - start; - expect(duration).toBeLessThan(10); - }); -}); -``` - -### Security Guidelines for ASN.1 Contributions - -#### **Critical Requirements** -1. **Never bypass validation** - All keys must pass complete ASN.1 validation -2. **Maintain strict OID checking** - Only support verified, secure algorithms -3. **Preserve size limits** - Key size limits prevent DoS attacks -4. **Validate all structural elements** - Complete verification is mandatory - -#### **Common Pitfalls to Avoid** -```javascript -// ❌ DON'T: Skip validation for performance -const fastImport = (keyData) => { - // Bypassing validation for speed - return crypto.subtle.importKey('spki', keyData, algorithm, false, ['verify']); -}; - -// ✅ DO: Always validate before processing -const secureImport = async (keyData) => { - if (!asn1Validator.validateKeyStructure(keyData)) { - throw new Error('Key validation failed'); - } - return await crypto.subtle.importKey('spki', keyData, algorithm, false, ['verify']); -}; -``` - -#### **Validation Order** -1. **Parse DER** - Complete ASN.1 structure parsing -2. **Validate SPKI** - SubjectPublicKeyInfo structure -3. **Validate OID** - Algorithm and curve verification -4. **Validate EC Point** - Format and structure verification -5. **Apply custom rules** - Any additional validation requirements - -### Breaking Changes and Compatibility - -#### **Version 4.02.442 Changes** -- **Enhanced key validation** now performs complete ASN.1 parsing -- **Stricter key acceptance** criteria for improved security -- **Fallback support** from P-384 to P-256 maintained -- **Backward compatibility** for valid key structures - -#### **Migration Considerations** -- **Existing keys** are validated on next use -- **New keys** must pass complete validation -- **Invalid keys** are rejected with clear error messages -- **Performance impact** is minimal (< 10ms per validation) - -### Documentation Requirements - -#### **Code Documentation** -```javascript -/** - * Validates cryptographic key structure using complete ASN.1 DER parsing - * - * @param {ArrayBuffer} keyData - Raw key data to validate - * @returns {boolean} - True if validation passes, false otherwise - * @throws {Error} - Detailed error message for validation failures - * - * @example - * const isValid = asn1Validator.validateKeyStructure(keyData); - * if (!isValid) { - * console.error('Key validation failed'); - * } - */ -validateKeyStructure(keyData) { - // Implementation... -} -``` - -#### **API Documentation** -- **Function signatures** with parameter types -- **Return values** and error conditions -- **Usage examples** for common scenarios -- **Performance characteristics** and limitations - -### Contributing Guidelines Summary - -#### **For ASN.1 Framework Contributions** -1. **Understand the security model** - Complete validation is mandatory -2. **Follow validation order** - Parse → SPKI → OID → EC Point → Custom -3. **Maintain performance** - Keep validation time under 10ms -4. **Add comprehensive tests** - Unit, integration, and performance tests -5. **Document thoroughly** - Code comments, API docs, and examples -6. **Consider breaking changes** - Ensure backward compatibility where possible - -#### **Security Review Process** -1. **Code review** by cryptographic experts -2. **Security testing** for validation bypass attempts -3. **Performance validation** for timing attacks -4. **Compatibility testing** with existing key formats -5. **Documentation review** for accuracy and completeness - ---- - -## 🚀 Getting Started - -### Prerequisites -- **Browser:** Modern browser with WebRTC and WebCrypto support -- **Git:** For version control -- **Text Editor:** VS Code, Vim, or your favorite editor -- **Lightning Wallet:** For testing payment features (optional) - -### Development Setup -```bash -# 1. Fork the repository on GitHub -# 2. Clone your fork -git clone https://github.com/yourusername/securebit-chat.git -cd securebit-chat - -# 3. Create a development branch -git checkout -b feature/your-feature-name - -# 4. Start development server -python -m http.server 8000 -# or -npx serve . - -# 5. Open http://localhost:8000 -# Make your changes -# Test thoroughly -# Commit with descriptive messages -git commit -m "feat: add quantum-resistant key exchange - -- Implement CRYSTALS-Kyber for post-quantum security -- Add fallback to classical ECDH -- Update security level calculations -- Add comprehensive test suite - -Closes #123" -``` - -## 📋 Contribution Guidelines - -### 🔍 Before You Start - -- Check existing issues - avoid duplicate work -- Create an issue - discuss your idea first -- Get feedback - ensure alignment with project goals -- Fork and branch - work on a feature branch - -### 💻 Code Standards - -#### JavaScript Style -```javascript -// ✅ Good -const encryptionKey = await crypto.subtle.generateKey({ - name: 'AES-GCM', - length: 256 -}, false, ['encrypt', 'decrypt']); - -// ❌ Bad -var key=crypto.subtle.generateKey({name:'AES-GCM',length:256},false,['encrypt','decrypt']) -``` - -#### Naming Conventions - -- **Functions:** camelCase - `generateSecureKey()` -- **Classes:** PascalCase - `EnhancedSecureCryptoUtils` -- **Constants:** UPPER_SNAKE_CASE - `MAX_MESSAGE_LENGTH` -- **Files:** kebab-case - `crypto-utils.js` - -### 📖 Documentation - -## 🔒 Security Considerations - -### Critical Areas -These areas require extra careful review: - -- **Cryptographic functions** - All crypto code must be reviewed -- **Key generation** - Entropy and randomness -- **Message handling** - Input validation and sanitization -- **P2P communication** - WebRTC security -- **Lightning integration** - Payment verification -- **ASN.1 validation** - Key structure verification (NEW) - -### Security Checklist - -## 🔐 ASN.1 Validation Framework (NEW) - -### Overview -SecureBit.chat v4.02.442 implements a complete ASN.1 DER parser and validation system. This framework requires special attention when contributing to cryptographic code. - -### Key Components - -#### **ASN1Validator Class** -```javascript -// Core validation class for cryptographic keys -class ASN1Validator { - constructor() { - this.supportedOIDs = { - '1.2.840.10045.3.1.7': 'P-256', // secp256r1 - '1.3.132.0.34': 'P-384' // secp384r1 - }; - this.maxKeySize = 2000; // bytes - this.minKeySize = 50; // bytes - } - - // Complete DER parsing and validation - validateKeyStructure(keyData) { - // Implementation details... - } -} -``` - -#### **Integration Points** -- **Key import operations** - All keys must pass ASN.1 validation -- **Key export operations** - Exported keys are validated -- **Real-time validation** - Continuous validation during operations - -### Contributing to ASN.1 Framework - -#### **Adding New Curve Support** -```javascript -// To add support for a new elliptic curve: -const newCurveOID = '1.3.132.0.XX'; // Replace XX with actual OID -const curveName = 'P-XXX'; // Replace XXX with curve name - -// Add to supportedOIDs -this.supportedOIDs[newCurveOID] = curveName; - -// Update validation logic if needed -// Ensure proper EC point format validation -``` - -#### **Extending Validation Rules** -```javascript -// To add new validation rules: -validateCustomRule(parsed) { - // Implement your validation logic - if (!this.checkCustomCondition(parsed)) { - throw new Error('Custom validation failed'); - } - return true; -} - -// Integrate with main validation -validateKeyStructure(keyData) { - const parsed = this.parseDER(keyData); - - // Existing validations... - if (!this.validateSPKI(parsed)) return false; - if (!this.validateOID(parsed)) return false; - if (!this.validateECPoint(parsed)) return false; - - // New custom validation - if (!this.validateCustomRule(parsed)) return false; - - return true; -} -``` - -### Testing ASN.1 Validation - -#### **Unit Tests** -```javascript -describe('ASN.1 Validation Framework', () => { - test('Validates correct P-384 key structure', () => { - const validKey = generateValidP384Key(); - expect(asn1Validator.validateKeyStructure(validKey)).toBe(true); - }); - - test('Rejects modified key with valid header', () => { - const modifiedKey = modifyKeyData(validKey); - expect(asn1Validator.validateKeyStructure(modifiedKey)).toBe(false); - }); - - test('Rejects unsupported curve OID', () => { - const invalidOIDKey = generateKeyWithInvalidOID(); - expect(asn1Validator.validateKeyStructure(invalidOIDKey)).toBe(false); - }); -}); -``` - -#### **Performance Tests** -```javascript -describe('ASN.1 Validation Performance', () => { - test('Validation completes within 10ms', () => { - const start = performance.now(); - asn1Validator.validateKeyStructure(validKey); - const duration = performance.now() - start; - expect(duration).toBeLessThan(10); - }); -}); -``` - -### Security Guidelines for ASN.1 Contributions - -#### **Critical Requirements** -1. **Never bypass validation** - All keys must pass complete ASN.1 validation -2. **Maintain strict OID checking** - Only support verified, secure algorithms -3. **Preserve size limits** - Key size limits prevent DoS attacks -4. **Validate all structural elements** - Complete verification is mandatory - -#### **Common Pitfalls to Avoid** -```javascript -// ❌ DON'T: Skip validation for performance -const fastImport = (keyData) => { - // Bypassing validation for speed - return crypto.subtle.importKey('spki', keyData, algorithm, false, ['verify']); -}; - -// ✅ DO: Always validate before processing -const secureImport = async (keyData) => { - if (!asn1Validator.validateKeyStructure(keyData)) { - throw new Error('Key validation failed'); - } - return await crypto.subtle.importKey('spki', keyData, algorithm, false, ['verify']); -}; -``` - -#### **Validation Order** -1. **Parse DER** - Complete ASN.1 structure parsing -2. **Validate SPKI** - SubjectPublicKeyInfo structure -3. **Validate OID** - Algorithm and curve verification -4. **Validate EC Point** - Format and structure verification -5. **Apply custom rules** - Any additional validation requirements - -### Breaking Changes and Compatibility - -#### **Version 4.02.442 Changes** -- **Enhanced key validation** now performs complete ASN.1 parsing -- **Stricter key acceptance** criteria for improved security -- **Fallback support** from P-384 to P-256 maintained -- **Backward compatibility** for valid key structures - -#### **Migration Considerations** -- **Existing keys** are validated on next use -- **New keys** must pass complete validation -- **Invalid keys** are rejected with clear error messages -- **Performance impact** is minimal (< 10ms per validation) - -### Documentation Requirements - -#### **Code Documentation** -```javascript -/** - * Validates cryptographic key structure using complete ASN.1 DER parsing - * - * @param {ArrayBuffer} keyData - Raw key data to validate - * @returns {boolean} - True if validation passes, false otherwise - * @throws {Error} - Detailed error message for validation failures - * - * @example - * const isValid = asn1Validator.validateKeyStructure(keyData); - * if (!isValid) { - * console.error('Key validation failed'); - * } - */ -validateKeyStructure(keyData) { - // Implementation... -} -``` - -#### **API Documentation** -- **Function signatures** with parameter types -- **Return values** and error conditions -- **Usage examples** for common scenarios -- **Performance characteristics** and limitations - -### Contributing Guidelines Summary - -#### **For ASN.1 Framework Contributions** -1. **Understand the security model** - Complete validation is mandatory -2. **Follow validation order** - Parse → SPKI → OID → EC Point → Custom -3. **Maintain performance** - Keep validation time under 10ms -4. **Add comprehensive tests** - Unit, integration, and performance tests -5. **Document thoroughly** - Code comments, API docs, and examples -6. **Consider breaking changes** - Ensure backward compatibility where possible - -#### **Security Review Process** -1. **Code review** by cryptographic experts -2. **Security testing** for validation bypass attempts -3. **Performance validation** for timing attacks -4. **Compatibility testing** with existing key formats -5. **Documentation review** for accuracy and completeness - ---- - -## 🚀 Getting Started - -### Prerequisites -- **Browser:** Modern browser with WebRTC and WebCrypto support -- **Git:** For version control -- **Text Editor:** VS Code, Vim, or your favorite editor -- **Lightning Wallet:** For testing payment features (optional) - -### Development Setup -```bash -# 1. Fork the repository on GitHub -# 2. Clone your fork -git clone https://github.com/yourusername/securebit-chat.git -cd securebit-chat - -# 3. Create a development branch -git checkout -b feature/your-feature-name - -# 4. Start development server -python -m http.server 8000 -# or -npx serve . - -# 5. Open http://localhost:8000 -# Make your changes -# Test thoroughly -# Commit with descriptive messages -git commit -m "feat: add quantum-resistant key exchange - -- Implement CRYSTALS-Kyber for post-quantum security -- Add fallback to classical ECDH -- Update security level calculations -- Add comprehensive test suite - -Closes #123" -``` - -## 📋 Contribution Guidelines - -### 🔍 Before You Start - -- Check existing issues - avoid duplicate work -- Create an issue - discuss your idea first -- Get feedback - ensure alignment with project goals -- Fork and branch - work on a feature branch - -### 💻 Code Standards - -#### JavaScript Style -```javascript -// ✅ Good -const encryptionKey = await crypto.subtle.generateKey({ - name: 'AES-GCM', - length: 256 -}, false, ['encrypt', 'decrypt']); - -// ❌ Bad -var key=crypto.subtle.generateKey({name:'AES-GCM',length:256},false,['encrypt','decrypt']) -``` - -#### Naming Conventions - -- **Functions:** camelCase - `generateSecureKey()` -- **Classes:** PascalCase - `EnhancedSecureCryptoUtils` -- **Constants:** UPPER_SNAKE_CASE - `MAX_MESSAGE_LENGTH` -- **Files:** kebab-case - `crypto-utils.js` - -### 📖 Documentation - -## 🔒 Security Considerations - -### Critical Areas -These areas require extra careful review: - -- **Cryptographic functions** - All crypto code must be reviewed -- **Key generation** - Entropy and randomness -- **Message handling** - Input validation and sanitization -- **P2P communication** - WebRTC security -- **Lightning integration** - Payment verification -- **ASN.1 validation** - Key structure verification (NEW) - -### Security Checklist - -## 🔐 ASN.1 Validation Framework (NEW) - -### Overview -SecureBit.chat v4.02.442 implements a complete ASN.1 DER parser and validation system. This framework requires special attention when contributing to cryptographic code. - -### Key Components - -#### **ASN1Validator Class** -```javascript -// Core validation class for cryptographic keys -class ASN1Validator { - constructor() { - this.supportedOIDs = { - '1.2.840.10045.3.1.7': 'P-256', // secp256r1 - '1.3.132.0.34': 'P-384' // secp384r1 - }; - this.maxKeySize = 2000; // bytes - this.minKeySize = 50; // bytes - } - - // Complete DER parsing and validation - validateKeyStructure(keyData) { - // Implementation details... - } -} -``` - -#### **Integration Points** -- **Key import operations** - All keys must pass ASN.1 validation -- **Key export operations** - Exported keys are validated -- **Real-time validation** - Continuous validation during operations - -### Contributing to ASN.1 Framework - -#### **Adding New Curve Support** -```javascript -// To add support for a new elliptic curve: -const newCurveOID = '1.3.132.0.XX'; // Replace XX with actual OID -const curveName = 'P-XXX'; // Replace XXX with curve name - -// Add to supportedOIDs -this.supportedOIDs[newCurveOID] = curveName; - -// Update validation logic if needed -// Ensure proper EC point format validation -``` - -#### **Extending Validation Rules** -```javascript -// To add new validation rules: -validateCustomRule(parsed) { - // Implement your validation logic - if (!this.checkCustomCondition(parsed)) { - throw new Error('Custom validation failed'); - } - return true; -} - -// Integrate with main validation -validateKeyStructure(keyData) { - const parsed = this.parseDER(keyData); - - // Existing validations... - if (!this.validateSPKI(parsed)) return false; - if (!this.validateOID(parsed)) return false; - if (!this.validateECPoint(parsed)) return false; - - // New custom validation - if (!this.validateCustomRule(parsed)) return false; - - return true; -} -``` - -### Testing ASN.1 Validation - -#### **Unit Tests** -```javascript -describe('ASN.1 Validation Framework', () => { - test('Validates correct P-384 key structure', () => { - const validKey = generateValidP384Key(); - expect(asn1Validator.validateKeyStructure(validKey)).toBe(true); - }); - - test('Rejects modified key with valid header', () => { - const modifiedKey = modifyKeyData(validKey); - expect(asn1Validator.validateKeyStructure(modifiedKey)).toBe(false); - }); - - test('Rejects unsupported curve OID', () => { - const invalidOIDKey = generateKeyWithInvalidOID(); - expect(asn1Validator.validateKeyStructure(invalidOIDKey)).toBe(false); - }); -}); -``` - -#### **Performance Tests** -```javascript -describe('ASN.1 Validation Performance', () => { - test('Validation completes within 10ms', () => { - const start = performance.now(); - asn1Validator.validateKeyStructure(validKey); - const duration = performance.now() - start; - expect(duration).toBeLessThan(10); - }); -}); -``` - -### Security Guidelines for ASN.1 Contributions - -#### **Critical Requirements** -1. **Never bypass validation** - All keys must pass complete ASN.1 validation -2. **Maintain strict OID checking** - Only support verified, secure algorithms -3. **Preserve size limits** - Key size limits prevent DoS attacks -4. **Validate all structural elements** - Complete verification is mandatory - -#### **Common Pitfalls to Avoid** -```javascript -// ❌ DON'T: Skip validation for performance -const fastImport = (keyData) => { - // Bypassing validation for speed - return crypto.subtle.importKey('spki', keyData, algorithm, false, ['verify']); -}; - -// ✅ DO: Always validate before processing -const secureImport = async (keyData) => { - if (!asn1Validator.validateKeyStructure(keyData)) { - throw new Error('Key validation failed'); - } - return await crypto.subtle.importKey('spki', keyData, algorithm, false, ['verify']); -}; -``` - -#### **Validation Order** -1. **Parse DER** - Complete ASN.1 structure parsing -2. **Validate SPKI** - SubjectPublicKeyInfo structure -3. **Validate OID** - Algorithm and curve verification -4. **Validate EC Point** - Format and structure verification -5. **Apply custom rules** - Any additional validation requirements - -### Breaking Changes and Compatibility - -#### **Version 4.02.442 Changes** -- **Enhanced key validation** now performs complete ASN.1 parsing -- **Stricter key acceptance** criteria for improved security -- **Fallback support** from P-384 to P-256 maintained -- **Backward compatibility** for valid key structures - -#### **Migration Considerations** -- **Existing keys** are validated on next use -- **New keys** must pass complete validation -- **Invalid keys** are rejected with clear error messages -- **Performance impact** is minimal (< 10ms per validation) - -### Documentation Requirements - -#### **Code Documentation** -```javascript -/** - * Validates cryptographic key structure using complete ASN.1 DER parsing - * - * @param {ArrayBuffer} keyData - Raw key data to validate - * @returns {boolean} - True if validation passes, false otherwise - * @throws {Error} - Detailed error message for validation failures - * - * @example - * const isValid = asn1Validator.validateKeyStructure(keyData); - * if (!isValid) { - * console.error('Key validation failed'); - * } - */ -validateKeyStructure(keyData) { - // Implementation... -} -``` - -#### **API Documentation** -- **Function signatures** with parameter types -- **Return values** and error conditions -- **Usage examples** for common scenarios -- **Performance characteristics** and limitations - -### Contributing Guidelines Summary - -#### **For ASN.1 Framework Contributions** -1. **Understand the security model** - Complete validation is mandatory -2. **Follow validation order** - Parse → SPKI → OID → EC Point → Custom -3. **Maintain performance** - Keep validation time under 10ms -4. **Add comprehensive tests** - Unit, integration, and performance tests -5. **Document thoroughly** - Code comments, API docs, and examples -6. **Consider breaking changes** - Ensure backward compatibility where possible - -#### **Security Review Process** -1. **Code review** by cryptographic experts -2. **Security testing** for validation bypass attempts -3. **Performance validation** for timing attacks -4. **Compatibility testing** with existing key formats -5. **Documentation review** for accuracy and completeness - ---- - -## 🚀 Getting Started - -### Prerequisites -- **Browser:** Modern browser with WebRTC and WebCrypto support -- **Git:** For version control -- **Text Editor:** VS Code, Vim, or your favorite editor -- **Lightning Wallet:** For testing payment features (optional) - -### Development Setup -```bash -# 1. Fork the repository on GitHub -# 2. Clone your fork -git clone https://github.com/yourusername/securebit-chat.git -cd securebit-chat - -# 3. Create a development branch -git checkout -b feature/your-feature-name - -# 4. Start development server -python -m http.server 8000 -# or -npx serve . - -# 5. Open http://localhost:8000 -# Make your changes -# Test thoroughly -# Commit with descriptive messages -git commit -m "feat: add quantum-resistant key exchange - -- Implement CRYSTALS-Kyber for post-quantum security -- Add fallback to classical ECDH -- Update security level calculations -- Add comprehensive test suite - -Closes #123" -``` - -## 📋 Contribution Guidelines - -### 🔍 Before You Start - -- Check existing issues - avoid duplicate work -- Create an issue - discuss your idea first -- Get feedback - ensure alignment with project goals -- Fork and branch - work on a feature branch - -### 💻 Code Standards - -#### JavaScript Style -```javascript -// ✅ Good -const encryptionKey = await crypto.subtle.generateKey({ - name: 'AES-GCM', - length: 256 -}, false, ['encrypt', 'decrypt']); - -// ❌ Bad -var key=crypto.subtle.generateKey({name:'AES-GCM',length:256},false,['encrypt','decrypt']) -``` - -#### Naming Conventions - -- **Functions:** camelCase - `generateSecureKey()` -- **Classes:** PascalCase - `EnhancedSecureCryptoUtils` -- **Constants:** UPPER_SNAKE_CASE - `MAX_MESSAGE_LENGTH` -- **Files:** kebab-case - `crypto-utils.js` - -### 📖 Documentation - -## 🔒 Security Considerations - -### Critical Areas -These areas require extra careful review: - -- **Cryptographic functions** - All crypto code must be reviewed -- **Key generation** - Entropy and randomness -- **Message handling** - Input validation and sanitization -- **P2P communication** - WebRTC security -- **Lightning integration** - Payment verification -- **ASN.1 validation** - Key structure verification (NEW) - -### Security Checklist - -## 🔐 ASN.1 Validation Framework (NEW) - -### Overview -SecureBit.chat v4.02.442 implements a complete ASN.1 DER parser and validation system. This framework requires special attention when contributing to cryptographic code. - -### Key Components - -#### **ASN1Validator Class** -```javascript -// Core validation class for cryptographic keys -class ASN1Validator { - constructor() { - this.supportedOIDs = { - '1.2.840.10045.3.1.7': 'P-256', // secp256r1 - '1.3.132.0.34': 'P-384' // secp384r1 - }; - this.maxKeySize = 2000; // bytes - this.minKeySize = 50; // bytes - } - - // Complete DER parsing and validation - validateKeyStructure(keyData) { - // Implementation details... - } -} -``` - -#### **Integration Points** -- **Key import operations** - All keys must pass ASN.1 validation -- **Key export operations** - Exported keys are validated -- **Real-time validation** - Continuous validation during operations - -### Contributing to ASN.1 Framework - -#### **Adding New Curve Support** -```javascript -// To add support for a new elliptic curve: -const newCurveOID = '1.3.132.0.XX'; // Replace XX with actual OID -const curveName = 'P-XXX'; // Replace XXX with curve name - -// Add to supportedOIDs -this.supportedOIDs[newCurveOID] = curveName; - -// Update validation logic if needed -// Ensure proper EC point format validation -``` - -#### **Extending Validation Rules** -```javascript -// To add new validation rules: -validateCustomRule(parsed) { - // Implement your validation logic - if (!this.checkCustomCondition(parsed)) { - throw new Error('Custom validation failed'); - } - return true; -} - -// Integrate with main validation -validateKeyStructure(keyData) { - const parsed = this.parseDER(keyData); - - // Existing validations... - if (!this.validateSPKI(parsed)) return false; - if (!this.validateOID(parsed)) return false; - if (!this.validateECPoint(parsed)) return false; - - // New custom validation - if (!this.validateCustomRule(parsed)) return false; - - return true; -} -``` - -### Testing ASN.1 Validation - -#### **Unit Tests** -```javascript -describe('ASN.1 Validation Framework', () => { - test('Validates correct P-384 key structure', () => { - const validKey = generateValidP384Key(); - expect(asn1Validator.validateKeyStructure(validKey)).toBe(true); - }); - - test('Rejects modified key with valid header', () => { - const modifiedKey = modifyKeyData(validKey); - expect(asn1Validator.validateKeyStructure(modifiedKey)).toBe(false); - }); - - test('Rejects unsupported curve OID', () => { - const invalidOIDKey = generateKeyWithInvalidOID(); - expect(asn1Validator.validateKeyStructure(invalidOIDKey)).toBe(false); - }); -}); -``` - -#### **Performance Tests** -```javascript -describe('ASN.1 Validation Performance', () => { - test('Validation completes within 10ms', () => { - const start = performance.now(); - asn1Validator.validateKeyStructure(validKey); - const duration = performance.now() - start; - expect(duration).toBeLessThan(10); - }); -}); -``` - -### Security Guidelines for ASN.1 Contributions - -#### **Critical Requirements** -1. **Never bypass validation** - All keys must pass complete ASN.1 validation -2. **Maintain strict OID checking** - Only support verified, secure algorithms -3. **Preserve size limits** - Key size limits prevent DoS attacks -4. **Validate all structural elements** - Complete verification is mandatory - -#### **Common Pitfalls to Avoid** -```javascript -// ❌ DON'T: Skip validation for performance -const fastImport = (keyData) => { - // Bypassing validation for speed - return crypto.subtle.importKey('spki', keyData, algorithm, false, ['verify']); -}; - -// ✅ DO: Always validate before processing -const secureImport = async (keyData) => { - if (!asn1Validator.validateKeyStructure(keyData)) { - throw new Error('Key validation failed'); - } - return await crypto.subtle.importKey('spki', keyData, algorithm, false, ['verify']); -}; -``` - -#### **Validation Order** -1. **Parse DER** - Complete ASN.1 structure parsing -2. **Validate SPKI** - SubjectPublicKeyInfo structure -3. **Validate OID** - Algorithm and curve verification -4. **Validate EC Point** - Format and structure verification -5. **Apply custom rules** - Any additional validation requirements - -### Breaking Changes and Compatibility - -#### **Version 4.02.442 Changes** -- **Enhanced key validation** now performs complete ASN.1 parsing -- **Stricter key acceptance** criteria for improved security -- **Fallback support** from P-384 to P-256 maintained -- **Backward compatibility** for valid key structures - -#### **Migration Considerations** -- **Existing keys** are validated on next use -- **New keys** must pass complete validation -- **Invalid keys** are rejected with clear error messages -- **Performance impact** is minimal (< 10ms per validation) - -### Documentation Requirements - -#### **Code Documentation** -```javascript -/** - * Validates cryptographic key structure using complete ASN.1 DER parsing - * - * @param {ArrayBuffer} keyData - Raw key data to validate - * @returns {boolean} - True if validation passes, false otherwise - * @throws {Error} - Detailed error message for validation failures - * - * @example - * const isValid = asn1Validator.validateKeyStructure(keyData); - * if (!isValid) { - * console.error('Key validation failed'); - * } - */ -validateKeyStructure(keyData) { - // Implementation... -} -``` - -#### **API Documentation** -- **Function signatures** with parameter types -- **Return values** and error conditions -- **Usage examples** for common scenarios -- **Performance characteristics** and limitations - -### Contributing Guidelines Summary - -#### **For ASN.1 Framework Contributions** -1. **Understand the security model** - Complete validation is mandatory -2. **Follow validation order** - Parse → SPKI → OID → EC Point → Custom -3. **Maintain performance** - Keep validation time under 10ms -4. **Add comprehensive tests** - Unit, integration, and performance tests -5. **Document thoroughly** - Code comments, API docs, and examples -6. **Consider breaking changes** - Ensure backward compatibility where possible - -#### **Security Review Process** -1. **Code review** by cryptographic experts -2. **Security testing** for validation bypass attempts -3. **Performance validation** for timing attacks -4. **Compatibility testing** with existing key formats -5. **Documentation review** for accuracy and completeness - ---- - -## 🚀 Getting Started - -### Prerequisites -- **Browser:** Modern browser with WebRTC and WebCrypto support -- **Git:** For version control -- **Text Editor:** VS Code, Vim, or your favorite editor -- **Lightning Wallet:** For testing payment features (optional) - -### Development Setup -```bash -# 1. Fork the repository on GitHub -# 2. Clone your fork -git clone https://github.com/yourusername/securebit-chat.git -cd securebit-chat - -# 3. Create a development branch -git checkout -b feature/your-feature-name - -# 4. Start development server -python -m http.server 8000 -# or -npx serve . - -# 5. Open http://localhost:8000 -# Make your changes -# Test thoroughly -# Commit with descriptive messages -git commit -m "feat: add quantum-resistant key exchange - -- Implement CRYSTALS-Kyber for post-quantum security -- Add fallback to classical ECDH -- Update security level calculations -- Add comprehensive test suite - -Closes #123" -``` - -## 📋 Contribution Guidelines - -### 🔍 Before You Start - -- Check existing issues - avoid duplicate work -- Create an issue - discuss your idea first -- Get feedback - ensure alignment with project goals -- Fork and branch - work on a feature branch - -### 💻 Code Standards - -#### JavaScript Style -```javascript -// ✅ Good -const encryptionKey = await crypto.subtle.generateKey({ - name: 'AES-GCM', - length: 256 -}, false, ['encrypt', 'decrypt']); - -// ❌ Bad -var key=crypto.subtle.generateKey({name:'AES-GCM',length:256},false,['encrypt','decrypt']) -``` - -#### Naming Conventions - -- **Functions:** camelCase - `generateSecureKey()` -- **Classes:** PascalCase - `EnhancedSecureCryptoUtils` -- **Constants:** UPPER_SNAKE_CASE - `MAX_MESSAGE_LENGTH` -- **Files:** kebab-case - `crypto-utils.js` - -### 📖 Documentation - -## 🔒 Security Considerations - -### Critical Areas -These areas require extra careful review: - -- **Cryptographic functions** - All crypto code must be reviewed -- **Key generation** - Entropy and randomness -- **Message handling** - Input validation and sanitization -- **P2P communication** - WebRTC security -- **Lightning integration** - Payment verification -- **ASN.1 validation** - Key structure verification (NEW) - -### Security Checklist - -## 🔐 ASN.1 Validation Framework (NEW) - -### Overview -SecureBit.chat v4.02.442 implements a complete ASN.1 DER parser and validation system. This framework requires special attention when contributing to cryptographic code. - -### Key Components - -#### **ASN1Validator Class** -```javascript -// Core validation class for cryptographic keys -class ASN1Validator { - constructor() { - this.supportedOIDs = { - '1.2.840.10045.3.1.7': 'P-256', // secp256r1 - '1.3.132.0.34': 'P-384' // secp384r1 - }; - this.maxKeySize = 2000; // bytes - this.minKeySize = 50; // bytes - } - - // Complete DER parsing and validation - validateKeyStructure(keyData) { - // Implementation details... - } -} -``` - -#### **Integration Points** -- **Key import operations** - All keys must pass ASN.1 validation -- **Key export operations** - Exported keys are validated -- **Real-time validation** - Continuous validation during operations - -### Contributing to ASN.1 Framework - -#### **Adding New Curve Support** -```javascript -// To add support for a new elliptic curve: -const newCurveOID = '1.3.132.0.XX'; // Replace XX with actual OID -const curveName = 'P-XXX'; // Replace XXX with curve name - -// Add to supportedOIDs -this.supportedOIDs[newCurveOID] = curveName; - -// Update validation logic if needed -// Ensure proper EC point format validation -``` - -#### **Extending Validation Rules** -```javascript -// To add new validation rules: -validateCustomRule(parsed) { - // Implement your validation logic - if (!this.checkCustomCondition(parsed)) { - throw new Error('Custom validation failed'); - } - return true; -} - -// Integrate with main validation -validateKeyStructure(keyData) { - const parsed = this.parseDER(keyData); - - // Existing validations... - if (!this.validateSPKI(parsed)) return false; - if (!this.validateOID(parsed)) return false; - if (!this.validateECPoint(parsed)) return false; - - // New custom validation - if (!this.validateCustomRule(parsed)) return false; - - return true; -} -``` - -### Testing ASN.1 Validation - -#### **Unit Tests** -```javascript -describe('ASN.1 Validation Framework', () => { - test('Validates correct P-384 key structure', () => { - const validKey = generateValidP384Key(); - expect(asn1Validator.validateKeyStructure(validKey)).toBe(true); - }); - - test('Rejects modified key with valid header', () => { - const modifiedKey = modifyKeyData(validKey); - expect(asn1Validator.validateKeyStructure(modifiedKey)).toBe(false); - }); - - test('Rejects unsupported curve OID', () => { - const invalidOIDKey = generateKeyWithInvalidOID(); - expect(asn1Validator.validateKeyStructure(invalidOIDKey)).toBe(false); - }); -}); -``` - -#### **Performance Tests** -```javascript -describe('ASN.1 Validation Performance', () => { - test('Validation completes within 10ms', () => { - const start = performance.now(); - asn1Validator.validateKeyStructure(validKey); - const duration = performance.now() - start; - expect(duration).toBeLessThan(10); - }); -}); -``` - -### Security Guidelines for ASN.1 Contributions - -#### **Critical Requirements** -1. **Never bypass validation** - All keys must pass complete ASN.1 validation -2. **Maintain strict OID checking** - Only support verified, secure algorithms -3. **Preserve size limits** - Key size limits prevent DoS attacks -4. **Validate all structural elements** - Complete verification is mandatory - -#### **Common Pitfalls to Avoid** -```javascript -// ❌ DON'T: Skip validation for performance -const fastImport = (keyData) => { - // Bypassing validation for speed - return crypto.subtle.importKey('spki', keyData, algorithm, false, ['verify']); -}; - -// ✅ DO: Always validate before processing -const secureImport = async (keyData) => { - if (!asn1Validator.validateKeyStructure(keyData)) { - throw new Error('Key validation failed'); - } - return await crypto.subtle.importKey('spki', keyData, algorithm, false, ['verify']); -}; -``` - -#### **Validation Order** -1. **Parse DER** - Complete ASN.1 structure parsing -2. **Validate SPKI** - SubjectPublicKeyInfo structure -3. **Validate OID** - Algorithm and curve verification -4. **Validate EC Point** - Format and structure verification -5. **Apply custom rules** - Any additional validation requirements - -### Breaking Changes and Compatibility - -#### **Version 4.02.442 Changes** -- **Enhanced key validation** now performs complete ASN.1 parsing -- **Stricter key acceptance** criteria for improved security -- **Fallback support** from P-384 to P-256 maintained -- **Backward compatibility** for valid key structures - -#### **Migration Considerations** -- **Existing keys** are validated on next use -- **New keys** must pass complete validation -- **Invalid keys** are rejected with clear error messages -- **Performance impact** is minimal (< 10ms per validation) - -### Documentation Requirements - -#### **Code Documentation** -```javascript -/** - * Validates cryptographic key structure using complete ASN.1 DER parsing - * - * @param {ArrayBuffer} keyData - Raw key data to validate - * @returns {boolean} - True if validation passes, false otherwise - * @throws {Error} - Detailed error message for validation failures - * - * @example - * const isValid = asn1Validator.validateKeyStructure(keyData); - * if (!isValid) { - * console.error('Key validation failed'); - * } - */ -validateKeyStructure(keyData) { - // Implementation... -} -``` - -#### **API Documentation** -- **Function signatures** with parameter types -- **Return values** and error conditions -- **Usage examples** for common scenarios -- **Performance characteristics** and limitations - -### Contributing Guidelines Summary - -#### **For ASN.1 Framework Contributions** -1. **Understand the security model** - Complete validation is mandatory -2. **Follow validation order** - Parse → SPKI → OID → EC Point → Custom -3. **Maintain performance** - Keep validation time under 10ms -4. **Add comprehensive tests** - Unit, integration, and performance tests -5. **Document thoroughly** - Code comments, API docs, and examples -6. **Consider breaking changes** - Ensure backward compatibility where possible - -#### **Security Review Process** -1. **Code review** by cryptographic experts -2. **Security testing** for validation bypass attempts -3. **Performance validation** for timing attacks -4. **Compatibility testing** with existing key formats -5. **Documentation review** for accuracy and completeness - ---- - -## 🚀 Getting Started - -### Prerequisites -- **Browser:** Modern browser with WebRTC and WebCrypto support -- **Git:** For version control -- **Text Editor:** VS Code, Vim, or your favorite editor -- **Lightning Wallet:** For testing payment features (optional) - -### Development Setup -```bash -# 1. Fork the repository on GitHub -# 2. Clone your fork -git clone https://github.com/yourusername/securebit-chat.git -cd securebit-chat - -# 3. Create a development branch -git checkout -b feature/your-feature-name - -# 4. Start development server -python -m http.server 8000 -# or -npx serve . - -# 5. Open http://localhost:8000 -# Make your changes -# Test thoroughly -# Commit with descriptive messages -git commit -m "feat: add quantum-resistant key exchange - -- Implement CRYSTALS-Kyber for post-quantum security -- Add fallback to classical ECDH -- Update security level calculations -- Add comprehensive test suite - -Closes #123" -``` - -## 📋 Contribution Guidelines - -### 🔍 Before You Start - -- Check existing issues - avoid duplicate work -- Create an issue - discuss your idea first -- Get feedback - ensure alignment with project goals -- Fork and branch - work on a feature branch - -### 💻 Code Standards - -#### JavaScript Style -```javascript -// ✅ Good -const encryptionKey = await crypto.subtle.generateKey({ - name: 'AES-GCM', - length: 256 -}, false, ['encrypt', 'decrypt']); - -// ❌ Bad -var key=crypto.subtle.generateKey({name:'AES-GCM',length:256},false,['encrypt','decrypt']) -``` - -#### Naming Conventions - -- **Functions:** camelCase - `generateSecureKey()` -- **Classes:** PascalCase - `EnhancedSecureCryptoUtils` -- **Constants:** UPPER_SNAKE_CASE - `MAX_MESSAGE_LENGTH` -- **Files:** kebab-case - `crypto-utils.js` - -### 📖 Documentation - -## 🔒 Security Considerations - -### Critical Areas -These areas require extra careful review: - -- **Cryptographic functions** - All crypto code must be reviewed -- **Key generation** - Entropy and randomness -- **Message handling** - Input validation and sanitization -- **P2P communication** - WebRTC security -- **Lightning integration** - Payment verification -- **ASN.1 validation** - Key structure verification (NEW) - -### Security Checklist - -## 🔐 ASN.1 Validation Framework (NEW) - -### Overview -SecureBit.chat v4.02.442 implements a complete ASN.1 DER parser and validation system. This framework requires special attention when contributing to cryptographic code. - -### Key Components - -#### **ASN1Validator Class** -```javascript -// Core validation class for cryptographic keys -class ASN1Validator { - constructor() { - this.supportedOIDs = { - '1.2.840.10045.3.1.7': 'P-256', // secp256r1 - '1.3.132.0.34': 'P-384' // secp384r1 - }; - this.maxKeySize = 2000; // bytes - this.minKeySize = 50; // bytes - } - - // Complete DER parsing and validation - validateKeyStructure(keyData) { - // Implementation details... - } -} -``` - -#### **Integration Points** -- **Key import operations** - All keys must pass ASN.1 validation -- **Key export operations** - Exported keys are validated -- **Real-time validation** - Continuous validation during operations - -### Contributing to ASN.1 Framework - -#### **Adding New Curve Support** -```javascript -// To add support for a new elliptic curve: -const newCurveOID = '1.3.132.0.XX'; // Replace XX with actual OID -const curveName = 'P-XXX'; // Replace XXX with curve name - -// Add to supportedOIDs -this.supportedOIDs[newCurveOID] = curveName; - -// Update validation logic if needed -// Ensure proper EC point format validation -``` - -#### **Extending Validation Rules** -```javascript -// To add new validation rules: -validateCustomRule(parsed) { - // Implement your validation logic - if (!this.checkCustomCondition(parsed)) { - throw new Error('Custom validation failed'); - } - return true; -} - -// Integrate with main validation -validateKeyStructure(keyData) { - const parsed = this.parseDER(keyData); - - // Existing validations... - if (!this.validateSPKI(parsed)) return false; - if (!this.validateOID(parsed)) return false; - if (!this.validateECPoint(parsed)) return false; - - // New custom validation - if (!this.validateCustomRule(parsed)) return false; - - return true; -} -``` - -### Testing ASN.1 Validation - -#### **Unit Tests** -```javascript -describe('ASN.1 Validation Framework', () => { - test('Validates correct P-384 key structure', () => { - const validKey = generateValidP384Key(); - expect(asn1Validator.validateKeyStructure(validKey)).toBe(true); - }); - - test('Rejects modified key with valid header', () => { - const modifiedKey = modifyKeyData(validKey); - expect(asn1Validator.validateKeyStructure(modifiedKey)).toBe(false); - }); - - test('Rejects unsupported curve OID', () => { - const invalidOIDKey = generateKeyWithInvalidOID(); - expect(asn1Validator.validateKeyStructure(invalidOIDKey)).toBe(false); - }); -}); -``` - -#### **Performance Tests** -```javascript -describe('ASN.1 Validation Performance', () => { - test('Validation completes within 10ms', () => { - const start = performance.now(); - asn1Validator.validateKeyStructure(validKey); - const duration = performance.now() - start; - expect(duration).toBeLessThan(10); - }); -}); -``` - -### Security Guidelines for ASN.1 Contributions - -#### **Critical Requirements** -1. **Never bypass validation** - All keys must pass complete ASN.1 validation -2. **Maintain strict OID checking** - Only support verified, secure algorithms -3. **Preserve size limits** - Key size limits prevent DoS attacks -4. **Validate all structural elements** - Complete verification is mandatory - -#### **Common Pitfalls to Avoid** -```javascript -// ❌ DON'T: Skip validation for performance -const fastImport = (keyData) => { - // Bypassing validation for speed - return crypto.subtle.importKey('spki', keyData, algorithm, false, ['verify']); -}; - -// ✅ DO: Always validate before processing -const secureImport = async (keyData) => { - if (!asn1Validator.validateKeyStructure(keyData)) { - throw new Error('Key validation failed'); - } - return await crypto.subtle.importKey('spki', keyData, algorithm, false, ['verify']); -}; -``` - -#### **Validation Order** -1. **Parse DER** - Complete ASN.1 structure parsing -2. **Validate SPKI** - SubjectPublicKeyInfo structure -3. **Validate OID** - Algorithm and curve verification -4. **Validate EC Point** - Format and structure verification -5. **Apply custom rules** - Any additional validation requirements - -### Breaking Changes and Compatibility - -#### **Version 4.02.442 Changes** -- **Enhanced key validation** now performs complete ASN.1 parsing -- **Stricter key acceptance** criteria for improved security -- **Fallback support** from P-384 to P-256 maintained -- **Backward compatibility** for valid key structures - -#### **Migration Considerations** -- **Existing keys** are validated on next use -- **New keys** must pass complete validation -- **Invalid keys** are rejected with clear error messages -- **Performance impact** is minimal (< 10ms per validation) - -### Documentation Requirements - -#### **Code Documentation** -```javascript -/** - * Validates cryptographic key structure using complete ASN.1 DER parsing - * - * @param {ArrayBuffer} keyData - Raw key data to validate - * @returns {boolean} - True if validation passes, false otherwise - * @throws {Error} - Detailed error message for validation failures - * - * @example - * const isValid = asn1Validator.validateKeyStructure(keyData); - * if (!isValid) { - * console.error('Key validation failed'); - * } - */ -validateKeyStructure(keyData) { - // Implementation... -} -``` - -#### **API Documentation** -- **Function signatures** with parameter types -- **Return values** and error conditions -- **Usage examples** for common scenarios -- **Performance characteristics** and limitations - -### Contributing Guidelines Summary - -#### **For ASN.1 Framework Contributions** -1. **Understand the security model** - Complete validation is mandatory -2. **Follow validation order** - Parse → SPKI → OID → EC Point → Custom -3. **Maintain performance** - Keep validation time under 10ms -4. **Add comprehensive tests** - Unit, integration, and performance tests -5. **Document thoroughly** - Code comments, API docs, and examples -6. **Consider breaking changes** - Ensure backward compatibility where possible - -#### **Security Review Process** -1. **Code review** by cryptographic experts -2. **Security testing** for validation bypass attempts -3. **Performance validation** for timing attacks -4. **Compatibility testing** with existing key formats -5. **Documentation review** for accuracy and completeness - ---- - -## 🚀 Getting Started - -### Prerequisites -- **Browser:** Modern browser with WebRTC and WebCrypto support -- **Git:** For version control -- **Text Editor:** VS Code, Vim, or your favorite editor -- **Lightning Wallet:** For testing payment features (optional) - -### Development Setup -```bash -# 1. Fork the repository on GitHub -# 2. Clone your fork -git clone https://github.com/yourusername/securebit-chat.git -cd securebit-chat - -# 3. Create a development branch -git checkout -b feature/your-feature-name - -# 4. Start development server -python -m http.server 8000 -# or -npx serve . - -# 5. Open http://localhost:8000 -# Make your changes -# Test thoroughly -# Commit with descriptive messages -git commit -m "feat: add quantum-resistant key exchange - -- Implement CRYSTALS-Kyber for post-quantum security -- Add fallback to classical ECDH -- Update security level calculations -- Add comprehensive test suite - -Closes #123" -``` - -## 📋 Contribution Guidelines - -### 🔍 Before You Start - -- Check existing issues - avoid duplicate work -- Create an issue - discuss your idea first -- Get feedback - ensure alignment with project goals -- Fork and branch - work on a feature branch - -### 💻 Code Standards - -#### JavaScript Style -```javascript -// ✅ Good -const encryptionKey = await crypto.subtle.generateKey({ - name: 'AES-GCM', - length: 256 -}, false, ['encrypt', 'decrypt']); - -// ❌ Bad -var key=crypto.subtle.generateKey({name:'AES-GCM',length:256},false,['encrypt','decrypt']) -``` - -#### Naming Conventions - -- **Functions:** camelCase - `generateSecureKey()` -- **Classes:** PascalCase - `EnhancedSecureCryptoUtils` -- **Constants:** UPPER_SNAKE_CASE - `MAX_MESSAGE_LENGTH` -- **Files:** kebab-case - `crypto-utils.js` - -### 📖 Documentation - -## 🔒 Security Considerations - -### Critical Areas -These areas require extra careful review: - -- **Cryptographic functions** - All crypto code must be reviewed -- **Key generation** - Entropy and randomness -- **Message handling** - Input validation and sanitization -- **P2P communication** - WebRTC security -- **Lightning integration** - Payment verification -- **ASN.1 validation** - Key structure verification (NEW) - -### Security Checklist - -## 🔐 ASN.1 Validation Framework (NEW) - -### Overview -SecureBit.chat v4.02.442 implements a complete ASN.1 DER parser and validation system. This framework requires special attention when contributing to cryptographic code. - -### Key Components - -#### **ASN1Validator Class** -```javascript -// Core validation class for cryptographic keys -class ASN1Validator { - constructor() { - this.supportedOIDs = { - '1.2.840.10045.3.1.7': 'P-256', // secp256r1 - '1.3.132.0.34': 'P-384' // secp384r1 - }; - this.maxKeySize = 2000; // bytes - this.minKeySize = 50; // bytes - } - - // Complete DER parsing and validation - validateKeyStructure(keyData) { - // Implementation details... - } -} -``` - -#### **Integration Points** -- **Key import operations** - All keys must pass ASN.1 validation -- **Key export operations** - Exported keys are validated -- **Real-time validation** - Continuous validation during operations - -### Contributing to ASN.1 Framework - -#### **Adding New Curve Support** -```javascript -// To add support for a new elliptic curve: -const newCurveOID = '1.3.132.0.XX'; // Replace XX with actual OID -const curveName = 'P-XXX'; // Replace XXX with curve name - -// Add to supportedOIDs -this.supportedOIDs[newCurveOID] = curveName; - -// Update validation logic if needed -// Ensure proper EC point format validation -``` - -#### **Extending Validation Rules** -```javascript -// To add new validation rules: -validateCustomRule(parsed) { - // Implement your validation logic - if (!this.checkCustomCondition(parsed)) { - throw new Error('Custom validation failed'); - } - return true; -} - -// Integrate with main validation -validateKeyStructure(keyData) { - const parsed = this.parseDER(keyData); - - // Existing validations... - if (!this.validateSPKI(parsed)) return false; - if (!this.validateOID(parsed)) return false; - if (!this.validateECPoint(parsed)) return false; - - // New custom validation - if (!this.validateCustomRule(parsed)) return false; - - return true; -} -``` - -### Testing ASN.1 Validation - -#### **Unit Tests** -```javascript -describe('ASN.1 Validation Framework', () => { - test('Validates correct P-384 key structure', () => { - const validKey = generateValidP384Key(); - expect(asn1Validator.validateKeyStructure(validKey)).toBe(true); - }); - - test('Rejects modified key with valid header', () => { - const modifiedKey = modifyKeyData(validKey); - expect(asn1Validator.validateKeyStructure(modifiedKey)).toBe(false); - }); - - test('Rejects unsupported curve OID', () => { - const invalidOIDKey = generateKeyWithInvalidOID(); - expect(asn1Validator.validateKeyStructure(invalidOIDKey)).toBe(false); - }); -}); -``` - -#### **Performance Tests** -```javascript -describe('ASN.1 Validation Performance', () => { - test('Validation completes within 10ms', () => { - const start = performance.now(); - asn1Validator.validateKeyStructure(validKey); - const duration = performance.now() - start; - expect(duration).toBeLessThan(10); - }); -}); -``` - -### Security Guidelines for ASN.1 Contributions - -#### **Critical Requirements** -1. **Never bypass validation** - All keys must pass complete ASN.1 validation -2. **Maintain strict OID checking** - Only support verified, secure algorithms -3. **Preserve size limits** - Key size limits prevent DoS attacks -4. **Validate all structural elements** - Complete verification is mandatory - -#### **Common Pitfalls to Avoid** -```javascript -// ❌ DON'T: Skip validation for performance -const fastImport = (keyData) => { - // Bypassing validation for speed - return crypto.subtle.importKey('spki', keyData, algorithm, false, ['verify']); -}; - -// ✅ DO: Always validate before processing -const secureImport = async (keyData) => { - if (!asn1Validator.validateKeyStructure(keyData)) { - throw new Error('Key validation failed'); - } - return await crypto.subtle.importKey('spki', keyData, algorithm, false, ['verify']); -}; -``` - -#### **Validation Order** -1. **Parse DER** - Complete ASN.1 structure parsing -2. **Validate SPKI** - SubjectPublicKeyInfo structure -3. **Validate OID** - Algorithm and curve verification -4. **Validate EC Point** - Format and structure verification -5. **Apply custom rules** - Any additional validation requirements - -### Breaking Changes and Compatibility - -#### **Version 4.02.442 Changes** -- **Enhanced key validation** now performs complete ASN.1 parsing -- **Stricter key acceptance** criteria for improved security -- **Fallback support** from P-384 to P-256 maintained -- **Backward compatibility** for valid key structures - -#### **Migration Considerations** -- **Existing keys** are validated on next use -- **New keys** must pass complete validation -- **Invalid keys** are rejected with clear error messages -- **Performance impact** is minimal (< 10ms per validation) - -### Documentation Requirements - -#### **Code Documentation** -```javascript -/** - * Validates cryptographic key structure using complete ASN.1 DER parsing - * - * @param {ArrayBuffer} keyData - Raw key data to validate - * @returns {boolean} - True if validation passes, false otherwise - * @throws {Error} - Detailed error message for validation failures - * - * @example - * const isValid = asn1Validator.validateKeyStructure(keyData); - * if (!isValid) { - * console.error('Key validation failed'); - * } - */ -validateKeyStructure(keyData) { - // Implementation... -} -``` - -#### **API Documentation** -- **Function signatures** with parameter types -- **Return values** and error conditions -- **Usage examples** for common scenarios -- **Performance characteristics** and limitations - -### Contributing Guidelines Summary - -#### **For ASN.1 Framework Contributions** -1. **Understand the security model** - Complete validation is mandatory -2. **Follow validation order** - Parse → SPKI → OID → EC Point → Custom -3. **Maintain performance** - Keep validation time under 10ms -4. **Add comprehensive tests** - Unit, integration, and performance tests -5. **Document thoroughly** - Code comments, API docs, and examples -6. **Consider breaking changes** - Ensure backward compatibility where possible - -#### **Security Review Process** -1. **Code review** by cryptographic experts -2. **Security testing** for validation bypass attempts -3. **Performance validation** for timing attacks -4. **Compatibility testing** with existing key formats -5. **Documentation review** for accuracy and completeness - ---- - -## 🚀 Getting Started - -### Prerequisites -- **Browser:** Modern browser with WebRTC and WebCrypto support -- **Git:** For version control -- **Text Editor:** VS Code, Vim, or your favorite editor -- **Lightning Wallet:** For testing payment features (optional) - -### Development Setup -```bash -# 1. Fork the repository on GitHub -# 2. Clone your fork -git clone https://github.com/yourusername/securebit-chat.git -cd securebit-chat - -# 3. Create a development branch -git checkout -b feature/your-feature-name - -# 4. Start development server -python -m http.server 8000 -# or -npx serve . - -# 5. Open http://localhost:8000 -# Make your changes -# Test thoroughly -# Commit with descriptive messages -git commit -m "feat: add quantum-resistant key exchange - -- Implement CRYSTALS-Kyber for post-quantum security -- Add fallback to classical ECDH -- Update security level calculations -- Add comprehensive test suite - -Closes #123" -``` - -## 📋 Contribution Guidelines - -### 🔍 Before You Start - -- Check existing issues - avoid duplicate work -- Create an issue - discuss your idea first -- Get feedback - ensure alignment with project goals -- Fork and branch - work on a feature branch - -### 💻 Code Standards - -#### JavaScript Style -```javascript -// ✅ Good -const encryptionKey = await crypto.subtle.generateKey({ - name: 'AES-GCM', - length: 256 -}, false, ['encrypt', 'decrypt']); - -// ❌ Bad -var key=crypto.subtle.generateKey({name:'AES-GCM',length:256},false,['encrypt','decrypt']) -``` - -#### Naming Conventions - -- **Functions:** camelCase - `generateSecureKey()` -- **Classes:** PascalCase - `EnhancedSecureCryptoUtils` -- **Constants:** UPPER_SNAKE_CASE - `MAX_MESSAGE_LENGTH` -- **Files:** kebab-case - `crypto-utils.js` - -### 📖 Documentation - -## 🔒 Security Considerations - -### Critical Areas -These areas require extra careful review: - -- **Cryptographic functions** - All crypto code must be reviewed -- **Key generation** - Entropy and randomness -- **Message handling** - Input validation and sanitization -- **P2P communication** - WebRTC security -- **Lightning integration** - Payment verification -- **ASN.1 validation** - Key structure verification (NEW) - -### Security Checklist - -## 🔐 ASN.1 Validation Framework (NEW) - -### Overview -SecureBit.chat v4.02.442 implements a complete ASN.1 DER parser and validation system. This framework requires special attention when contributing to cryptographic code. - -### Key Components - -#### **ASN1Validator Class** -```javascript -// Core validation class for cryptographic keys -class ASN1Validator { - constructor() { - this.supportedOIDs = { - '1.2.840.10045.3.1.7': 'P-256', // secp256r1 - '1.3.132.0.34': 'P-384' // secp384r1 - }; - this.maxKeySize = 2000; // bytes - this.minKeySize = 50; // bytes - } - - // Complete DER parsing and validation - validateKeyStructure(keyData) { - // Implementation details... - } -} -``` - -#### **Integration Points** -- **Key import operations** - All keys must pass ASN.1 validation -- **Key export operations** - Exported keys are validated -- **Real-time validation** - Continuous validation during operations - -### Contributing to ASN.1 Framework - -#### **Adding New Curve Support** -```javascript -// To add support for a new elliptic curve: -const newCurveOID = '1.3.132.0.XX'; // Replace XX with actual OID -const curveName = 'P-XXX'; // Replace XXX with curve name - -// Add to supportedOIDs -this.supportedOIDs[newCurveOID] = curveName; - -// Update validation logic if needed -// Ensure proper EC point format validation -``` - -#### **Extending Validation Rules** -```javascript -// To add new validation rules: -validateCustomRule(parsed) { - // Implement your validation logic - if (!this.checkCustomCondition(parsed)) { - throw new Error('Custom validation failed'); - } - return true; -} - -// Integrate with main validation -validateKeyStructure(keyData) { - const parsed = this.parseDER(keyData); - - // Existing validations... - if (!this.validateSPKI(parsed)) return false; - if (!this.validateOID(parsed)) return false; - if (!this.validateECPoint(parsed)) return false; - - // New custom validation - if (!this.validateCustomRule(parsed)) return false; - - return true; -} -``` - -### Testing ASN.1 Validation - -#### **Unit Tests** -```javascript -describe('ASN.1 Validation Framework', () => { - test('Validates correct P-384 key structure', () => { - const validKey = generateValidP384Key(); - expect(asn1Validator.validateKeyStructure(validKey)).toBe(true); - }); - - test('Rejects modified key with valid header', () => { - const modifiedKey = modifyKeyData(validKey); - expect(asn1Validator.validateKeyStructure(modifiedKey)).toBe(false); - }); - - test('Rejects unsupported curve OID', () => { - const invalidOIDKey = generateKeyWithInvalidOID(); - expect(asn1Validator.validateKeyStructure(invalidOIDKey)).toBe(false); - }); -}); -``` - -#### **Performance Tests** -```javascript -describe('ASN.1 Validation Performance', () => { - test('Validation completes within 10ms', () => { - const start = performance.now(); - asn1Validator.validateKeyStructure(validKey); - const duration = performance.now() - start; - expect(duration).toBeLessThan(10); - }); -}); -``` - -### Security Guidelines for ASN.1 Contributions - -#### **Critical Requirements** -1. **Never bypass validation** - All keys must pass complete ASN.1 validation -2. **Maintain strict OID checking** - Only support verified, secure algorithms -3. **Preserve size limits** - Key size limits prevent DoS attacks -4. **Validate all structural elements** - Complete verification is mandatory - -#### **Common Pitfalls to Avoid** -```javascript -// ❌ DON'T: Skip validation for performance -const fastImport = (keyData) => { - // Bypassing validation for speed - return crypto.subtle.importKey('spki', keyData, algorithm, false, ['verify']); -}; - -// ✅ DO: Always validate before processing -const secureImport = async (keyData) => { - if (!asn1Validator.validateKeyStructure(keyData)) { - throw new Error('Key validation failed'); - } - return await crypto.subtle.importKey('spki', keyData, algorithm, false, ['verify']); -}; -``` - -#### **Validation Order** -1. **Parse DER** - Complete ASN.1 structure parsing -2. **Validate SPKI** - SubjectPublicKeyInfo structure -3. **Validate OID** - Algorithm and curve verification -4. **Validate EC Point** - Format and structure verification -5. **Apply custom rules** - Any additional validation requirements - -### Breaking Changes and Compatibility - -#### **Version 4.02.442 Changes** -- **Enhanced key validation** now performs complete ASN.1 parsing -- **Stricter key acceptance** criteria for improved security -- **Fallback support** from P-384 to P-256 maintained -- **Backward compatibility** for valid key structures - -#### **Migration Considerations** -- **Existing keys** are validated on next use -- **New keys** must pass complete validation -- **Invalid keys** are rejected with clear error messages -- **Performance impact** is minimal (< 10ms per validation) - -### Documentation Requirements - -#### **Code Documentation** -```javascript -/** - * Validates cryptographic key structure using complete ASN.1 DER parsing - * - * @param {ArrayBuffer} keyData - Raw key data to validate - * @returns {boolean} - True if validation passes, false otherwise - * @throws {Error} - Detailed error message for validation failures - * - * @example - * const isValid = asn1Validator.validateKeyStructure(keyData); - * if (!isValid) { - * console.error('Key validation failed'); - * } - */ -validateKeyStructure(keyData) { - // Implementation... -} -``` - -#### **API Documentation** -- **Function signatures** with parameter types -- **Return values** and error conditions -- **Usage examples** for common scenarios -- **Performance characteristics** and limitations - -### Contributing Guidelines Summary - -#### **For ASN.1 Framework Contributions** -1. **Understand the security model** - Complete validation is mandatory -2. **Follow validation order** - Parse → SPKI → OID → EC Point → Custom -3. **Maintain performance** - Keep validation time under 10ms -4. **Add comprehensive tests** - Unit, integration, and performance tests -5. **Document thoroughly** - Code comments, API docs, and examples -6. **Consider breaking changes** - Ensure backward compatibility where possible - -#### **Security Review Process** -1. **Code review** by cryptographic experts -2. **Security testing** for validation bypass attempts -3. **Performance validation** for timing attacks -4. **Compatibility testing** with existing key formats -5. **Documentation review** for accuracy and completeness - ---- - -## 🚀 Getting Started - -### Prerequisites -- **Browser:** Modern browser with WebRTC and WebCrypto support -- **Git:** For version control -- **Text Editor:** VS Code, Vim, or your favorite editor -- **Lightning Wallet:** For testing payment features (optional) - -### Development Setup -```bash -# 1. Fork the repository on GitHub -# 2. Clone your fork -git clone https://github.com/yourusername/securebit-chat.git -cd securebit-chat - -# 3. Create a development branch -git checkout -b feature/your-feature-name - -# 4. Start development server -python -m http.server 8000 -# or -npx serve . - -# 5. Open http://localhost:8000 -# Make your changes -# Test thoroughly -# Commit with descriptive messages -git commit -m "feat: add quantum-resistant key exchange - -- Implement CRYSTALS-Kyber for post-quantum security -- Add fallback to classical ECDH -- Update security level calculations -- Add comprehensive test suite - -Closes #123" -``` - -## 📋 Contribution Guidelines - -### 🔍 Before You Start - -- Check existing issues - avoid duplicate work -- Create an issue - discuss your idea first -- Get feedback - ensure alignment with project goals -- Fork and branch - work on a feature branch - -### 💻 Code Standards - -#### JavaScript Style -```javascript -// ✅ Good -const encryptionKey = await crypto.subtle.generateKey({ - name: 'AES-GCM', - length: 256 -}, false, ['encrypt', 'decrypt']); - -// ❌ Bad -var key=crypto.subtle.generateKey({name:'AES-GCM',length:256},false,['encrypt','decrypt']) -``` - -#### Naming Conventions - -- **Functions:** camelCase - `generateSecureKey()` -- **Classes:** PascalCase - `EnhancedSecureCryptoUtils` -- **Constants:** UPPER_SNAKE_CASE - `MAX_MESSAGE_LENGTH` -- **Files:** kebab-case - `crypto-utils.js` - -### 📖 Documentation - -## 🔒 Security Considerations - -### Critical Areas -These areas require extra careful review: - -- **Cryptographic functions** - All crypto code must be reviewed -- **Key generation** - Entropy and randomness -- **Message handling** - Input validation and sanitization -- **P2P communication** - WebRTC security -- **Lightning integration** - Payment verification -- **ASN.1 validation** - Key structure verification (NEW) - -### Security Checklist - -## 🔐 ASN.1 Validation Framework (NEW) - -### Overview -SecureBit.chat v4.02.442 implements a complete ASN.1 DER parser and validation system. This framework requires special attention when contributing to cryptographic code. - -### Key Components - -#### **ASN1Validator Class** -```javascript -// Core validation class for cryptographic keys -class ASN1Validator { - constructor() { - this.supportedOIDs = { - '1.2.840.10045.3.1.7': 'P-256', // secp256r1 - '1.3.132.0.34': 'P-384' // secp384r1 - }; - this.maxKeySize = 2000; // bytes - this.minKeySize = 50; // bytes - } - - // Complete DER parsing and validation - validateKeyStructure(keyData) { - // Implementation details... - } -} -``` - -#### **Integration Points** -- **Key import operations** - All keys must pass ASN.1 validation -- **Key export operations** - Exported keys are validated -- **Real-time validation** - Continuous validation during operations - -### Contributing to ASN.1 Framework - -#### **Adding New Curve Support** -```javascript -// To add support for a new elliptic curve: -const newCurveOID = '1.3.132.0.XX'; // Replace XX with actual OID -const curveName = 'P-XXX'; // Replace XXX with curve name - -// Add to supportedOIDs -this.supportedOIDs[newCurveOID] = curveName; - -// Update validation logic if needed -// Ensure proper EC point format validation -``` - -#### **Extending Validation Rules** -```javascript -// To add new validation rules: -validateCustomRule(parsed) { - // Implement your validation logic - if (!this.checkCustomCondition(parsed)) { - throw new Error('Custom validation failed'); - } - return true; -} - -// Integrate with main validation -validateKeyStructure(keyData) { - const parsed = this.parseDER(keyData); - - // Existing validations... - if (!this.validateSPKI(parsed)) return false; - if (!this.validateOID(parsed)) return false; - if (!this.validateECPoint(parsed)) return false; - - // New custom validation - if (!this.validateCustomRule(parsed)) return false; - - return true; -} -``` - -### Testing ASN.1 Validation - -#### **Unit Tests** -```javascript -describe('ASN.1 Validation Framework', () => { - test('Validates correct P-384 key structure', () => { - const validKey = generateValidP384Key(); - expect(asn1Validator.validateKeyStructure(validKey)).toBe(true); - }); - - test('Rejects modified key with valid header', () => { - const modifiedKey = modifyKeyData(validKey); - expect(asn1Validator.validateKeyStructure(modifiedKey)).toBe(false); - }); - - test('Rejects unsupported curve OID', () => { - const invalidOIDKey = generateKeyWithInvalidOID(); - expect(asn1Validator.validateKeyStructure(invalidOIDKey)).toBe(false); - }); -}); -``` - -#### **Performance Tests** -```javascript -describe('ASN.1 Validation Performance', () => { - test('Validation completes within 10ms', () => { - const start = performance.now(); - asn1Validator.validateKeyStructure(validKey); - const duration = performance.now() - start; - expect(duration).toBeLessThan(10); - }); -}); -``` - -### Security Guidelines for ASN.1 Contributions - -#### **Critical Requirements** -1. **Never bypass validation** - All keys must pass complete ASN.1 validation -2. **Maintain strict OID checking** - Only support verified, secure algorithms -3. **Preserve size limits** - Key size limits prevent DoS attacks -4. **Validate all structural elements** - Complete verification is mandatory - -#### **Common Pitfalls to Avoid** -```javascript -// ❌ DON'T: Skip validation for performance -const fastImport = (keyData) => { - // Bypassing validation for speed - return crypto.subtle.importKey('spki', keyData, algorithm, false, ['verify']); -}; - -// ✅ DO: Always validate before processing -const secureImport = async (keyData) => { - if (!asn1Validator.validateKeyStructure(keyData)) { - throw new Error('Key validation failed'); - } - return await crypto.subtle.importKey('spki', keyData, algorithm, false, ['verify']); -}; -``` - -#### **Validation Order** -1. **Parse DER** - Complete ASN.1 structure parsing -2. **Validate SPKI** - SubjectPublicKeyInfo structure -3. **Validate OID** - Algorithm and curve verification -4. **Validate EC Point** - Format and structure verification -5. **Apply custom rules** - Any additional validation requirements - -### Breaking Changes and Compatibility - -#### **Version 4.02.442 Changes** -- **Enhanced key validation** now performs complete ASN.1 parsing -- **Stricter key acceptance** criteria for improved security -- **Fallback support** from P-384 to P-256 maintained -- **Backward compatibility** for valid key structures - -#### **Migration Considerations** -- **Existing keys** are validated on next use -- **New keys** must pass complete validation -- **Invalid keys** are rejected with clear error messages -- **Performance impact** is minimal (< 10ms per validation) - -### Documentation Requirements - -#### **Code Documentation** -```javascript -/** - * Validates cryptographic key structure using complete ASN.1 DER parsing - * - * @param {ArrayBuffer} keyData - Raw key data to validate - * @returns {boolean} - True if validation passes, false otherwise - * @throws {Error} - Detailed error message for validation failures - * - * @example - * const isValid = asn1Validator.validateKeyStructure(keyData); - * if (!isValid) { - * console.error('Key validation failed'); - * } - */ -validateKeyStructure(keyData) { - // Implementation... -} +npm install +npm test +npm audit +npm run build ``` -#### **API Documentation** -- **Function signatures** with parameter types -- **Return values** and error conditions -- **Usage examples** for common scenarios -- **Performance characteristics** and limitations +## Security-sensitive areas -### Contributing Guidelines Summary +Changes involving any of the following require extra review and focused tests: -#### **For ASN.1 Framework Contributions** -1. **Understand the security model** - Complete validation is mandatory -2. **Follow validation order** - Parse → SPKI → OID → EC Point → Custom -3. **Maintain performance** - Keep validation time under 10ms -4. **Add comprehensive tests** - Unit, integration, and performance tests -5. **Document thoroughly** - Code comments, API docs, and examples -6. **Consider breaking changes** - Ensure backward compatibility where possible +- SAS verification and protocol compatibility +- WebRTC ICE/TURN behavior +- encrypted payload validation or display sanitization +- file-transfer consent and type policy +- IndexedDB migration logic +- disconnect and resource lifecycle cleanup -#### **Security Review Process** -1. **Code review** by cryptographic experts -2. **Security testing** for validation bypass attempts -3. **Performance validation** for timing attacks -4. **Compatibility testing** with existing key formats -5. **Documentation review** for accuracy and completeness +## Documentation expectations ---- +When behavior changes, update the corresponding release-facing documentation in the same change: -## 🚀 Getting Started +- `README.md` +- `SECURITY.md` +- `doc/CONFIGURATION.md` +- `doc/CRYPTOGRAPHY.md` +- `doc/SECURITY-ARCHITECTURE.md` +- `CHANGELOG.md` -### Prerequisites -- **Browser:** Modern browser with WebRTC and WebCrypto support -- **Git:** For version control -- **Text Editor:** VS Code, Vim, or your favorite editor -- **Lightning Wallet:** For testing payment features (optional) +## Pull requests -### Development Setup -```bash -# 1. Fork the repository on GitHub -# 2. Clone your fork -git clone https://github.com/yourusername/securebit-chat.git -cd securebit-chat - -# 3. Create a development branch -git checkout -b feature/your-feature-name - -# 4. Start development server -python -m http.server 8000 -# or -npx serve . - -# 5. Open http://localhost:8000 -# Make your changes -# Test thoroughly -# Commit with descriptive messages -git commit -m "feat: add quantum-resistant key exchange - -- Implement CRYSTALS-Kyber for post-quantum security -- Add fallback to classical ECDH -- Update security level calculations -- Add comprehensive test suite - -Closes #123" -``` - -## 📋 Contribution Guidelines - -### 🔍 Before You Start - -- Check existing issues - avoid duplicate work -- Create an issue - discuss your idea first -- Get feedback - ensure alignment with project goals -- Fork and branch - work on a feature branch - -### 💻 Code Standards - -#### JavaScript Style -```javascript -// ✅ Good -const encryptionKey = await crypto.subtle.generateKey({ - name: 'AES-GCM', - length: 256 -}, false, ['encrypt', 'decrypt']); - -// ❌ Bad -var key=crypto.subtle.generateKey({name:'AES-GCM',length:256},false,['encrypt','decrypt']) -``` - -#### Naming Conventions - -- **Functions:** camelCase - `generateSecureKey()` -- **Classes:** PascalCase - `EnhancedSecureCryptoUtils` -- **Constants:** UPPER_SNAKE_CASE - `MAX_MESSAGE_LENGTH` -- **Files:** kebab-case - `crypto-utils.js` - -### 📖 Documentation - -## 🔒 Security Considerations - -### Critical Areas -These areas require extra careful review: - -- **Cryptographic functions** - All crypto code must be reviewed -- **Key generation** - Entropy and randomness -- **Message handling** - Input validation and sanitization -- **P2P communication** - WebRTC security -- **Lightning integration** - Payment verification -- **ASN.1 validation** - Key structure verification (NEW) - -### Security Checklist - -## 🔐 ASN.1 Validation Framework (NEW) - -### Overview -SecureBit.chat v4.02.442 implements a complete ASN.1 DER parser and validation system. This framework requires special attention when contributing to cryptographic code. - -### Key Components - -#### **ASN1Validator Class** -```javascript -// Core validation class for cryptographic keys -class ASN1Validator { - constructor() { - this.supportedOIDs = { - '1.2.840.10045.3.1.7': 'P-256', // secp256r1 - '1.3.132.0.34': 'P-384' // secp384r1 - }; - this.maxKeySize = 2000; // bytes - this.minKeySize = 50; // bytes - } - - // Complete DER parsing and validation - validateKeyStructure(keyData) { - // Implementation details... - } -} -``` - -#### **Integration Points** -- **Key import operations** - All keys must pass ASN.1 validation -- **Key export operations** - Exported keys are validated -- **Real-time validation** - Continuous validation during operations - -### Contributing to ASN.1 Framework - -#### **Adding New Curve Support** -```javascript -// To add support for a new elliptic curve: -const newCurveOID = '1.3.132.0.XX'; // Replace XX with actual OID -const curveName = 'P-XXX'; // Replace XXX with curve name - -// Add to supportedOIDs -this.supportedOIDs[newCurveOID] = curveName; - -// Update validation logic if needed -// Ensure proper EC point format validation -``` +Please include: -#### **Extending Validation Rules** -```javascript -// To add new validation rules: -validateCustomRule(parsed) { - // Implement your validation logic - if (!this \ No newline at end of file +- concise problem statement +- implementation summary +- tests run +- regression risks +- screenshots or logs for user-visible changes when relevant diff --git a/doc/CRYPTOGRAPHY.md b/doc/CRYPTOGRAPHY.md index be80881..73d434b 100644 --- a/doc/CRYPTOGRAPHY.md +++ b/doc/CRYPTOGRAPHY.md @@ -1,2099 +1,26 @@ -# SecureBit.chat Cryptographic Implementation v4.02.985 +# Cryptography and Verification -## 🔐 Overview +## Release context -SecureBit.chat implements state-of-the-art cryptographic protocols providing **military-grade security** for peer-to-peer communications. Our cryptographic design prioritizes security, performance, and future-proofing against emerging threats including quantum computing. **Version 4.02.985 introduces revolutionary ECDH + DTLS + SAS security system for enhanced MITM protection.** +- Product release: `v4.8.5` +- Protocol version: `4.1` -**Cryptographic Strength:** 256+ bit security level -**Quantum Resistance:** Timeline > 2040 -**Standards Compliance:** NIST, FIPS, NSA Suite B, RFC 5280, RFC 5480, RFC 5763 -**Implementation:** Hardware-accelerated, constant-time algorithms with ECDH + DTLS + SAS authentication +## Session establishment ---- +SecureBit.chat uses ECDH-derived session material, DTLS-protected WebRTC transport, and a mandatory Short Authentication String (SAS) verification step. -## 📋 Table of Contents +The SAS is deterministic for both peers in the same authenticated session. Users compare the displayed code through an out-of-band channel and enter the matching code manually. Local success alone is insufficient: the session becomes verified only after both peers confirm. -1. [ECDH + DTLS + SAS Security System](#ecdh--dtls--sas-security-system) -2. [Cryptographic Primitives](#cryptographic-primitives) -3. [Key Management](#key-management) -4. [Encryption Implementation](#encryption-implementation) -5. [Production Security Logging](#production-security-logging) -6. [Digital Signatures](#digital-signatures) -7. [Mutex Framework](#mutex-framework-race-condition-protection) -8. [Key Derivation](#key-derivation) -9. [Perfect Forward Secrecy](#perfect-forward-secrecy) -10. [Security Analysis](#security-analysis) -11. [Implementation Details](#implementation-details) -12. [Performance Optimization](#performance-optimization) -13. [Compliance and Standards](#compliance-and-standards) -14. [ASN.1 Validation Framework](#asn1-validation-framework) +## Message protection ---- +- encrypted payloads are validated before decryption +- decrypted chat text is sanitized before entering React state or the UI +- replay and ordering controls remain part of the session layer -## 🛡️ ECDH + DTLS + SAS Security System +## Local key metadata -### Overview +Sensitive IndexedDB metadata is stored in encrypted envelopes. Legacy plaintext metadata remains readable through a migration path and is re-written in encrypted form when accessed. Corrupted encrypted metadata fails closed. -SecureBit.chat v4.02.985 introduces a revolutionary three-layer security system that eliminates traditional PAKE-based authentication in favor of a more robust and standardized approach: +## Scope note -1. **ECDH (Elliptic Curve Diffie-Hellman)** - Secure key exchange -2. **DTLS Fingerprint Verification** - Transport layer security validation -3. **SAS (Short Authentication String)** - MITM attack prevention - -### ECDH Key Exchange - -**Purpose:** Establish a shared secret between two parties without prior knowledge - -**Implementation:** -- **Curve:** P-384 (secp384r1) for maximum security -- **Key Generation:** Cryptographically secure random key pairs -- **Shared Secret:** Derived using ECDH protocol -- **Key Material:** Used for subsequent encryption and authentication - -**Security Properties:** -- **Forward Secrecy:** Each session uses unique key pairs -- **Perfect Forward Secrecy:** Past sessions cannot be compromised -- **MITM Resistance:** Requires knowledge of both private keys - -### DTLS Fingerprint Verification - -**Purpose:** Verify the authenticity of the WebRTC transport layer - -**Implementation:** -- **Certificate Extraction:** From WebRTC SDP offers/answers -- **Fingerprint Generation:** SHA-256 hash of the certificate -- **Verification:** Both parties verify each other's DTLS fingerprints -- **Transport Security:** Ensures connection is not intercepted - -**Security Properties:** -- **Transport Integrity:** Prevents connection hijacking -- **Certificate Validation:** Ensures authentic WebRTC certificates -- **MITM Detection:** Detects man-in-the-middle at transport layer - -### SAS (Short Authentication String) - -**Purpose:** Provide out-of-band verification to prevent MITM attacks - -**Implementation:** -- **Generation:** HKDF-based derivation from shared secret and DTLS fingerprints -- **Format:** 7-digit numeric code (0000000-9999999) -- **Sharing:** Generated once on Offer side, shared with Answer side -- **Verification:** Both users must confirm the same code - -**Security Properties:** -- **MITM Prevention:** Requires attacker to know the shared secret -- **User Verification:** Human-readable verification step -- **Standard Compliance:** Follows RFC 5763 recommendations - -### Security Flow - -``` -1. ECDH Key Exchange - ├── Generate key pairs (P-384) - ├── Exchange public keys - └── Derive shared secret - -2. DTLS Fingerprint Verification - ├── Extract certificates from SDP - ├── Generate SHA-256 fingerprints - └── Verify transport authenticity - -3. SAS Generation and Verification - ├── Generate SAS from shared secret + fingerprints - ├── Share SAS code between parties - └── Mutual verification by both users - -4. Connection Establishment - ├── All three layers verified - ├── Secure channel established - └── Communication begins -``` - -### Advantages Over PAKE - -| Aspect | PAKE (Previous) | ECDH + DTLS + SAS (Current) | -|--------|-----------------|------------------------------| -| **Dependencies** | libsodium required | Native Web Crypto API | -| **Standards** | Custom implementation | RFC-compliant protocols | -| **MITM Protection** | Single layer | Triple-layer defense | -| **User Experience** | Password-based | Code-based verification | -| **Security** | Good | Military-grade | -| **Maintenance** | Complex | Simplified | - -### Implementation Details - -**Key Components:** -- `_computeSAS()` - SAS generation using HKDF -- `_extractDTLSFingerprintFromSDP()` - Certificate extraction -- `_decodeKeyFingerprint()` - Key material processing -- `confirmVerification()` - Mutual verification handling - -**Security Considerations:** -- **Timing Attacks:** Constant-time operations -- **Side Channels:** No information leakage -- **Replay Protection:** Unique session identifiers -- **Forward Secrecy:** Session-specific keys - ---- - -## 🔧 Cryptographic Primitives - -### Primary Algorithms - -| Function | Algorithm | Key Size | Security Level | Standard | -|----------|-----------|----------|----------------|----------| -| **Symmetric Encryption** | AES-256-GCM | 256-bit | 256-bit | FIPS 197 | -| **Asymmetric Encryption** | ECDH P-384 | 384-bit | 192-bit | FIPS 186-4 | -| **Digital Signatures** | ECDSA P-384 | 384-bit | 192-bit | FIPS 186-4 | -| **File Metadata Signatures** | RSA-2048 | 2048-bit | 112-bit | FIPS 186-4 | -| **Hash Function** | SHA-384 | - | 192-bit | FIPS 180-4 | -| **Message Authentication** | HMAC-SHA-384 | 384-bit | 192-bit | FIPS 198-1 | -| **Key Derivation** | HKDF-SHA-384 | Variable | 192-bit | RFC 5869 | -| **ASN.1 Validation** | Complete DER Parser | - | Structural | RFC 5280, RFC 5480 | - -### Algorithm Selection Rationale - -#### **AES-256-GCM** -- **Chosen For:** Authenticated encryption, hardware acceleration -- **Security:** Proven security, quantum resistant until 2040+ -- **Performance:** Hardware AES-NI support on modern processors -- **Mode Benefits:** Combined confidentiality and authenticity - -#### **ECDH P-384 (secp384r1)** -- **Chosen For:** Key agreement with forward secrecy -- **Security:** Equivalent to 7680-bit RSA, NSA Suite B approved -- **Efficiency:** Smaller keys than RSA with equivalent security -- **Future-Proof:** Quantum resistant timeline > 15 years - -#### **ECDSA P-384** -- **Chosen For:** Digital signatures and authentication -- **Security:** Matches ECDH curve for consistent security level -- **Non-repudiation:** Cryptographic proof of message origin -- **Performance:** Faster than RSA signatures - -#### **SHA-384** -- **Chosen For:** Hash function matching curve security -- **Security:** 192-bit collision resistance, preimage resistance -- **Compatibility:** Matches P-384 curve security level -- **Standard:** Part of SHA-2 family, widely standardized - -#### **ASN.1 DER Parser (NEW)** -- **Chosen For:** Complete key structure validation -- **Security:** Prevents key manipulation attacks -- **Compliance:** Full PKCS and RFC standards adherence -- **Performance:** < 10ms validation time - ---- - -## 🔑 Key Management - -### Key Hierarchy - -``` -┌─────────────────────────────────────────────────────────────┐ -│ Master Key Material │ -├─────────────────────────────────────────────────────────────┤ -│ ECDH Private Key (384-bit, non-extractable) │ -│ ├── Shared Secret (384-bit, ephemeral) │ -│ │ ├── Encryption Key (256-bit AES) │ -│ │ ├── MAC Key (384-bit HMAC) │ -│ │ ├── Metadata Key (256-bit AES) │ -│ │ └── Fingerprint Key (256-bit, extractable only) │ -│ └── Key Versions (PFS, rotated every 5 minutes) │ -├─────────────────────────────────────────────────────────────┤ -│ ECDSA Private Key (384-bit, non-extractable) │ -│ ├── Message Signing │ -│ ├── Key Package Signing │ -│ └── Authentication Proofs │ -├─────────────────────────────────────────────────────────────┤ -│ Nested Encryption Key (256-bit AES, hardware-generated) │ -│ ├── Additional encryption layer │ -│ └── Rotated every 1000 messages │ -├─────────────────────────────────────────────────────────────┤ -│ ASN.1 Validation Keys (Structural verification) │ -│ ├── OID validation (P-256/P-384 only) │ -│ ├── EC point format verification (0x04 uncompressed) │ -│ ├── SPKI structure validation │ -│ └── Key size limits (50-2000 bytes) │ -└─────────────────────────────────────────────────────────────┘ -``` - -### Key Generation - -#### **ECDH Key Pair Generation** -```javascript -async function generateECDHKeyPair() { - try { - // Primary: P-384 curve - const keyPair = await crypto.subtle.generateKey( - { - name: 'ECDH', - namedCurve: 'P-384' // secp384r1 - }, - false, // Non-extractable for security - ['deriveKey'] - ); - - // Validate key generation - await validateKeyPair(keyPair); - return keyPair; - - } catch (p384Error) { - // Fallback: P-256 curve - return await crypto.subtle.generateKey( - { - name: 'ECDH', - namedCurve: 'P-256' // secp256r1 - }, - false, - ['deriveKey'] - ); - } -} -``` - -#### **ECDSA Key Pair Generation** -```javascript -async function generateECDSAKeyPair() { - return await crypto.subtle.generateKey( - { - name: 'ECDSA', - namedCurve: 'P-384' - }, - false, // Non-extractable for security - ['sign', 'verify'] - ); -} -``` - -### Key Storage and Protection - -#### **Non-Extractable Keys** -- All private keys generated with `extractable: false` -- Hardware security module (HSM) storage when available -- Keys cannot be exported from secure storage -- Protection against memory dump attacks - -#### **Key Validation** -```javascript -async function validateKeyPair(keyPair) { - // Verify key algorithm and curve - assert(keyPair.privateKey.algorithm.name === 'ECDH'); - assert(keyPair.privateKey.algorithm.namedCurve === 'P-384'); - - // Verify key properties - assert(keyPair.privateKey.extractable === false); - assert(keyPair.privateKey.usages.includes('deriveKey')); - - // Test key functionality - const testData = crypto.getRandomValues(new Uint8Array(32)); - const derived = await crypto.subtle.deriveKey(/* ... */); - assert(derived instanceof CryptoKey); -} -``` - -### Secure Key Storage System - -#### **WeakMap-Based Key Isolation** -```javascript -class SecureKeyManager { - constructor() { - this._secureKeyStorage = new WeakMap(); - this._keyMetadata = new WeakMap(); - this._initializeSecureKeyStorage(); - } - - _initializeSecureKeyStorage() { - // Initialize secure storage with validation - this._secureKeyStorage.set(this, {}); - this._keyMetadata.set(this, { - creationTime: Date.now(), - rotationCount: 0, - lastAccess: Date.now() - }); - } - - _getSecureKey(keyName) { - const storage = this._secureKeyStorage.get(this); - const metadata = this._keyMetadata.get(this); - - if (!storage || !storage[keyName]) { - throw new Error(`Key ${keyName} not found in secure storage`); - } - - // Update access metadata - metadata.lastAccess = Date.now(); - return storage[keyName]; - } - - _setSecureKey(keyName, keyValue, options = {}) { - const storage = this._secureKeyStorage.get(this); - const metadata = this._keyMetadata.get(this); - - // Validate key value - if (options.validate) { - this._validateKeyValue(keyValue, keyName); - } - - // Store key securely - storage[keyName] = keyValue; - metadata.lastAccess = Date.now(); - - // Start security monitoring if not already active - this._startKeySecurityMonitoring(); - } - - _validateKeyValue(keyValue, keyName) { - // Type validation - if (!keyValue || typeof keyValue !== 'object') { - throw new Error(`Invalid key value for ${keyName}`); - } - - // CryptoKey validation - if (keyValue instanceof CryptoKey) { - if (keyValue.extractable) { - throw new Error(`Extractable keys are not allowed for ${keyName}`); - } - } - - // Buffer validation - if (keyValue instanceof ArrayBuffer || keyValue instanceof Uint8Array) { - if (keyValue.byteLength < 32) { - throw new Error(`Key ${keyName} too short for security requirements`); - } - } - } - - _rotateKeys() { - const metadata = this._keyMetadata.get(this); - metadata.rotationCount++; - metadata.lastRotation = Date.now(); - - // Implement key rotation logic - this._performKeyRotation(); - } - - _emergencyKeyWipe() { - // Clear all keys from memory - this._secureKeyStorage.delete(this); - this._keyMetadata.delete(this); - - // Force garbage collection if available - if (typeof gc === 'function') { - gc(); - } - } - - _startKeySecurityMonitoring() { - // Monitor key lifetime and access patterns - setInterval(() => { - this._checkKeySecurity(); - }, 30000); // Check every 30 seconds - } - - _checkKeySecurity() { - const metadata = this._keyMetadata.get(this); - const now = Date.now(); - - // Check key age - if (now - metadata.creationTime > 3600000) { // 1 hour - this._rotateKeys(); - } - - // Check for suspicious access patterns - if (now - metadata.lastAccess > 300000) { // 5 minutes - this._logSecurityWarning('Key access timeout detected'); - } - } -} -``` - -#### **Backward Compatibility** -```javascript -// Getters and setters for existing code compatibility -get encryptionKey() { - return this._getSecureKey('encryptionKey'); -} - -set encryptionKey(value) { - this._setSecureKey('encryptionKey', value, { validate: true }); -} - -get macKey() { - return this._getSecureKey('macKey'); -} - -set macKey(value) { - this._setSecureKey('macKey', value, { validate: true }); -} -``` - -#### **Security Benefits** -- **Memory Protection:** Keys inaccessible via direct property access -- **Debugger Resistance:** Keys not visible in browser developer tools -- **Access Control:** All key access goes through validation -- **Automatic Cleanup:** Keys automatically removed from memory -- **Threat Response:** Immediate key destruction capabilities - ---- - -## 🔒 Encryption Implementation - -### Triple-Layer Encryption Architecture - -``` -Original Message - ↓ -┌─────────────────┐ -│ Layer 1: │ -│ Standard AES │ ← Primary encryption with metadata -│ (Enhanced) │ -└─────────┬───────┘ - ↓ -┌─────────────────┐ -│ Layer 2: │ -│ Nested AES │ ← Additional security layer -│ (Independent) │ -└─────────┬───────┘ - ↓ -┌─────────────────┐ -│ Layer 3: │ -│ WebRTC DTLS │ ← Transport layer encryption -│ (Built-in) │ -└─────────┬───────┘ - ↓ - Network Packet -``` - -### Enhanced Message Encryption - -#### **Message Structure** -```javascript -const enhancedMessage = { - // Encrypted metadata (AES-256-GCM) - metadataIv: [12 bytes], - metadataData: [encrypted metadata], - - // Encrypted message content (AES-256-GCM) - messageIv: [12 bytes], - messageData: [encrypted + padded content], - - // Authentication (HMAC-SHA-384) - mac: [48 bytes], - - // Version and format - version: "4.0", - format: "enhanced" -}; -``` - -#### **Encryption Process** -```javascript -async function encryptMessage(message, encryptionKey, macKey, metadataKey, messageId, sequenceNumber) { - // Step 1: Prepare message with padding - const messageData = new TextEncoder().encode(message); - const paddingSize = 16 - (messageData.length % 16); - const paddedMessage = new Uint8Array(messageData.length + paddingSize); - paddedMessage.set(messageData); - paddedMessage.set(crypto.getRandomValues(new Uint8Array(paddingSize)), messageData.length); - - // Step 2: Generate IVs - const messageIv = crypto.getRandomValues(new Uint8Array(12)); - const metadataIv = crypto.getRandomValues(new Uint8Array(12)); - - // Step 3: Encrypt message content - const encryptedMessage = await crypto.subtle.encrypt( - { name: 'AES-GCM', iv: messageIv }, - encryptionKey, - paddedMessage - ); - - // Step 4: Prepare and encrypt metadata - const metadata = { - id: messageId, - timestamp: Date.now(), - sequenceNumber: sequenceNumber, - originalLength: messageData.length, - version: '4.0' - }; - - const metadataStr = JSON.stringify(sortObjectKeys(metadata)); - const encryptedMetadata = await crypto.subtle.encrypt( - { name: 'AES-GCM', iv: metadataIv }, - metadataKey, - new TextEncoder().encode(metadataStr) - ); - - // Step 5: Create payload and compute MAC - 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 = sortObjectKeys(payload); - const payloadStr = JSON.stringify(sortedPayload); - - const mac = await crypto.subtle.sign( - 'HMAC', - macKey, - new TextEncoder().encode(payloadStr) - ); - - payload.mac = Array.from(new Uint8Array(mac)); - - return payload; -} -``` - -### Nested Encryption Layer - -#### **Purpose and Implementation** -```javascript -async function applyNestedEncryption(data, nestedKey, counter) { - // Create unique IV for each encryption - const uniqueIV = new Uint8Array(12); - uniqueIV.set(baseIV); - uniqueIV[11] = (counter++) & 0xFF; - - // Apply additional AES-GCM encryption - const encrypted = await crypto.subtle.encrypt( - { name: 'AES-GCM', iv: uniqueIV }, - nestedKey, - data - ); - - // Combine IV and encrypted data - const result = new Uint8Array(12 + encrypted.byteLength); - result.set(uniqueIV, 0); - result.set(new Uint8Array(encrypted), 12); - - return result.buffer; -} -``` - -#### **Security Benefits** -- **Defense in Depth:** Multiple independent encryption layers -- **Algorithm Diversity:** Protection against algorithm-specific attacks -- **Implementation Isolation:** Separate keys and implementations -- **Future-Proofing:** Additional security against unknown vulnerabilities - ---- - -## 🛡️ Production Security Logging - -### Secure Logging System - -#### **Environment-Aware Logging** -```javascript -class SecureLogger { - constructor() { - this._isProduction = this._detectProductionMode(); - this._logCounters = new Map(); - this._rateLimitWindow = 60000; // 1 minute - this._maxLogsPerWindow = 100; - } - - _detectProductionMode() { - // Detect production environment - return window.location.hostname !== 'localhost' && - window.location.hostname !== '127.0.0.1' && - !window.location.hostname.includes('dev') && - !window.location.hostname.includes('test'); - } - - _secureLog(level, message, data = null) { - // Check rate limiting - if (this._isRateLimited(level)) { - return; - } - - // Sanitize data - const sanitizedData = this._sanitizeData(data); - - // Environment-specific logging - if (this._isProduction) { - this._productionLog(level, message, sanitizedData); - } else { - this._developmentLog(level, message, sanitizedData); - } - - // Update rate limiting counters - this._updateLogCounter(level); - } - - _productionLog(level, message, data) { - // Production: Only critical errors and warnings - if (level === 'error' || level === 'warn') { - console[level](`[SecureBit] ${message}`, data); - } - } - - _developmentLog(level, message, data) { - // Development: Full debugging information (sanitized) - console[level](`[SecureBit:${level.toUpperCase()}] ${message}`, data); - } - - _sanitizeData(data) { - if (!data) return null; - - const sanitized = {}; - const sensitivePatterns = [ - /key/i, /token/i, /password/i, /secret/i, /auth/i, - /encryption/i, /private/i, /signature/i, /mac/i - ]; - - for (const [key, value] of Object.entries(data)) { - // Check if key contains sensitive information - const isSensitive = sensitivePatterns.some(pattern => pattern.test(key)); - - if (isSensitive) { - sanitized[key] = '[REDACTED]'; - } else if (value instanceof ArrayBuffer || value instanceof Uint8Array) { - sanitized[key] = `[Buffer: ${value.byteLength} bytes]`; - } else if (typeof value === 'string' && value.length > 100) { - sanitized[key] = value.substring(0, 50) + '...'; - } else if (typeof value === 'object' && value !== null) { - sanitized[key] = this._sanitizeData(value); - } else { - sanitized[key] = value; - } - } - - return sanitized; - } - - _isRateLimited(level) { - const now = Date.now(); - const key = `${level}_${Math.floor(now / this._rateLimitWindow)}`; - const count = this._logCounters.get(key) || 0; - - return count >= this._maxLogsPerWindow; - } - - _updateLogCounter(level) { - const now = Date.now(); - const key = `${level}_${Math.floor(now / this._rateLimitWindow)}`; - const count = this._logCounters.get(key) || 0; - - this._logCounters.set(key, count + 1); - - // Cleanup old counters - this._cleanupOldCounters(now); - } - - _cleanupOldCounters(currentTime) { - const cutoff = currentTime - (this._rateLimitWindow * 10); // Keep 10 windows - - for (const [key] of this._logCounters) { - const timestamp = parseInt(key.split('_')[1]) * this._rateLimitWindow; - if (timestamp < cutoff) { - this._logCounters.delete(key); - } - } - } - - // Public logging methods - debug(message, data) { - this._secureLog('debug', 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); - } -} -``` - -#### **Usage Examples** -```javascript -const logger = new SecureLogger(); - -// Secure logging with data sanitization -logger.debug('Connection established', { - userId: 'user123', - encryptionKey: new Uint8Array(32), - messageContent: 'Hello, world!', - sessionId: 'abc123def456' -}); - -// Production output: No debug logs -// Development output: [SecureBit:DEBUG] Connection established { userId: 'user123', encryptionKey: '[REDACTED]', messageContent: 'Hello, world!', sessionId: '[REDACTED]' } -``` - -#### **Security Benefits** -- **Data Protection:** Encryption keys, message content, and tokens are automatically sanitized -- **Privacy Preservation:** User privacy maintained in production logs -- **Debugging Support:** Safe debugging information without sensitive content -- **Rate Limiting:** Prevents log spam and memory exhaustion -- **Compliance:** Meets privacy regulations and security standards - ---- - -## ✍️ Digital Signatures - -### ECDSA Implementation - -#### **Signature Generation** -```javascript -async function signData(privateKey, data) { - const encoder = new TextEncoder(); - const dataBuffer = typeof data === 'string' ? encoder.encode(data) : data; - - try { - // Primary: SHA-384 - const signature = await crypto.subtle.sign( - { - name: 'ECDSA', - hash: 'SHA-384' - }, - privateKey, - dataBuffer - ); - - return Array.from(new Uint8Array(signature)); - - } catch (sha384Error) { - // Fallback: SHA-256 - const signature = await crypto.subtle.sign( - { - name: 'ECDSA', - hash: 'SHA-256' - }, - privateKey, - dataBuffer - ); - - return Array.from(new Uint8Array(signature)); - } -} -``` - -#### **Signature Verification** -```javascript -async function verifySignature(publicKey, signature, data) { - const encoder = new TextEncoder(); - const dataBuffer = typeof data === 'string' ? encoder.encode(data) : data; - const signatureBuffer = new Uint8Array(signature); - - try { - // Primary: SHA-384 - const isValid = await crypto.subtle.verify( - { - name: 'ECDSA', - hash: 'SHA-384' - }, - publicKey, - signatureBuffer, - dataBuffer - ); - - return isValid; - - } catch (sha384Error) { - // Fallback: SHA-256 - const isValid = await crypto.subtle.verify( - { - name: 'ECDSA', - hash: 'SHA-256' - }, - publicKey, - signatureBuffer, - dataBuffer - ); - - return isValid; - } -} -``` - -### Signed Key Exchange - -#### **Key Package Structure** -```javascript -const signedKeyPackage = { - keyType: 'ECDH', // or 'ECDSA' - keyData: [/* exported public key bytes */], - timestamp: Date.now(), - version: '4.0', - signature: [/* ECDSA signature bytes */] -}; -``` - -#### **Key Package Signing** -```javascript -async function exportPublicKeyWithSignature(publicKey, signingKey, keyType) { - // Export public key - const exported = await crypto.subtle.exportKey('spki', publicKey); - const keyData = Array.from(new Uint8Array(exported)); - - // Validate key structure - await validateKeyStructure(keyData, keyType); -``` - -### RSA-2048 File Metadata Signatures - -#### **RSA Key Generation** -```javascript -async function generateRSAKeyPair() { - 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'] - ); - - return keyPair; -} -``` - -#### **File Metadata Signing** -```javascript -async function signFileMetadata(metadata, privateKey) { - 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)); -} -``` - -#### **File Metadata Verification** -```javascript -async function verifyFileMetadata(metadata, signature, publicKey) { - 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); - - return await crypto.subtle.verify( - 'RSASSA-PKCS1-v1_5', - publicKey, - signatureBuffer, - data - ); -} -``` - -#### **RSA Signature Benefits** -- **File Integrity:** Cryptographic proof of file metadata authenticity -- **Source Verification:** Ensures files come from verified sources -- **Tamper Detection:** Prevents metadata manipulation -- **Compliance:** Meets enterprise security requirements - - // Create key package - const keyPackage = { - keyType, - keyData, - timestamp: Date.now(), - version: '4.0' - }; - - // Sign the key package - const packageString = JSON.stringify(keyPackage); - const signature = await signData(signingKey, packageString); - - return { - ...keyPackage, - signature - }; -} -``` - -### Authentication Proofs - -#### **Mutual Authentication** -```javascript -async function createAuthProof(challenge, privateKey, publicKey) { - // Validate challenge - if (!challenge || !challenge.challenge || !challenge.timestamp) { - throw new Error('Invalid challenge structure'); - } - - // Check challenge age (max 2 minutes) - const challengeAge = Date.now() - challenge.timestamp; - if (challengeAge > 120000) { - throw new Error('Challenge expired'); - } - - // Create proof data - const proofData = { - challenge: challenge.challenge, - timestamp: challenge.timestamp, - nonce: challenge.nonce, - responseTimestamp: Date.now(), - publicKeyHash: await hashPublicKey(publicKey) - }; - - // Sign the proof - const proofString = JSON.stringify(proofData); - const signature = await signData(privateKey, proofString); - - return { - ...proofData, - signature, - version: '4.0' - }; -} -``` - ---- - -## 🔒 Mutex Framework (Race Condition Protection) - -### Connection Security Framework - -#### **Advanced Mutex Implementation** -```javascript -class ConnectionMutexManager { - constructor() { - this._mutexLocks = new Map(); - this._operationTimeouts = new Map(); - this._defaultTimeout = 15000; // 15 seconds - this._cleanupInterval = 30000; // 30 seconds - } - - async _withMutex(mutexName, operation, timeout = this._defaultTimeout) { - const operationId = this._generateOperationId(); - const startTime = Date.now(); - - // Check if mutex is already locked - if (this._mutexLocks.has(mutexName)) { - throw new Error(`Mutex ${mutexName} is already locked`); - } - - // Acquire mutex - this._mutexLocks.set(mutexName, { - operationId, - startTime, - timeout - }); - - // Set timeout for automatic cleanup - const timeoutId = setTimeout(() => { - this._handleMutexTimeout(mutexName, operationId); - }, timeout); - - try { - // Execute operation with phase tracking - const result = await this._executeWithPhaseTracking(operation, operationId); - - // Clear timeout and release mutex - clearTimeout(timeoutId); - this._mutexLocks.delete(mutexName); - this._operationTimeouts.delete(operationId); - - return result; - - } catch (error) { - // Handle operation failure - clearTimeout(timeoutId); - this._mutexLocks.delete(mutexName); - this._operationTimeouts.delete(operationId); - - // Perform cleanup for failed operations - await this._cleanupFailedOperation(mutexName, operationId, error); - throw error; - } - } - - _generateOperationId() { - return `op_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`; - } - - async _executeWithPhaseTracking(operation, operationId) { - const phases = [ - 'key_generation', - 'connection_validation', - 'channel_establishment', - 'security_verification' - ]; - - for (const phase of phases) { - try { - this._logPhaseStart(operationId, phase); - await this._executePhase(operation, phase); - this._logPhaseSuccess(operationId, phase); - } catch (error) { - this._logPhaseFailure(operationId, phase, error); - throw error; - } - } - - return await operation(); - } - - async _cleanupFailedOperation(mutexName, operationId, error) { - // Cleanup resources for failed operations - await this._cleanupFailedOfferCreation(operationId); - - // Log cleanup completion - this._logCleanupComplete(operationId, error); - } - - _handleMutexTimeout(mutexName, operationId) { - // Handle mutex timeout - this._logMutexTimeout(mutexName, operationId); - - // Force release mutex - this._mutexLocks.delete(mutexName); - this._operationTimeouts.delete(operationId); - - // Trigger emergency cleanup - this._emergencyCleanup(operationId); - } - - _emergencyCleanup(operationId) { - // Emergency cleanup for deadlock situations - this._logEmergencyCleanup(operationId); - - // Force garbage collection if available - if (typeof gc === 'function') { - gc(); - } - } - - // Logging methods - _logPhaseStart(operationId, phase) { - console.debug(`[Mutex] Operation ${operationId} starting phase: ${phase}`); - } - - _logPhaseSuccess(operationId, phase) { - console.debug(`[Mutex] Operation ${operationId} completed phase: ${phase}`); - } - - _logPhaseFailure(operationId, phase, error) { - console.error(`[Mutex] Operation ${operationId} failed in phase: ${phase}`, error); - } - - _logCleanupComplete(operationId, error) { - console.warn(`[Mutex] Cleanup completed for operation ${operationId}`, error); - } - - _logMutexTimeout(mutexName, operationId) { - console.error(`[Mutex] Timeout for mutex ${mutexName}, operation ${operationId}`); - } - - _logEmergencyCleanup(operationId) { - console.error(`[Mutex] Emergency cleanup triggered for operation ${operationId}`); - } -} -``` - -#### **Usage Examples** -```javascript -const mutexManager = new ConnectionMutexManager(); - -// Mutex-protected connection operations -await mutexManager._withMutex('connectionOperation', async () => { - // Atomic key generation - await this._generateEncryptionKeys(); - - // Connection validation - await this._validateConnectionParameters(); - - // Secure channel establishment - await this._establishSecureChannel(); - - // Security verification - await this._verifySecurityParameters(); -}); -``` - -#### **Security Benefits** -- **Race Condition Prevention:** Eliminates timing-based attacks during key generation -- **Connection Integrity:** Ensures atomic connection establishment -- **Error Recovery:** Automatic rollback for failed operations -- **Deadlock Prevention:** Timeout-based emergency recovery -- **Diagnostic Capability:** Comprehensive phase tracking for error identification - ---- - -## 🔗 Key Derivation - -### HKDF Implementation (RFC 5869 Compliant) - -#### **Enhanced Key Derivation with Proper Separation** -```javascript -async function deriveSharedKeys(privateKey, publicKey, salt) { - // Validate inputs - assertCryptoKey(privateKey, 'ECDH', ['deriveKey']); - assertCryptoKey(publicKey, 'ECDH', []); - - 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(); - - // Step 1: Derive raw ECDH shared secret using pure ECDH - const rawKeyMaterial = await crypto.subtle.deriveKey( - { - name: 'ECDH', - public: publicKey - }, - privateKey, - { - name: 'AES-GCM', - length: 256 - }, - true, // Extractable for HKDF processing - ['encrypt', 'decrypt'] - ); - - // Export the raw key material - const rawKeyData = await crypto.subtle.exportKey('raw', rawKeyMaterial); - - // Import as HKDF key material for further derivation - const rawSharedSecret = await crypto.subtle.importKey( - 'raw', - rawKeyData, - { - name: 'HKDF', - hash: 'SHA-256' - }, - false, - ['deriveKey'] - ); - - // Step 2: Derive specific keys using HKDF with unique info parameters - // Each key uses unique info parameter for proper separation - - // Derive message encryption key (messageKey) - const messageKey = await crypto.subtle.deriveKey( - { - name: 'HKDF', - hash: 'SHA-256', - salt: saltBytes, - info: encoder.encode('message-encryption-v4') - }, - rawSharedSecret, - { - name: 'AES-GCM', - length: 256 - }, - false, // Non-extractable for enhanced security - ['encrypt', 'decrypt'] - ); - - // Derive MAC key for message authentication - const macKey = await crypto.subtle.deriveKey( - { - name: 'HKDF', - hash: 'SHA-256', - salt: saltBytes, - info: encoder.encode('message-authentication-v4') - }, - rawSharedSecret, - { - name: 'HMAC', - hash: 'SHA-256' - }, - false, // Non-extractable - ['sign', 'verify'] - ); - - // Derive Perfect Forward Secrecy key (pfsKey) - const pfsKey = await crypto.subtle.deriveKey( - { - name: 'HKDF', - hash: 'SHA-256', - salt: saltBytes, - info: encoder.encode('perfect-forward-secrecy-v4') - }, - rawSharedSecret, - { - name: 'AES-GCM', - length: 256 - }, - false, // Non-extractable - ['encrypt', 'decrypt'] - ); - - // Derive separate metadata encryption key - const metadataKey = await crypto.subtle.deriveKey( - { - name: 'HKDF', - hash: 'SHA-256', - salt: saltBytes, - info: encoder.encode('metadata-protection-v4') - }, - rawSharedSecret, - { - name: 'AES-GCM', - length: 256 - }, - false, // Non-extractable - ['encrypt', 'decrypt'] - ); - - // Generate temporary extractable key for fingerprint calculation - const fingerprintKey = await crypto.subtle.deriveKey( - { - name: 'HKDF', - hash: 'SHA-256', - salt: saltBytes, - info: encoder.encode('fingerprint-generation-v4') - }, - rawSharedSecret, - { - name: 'AES-GCM', - length: 256 - }, - true, // Extractable only for fingerprint - ['encrypt', 'decrypt'] - ); - - // Generate key fingerprint for verification - const fingerprintKeyData = await crypto.subtle.exportKey('raw', fingerprintKey); - const fingerprint = await generateKeyFingerprint(Array.from(new Uint8Array(fingerprintKeyData))); - - return { - messageKey, - macKey, - pfsKey, - metadataKey, - fingerprint, - timestamp: Date.now(), - version: '4.0' - }; -} -``` - -#### **HKDF Security Properties** -- **RFC 5869 Compliance:** Full adherence to HMAC-based Extract-and-Expand Key Derivation Function standard -- **Proper Key Separation:** Each derived key uses unique `info` parameter to prevent key reuse -- **Salt Security:** 64-byte cryptographically secure salt for each derivation -- **Non-Extractable Keys:** All operational keys are hardware-protected and non-exportable -- **Forward Secrecy:** Independent key derivation for each session prevents key compromise propagation -- **Algorithm Consistency:** SHA-256 hash function for optimal compatibility and performance - -### Key Fingerprinting - -#### **Cryptographic Fingerprint Generation** -```javascript -async function generateKeyFingerprint(keyData) { - const keyBuffer = new Uint8Array(keyData); - - // Use SHA-384 for fingerprint generation - const hashBuffer = await crypto.subtle.digest('SHA-384', keyBuffer); - const hashArray = Array.from(new Uint8Array(hashBuffer)); - - // Format as colon-separated hex pairs (first 12 bytes) - return hashArray.slice(0, 12) - .map(b => b.toString(16).padStart(2, '0')) - .join(':'); -} -``` - -#### **Public Key Hashing** -```javascript -async function hashPublicKey(publicKey) { - 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(''); -} -``` - ---- - -## ⏰ Perfect Forward Secrecy - -### Key Rotation Protocol - -#### **Automatic Key Rotation** -```javascript -class PFSKeyManager { - constructor() { - this.keyRotationInterval = 300000; // 5 minutes - this.lastKeyRotation = Date.now(); - this.currentKeyVersion = 0; - this.keyVersions = new Map(); - this.oldKeys = new Map(); - this.maxOldKeys = 3; // Keep last 3 versions - } - - shouldRotateKeys() { - const now = Date.now(); - const timeSinceLastRotation = now - this.lastKeyRotation; - - // Rotate every 5 minutes or after 100 messages - return timeSinceLastRotation > this.keyRotationInterval || - this.messageCounter % 100 === 0; - } - - async rotateKeys() { - if (!this.isConnected() || !this.isVerified) { - return false; - } - - try { - // Signal key rotation to peer - const rotationSignal = { - type: 'key_rotation_signal', - newVersion: this.currentKeyVersion + 1, - timestamp: Date.now() - }; - - this.dataChannel.send(JSON.stringify(rotationSignal)); - - // Wait for peer confirmation - return new Promise((resolve) => { - this.pendingRotation = { - newVersion: this.currentKeyVersion + 1, - resolve: resolve - }; - - // Timeout after 5 seconds - setTimeout(() => { - if (this.pendingRotation) { - this.pendingRotation.resolve(false); - this.pendingRotation = null; - } - }, 5000); - }); - - } catch (error) { - console.error('Key rotation failed:', error); - return false; - } - } - - cleanupOldKeys() { - const now = Date.now(); - const maxKeyAge = 900000; // 15 minutes - - for (const [version, keySet] of this.oldKeys.entries()) { - if (now - keySet.timestamp > maxKeyAge) { - this.oldKeys.delete(version); - console.log(`Old PFS keys cleaned up: version ${version}`); - } - } - } -} -``` - -#### **Key Version Management** -```javascript -getKeysForVersion(version) { - // Check old keys first - const oldKeySet = this.oldKeys.get(version); - if (oldKeySet && oldKeySet.encryptionKey && oldKeySet.macKey && oldKeySet.metadataKey) { - return { - encryptionKey: oldKeySet.encryptionKey, - macKey: oldKeySet.macKey, - metadataKey: oldKeySet.metadataKey - }; - } - - // Check current version - if (version === this.currentKeyVersion) { - if (this.encryptionKey && this.macKey && this.metadataKey) { - return { - encryptionKey: this.encryptionKey, - macKey: this.macKey, - metadataKey: this.metadataKey - }; - } - } - - console.error(`No valid keys found for version ${version}`); - return null; -} -``` - -### Forward Secrecy Guarantees - -#### **Security Properties** -- **Computational Forward Secrecy:** Past sessions cannot be decrypted even with current keys -- **Perfect Forward Secrecy:** Past sessions cannot be decrypted even with long-term keys -- **Post-Compromise Security:** Future sessions remain secure after key compromise -- **Key Independence:** Each session uses independent cryptographic material - -#### **Implementation Verification** -```javascript -async function verifyPFS() { - // Check key rotation is active - const hasKeyRotation = this.keyRotationInterval > 0; - const hasVersionTracking = this.currentKeyVersion !== undefined; - const hasOldKeyCleanup = this.oldKeys instanceof Map; - - // Verify automatic rotation - const rotationWorking = typeof this.shouldRotateKeys === 'function'; - - return hasKeyRotation && hasVersionTracking && hasOldKeyCleanup && rotationWorking; -} -``` - ---- - -## 🔬 Security Analysis - -### Cryptographic Security Levels - -| Component | Algorithm | Key Size | Classical Security | Quantum Security | Post-Quantum Timeline | -|-----------|-----------|----------|-------------------|------------------|----------------------| -| **ECDH** | P-384 | 384-bit | 192-bit | 64-bit | 2040+ | -| **ECDSA** | P-384 | 384-bit | 192-bit | 64-bit | 2040+ | -| **AES** | AES-256 | 256-bit | 256-bit | 128-bit | 2080+ | -| **SHA** | SHA-384 | - | 192-bit | 96-bit | 2050+ | -| **HMAC** | HMAC-SHA-384 | 384-bit | 192-bit | 96-bit | 2050+ | - -### Attack Resistance Analysis - -#### **Classical Attacks** -- ✅ **Brute Force:** Computationally infeasible (2^256 operations) -- ✅ **Cryptanalysis:** No known practical attacks on used algorithms -- ✅ **Side-Channel:** Constant-time implementations, hardware protection -- ✅ **Implementation:** Secure coding practices, input validation - -#### **Quantum Attacks** -- ⚠️ **Shor's Algorithm:** Affects ECDH/ECDSA (timeline > 15 years) -- ✅ **Grover's Algorithm:** AES-256 remains secure (128-bit post-quantum) -- ✅ **Hash Functions:** SHA-384 maintains adequate security -- 🔄 **Mitigation:** Post-quantum algorithms planned for 2026 - -#### **Advanced Persistent Threats** -- ✅ **Nation-State:** Multiple security layers, PFS -- ✅ **Zero-Day Exploits:** Defense in depth, algorithm diversity -- ✅ **Supply Chain:** Hardware-based key generation -- ✅ **Insider Threats:** Non-extractable keys, audit trails - -### Cryptographic Assumptions - -#### **Computational Assumptions** -1. **Elliptic Curve Discrete Logarithm Problem (ECDLP)** is hard -2. **AES is a secure pseudorandom permutation** -3. **SHA-384 is collision and preimage resistant** -4. **Random number generators are cryptographically secure** - -#### **Implementation Assumptions** -1. **Hardware provides secure random number generation** -2. **Browser crypto APIs are correctly implemented** -3. **Side-channel attacks are mitigated by hardware** -4. **Memory protection prevents key extraction** - ---- - -## ⚡ Performance Optimization - -### Hardware Acceleration - -#### **AES-NI Utilization** -```javascript -// Leverages hardware AES acceleration when available -const encryptWithHardwareAcceleration = async (data, key) => { - // Browser automatically uses AES-NI if available - return await crypto.subtle.encrypt( - { name: 'AES-GCM', iv: generateIV() }, - key, - data - ); -}; -``` - -#### **Performance Benchmarks** - -| Operation | Software (ms) | Hardware (ms) | Speedup | -|-----------|---------------|---------------|---------| -| **AES Encryption** | 2.5 | 0.3 | 8.3x | -| **ECDH Key Agreement** | 15.0 | 5.0 | 3.0x | -| **ECDSA Signing** | 12.0 | 4.0 | 3.0x | -| **SHA-384 Hashing** | 1.5 | 0.5 | 3.0x | -| **Overall Pipeline** | 31.0 | 9.8 | 3.2x | - -### Memory Management - -#### **Secure Memory Practices** -```javascript -class SecureMemoryManager { - static clearSensitiveData(buffer) { - // Overwrite sensitive data - if (buffer instanceof ArrayBuffer) { - const view = new Uint8Array(buffer); - crypto.getRandomValues(view); - } - } - - static zeroMemory(array) { - // Zero out array contents - for (let i = 0; i < array.length; i++) { - array[i] = 0; - } - } - - static secureDispose(cryptoKey) { - // Browser handles secure disposal of CryptoKey objects - // Keys are automatically cleared when no longer referenced - cryptoKey = null; - } -} -``` - -### Constant-Time Operations - -#### **Timing Attack Prevention** -```javascript -// Constant-time comparison for preventing timing attacks -function constantTimeEquals(a, b) { - if (a.length !== b.length) { - return false; - } - - let result = 0; - for (let i = 0; i < a.length; i++) { - result |= a[i] ^ b[i]; - } - - return result === 0; -} - -// Use constant-time comparison for MAC verification -function verifyMAC(expected, actual) { - return constantTimeEquals( - new Uint8Array(expected), - new Uint8Array(actual) - ); -} -``` - ---- - -## 📊 Compliance and Standards - -### Standards Compliance - -#### **NIST Standards** -- ✅ **NIST SP 800-57:** Key Management Guidelines -- ✅ **FIPS 186-4:** Digital Signature Standard (ECDSA) -- ✅ **FIPS 197:** Advanced Encryption Standard (AES) -- ✅ **FIPS 180-4:** Secure Hash Standard (SHA-384) -- ✅ **FIPS 198-1:** Keyed-Hash Message Authentication Code - -#### **RFC Standards** -- ✅ **RFC 5869:** HMAC-based Extract-and-Expand Key Derivation Function -- ✅ **RFC 6979:** Deterministic Usage of DSA and ECDSA -- ✅ **RFC 7748:** Elliptic Curves for Security -- ✅ **RFC 8439:** ChaCha20-Poly1305 (reference implementation) - -#### **Industry Standards** -- ✅ **NSA Suite B:** Cryptographic algorithms for national security -- ✅ **Common Criteria:** Security functional requirements -- ✅ **ISO 27001:** Information security management -- ✅ **PKCS #11:** Cryptographic Token Interface - -### Certification Status - -| Standard | Status | Timeline | -|----------|--------|----------| -| **FIPS 140-2 Level 2** | 🔄 In Progress | Q2 2025 | -| **Common Criteria EAL4+** | 📋 Planned | Q3 2025 | -| **FIPS 140-3** | 📋 Planned | Q4 2025 | -| **NSA Commercial Solutions** | 🔄 In Progress | Q1 2026 | - -### Regulatory Compliance - -#### **Data Protection Regulations** -- ✅ **GDPR Article 32:** Technical and organizational measures -- ✅ **CCPA Section 1798.150:** Encryption requirements -- ✅ **HIPAA Security Rule:** Administrative, physical, and technical safeguards -- ✅ **SOX Section 404:** Internal controls over financial reporting - -#### **Export Control Compliance** -- ✅ **ITAR Category XIII:** Cryptographic equipment compliance -- ✅ **EAR Part 740.17:** Encryption commodities and software -- ✅ **Wassenaar Arrangement:** Dual-use goods controls - ---- - -## 🧪 Testing and Validation - -### Cryptographic Test Vectors - -#### **ECDH Test Vectors** -```javascript -const ecdhTestVectors = [ - { - curve: 'P-384', - privateKeyA: '0x1234...', // Test private key A - publicKeyB: '0x5678...', // Test public key B - expectedSharedSecret: '0x9abc...', // Expected result - description: 'NIST P-384 test vector #1' - }, - // Additional test vectors... -]; - -async function validateECDHImplementation() { - for (const vector of ecdhTestVectors) { - const result = await performECDH(vector.privateKeyA, vector.publicKeyB); - assert(result === vector.expectedSharedSecret, - `ECDH test failed: ${vector.description}`); - } -} -``` - -#### **AES-GCM Test Vectors** -```javascript -const aesGcmTestVectors = [ - { - key: '0x0123456789abcdef...', - iv: '0x000000000000000000000000', - plaintext: '0x00000000000000000000000000000000', - aad: '0x', - ciphertext: '0x0388dace60b6a392f328c2b971b2fe78', - tag: '0xab6e47d42cec13bdf53a67b21257bddf', - description: 'NIST GCM test vector #1' - }, - // Additional test vectors... -]; -``` - -### Security Testing - -#### **Automated Security Tests** -```javascript -class CryptographicSecurityTester { - async runAllTests() { - const testResults = await Promise.all([ - this.testKeyGeneration(), - this.testEncryptionDecryption(), - this.testSignatureVerification(), - this.testKeyDerivation(), - this.testPerfectForwardSecrecy(), - this.testReplayProtection(), - this.testTimingAttacks(), - this.testSideChannelResistance() - ]); - - return testResults.every(result => result.passed); - } - - async testKeyGeneration() { - try { - // Test ECDH key generation - const ecdhKeyPair = await generateECDHKeyPair(); - assert(ecdhKeyPair.privateKey.algorithm.namedCurve === 'P-384'); - assert(ecdhKeyPair.privateKey.extractable === false); - - // Test ECDSA key generation - const ecdsaKeyPair = await generateECDSAKeyPair(); - assert(ecdsaKeyPair.privateKey.algorithm.namedCurve === 'P-384'); - assert(ecdsaKeyPair.privateKey.extractable === false); - - return { passed: true, test: 'Key Generation' }; - } catch (error) { - return { passed: false, test: 'Key Generation', error: error.message }; - } - } - - async testTimingAttacks() { - const iterations = 1000; - const timings = []; - - // Measure signature verification times - for (let i = 0; i < iterations; i++) { - const start = performance.now(); - await verifySignature(/* test parameters */); - const end = performance.now(); - timings.push(end - start); - } - - // Statistical analysis for timing consistency - const mean = timings.reduce((a, b) => a + b) / timings.length; - const variance = timings.reduce((sum, time) => sum + Math.pow(time - mean, 2), 0) / timings.length; - const coefficient = Math.sqrt(variance) / mean; - - // Should have low coefficient of variation (< 0.1) - return { - passed: coefficient < 0.1, - test: 'Timing Attack Resistance', - coefficient: coefficient - }; - } -} -``` - -### Fuzzing and Stress Testing - -#### **Input Validation Testing** -```javascript -class CryptographicFuzzTester { - async fuzzEncryption() { - const fuzzInputs = [ - new Uint8Array(0), // Empty input - new Uint8Array(1).fill(0), // Single zero byte - new Uint8Array(1024 * 1024).fill(255), // 1MB of 0xFF - crypto.getRandomValues(new Uint8Array(65536)), // Random data - // Malformed inputs, boundary conditions, etc. - ]; - - for (const input of fuzzInputs) { - try { - const encrypted = await encryptMessage(input, /* keys */); - const decrypted = await decryptMessage(encrypted, /* keys */); - - // Verify round-trip integrity - assert(this.arraysEqual(input, decrypted)); - } catch (error) { - // Expected for some malformed inputs - console.log(`Fuzz test handled gracefully: ${error.message}`); - } - } - } - - arraysEqual(a, b) { - return a.length === b.length && a.every((val, i) => val === b[i]); - } -} -``` - ---- - -## 🔮 Future Cryptographic Enhancements - -### Post-Quantum Cryptography Migration - -#### **Timeline and Strategy** -``` -2025 Q4: Research and prototyping -├── Evaluate NIST-standardized algorithms -├── Performance benchmarking -└── Hybrid classical/post-quantum implementation - -2026 Q2: Hybrid deployment -├── CRYSTALS-Kyber for key encapsulation -├── CRYSTALS-Dilithium for digital signatures -└── Dual algorithm support with fallback - -2027 Q1: Full post-quantum transition -├── Pure post-quantum algorithms -├── Legacy compatibility layer -└── Migration tools for existing users -``` - -#### **Planned Algorithms** -| Function | Current Algorithm | Post-Quantum Algorithm | Timeline | -|----------|-------------------|------------------------|----------| -| **Key Exchange** | ECDH P-384 | CRYSTALS-Kyber-1024 | 2026 Q2 | -| **Signatures** | ECDSA P-384 | CRYSTALS-Dilithium-5 | 2026 Q2 | -| **Encryption** | AES-256-GCM | AES-256-GCM (quantum-safe) | Current | -| **Hashing** | SHA-384 | SHA-3-384 | 2026 Q4 | - -### Advanced Cryptographic Features - -#### **Homomorphic Encryption** -```javascript -// Future implementation for privacy-preserving operations -class HomomorphicEncryption { - async encryptWithHomomorphism(data, publicKey) { - // Enable computations on encrypted data - // Useful for encrypted search, statistics - } - - async computeOnEncrypted(encryptedData, operation) { - // Perform operations without decryption - return encryptedResult; - } -} -``` - -#### **Zero-Knowledge Proofs** -```javascript -// Future implementation for authentication without revelation -class ZeroKnowledgeAuth { - async generateProof(secret, challenge) { - // Prove knowledge without revealing secret - } - - async verifyProof(proof, challenge, publicData) { - // Verify proof without learning secret - } -} -``` - -### Quantum Key Distribution - -#### **Hardware Integration Planning** -```javascript -// Future quantum key distribution integration -class QuantumKeyDistribution { - async establishQuantumChannel() { - // Hardware-based quantum key generation - // Ultimate forward secrecy - } - - async detectEavesdropping() { - // Quantum mechanics for eavesdropping detection - // Automatic key invalidation on interference - } -} -``` - ---- - -## 📚 Implementation Examples - -### Complete Message Encryption Flow - -#### **Full Implementation Example** -```javascript -class SecureMessageProcessor { - constructor(encryptionKey, macKey, metadataKey, signingKey) { - this.encryptionKey = encryptionKey; - this.macKey = macKey; - this.metadataKey = metadataKey; - this.signingKey = signingKey; - this.sequenceNumber = 0; - } - - async sendSecureMessage(message) { - try { - // Step 1: Generate message ID and increment sequence - const messageId = `msg_${Date.now()}_${Math.random().toString(36)}`; - const sequenceNumber = this.sequenceNumber++; - - // Step 2: Encrypt message with metadata protection - const encryptedData = await encryptMessage( - message, - this.encryptionKey, - this.macKey, - this.metadataKey, - messageId, - sequenceNumber - ); - - // Step 3: Create enhanced message payload - const payload = { - type: 'enhanced_message', - data: encryptedData, - keyVersion: this.currentKeyVersion, - version: '4.0' - }; - - // Step 4: Sign the entire payload - const payloadString = JSON.stringify(payload); - const signature = await signData(this.signingKey, payloadString); - payload.signature = signature; - - // Step 5: Send through WebRTC channel - this.dataChannel.send(JSON.stringify(payload)); - - console.log(`✅ Secure message sent: ${messageId}`); - return { success: true, messageId }; - - } catch (error) { - console.error('❌ Secure message sending failed:', error); - return { success: false, error: error.message }; - } - } - - async receiveSecureMessage(rawData) { - try { - // Step 1: Parse incoming message - const payload = JSON.parse(rawData); - - // Step 2: Verify message signature - if (payload.signature) { - const payloadCopy = { ...payload }; - delete payloadCopy.signature; - const payloadString = JSON.stringify(payloadCopy); - - const isValidSignature = await verifySignature( - this.peerPublicKey, - payload.signature, - payloadString - ); - - if (!isValidSignature) { - throw new Error('Invalid message signature'); - } - } - - // Step 3: Get appropriate keys for decryption - const keyVersion = payload.keyVersion || 0; - const keys = this.getKeysForVersion(keyVersion); - - if (!keys) { - throw new Error(`Keys not available for version ${keyVersion}`); - } - - // Step 4: Decrypt message - const decryptedData = await decryptMessage( - payload.data, - keys.encryptionKey, - keys.macKey, - keys.metadataKey - ); - - // Step 5: Verify sequence number and prevent replay - if (this.processedMessageIds.has(decryptedData.messageId)) { - throw new Error('Duplicate message detected - replay attack'); - } - this.processedMessageIds.add(decryptedData.messageId); - - console.log(`✅ Secure message received: ${decryptedData.messageId}`); - return { - success: true, - message: decryptedData.message, - messageId: decryptedData.messageId, - timestamp: decryptedData.timestamp - }; - - } catch (error) { - console.error('❌ Secure message processing failed:', error); - return { success: false, error: error.message }; - } - } -} -``` - -### Error Handling and Recovery - -#### **Cryptographic Error Recovery** -```javascript -class CryptographicErrorHandler { - static async handleDecryptionError(error, retryCount = 0) { - const maxRetries = 3; - - if (retryCount >= maxRetries) { - throw new Error(`Decryption failed after ${maxRetries} attempts: ${error.message}`); - } - - // Analyze error type and attempt recovery - if (error.message.includes('InvalidAccessError')) { - // Key might be corrupted, regenerate if possible - console.warn('Key access error, attempting key recovery...'); - await this.attemptKeyRecovery(); - return { retry: true, newKeys: true }; - } - - if (error.message.includes('OperationError')) { - // Generic operation error, retry with delay - console.warn(`Cryptographic operation failed, retrying in ${retryCount * 1000}ms...`); - await new Promise(resolve => setTimeout(resolve, retryCount * 1000)); - return { retry: true, delay: retryCount * 1000 }; - } - - // Unrecoverable error - throw error; - } - - static async validateCryptographicState() { - // Comprehensive cryptographic state validation - const checks = [ - this.validateKeyIntegrity(), - this.validateAlgorithmSupport(), - this.validateRandomNumberGenerator(), - this.validateTimingConsistency() - ]; - - const results = await Promise.allSettled(checks); - const failures = results.filter(r => r.status === 'rejected'); - - if (failures.length > 0) { - throw new Error(`Cryptographic state validation failed: ${failures.map(f => f.reason).join(', ')}`); - } - - return { valid: true, timestamp: Date.now() }; - } -} -``` - ---- - -## 📞 Support and Documentation - -### Technical Support - -For cryptographic implementation questions: -- **Security Team:** security@SecureBit.chat -- **Cryptographic Specialists:** crypto@SecureBit.chat -- **GitHub Issues:** [Cryptography Issues](https://github.com/SecureBitChat/securebit-chat/issues?q=label%3Acryptography) - -### Additional Resources - -#### **Academic Papers** -- [Elliptic Curve Cryptography](https://link.springer.com/article/10.1007/s00145-001-0020-9) -- [AES-GCM Security Analysis](https://csrc.nist.gov/publications/detail/sp/800-38d/final) -- [Post-Quantum Cryptography](https://csrc.nist.gov/Projects/post-quantum-cryptography) - -#### **Standards Documents** -- [NIST SP 800-57 Part 1](https://csrc.nist.gov/publications/detail/sp/800-57-part-1/rev-5/final) -- [FIPS 186-4 Digital Signature Standard](https://csrc.nist.gov/publications/detail/fips/186/4/final) -- [RFC 5869 HKDF](https://tools.ietf.org/html/rfc5869) - -#### **Implementation Guides** -- [Web Crypto API Best Practices](https://www.w3.org/TR/WebCryptoAPI/) -- [Secure Coding Guidelines](https://wiki.sei.cmu.edu/confluence/display/c/SEI+CERT+C+Coding+Standard) -- [Cryptographic Protocol Design](https://link.springer.com/book/10.1007/978-3-662-46447-2) - ---- - -## 🏁 Conclusion - -SecureBit.chat's cryptographic implementation represents the state-of-the-art in secure peer-to-peer communications. Our multi-layered approach combining classical cryptography with forward-looking security measures provides unprecedented protection against current and future threats. - -### Key Achievements - -- **🔒 Military-Grade Security:** Triple-layer encryption with 256+ bit security -- **🛡️ Future-Proof Design:** Quantum-resistant timeline > 15 years -- **⚡ High Performance:** Hardware acceleration with minimal latency impact -- **📊 Standards Compliance:** NIST, FIPS, NSA Suite B certified algorithms -- **🔄 Perfect Forward Secrecy:** Automatic key rotation every 5 minutes -- **🎯 Zero Trust:** No reliance on external trusted parties - -### Security Guarantees - -Our cryptographic implementation provides: -- **Confidentiality:** Triple-layer AES-256-GCM encryption -- **Integrity:** HMAC-SHA-384 message authentication -- **Authenticity:** ECDSA P-384 digital signatures -- **Non-repudiation:** Cryptographic proof of message origin -- **Forward Secrecy:** Past communications remain secure -- **Replay Protection:** Comprehensive anti-replay mechanisms - -**This cryptographic foundation enables SecureBit.chat to provide the most secure peer-to-peer communications platform available today.** - ---- - -*This document reflects the current state of cryptographic implementation in SecureBit.chat v4.1. All algorithms and protocols are subject to ongoing security review and enhancement.* - -**Last Updated:** January 15, 2025 -**Document Version:** 4.1 -**Cryptographic Implementation:** Stage 5 - Military-Grade Security -**Review Status:** ✅ Verified by Cryptographic Specialists \ No newline at end of file +This document describes the current browser implementation behavior relevant to the v4.8.5 hardening release. It does not replace independent cryptographic review. diff --git a/doc/SECURITY-ARCHITECTURE.md b/doc/SECURITY-ARCHITECTURE.md index 202b1dc..0d98ceb 100644 --- a/doc/SECURITY-ARCHITECTURE.md +++ b/doc/SECURITY-ARCHITECTURE.md @@ -1,774 +1,53 @@ -# SecureBit.chat Security Architecture v4.02.985 +# Security Architecture -## 🛡️ Overview +## Current baseline -SecureBit.chat implements a revolutionary **18-layer security architecture** with ECDH + DTLS + SAS authentication that provides military-grade protection for peer-to-peer communications. This document details the technical implementation of our security system, which exceeds most government and enterprise communication standards. +| Area | Current behavior | +| --- | --- | +| Protocol | `4.1` with mismatch rejection | +| Peer verification | mandatory manual SAS entry | +| Transport | WebRTC over DTLS | +| Privacy mode | optional TURN relay-only mode | +| Message UI safety | incoming decrypted text sanitized before display | +| File transfer | validated metadata, explicit consent, allowlist policy | +| Local metadata | encrypted IndexedDB envelopes with migration | +| Lifecycle | unified disconnect cleanup and bounded resource retention | -**Current Implementation:** Stage 5 - Maximum Security -**Security Rating:** Maximum (ECDH + DTLS + SAS) -**Active Layers:** 18/18 -**Threat Protection:** Comprehensive (MITM, Traffic Analysis, Replay Attacks, Session Hijacking, Race Conditions, Key Exposure, DTLS Race Conditions, Memory Safety, Use-After-Free, Key Structure Manipulation) +## Verification state machine ---- - -## 📋 Table of Contents - -1. [Security Architecture Overview](#security-architecture-overview) -2. [Layer-by-Layer Analysis](#layer-by-layer-analysis) -3. [Cryptographic Specifications](#cryptographic-specifications) -4. [Threat Model](#threat-model) -5. [Implementation Details](#implementation-details) -6. [Security Verification](#security-verification) -7. [Performance Impact](#performance-impact) -8. [Compliance Standards](#compliance-standards) -9. [ASN.1 Validation Framework](#asn1-validation-framework) - ---- - -## 🏗️ Security Architecture Overview - -### 19-Layer Defense System - -``` -┌─────────────────────────────────────────────────────────────┐ -│ APPLICATION LAYER │ -├─────────────────────────────────────────────────────────────┤ -│ Layer 19: HKDF Key Derivation (RFC 5869 Compliant) │ -│ Layer 18: EC Point Validation (Format & Structure) │ -│ Layer 17: OID Validation (Algorithm & Curve Verification) │ -│ Layer 16: ASN.1 Validation (Complete Key Structure) │ -│ Layer 15: Production Security Logging (Data Sanitization) │ -│ Layer 14: Secure Key Storage (WeakMap Isolation) │ -│ Layer 13: Mutex Framework (Race Condition Protection) │ -├─────────────────────────────────────────────────────────────┤ -│ CRYPTOGRAPHIC LAYER │ -├─────────────────────────────────────────────────────────────┤ -│ Layer 12: Perfect Forward Secrecy (Key Rotation) │ -│ Layer 11: Enhanced Rate Limiting (DDoS Protection) │ -│ Layer 10: Fake Traffic Generation (Traffic Analysis) │ -│ Layer 9: Message Chunking (Timing Analysis Protection) │ -│ Layer 8: Packet Reordering Protection (Sequence Security) │ -├─────────────────────────────────────────────────────────────┤ -│ OBFUSCATION LAYER │ -├─────────────────────────────────────────────────────────────┤ -│ Layer 7: Anti-Fingerprinting (Pattern Obfuscation) │ -│ Layer 6: Packet Padding (Size Obfuscation) │ -│ Layer 5: Nested Encryption (Additional AES-GCM) │ -├─────────────────────────────────────────────────────────────┤ -│ ENCRYPTION LAYER │ -├─────────────────────────────────────────────────────────────┤ -│ Layer 4: Message Encryption (Enhanced AES-GCM) │ -│ Layer 3: Metadata Protection (Separate AES-GCM) │ -│ Layer 2: Key Exchange (ECDH P-384) │ -│ Layer 1: Enhanced Authentication (ECDSA P-384) │ -├─────────────────────────────────────────────────────────────┤ -│ TRANSPORT LAYER │ -│ (WebRTC/ICE/DTLS) │ -└─────────────────────────────────────────────────────────────┘ +```text +connection established + ↓ +shared keys derived + ↓ +deterministic SAS displayed + ↓ +manual out-of-band comparison + ↓ +local input validated + ↓ +peer confirmation received + ↓ +verified session ``` -### Security Progression Stages +The verified state is reached only when both local and remote confirmation flags are true. -| Stage | Layers Active | Security Level | Target Threats | -|-------|---------------|----------------|-----------------| -| 1 | 1-5 | Basic Enhanced | Basic attacks, MITM | -| 2 | 1-7 | Medium | + Traffic analysis | -| 3 | 1-9 | High | + Timing attacks | -| 4 | 1-12 | High Enhanced | + Advanced persistent threats | -| 5 | 1-15 | Military-Grade | + Race conditions, Key exposure | -| 6 | 1-19 | Maximum | + DTLS race conditions, Memory safety, Key structure validation, HKDF compliance | +## File-transfer architecture ---- +1. sender emits metadata +2. receiver validates name, size, type, and abuse limits +3. receiver sees Accept / Reject prompt +4. no receive buffers are allocated before acceptance +5. sender transmits chunks only after acceptance +6. completed received buffers are retained within a bounded window -## 🔍 Layer-by-Layer Analysis +## Disconnect cleanup -### Layer 1: Enhanced Authentication (ECDSA P-384) -**Purpose:** Cryptographic proof of message authenticity and sender verification +The canonical disconnect path clears: -**Technical Specifications:** -- **Algorithm:** ECDSA with P-384 curve -- **Hash Function:** SHA-384 (primary), SHA-256 (fallback) -- **Key Size:** 384-bit (equivalent to 7680-bit RSA) -- **Signature Size:** 96 bytes -- **Key Properties:** Non-extractable, hardware-protected - -**Implementation:** -```javascript -// Self-signed key package for MITM protection -const keyPackage = { - keyType: 'ECDSA', - keyData: exported384BitKey, - timestamp: Date.now(), - version: '4.02', - signature: ecdsaSignature -}; -``` - -### Layer 16: ASN.1 Validation (Complete Key Structure) -**Purpose:** Complete structural validation of all cryptographic keys according to PKCS standards - -**Technical Specifications:** -- **Parser:** Complete ASN.1 DER parser -- **Validation Scope:** Full key structure verification -- **Standards:** RFC 5280, RFC 5480, PKCS compliance -- **Performance:** < 10ms validation time -- **Coverage:** All cryptographic operations - -**Implementation:** -```javascript -// Complete ASN.1 DER parsing and validation -const validateKeyStructure = (keyData) => { - const asn1Parser = new ASN1Validator(); - const parsed = asn1Parser.parseDER(keyData); - - // Validate complete structure - if (!asn1Parser.validateSPKI(parsed)) { - throw new Error('Invalid SPKI structure'); - } - - // Validate OID and curves - if (!asn1Parser.validateOID(parsed)) { - throw new Error('Invalid algorithm OID'); - } - - // Validate EC point format - if (!asn1Parser.validateECPoint(parsed)) { - throw new Error('Invalid EC point format'); - } - - return true; -}; -``` - -### Layer 17: OID Validation (Algorithm & Curve Verification) -**Purpose:** Verification of cryptographic algorithms and elliptic curves - -**Technical Specifications:** -- **Supported Curves:** P-256, P-384 only -- **Algorithm Validation:** Complete OID verification -- **Fallback Support:** P-384 to P-256 compatibility -- **Security:** Prevents algorithm substitution attacks - -**Implementation:** -```javascript -// OID validation for algorithms and curves -const validateOID = (parsed) => { - const validOIDs = { - '1.2.840.10045.3.1.7': 'P-256', // secp256r1 - '1.3.132.0.34': 'P-384' // secp384r1 - }; - - const oid = parsed.algorithm.algorithm; - if (!validOIDs[oid]) { - throw new Error(`Unsupported curve: ${oid}`); - } - - return validOIDs[oid]; -}; -``` - -### Layer 19: HKDF Key Derivation (RFC 5869 Compliant) -**Purpose:** RFC 5869 compliant key derivation with proper key separation and cryptographic security - -**Technical Specifications:** -- **Standard:** RFC 5869 HMAC-based Extract-and-Expand Key Derivation Function -- **Hash Function:** SHA-256 for optimal compatibility and performance -- **Salt Security:** 64-byte cryptographically secure salt for each derivation -- **Key Separation:** Unique `info` parameters for each derived key type -- **Non-Extractable Keys:** Hardware-protected keys for enhanced security - -**Implementation:** -```javascript -// HKDF key derivation with proper separation -const deriveSharedKeys = async (privateKey, publicKey, salt) => { - // Step 1: Pure ECDH derivation - const rawKeyMaterial = await crypto.subtle.deriveKey( - { name: 'ECDH', public: publicKey }, - privateKey, - { name: 'AES-GCM', length: 256 }, - true, // Extractable for HKDF processing - ['encrypt', 'decrypt'] - ); - - // Export and import for HKDF - const rawKeyData = await crypto.subtle.exportKey('raw', rawKeyMaterial); - const rawSharedSecret = await crypto.subtle.importKey( - 'raw', rawKeyData, - { name: 'HKDF', hash: 'SHA-256' }, - false, ['deriveKey'] - ); - - // Step 2: Derive specific keys with unique info parameters - const messageKey = await crypto.subtle.deriveKey( - { - name: 'HKDF', - hash: 'SHA-256', - salt: saltBytes, - info: encoder.encode('message-encryption-v4') - }, - rawSharedSecret, - { name: 'AES-GCM', length: 256 }, - false, ['encrypt', 'decrypt'] - ); - - // Additional keys derived with unique info parameters... - return { messageKey, macKey, pfsKey, metadataKey, fingerprint }; -}; -``` - -### Layer 18: EC Point Validation (Format & Structure Verification) -**Purpose:** Verification of elliptic curve point format and structure - -**Technical Specifications:** -- **Format:** Uncompressed format 0x04 only -- **Structure:** Complete point coordinate validation -- **Size Limits:** 50-2000 bytes to prevent DoS attacks -- **BIT STRING:** Unused bits must be 0 - -**Implementation:** -```javascript -// EC point format and structure validation -const validateECPoint = (parsed) => { - const publicKey = parsed.subjectPublicKey; - - // Check format (uncompressed 0x04) - if (publicKey[0] !== 0x04) { - throw new Error('Only uncompressed EC point format supported'); - } - - // Validate size limits - if (publicKey.length < 50 || publicKey.length > 2000) { - throw new Error('Key size outside allowed range (50-2000 bytes)'); - } - - // Validate BIT STRING unused bits - if (parsed.unusedBits !== 0) { - throw new Error('BIT STRING unused bits must be 0'); - } - - return true; -}; -``` - ---- - -## 🔐 Cryptographic Specifications - -### Algorithm Selection Rationale - -| Component | Algorithm | Key Size | Rationale | -|-----------|-----------|----------|-----------| -| Key Exchange | ECDH P-384 | 384-bit | NSA Suite B, quantum-resistant timeline | -| Signatures | ECDSA P-384 | 384-bit | Matches key exchange, proven security | -| Encryption | AES-256-GCM | 256-bit | NIST recommended, authenticated encryption | -| Hashing | SHA-384 | 384-bit | Matches curve size, collision resistant | -| MAC | HMAC-SHA-384 | 384-bit | Proven security, matches hash function | - -### Security Strengths - -- **ECDH P-384:** Equivalent to 7680-bit RSA -- **AES-256:** Quantum computer resistant until 2040+ -- **SHA-384:** 192-bit security level (collision resistance) -- **Combined Security:** Exceeds 256-bit security level - -### Cryptographic Operations Performance - -| Operation | Time (ms) | CPU Usage | Memory Usage | -|-----------|-----------|-----------|--------------| -| Key Generation | 10-50 | Medium | Low | -| ECDH Agreement | 5-15 | Low | Low | -| AES Encryption | 0.1-1 | Very Low | Very Low | -| ECDSA Signing | 2-8 | Low | Low | -| Message Processing | 1-5 | Low | Low | - ---- - -## 🎯 Threat Model - -### Threat Classifications - -#### **🔴 Critical Threats (Fully Mitigated)** -- **Nation-State Attacks:** Advanced persistent threats -- **MITM Attacks:** Certificate pinning bypass attempts -- **Cryptographic Attacks:** Implementation vulnerabilities -- **Traffic Analysis:** Deep packet inspection and metadata analysis - -#### **🟡 High Threats (Substantially Mitigated)** -- **Side-Channel Attacks:** Timing and power analysis -- **Social Engineering:** User manipulation (partially mitigated) -- **Endpoint Compromise:** Device-level attacks -- **Quantum Computing:** Future quantum attacks (timeline > 15 years) - -#### **🟢 Medium Threats (Completely Mitigated)** -- **Passive Eavesdropping:** Network traffic interception -- **Replay Attacks:** Message reuse attempts -- **DDoS Attacks:** Service disruption attempts -- **Protocol Downgrade:** Forced weak encryption - -### Attack Scenarios and Defenses - -#### Scenario 1: Government Surveillance -**Attack:** Comprehensive traffic monitoring and analysis -**Defense Layers:** 6, 7, 10, 12 (traffic obfuscation) -**Result:** Encrypted traffic indistinguishable from noise - -#### Scenario 2: Corporate Espionage -**Attack:** Targeted interception with advanced tools -**Defense Layers:** 1, 2, 3, 4, 5 (cryptographic protection) -**Result:** Computationally infeasible to decrypt - -#### Scenario 3: ISP-Level Monitoring -**Attack:** Deep packet inspection and metadata collection -**Defense Layers:** 6, 7, 8, 9, 10 (pattern obfuscation) -**Result:** No useful metadata or patterns extractable - -#### Scenario 4: Academic Cryptanalysis -**Attack:** Advanced mathematical attacks on crypto -**Defense Layers:** 2, 4, 5 (multiple algorithms) -**Result:** Multiple independent cryptographic barriers - ---- - -## 🔧 Implementation Details - -### Message Flow Through Security Layers - -``` -┌─────────────────┐ -│ User Message │ -└─────────┬───────┘ - │ -┌─────────▼───────┐ ┌──────────────────┐ -│ Layer 7: Anti │ │ Outbound Process │ -│ Fingerprinting │◄───┤ (Sending) │ -└─────────┬───────┘ └──────────────────┘ - │ -┌─────────▼───────┐ -│ Layer 6: Packet│ -│ Padding │ -└─────────┬───────┘ - │ -┌─────────▼───────┐ -│ Layer 8: Packet│ -│ Reordering │ -└─────────┬───────┘ - │ -┌─────────▼───────┐ -│ Layer 5: Nested│ -│ Encryption │ -└─────────┬───────┘ - │ -┌─────────▼───────┐ -│ Layer 4: Message│ -│ Encryption │ -└─────────┬───────┘ - │ -┌─────────▼───────┐ -│ WebRTC Channel │ -└─────────────────┘ -``` - -### Security Layer Configuration - -```javascript -// Production configuration for maximum security -const securityConfig = { - // Stage 4 - Maximum Security - features: { - hasEncryption: true, - hasECDH: true, - hasECDSA: true, - hasMutualAuth: true, - hasMetadataProtection: true, - hasEnhancedReplayProtection: true, - hasNonExtractableKeys: true, - hasRateLimiting: true, - hasEnhancedValidation: true, - hasPFS: true, - hasNestedEncryption: true, - hasPacketPadding: true, - hasFakeTraffic: true, - hasMessageChunking: true, - hasDecoyChannels: true, - hasPacketReordering: true, - hasAntiFingerprinting: true - }, - - // Performance optimizations - performance: { - paddingRange: [64, 512], // Reduced for efficiency - chunkSize: 2048, // Larger chunks - fakeTrafficInterval: [10000, 30000], // Less frequent - keyRotation: 300000 // 5 minutes - } -}; -``` - ---- - -## ✅ Security Verification - -### Automated Testing - -```javascript -// Security layer verification -async function verifySecurityLayers() { - const tests = [ - verifyEncryption(), - verifyECDHKeyExchange(), - verifyECDSASignatures(), - verifyMutualAuth(), - verifyMetadataProtection(), - verifyReplayProtection(), - verifyNonExtractableKeys(), - verifyRateLimiting(), - verifyEnhancedValidation(), - verifyPFS(), - verifyNestedEncryption(), - verifyPacketPadding() - ]; - - const results = await Promise.all(tests); - return results.every(result => result === true); -} -``` - -### Manual Verification Commands - -```javascript -// Check security status -webrtcManager.getSecurityStatus() -// Expected: { stage: 4, securityLevel: 'MAXIMUM', activeFeatures: 12 } - -// Verify cryptographic implementation -webrtcManager.calculateSecurityLevel() -// Expected: { level: 'HIGH', score: 80+, verificationResults: {...} } - -// Test fake traffic filtering -webrtcManager.checkFakeTrafficStatus() -// Expected: { fakeTrafficEnabled: true, timerActive: true } -``` - -### Security Metrics Dashboard - -| Metric | Target | Current | Status | -|--------|---------|---------|---------| -| Active Security Layers | 19 | 19 | ✅ | -| Encryption Strength | 256-bit | 256-bit | ✅ | -| Key Exchange Security | P-384 | P-384 | ✅ | -| Forward Secrecy | Complete | Complete | ✅ | -| Traffic Obfuscation | Maximum | Maximum | ✅ | -| Attack Surface | Minimal | Minimal | ✅ | -| HKDF Compliance | RFC 5869 | RFC 5869 | ✅ | - ---- - -## 🔒 Layer 13: Mutex Framework (Race Condition Protection) - -### Purpose -Prevents race conditions during connection establishment and cryptographic operations through advanced mutex coordination system. - -### Technical Implementation -- **Custom Mutex System:** `_withMutex('connectionOperation')` with 15-second timeout -- **Atomic Operations:** Serialized connection operations to prevent conflicts -- **Deadlock Prevention:** Emergency recovery mechanisms with automatic cleanup -- **Operation Tracking:** Unique `operationId` for comprehensive diagnostics - -### Security Benefits -- **Race Condition Prevention:** Eliminates timing-based attacks during key generation -- **Connection Integrity:** Ensures atomic connection establishment -- **Error Recovery:** Automatic rollback via `_cleanupFailedOfferCreation()` on failures -- **Diagnostic Capability:** Phase tracking for precise error identification - -### Implementation Details -```javascript -// Mutex-protected connection operations -await this._withMutex('connectionOperation', async () => { - const operationId = this._generateOperationId(); - try { - await this._generateEncryptionKeys(); - await this._validateConnectionParameters(); - await this._establishSecureChannel(); - } catch (error) { - await this._cleanupFailedOfferCreation(operationId); - throw error; - } -}); -``` - ---- - -## 🔐 Layer 14: Secure Key Storage (WeakMap Isolation) - -### Purpose -Replaces public key properties with private WeakMap-based storage to prevent unauthorized access and memory exposure. - -### Technical Implementation -- **WeakMap Storage:** `_secureKeyStorage` for all cryptographic keys -- **Private Access Methods:** `_getSecureKey()`, `_setSecureKey()`, `_initializeSecureKeyStorage()` -- **Key Validation:** `_validateKeyValue()` with type and format checking -- **Key Rotation:** `_rotateKeys()` with secure key replacement -- **Emergency Wipe:** `_emergencyKeyWipe()` for threat response - -### Security Benefits -- **Memory Protection:** Keys inaccessible via direct property access or debugger -- **Access Control:** Secure getters/setters with validation -- **Key Lifetime Management:** Automatic rotation and expiration -- **Threat Response:** Immediate key destruction capabilities - -### Implementation Details -```javascript -// Secure key storage initialization -this._initializeSecureKeyStorage(); - -// Secure key access -const encryptionKey = this._getSecureKey('encryptionKey'); -this._setSecureKey('encryptionKey', newKey, { validate: true }); - -// Emergency key wipe -this._emergencyKeyWipe(); -``` - ---- - -## 🛡️ Layer 15: Production Security Logging (Data Sanitization) - -### Purpose -Implements environment-aware logging system that prevents sensitive data exposure while maintaining useful diagnostics. - -### Technical Implementation -- **Environment Detection:** Automatic production vs development mode detection -- **Data Sanitization:** `_secureLog()` replacing `console.log` with sanitization -- **Log Level Control:** Production (warn+error only), Development (debug+) -- **Rate Limiting:** Automatic log spam prevention and cleanup -- **Memory Management:** Automatic cleanup for log counters - -### Security Benefits -- **Data Protection:** Encryption keys, message content, and tokens are sanitized -- **Privacy Preservation:** User privacy maintained in production logs -- **Debugging Support:** Safe debugging information without sensitive content -- **Compliance:** Meets privacy regulations and security standards - -### Implementation Details -```javascript -// Secure logging with data sanitization -this._secureLog('debug', 'Connection established', { - userId: '[REDACTED]', - encryptionKey: '[REDACTED]', - messageContent: '[REDACTED]' -}); - -// Environment-aware logging -if (this._isProductionMode()) { - // Only critical errors and warnings -} else { - // Full debugging information (sanitized) -} -``` - ---- - -## 🛡️ Layer 16: Atomic Operations (Race Condition Prevention) - -### Purpose -Prevents race conditions in critical security operations through atomic lock-based mechanisms. - -### Technical Implementation -- **Lock Management:** Map-based lock system with unique keys -- **Atomic Operations:** `withLock()` wrapper for critical sections -- **Timeout Protection:** Configurable lock timeouts (default: 5 seconds) -- **Automatic Cleanup:** Lock removal after operation completion -- **Error Handling:** Graceful fallback on lock failures - -### Security Benefits -- **Race Condition Prevention:** Eliminates concurrent access vulnerabilities -- **Data Integrity:** Ensures consistent state during operations -- **Critical Section Protection:** Secures file transfer and cryptographic operations -- **Deadlock Prevention:** Automatic cleanup prevents resource exhaustion - -### Implementation Details -```javascript -// Atomic operation wrapper -return this.atomicOps.withLock( - `chunk-${chunkMessage.fileId}`, - async () => { - // Critical section protected by lock - // File chunk processing logic - } -); -``` - ---- - -## 🛡️ Layer 17: DTLS Race Condition Protection (WebRTC Security) - -### Purpose -Advanced protection against October 2024 WebRTC DTLS ClientHello race condition vulnerabilities. - -### Technical Implementation -- **ICE Endpoint Verification:** Secure validation before DTLS establishment -- **ClientHello Validation:** TLS cipher suite and version verification -- **Source Authentication:** Cryptographic verification of DTLS packet sources -- **Queue Management:** DTLS message queuing during ICE verification -- **Timeout Protection:** Configurable verification timeouts - -### Security Benefits -- **DTLS Vulnerability Mitigation:** Protects against race condition attacks -- **WebRTC Security Enhancement:** Comprehensive transport layer protection -- **Endpoint Validation:** Ensures legitimate connection sources -- **Protocol Security:** TLS version and cipher suite validation - -### Implementation Details -```javascript -// DTLS source validation -await this.validateDTLSSource(clientHelloData, expectedSource); - -// ICE endpoint verification -this.addVerifiedICEEndpoint(endpoint); - -// DTLS message handling -await this.handleDTLSClientHello(clientHelloData, sourceEndpoint); -``` - ---- - -## 🛡️ Layer 18: Memory Safety Protection (Use-After-Free) - -### Purpose -Advanced memory safety mechanisms to prevent use-after-free vulnerabilities and ensure secure data cleanup. - -### Technical Implementation -- **Secure Memory Wiping:** Advanced buffer wiping with zero-filling -- **Context Isolation:** Symbol-based private instance management -- **Memory Cleanup:** Comprehensive cleanup of sensitive data structures -- **Error Handling:** Secure error handling without information leakage -- **Garbage Collection:** Optional forced GC for critical operations - -### Security Benefits -- **Use-After-Free Prevention:** Eliminates memory safety vulnerabilities -- **Data Leakage Prevention:** Secure cleanup of sensitive information -- **Context Security:** Isolated instance management prevents tampering -- **Error Security:** Sanitized error messages prevent information disclosure - -### Implementation Details -```javascript -// Secure memory wiping -SecureMemoryManager.secureWipe(buffer); - -// Context isolation -SecureFileTransferContext.getInstance().setFileTransferSystem(this); - -// Enhanced memory cleanup -for (const [key, value] of Object.entries(receivingState)) { - if (value instanceof ArrayBuffer || value instanceof Uint8Array) { - SecureMemoryManager.secureWipe(value); - } -} -``` - ---- - -## ⚡ Performance Impact - -### Latency Analysis - -| Security Layer | Added Latency | Justification | -|----------------|---------------|---------------| -| Authentication | ~5ms | Necessary for MITM protection | -| Key Exchange | ~10ms | One-time cost per session | -| Metadata Protection | ~1ms | Minimal overhead | -| Message Encryption | ~2ms | Standard AES-GCM performance | -| Nested Encryption | ~2ms | Additional security layer | -| Packet Padding | ~0.5ms | Simple padding operation | -| Anti-Fingerprinting | ~3ms | Pattern obfuscation | -| Reordering Protection | ~1ms | Header processing | -| Message Chunking | ~50ms | Intentional delay for security | -| Fake Traffic | 0ms | Background operation | -| Rate Limiting | ~0.1ms | Memory lookup | -| PFS Key Rotation | ~10ms | Every 5 minutes | -| Mutex Framework | ~2ms | Race condition protection | -| Secure Key Storage | ~0.5ms | WeakMap access overhead | -| Production Logging | ~1ms | Data sanitization processing | -| Atomic Operations | ~2ms | Race condition protection | -| DTLS Protection | ~3ms | WebRTC security enhancement | -| Memory Safety | ~1ms | Secure cleanup operations | - -**Total Average Latency:** ~84.5ms per message (acceptable for secure communications) - -### Throughput Impact - -- **Without Security:** ~1000 messages/second -- **With Stage 4 Security:** ~500 messages/second -- **Efficiency:** 50% (excellent for security level provided) - -### Memory Usage - -- **Base Memory:** ~2MB -- **Security Layers:** ~3MB additional -- **Cryptographic Keys:** ~1MB -- **Total:** ~6MB (minimal for modern devices) - ---- - -## 📊 Compliance Standards - -### Industry Standards Met - -- ✅ **NIST SP 800-57:** Key management best practices -- ✅ **FIPS 140-2 Level 2:** Cryptographic module security -- ✅ **NSA Suite B:** Cryptographic algorithms (P-384, AES-256) -- ✅ **RFC 7748:** Elliptic curve cryptography standards -- ✅ **RFC 5869:** HKDF key derivation -- ✅ **RFC 3394:** AES key wrap specifications - -### Regulatory Compliance - -- ✅ **GDPR:** Privacy by design, data minimization -- ✅ **CCPA:** California privacy protection -- ✅ **HIPAA:** Healthcare data protection (suitable for) -- ✅ **SOX:** Financial data protection (suitable for) -- ✅ **ITAR:** International traffic in arms regulations (crypto export) - -### Security Certifications (Pending) - -- 🔄 **Common Criteria EAL4+:** Security functionality evaluation -- 🔄 **FIPS 140-3:** Next-generation cryptographic validation -- 🔄 **ISO 27001:** Information security management - ---- - -## 🚀 Future Enhancements - -### Quantum-Resistant Cryptography (2026) -- **Post-Quantum Key Exchange:** CRYSTALS-Kyber -- **Post-Quantum Signatures:** CRYSTALS-Dilithium -- **Hybrid Classical/Quantum:** Dual algorithm support - -### Advanced Traffic Obfuscation (2025) -- **AI-Powered Pattern Generation:** Machine learning fake traffic -- **Protocol Mimicry:** Disguise as common protocols (HTTP, DNS) -- **Adaptive Obfuscation:** Real-time pattern adjustment - -### Enhanced Perfect Forward Secrecy (2025) -- **Automatic Key Rotation:** Every 1 minute -- **Group Key Management:** Multi-party key rotation -- **Quantum Key Distribution:** Hardware-based key generation - ---- - -## 📞 Technical Support - -For technical questions about the security architecture: - -- **Security Team:** security@SecureBit.chat -- **Technical Documentation:** docs@SecureBit.chat -- **GitHub Issues:** [Security Architecture Issues](https://github.com/SecureBitChat/securebit-chat/issues?q=label%3Asecurity-architecture) - ---- - -*This document is updated with each major security enhancement. Current version reflects Stage 5 Military-Grade Security implementation with comprehensive connection security overhaul.* - -**Last Updated:** January 15, 2025 -**Document Version:** 4.1 -**Security Implementation:** Stage 5 - Military-Grade Security -**Review Status:** ✅ Verified and Tested \ No newline at end of file +- WebRTC channels and peer connection handles +- timers, deferred retries, fake traffic, and decoy traffic +- pending transfer state and consent waits +- verification state and crypto/PFS state +- React file-transfer callbacks and stale UI transfer state diff --git a/index.html b/index.html index 9011a34..e21f5ff 100644 --- a/index.html +++ b/index.html @@ -147,13 +147,13 @@ - - + +
- - + + diff --git a/meta.json b/meta.json index c391543..435887a 100644 --- a/meta.json +++ b/meta.json @@ -1,10 +1,10 @@ { - "version": "1767754446404", - "buildVersion": "1767754446404", - "appVersion": "4.7.56", - "buildTime": "2026-01-07T02:54:06.493Z", - "buildId": "1767754446404-ebcf2dc", - "gitHash": "ebcf2dc", + "version": "1779043608721", + "buildVersion": "1779043608721", + "appVersion": "4.8.5", + "buildTime": "2026-05-17T18:46:48.763Z", + "buildId": "1779043608721-4b8c882", + "gitHash": "4b8c882", "generated": true, - "generatedAt": "2026-01-07T02:54:06.494Z" + "generatedAt": "2026-05-17T18:46:48.764Z" } \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index d820020..4b0b5a2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,24 +1,24 @@ { "name": "securebit-chat", - "version": "1.0.0", + "version": "4.8.5", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "securebit-chat", - "version": "1.0.0", + "version": "4.8.5", "license": "MIT", "dependencies": { - "base64-js": "^1.5.1", - "cbor-js": "^0.1.0", - "html5-qrcode": "^2.3.8", - "pako": "^2.1.0", - "qr-scanner": "^1.4.2", - "qrcode": "^1.5.4" + "base64-js": "1.5.1", + "cbor-js": "0.1.0", + "html5-qrcode": "2.3.8", + "pako": "2.1.0", + "qr-scanner": "1.4.2", + "qrcode": "1.5.4" }, "devDependencies": { - "esbuild": "^0.25.9", - "tailwindcss": "^3.4.17" + "esbuild": "0.25.9", + "tailwindcss": "3.4.17" } }, "node_modules/@alloc/quick-lru": { @@ -766,9 +766,9 @@ } }, "node_modules/brace-expansion": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", - "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.0.tgz", + "integrity": "sha512-TN1kCZAgdgweJhWWpgKYrQaMNHcDULHkWwQIspdtjV4Y5aurRdZpjAqn6yX3FPqTA9ngHCc4hJxMAMgGfve85w==", "dev": true, "license": "MIT", "dependencies": { @@ -1120,9 +1120,10 @@ } }, "node_modules/glob": { - "version": "10.4.5", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", - "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz", + "integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", "dev": true, "license": "ISC", "dependencies": { @@ -1330,13 +1331,13 @@ } }, "node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "version": "9.0.9", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.9.tgz", + "integrity": "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==", "dev": true, "license": "ISC", "dependencies": { - "brace-expansion": "^2.0.1" + "brace-expansion": "^2.0.2" }, "engines": { "node": ">=16 || 14 >=14.17" @@ -1516,9 +1517,9 @@ "license": "ISC" }, "node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", + "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", "dev": true, "license": "MIT", "engines": { @@ -1558,9 +1559,9 @@ } }, "node_modules/postcss": { - "version": "8.5.6", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", - "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", + "version": "8.5.14", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.14.tgz", + "integrity": "sha512-SoSL4+OSEtR99LHFZQiJLkT59C5B1amGO1NzTwj7TT1qCUgUO6hxOvzkOYxD+vMrXBM3XJIKzokoERdqQq/Zmg==", "dev": true, "funding": [ { @@ -2152,9 +2153,9 @@ "license": "ISC" }, "node_modules/yaml": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.1.tgz", - "integrity": "sha512-lcYcMxX2PO9XMGvAJkJ3OsNMw+/7FKes7/hgerGUYWIoWu5j/+YQqcZr5JnPZWzOsEBgMbSbiSTn/dv/69Mkpw==", + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.9.0.tgz", + "integrity": "sha512-2AvhNX3mb8zd6Zy7INTtSpl1F15HW6Wnqj0srWlkKLcpYl/gMIMJiyuGq2KeI2YFxUPjdlB+3Lc10seMLtL4cA==", "dev": true, "license": "ISC", "bin": { @@ -2162,6 +2163,9 @@ }, "engines": { "node": ">= 14.6" + }, + "funding": { + "url": "https://github.com/sponsors/eemeli" } }, "node_modules/yargs": { diff --git a/package.json b/package.json index 91a9a5b..e51122c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "securebit-chat", - "version": "4.7.56", + "version": "4.8.5", "description": "Secure P2P Communication Application with End-to-End Encryption", "main": "index.html", "scripts": { @@ -11,7 +11,7 @@ "dev": "npm run build && python -m http.server 8000", "watch": "npx tailwindcss -i src/styles/tw-input.css -o assets/tailwind.css --watch", "serve": "npx http-server -p 8000", - "test": "echo \"Error: no test specified\" && exit 1" + "test": "node tests/sas-verification.test.mjs && node tests/file-transfer-consent.test.mjs && node tests/incoming-message-sanitization.test.mjs && node tests/file-type-allowlist.test.mjs && node tests/webrtc-privacy-mode.test.mjs && node tests/indexeddb-metadata-encryption.test.mjs && node tests/disconnect-cleanup.test.mjs && node tests/timer-lifecycle.test.mjs && node tests/file-transfer-cleanup.test.mjs && node tests/file-transfer-ui-cleanup.test.mjs && node tests/file-transfer-callback-propagation.test.mjs" }, "keywords": [ "p2p", @@ -24,15 +24,15 @@ "author": "SecureBit Team", "license": "MIT", "devDependencies": { - "esbuild": "^0.25.9", - "tailwindcss": "^3.4.17" + "esbuild": "0.25.9", + "tailwindcss": "3.4.17" }, "dependencies": { - "base64-js": "^1.5.1", - "cbor-js": "^0.1.0", - "html5-qrcode": "^2.3.8", - "pako": "^2.1.0", - "qr-scanner": "^1.4.2", - "qrcode": "^1.5.4" + "base64-js": "1.5.1", + "cbor-js": "0.1.0", + "html5-qrcode": "2.3.8", + "pako": "2.1.0", + "qr-scanner": "1.4.2", + "qrcode": "1.5.4" } } diff --git a/src/app.jsx b/src/app.jsx index 68bf5be..934c596 100644 --- a/src/app.jsx +++ b/src/app.jsx @@ -36,6 +36,31 @@ // Verification Component const VerificationStep = ({ verificationCode, onConfirm, onReject, localConfirmed, remoteConfirmed, bothConfirmed }) => { + const [sasInput, setSasInput] = React.useState(''); + const [error, setError] = React.useState(''); + const normalizedExpectedLength = (verificationCode || '').replace(/[-\s]/g, '').length; + const normalizedInputLength = sasInput.replace(/[-\s]/g, '').length; + const canConfirm = !localConfirmed && normalizedExpectedLength > 0 && normalizedInputLength === normalizedExpectedLength; + + React.useEffect(() => { + setSasInput(''); + setError(''); + }, [verificationCode]); + + const handleConfirm = async () => { + try { + setError(''); + await onConfirm(sasInput); + } catch (confirmationError) { + setSasInput(''); + if (confirmationError?.message === 'SAS_MAX_ATTEMPTS') { + setError('Too many incorrect attempts. Session reset for safety.'); + } else { + setError('Incorrect code. Check it with your peer and try again.'); + } + } + }; + return React.createElement('div', { className: "card-minimal rounded-xl p-6 border-purple-500/20" }, [ @@ -63,7 +88,7 @@ React.createElement('p', { key: 'description', className: "text-secondary text-sm" - }, "Verify the security code with your contact via another communication channel (voice, SMS, etc.):"), + }, "Compare this code with your peer out-of-band, then type the same code below to unlock the chat."), React.createElement('div', { key: 'code-display', className: "text-center" @@ -73,6 +98,36 @@ className: "verification-code text-2xl py-4" }, verificationCode) ]), + React.createElement('div', { + key: 'sas-input-wrap', + className: "space-y-2" + }, [ + React.createElement('label', { + key: 'sas-label', + className: "block text-sm text-secondary" + }, "Enter the verified code"), + React.createElement('input', { + key: 'sas-input', + type: 'text', + value: sasInput, + onChange: (event) => { + setSasInput(event.target.value.toUpperCase()); + if (error) setError(''); + }, + autoFocus: true, + autoComplete: 'off', + spellCheck: false, + inputMode: 'text', + disabled: localConfirmed, + placeholder: verificationCode ? 'Type code here' : 'Waiting for code…', + className: "w-full rounded-lg border border-purple-500/30 bg-black/20 px-4 py-3 text-center text-xl tracking-[0.3em] text-primary uppercase focus:border-purple-400 focus:outline-none disabled:cursor-not-allowed disabled:opacity-60", + style: { fontFamily: 'monospace', textTransform: 'uppercase' } + }), + error && React.createElement('p', { + key: 'sas-error', + className: "text-sm text-red-400" + }, error) + ]), // Verification status indicators React.createElement('div', { key: 'verification-status', @@ -142,14 +197,14 @@ }, [ 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'}` + onClick: handleConfirm, + disabled: !canConfirm, + className: `flex-1 py-3 px-4 rounded-lg font-medium transition-all duration-200 ${!canConfirm ? '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' + localConfirmed ? 'Confirmed' : 'Confirm code' ]), React.createElement('button', { key: 'reject', @@ -283,7 +338,9 @@ markAnswerCreated, notificationIntegrationRef, isGeneratingKeys, - handleCreateOffer + handleCreateOffer, + relayOnlyMode, + setRelayOnlyMode }) => { const [mode, setMode] = React.useState('select'); const [notificationPermissionRequested, setNotificationPermissionRequested] = React.useState(false); @@ -294,12 +351,12 @@ onClearData(); }; - const handleVerificationConfirm = () => { - onVerifyConnection(true); + const handleVerificationConfirm = (userCode) => { + return onVerifyConnection(userCode); }; const handleVerificationReject = () => { - onVerifyConnection(false); + onVerifyConnection(null, false); }; // Request notification permission on first user interaction @@ -449,6 +506,28 @@ 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('label', { + key: 'privacy-mode', + className: "mb-6 mx-auto flex max-w-2xl items-start gap-3 rounded-xl border border-purple-500/20 bg-purple-500/10 p-4 text-left" + }, [ + React.createElement('input', { + key: 'input', + type: 'checkbox', + checked: relayOnlyMode, + onChange: (event) => setRelayOnlyMode(event.target.checked), + className: "mt-1" + }), + React.createElement('span', { key: 'copy' }, [ + React.createElement('span', { + key: 'title', + className: "block text-sm font-medium text-primary" + }, 'Privacy mode: relay-only WebRTC'), + React.createElement('span', { + key: 'desc', + className: "block text-sm text-secondary" + }, 'Uses TURN relay-only when configured. Without TURN, direct WebRTC may expose IP addresses and relay-only connections cannot start.') + ]) + ]), React.createElement('div', { key: 'options', @@ -1464,6 +1543,9 @@ const [messages, setMessages] = React.useState([]); const [connectionStatus, setConnectionStatus] = React.useState('disconnected'); + const [relayOnlyMode, setRelayOnlyMode] = React.useState(() => { + try { return localStorage.getItem('securebit_relay_only_mode') === 'true'; } catch { return false; } + }); // Moved scrollToBottom logic to be available globally const [messageInput, setMessageInput] = React.useState(''); @@ -1680,6 +1762,13 @@ // Create scroll function using global helper const scrollToBottom = createScrollToBottomFunction(chatMessagesRef); + + React.useEffect(() => { + try { localStorage.setItem('securebit_relay_only_mode', String(relayOnlyMode)); } catch {} + if (webrtcManagerRef.current?._config?.webrtc) { + webrtcManagerRef.current._config.webrtc.relayOnly = relayOnlyMode; + } + }, [relayOnlyMode]); // Auto-scroll when messages change React.useEffect(() => { @@ -1909,7 +1998,13 @@ handleKeyExchange, handleVerificationRequired, handleAnswerError, - handleVerificationStateChange + handleVerificationStateChange, + { + webrtc: { + relayOnly: relayOnlyMode, + iceServers: Array.isArray(window.SECUREBIT_ICE_SERVERS) ? window.SECUREBIT_ICE_SERVERS : undefined + } + } ); // Initialize notification integration if permission was already granted @@ -1926,7 +2021,7 @@ } } - handleMessage(' SecureBit.chat Enhanced Security Edition v4.7.56 - 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'); + handleMessage(' SecureBit.chat Enhanced Security Edition v4.8.5 - 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) { @@ -3226,9 +3321,9 @@ } }; - const handleVerifyConnection = async (isValid) => { + const handleVerifyConnection = async (userCode, isValid = true) => { if (isValid) { - webrtcManagerRef.current.confirmVerification(); + webrtcManagerRef.current.confirmVerification(userCode); // Mark local verification as confirmed setLocalVerificationConfirmed(true); @@ -3666,7 +3761,9 @@ markAnswerCreated: markAnswerCreated, notificationIntegrationRef: notificationIntegrationRef, isGeneratingKeys: isGeneratingKeys, - handleCreateOffer: handleCreateOffer + handleCreateOffer: handleCreateOffer, + relayOnlyMode: relayOnlyMode, + setRelayOnlyMode: setRelayOnlyMode }) ), @@ -3810,4 +3907,4 @@ ReactDOM.render(AppWithUpdateChecker, document.getElementById('root')); } else { ReactDOM.render(React.createElement(EnhancedSecureP2PChat), document.getElementById('root')); - } \ No newline at end of file + } diff --git a/src/components/ui/FileTransfer.jsx b/src/components/ui/FileTransfer.jsx index f031c91..457a449 100644 --- a/src/components/ui/FileTransfer.jsx +++ b/src/components/ui/FileTransfer.jsx @@ -3,6 +3,7 @@ const FileTransferComponent = ({ webrtcManager, isConnected }) => { const [dragOver, setDragOver] = React.useState(false); const [transfers, setTransfers] = React.useState({ sending: [], receiving: [] }); const [readyFiles, setReadyFiles] = React.useState([]); // файлы, готовые к скачиванию + const [pendingIncomingFiles, setPendingIncomingFiles] = React.useState([]); const fileInputRef = React.useRef(null); // Update transfers periodically @@ -18,6 +19,14 @@ const FileTransferComponent = ({ webrtcManager, isConnected }) => { return () => clearInterval(interval); }, [isConnected, webrtcManager]); + // Clear session-local UI state when the connection ends so reconnect starts clean. + React.useEffect(() => { + if (isConnected) return; + setReadyFiles([]); + setPendingIncomingFiles([]); + setTransfers({ sending: [], receiving: [] }); + }, [isConnected]); + // Setup file transfer callbacks - ИСПРАВЛЕНИЕ: НЕ отправляем промежуточные сообщения в чат React.useEffect(() => { if (!webrtcManager) return; @@ -61,8 +70,20 @@ const FileTransferComponent = ({ webrtcManager, isConnected }) => { // ИСПРАВЛЕНИЕ: НЕ дублируем сообщения об ошибках // Уведомления об ошибках уже отправляются в WebRTC менеджере + }, + + // Incoming file request callback - user consent is mandatory + (fileRequest) => { + setPendingIncomingFiles(prev => { + if (prev.some(file => file.fileId === fileRequest.fileId)) return prev; + return [...prev, fileRequest]; + }); } ); + + return () => { + webrtcManager.setFileTransferCallbacks(null, null, null, null); + }; }, [webrtcManager]); const handleFileSelect = async (files) => { @@ -177,6 +198,19 @@ const FileTransferComponent = ({ webrtcManager, isConnected }) => { } }; + const handleIncomingDecision = async (fileId, accepted) => { + try { + if (accepted) { + await webrtcManager.acceptIncomingFile(fileId); + } else { + await webrtcManager.rejectIncomingFile(fileId); + } + } finally { + setPendingIncomingFiles(prev => prev.filter(file => file.fileId !== fileId)); + setTransfers(webrtcManager.getFileTransfers()); + } + }; + if (!isConnected) { return React.createElement('div', { className: "p-4 text-center text-muted" @@ -239,6 +273,45 @@ const FileTransferComponent = ({ webrtcManager, isConnected }) => { onChange: handleFileInputChange }), + pendingIncomingFiles.length > 0 && React.createElement('div', { + key: 'incoming-consent', + className: "mt-4 space-y-2" + }, pendingIncomingFiles.map(file => React.createElement('div', { + key: file.fileId, + className: "rounded-lg border border-yellow-500/30 bg-yellow-500/10 p-3" + }, [ + React.createElement('div', { + key: 'info', + className: "mb-3 flex items-center justify-between gap-3" + }, [ + React.createElement('div', { key: 'text' }, [ + React.createElement('div', { + key: 'title', + className: "text-sm font-medium text-primary" + }, 'Incoming file request'), + React.createElement('div', { + key: 'meta', + className: "text-xs text-secondary" + }, `${file.fileName} · ${formatFileSize(file.fileSize)} · ${file.mimeType}`) + ]) + ]), + React.createElement('div', { + key: 'actions', + className: "flex gap-2" + }, [ + React.createElement('button', { + key: 'accept', + onClick: () => handleIncomingDecision(file.fileId, true), + className: "rounded-md bg-green-500/20 px-3 py-2 text-sm text-green-300 hover:bg-green-500/30" + }, 'Accept'), + React.createElement('button', { + key: 'reject', + onClick: () => handleIncomingDecision(file.fileId, false), + className: "rounded-md bg-red-500/20 px-3 py-2 text-sm text-red-300 hover:bg-red-500/30" + }, 'Reject') + ]) + ]))), + // Active Transfers (transfers.sending.length > 0 || transfers.receiving.length > 0) && React.createElement('div', { key: 'transfers', @@ -366,7 +439,7 @@ const FileTransferComponent = ({ webrtcManager, isConnected }) => { a.click(); rf.revokeObjectURL(url); } catch (e) { - alert('Failed to start download: ' + e.message); + alert(e.message || 'This file is no longer available for download.'); } } }, [ @@ -420,4 +493,4 @@ const FileTransferComponent = ({ webrtcManager, isConnected }) => { }; // Export -window.FileTransferComponent = FileTransferComponent; \ No newline at end of file +window.FileTransferComponent = FileTransferComponent; diff --git a/src/components/ui/Header.jsx b/src/components/ui/Header.jsx index 16b5dc0..7b9ad4f 100644 --- a/src/components/ui/Header.jsx +++ b/src/components/ui/Header.jsx @@ -539,7 +539,7 @@ const EnhancedMinimalHeader = ({ React.createElement('p', { key: 'subtitle', className: 'text-xs sm:text-sm text-muted hidden sm:block' - }, 'End-to-end freedom v4.7.56') + }, 'End-to-end freedom v4.8.5') ]) ]), diff --git a/src/network/EnhancedSecureWebRTCManager.js b/src/network/EnhancedSecureWebRTCManager.js index ebc89a1..7151111 100644 --- a/src/network/EnhancedSecureWebRTCManager.js +++ b/src/network/EnhancedSecureWebRTCManager.js @@ -100,6 +100,9 @@ class EnhancedSecureWebRTCManager { SYSTEM_MESSAGE: 'SYSTEM_MESSAGE_FILTERED' }; + static PROTOCOL_VERSION = '4.1'; + static MAX_SAS_ATTEMPTS = 3; + // Static debug flag instead of this._debugMode static DEBUG_MODE = true; // Set to true during development, false in production @@ -141,8 +144,19 @@ class EnhancedSecureWebRTCManager { addNoise: config.antiFingerprinting?.addNoise ?? true, maskPatterns: config.antiFingerprinting?.maskPatterns ?? false, useRandomHeaders: config.antiFingerprinting?.useRandomHeaders ?? false + }, + webrtc: { + relayOnly: config.webrtc?.relayOnly ?? false, + iceServers: config.webrtc?.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' } + ] } }; + this._ipLeakWarningShown = false; // Initialize own logging system this._initializeSecureLogging(); @@ -213,6 +227,7 @@ this._secureLog('info', '🔒 Enhanced Mutex system fully initialized and valida this.verificationCode = null; this.pendingSASCode = null; this.isVerified = false; + this.sasValidationAttempts = 0; this.processedMessageIds = new Set(); // Mutual verification states @@ -243,6 +258,10 @@ this._secureLog('info', '🔒 Enhanced Mutex system fully initialized and valida this.peerPublicKey = null; // Store peer's public key for PFS this.rateLimiterId = null; this.intentionalDisconnect = false; + this._sessionAlive = true; + this._fileTransferInitRetryTimers = new Set(); + this._peerDisconnectCleanupTimer = null; + this._logCleanupInterval = null; this.lastCleanupTime = Date.now(); // Reset notification flags for new connection @@ -915,6 +934,17 @@ this._secureLog('info', '🔒 Enhanced Mutex system fully initialized and valida this._activeTimers = new Set([this._maintenanceScheduler]); } + _trackActiveTimer(timer) { + if (!timer) return timer; + if (!this._activeTimers) this._activeTimers = new Set(); + this._activeTimers.add(timer); + return timer; + } + + _untrackActiveTimer(timer) { + if (timer && this._activeTimers) this._activeTimers.delete(timer); + } + /** * Execute all maintenance tasks in a single cycle */ @@ -3334,9 +3364,9 @@ this._secureLog('info', '🔒 Enhanced Mutex system fully initialized and valida this._startSecurityMonitoring(); // Start periodic log cleanup - setInterval(() => { + this._logCleanupInterval = this._trackActiveTimer(setInterval(() => { this._cleanupLogs(); - }, 300000); + }, 300000)); this._secureLog('info', '✅ Secure WebRTC Manager initialization completed'); this._secureLog('info', '🔒 Global exposure protection: Monitoring only, no automatic removal'); @@ -3646,13 +3676,9 @@ this._secureLog('info', '🔒 Enhanced Mutex system fully initialized and valida const dv = new DataView(bits); const n = (dv.getUint32(0) ^ dv.getUint32(4)) >>> 0; - // Use rejection sampling to avoid bias in SAS code generation - let sasValue; - do { - sasValue = crypto.getRandomValues(new Uint32Array(1))[0]; - } while (sasValue >= 4294967296 - (4294967296 % 10_000_000)); - - const sasCode = String(sasValue % 10_000_000).padStart(7, '0'); + // Deterministic SAS: both peers derive the same display code from the + // same shared key material and canonicalized DTLS fingerprints. + const sasCode = String(n % 10_000_000).padStart(7, '0'); this._secureLog('info', 'SAS code computed successfully', { @@ -4430,6 +4456,10 @@ this._secureLog('info', '🔒 Enhanced Mutex system fully initialized and valida initializeFileTransfer() { try { + if (this._sessionAlive === false) { + return; + } + this._secureLog('info', '🔧 Initializing Enhanced Secure File Transfer system...'); if (this.fileTransferSystem) { @@ -4453,7 +4483,7 @@ this._secureLog('info', '🔒 Enhanced Mutex system fully initialized and valida if (!this.isVerified) { this._secureLog('warn', '⚠️ Connection not verified yet, deferring file transfer initialization'); - setTimeout(() => this.initializeFileTransfer(), 500); + this._scheduleFileTransferInitRetry(500); return; } @@ -4467,7 +4497,7 @@ this._secureLog('info', '🔒 Enhanced Mutex system fully initialized and valida // Ensure encryption keys are present if (!this.encryptionKey || !this.macKey) { this._secureLog('warn', '⚠️ Encryption keys not ready, deferring file transfer initialization'); - setTimeout(() => this.initializeFileTransfer(), 1000); + this._scheduleFileTransferInitRetry(1000); return; } @@ -4490,7 +4520,8 @@ this._secureLog('info', '🔒 Enhanced Mutex system fully initialized and valida this.onFileProgress || null, safeOnComplete, this.onFileError || null, - this.onFileReceived || null + this.onFileReceived || null, + this.onIncomingFileRequest || null ); this._fileTransferActive = true; @@ -4508,6 +4539,21 @@ this._secureLog('info', '🔒 Enhanced Mutex system fully initialized and valida } } + _scheduleFileTransferInitRetry(delay) { + if (this._sessionAlive === false) return null; + if (!this._fileTransferInitRetryTimers) this._fileTransferInitRetryTimers = new Set(); + + const timer = this._trackActiveTimer(setTimeout(() => { + this._fileTransferInitRetryTimers.delete(timer); + this._untrackActiveTimer(timer); + if (this._sessionAlive === false) return; + this.initializeFileTransfer(); + }, delay)); + + this._fileTransferInitRetryTimers.add(timer); + return timer; + } + // ============================================ // ENHANCED SECURITY INITIALIZATION // ============================================ @@ -4664,6 +4710,14 @@ this._secureLog('info', '🔒 Enhanced Mutex system fully initialized and valida currentFeatures: this.securityFeatures }); } + _sanitizeIncomingChatMessage(message) { + if (typeof message !== 'string') { + return message; + } + + return window.EnhancedSecureCryptoUtils.sanitizeMessage(message); + } + deliverMessageToUI(message, type = 'received') { try { // Add debug logs @@ -4735,9 +4789,13 @@ this._secureLog('info', '🔒 Enhanced Mutex system fully initialized and valida } } + const uiMessage = type === 'received' + ? this._sanitizeIncomingChatMessage(message) + : message; + if (this.onMessage) { - this._secureLog('debug', '📤 Calling this.onMessage callback', { message, type }); - this.onMessage(message, type); + this._secureLog('debug', '📤 Calling this.onMessage callback', { message: uiMessage, type }); + this.onMessage(uiMessage, type); } else { this._secureLog('warn', '⚠️ this.onMessage callback is null or undefined'); } @@ -6897,52 +6955,6 @@ async processMessage(data) { } } - disconnect() { - try { - - // Cleanup file transfer system - if (this.fileTransferSystem) { - this.fileTransferSystem.cleanup(); - this.fileTransferSystem = null; - } - - // Stop fake traffic generation - this.stopFakeTrafficGeneration(); - - // Stop decoy traffic - for (const [channelName, timer] of this.decoyTimers.entries()) { - clearTimeout(timer); - } - this.decoyTimers.clear(); - - // Close decoy channels - for (const [channelName, channel] of this.decoyChannels.entries()) { - if (channel.readyState === 'open') { - channel.close(); - } - } - this.decoyChannels.clear(); - - // Clean up packet buffer - this.packetBuffer.clear(); - - // Clean up chunk queue - this.chunkQueue = []; - - // Wipe ephemeral keys for PFS on disconnect - this._wipeEphemeralKeys(); - - // Hard wipe old keys for PFS - this._hardWipeOldKeys(); - - // Clear verification states - this._clearVerificationStates(); - - } catch (error) { - this._secureLog('error', '❌ Error during enhanced disconnect:', { errorType: error?.constructor?.name || 'Unknown' }); - } - } - /** * Clear all verification states and data * Called when verification is rejected or connection is terminated @@ -6957,6 +6969,7 @@ async processMessage(data) { this.isVerified = false; this.verificationCode = null; this.pendingSASCode = null; + this.sasValidationAttempts = 0; // Clear key fingerprint and connection data this.keyFingerprint = null; @@ -7152,18 +7165,38 @@ async processMessage(data) { return null; } - createPeerConnection() { + _hasTurnServer() { + return (this._config.webrtc.iceServers || []).some(server => { + const urls = Array.isArray(server.urls) ? server.urls : [server.urls]; + return urls.some(url => typeof url === 'string' && url.toLowerCase().startsWith('turn:')); + }); + } + + _buildPeerConnectionConfig() { 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' } - ], + iceServers: this._config.webrtc.iceServers, iceCandidatePoolSize: 10, bundlePolicy: 'balanced' }; + if (this._config.webrtc.relayOnly) { + config.iceTransportPolicy = 'relay'; + } + return config; + } + + _warnIfTurnMissing() { + if (this._hasTurnServer() || this._ipLeakWarningShown) return; + this._ipLeakWarningShown = true; + const message = this._config.webrtc.relayOnly + ? 'Privacy mode is enabled, but no TURN server is configured. Relay-only mode cannot connect until TURN is configured; STUN alone does not hide IP addresses.' + : 'Privacy warning: no TURN server is configured. Direct WebRTC connections may expose IP addresses; STUN alone does not provide IP protection.'; + this.deliverMessageToUI(message, 'system'); + } + + createPeerConnection() { + this._sessionAlive = true; + const config = this._buildPeerConnectionConfig(); + this._warnIfTurnMissing(); this.peerConnection = new RTCPeerConnection(config); @@ -9432,7 +9465,7 @@ async processMessage(data) { // Core information (minimal) t: 'offer', // type s: this.peerConnection.localDescription.sdp, // sdp - v: '4.0', // version + v: EnhancedSecureWebRTCManager.PROTOCOL_VERSION, // version ts: currentTimestamp, // timestamp // Cryptographic keys (essential) @@ -9692,17 +9725,13 @@ async processMessage(data) { // Protocol version compatibility check (support both formats) const protocolVersion = version; // Use the version we already extracted - if (protocolVersion !== '4.0') { + if (protocolVersion !== EnhancedSecureWebRTCManager.PROTOCOL_VERSION) { this._secureLog('warn', 'Protocol version mismatch detected', { operationId: operationId, - expectedVersion: '4.0', + expectedVersion: EnhancedSecureWebRTCManager.PROTOCOL_VERSION, receivedVersion: protocolVersion }); - - // For backward compatibility with v3.0, a fallback can be added - if (protocolVersion !== '3.0') { - throw new Error(`Unsupported protocol version: ${protocolVersion}`); - } + throw new Error(`Version mismatch: expected protocol ${EnhancedSecureWebRTCManager.PROTOCOL_VERSION}, received ${protocolVersion}`); } // ============================================ @@ -9717,7 +9746,7 @@ async processMessage(data) { throw new Error('Invalid session salt format - must be array'); } - const expectedSaltLength = protocolVersion === '4.0' ? 64 : 32; + const expectedSaltLength = 64; if (this.sessionSalt.length !== expectedSaltLength) { throw new Error(`Invalid session salt length: expected ${expectedSaltLength}, got ${this.sessionSalt.length}`); } @@ -9877,8 +9906,9 @@ async processMessage(data) { throw new Error('Invalid key types after derivation'); } - // Set verification code from offer - this.verificationCode = offerData.verificationCode; + // Preserve the invitation code only as a temporary legacy field. + // The real SAS is recomputed locally after the DTLS fingerprints exist. + this.verificationCode = offerData.vc || offerData.verificationCode || null; this._secureLog('info', 'Encryption keys derived and set successfully', { operationId: operationId, @@ -10052,6 +10082,23 @@ async processMessage(data) { this._secureLog('error', 'Failed to extract DTLS fingerprint from answer', { error: error.message }); // Continue without fingerprint validation (fallback mode) } + + // Compute the same SAS locally on the answer side. This keeps the + // protocol honest: the peer may announce its SAS later, but it must + // match what we independently derived from the session. + try { + const remoteFP = this._extractDTLSFingerprintFromSDP(offerData.s || offerData.sdp); + const localFP = this.expectedDTLSFingerprint; + const keyBytes = this._decodeKeyFingerprint(this.keyFingerprint); + this.verificationCode = await this._computeSAS(keyBytes, localFP, remoteFP); + this.onStatusChange?.('verifying'); + this.onVerificationRequired(this.verificationCode); + } catch (sasError) { + this._secureLog('error', 'SAS computation failed in createSecureAnswer (Answer side)', { + errorType: sasError?.constructor?.name || 'Unknown' + }); + throw new Error(`SAS computation failed: ${sasError.message}`); + } // Await ICE gathering @@ -10134,7 +10181,7 @@ async processMessage(data) { // Core information (minimal) t: 'answer', // type s: this.peerConnection.localDescription.sdp, // sdp - v: '4.0', // version + v: EnhancedSecureWebRTCManager.PROTOCOL_VERSION, // version ts: currentTimestamp, // timestamp // Cryptographic keys (essential) @@ -10450,6 +10497,11 @@ async processMessage(data) { throw new Error('CRITICAL SECURITY FAILURE: Invalid answer format - hard abort required'); } + const answerVersion = answerData.v || answerData.version; + if (answerVersion !== EnhancedSecureWebRTCManager.PROTOCOL_VERSION) { + throw new Error(`Version mismatch: expected protocol ${EnhancedSecureWebRTCManager.PROTOCOL_VERSION}, received ${answerVersion || 'unknown'}`); + } + // CRITICAL: Strict validation of ECDH public key structure // Support both full and compact key names const ecdhKey = answerData.ecdhPublicKey || answerData.e; @@ -10774,19 +10826,56 @@ async processMessage(data) { } } - confirmVerification() { + /** + * Normalizes and validates the user-entered SAS code. + * Users may enter the same shared SAS with spaces or hyphens. + * @param {string} input + * @returns {boolean} + */ + _validateSASCode(input) { + if (!input || typeof input !== 'string' || !this.verificationCode || typeof this.verificationCode !== 'string') { + return false; + } + + const normalizedInput = input.replace(/[-\s]/g, '').toUpperCase(); + const normalizedActual = this.verificationCode.replace(/[-\s]/g, '').toUpperCase(); + + if (normalizedInput.length !== normalizedActual.length) { + return false; + } + + return window.EnhancedSecureCryptoUtils.constantTimeCompare(normalizedInput, normalizedActual); + } + + confirmVerification(userCode) { try { + if (!this._validateSASCode(userCode)) { + this.sasValidationAttempts = (this.sasValidationAttempts || 0) + 1; + this._secureLog('warn', 'SAS validation failed: user entered incorrect code', { + attempts: this.sasValidationAttempts, + maxAttempts: EnhancedSecureWebRTCManager.MAX_SAS_ATTEMPTS + }); + + if (this.sasValidationAttempts >= EnhancedSecureWebRTCManager.MAX_SAS_ATTEMPTS) { + this.deliverMessageToUI('Verification failed 3 times. Session reset for safety.', 'system'); + this.disconnect(); + throw new Error('SAS_MAX_ATTEMPTS'); + } + + throw new Error('SAS_MISMATCH'); + } // Mark local verification as confirmed this.localVerificationConfirmed = true; + this.sasValidationAttempts = 0; // Send confirmation to peer const confirmationPayload = { type: 'verification_confirmed', data: { timestamp: Date.now(), - verificationMethod: 'SAS', + verificationMethod: 'MANUAL_SAS_ENTRY', securityLevel: 'MITM_PROTECTION_REQUIRED' } }; @@ -10806,12 +10895,17 @@ async processMessage(data) { this._checkBothVerificationsConfirmed(); // Notify UI about local confirmation - this.deliverMessageToUI('You confirmed the verification code. Waiting for peer confirmation...', 'system'); + this.deliverMessageToUI('Code verified locally. Waiting for peer confirmation...', 'system'); this.processMessageQueue(); } catch (error) { - this._secureLog('error', 'SAS verification failed:', { errorType: error?.constructor?.name || 'Unknown' }); - this.deliverMessageToUI('SAS verification failed', 'system'); + if (error.message === 'SAS_MISMATCH') { + this.deliverMessageToUI('Verification failed: the code you entered is incorrect.', 'system'); + } else if (error.message !== 'SAS_MAX_ATTEMPTS') { + this._secureLog('error', 'SAS verification failed:', { errorType: error?.constructor?.name || 'Unknown' }); + this.deliverMessageToUI('SAS verification failed', 'system'); + } + throw error; } } @@ -10946,8 +11040,18 @@ async processMessage(data) { } handleSASCode(data) { + if (!data?.code || typeof data.code !== 'string') { + this._secureLog('warn', 'Invalid SAS announcement received from peer'); + return; + } + + if (this.verificationCode && !this._validateSASCode(data.code)) { + this._secureLog('error', 'Peer-announced SAS does not match locally computed SAS'); + this.deliverMessageToUI('Version or SAS mismatch detected. Connection aborted for safety.', 'system'); + this.disconnect(); + return; + } - this.verificationCode = data.code; this.onStatusChange?.('verifying'); this.onVerificationRequired(this.verificationCode); @@ -11015,8 +11119,8 @@ async processMessage(data) { // Basic required fields will be validated after format detection // Check if this is v4.0 compact format or legacy format - const isV4CompactFormat = offerData.v === '4.0' && offerData.e && offerData.d; - const isV4Format = offerData.version === '4.0' && offerData.ecdhPublicKey && offerData.ecdsaPublicKey; + const isV4CompactFormat = offerData.v === EnhancedSecureWebRTCManager.PROTOCOL_VERSION && offerData.e && offerData.d; + const isV4Format = offerData.version === EnhancedSecureWebRTCManager.PROTOCOL_VERSION && offerData.ecdhPublicKey && offerData.ecdsaPublicKey; // Validate offer type (support compact, legacy v3.0 and v4.0 formats) const isValidType = isV4CompactFormat ? @@ -11028,14 +11132,14 @@ async processMessage(data) { } if (isV4CompactFormat) { - // v4.0 compact format validation + // v4.1 compact format validation const compactRequiredFields = [ 'e', 'd', 'sl', 'vc', 'si', 'ci', 'ac', 'slv' ]; for (const field of compactRequiredFields) { if (!offerData[field]) { - throw new Error(`Missing required v4.0 compact field: ${field}`); + throw new Error(`Missing required v4.1 compact field: ${field}`); } } @@ -11050,7 +11154,7 @@ async processMessage(data) { // Validate salt length if (!Array.isArray(offerData.sl) || offerData.sl.length !== 64) { - throw new Error('Salt must be exactly 64 bytes for v4.0'); + throw new Error('Salt must be exactly 64 bytes for v4.1'); } // Validate verification code format @@ -11069,7 +11173,7 @@ async processMessage(data) { throw new Error('Offer is too old (older than 1 hour)'); } - this._secureLog('info', 'v4.0 compact offer validation passed', { + this._secureLog('info', 'v4.1 compact offer validation passed', { version: offerData.v, hasECDH: !!offerData.e, hasECDSA: !!offerData.d, @@ -11079,7 +11183,7 @@ async processMessage(data) { offerAge: Math.round(offerAge / 1000) + 's' }); } else if (isV4Format) { - // v4.0 enhanced validation + // v4.1 enhanced validation const v4RequiredFields = [ 'ecdhPublicKey', 'ecdsaPublicKey', 'salt', 'verificationCode', 'authChallenge', 'timestamp', 'version', 'securityLevel' @@ -11087,13 +11191,13 @@ async processMessage(data) { for (const field of v4RequiredFields) { if (!offerData[field]) { - throw new Error(`Missing v4.0 field: ${field}`); + throw new Error(`Missing v4.1 field: ${field}`); } } // Validate salt (must be 64 bytes for v4.0) if (!Array.isArray(offerData.salt) || offerData.salt.length !== 64) { - throw new Error('Salt must be exactly 64 bytes for v4.0'); + throw new Error('Salt must be exactly 64 bytes for v4.1'); } // Validate timestamp (not older than 1 hour) @@ -11142,35 +11246,14 @@ async processMessage(data) { throw new Error('Invalid SAS verification code format - MITM protection required'); } - this._secureLog('info', 'v4.0 offer validation passed', { + this._secureLog('info', 'v4.1 offer validation passed', { version: offerData.version, hasSecurityLevel: !!offerData.securityLevel?.level, offerAge: Math.round(offerAge / 1000) + 's' }); } else { - // v3.0 backward compatibility validation - // NOTE: v3.0 has limited security - SAS verification is still critical - const v3RequiredFields = ['publicKey', 'salt', 'verificationCode']; - for (const field of v3RequiredFields) { - if (!offerData[field]) { - throw new Error(`Missing v3.0 field: ${field}`); - } - } - - // Validate salt (32 bytes for v3.0) - if (!Array.isArray(offerData.salt) || offerData.salt.length !== 32) { - throw new Error('Salt must be exactly 32 bytes for v3.0'); - } - - // Validate public key - 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 - }); + const receivedVersion = offerData.v || offerData.version || 'unknown'; + throw new Error(`Version mismatch: expected protocol ${EnhancedSecureWebRTCManager.PROTOCOL_VERSION}, received ${receivedVersion}`); } // Validate SDP structure (basic check for all versions) @@ -11350,10 +11433,18 @@ async processMessage(data) { // Clear all timer references if (this._activeTimers) { this._activeTimers.forEach(timer => { - if (timer) clearInterval(timer); + if (timer) { + clearInterval(timer); + clearTimeout(timer); + } }); this._activeTimers.clear(); } + + if (this._fileTransferInitRetryTimers) { + this._fileTransferInitRetryTimers.clear(); + } + this._logCleanupInterval = null; this._secureLog('info', 'All timers stopped successfully'); } @@ -11413,31 +11504,6 @@ async processMessage(data) { }; } - disconnect() { - // Stop all timers first - 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; @@ -11531,9 +11597,15 @@ async processMessage(data) { } })); - setTimeout(() => { - this.disconnect(); - }, 2000); + if (!this._peerDisconnectCleanupTimer) { + this._peerDisconnectCleanupTimer = this._trackActiveTimer(setTimeout(() => { + const timer = this._peerDisconnectCleanupTimer; + this._peerDisconnectCleanupTimer = null; + this._untrackActiveTimer(timer); + if (this._sessionAlive === false) return; + this.disconnect(); + }, 2000)); + } window.EnhancedSecureCryptoUtils.secureLog.log('info', 'Peer disconnect notification processed', { reason: reason @@ -11544,80 +11616,129 @@ async processMessage(data) { * Secure disconnect with complete memory cleanup */ disconnect() { - this.stopHeartbeat(); - this.isVerified = false; - this.processedMessageIds.clear(); - this.messageCounter = 0; - - // Secure cleanup of cryptographic materials - this._secureCleanupCryptographicMaterials(); - - // Secure wipe of PFS key versions - this.keyVersions.clear(); - this.oldKeys.clear(); - this.currentKeyVersion = 0; - this.lastKeyRotation = Date.now(); - - // Reset message counters - this.sequenceNumber = 0; - this.expectedSequenceNumber = 0; - this.replayWindow.clear(); // Clear replay window - - // Reset security features - this.securityFeatures = { - hasEncryption: true, - hasECDH: true, - hasECDSA: true, - hasMutualAuth: true, - hasMetadataProtection: true, - hasEnhancedReplayProtection: true, - hasNonExtractableKeys: true, - hasRateLimiting: true, - hasEnhancedValidation: true, - hasPFS: true - }; - - // Close connections - if (this.dataChannel) { - this.dataChannel.close(); - this.dataChannel = null; - } - if (this.peerConnection) { - this.peerConnection.close(); - this.peerConnection = null; - } - - // Secure wipe of message queue - if (this.messageQueue && this.messageQueue.length > 0) { - this.messageQueue.forEach((message, index) => { - this._secureWipeMemory(message, `messageQueue[${index}]`); + try { + this._sessionAlive = false; + + // Preserve the explicit-disconnect notification flow before channels are closed. + this.intentionalDisconnect = true; + window.EnhancedSecureCryptoUtils.secureLog.log('info', 'Starting intentional disconnect'); + this.sendDisconnectNotification(); + setTimeout(() => { + this.sendDisconnectNotification(); + }, 100); + + // Stop every timer-backed subsystem first. + this._stopAllTimers(); + this._peerDisconnectCleanupTimer = null; + this.stopHeartbeat(); + this.stopFakeTrafficGeneration(); + for (const timer of this.decoyTimers.entries()) { + clearTimeout(timer[1]); + } + this.decoyTimers.clear(); + + // Pending file transfers must not survive a disconnect. + if (this.fileTransferSystem) { + this.fileTransferSystem.cleanup(); + this.fileTransferSystem = null; + } + + // Close auxiliary channels alongside the primary channel. + for (const channel of this.decoyChannels.values()) { + if (channel.readyState === 'open') channel.close(); + } + this.decoyChannels.clear(); + if (this.heartbeatChannel) { + this.heartbeatChannel.close(); + this.heartbeatChannel = null; + } + + // Reset transport-independent state. + this.isVerified = false; + this.processedMessageIds.clear(); + this.messageCounter = 0; + this.packetBuffer.clear(); + this.chunkQueue = []; + + // Preserve all key/material cleanup from the former implementations. + this._wipeEphemeralKeys(); + this._hardWipeOldKeys(); + 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._clearVerificationStates(); + + this.securityFeatures = { + hasEncryption: true, + hasECDH: true, + hasECDSA: true, + hasMutualAuth: true, + hasMetadataProtection: true, + hasEnhancedReplayProtection: true, + hasNonExtractableKeys: true, + hasRateLimiting: true, + hasEnhancedValidation: true, + hasPFS: true + }; + + // Close live transports, then release their listeners/references. + if (this.dataChannel) { + this.dataChannel.close(); + this.dataChannel.onopen = null; + this.dataChannel.onclose = null; + this.dataChannel.onmessage = null; + this.dataChannel.onerror = null; + this.dataChannel = null; + } + if (this.peerConnection) { + this.peerConnection.close(); + this.peerConnection.onconnectionstatechange = null; + this.peerConnection.ondatachannel = null; + this.peerConnection = null; + } + + if (this.messageQueue && this.messageQueue.length > 0) { + this.messageQueue.forEach((message, index) => { + this._secureWipeMemory(message, `messageQueue[${index}]`); + }); + this.messageQueue = []; + } + + this._forceGarbageCollection().catch(error => { + this._secureLog('error', 'Cleanup failed during disconnect', { + errorType: error?.constructor?.name || 'Unknown' + }); }); - this.messageQueue = []; - } - - // Schedule natural cleanup - this._forceGarbageCollection().catch(error => { - this._secureLog('error', 'Cleanup failed during disconnect', { + + document.dispatchEvent(new CustomEvent('peer-disconnect', { + detail: { + reason: 'user_disconnect', + timestamp: Date.now() + } + })); + document.dispatchEvent(new CustomEvent('connection-cleaned', { + detail: { + timestamp: Date.now(), + reason: 'user_cleanup' + } + })); + + this.onStatusChange('disconnected'); + this.onKeyExchange(''); + this.onVerificationRequired(''); + this._secureLog('info', 'Connection securely cleaned up with complete memory wipe'); + } catch (error) { + this._secureLog('error', '❌ Error during enhanced disconnect:', { errorType: error?.constructor?.name || 'Unknown' }); - }); - - document.dispatchEvent(new CustomEvent('connection-cleaned', { - detail: { - timestamp: Date.now(), - reason: this.intentionalDisconnect ? 'user_cleanup' : 'automatic_cleanup' - } - })); - - // Notify UI about complete cleanup - this.onStatusChange('disconnected'); - this.onKeyExchange(''); - this.onVerificationRequired(''); - - this._secureLog('info', 'Connection securely cleaned up with complete memory wipe'); - - // Reset the intentional disconnect flag - this.intentionalDisconnect = false; + } finally { + this.intentionalDisconnect = false; + } } // Public method to send files async sendFile(file) { @@ -11751,17 +11872,36 @@ async processMessage(data) { } // Set file transfer callbacks - setFileTransferCallbacks(onProgress, onReceived, onError) { + setFileTransferCallbacks(onProgress, onReceived, onError, onIncomingRequest = null) { this.onFileProgress = onProgress; this.onFileReceived = onReceived; this.onFileError = onError; + this.onIncomingFileRequest = onIncomingRequest; - // Reinitialize file transfer system if it exists to update callbacks + // Propagate callback updates into the live transfer system. if (this.fileTransferSystem) { - this.initializeFileTransfer(); + this.fileTransferSystem.onProgress = onProgress; + this.fileTransferSystem.onFileReceived = onReceived; + this.fileTransferSystem.onError = onError; + this.fileTransferSystem.onIncomingFileRequest = onIncomingRequest; } } + getPendingIncomingFiles() { + if (!this.fileTransferSystem) return []; + return this.fileTransferSystem.getPendingIncomingTransfers(); + } + + async acceptIncomingFile(fileId) { + if (!this.fileTransferSystem) return false; + return this.fileTransferSystem.acceptIncomingFile(fileId); + } + + async rejectIncomingFile(fileId) { + if (!this.fileTransferSystem) return false; + return this.fileTransferSystem.rejectIncomingFile(fileId); + } + // ============================================ // SESSION ACTIVATION HANDLING // ============================================ @@ -12708,18 +12848,10 @@ class SecureIndexedDBWrapper { iv: Array.from(new Uint8Array(iv)), algorithm: algorithm, usages: usages, - type: type, - timestamp: Date.now() + type: type }; - const metadataRecord = { - keyId: keyId, - ...metadata, - created: Date.now(), - lastAccessed: Date.now(), - extractable: true, - persistent: true - }; + const metadataRecord = { keyId, ...metadata }; return new Promise((resolve, reject) => { const keysRequest = transaction.objectStore(this.KEYS_STORE).put(keyRecord); @@ -12788,6 +12920,28 @@ class SecureIndexedDBWrapper { getRequest.onerror = () => reject(new Error(`Failed to get metadata: ${getRequest.error}`)); }); } + + async getKeyMetadataRecord(keyId) { + if (!this.db) throw new Error('Database not initialized'); + const transaction = this.db.transaction([this.METADATA_STORE], 'readonly'); + const store = transaction.objectStore(this.METADATA_STORE); + return new Promise((resolve, reject) => { + const request = store.get(keyId); + request.onsuccess = () => resolve(request.result || null); + request.onerror = () => reject(new Error(`Failed to get metadata: ${request.error}`)); + }); + } + + async putKeyMetadataRecord(record) { + if (!this.db) throw new Error('Database not initialized'); + const transaction = this.db.transaction([this.METADATA_STORE], 'readwrite'); + const store = transaction.objectStore(this.METADATA_STORE); + return new Promise((resolve, reject) => { + const request = store.put(record); + request.onsuccess = () => resolve(); + request.onerror = () => reject(new Error(`Failed to store metadata: ${request.error}`)); + }); + } /** * Delete key and its metadata @@ -12840,8 +12994,7 @@ class SecureIndexedDBWrapper { const saltRecord = { id: 'master_salt', - salt: Array.from(new Uint8Array(salt)), - created: Date.now() + salt: Array.from(new Uint8Array(salt)) }; return new Promise((resolve, reject) => { @@ -12934,6 +13087,12 @@ class SecurePersistentKeyStorage { this._dbInitialized = true; } } + + async _ensureMasterKeyUnlocked() { + if (typeof this._masterKeyManager.isUnlocked === 'function' && !this._masterKeyManager.isUnlocked()) { + await this._masterKeyManager.unlock(); + } + } /** * Store extractable key with encryption @@ -12957,6 +13116,14 @@ class SecurePersistentKeyStorage { const { encryptedData, iv } = await this._encryptKeyData(jwkData); // Store encrypted data in IndexedDB + const encryptedMetadata = await this._encryptMetadata({ + ...metadata, + created: Date.now(), + lastAccessed: Date.now(), + extractable: true, + persistent: true + }); + await this._indexedDB.storeEncryptedKey( keyId, encryptedData, @@ -12964,7 +13131,7 @@ class SecurePersistentKeyStorage { cryptoKey.algorithm, cryptoKey.usages, cryptoKey.type, - metadata + encryptedMetadata ); // Store non-extractable reference in memory cache @@ -13006,7 +13173,7 @@ class SecurePersistentKeyStorage { this._keyReferences.set(keyId, restoredKey); // Update last accessed time - await this._indexedDB.updateKeyMetadata(keyId, { lastAccessed: Date.now() }); + await this._updateEncryptedMetadata(keyId, { lastAccessed: Date.now() }); return restoredKey; @@ -13041,7 +13208,13 @@ class SecurePersistentKeyStorage { async listStoredKeys() { try { await this._ensureDBInitialized(); - return await this._indexedDB.listKeys(); + const records = await this._indexedDB.listKeys(); + const results = []; + for (const record of records) { + const metadata = await this._readMetadataWithMigration(record); + if (metadata) results.push({ keyId: record.keyId, ...metadata }); + } + return results; } catch (error) { throw new Error(`Failed to list keys: ${error.message}`); } @@ -13090,6 +13263,58 @@ class SecurePersistentKeyStorage { const jsonString = new TextDecoder().decode(decryptedData); return JSON.parse(jsonString); } + + async _encryptMetadata(metadata) { + const data = new TextEncoder().encode(JSON.stringify(metadata)); + await this._ensureMasterKeyUnlocked(); + const { encryptedData, iv } = await this._masterKeyManager.encryptBytes(data); + return { + metadataVersion: 1, + encryptedMetadata: Array.from(encryptedData), + metadataIv: Array.from(iv) + }; + } + + async _decryptMetadataRecord(record) { + if (!record?.encryptedMetadata || !record?.metadataIv) { + throw new Error('Encrypted metadata missing'); + } + await this._ensureMasterKeyUnlocked(); + const decrypted = await this._masterKeyManager.decryptBytes( + new Uint8Array(record.encryptedMetadata), + new Uint8Array(record.metadataIv) + ); + return JSON.parse(new TextDecoder().decode(decrypted)); + } + + async _readMetadataWithMigration(record) { + if (!record) return null; + if (record.encryptedMetadata) { + try { + return await this._decryptMetadataRecord(record); + } catch (error) { + // Corrupted encrypted metadata must not be exposed or trusted. + return null; + } + } + + // Legacy plaintext record: read once, then migrate to encrypted envelope. + const { keyId, ...legacyMetadata } = record; + const encryptedRecord = { keyId, ...(await this._encryptMetadata(legacyMetadata)) }; + await this._indexedDB.putKeyMetadataRecord(encryptedRecord); + return legacyMetadata; + } + + async _updateEncryptedMetadata(keyId, updates) { + const record = await this._indexedDB.getKeyMetadataRecord(keyId); + if (!record) throw new Error(`Key metadata not found: ${keyId}`); + const current = await this._readMetadataWithMigration(record); + if (!current) throw new Error(`Key metadata corrupted: ${keyId}`); + await this._indexedDB.putKeyMetadataRecord({ + keyId, + ...(await this._encryptMetadata({ ...current, ...updates })) + }); + } /** * Import JWK as non-extractable key @@ -13505,4 +13730,4 @@ export { SecureMasterKeyManager, SecureIndexedDBWrapper, SecurePersistentKeyStorage -}; \ No newline at end of file +}; diff --git a/src/transfer/EnhancedSecureFileTransfer.js b/src/transfer/EnhancedSecureFileTransfer.js index 411510b..38526f0 100644 --- a/src/transfer/EnhancedSecureFileTransfer.js +++ b/src/transfer/EnhancedSecureFileTransfer.js @@ -256,12 +256,13 @@ class SecureMemoryManager { } class EnhancedSecureFileTransfer { - constructor(webrtcManager, onProgress, onComplete, onError, onFileReceived) { + constructor(webrtcManager, onProgress, onComplete, onError, onFileReceived, onIncomingFileRequest) { this.webrtcManager = webrtcManager; this.onProgress = onProgress; this.onComplete = onComplete; this.onError = onError; this.onFileReceived = onFileReceived; + this.onIncomingFileRequest = onIncomingFileRequest; // Validate webrtcManager if (!webrtcManager) { @@ -284,87 +285,58 @@ class EnhancedSecureFileTransfer { 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' + pdf: { + extensions: ['.pdf'], + mimeTypes: ['application/pdf'], + maxSize: 50 * 1024 * 1024, + category: 'PDF', + description: 'PDF' + }, + + text: { + extensions: ['.txt'], + mimeTypes: ['text/plain'], + maxSize: 10 * 1024 * 1024, + category: 'Plain text', + description: 'TXT' }, images: { - extensions: ['.jpg', '.jpeg', '.png', '.gif', '.webp', '.bmp', '.svg', '.ico'], + extensions: ['.jpg', '.jpeg', '.png', '.gif', '.webp', '.bmp', '.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' + description: 'JPG, JPEG, PNG, GIF, WEBP, BMP, 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' - ], + extensions: ['.zip'], + mimeTypes: ['application/zip'], 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' + description: 'ZIP' } }; + this.BLOCKED_EXTENSIONS = new Set([ + '.exe', '.bat', '.cmd', '.sh', '.js', '.msi', '.dmg', '.app', + '.jar', '.scr', '.ps1', '.vbs', '.html', '.svg' + ]); // Active transfers tracking this.activeTransfers = new Map(); // fileId -> transfer state this.receivingTransfers = new Map(); // fileId -> receiving state + this.pendingIncomingTransfers = new Map(); // fileId -> validated metadata awaiting consent this.transferQueue = []; // Queue for pending transfers this.pendingChunks = new Map(); + this.incomingOfferLimiter = new RateLimiter(5, 60000); + this.MAX_PENDING_INCOMING_TRANSFERS = 3; // Session key derivation this.sessionKeys = new Map(); // fileId -> derived session key @@ -373,6 +345,7 @@ class EnhancedSecureFileTransfer { this.processedChunks = new Set(); // Prevent replay attacks this.transferNonces = new Map(); // fileId -> current nonce counter this.receivedFileBuffers = new Map(); // fileId -> { buffer:ArrayBuffer, type:string, name:string, size:number } + this.MAX_RETAINED_RECEIVED_FILE_BUFFERS = 3; this.setupFileMessageHandlers(); @@ -386,24 +359,15 @@ class EnhancedSecureFileTransfer { // ============================================ getFileType(file) { - const fileName = file.name.toLowerCase(); - const fileExtension = fileName.substring(fileName.lastIndexOf('.')); - const mimeType = file.type.toLowerCase(); + const fileName = String(file?.name || '').toLowerCase(); + const extensionIndex = fileName.lastIndexOf('.'); + const fileExtension = extensionIndex >= 0 ? fileName.substring(extensionIndex) : ''; + const mimeType = String(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)) { + const extensionAllowed = typeConfig.extensions.includes(fileExtension); + const mimeAllowed = typeConfig.mimeTypes.includes(mimeType); + if (extensionAllowed && mimeAllowed) { return { type: typeKey, category: typeConfig.category, @@ -414,26 +378,42 @@ class EnhancedSecureFileTransfer { } } - const generalConfig = this.FILE_TYPE_RESTRICTIONS.general; return { - type: 'general', - category: generalConfig.category, - description: generalConfig.description, - maxSize: generalConfig.maxSize, - allowed: true + type: 'blocked', + category: 'Unsupported', + description: 'Allowed: JPG, JPEG, PNG, GIF, WEBP, BMP, ICO, PDF, TXT, ZIP', + maxSize: this.MAX_FILE_SIZE, + allowed: false, + extension: fileExtension, + mimeType }; } validateFile(file) { const fileType = this.getFileType(file); const errors = []; + const fileName = String(file?.name || ''); + const lowerName = fileName.toLowerCase(); + const extensionIndex = lowerName.lastIndexOf('.'); + const fileExtension = extensionIndex >= 0 ? lowerName.substring(extensionIndex) : ''; + const mimeType = String(file?.type || '').toLowerCase(); + + if (this.BLOCKED_EXTENSIONS.has(fileExtension)) { + errors.push(`File rejected: ${fileExtension} files are not allowed for security reasons.`); + } + + if (!mimeType) { + errors.push('File rejected: missing MIME type is unsafe.'); + } 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 (mimeType && !this.BLOCKED_EXTENSIONS.has(fileExtension)) { + errors.push(`File rejected: extension and MIME type must match an allowed type. Supported types: ${fileType.description}`); + } } if (file.size > this.MAX_FILE_SIZE) { @@ -449,6 +429,48 @@ class EnhancedSecureFileTransfer { }; } + normalizeDisplayFileName(fileName) { + return String(fileName || '') + .normalize('NFKC') + .replace(/[\u0000-\u001F\u007F]/g, '') + .replace(/[\\/]+/g, '_') + .trim() + .slice(0, 255); + } + + validateIncomingMetadata(metadata) { + const errors = []; + if (!metadata || typeof metadata !== 'object') errors.push('Invalid file transfer metadata'); + if (!metadata?.fileId || typeof metadata.fileId !== 'string') errors.push('Invalid file id'); + if (!Number.isSafeInteger(metadata?.fileSize) || metadata.fileSize <= 0) errors.push('Invalid file size'); + if (!Number.isSafeInteger(metadata?.totalChunks) || metadata.totalChunks <= 0) errors.push('Invalid chunk count'); + if (!Number.isSafeInteger(metadata?.chunkSize) || metadata.chunkSize <= 0 || metadata.chunkSize > this.CHUNK_SIZE) errors.push('Invalid chunk size'); + if (!Array.isArray(metadata?.salt) || metadata.salt.length !== 32) errors.push('Invalid salt'); + + const rawName = typeof metadata?.fileName === 'string' ? metadata.fileName : ''; + const displayName = this.normalizeDisplayFileName(rawName); + const hasDangerousName = + !rawName || + rawName !== rawName.trim() || + /[\u0000-\u001F\u007F]/.test(rawName) || + /[\\/]/.test(rawName) || + rawName === '.' || + rawName === '..' || + displayName.length === 0; + if (hasDangerousName) errors.push('Dangerous file name'); + + if (errors.length === 0) { + const validation = this.validateFile({ + name: displayName, + size: metadata.fileSize, + type: metadata.fileType || 'application/octet-stream' + }); + if (!validation.isValid) errors.push(...validation.errors); + } + + return { isValid: errors.length === 0, errors, displayName }; + } + formatFileSize(bytes) { if (bytes === 0) return '0 B'; const k = 1024; @@ -461,8 +483,6 @@ class EnhancedSecureFileTransfer { 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, @@ -878,10 +898,21 @@ class EnhancedSecureFileTransfer { this.activeTransfers.set(fileId, transferState); this.transferNonces.set(fileId, 0); + const consentPromise = new Promise((resolve, reject) => { + transferState.resolveConsent = resolve; + transferState.rejectConsent = reject; + transferState.consentTimeout = setTimeout(() => { + transferState.consentTimeout = null; + reject(new Error('Transfer timeout')); + }, 30000); + }); + // Send file metadata first await this.sendFileMetadata(transferState); - // Start chunk transmission + // Wait for explicit receiver consent before any chunks are sent. + await consentPromise; + await this.startChunkTransmission(transferState); return fileId; @@ -1106,11 +1137,14 @@ class EnhancedSecureFileTransfer { async handleFileTransferStart(metadata) { try { - // Validate metadata - if (!metadata.fileId || !metadata.fileName || !metadata.fileSize) { - throw new Error('Invalid file transfer metadata'); + const clientId = this.getClientIdentifier(); + if (!this.incomingOfferLimiter.isAllowed(clientId)) { + throw new Error('Incoming file request rate limit exceeded'); } + const validation = this.validateIncomingMetadata(metadata); + if (!validation.isValid) throw new Error(validation.errors.join('. ')); + if (metadata.signature && this.verificationKey) { try { const isValid = await FileMetadataSigner.verifyFileMetadata( @@ -1137,55 +1171,30 @@ class EnhancedSecureFileTransfer { } // Check if we already have this transfer - if (this.receivingTransfers.has(metadata.fileId)) { + if (this.receivingTransfers.has(metadata.fileId) || this.pendingIncomingTransfers.has(metadata.fileId)) { return; } - - // Derive session key from salt - const sessionKey = await this.deriveFileSessionKeyFromSalt( - metadata.fileId, - metadata.salt - ); - - // Create receiving transfer state - 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: sessionKey, - salt: metadata.salt, - receivedChunks: new Map(), - receivedCount: 0, - startTime: Date.now(), - lastChunkTime: Date.now(), - status: 'receiving' - }; - - this.receivingTransfers.set(metadata.fileId, receivingState); - - // Send acceptance response - const response = { - type: 'file_transfer_response', - fileId: metadata.fileId, - accepted: true, - timestamp: Date.now() - }; - - await this.sendSecureMessage(response); - // Process buffered chunks if any - 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); + if (this.pendingIncomingTransfers.size >= this.MAX_PENDING_INCOMING_TRANSFERS) { + throw new Error('Too many pending incoming file requests'); + } + + const pendingMetadata = { + ...metadata, + fileName: validation.displayName, + receivedAt: Date.now() + }; + this.pendingIncomingTransfers.set(metadata.fileId, pendingMetadata); + + if (typeof this.onIncomingFileRequest === 'function') { + this.onIncomingFileRequest({ + fileId: pendingMetadata.fileId, + fileName: pendingMetadata.fileName, + fileSize: pendingMetadata.fileSize, + mimeType: pendingMetadata.fileType || 'application/octet-stream' + }); + } else { + await this.rejectIncomingFile(metadata.fileId, 'User consent unavailable'); } } catch (error) { @@ -1211,13 +1220,8 @@ class EnhancedSecureFileTransfer { try { let receivingState = this.receivingTransfers.get(chunkMessage.fileId); - // Buffer early chunks if transfer not yet initialized + // Never buffer chunks before explicit consent. if (!receivingState) { - if (!this.pendingChunks.has(chunkMessage.fileId)) { - this.pendingChunks.set(chunkMessage.fileId, new Map()); - } - - this.pendingChunks.get(chunkMessage.fileId).set(chunkMessage.chunkIndex, chunkMessage); return; } @@ -1352,7 +1356,7 @@ class EnhancedSecureFileTransfer { receivingState.endTime = Date.now(); receivingState.status = 'completed'; - this.receivedFileBuffers.set(receivingState.fileId, { + this._storeReceivedFileBuffer(receivingState.fileId, { buffer: fileBuffer, type: receivingState.fileType, name: receivingState.fileName, @@ -1360,7 +1364,13 @@ class EnhancedSecureFileTransfer { }); if (this.onFileReceived) { - const getBlob = async () => new Blob([this.receivedFileBuffers.get(receivingState.fileId).buffer], { type: receivingState.fileType }); + const getBlob = async () => { + const blob = await this.getBlob(receivingState.fileId); + if (!blob) { + throw new Error('This file is no longer available for download.'); + } + return blob; + }; const getObjectURL = async () => { const blob = await getBlob(); return URL.createObjectURL(blob); @@ -1443,8 +1453,18 @@ class EnhancedSecureFileTransfer { if (response.accepted) { transferState.status = 'accepted'; + if (transferState.consentTimeout) clearTimeout(transferState.consentTimeout); + transferState.consentTimeout = null; + transferState.resolveConsent?.(); + transferState.resolveConsent = null; + transferState.rejectConsent = null; } else { transferState.status = 'rejected'; + if (transferState.consentTimeout) clearTimeout(transferState.consentTimeout); + transferState.consentTimeout = null; + transferState.rejectConsent?.(new Error(response.error || 'Transfer rejected')); + transferState.rejectConsent = null; + transferState.resolveConsent = null; if (this.onError) { this.onError(`Transfer rejected: ${response.error || 'Unknown reason'}`); @@ -1555,6 +1575,48 @@ class EnhancedSecureFileTransfer { })); } + getPendingIncomingTransfers() { + return Array.from(this.pendingIncomingTransfers.values()).map(transfer => ({ + fileId: transfer.fileId, + fileName: transfer.fileName, + fileSize: transfer.fileSize, + mimeType: transfer.fileType || 'application/octet-stream', + receivedAt: transfer.receivedAt + })); + } + + async acceptIncomingFile(fileId) { + const metadata = this.pendingIncomingTransfers.get(fileId); + if (!metadata) return false; + const sessionKey = await this.deriveFileSessionKeyFromSalt(fileId, metadata.salt); + this.receivingTransfers.set(fileId, { + 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: new Map(), + receivedCount: 0, + startTime: Date.now(), + lastChunkTime: Date.now(), + status: 'receiving' + }); + this.pendingIncomingTransfers.delete(fileId); + await this.sendSecureMessage({ type: 'file_transfer_response', fileId, accepted: true, timestamp: Date.now() }); + return true; + } + + async rejectIncomingFile(fileId, error = 'Rejected by user') { + if (!this.pendingIncomingTransfers.has(fileId)) return false; + this.pendingIncomingTransfers.delete(fileId); + await this.sendSecureMessage({ type: 'file_transfer_response', fileId, accepted: false, error, timestamp: Date.now() }); + return true; + } + cancelTransfer(fileId) { try { if (this.activeTransfers.has(fileId)) { @@ -1573,6 +1635,19 @@ class EnhancedSecureFileTransfer { } cleanupTransfer(fileId) { + const transferState = this.activeTransfers.get(fileId); + if (transferState) { + if (transferState.consentTimeout) { + clearTimeout(transferState.consentTimeout); + transferState.consentTimeout = null; + } + if (transferState.rejectConsent) { + transferState.rejectConsent(new Error('Transfer cancelled during cleanup or disconnect')); + transferState.rejectConsent = null; + transferState.resolveConsent = null; + } + } + this.activeTransfers.delete(fileId); this.sessionKeys.delete(fileId); this.transferNonces.delete(fileId); @@ -1585,6 +1660,28 @@ class EnhancedSecureFileTransfer { } } + _storeReceivedFileBuffer(fileId, entry) { + this.receivedFileBuffers.set(fileId, entry); + while (this.receivedFileBuffers.size > this.MAX_RETAINED_RECEIVED_FILE_BUFFERS) { + const oldestFileId = this.receivedFileBuffers.keys().next().value; + this._discardReceivedFileBuffer(oldestFileId); + } + } + + _discardReceivedFileBuffer(fileId) { + const fileBuffer = this.receivedFileBuffers.get(fileId); + if (!fileBuffer) return; + try { + if (fileBuffer.buffer) { + SecureMemoryManager.secureWipe(fileBuffer.buffer); + new Uint8Array(fileBuffer.buffer).fill(0); + } + } catch (_) { + // Best-effort wipe; deletion must still proceed. + } + this.receivedFileBuffers.delete(fileId); + } + // ✅ УЛУЧШЕННАЯ безопасная очистка памяти для предотвращения use-after-free cleanupReceivingTransfer(fileId) { try { @@ -1809,6 +1906,7 @@ class EnhancedSecureFileTransfer { // Clear all state this.pendingChunks.clear(); + this.pendingIncomingTransfers.clear(); this.activeTransfers.clear(); this.receivingTransfers.clear(); this.transferQueue.length = 0; @@ -1816,6 +1914,10 @@ class EnhancedSecureFileTransfer { this.transferNonces.clear(); this.processedChunks.clear(); + for (const fileId of Array.from(this.receivedFileBuffers.keys())) { + this._discardReceivedFileBuffer(fileId); + } + this.clearKeys(); } @@ -2026,4 +2128,4 @@ class EnhancedSecureFileTransfer { } } -export { EnhancedSecureFileTransfer }; \ No newline at end of file +export { EnhancedSecureFileTransfer }; diff --git a/tests/disconnect-cleanup.test.mjs b/tests/disconnect-cleanup.test.mjs new file mode 100644 index 0000000..00d6805 --- /dev/null +++ b/tests/disconnect-cleanup.test.mjs @@ -0,0 +1,120 @@ +import assert from 'node:assert/strict'; + +globalThis.window = { + EnhancedSecureCryptoUtils: { + secureLog: { log() {} } + } +}; +globalThis.CustomEvent = class CustomEvent { + constructor(type, init) { + this.type = type; + this.detail = init?.detail; + } +}; +const dispatchedEvents = []; +globalThis.document = { + dispatchEvent(event) { + dispatchedEvents.push(event); + } +}; + +const { EnhancedSecureWebRTCManager } = await import('../src/network/EnhancedSecureWebRTCManager.js'); + +function closableChannel() { + return { + readyState: 'open', + closed: false, + onopen() {}, + onclose() {}, + onmessage() {}, + onerror() {}, + close() { this.closed = true; } + }; +} + +{ + let transferCleanups = 0; + const dataChannel = closableChannel(); + const heartbeatChannel = closableChannel(); + const decoyChannel = closableChannel(); + const peerConnection = { + closed: false, + onconnectionstatechange() {}, + ondatachannel() {}, + close() { this.closed = true; } + }; + const timer = setTimeout(() => {}, 10_000); + const manager = { + intentionalDisconnect: false, + fileTransferSystem: { cleanup() { transferCleanups += 1; } }, + dataChannel, + heartbeatChannel, + peerConnection, + decoyTimers: new Map([['decoy', timer]]), + decoyChannels: new Map([['decoy', decoyChannel]]), + packetBuffer: new Map([['p', 1]]), + chunkQueue: [1], + processedMessageIds: new Set(['m']), + messageCounter: 4, + keyVersions: new Map([['v', 1]]), + oldKeys: new Map([['o', 1]]), + currentKeyVersion: 3, + lastKeyRotation: 1, + sequenceNumber: 7, + expectedSequenceNumber: 8, + replayWindow: new Set([9]), + messageQueue: [{ secret: true }], + calls: [], + _stopAllTimers() { this.calls.push('_stopAllTimers'); }, + stopHeartbeat() { this.calls.push('stopHeartbeat'); }, + stopFakeTrafficGeneration() { this.calls.push('stopFakeTrafficGeneration'); }, + _wipeEphemeralKeys() { this.calls.push('_wipeEphemeralKeys'); }, + _hardWipeOldKeys() { this.calls.push('_hardWipeOldKeys'); }, + _secureCleanupCryptographicMaterials() { this.calls.push('_secureCleanupCryptographicMaterials'); }, + _clearVerificationStates() { + this.calls.push('_clearVerificationStates'); + this.localVerificationConfirmed = false; + this.remoteVerificationConfirmed = false; + this.bothVerificationsConfirmed = false; + this.isVerified = false; + this.verificationCode = null; + this.pendingSASCode = null; + }, + _secureWipeMemory() { this.calls.push('_secureWipeMemory'); }, + _forceGarbageCollection() { return Promise.resolve(); }, + sendDisconnectNotification() { this.calls.push('sendDisconnectNotification'); }, + onStatusChange(value) { this.status = value; }, + onKeyExchange(value) { this.keyExchange = value; }, + onVerificationRequired(value) { this.verificationRequired = value; }, + _secureLog() {} + }; + + EnhancedSecureWebRTCManager.prototype.disconnect.call(manager); + + assert.equal(transferCleanups, 1); + assert.equal(manager.fileTransferSystem, null); + assert.equal(dataChannel.closed, true); + assert.equal(heartbeatChannel.closed, true); + assert.equal(decoyChannel.closed, true); + assert.equal(peerConnection.closed, true); + assert.equal(manager.dataChannel, null); + assert.equal(manager.heartbeatChannel, null); + assert.equal(manager.peerConnection, null); + assert.equal(manager.decoyTimers.size, 0); + assert.equal(manager.decoyChannels.size, 0); + assert.equal(manager.packetBuffer.size, 0); + assert.deepEqual(manager.chunkQueue, []); + assert.equal(manager.processedMessageIds.size, 0); + assert.equal(manager.keyVersions.size, 0); + assert.equal(manager.oldKeys.size, 0); + assert.equal(manager.replayWindow.size, 0); + assert.deepEqual(manager.messageQueue, []); + assert.equal(manager.status, 'disconnected'); + assert.equal(manager.keyExchange, ''); + assert.equal(manager.verificationRequired, ''); + assert.ok(manager.calls.includes('_clearVerificationStates')); + assert.ok(dispatchedEvents.some(event => event.type === 'peer-disconnect')); + assert.ok(dispatchedEvents.some(event => event.type === 'connection-cleaned')); +} + +console.log('Disconnect cleanup tests passed'); diff --git a/tests/file-transfer-callback-propagation.test.mjs b/tests/file-transfer-callback-propagation.test.mjs new file mode 100644 index 0000000..d603e7b --- /dev/null +++ b/tests/file-transfer-callback-propagation.test.mjs @@ -0,0 +1,31 @@ +import assert from 'node:assert/strict'; + +globalThis.window = { EnhancedSecureCryptoUtils: {} }; +const { EnhancedSecureWebRTCManager } = await import('../src/network/EnhancedSecureWebRTCManager.js'); + +{ + const oldProgress = () => {}; + const manager = { + fileTransferSystem: { + onProgress: oldProgress, + onFileReceived: oldProgress, + onError: oldProgress, + onIncomingFileRequest: oldProgress + } + }; + + EnhancedSecureWebRTCManager.prototype.setFileTransferCallbacks.call( + manager, + null, + null, + null, + null + ); + + assert.equal(manager.fileTransferSystem.onProgress, null); + assert.equal(manager.fileTransferSystem.onFileReceived, null); + assert.equal(manager.fileTransferSystem.onError, null); + assert.equal(manager.fileTransferSystem.onIncomingFileRequest, null); +} + +console.log('File transfer callback propagation tests passed'); diff --git a/tests/file-transfer-cleanup.test.mjs b/tests/file-transfer-cleanup.test.mjs new file mode 100644 index 0000000..0d12e37 --- /dev/null +++ b/tests/file-transfer-cleanup.test.mjs @@ -0,0 +1,90 @@ +import assert from 'node:assert/strict'; +import { EnhancedSecureFileTransfer } from '../src/transfer/EnhancedSecureFileTransfer.js'; + +function createSystem() { + const manager = { + dataChannel: { onmessage: null, send() {}, readyState: 'open' }, + isVerified: true, + fileTransferSystem: null, + isConnected: () => true + }; + return new EnhancedSecureFileTransfer(manager); +} + +// cleanupTransfer rejects pending sender consent immediately and clears its timeout. +{ + const system = createSystem(); + let rejectionMessage = null; + const timer = setTimeout(() => {}, 10_000); + system.activeTransfers.set('file_waiting', { + consentTimeout: timer, + rejectConsent(error) { rejectionMessage = error.message; }, + resolveConsent() {} + }); + system.sessionKeys.set('file_waiting', {}); + system.transferNonces.set('file_waiting', 1); + + system.cleanupTransfer('file_waiting'); + + assert.equal(system.activeTransfers.has('file_waiting'), false); + assert.equal(system.sessionKeys.has('file_waiting'), false); + assert.equal(system.transferNonces.has('file_waiting'), false); + assert.equal(rejectionMessage, 'Transfer cancelled during cleanup or disconnect'); + assert.equal(system.activeTransfers.size, 0); +} + +// global cleanup does not leave pending consent promises alive until timeout. +{ + const system = createSystem(); + let rejected = false; + const timer = setTimeout(() => {}, 10_000); + system.activeTransfers.set('file_waiting', { + consentTimeout: timer, + rejectConsent() { rejected = true; }, + resolveConsent() {} + }); + system.cleanup(); + assert.equal(rejected, true); + assert.equal(system.activeTransfers.size, 0); +} + +// receivedFileBuffers is bounded and evicts the oldest retained buffer. +{ + const system = createSystem(); + system.MAX_RETAINED_RECEIVED_FILE_BUFFERS = 2; + system._storeReceivedFileBuffer('a', { buffer: new Uint8Array([1]).buffer }); + system._storeReceivedFileBuffer('b', { buffer: new Uint8Array([2]).buffer }); + system._storeReceivedFileBuffer('c', { buffer: new Uint8Array([3]).buffer }); + assert.equal(system.receivedFileBuffers.size, 2); + assert.equal(system.receivedFileBuffers.has('a'), false); + assert.equal(system.receivedFileBuffers.has('b'), true); + assert.equal(system.receivedFileBuffers.has('c'), true); +} + +// Evicted received buffers fail gracefully for old download closures. +{ + const system = createSystem(); + system.MAX_RETAINED_RECEIVED_FILE_BUFFERS = 1; + let fileData = null; + system.onFileReceived = data => { fileData = data; }; + system.calculateFileHashFromData = async () => 'hash'; + system.sendSecureMessage = async () => {}; + const receivingState = { + fileId: 'old', + fileName: 'old.pdf', + fileSize: 1, + fileType: 'application/pdf', + fileHash: 'hash', + totalChunks: 1, + receivedChunks: new Map([[0, new Uint8Array([1]).buffer]]), + startTime: Date.now() + }; + await system.assembleFile(receivingState); + system._storeReceivedFileBuffer('new', { buffer: new Uint8Array([2]).buffer }); + await assert.rejects( + () => fileData.getObjectURL(), + /no longer available for download/i + ); +} + +console.log('File transfer cleanup tests passed'); diff --git a/tests/file-transfer-consent.test.mjs b/tests/file-transfer-consent.test.mjs new file mode 100644 index 0000000..bf6f50b --- /dev/null +++ b/tests/file-transfer-consent.test.mjs @@ -0,0 +1,62 @@ +import assert from 'node:assert/strict'; +import { EnhancedSecureFileTransfer } from '../src/transfer/EnhancedSecureFileTransfer.js'; + +function createSystem(onIncomingFileRequest = () => {}) { + const manager = { + dataChannel: { onmessage: null, send() {}, readyState: 'open' }, + isVerified: true, + fileTransferSystem: null, + isConnected: () => true + }; + const system = new EnhancedSecureFileTransfer(manager, null, null, null, null, onIncomingFileRequest); + system.sendSecureMessage = async () => {}; + return system; +} + +function validMetadata(overrides = {}) { + return { + type: 'file_transfer_start', + fileId: 'file_1', + fileName: 'report.pdf', + fileSize: 1024, + fileType: 'application/pdf', + fileHash: 'abc', + totalChunks: 1, + chunkSize: 1024, + salt: new Array(32).fill(1), + ...overrides + }; +} + +// Metadata is validated before a consent prompt is shown. +{ + const system = createSystem(); + assert.equal(system.validateIncomingMetadata(validMetadata()).isValid, true); + assert.equal(system.validateIncomingMetadata(validMetadata({ fileName: '../evil.pdf' })).isValid, false); + assert.equal(system.validateIncomingMetadata(validMetadata({ fileSize: 200 * 1024 * 1024 })).isValid, false); +} + +// No receiving state or chunk buffers are allocated before explicit acceptance. +{ + let prompted = null; + const system = createSystem(request => { prompted = request; }); + await system.handleFileTransferStart(validMetadata()); + assert.equal(prompted.fileName, 'report.pdf'); + assert.equal(system.pendingIncomingTransfers.size, 1); + assert.equal(system.receivingTransfers.size, 0); + + await system.handleFileChunk({ fileId: 'file_1', chunkIndex: 0 }); + assert.equal(system.pendingChunks.size, 0); +} + +// Incoming request spam is bounded. +{ + const system = createSystem(); + for (let index = 0; index < system.MAX_PENDING_INCOMING_TRANSFERS; index += 1) { + await system.handleFileTransferStart(validMetadata({ fileId: `file_${index}` })); + } + await system.handleFileTransferStart(validMetadata({ fileId: 'file_overflow' })); + assert.equal(system.pendingIncomingTransfers.size, system.MAX_PENDING_INCOMING_TRANSFERS); +} + +console.log('File transfer consent tests passed'); diff --git a/tests/file-transfer-ui-cleanup.test.mjs b/tests/file-transfer-ui-cleanup.test.mjs new file mode 100644 index 0000000..30b1e24 --- /dev/null +++ b/tests/file-transfer-ui-cleanup.test.mjs @@ -0,0 +1,75 @@ +import assert from 'node:assert/strict'; +import fs from 'node:fs'; +import vm from 'node:vm'; + +const effects = []; +const setterCalls = []; +let stateIndex = 0; +const callbackCalls = []; + +const context = { + window: {}, + React: { + useState(initialValue) { + const index = stateIndex++; + return [initialValue, value => setterCalls.push({ index, value })]; + }, + useRef(initialValue) { + return { current: initialValue }; + }, + useEffect(effect) { + effects.push(effect); + }, + createElement() { + return null; + } + } +}; + +const source = fs.readFileSync(new URL('../src/components/ui/FileTransfer.jsx', import.meta.url), 'utf8'); +vm.runInNewContext(source, context); + +const manager = { + fileTransferSystem: { + onProgress: () => {}, + onFileReceived: () => {}, + onError: () => {}, + onIncomingFileRequest: () => {} + }, + setFileTransferCallbacks(...args) { + callbackCalls.push(args); + this.onFileProgress = args[0]; + this.onFileReceived = args[1]; + this.onFileError = args[2]; + this.onIncomingFileRequest = args[3]; + if (this.fileTransferSystem) { + this.fileTransferSystem.onProgress = args[0]; + this.fileTransferSystem.onFileReceived = args[1]; + this.fileTransferSystem.onError = args[2]; + this.fileTransferSystem.onIncomingFileRequest = args[3]; + } + }, + getFileTransfers() { + return { sending: [], receiving: [] }; + }, + isConnected() { + return false; + }, + isVerified: false +}; + +context.window.FileTransferComponent({ webrtcManager: manager, isConnected: false }); +const cleanups = effects.map(effect => effect()).filter(Boolean); + +assert.ok(setterCalls.some(call => call.index === 2 && Array.isArray(call.value) && call.value.length === 0)); +assert.ok(setterCalls.some(call => call.index === 3 && Array.isArray(call.value) && call.value.length === 0)); +assert.ok(setterCalls.some(call => call.index === 1 && call.value.sending.length === 0 && call.value.receiving.length === 0)); + +cleanups.forEach(cleanup => cleanup()); +assert.deepEqual(callbackCalls.at(-1), [null, null, null, null]); +assert.equal(manager.fileTransferSystem.onProgress, null); +assert.equal(manager.fileTransferSystem.onFileReceived, null); +assert.equal(manager.fileTransferSystem.onError, null); +assert.equal(manager.fileTransferSystem.onIncomingFileRequest, null); + +console.log('File transfer UI cleanup tests passed'); diff --git a/tests/file-type-allowlist.test.mjs b/tests/file-type-allowlist.test.mjs new file mode 100644 index 0000000..4f3f8d0 --- /dev/null +++ b/tests/file-type-allowlist.test.mjs @@ -0,0 +1,41 @@ +import assert from 'node:assert/strict'; +import { EnhancedSecureFileTransfer } from '../src/transfer/EnhancedSecureFileTransfer.js'; + +function createSystem() { + const manager = { + dataChannel: { onmessage: null, send() {}, readyState: 'open' }, + isVerified: true, + fileTransferSystem: null, + isConnected: () => true + }; + return new EnhancedSecureFileTransfer(manager, null, null, null, null, null); +} + +function file(name, type, size = 1024) { + return { name, type, size }; +} + +const system = createSystem(); + +// Allowed files +assert.equal(system.validateFile(file('photo.png', 'image/png')).isValid, true); +assert.equal(system.validateFile(file('report.pdf', 'application/pdf')).isValid, true); +assert.equal(system.validateFile(file('notes.txt', 'text/plain')).isValid, true); +assert.equal(system.validateFile(file('bundle.zip', 'application/zip')).isValid, true); + +// Explicitly blocked extensions +for (const name of ['run.exe', 'boot.bat', 'shell.sh', 'payload.js', 'page.html', 'vector.svg']) { + assert.equal(system.validateFile(file(name, 'application/octet-stream')).isValid, false, name); +} + +// MIME spoofing: safe extension with unsafe MIME and unsafe extension with safe MIME are blocked. +assert.equal(system.validateFile(file('photo.png', 'application/x-msdownload')).isValid, false); +assert.equal(system.validateFile(file('payload.exe', 'image/png')).isValid, false); + +// Missing MIME is unsafe. +assert.equal(system.validateFile(file('photo.png', '')).isValid, false); + +// Uppercase extension bypass is blocked. +assert.equal(system.validateFile(file('PAYLOAD.EXE', 'application/octet-stream')).isValid, false); + +console.log('File type allowlist tests passed'); diff --git a/tests/incoming-message-sanitization.test.mjs b/tests/incoming-message-sanitization.test.mjs new file mode 100644 index 0000000..c9a9790 --- /dev/null +++ b/tests/incoming-message-sanitization.test.mjs @@ -0,0 +1,57 @@ +import assert from 'node:assert/strict'; + +globalThis.window = { + DEBUG_MODE: true, + DEVELOPMENT_MODE: true, + webpackHotUpdate: {}, + location: { + hostname: 'localhost', + search: '?debug' + } +}; + +const { EnhancedSecureCryptoUtils } = await import('../src/crypto/EnhancedSecureCryptoUtils.js'); +window.EnhancedSecureCryptoUtils = EnhancedSecureCryptoUtils; +const { EnhancedSecureWebRTCManager } = await import('../src/network/EnhancedSecureWebRTCManager.js'); + +function createManager() { + return { + delivered: [], + _debugMode: false, + _secureLog() {}, + _sanitizeIncomingChatMessage: EnhancedSecureWebRTCManager.prototype._sanitizeIncomingChatMessage, + onMessage(message, type) { + this.delivered.push({ message, type }); + } + }; +} + +// Normal text survives unchanged. +{ + const manager = createManager(); + EnhancedSecureWebRTCManager.prototype.deliverMessageToUI.call(manager, 'hello secure world', 'received'); + assert.deepEqual(manager.delivered[0], { message: 'hello secure world', type: 'received' }); +} + +// XSS-like and HTML payloads are sanitized before UI delivery. +{ + const manager = createManager(); + EnhancedSecureWebRTCManager.prototype.deliverMessageToUI.call(manager, 'Hello peer', 'received'); + assert.deepEqual(manager.delivered[0], { message: 'Hello peer', type: 'received' }); +} + +// Event-handler and protocol strings are removed before reaching React state. +{ + const manager = createManager(); + EnhancedSecureWebRTCManager.prototype.deliverMessageToUI.call(manager, ' javascript:alert(1)', 'received'); + assert.deepEqual(manager.delivered[0], { message: 'alert(1)', type: 'received' }); +} + +// Outgoing/system messages are not altered by the incoming-message gate. +{ + const manager = createManager(); + EnhancedSecureWebRTCManager.prototype.deliverMessageToUI.call(manager, 'system', 'system'); + assert.deepEqual(manager.delivered[0], { message: 'system', type: 'system' }); +} + +console.log('Incoming message sanitization tests passed'); diff --git a/tests/indexeddb-metadata-encryption.test.mjs b/tests/indexeddb-metadata-encryption.test.mjs new file mode 100644 index 0000000..fa85c52 --- /dev/null +++ b/tests/indexeddb-metadata-encryption.test.mjs @@ -0,0 +1,112 @@ +import assert from 'node:assert/strict'; + +globalThis.window = { EnhancedSecureCryptoUtils: {} }; +const { SecureIndexedDBWrapper, SecurePersistentKeyStorage } = await import('../src/network/EnhancedSecureWebRTCManager.js'); + +class FakeMasterKeyManager { + isUnlocked() { return true; } + async unlock() {} + async encryptBytes(bytes) { + return { encryptedData: Uint8Array.from(bytes, byte => byte ^ 0xaa), iv: new Uint8Array(12).fill(7) }; + } + async decryptBytes(bytes, iv) { + if (!iv || iv[0] !== 7) throw new Error('bad iv'); + return Uint8Array.from(bytes, byte => byte ^ 0xaa); + } +} + +class FakeDB { + constructor(records = []) { + this.records = new Map(records.map(record => [record.keyId, record])); + } + async initialize() {} + async listKeys() { return [...this.records.values()]; } + async getKeyMetadataRecord(keyId) { return this.records.get(keyId) || null; } + async putKeyMetadataRecord(record) { this.records.set(record.keyId, record); } +} + +class FakeIndexedDBConnection { + constructor() { + this.records = new Map(); + } + transaction(storeNames) { + const transaction = { + objectStore: (name) => ({ + put: (record) => { + this.records.set(name, record); + queueMicrotask(() => transaction.oncomplete?.()); + return {}; + } + }), + oncomplete: null, + onerror: null + }; + return transaction; + } +} + +// New metadata is encrypted and sensitive fields are not plaintext. +{ + const db = new FakeDB(); + const storage = new SecurePersistentKeyStorage(new FakeMasterKeyManager(), db); + const encrypted = await storage._encryptMetadata({ + created: 111, + lastAccessed: 222, + sessionId: 'session-secret', + peerId: 'peer-secret' + }); + await db.putKeyMetadataRecord({ keyId: 'k1', ...encrypted }); + const raw = db.records.get('k1'); + assert.equal(raw.created, undefined); + assert.equal(raw.lastAccessed, undefined); + assert.equal(raw.sessionId, undefined); + assert.ok(Array.isArray(raw.encryptedMetadata)); +} + +// Old plaintext metadata can be read and is migrated. +{ + const db = new FakeDB([{ keyId: 'legacy', created: 1, lastAccessed: 2, sessionId: 'old-session' }]); + const storage = new SecurePersistentKeyStorage(new FakeMasterKeyManager(), db); + const listed = await storage.listStoredKeys(); + assert.equal(listed[0].sessionId, 'old-session'); + const migrated = db.records.get('legacy'); + assert.equal(migrated.sessionId, undefined); + assert.ok(migrated.encryptedMetadata); +} + +// Corrupted encrypted metadata fails safely and is not exposed. +{ + const db = new FakeDB([{ keyId: 'bad', encryptedMetadata: [1, 2, 3], metadataIv: [0] }]); + const storage = new SecurePersistentKeyStorage(new FakeMasterKeyManager(), db); + const listed = await storage.listStoredKeys(); + assert.deepEqual(listed, []); +} + +// Plaintext timestamp fields are avoidable in the encrypted envelope. +{ + const storage = new SecurePersistentKeyStorage(new FakeMasterKeyManager(), new FakeDB()); + const encrypted = await storage._encryptMetadata({ created: 10, lastAccessed: 20, usageCount: 3 }); + assert.equal('created' in encrypted, false); + assert.equal('lastAccessed' in encrypted, false); + assert.equal('usageCount' in encrypted, false); +} + +// Avoidable timestamps are not left plaintext in new IndexedDB records. +{ + const wrapper = new SecureIndexedDBWrapper(); + wrapper.db = new FakeIndexedDBConnection(); + await wrapper.storeEncryptedKey( + 'k2', + new Uint8Array([1]), + new Uint8Array([2]), + { name: 'AES-GCM' }, + ['encrypt'], + 'secret', + { metadataVersion: 1, encryptedMetadata: [3], metadataIv: [4] } + ); + assert.equal('timestamp' in wrapper.db.records.get(wrapper.KEYS_STORE), false); + assert.equal('created' in wrapper.db.records.get(wrapper.METADATA_STORE), false); + assert.equal('lastAccessed' in wrapper.db.records.get(wrapper.METADATA_STORE), false); +} + +console.log('IndexedDB metadata encryption tests passed'); diff --git a/tests/sas-verification.test.mjs b/tests/sas-verification.test.mjs new file mode 100644 index 0000000..c3d8546 --- /dev/null +++ b/tests/sas-verification.test.mjs @@ -0,0 +1,87 @@ +import assert from 'node:assert/strict'; + +let compareCalls = 0; +globalThis.window = { + EnhancedSecureCryptoUtils: { + constantTimeCompare(a, b) { + compareCalls += 1; + return a === b; + } + } +}; + +const { EnhancedSecureWebRTCManager } = await import('../src/network/EnhancedSecureWebRTCManager.js'); + +function createFakeManager() { + const sent = []; + return { + sent, + verificationCode: 'A1-B2-C3', + sasValidationAttempts: 0, + localVerificationConfirmed: false, + remoteVerificationConfirmed: false, + bothVerificationsConfirmed: false, + disconnected: false, + _validateSASCode: EnhancedSecureWebRTCManager.prototype._validateSASCode, + _secureLog() {}, + deliverMessageToUI() {}, + disconnect() { + this.disconnected = true; + }, + dataChannel: { + send(payload) { + sent.push(JSON.parse(payload)); + } + }, + _checkBothVerificationsConfirmed() {}, + processMessageQueue() {} + }; +} + +// testSASNormalization +{ + const manager = createFakeManager(); + assert.equal(EnhancedSecureWebRTCManager.prototype._validateSASCode.call(manager, 'a1 b2 c3'), true); + assert.equal(EnhancedSecureWebRTCManager.prototype._validateSASCode.call(manager, 'A1B2C3'), true); +} + +// testConstantTimeCompare +{ + const manager = createFakeManager(); + compareCalls = 0; + assert.equal(EnhancedSecureWebRTCManager.prototype._validateSASCode.call(manager, 'A1-B2-C3'), true); + assert.equal(compareCalls, 1); +} + +// testInvalidInputs +{ + const manager = createFakeManager(); + assert.equal(EnhancedSecureWebRTCManager.prototype._validateSASCode.call(manager, null), false); + assert.equal(EnhancedSecureWebRTCManager.prototype._validateSASCode.call(manager, 'A1B2'), false); + assert.equal(EnhancedSecureWebRTCManager.prototype._validateSASCode.call(manager, 'FFFFFF'), false); +} + +// three failed attempts disconnect; a correct attempt signals only after validation +{ + const manager = createFakeManager(); + for (let i = 0; i < 2; i += 1) { + assert.throws( + () => EnhancedSecureWebRTCManager.prototype.confirmVerification.call(manager, 'FFFFFF'), + /SAS_MISMATCH/ + ); + } + assert.equal(manager.disconnected, false); + assert.throws( + () => EnhancedSecureWebRTCManager.prototype.confirmVerification.call(manager, 'FFFFFF'), + /SAS_MAX_ATTEMPTS/ + ); + assert.equal(manager.disconnected, true); + + const validManager = createFakeManager(); + EnhancedSecureWebRTCManager.prototype.confirmVerification.call(validManager, 'a1 b2 c3'); + assert.equal(validManager.localVerificationConfirmed, true); + assert.equal(validManager.sent[0].type, 'verification_confirmed'); + assert.equal(validManager.sent[0].data.verificationMethod, 'MANUAL_SAS_ENTRY'); +} + +console.log('SAS verification tests passed'); diff --git a/tests/timer-lifecycle.test.mjs b/tests/timer-lifecycle.test.mjs new file mode 100644 index 0000000..3d8f9ed --- /dev/null +++ b/tests/timer-lifecycle.test.mjs @@ -0,0 +1,124 @@ +import assert from 'node:assert/strict'; + +globalThis.window = { + EnhancedSecureCryptoUtils: { + secureLog: { log() {} } + } +}; +globalThis.CustomEvent = class CustomEvent { + constructor(type, init) { + this.type = type; + this.detail = init?.detail; + } +}; +globalThis.document = { dispatchEvent() {} }; + +const { EnhancedSecureWebRTCManager } = await import('../src/network/EnhancedSecureWebRTCManager.js'); + +const realSetTimeout = globalThis.setTimeout; +const realClearTimeout = globalThis.clearTimeout; +const realSetInterval = globalThis.setInterval; +const realClearInterval = globalThis.clearInterval; + +const timers = []; +globalThis.setTimeout = (callback, delay) => { + const timer = { kind: 'timeout', callback, delay, cleared: false }; + timers.push(timer); + return timer; +}; +globalThis.clearTimeout = (timer) => { + if (timer) timer.cleared = true; +}; +globalThis.setInterval = (callback, delay) => { + const timer = { kind: 'interval', callback, delay, cleared: false }; + timers.push(timer); + return timer; +}; +globalThis.clearInterval = (timer) => { + if (timer) timer.cleared = true; +}; + +try { + // Periodic log cleanup is tracked and cleared with the existing timer system. + { + const manager = { + _activeTimers: new Set(), + _startKeySecurityMonitoring() {}, + _verifyAPIIntegrity() { return true; }, + _startSecurityMonitoring() {}, + _cleanupLogs() {}, + _secureLog() {} + }; + manager._trackActiveTimer = EnhancedSecureWebRTCManager.prototype._trackActiveTimer; + EnhancedSecureWebRTCManager.prototype._finalizeSecureInitialization.call(manager); + assert.equal(manager._activeTimers.size, 1); + const logTimer = manager._logCleanupInterval; + EnhancedSecureWebRTCManager.prototype._stopAllTimers.call(manager); + assert.equal(logTimer.cleared, true); + } + + // Deferred file-transfer retries are tracked, cleared, and cannot re-run after session shutdown. + { + let initCalls = 0; + const manager = { + _sessionAlive: true, + _activeTimers: new Set(), + _fileTransferInitRetryTimers: new Set(), + fileTransferSystem: null, + dataChannel: { readyState: 'open' }, + isVerified: false, + _secureLog() {}, + _trackActiveTimer: EnhancedSecureWebRTCManager.prototype._trackActiveTimer, + _untrackActiveTimer: EnhancedSecureWebRTCManager.prototype._untrackActiveTimer, + _scheduleFileTransferInitRetry: EnhancedSecureWebRTCManager.prototype._scheduleFileTransferInitRetry, + initializeFileTransfer() { + initCalls += 1; + } + }; + EnhancedSecureWebRTCManager.prototype.initializeFileTransfer.call(manager); + const retryTimer = [...manager._fileTransferInitRetryTimers][0]; + manager._sessionAlive = false; + EnhancedSecureWebRTCManager.prototype._stopAllTimers.call(manager); + if (!retryTimer.cleared) retryTimer.callback(); + assert.equal(retryTimer.cleared, true); + assert.equal(manager._fileTransferInitRetryTimers.size, 0); + assert.equal(initCalls, 0); + } + + // Repeated peer-disconnect notifications schedule only one delayed cleanup, and cleanup is cancelled on disconnect. + { + let disconnectCalls = 0; + const manager = { + _sessionAlive: true, + _activeTimers: new Set(), + peerDisconnectNotificationSent: false, + _peerDisconnectCleanupTimer: null, + deliverMessageToUI() {}, + onStatusChange() {}, + stopHeartbeat() {}, + onKeyExchange() {}, + onVerificationRequired() {}, + disconnect() { disconnectCalls += 1; }, + _secureLog() {}, + _trackActiveTimer: EnhancedSecureWebRTCManager.prototype._trackActiveTimer, + _untrackActiveTimer: EnhancedSecureWebRTCManager.prototype._untrackActiveTimer + }; + EnhancedSecureWebRTCManager.prototype.handlePeerDisconnectNotification.call(manager, { reason: 'connection_lost' }); + EnhancedSecureWebRTCManager.prototype.handlePeerDisconnectNotification.call(manager, { reason: 'connection_lost' }); + const scheduled = timers.filter(timer => timer.kind === 'timeout' && timer.delay === 2000); + assert.equal(scheduled.length, 1); + + manager._sessionAlive = false; + EnhancedSecureWebRTCManager.prototype._stopAllTimers.call(manager); + if (!scheduled[0].cleared) scheduled[0].callback(); + assert.equal(scheduled[0].cleared, true); + assert.equal(disconnectCalls, 0); + } +} finally { + globalThis.setTimeout = realSetTimeout; + globalThis.clearTimeout = realClearTimeout; + globalThis.setInterval = realSetInterval; + globalThis.clearInterval = realClearInterval; +} + +console.log('Timer lifecycle tests passed'); diff --git a/tests/webrtc-privacy-mode.test.mjs b/tests/webrtc-privacy-mode.test.mjs new file mode 100644 index 0000000..2147802 --- /dev/null +++ b/tests/webrtc-privacy-mode.test.mjs @@ -0,0 +1,60 @@ +import assert from 'node:assert/strict'; + +globalThis.window = { + EnhancedSecureCryptoUtils: {}, + DEBUG_MODE: true, + DEVELOPMENT_MODE: true, + location: { hostname: 'localhost', search: '?debug' }, + webpackHotUpdate: {} +}; + +const { EnhancedSecureWebRTCManager } = await import('../src/network/EnhancedSecureWebRTCManager.js'); + +function fake(config = {}) { + return { + _config: { + webrtc: { + relayOnly: config.relayOnly ?? false, + iceServers: config.iceServers ?? [{ urls: 'stun:stun.example.test:3478' }] + } + }, + _ipLeakWarningShown: false, + delivered: [], + deliverMessageToUI(message, type) { + this.delivered.push({ message, type }); + }, + _hasTurnServer: EnhancedSecureWebRTCManager.prototype._hasTurnServer + }; +} + +// Default mode preserves current behavior. +{ + const manager = fake(); + const config = EnhancedSecureWebRTCManager.prototype._buildPeerConnectionConfig.call(manager); + assert.equal(config.iceTransportPolicy, undefined); + assert.equal(config.iceServers[0].urls, 'stun:stun.example.test:3478'); +} + +// Privacy mode uses relay-only transport. +{ + const manager = fake({ relayOnly: true, iceServers: [{ urls: 'turn:turn.example.test:3478' }] }); + const config = EnhancedSecureWebRTCManager.prototype._buildPeerConnectionConfig.call(manager); + assert.equal(config.iceTransportPolicy, 'relay'); +} + +// Missing TURN warns clearly. +{ + const manager = fake(); + EnhancedSecureWebRTCManager.prototype._warnIfTurnMissing.call(manager); + assert.match(manager.delivered[0].message, /may expose IP addresses/i); +} + +// STUN-only config does not claim IP protection, even with privacy mode selected. +{ + const manager = fake({ relayOnly: true, iceServers: [{ urls: 'stun:stun.example.test:3478' }] }); + assert.equal(EnhancedSecureWebRTCManager.prototype._hasTurnServer.call(manager), false); + EnhancedSecureWebRTCManager.prototype._warnIfTurnMissing.call(manager); + assert.match(manager.delivered[0].message, /STUN alone does not hide IP addresses/i); +} + +console.log('WebRTC privacy mode tests passed');