diff --git a/zefie_wtvp_minisrv/client_emu.js b/zefie_wtvp_minisrv/client_emu.js index ddcd82e8..1e8f75f2 100644 --- a/zefie_wtvp_minisrv/client_emu.js +++ b/zefie_wtvp_minisrv/client_emu.js @@ -19,11 +19,12 @@ const AdmZip = require('adm-zip'); * using the WTVP protocol with proper authentication and service discovery. */ class WebTVClientSimulator { - constructor(host, port, ssid, url, outputFile = null, maxRedirects = 10, useEncryption = false, request_type_download = false, debug = false, tricks = false, followImages = false, followAll = false, maxDepth = 5, maxRetries = 5, requestDelay = 250, boxType = null, username = null) { + constructor(host, port, ssid, url, outputFile = null, maxRedirects = 10, useEncryption = false, request_type_download = false, debug = false, tricks = false, followImages = false, followAll = false, maxDepth = 5, maxRetries = 5, requestDelay = 250, boxType = null, username = null, keepgz = false) { this.host = host; this.port = port; this.ssid = ssid; this.url = url; + this.keepgz = keepgz; this.request_type_download = request_type_download; this.outputFile = outputFile; this.followImages = followImages; @@ -1211,7 +1212,9 @@ class WebTVClientSimulator { const match = this.url.match(/^([\w-]+):\/?(.*)/); if (match) { const serviceName = match[1]; - const path = '/' + (match[2] || ''); + let path = '/' + (match[2] || ''); + + this.debugLog(`Parsed target service: ${serviceName}, path: ${path}`); try { @@ -1338,21 +1341,36 @@ class WebTVClientSimulator { const contentType = headers['content-type'] || ''; const normalizedContentType = contentType.split(';')[0].trim().toLowerCase(); + // Handle gzip decompression if content-type is application/gzip and keepgz is false + let processedContent = content; + if (normalizedContentType === 'application/gzip' && !this.keepgz) { + this.debugLog('Decompressing gzip content...'); + try { + const buffer = Buffer.isBuffer(content) ? content : Buffer.from(content, 'binary'); + processedContent = zlib.gunzipSync(buffer); + this.debugLog('Gzip decompression successful'); + } catch (error) { + console.error('Error decompressing gzip content:', error); + this.debugLog('Falling back to original content'); + processedContent = content; + } + } + const isHtml = /text\/html/i.test(contentType) || - (typeof content === 'string' && / TellyScript/DialScript content detected, saved as .tok file`); } @@ -2552,7 +2628,8 @@ function parseArgs() { maxRetries: 5, requestDelay: 250, debug: false, - username: null + username: null, + keepgz: false }; for (let i = 0; i < args.length; i++) { @@ -2632,6 +2709,9 @@ function parseArgs() { config.username = args[++i]; } break; + case '--keepgz': + config.keepgz = true; + break; case '--help': console.log(` WebTV Client Simulator @@ -2655,6 +2735,7 @@ Options: --depth Maximum crawl depth for --follow-all mode (default: 5) --retries Maximum number of retries for ECONNREFUSED errors (default: 5) --delay Delay between requests in milliseconds (default: 250) + --keepgz Keep .gz files compressed when following wtv/download-list (default: false) --debug Enable debug logging --help Show this help message @@ -2675,7 +2756,7 @@ Example: */ async function main() { const config = parseArgs(); - const simulator = new WebTVClientSimulator(config.host, config.port, config.ssid, config.url, config.outputFile, config.maxRedirects, config.useEncryption, config.request_type_download, config.debug, config.useTricksAccess, config.followImages, config.followAll, config.maxDepth, config.maxRetries, config.requestDelay, config.boxType, config.username); + const simulator = new WebTVClientSimulator(config.host, config.port, config.ssid, config.url, config.outputFile, config.maxRedirects, config.useEncryption, config.request_type_download, config.debug, config.useTricksAccess, config.followImages, config.followAll, config.maxDepth, config.maxRetries, config.requestDelay, config.boxType, config.username, config.keepgz); // Handle graceful shutdown process.on('SIGINT', () => {