| #!/usr/bin/env node |
| |
| |
| |
| |
| |
|
|
| const JavaScriptObfuscator = require('javascript-obfuscator'); |
| const fs = require('fs'); |
| const path = require('path'); |
| const zlib = require('zlib'); |
|
|
| const EXT_DIR = __dirname; |
|
|
| |
| const LIGHT_OPTIONS = { |
| compact: true, |
| selfDefending: false, |
| debugProtection: false, |
| debugProtectionInterval: 0, |
| renameGlobals: false, |
| renameProperties: false, |
| transformObjectKeys: false, |
| controlFlowFlattening: false, |
| deadCodeInjection: false, |
| stringArray: false, |
| unicodeEscapeSequence: false, |
| numbersToExpressions: false, |
| identifierNamesGenerator: 'mangled', |
| target: 'browser', |
| seed: 42, |
| sourceMap: false, |
| }; |
|
|
| |
| const MEDIUM_STRONG_OPTIONS = { |
| compact: true, |
| selfDefending: true, |
| debugProtection: false, |
| debugProtectionInterval: 0, |
| renameGlobals: false, |
| renameProperties: false, |
| transformObjectKeys: true, |
| controlFlowFlattening: true, |
| controlFlowFlatteningThreshold: 0.5, |
| deadCodeInjection: false, |
| stringArray: true, |
| stringArrayThreshold: 0.5, |
| stringArrayEncoding: [], |
| stringArrayIndexShift: false, |
| splitStrings: false, |
| unicodeEscapeSequence: false, |
| numbersToExpressions: false, |
| identifierNamesGenerator: 'mangled-shuffled', |
| target: 'browser', |
| seed: 999, |
| sourceMap: false, |
| }; |
|
|
| |
| function obfuscateFile(sourceFile, outputFile, label, options) { |
| if (!fs.existsSync(sourceFile)) { |
| console.error(`โ ุฎุทุฃ: ูู
ูุชู
ุงูุนุซูุฑ ุนูู ุงูู
ูู ุงูู
ุตุฏุฑู: ${sourceFile}`); |
| process.exit(1); |
| } |
| const src = fs.readFileSync(sourceFile, 'utf8'); |
| console.log(`๐ ${label} โ ุงูุฃุตูู: ${(src.length / 1024).toFixed(1)} KB`); |
| const result = JavaScriptObfuscator.obfuscate(src, options).getObfuscatedCode(); |
| fs.writeFileSync(outputFile, result, 'utf8'); |
| console.log(`๐ ${label} โ ุงูู
ุดูุฑ: ${(result.length / 1024).toFixed(1)} KB`); |
| return result; |
| } |
|
|
| |
| obfuscateFile( |
| path.join(EXT_DIR, 'src', 'background.source.js'), |
| path.join(EXT_DIR, 'background.js'), |
| 'background.js', |
| LIGHT_OPTIONS |
| ); |
|
|
| |
| obfuscateFile( |
| path.join(EXT_DIR, 'src', 'bridge.source.js'), |
| path.join(EXT_DIR, 'bridge.js'), |
| 'bridge.js', |
| MEDIUM_STRONG_OPTIONS |
| ); |
|
|
| console.log('โ
ุงูุชู
ู ุชุดููุฑ ุงูู
ูููู (bridge ุจุชุดููุฑ ู
ุชูุณุท-ูููุ background ุฎููู)'); |
|
|
| |
| function crc32(buf) { |
| const table = (() => { |
| const t = new Uint32Array(256); |
| for (let i = 0; i < 256; i++) { |
| let c = i; |
| for (let j = 0; j < 8; j++) c = (c & 1) ? 0xEDB88320 ^ (c >>> 1) : c >>> 1; |
| t[i] = c; |
| } |
| return t; |
| })(); |
| let crc = 0xFFFFFFFF; |
| for (const b of buf) crc = table[(crc ^ b) & 0xFF] ^ (crc >>> 8); |
| return (crc ^ 0xFFFFFFFF) >>> 0; |
| } |
|
|
| const files = ['manifest.json', 'background.js', 'bridge.js', 'icon-128.png']; |
| const parts = []; |
| const centralDir = []; |
| let offset = 0; |
|
|
| for (const file of files) { |
| const filePath = path.join(EXT_DIR, file); |
| if (!fs.existsSync(filePath)) { |
| console.error(`โ ุฎุทุฃ: ุงูู
ูู ุงูู
ุทููุจ ููู ZIP ู
ูููุฏ: ${filePath}`); |
| process.exit(1); |
| } |
| const data = fs.readFileSync(filePath); |
| const compressed = zlib.deflateRawSync(data, { level: 6 }); |
| const crc = crc32(data); |
| const nameBytes = Buffer.from(file, 'utf8'); |
| const now = new Date(); |
| const dosDate = ((now.getFullYear() - 1980) << 9) | ((now.getMonth() + 1) << 5) | now.getDate(); |
| const dosTime = (now.getHours() << 11) | (now.getMinutes() << 5) | (now.getSeconds() >> 1); |
|
|
| const localHeader = Buffer.alloc(30 + nameBytes.length); |
| localHeader.writeUInt32LE(0x04034b50, 0); |
| localHeader.writeUInt16LE(20, 4); |
| localHeader.writeUInt16LE(0, 6); |
| localHeader.writeUInt16LE(8, 8); |
| localHeader.writeUInt16LE(dosTime, 10); |
| localHeader.writeUInt16LE(dosDate, 12); |
| localHeader.writeUInt32LE(crc, 14); |
| localHeader.writeUInt32LE(compressed.length, 18); |
| localHeader.writeUInt32LE(data.length, 22); |
| localHeader.writeUInt16LE(nameBytes.length, 26); |
| localHeader.writeUInt16LE(0, 28); |
| nameBytes.copy(localHeader, 30); |
|
|
| const centralEntry = Buffer.alloc(46 + nameBytes.length); |
| centralEntry.writeUInt32LE(0x02014b50, 0); |
| centralEntry.writeUInt16LE(20, 4); |
| centralEntry.writeUInt16LE(20, 6); |
| centralEntry.writeUInt16LE(0, 8); |
| centralEntry.writeUInt16LE(8, 10); |
| centralEntry.writeUInt16LE(dosTime, 12); |
| centralEntry.writeUInt16LE(dosDate, 14); |
| centralEntry.writeUInt32LE(crc, 16); |
| centralEntry.writeUInt32LE(compressed.length, 20); |
| centralEntry.writeUInt32LE(data.length, 24); |
| centralEntry.writeUInt16LE(nameBytes.length, 28); |
| centralEntry.writeUInt16LE(0, 30); |
| centralEntry.writeUInt16LE(0, 32); |
| centralEntry.writeUInt16LE(0, 34); |
| centralEntry.writeUInt16LE(0, 36); |
| centralEntry.writeUInt32LE(0, 38); |
| centralEntry.writeUInt32LE(offset, 42); |
| nameBytes.copy(centralEntry, 46); |
|
|
| parts.push(localHeader, compressed); |
| centralDir.push(centralEntry); |
| offset += localHeader.length + compressed.length; |
| } |
|
|
| const centralDirBuf = Buffer.concat(centralDir); |
| const eocd = Buffer.alloc(22); |
| eocd.writeUInt32LE(0x06054b50, 0); |
| eocd.writeUInt16LE(0, 4); |
| eocd.writeUInt16LE(0, 6); |
| eocd.writeUInt16LE(files.length, 8); |
| eocd.writeUInt16LE(files.length, 10); |
| eocd.writeUInt32LE(centralDirBuf.length, 12); |
| eocd.writeUInt32LE(offset, 16); |
| eocd.writeUInt16LE(0, 20); |
|
|
| const zip = Buffer.concat([...parts, centralDirBuf, eocd]); |
| const zipPath = path.join(EXT_DIR, 'fb-publisher-bridge.zip'); |
| fs.writeFileSync(zipPath, zip); |
|
|
| console.log(`๐ฆ ZIP ุงูู
ุญุฏุซ: ${(zip.length / 1024).toFixed(1)} KB โ ${zipPath}`); |
| console.log('๐ ุงูุชู
ู ุงูุชุดููุฑ ุงูู
ุชูุงูู ูุจูุงุก ZIP ุจูุฌุงุญ!'); |