Files
P4RS3LT0NGV3/src/transformers/encoding/z85.js
T
2026-03-20 22:57:14 -07:00

93 lines
3.1 KiB
JavaScript

// z85 encoding (ZeroMQ Base85)
import BaseTransformer from '../BaseTransformer.js';
export default new BaseTransformer({
name: 'Z85',
priority: 250,
category: 'encoding',
// Z85 uses a different character set than standard Base85
charset: '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ.-:+=^!/*?&<>()[]{}@%$#',
func: function(text) {
const bytes = new TextEncoder().encode(text);
let result = '';
const originalLength = bytes.length;
// Z85 encodes 4 bytes into 5 characters
for (let i = 0; i < bytes.length; i += 4) {
const chunk = Array.from(bytes.slice(i, i + 4));
const chunkLength = chunk.length;
while (chunk.length < 4) chunk.push(0);
// Convert 4 bytes to 32-bit integer
let value = 0;
for (let j = 0; j < 4; j++) {
value = (value << 8) + chunk[j];
}
// Convert to base 85 (5 digits)
const z85Chars = [];
for (let j = 0; j < 5; j++) {
z85Chars.unshift(this.charset[value % 85]);
value = Math.floor(value / 85);
}
result += z85Chars.join('');
}
// Store original length for decoding
this._z85OriginalLength = originalLength;
return result;
},
reverse: function(text) {
const bytes = [];
// Z85 decodes 5 characters into 4 bytes
for (let i = 0; i < text.length; i += 5) {
const chunk = text.substring(i, i + 5);
if (chunk.length < 5) break;
// Convert 5 base-85 digits to 32-bit integer
let value = 0;
for (const char of chunk) {
const idx = this.charset.indexOf(char);
if (idx === -1) return ''; // Invalid character
value = value * 85 + idx;
}
// Extract 4 bytes
bytes.push((value >> 24) & 0xFF);
bytes.push((value >> 16) & 0xFF);
bytes.push((value >> 8) & 0xFF);
bytes.push(value & 0xFF);
}
// Trim to original length if we stored it
if (this._z85OriginalLength !== undefined) {
bytes.length = Math.min(bytes.length, this._z85OriginalLength);
} else {
// Remove trailing null bytes (padding)
while (bytes.length > 0 && bytes[bytes.length - 1] === 0) {
bytes.pop();
}
}
try {
return new TextDecoder().decode(new Uint8Array(bytes));
} catch (e) {
return '';
}
},
preview: function(text) {
if (!text) return '[z85]';
const result = this.func(text.slice(0, 4));
return result.substring(0, 10) + '...';
},
detector: function(text) {
// Z85 uses specific character set
const z85Pattern = /^[0-9a-zA-Z.\-:+=^!\/\*\?&<>()\[\]{}@%$#]+$/;
return text.length >= 5 && z85Pattern.test(text) && text.length % 5 === 0;
}
});