roxify 1.16.13 → 1.16.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -21,7 +21,7 @@ async function loadJsEngine() {
21
21
  };
22
22
  }
23
23
  // Keep in sync with package.json#version.
24
- const VERSION = '1.16.13';
24
+ const VERSION = '1.16.14';
25
25
  function getDirectorySize(dirPath) {
26
26
  let totalSize = 0;
27
27
  try {
@@ -67,20 +67,18 @@ async function readLargeFile(filePath) {
67
67
  }
68
68
  function showHelp() {
69
69
  console.log(`
70
- ROX CLI — Encode/decode binary in PNG or WAV
70
+ ROX CLI — Encode/decode binary in PNG
71
71
 
72
72
  Usage:
73
73
  npx rox <command> [options]
74
74
 
75
75
  Commands:
76
76
  encode <input>... [output] Encode one or more files/directories
77
- decode <input> [output] Decode PNG/WAV to original file
77
+ decode <input> [output] Decode PNG to original file
78
78
  list <input> List files in a Rox archive
79
79
  havepassphrase <input> Check whether the archive requires a passphrase
80
80
 
81
81
  Options:
82
- --image Use PNG container (default)
83
- --sound Use WAV audio container (smaller overhead, faster)
84
82
  -p, --passphrase <pass> Use passphrase (AES-256-GCM)
85
83
  -m, --mode <mode> Mode: screenshot (default)
86
84
  -e, --encrypt <type> auto|aes|xor|none
@@ -101,17 +99,10 @@ Lossy-Resilient Encoding:
101
99
  --ecc-level <level> ECC redundancy: low|medium|quartile|high (default: medium)
102
100
  --block-size <n> Robust image block size: 2-8 pixels (default: 4)
103
101
 
104
- When --lossy-resilient is active, data is encoded with Reed-Solomon ECC
105
- and rendered as a QR-code-style grid (image) or MFSK tones (audio).
106
- Use --sound or --image to choose the container format.
107
-
108
102
  Examples:
109
103
  npx rox encode secret.pdf Encode to PNG
110
- npx rox encode secret.pdf --sound Encode to WAV
111
104
  npx rox encode secret.pdf --lossy-resilient Lossy-resilient PNG
112
- npx rox encode secret.pdf --lossy-resilient --sound --ecc-level high
113
105
  npx rox decode secret.pdf.png Decode back
114
- npx rox decode secret.pdf.wav Decode WAV back
115
106
 
116
107
  Run "npx rox help" for this message.
117
108
  `);
@@ -173,14 +164,6 @@ function parseArgs(args) {
173
164
  parsed.blockSize = bs;
174
165
  i += 2;
175
166
  }
176
- else if (key === 'sound') {
177
- parsed.container = 'sound';
178
- i++;
179
- }
180
- else if (key === 'image') {
181
- parsed.container = 'image';
182
- i++;
183
- }
184
167
  else if (key === 'debug-dir') {
185
168
  parsed.debugDir = args[i + 1];
186
169
  i += 2;
@@ -281,14 +264,13 @@ async function encodeCommand(args) {
281
264
  safeCwd = '/';
282
265
  }
283
266
  const resolvedInputs = inputPaths.map((p) => resolve(safeCwd, p));
284
- const containerMode = parsed.container || 'image'; // default: image (PNG)
285
- const containerExt = containerMode === 'sound' ? '.wav' : '.png';
286
- let outputName = inputPaths.length === 1 ? basename(firstInput) : 'archive';
267
+ const outputNameBase = inputPaths.length === 1 ? basename(firstInput) : 'archive';
268
+ let outputName = outputNameBase;
287
269
  if (inputPaths.length === 1 && !statSync(resolvedInputs[0]).isDirectory()) {
288
- outputName = outputName.replace(/(\.[^.]+)?$/, containerExt);
270
+ outputName = outputNameBase.replace(/(\.[^.]+)?$/, '.png');
289
271
  }
290
272
  else {
291
- outputName += containerExt;
273
+ outputName = outputNameBase + '.png';
292
274
  }
293
275
  let resolvedOutput;
294
276
  try {
@@ -317,7 +299,7 @@ async function encodeCommand(args) {
317
299
  }
318
300
  }
319
301
  catch (e) { }
320
- if (isRustBinaryAvailable() && !parsed.forceTs && containerMode !== 'sound') {
302
+ if (isRustBinaryAvailable() && !parsed.forceTs) {
321
303
  try {
322
304
  console.log(`Encoding to ${resolvedOutput} (Using native Rust encoder)\n`);
323
305
  const startTime = Date.now();
@@ -415,7 +397,6 @@ async function encodeCommand(args) {
415
397
  skipOptimization: false,
416
398
  compressionLevel: 6,
417
399
  outputFormat: 'auto',
418
- container: containerMode,
419
400
  });
420
401
  if (parsed.verbose)
421
402
  options.verbose = true;
@@ -432,7 +413,7 @@ async function encodeCommand(args) {
432
413
  if (parsed.blockSize)
433
414
  options.robustBlockSize = parsed.blockSize;
434
415
  }
435
- console.log(`Encoding to ${resolvedOutput} (Mode: ${mode}, Container: ${containerMode === 'sound' ? 'WAV' : 'PNG'})\n`);
416
+ console.log(`Encoding to ${resolvedOutput}\n`);
436
417
  let inputData;
437
418
  let inputSizeVal = 0;
438
419
  let displayName;
@@ -768,6 +749,7 @@ async function main() {
768
749
  await encodeCommand(commandArgs);
769
750
  break;
770
751
  case 'decode':
752
+ case 'decompress':
771
753
  await decodeCommand(commandArgs);
772
754
  break;
773
755
  case 'list':
package/dist/index.d.ts CHANGED
@@ -1,4 +1,3 @@
1
- export * from './utils/audio.js';
2
1
  export * from './utils/constants.js';
3
2
  export * from './utils/crc.js';
4
3
  export * from './utils/decoder.js';
package/dist/index.js CHANGED
@@ -1,4 +1,3 @@
1
- export * from './utils/audio.js';
2
1
  export * from './utils/constants.js';
3
2
  export * from './utils/crc.js';
4
3
  export * from './utils/decoder.js';
@@ -43,28 +43,14 @@ export async function encodeBinaryToPng(input, opts = {}) {
43
43
  const fileListJson = opts.includeFileList && opts.fileList
44
44
  ? normalizeNativeFileList(opts.fileList)
45
45
  : undefined;
46
- // --- PNG container via native Rust encoder ---
47
- if (opts.container === 'sound') {
48
- if (opts.passphrase) {
49
- const encryptType = opts.encrypt && opts.encrypt !== 'auto' ? opts.encrypt : 'aes';
50
- const result = native.nativeEncodeWavWithEncryptionNameAndFilelist(inputBuf, compressionLevel, opts.passphrase, encryptType, fileName, fileListJson);
51
- return Buffer.from(result);
52
- }
53
- else {
54
- const result = native.nativeEncodeWavWithNameAndFilelist(inputBuf, compressionLevel, fileName, fileListJson);
55
- return Buffer.from(result);
56
- }
46
+ if (opts.passphrase) {
47
+ const encryptType = opts.encrypt && opts.encrypt !== 'auto' ? opts.encrypt : 'aes';
48
+ const result = native.nativeEncodePngWithEncryptionNameAndFilelist(inputBuf, compressionLevel, opts.passphrase, encryptType, fileName, fileListJson);
49
+ return Buffer.from(result);
57
50
  }
58
51
  else {
59
- if (opts.passphrase) {
60
- const encryptType = opts.encrypt && opts.encrypt !== 'auto' ? opts.encrypt : 'aes';
61
- const result = native.nativeEncodePngWithEncryptionNameAndFilelist(inputBuf, compressionLevel, opts.passphrase, encryptType, fileName, fileListJson);
62
- return Buffer.from(result);
63
- }
64
- else {
65
- const result = native.nativeEncodePngWithNameAndFilelist(inputBuf, compressionLevel, fileName, fileListJson);
66
- return Buffer.from(result);
67
- }
52
+ const result = native.nativeEncodePngWithNameAndFilelist(inputBuf, compressionLevel, fileName, fileListJson);
53
+ return Buffer.from(result);
68
54
  }
69
55
  }
70
56
  function normalizeNativeFileList(fileList) {
@@ -13,8 +13,6 @@ export interface EncodeOptions {
13
13
  _skipAuto?: boolean;
14
14
  output?: 'auto' | 'png' | 'rox';
15
15
  outputFormat?: 'png' | 'webp';
16
- /** Container format: 'image' (PNG, default) or 'sound' (WAV) */
17
- container?: 'image' | 'sound';
18
16
  /**
19
17
  * Enable lossy-resilient encoding. When true, the output survives lossy
20
18
  * compression (MP3/AAC for audio, JPEG/WebP for image) using QR-code-like
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "roxify",
3
- "version": "1.16.13",
3
+ "version": "1.16.14",
4
4
  "type": "module",
5
5
  "description": "Ultra-lightweight PNG steganography with native Rust acceleration. Encode binary data into PNG images with zstd compression.",
6
6
  "main": "dist/index.js",
@@ -1,23 +0,0 @@
1
- /**
2
- * WAV container for binary data.
3
- *
4
- * Encodes raw bytes as 8-bit unsigned PCM mono samples (44100 Hz).
5
- * Header is exactly 44 bytes. Total container overhead: 44 bytes (constant).
6
- *
7
- * Compared to PNG (stored deflate): PNG overhead grows with data size
8
- * (zlib framing, filter bytes, chunk CRCs). WAV overhead is constant.
9
- */
10
- /**
11
- * Pack raw bytes into a WAV file (8-bit PCM, mono, 44100 Hz).
12
- * The bytes are stored directly as unsigned PCM samples.
13
- */
14
- export declare function bytesToWav(data: Buffer): Buffer;
15
- /**
16
- * Extract raw bytes from a WAV file.
17
- * Returns the PCM data (the original bytes).
18
- */
19
- export declare function wavToBytes(wav: Buffer): Buffer;
20
- /**
21
- * Check if a buffer starts with a RIFF/WAVE header.
22
- */
23
- export declare function isWav(buf: Buffer): boolean;
@@ -1,98 +0,0 @@
1
- /**
2
- * WAV container for binary data.
3
- *
4
- * Encodes raw bytes as 8-bit unsigned PCM mono samples (44100 Hz).
5
- * Header is exactly 44 bytes. Total container overhead: 44 bytes (constant).
6
- *
7
- * Compared to PNG (stored deflate): PNG overhead grows with data size
8
- * (zlib framing, filter bytes, chunk CRCs). WAV overhead is constant.
9
- */
10
- const WAV_HEADER_SIZE = 44;
11
- const SAMPLE_RATE = 44100;
12
- const BITS_PER_SAMPLE = 8;
13
- const NUM_CHANNELS = 1;
14
- /**
15
- * Pack raw bytes into a WAV file (8-bit PCM, mono, 44100 Hz).
16
- * The bytes are stored directly as unsigned PCM samples.
17
- */
18
- export function bytesToWav(data) {
19
- const dataSize = data.length;
20
- const fileSize = WAV_HEADER_SIZE - 8 + dataSize;
21
- const byteRate = SAMPLE_RATE * NUM_CHANNELS * (BITS_PER_SAMPLE / 8);
22
- const blockAlign = NUM_CHANNELS * (BITS_PER_SAMPLE / 8);
23
- const wav = Buffer.alloc(WAV_HEADER_SIZE + dataSize);
24
- let offset = 0;
25
- // RIFF header
26
- wav.write('RIFF', offset, 'ascii');
27
- offset += 4;
28
- wav.writeUInt32LE(fileSize, offset);
29
- offset += 4;
30
- wav.write('WAVE', offset, 'ascii');
31
- offset += 4;
32
- // fmt sub-chunk
33
- wav.write('fmt ', offset, 'ascii');
34
- offset += 4;
35
- wav.writeUInt32LE(16, offset);
36
- offset += 4; // sub-chunk size (PCM = 16)
37
- wav.writeUInt16LE(1, offset);
38
- offset += 2; // audio format (1 = PCM)
39
- wav.writeUInt16LE(NUM_CHANNELS, offset);
40
- offset += 2;
41
- wav.writeUInt32LE(SAMPLE_RATE, offset);
42
- offset += 4;
43
- wav.writeUInt32LE(byteRate, offset);
44
- offset += 4;
45
- wav.writeUInt16LE(blockAlign, offset);
46
- offset += 2;
47
- wav.writeUInt16LE(BITS_PER_SAMPLE, offset);
48
- offset += 2;
49
- // data sub-chunk
50
- wav.write('data', offset, 'ascii');
51
- offset += 4;
52
- wav.writeUInt32LE(dataSize, offset);
53
- offset += 4;
54
- data.copy(wav, offset);
55
- return wav;
56
- }
57
- /**
58
- * Extract raw bytes from a WAV file.
59
- * Returns the PCM data (the original bytes).
60
- */
61
- export function wavToBytes(wav) {
62
- if (wav.length < WAV_HEADER_SIZE) {
63
- throw new Error('WAV data too short');
64
- }
65
- if (wav.toString('ascii', 0, 4) !== 'RIFF') {
66
- throw new Error('Not a RIFF file');
67
- }
68
- if (wav.toString('ascii', 8, 12) !== 'WAVE') {
69
- throw new Error('Not a WAVE file');
70
- }
71
- // Find the "data" sub-chunk
72
- let offset = 12;
73
- while (offset + 8 <= wav.length) {
74
- const chunkId = wav.toString('ascii', offset, offset + 4);
75
- const chunkSize = wav.readUInt32LE(offset + 4);
76
- if (chunkId === 'data') {
77
- const dataStart = offset + 8;
78
- const dataEnd = dataStart + chunkSize;
79
- if (dataEnd > wav.length) {
80
- return wav.subarray(dataStart);
81
- }
82
- return wav.subarray(dataStart, dataEnd);
83
- }
84
- offset += 8 + chunkSize;
85
- if (chunkSize % 2 !== 0)
86
- offset += 1; // RIFF word alignment
87
- }
88
- throw new Error('data chunk not found in WAV');
89
- }
90
- /**
91
- * Check if a buffer starts with a RIFF/WAVE header.
92
- */
93
- export function isWav(buf) {
94
- return (buf.length >= 12 &&
95
- buf[0] === 0x52 && buf[1] === 0x49 && buf[2] === 0x46 && buf[3] === 0x46 && // RIFF
96
- buf[8] === 0x57 && buf[9] === 0x41 && buf[10] === 0x56 && buf[11] === 0x45 // WAVE
97
- );
98
- }