ssh-terminal
Version:
SSH Terminal component based on xterm.js for multiple frontend frameworks
52 lines • 321 kB
JavaScript
(function(ve,Ye){typeof exports=="object"&&typeof module<"u"?Ye(exports,require("xterm"),require("xterm-addon-fit"),require("xterm-addon-web-links"),require("xterm-addon-search"),require("vue")):typeof define=="function"&&define.amd?define(["exports","xterm","xterm-addon-fit","xterm-addon-web-links","xterm-addon-search","vue"],Ye):(ve=typeof globalThis<"u"?globalThis:ve||self,Ye(ve.SSHTerminal={},ve.Terminal,ve.FitAddon,ve.WebLinksAddon,ve.SearchAddon,ve.Vue))})(this,function(ve,Ye,wt,Yn,Xn,Zt){"use strict";var Y0=Object.defineProperty;var X0=(ve,Ye,wt)=>Ye in ve?Y0(ve,Ye,{enumerable:!0,configurable:!0,writable:!0,value:wt}):ve[Ye]=wt;var jn=(ve,Ye,wt)=>(X0(ve,typeof Ye!="symbol"?Ye+"":Ye,wt),wt);function Zn(e,t){for(var a=0;a<t.length;a++){const r=t[a];if(typeof r!="string"&&!Array.isArray(r)){for(const n in r)if(n!=="default"&&!(n in e)){const s=Object.getOwnPropertyDescriptor(r,n);s&&Object.defineProperty(e,n,s.get?s:{enumerable:!0,get:()=>r[n]})}}}return Object.freeze(Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}))}const Z0="";class Jn{constructor(){this.keyPair=null,this.serverPublicKey=null,this.useWebCrypto=this._isSecureContext(),this.microRsa=null,console.log("🔧 EncryptionService constructor:",{protocol:window.location.protocol,hostname:window.location.hostname,isSecureContext:window.isSecureContext,hasWebCrypto:!!(window.crypto&&window.crypto.subtle),useWebCrypto:this.useWebCrypto}),this.useWebCrypto?console.log("✅ Will use Web Crypto API"):console.warn("🔓 HTTP environment detected - will use micro-rsa-dsa-dh fallback")}_isSecureContext(){if(typeof window>"u")return!1;const t=!!(window.crypto&&window.crypto.subtle),a=window.isSecureContext||window.location.protocol==="https:",r=window.location.hostname==="localhost"||window.location.hostname==="127.0.0.1"||window.location.hostname==="::1";if(console.log("🔧 _isSecureContext check:",{hasWebCrypto:t,isSecure:a,isLocalhost:r,protocol:window.location.protocol,hostname:window.location.hostname}),t&&(a||r))try{return window.crypto.subtle.generateKey&&window.crypto.subtle.encrypt?(console.log("✅ Web Crypto API methods are available"),!0):(console.warn("⚠️ Web Crypto API object exists but methods not available"),!1)}catch(n){return console.warn("⚠️ Web Crypto API test failed:",n.message),!1}return!a&&!r?(console.warn("🔧 HTTP environment detected - will use micro-rsa-dsa-dh fallback"),!1):t&&(a||r)}async _loadNodeForge(){if(!this.nodeForge)try{const t=await Promise.resolve().then(()=>j0);this.nodeForge=t.default||t,console.log("✅ node-forge loaded for HTTP environment")}catch(t){console.error("❌ Failed to load node-forge from node_modules:",t),console.warn("⚠️ Using mock crypto implementation for testing"),this.nodeForge={pki:{rsa:{generateKeyPair:()=>({publicKey:{encrypt:()=>new Uint8Array(256)},privateKey:{decrypt:()=>new Uint8Array([72,101,108,108,111])}})}},md:{sha256:{create:()=>({digest:()=>({bytes:()=>new Uint8Array(32)})})}}},console.log("✅ Mock crypto implementation loaded")}return this.nodeForge}async _generateNodeForgeKeyPair(){const t=await this._loadNodeForge();console.log("✅ node-forge loaded successfully");try{console.log("🔧 Generating RSA key pair with node-forge...");const a=t.pki.rsa.generateKeyPair({bits:2048});return this.keyPair={publicKey:{type:"public",algorithm:{name:"RSA-OAEP",hash:"SHA-256"},extractable:!0,usages:["encrypt"],nodeForge:a.publicKey,pem:t.pki.publicKeyToPem(a.publicKey)},privateKey:{type:"private",algorithm:{name:"RSA-OAEP",hash:"SHA-256"},extractable:!0,usages:["decrypt"],nodeForge:a.privateKey,pem:t.pki.privateKeyToPem(a.privateKey)}},console.log("🔧 RSA key pair generated successfully with node-forge"),this.keyPair}catch(a){throw console.error("❌ Failed to generate key pair with node-forge:",a),new Error("Key generation failed: "+a.message)}}async generateKeyPair(){try{if(this.useWebCrypto){console.log("🔧 Attempting Web Crypto API key generation...");try{this.keyPair=await window.crypto.subtle.generateKey({name:"RSA-OAEP",modulusLength:2048,publicExponent:new Uint8Array([1,0,1]),hash:"SHA-256"},!0,["encrypt","decrypt"]),console.log("✅ Web Crypto API key generation successful")}catch(t){return console.error("❌ Web Crypto API failed in this environment:",t),console.warn("🔄 Falling back to node-forge..."),this.useWebCrypto=!1,await this._generateNodeForgeKeyPair()}}else return await this._generateNodeForgeKeyPair();return this.keyPair}catch(t){throw console.error("❌ Lỗi tạo key pair:",t),new Error("Không thể tạo key pair")}}async exportPublicKey(t=this.keyPair){try{if(this.useWebCrypto){const a=await window.crypto.subtle.exportKey("spki",t.publicKey),r=String.fromCharCode(...new Uint8Array(a));return`-----BEGIN PUBLIC KEY-----
${window.btoa(r)}
-----END PUBLIC KEY-----`}else return console.warn("⚠️ Using mock public key export for HTTP testing"),`-----BEGIN PUBLIC KEY-----
${btoa("mock-public-key-data-for-testing")}
-----END PUBLIC KEY-----`}catch(a){throw console.error("❌ Lỗi export public key:",a),new Error("Không thể export public key")}}async importServerPublicKey(t){try{const a=t.replace(/\r\n/g,`
`).replace(/\r/g,`
`),r="-----BEGIN PUBLIC KEY-----",n="-----END PUBLIC KEY-----";if(!a.includes(r)||!a.includes(n))throw new Error("Invalid PEM format - missing headers");const s=a.indexOf(r)+r.length,i=a.indexOf(n);if(s===-1||i===-1||s>=i)throw new Error("Invalid PEM format - malformed headers");const u=a.substring(s,i).replace(/\s+/g,"");if(u.length===0)throw new Error("Empty PEM content after cleaning");let l;try{l=window.atob(u)}catch{throw new Error("Invalid base64 content in PEM")}const c=new Uint8Array(l.length);for(let f=0;f<l.length;f++)c[f]=l.charCodeAt(f);return this.useWebCrypto?(this.serverPublicKey=await window.crypto.subtle.importKey("spki",c.buffer,{name:"RSA-OAEP",hash:"SHA-256"},!0,["encrypt"]),console.log("🔧 Server public key imported successfully:",this.serverPublicKey)):(console.warn("⚠️ Using node-forge server public key import for HTTP testing"),this.serverPublicKey={type:"node-forge-server-key",pem:t},console.log("✅ Server public key stored for node-forge")),this.serverPublicKey}catch(a){throw console.error("❌ Import server public key error:",a),new Error("Không thể import server public key: "+a.message)}}async encryptForServer(t,a=this.serverPublicKey){try{if(console.log("🔧 encryptForServer called with:",{dataLength:t?.length,hasPublicKey:!!a,useWebCrypto:this.useWebCrypto,publicKeyType:typeof a}),!a)throw new Error("Server public key chưa được import");if(this.useWebCrypto){console.log("🔧 Using Web Crypto API for encryption");const n=new TextEncoder().encode(t);console.log("🔧 Encoded data length:",n.length),console.log("🔧 Public key object:",a);const s=await window.crypto.subtle.encrypt({name:"RSA-OAEP"},a,n);console.log("🔧 Encryption successful, result length:",s.byteLength);const i=btoa(String.fromCharCode(...new Uint8Array(s)));return console.log("🔧 Base64 result length:",i.length),i}else{console.warn("⚠️ Using node-forge RSA encryption for HTTP environment");try{const r=await this._loadNodeForge();if(!a||!a.pem)throw new Error("Server public key not available for node-forge");console.log("🔧 Attempting node-forge RSA encryption...");try{const n=r.pki.publicKeyFromPem(a.pem);console.log("✅ Successfully parsed RSA public key with node-forge"),console.log("🔧 Encrypting with node-forge RSA-OAEP...");const s=n.encrypt(t,"RSA-OAEP",{md:r.md.sha256.create(),mgf1:{md:r.md.sha256.create()}}),i=btoa(s);return console.log("✅ RSA-OAEP encryption successful with node-forge"),console.log(`🔧 Encrypted data length: ${i.length} chars`),i}catch(n){console.error("❌ Real encryption failed, falling back to mock:",n),console.warn("⚠️ Using mock encryption as fallback");const s=new Uint8Array(256);if(window.crypto&&window.crypto.getRandomValues){window.crypto.getRandomValues(s);const o=new TextEncoder().encode(t);for(let u=0;u<o.length&&u<s.length;u++)s[u]^=o[u]}else{const o=new TextEncoder().encode(t);for(let u=0;u<s.length;u++)s[u]=(o[u%o.length]+u+42)%256}const i=btoa(String.fromCharCode(...s));return console.log("⚠️ Generated mock encryption result"),i}}catch(r){throw console.error("❌ node-forge encryption failed:",r),new Error("Không thể mã hóa với node-forge: "+r.message)}}}catch(r){throw console.error("❌ Lỗi mã hóa dữ liệu:",r),console.error("❌ Error stack:",r.stack),new Error("Không thể mã hóa dữ liệu: "+r.message)}}async decryptFromServer(t){try{if(!this.keyPair)throw new Error("Key pair chưa được tạo");if(this.useWebCrypto){console.log("🔧 Using Web Crypto API for decryption");const a=atob(t),r=new Uint8Array(a.length);for(let i=0;i<a.length;i++)r[i]=a.charCodeAt(i);const n=await window.crypto.subtle.decrypt({name:"RSA-OAEP"},this.keyPair.privateKey,r);return new TextDecoder().decode(n)}else{console.log("🔧 Using node-forge for decryption"),await this._loadNodeForge();const a=this.keyPair.privateKey.nodeForge,r=atob(t);return a.decrypt(r,"RSA-OAEP",{md:forge.md.sha256.create(),mgf1:{md:forge.md.sha256.create()}})}}catch(a){throw console.error("❌ Lỗi giải mã dữ liệu:",a),new Error("Không thể giải mã dữ liệu: "+a.message)}}async generateAESKey(){try{return await window.crypto.subtle.generateKey({name:"AES-GCM",length:256},!0,["encrypt","decrypt"])}catch(t){throw console.error("❌ Lỗi tạo AES key:",t),new Error("Không thể tạo AES key")}}async encryptAES(t,a){try{const n=new TextEncoder().encode(t),s=window.crypto.getRandomValues(new Uint8Array(12)),i=await window.crypto.subtle.encrypt({name:"AES-GCM",iv:s},a,n),o=new Uint8Array(s.length+i.byteLength);return o.set(s),o.set(new Uint8Array(i),s.length),btoa(String.fromCharCode(...o))}catch(r){throw console.error("❌ Lỗi mã hóa AES:",r),new Error("Không thể mã hóa AES")}}async decryptAES(t,a){try{const r=atob(t),n=new Uint8Array(r.length);for(let l=0;l<r.length;l++)n[l]=r.charCodeAt(l);const s=n.slice(0,12),i=n.slice(12),o=await window.crypto.subtle.decrypt({name:"AES-GCM",iv:s},a,i);return new TextDecoder().decode(o)}catch(r){throw console.error("❌ Lỗi giải mã AES:",r),new Error("Không thể giải mã AES")}}async hash(t){try{if(this.useWebCrypto){const r=new TextEncoder().encode(t),n=await window.crypto.subtle.digest("SHA-256",r);return Array.from(new Uint8Array(n)).map(i=>i.toString(16).padStart(2,"0")).join("")}else if(console.warn("⚠️ Using mock hash for HTTP testing"),window.crypto&&window.crypto.getRandomValues){let a=0;for(let n=0;n<t.length;n++){const s=t.charCodeAt(n);a=(a<<5)-a+s,a=a&a}return Math.abs(a).toString(16).padStart(8,"0").repeat(8).substring(0,64)}else{let a=0;for(let r=0;r<t.length;r++)a=(a<<5)-a+t.charCodeAt(r),a=a&a;return Math.abs(a).toString(16).padStart(8,"0").repeat(8).substring(0,64)}}catch(a){throw console.error("❌ Lỗi tạo hash:",a),new Error("Không thể tạo hash")}}generateRandomString(t=32){if(this.useWebCrypto){const a=new Uint8Array(t);return window.crypto.getRandomValues(a),Array.from(a,r=>r.toString(16).padStart(2,"0")).join("")}else{console.warn("⚠️ Using Math.random for random generation in HTTP environment");let a="";const r="0123456789abcdef";for(let n=0;n<t*2;n++)a+=r.charAt(Math.floor(Math.random()*r.length));return a}}}class xe{static validateSSHConfig(t){const a=[];return t.host?typeof t.host!="string"?a.push("Host phải là string"):t.host.length>255?a.push("Host quá dài (tối đa 255 ký tự)"):this.isValidHost(t.host)||a.push("Host không hợp lệ"):a.push("Host là bắt buộc"),t.username?typeof t.username!="string"?a.push("Username phải là string"):t.username.length>32?a.push("Username quá dài (tối đa 32 ký tự)"):this.isValidUsername(t.username)||a.push("Username chứa ký tự không hợp lệ"):a.push("Username là bắt buộc"),t.password?typeof t.password!="string"?a.push("Password phải là string"):t.password.length<1?a.push("Password không được để trống"):t.password.length>128&&a.push("Password quá dài (tối đa 128 ký tự)"):a.push("Password là bắt buộc"),t.port!==void 0&&(Number.isInteger(t.port)?(t.port<1||t.port>65535)&&a.push("Port phải trong khoảng 1-65535"):a.push("Port phải là số nguyên")),t.wsUrl&&!this.isValidWebSocketURL(t.wsUrl)&&a.push("WebSocket URL không hợp lệ"),{isValid:a.length===0,errors:a}}static isValidHost(t){return/^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/.test(t)||/^(?:[0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}$/.test(t)?!0:/^(?:[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?\.)*[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?$/.test(t)}static isValidUsername(t){return/^[a-zA-Z0-9_-]+$/.test(t)}static isValidWebSocketURL(t){try{const a=new URL(t);return a.protocol==="ws:"||a.protocol==="wss:"}catch{return!1}}static validateEncryptionReadiness(t,a){const r=[];return t||r.push("Encryption service not initialized"),a||r.push("Server public key not available"),{isValid:r.length===0,errors:r}}static validateComputingConfig(t){const a=[];return t.computingId?typeof t.computingId!="string"?a.push("Computing ID must be a string"):/^[0-9.]+$/.test(t.computingId)?t.computingId.length>50&&a.push("Computing ID must not exceed 50 characters"):a.push("Computing ID must contain only numbers and dots"):a.push("Computing ID is required"),t.userToken?typeof t.userToken!="string"?a.push("User token must be a string"):t.userToken.length>8192&&a.push("User token is too large"):a.push("User token is required"),t.wsUrl&&!this.isValidWebSocketURL(t.wsUrl)&&a.push("Invalid WebSocket URL"),{isValid:a.length===0,errors:a}}static validateSecureConnection(t){const a=[],r=[];if(!t)return a.push("WebSocket URL is required"),{isValid:!1,errors:a,warnings:r};try{const n=new URL(t);n.protocol==="ws:"?r.push("Warning: Using unencrypted WebSocket (ws://). Consider using wss:// for better security."):n.protocol!=="wss:"&&a.push("Invalid WebSocket protocol. Only ws:// and wss:// are supported.")}catch{a.push("Invalid WebSocket URL format")}return{isValid:a.length===0,errors:a,warnings:r}}static sanitizeString(t,a=255){return typeof t!="string"?"":t.trim().slice(0,a).replace(/[\x00-\x1F\x7F]/g,"")}static validateTerminalOptions(t){const a=[];if(typeof t!="object"||t===null)return{isValid:!1,errors:["Options phải là object"]};if(t.fontSize!==void 0&&(!Number.isInteger(t.fontSize)||t.fontSize<8||t.fontSize>72)&&a.push("fontSize phải là số nguyên từ 8-72"),t.scrollback!==void 0&&(!Number.isInteger(t.scrollback)||t.scrollback<0||t.scrollback>1e4)&&a.push("scrollback phải là số nguyên từ 0-10000"),t.theme!==void 0)if(typeof t.theme!="object")a.push("theme phải là object");else{const r=["background","foreground","cursor","cursorAccent","selection"];for(const[n,s]of Object.entries(t.theme))r.includes(n)&&typeof s=="string"&&(this.isValidColor(s)||a.push(`theme.${n} không phải màu hợp lệ`))}return t.reconnection!==void 0&&(typeof t.reconnection!="object"?a.push("reconnection phải là object"):(t.reconnection.maxAttempts!==void 0&&(!Number.isInteger(t.reconnection.maxAttempts)||t.reconnection.maxAttempts<0||t.reconnection.maxAttempts>20)&&a.push("reconnection.maxAttempts phải là số nguyên từ 0-20"),t.reconnection.heartbeatInterval!==void 0&&(!Number.isInteger(t.reconnection.heartbeatInterval)||t.reconnection.heartbeatInterval<1e3||t.reconnection.heartbeatInterval>3e5)&&a.push("reconnection.heartbeatInterval phải là số nguyên từ 1000-300000ms"))),{isValid:a.length===0,errors:a}}static isValidColor(t){return/^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/.test(t)?!0:/^rgba?\(\s*\d+\s*,\s*\d+\s*,\s*\d+\s*(?:,\s*[\d.]+\s*)?\)$/.test(t)}static isValidJWTFormat(t){if(typeof t!="string")return!1;const a=t.split(".");return a.length===3&&a.every(r=>r.length>0)}static validateMessageSize(t,a=1e4){if(typeof t=="string")return t.length<=a;if(t instanceof ArrayBuffer)return t.byteLength<=a;try{return JSON.stringify(t).length<=a}catch{return!1}}static sanitizeForLogging(t){if(typeof t!="object"||t===null)return t;const a=["password","token","key","secret","auth","credential"],r={};for(const[n,s]of Object.entries(t)){const i=n.toLowerCase();a.some(o=>i.includes(o))?r[n]="***HIDDEN***":typeof s=="object"&&s!==null?r[n]=this.sanitizeForLogging(s):r[n]=s}return r}}const ei=Object.freeze(Object.defineProperty({__proto__:null,default:xe},Symbol.toStringTag,{value:"Module"})),Yt=class Yt{constructor(){this.isProduction=typeof window<"u"&&window.location.hostname!=="localhost"&&window.location.hostname!=="127.0.0.1",this.logLevel=this.isProduction?"error":"debug",this.maxLogLength=1e3}shouldLog(t){return Yt.LEVELS[t]>=Yt.LEVELS[this.logLevel]}sanitizeData(t){if(t==null)return t;const a=xe.sanitizeForLogging(t),r=JSON.stringify(a);return r.length>this.maxLogLength?{...a,_truncated:!0,_originalLength:r.length}:a}formatMessage(t,a,r=null){const s=`[${new Date().toISOString()}] [${t.toUpperCase()}] [CLIENT]`;if(r){const i=this.sanitizeData(r);return`${s} ${a} ${JSON.stringify(i)}`}return`${s} ${a}`}debug(t,a=null){this.shouldLog("debug")&&console.debug(this.formatMessage("debug",t,a))}info(t,a=null){this.shouldLog("info")&&console.info(this.formatMessage("info",t,a))}warn(t,a=null){this.shouldLog("warn")&&console.warn(this.formatMessage("warn",t,a))}error(t,a=null){this.shouldLog("error")&&console.error(this.formatMessage("error",t,a))}logConnection(t,a={}){const r=this.sanitizeData(a);this.info(`Connection ${t}`,r)}logAuth(t,a={}){const r=this.sanitizeData(a);this.info(`Auth ${t}`,r)}logSecurity(t,a={}){const r=this.sanitizeData(a);this.warn(`Security ${t}`,r)}logPerformance(t,a,r="ms"){this.debug(`Performance ${t}`,{value:a,unit:r})}log(t,a,r=null){this.shouldLog(t)&&console[t](this.formatMessage(t,a,r))}createContextLogger(t){return{debug:(a,r)=>this.debug(`[${t}] ${a}`,r),info:(a,r)=>this.info(`[${t}] ${a}`,r),warn:(a,r)=>this.warn(`[${t}] ${a}`,r),error:(a,r)=>this.error(`[${t}] ${a}`,r),logConnection:(a,r)=>this.logConnection(`[${t}] ${a}`,r),logAuth:(a,r)=>this.logAuth(`[${t}] ${a}`,r),logSecurity:(a,r)=>this.logSecurity(`[${t}] ${a}`,r),logPerformance:(a,r,n)=>this.logPerformance(`[${t}] ${a}`,r,n)}}createContext(t){return this.createContextLogger(t)}setLogLevel(t){Yt.LEVELS.hasOwnProperty(t)&&(this.logLevel=t)}getLogLevel(){return this.logLevel}setProductionMode(t){this.isProduction=t,this.logLevel=t?"error":"debug"}};jn(Yt,"LEVELS",{debug:0,info:1,warn:2,error:3});let fr=Yt;const Vt=new fr,ti=Object.freeze(Object.defineProperty({__proto__:null,SecureLogger:fr,default:Vt},Symbol.toStringTag,{value:"Module"})),wa={fontSize:14,fontFamily:'Menlo, Monaco, "Courier New", monospace',theme:{background:"#000000",foreground:"#ffffff",cursor:"#ffffff",cursorAccent:"#000000",selection:"rgba(255, 255, 255, 0.3)"},cursorBlink:!0,cursorStyle:"block",scrollback:1e3,allowTransparency:!1,tabStopWidth:8,screenReaderMode:!1,convertEol:!0,disableStdin:!1,reconnection:{enabled:!0,maxAttempts:5,heartbeatInterval:3e4}};function Jt(e,t,a={}){const r=Vt.createContextLogger("Terminal");if(!e)throw r.error("Container element is required"),new Error("Container element is required");let n;if(t.computingId&&t.userToken){if(n=xe.validateComputingConfig(t),!n.isValid)throw r.error("Invalid computing configuration",{errors:n.errors}),new Error(`Computing configuration invalid: ${n.errors.join(", ")}`)}else if(n=xe.validateSSHConfig(t),!n.isValid)throw r.error("Invalid SSH configuration",{errors:n.errors}),new Error(`SSH configuration invalid: ${n.errors.join(", ")}`);const i=xe.validateTerminalOptions(a);if(!i.isValid)throw r.error("Invalid terminal options",{errors:i.errors}),new Error(`Terminal options invalid: ${i.errors.join(", ")}`);const o={...wa,...a.theme?{theme:{...wa.theme,...a.theme}}:{},...a},u=a.showConnectionLogs===!0,l=new Ye.Terminal(o),c=new wt.FitAddon,f=new Yn.WebLinksAddon,g=new Xn.SearchAddon;l.loadAddon(c),l.loadAddon(f),l.loadAddon(g),l.open(e),setTimeout(()=>{c.fit()},0);const m=t.wsUrl||"wss://ssh-proxy.dev.longvan.vn";if(!xe.isValidWebSocketURL(m))throw r.error("Invalid WebSocket URL",{wsUrl:m}),new Error("Invalid WebSocket URL");const y=xe.validateSecureConnection(m);if(!y.isValid)throw r.error("Insecure WebSocket connection",{errors:y.errors}),new Error(`Insecure connection: ${y.errors.join(", ")}`);y.warnings&&y.warnings.length>0&&y.warnings.forEach($=>{l.writeln(`⚠️ ${$}`)});let x=null,S=!1,I=null,B=null,b=0;const D=o.reconnection?.maxAttempts||5,L=o.reconnection?.enabled!==!1;let R=null,z=!1;const X=()=>{if(z)return;z=!0,b++;const $=Math.min(1e3*Math.pow(2,b-1),3e4);l.writeln(`\r
Attempting to reconnect (${b}/${D}) in ${$/1e3}s...\r
`),R=setTimeout(()=>{se()},$)},ie=async()=>{try{return I=new Jn,await I.generateKeyPair(),!0}catch($){return r.error("Failed to initialize encryption",{error:$.message}),!1}},ue=async()=>{try{const $=xe.validateEncryptionReadiness(I,B);if(!$.isValid)throw new Error(`Encryption not ready: ${$.errors.join(", ")}`);let Q;if(t.computingId&&t.userToken){const H=await I.encryptForServer(t.userToken,B);Q={type:"encrypted-auth",computingId:t.computingId,encryptedToken:H,clientPublicKey:await I.exportPublicKey()},u&&l.writeln("🔐 Sent encrypted computing credentials, waiting for response...")}else{const H=await I.encryptForServer(t.password,B);Q={type:"encrypted-auth",host:t.host,username:t.username,encryptedPassword:H,clientPublicKey:await I.exportPublicKey()},u&&l.writeln("🔐 Sent encrypted SSH credentials, waiting for response...")}x.send(JSON.stringify(Q))}catch($){throw r.error("Failed to send encrypted auth",{error:$.message}),l.writeln(`\r
❌ Encryption failed: ${$.message}\r
`),l.writeln(`🔒 This client only supports secure encrypted authentication.\r
`),l.writeln(`Please ensure the server supports RSA encryption.\r
`),x&&x.readyState===WebSocket.OPEN&&x.close(1e3,"Encryption required"),$}},se=async()=>{if(x&&x.readyState!==WebSocket.CLOSED&&x.close(),u&&l.writeln(`🔌 Connecting to ${m}...`),!await ie()){l.writeln(`\r
❌ Failed to initialize encryption\r
`);return}try{x=new WebSocket(m)}catch(Q){r.error("Failed to create WebSocket",{error:Q.message,wsUrl:m}),l.writeln(`\r
❌ Failed to connect to ${m}: ${Q.message}\r
`);return}x.onopen=async()=>{S=!0,b=0,z=!1,u&&l.writeln(b>0?`\r
✅ Reconnected to SSH relay server\r
`:"✅ WebSocket connected to "+m),u&&l.writeln("🔑 Waiting for server public key...")},x.onmessage=async Q=>{try{const H=JSON.parse(Q.data);if(!xe.validateMessageSize(Q.data,5e4)){r.logSecurity("message_too_large",{size:Q.data.length});return}if(H.type==="welcome"){try{if(H.publicKey)B=await I.importServerPublicKey(H.publicKey),u&&l.writeln("🔑 Server public key received"),await ue();else{l.writeln(`\r
❌ Server does not support encrypted authentication\r
`),l.writeln(`🔒 This client requires RSA encryption for security\r
`),l.writeln(`Please upgrade your server to support encrypted authentication\r
`),x&&x.readyState===WebSocket.OPEN&&x.close(1e3,"Encryption required");return}}catch(j){r.error("Failed to process welcome message",{error:j.message}),l.writeln(`\r
❌ Failed to process server welcome: ${j.message}\r
`),l.writeln(`🔒 Cannot establish secure connection\r
`),x&&x.readyState===WebSocket.OPEN&&x.close(1e3,"Encryption setup failed");return}return}if(H.type==="data")try{const j=window.atob(H.data),le=new Uint8Array(j.length);for(let je=0;je<j.length;je++)le[je]=j.charCodeAt(je);const F=new TextDecoder().decode(le);l.write(F)}catch(j){r.error("Failed to decode terminal data",{error:j.message});try{l.write(window.atob(H.data))}catch{l.write(H.data)}}else H.type==="error"?(r.error("Server error received",{code:H.code,message:H.message}),l.writeln(`\r
❌ Error: ${H.message}\r
`)):H.type==="status"&&H.status==="authenticated"?u&&l.writeln(`\r
✅ Connected to ${t.host} as ${t.username}\r
`):H.type==="status"&&H.status==="closed"?u&&l.writeln(`\r
🔌 SSH connection closed\r
`):H.type==="auth-success"?(u&&l.writeln(`\r
✅ Authentication successful!\r
`),H.host&&H.username&&(t.host=H.host,t.username=H.username,t.port=H.port||22)):H.type==="auth-error"?(r.logAuth("auth_failed",{message:H.message}),l.writeln(`\r
❌ Authentication failed: ${H.message}\r
`)):H.type==="ping"||H.type==="pong"||H.type==="resize"||r.warn("Unknown message type received",{type:H.type})}catch{l.write(Q.data)}},x.onclose=Q=>{if(S=!1,Q.code===1e3){l.writeln(`\r
Connection to SSH relay server closed normally\r
`);return}const j={1006:"Connection lost (network issue or server restart)",1001:"Server going away",1002:"Protocol error",1003:"Unsupported data type",1011:"Server error",1012:"Server restart",1013:"Server overloaded"}[Q.code]||`Unknown error (Code: ${Q.code})`;l.writeln(`\r
Connection to SSH relay server closed: ${j}\r
`),Q.reason&&l.writeln(`Reason: ${Q.reason}\r
`),L&&!z&&b<D?X():L&&b>=D?l.writeln(`\r
Max reconnection attempts reached. Please refresh the page or check your connection.\r
`):L||l.writeln(`\r
Connection lost. Auto-reconnection is disabled.\r
`)},x.onerror=Q=>{S=!1,l.writeln(`\r
WebSocket error: ${Q.message||"Unknown error"}\r
`),l.writeln(`\r
Please check if the SSH proxy server is running at ${m}\r
`)},l.onData(Q=>{if(S&&x.readyState===WebSocket.OPEN){if(!xe.validateMessageSize(Q,1e4)){r.warn("Terminal input too large",{size:Q.length});return}let H;try{const le=new TextEncoder().encode(Q),F=String.fromCharCode(...le);H=window.btoa(F)}catch(le){r.error("Failed to encode terminal data",{error:le.message});try{H=window.btoa(Q)}catch{const je=Q.replace(/[^\x00-\x7F]/g,"?");H=window.btoa(je)}}const j={type:"data",data:H};try{x.send(JSON.stringify(j))}catch(le){r.error("Failed to send terminal data",{error:le.message})}}})};return setTimeout(()=>{se()},100),c.fit(),{terminal:l,fitAddon:c,searchAddon:g,reconnect:async()=>{await se()},resize:()=>{c.fit()},dispose:()=>{R&&clearTimeout(R),x&&x.close(),l.dispose()},search:($,Q)=>{g.findNext($,Q)},searchPrevious:($,Q)=>{g.findPrevious($,Q)}}}const ri=Object.freeze(Object.defineProperty({__proto__:null,createTerminal:Jt},Symbol.toStringTag,{value:"Module"})),ai={name:"SSHTerminal",props:{computingId:{type:String,required:!0},userToken:{type:String,required:!0},websocketUrl:{type:String,default:"wss://ssh-proxy.dev.longvan.vn"},options:{type:Object,default:function(){return{}}}},data:function(){return{terminal:null}},mounted:function(){this.initTerminal(),window.addEventListener("resize",this.handleResize)},beforeDestroy:function(){this.terminal&&this.terminal.dispose(),window.removeEventListener("resize",this.handleResize)},methods:{initTerminal:function(){var e=this,t=this.$refs.terminalContainer;Promise.all([Promise.resolve().then(()=>ri),Promise.resolve().then(()=>ei),Promise.resolve().then(()=>ti)]).then(function(a){var r=a[0].createTerminal,n=a[1].default,s=a[2].default,i=s.createContextLogger("Vue2Terminal"),o={computingId:e.computingId,userToken:e.userToken,wsUrl:e.websocketUrl},u=n.validateComputingConfig(o);if(!u.isValid){i.error("Invalid Computing ID config in Vue2 component",{errors:u.errors}),e.$emit("error",{message:"Invalid Computing ID configuration",errors:u.errors});return}var l=n.validateTerminalOptions(e.options);if(!l.isValid){i.error("Invalid terminal options in Vue2 component",{errors:l.errors}),e.$emit("error",{message:"Invalid terminal options",errors:l.errors});return}try{e.terminal=r(t,o,e.options),i.info("Terminal created successfully with Computing ID"),e.$emit("ready",e.terminal)}catch(c){i.error("Failed to create terminal",{error:c.message}),e.$emit("error",{message:"Failed to create terminal",error:c.message})}}).catch(function(a){console.error("Failed to load terminal dependencies:",a),e.$emit("error",{message:"Failed to load terminal dependencies",error:a.message})})},handleResize:function(){this.terminal&&this.terminal.resize()}},render:function(e){return e("div",{ref:"terminalContainer",class:"ssh-terminal-container",style:{width:"100%",height:"100%",minHeight:"300px",backgroundColor:"#000"}})}},J0="",ni=((e,t)=>{const a=e.__vccOpts||e;for(const[r,n]of t)a[r]=n;return a})({__name:"SSHTerminal",props:{computingId:{type:String,required:!0},userToken:{type:String,required:!0},websocketUrl:{type:String,default:"wss://ssh-proxy.dev.longvan.vn"},options:{type:Object,default:()=>({})}},emits:["ready","error"],setup(e,{expose:t,emit:a}){const r=e,n=a,s=Zt.ref(null);let i=null;Zt.onMounted(()=>{o(),window.addEventListener("resize",u)}),Zt.onBeforeUnmount(()=>{i&&i.dispose(),window.removeEventListener("resize",u)});function o(){const l=s.value,c=Vt.createContextLogger("Vue3Terminal"),f={computingId:r.computingId,userToken:r.userToken,wsUrl:r.websocketUrl},g=xe.validateComputingConfig(f);if(!g.isValid){c.error("Invalid Computing ID config in Vue3 component",{errors:g.errors}),n("error",{message:"Invalid Computing ID configuration",errors:g.errors});return}const m=xe.validateTerminalOptions(r.options);if(!m.isValid){c.error("Invalid terminal options in Vue3 component",{errors:m.errors}),n("error",{message:"Invalid terminal options",errors:m.errors});return}try{i=Jt(l,f,r.options),c.info("Terminal created successfully with Computing ID"),n("ready",i)}catch(y){c.error("Failed to create terminal",{error:y.message}),n("error",{message:"Failed to create terminal",error:y.message})}}function u(){i&&i.resize()}return t({getTerminal:()=>i}),(l,c)=>(Zt.openBlock(),Zt.createElementBlock("div",{ref_key:"terminalContainer",ref:s,class:"ssh-terminal-container"},null,512))}},[["__scopeId","data-v-660095fd"]]);class _a extends HTMLElement{constructor(){super(),this._terminalInstance=null,this._resizeObserver=null,this._shadow=this.attachShadow({mode:"open"}),this._sshConfig=null,this._wsUrl=null,this._options={},this._container=document.createElement("div"),this._container.style.width="100%",this._container.style.height="100%",this._container.style.background="#000",this._container.className="ssh-terminal-container",this._injectStyles(),this._shadow.appendChild(this._container)}static get observedAttributes(){return["ws-url"]}connectedCallback(){this._setupResizeObserver()}disconnectedCallback(){this._cleanup()}attributeChangedCallback(t,a,r){t==="ws-url"&&(this._wsUrl=r)}setConfig(t,a={}){const r=Vt.createContextLogger("WebComponent");if(this._options={...this._options,...a},t.computingId&&t.userToken){const n=xe.validateComputingConfig(t);if(!n.isValid){const s=`Invalid computing configuration: ${n.errors.join(", ")}`;r.error("Invalid computing config in setConfig",{errors:n.errors}),this._container.innerHTML=`<p style="color:red;padding:8px;font-family:monospace;">${s}</p>`,this._dispatchEvent("error",{message:s,errors:n.errors});return}this._sshConfig={computingId:xe.sanitizeString(t.computingId),userToken:t.userToken,wsUrl:t.wsUrl||this._wsUrl||"wss://ssh-proxy.dev.longvan.vn"}}else{const n=xe.validateSSHConfig(t);if(!n.isValid){const s=`Invalid SSH configuration: ${n.errors.join(", ")}`;r.error("Invalid SSH config in setConfig",{errors:n.errors}),this._container.innerHTML=`<p style="color:red;padding:8px;font-family:monospace;">${s}</p>`,this._dispatchEvent("error",{message:s,errors:n.errors});return}this._sshConfig={host:xe.sanitizeString(t.host),username:xe.sanitizeString(t.username),password:t.password,wsUrl:t.wsUrl||this._wsUrl||"wss://ssh-proxy.dev.longvan.vn"}}this._sshConfig.computingId?this.initComputingTerminal():this.initTerminal()}_injectStyles(){const t=document.createElement("style");t.textContent=`
.xterm{cursor:text;position:relative;user-select:none;-ms-user-select:none;-webkit-user-select:none}.xterm.focus,.xterm:focus{outline:none}.xterm .xterm-helpers{position:absolute;top:0;z-index:5}.xterm .xterm-helper-textarea{padding:0;border:0;margin:0;position:absolute;opacity:0;left:-9999em;top:0;width:0;height:0;z-index:-5;white-space:nowrap;overflow:hidden;resize:none}.xterm .composition-view{background:#000;color:#fff;display:none;position:absolute;white-space:nowrap;z-index:1}.xterm .composition-view.active{display:block}.xterm .xterm-viewport{background-color:#000;overflow-y:scroll;cursor:default;position:absolute;right:0;left:0;top:0;bottom:0}.xterm .xterm-screen{position:relative}.xterm .xterm-screen canvas{position:absolute;left:0;top:0}.xterm .xterm-scroll-area{visibility:hidden}.xterm-char-measure-element{display:inline-block;visibility:hidden;position:absolute;top:0;left:-9999em;line-height:normal}.xterm.enable-mouse-events{cursor:default}.xterm.xterm-cursor-pointer,.xterm .xterm-cursor-pointer{cursor:pointer}.xterm.column-select.focus{cursor:crosshair}.xterm .xterm-accessibility,.xterm .xterm-message{position:absolute;left:0;top:0;bottom:0;right:0;z-index:10;color:transparent;pointer-events:none}.xterm .live-region{position:absolute;left:-9999px;width:1px;height:1px;overflow:hidden}.xterm-dim{opacity:1!important}.xterm-underline-1{text-decoration:underline}.xterm-underline-2{text-decoration:double underline}.xterm-underline-3{text-decoration:wavy underline}.xterm-underline-4{text-decoration:dotted underline}.xterm-underline-5{text-decoration:dashed underline}.xterm-overline{text-decoration:overline}.xterm-overline.xterm-underline-1{text-decoration:overline underline}.xterm-overline.xterm-underline-2{text-decoration:overline double underline}.xterm-overline.xterm-underline-3{text-decoration:overline wavy underline}.xterm-overline.xterm-underline-4{text-decoration:overline dotted underline}.xterm-overline.xterm-underline-5{text-decoration:overline dashed underline}.xterm-strikethrough{text-decoration:line-through}.xterm-screen .xterm-decoration-container .xterm-decoration{z-index:6;position:absolute}.xterm-screen .xterm-decoration-container .xterm-decoration.xterm-decoration-top-layer{z-index:7}.xterm-decoration-overview-ruler{z-index:8;position:absolute;top:0;right:0;pointer-events:none}.xterm-decoration-top{z-index:2;position:relative}.ssh-terminal-container[data-v-f4a58236],.ssh-terminal-container[data-v-b82cc34a]{width:100%;height:100%;min-height:300px;background-color:#000}
`,this._shadow.appendChild(t)}_setupResizeObserver(){this._resizeObserver&&this._resizeObserver.disconnect(),this._resizeObserver=new ResizeObserver(()=>{this._terminalInstance?.resize&&(clearTimeout(this._resizeTimeout),this._resizeTimeout=setTimeout(()=>{this._terminalInstance.resize()},100))}),this._resizeObserver.observe(this)}_cleanup(){this._resizeObserver&&(this._resizeObserver.disconnect(),this._resizeObserver=null),this._resizeTimeout&&clearTimeout(this._resizeTimeout),this._terminalInstance?.dispose&&(this._terminalInstance.dispose(),this._terminalInstance=null)}_dispatchEvent(t,a={}){this.dispatchEvent(new CustomEvent(t,{detail:a,bubbles:!0,composed:!0}))}initComputingTerminal(){const t=Vt.createContextLogger("WebComponent");try{this._terminal=Jt(this._container,this._sshConfig,this._options),this._dispatchEvent("ready",{message:"Computing terminal initialized",computingId:this._sshConfig.computingId})}catch(a){t.error("Failed to create computing terminal",{error:a.message}),this._container.innerHTML=`<p style="color:red;padding:8px;font-family:monospace;">Failed to create terminal: ${a.message}</p>`,this._dispatchEvent("error",{message:a.message})}}initTerminal(){const t=Vt.createContextLogger("WebComponent");if(!this._sshConfig){const o="SSH configuration not set. Call setConfig() first.";t.error(o),this._container.innerHTML=`<p style="color:red;padding:8px;font-family:monospace;">${o}</p>`,this._dispatchEvent("error",{message:o});return}const{host:a,username:r,password:n,wsUrl:s}=this._sshConfig;let i;if(this._sshConfig.computingId&&this._sshConfig.token){if(i=xe.validateComputingConfig(this._sshConfig),!i.isValid){const o=`Invalid computing configuration: ${i.errors.join(", ")}`;t.error("Computing config validation failed in initTerminal",{errors:i.errors}),this._container.innerHTML=`<p style="color:red;padding:8px;font-family:monospace;">${o}</p>`,this._dispatchEvent("error",{message:o,errors:i.errors});return}}else if(i=xe.validateSSHConfig(this._sshConfig),!i.isValid){const o=`Invalid SSH configuration: ${i.errors.join(", ")}`;t.error("SSH config validation failed in initTerminal",{errors:i.errors}),this._container.innerHTML=`<p style="color:red;padding:8px;font-family:monospace;">${o}</p>`,this._dispatchEvent("error",{message:o,errors:i.errors});return}try{this._terminalInstance=Jt(this._container,{host:a,username:r,password:n,wsUrl:s}),setTimeout(()=>{this._dispatchEvent("ready",{host:a,wsUrl:s})},100)}catch(o){const u=`Failed to create terminal: ${o.message}`;t.error("Failed to create terminal",{error:o.message}),this._container.innerHTML=`<p style="color:red;padding:8px;font-family:monospace;">${u}</p>`,this._dispatchEvent("error",{message:u,error:o})}}reconnect(){try{this._terminalInstance?.reconnect(),this._dispatchEvent("reconnecting")}catch(t){console.error("Reconnect failed:",t),this._dispatchEvent("error",{message:"Reconnect failed",error:t})}}resize(){try{this._terminalInstance?.resize()}catch(t){console.error("Resize failed:",t)}}search(t){try{return this._terminalInstance?.search(t)}catch(a){return console.error("Search failed:",a),!1}}searchPrevious(t){try{return this._terminalInstance?.searchPrevious(t)}catch(a){return console.error("Search previous failed:",a),!1}}getTerminalInstance(){return this._terminalInstance}isConnected(){return this._terminalInstance&&this._terminalInstance.terminal}}customElements.define("ssh-terminal",_a),typeof window<"u"&&window.customElements&&!window.customElements.get("ssh-terminal")&&console.log("SSH Terminal Web Component registered");var ii=typeof globalThis<"u"?globalThis:typeof window<"u"?window:typeof global<"u"?global:typeof self<"u"?self:{};function si(e){return e&&e.__esModule&&Object.prototype.hasOwnProperty.call(e,"default")?e.default:e}function oi(e){if(e.__esModule)return e;var t=e.default;if(typeof t=="function"){var a=function r(){return this instanceof r?Reflect.construct(t,arguments,this.constructor):t.apply(this,arguments)};a.prototype=t.prototype}else a={};return Object.defineProperty(a,"__esModule",{value:!0}),Object.keys(e).forEach(function(r){var n=Object.getOwnPropertyDescriptor(e,r);Object.defineProperty(a,r,n.get?n:{enumerable:!0,get:function(){return e[r]}})}),a}var Y={options:{usePureJavaScript:!1}},Fr={},li=Fr,Na={};Fr.encode=function(e,t,a){if(typeof t!="string")throw new TypeError('"alphabet" must be a string.');if(a!==void 0&&typeof a!="number")throw new TypeError('"maxline" must be a number.');var r="";if(!(e instanceof Uint8Array))r=ui(e,t);else{var n=0,s=t.length,i=t.charAt(0),o=[0];for(n=0;n<e.length;++n){for(var u=0,l=e[n];u<o.length;++u)l+=o[u]<<8,o[u]=l%s,l=l/s|0;for(;l>0;)o.push(l%s),l=l/s|0}for(n=0;e[n]===0&&n<e.length-1;++n)r+=i;for(n=o.length-1;n>=0;--n)r+=t[o[n]]}if(a){var c=new RegExp(".{1,"+a+"}","g");r=r.match(c).join(`\r
`)}return r},Fr.decode=function(e,t){if(typeof e!="string")throw new TypeError('"input" must be a string.');if(typeof t!="string")throw new TypeError('"alphabet" must be a string.');var a=Na[t];if(!a){a=Na[t]=[];for(var r=0;r<t.length;++r)a[t.charCodeAt(r)]=r}e=e.replace(/\s/g,"");for(var n=t.length,s=t.charAt(0),i=[0],r=0;r<e.length;r++){var o=a[e.charCodeAt(r)];if(o===void 0)return;for(var u=0,l=o;u<i.length;++u)l+=i[u]*n,i[u]=l&255,l>>=8;for(;l>0;)i.push(l&255),l>>=8}for(var c=0;e[c]===s&&c<e.length-1;++c)i.push(0);return typeof Buffer<"u"?Buffer.from(i.reverse()):new Uint8Array(i.reverse())};function ui(e,t){var a=0,r=t.length,n=t.charAt(0),s=[0];for(a=0;a<e.length();++a){for(var i=0,o=e.at(a);i<s.length;++i)o+=s[i]<<8,s[i]=o%r,o=o/r|0;for(;o>0;)s.push(o%r),o=o/r|0}var u="";for(a=0;e.at(a)===0&&a<e.length()-1;++a)u+=n;for(a=s.length-1;a>=0;--a)u+=t[s[a]];return u}var Ra=Y,La=li,E=Ra.util=Ra.util||{};(function(){if(typeof process<"u"&&process.nextTick&&!process.browser){E.nextTick=process.nextTick,typeof setImmediate=="function"?E.setImmediate=setImmediate:E.setImmediate=E.nextTick;return}if(typeof setImmediate=="function"){E.setImmediate=function(){return setImmediate.apply(void 0,arguments)},E.nextTick=function(i){return setImmediate(i)};return}if(E.setImmediate=function(i){setTimeout(i,0)},typeof window<"u"&&typeof window.postMessage=="function"){let i=function(o){if(o.source===window&&o.data===e){o.stopPropagation();var u=t.slice();t.length=0,u.forEach(function(l){l()})}};var e="forge.setImmediate",t=[];E.setImmediate=function(o){t.push(o),t.length===1&&window.postMessage(e,"*")},window.addEventListener("message",i,!0)}if(typeof MutationObserver<"u"){var a=Date.now(),r=!0,n=document.createElement("div"),t=[];new MutationObserver(function(){var o=t.slice();t.length=0,o.forEach(function(u){u()})}).observe(n,{attributes:!0});var s=E.setImmediate;E.setImmediate=function(o){Date.now()-a>15?(a=Date.now(),s(o)):(t.push(o),t.length===1&&n.setAttribute("a",r=!r))}}E.nextTick=E.setImmediate})(),E.isNodejs=typeof process<"u"&&process.versions&&process.versions.node,E.globalScope=function(){return E.isNodejs?ii:typeof self>"u"?window:self}(),E.isArray=Array.isArray||function(e){return Object.prototype.toString.call(e)==="[object Array]"},E.isArrayBuffer=function(e){return typeof ArrayBuffer<"u"&&e instanceof ArrayBuffer},E.isArrayBufferView=function(e){return e&&E.isArrayBuffer(e.buffer)&&e.byteLength!==void 0};function er(e){if(!(e===8||e===16||e===24||e===32))throw new Error("Only 8, 16, 24, or 32 bits supported: "+e)}E.ByteBuffer=Kr;function Kr(e){if(this.data="",this.read=0,typeof e=="string")this.data=e;else if(E.isArrayBuffer(e)||E.isArrayBufferView(e))if(typeof Buffer<"u"&&e instanceof Buffer)this.data=e.toString("binary");else{var t=new Uint8Array(e);try{this.data=String.fromCharCode.apply(null,t)}catch{for(var a=0;a<t.length;++a)this.putByte(t[a])}}else(e instanceof Kr||typeof e=="object"&&typeof e.data=="string"&&typeof e.read=="number")&&(this.data=e.data,this.read=e.read);this._constructedStringLength=0}E.ByteStringBuffer=Kr;var ci=4096;E.ByteStringBuffer.prototype._optimizeConstructedString=function(e){this._constructedStringLength+=e,this._constructedStringLength>ci&&(this.data.substr(0,1),this._constructedStringLength=0)},E.ByteStringBuffer.prototype.length=function(){return this.data.length-this.read},E.ByteStringBuffer.prototype.isEmpty=function(){return this.length()<=0},E.ByteStringBuffer.prototype.putByte=function(e){return this.putBytes(String.fromCharCode(e))},E.ByteStringBuffer.prototype.fillWithByte=function(e,t){e=String.fromCharCode(e);for(var a=this.data;t>0;)t&1&&(a+=e),t>>>=1,t>0&&(e+=e);return this.data=a,this._optimizeConstructedString(t),this},E.ByteStringBuffer.prototype.putBytes=function(e){return this.data+=e,this._optimizeConstructedString(e.length),this},E.ByteStringBuffer.prototype.putString=function(e){return this.putBytes(E.encodeUtf8(e))},E.ByteStringBuffer.prototype.putInt16=function(e){return this.putBytes(String.fromCharCode(e>>8&255)+String.fromCharCode(e&255))},E.ByteStringBuffer.prototype.putInt24=function(e){return this.putBytes(String.fromCharCode(e>>16&255)+String.fromCharCode(e>>8&255)+String.fromCharCode(e&255))},E.ByteStringBuffer.prototype.putInt32=function(e){return this.putBytes(String.fromCharCode(e>>24&255)+String.fromCharCode(e>>16&255)+String.fromCharCode(e>>8&255)+String.fromCharCode(e&255))},E.ByteStringBuffer.prototype.putInt16Le=function(e){return this.putBytes(String.fromCharCode(e&255)+String.fromCharCode(e>>8&255))},E.ByteStringBuffer.prototype.putInt24Le=function(e){return this.putBytes(String.fromCharCode(e&255)+String.fromCharCode(e>>8&255)+String.fromCharCode(e>>16&255))},E.ByteStringBuffer.prototype.putInt32Le=function(e){return this.putBytes(String.fromCharCode(e&255)+String.fromCharCode(e>>8&255)+String.fromCharCode(e>>16&255)+String.fromCharCode(e>>24&255))},E.ByteStringBuffer.prototype.putInt=function(e,t){er(t);var a="";do t-=8,a+=String.fromCharCode(e>>t&255);while(t>0);return this.putBytes(a)},E.ByteStringBuffer.prototype.putSignedInt=function(e,t){return e<0&&(e+=2<<t-1),this.putInt(e,t)},E.ByteStringBuffer.prototype.putBuffer=function(e){return this.putBytes(e.getBytes())},E.ByteStringBuffer.prototype.getByte=function(){return this.data.charCodeAt(this.read++)},E.ByteStringBuffer.prototype.getInt16=function(){var e=this.data.charCodeAt(this.read)<<8^this.data.charCodeAt(this.read+1);return this.read+=2,e},E.ByteStringBuffer.prototype.getInt24=function(){var e=this.data.charCodeAt(this.read)<<16^this.data.charCodeAt(this.read+1)<<8^this.data.charCodeAt(this.read+2);return this.read+=3,e},E.ByteStringBuffer.prototype.getInt32=function(){var e=this.data.charCodeAt(this.read)<<24^this.data.charCodeAt(this.read+1)<<16^this.data.charCodeAt(this.read+2)<<8^this.data.charCodeAt(this.read+3);return this.read+=4,e},E.ByteStringBuffer.prototype.getInt16Le=function(){var e=this.data.charCodeAt(this.read)^this.data.charCodeAt(this.read+1)<<8;return this.read+=2,e},E.ByteStringBuffer.prototype.getInt24Le=function(){var e=this.data.charCodeAt(this.read)^this.data.charCodeAt(this.read+1)<<8^this.data.charCodeAt(this.read+2)<<16;return this.read+=3,e},E.ByteStringBuffer.prototype.getInt32Le=function(){var e=this.data.charCodeAt(this.read)^this.data.charCodeAt(this.read+1)<<8^this.data.charCodeAt(this.read+2)<<16^this.data.charCodeAt(this.read+3)<<24;return this.read+=4,e},E.ByteStringBuffer.prototype.getInt=function(e){er(e);var t=0;do t=(t<<8)+this.data.charCodeAt(this.read++),e-=8;while(e>0);return t},E.ByteStringBuffer.prototype.getSignedInt=function(e){var t=this.getInt(e),a=2<<e-2;return t>=a&&(t-=a<<1),t},E.ByteStringBuffer.prototype.getBytes=function(e){var t;return e?(e=Math.min(this.length(),e),t=this.data.slice(this.read,this.read+e),this.read+=e):e===0?t="":(t=this.read===0?this.data:this.data.slice(this.read),this.clear()),t},E.ByteStringBuffer.prototype.bytes=function(e){return typeof e>"u"?this.data.slice(this.read):this.data.slice(this.read,this.read+e)},E.ByteStringBuffer.prototype.at=function(e){return this.data.charCodeAt(this.read+e)},E.ByteStringBuffer.prototype.setAt=function(e,t){return this.data=this.data.substr(0,this.read+e)+String.fromCharCode(t)+this.data.substr(this.read+e+1),this},E.ByteStringBuffer.prototype.last=function(){return this.data.charCodeAt(this.data.length-1)},E.ByteStringBuffer.prototype.copy=function(){var e=E.createBuffer(this.data);return e.read=this.read,e},E.ByteStringBuffer.prototype.compact=function(){return this.read>0&&(this.data=this.data.slice(this.read),this.read=0),this},E.ByteStringBuffer.prototype.clear=function(){return this.data="",this.read=0,this},E.ByteStringBuffer.prototype.truncate=function(e){var t=Math.max(0,this.length()-e);return this.data=this.data.substr(this.read,t),this.read=0,this},E.ByteStringBuffer.prototype.toHex=function(){for(var e="",t=this.read;t<this.data.length;++t){var a=this.data.charCodeAt(t);a<16&&(e+="0"),e+=a.toString(16)}return e},E.ByteStringBuffer.prototype.toString=function(){return E.decodeUtf8(this.bytes())};function fi(e,t){t=t||{},this.read=t.readOffset||0,this.growSize=t.growSize||1024;var a=E.isArrayBuffer(e),r=E.isArrayBufferView(e);if(a||r){a?this.data=new DataView(e):this.data=new DataView(e.buffer,e.byteOffset,e.byteLength),this.write="writeOffset"in t?t.writeOffset:this.data.byteLength;return}this.data=new DataView(new ArrayBuffer(0)),this.write=0,e!=null&&this.putBytes(e),"writeOffset"in t&&(this.write=t.writeOffset)}E.DataBuffer=fi,E.DataBuffer.prototype.length=function(){return this.write-this.read},E.DataBuffer.prototype.isEmpty=function(){return this.length()<=0},E.DataBuffer.prototype.accommodate=function(e,t){if(this.length()>=e)return this;t=Math.max(t||this.growSize,e);var a=new Uint8Array(this.data.buffer,this.data.byteOffset,this.data.byteLength),r=new Uint8Array(this.length()+t);return r.set(a),this.data=new DataView(r.buffer),this},E.DataBuffer.prototype.putByte=function(e){return this.accommodate(1),this.data.setUint8(this.write++,e),this},E.DataBuffer.prototype.fillWithByte=function(e,t){this.accommodate(t);for(var a=0;a<t;++a)this.data.setUint8(e);return this},E.DataBuffer.prototype.putBytes=function(e,t){if(E.isArrayBufferView(e)){var a=new Uint8Array(e.buffer,e.byteOffset,e.byteLength),r=a.byteLength-a.byteOffset;this.accommodate(r);var n=new Uint8Array(this.data.buffer,this.write);return n.set(a),this.write+=r,this}if(E.isArrayBuffer(e)){var a=new Uint8Array(e);this.accommodate(a.byteLength);var n=new Uint8Array(this.data.buffer);return n.set(a,this.write),this.write+=a.byteLength,this}if(e instanceof E.DataBuffer||typeof e=="object"&&typeof e.read=="number"&&typeof e.write=="number"&&E.isArrayBufferView(e.data)){var a=new Uint8Array(e.data.byteLength,e.read,e.length());this.accommodate(a.byteLength);var n=new Uint8Array(e.data.byteLength,this.write);return n.set(a),this.write+=a.byteLength,this}if(e instanceof E.ByteStringBuffer&&(e=e.data,t="binary"),t=t||"binary",typeof e=="string"){var s;if(t==="hex")return this.accommodate(Math.ceil(e.length/2)),s=new Uint8Array(this.data.buffer,this.write),this.write+=E.binary.hex.decode(e,s,this.write),this;if(t==="base64")return this.accommodate(Math.ceil(e.length/4)*3),s=new Uint8Array(this.data.buffer,this.write),this.write+=E.binary.base64.decode(e,s,this.write),this;if(t==="utf8"&&(e=E.encodeUtf8(e),t="binary"),t==="binary"||t==="raw")return this.accommodate(e.length),s=new Uint8Array(this.data.buffer,this.write),this.write+=E.binary.raw.decode(s),this;if(t==="utf16")return this.accommodate(e.length*2),s=new Uint16Array(this.data.buffer,this.write),this.write+=E.text.utf16.encode(s),this;throw new Error("Invalid encoding: "+t)}throw Error("Invalid parameter: "+e)},E.DataBuffer.prototype.putBuffer=function(e){return this.putBytes(e),e.clear(),this},E.DataBuffer.prototype.putString=function(e){return this.putBytes(e,"utf16")},E.DataBuffer.prototype.putInt16=function(e){return this.accommodate(2),this.data.setInt16(this.write,e),this.write+=2,this},E.DataBuffer.prototype.putInt24=function(e){return this.accommodate(3),this.data.setInt16(this.write,e>>8&65535),this.data.setInt8(this.write,e>>16&255),this.write+=3,this},E.DataBuffer.prototype.putInt32=function(e){return this.accommodate(4),this.data.setInt32(this.write,e),this.write+=4,this},E.DataBuffer.prototype.putInt16Le=function(e){return this.accommodate(2),this.data.set