cryptpadtab

encrypted notes in a browser tab  https://p.ce9e.org/cryptpadtab/
git clone https://git.ce9e.org/cryptpadtab.git

commit
7434ff79bd7a5e08378771867d1b230b79bbfe68
parent
e5abb49dcced9af631279330025775c317b8d24b
Author
Tobias Bengfort <tobias.bengfort@posteo.de>
Date
2024-05-29 13:35
use native gzip compression

Diffstat

M static/gzip.js 24 ++++++++----------------
D static/lzw.js 128 ------------------------------------------------------------
M static/main.js 22 +++++++++++-----------

3 files changed, 19 insertions, 155 deletions


diff --git a/static/gzip.js b/static/gzip.js

@@ -1,27 +1,19 @@
    1    -1 export async function compress(bytes) {
    2    -1 	var compressionStream = new CompressionStream('gzip');
    3    -1 	var writableStream = new WritableStream();
   -1     1 async function applyStream(bytes, stream) {
    4     2 	var readableStream = new ReadableStream({
    5     3 		start(controller) {
    6     4 			controller.enqueue(bytes);
    7     5 			controller.close();
    8     6 		}
    9     7 	});
   10    -1 	await readableStream.pipeThrough(compressionStream).pipeTo(writableStream);
   11    -1 	var result = await new Response(writableStream).arrayBuffer();
   -1     8 	var resultStream = await readableStream.pipeThrough(stream);
   -1     9 	var result = await new Response(resultStream).arrayBuffer();
   12    10 	return new Uint8Array(result);
   13    11 }
   14    12 
   -1    13 export async function compress(bytes) {
   -1    14 	return await applyStream(bytes, new CompressionStream('gzip'));
   -1    15 }
   -1    16 
   15    17 export async function decompress(bytes) {
   16    -1 	var decompressionStream = new DecompressionStream('gzip');
   17    -1 	var writableStream = new WritableStream();
   18    -1 	var readableStream = new ReadableStream({
   19    -1 		start(controller) {
   20    -1 			controller.enqueue(bytes);
   21    -1 			controller.close();
   22    -1 		}
   23    -1 	});
   24    -1 	await readableStream.pipeThrough(decompressionStream).pipeTo(writableStream);
   25    -1 	var result = await new Response(writableStream).arrayBuffer();
   26    -1 	return new Uint8Array(result);
   -1    18 	return await applyStream(bytes, new DecompressionStream('gzip'));
   27    19 }

diff --git a/static/lzw.js b/static/lzw.js

@@ -1,128 +0,0 @@
    1    -1 class Buffer {
    2    -1 	constructor(bytes) {
    3    -1 		this.bytes = bytes;
    4    -1 		this.i_byte = 0;
    5    -1 		this.i_bit = 0;
    6    -1 	}
    7    -1 
    8    -1 	next() {
    9    -1 		if (this.i_bit < 7) {
   10    -1 			this.i_bit += 1;
   11    -1 		} else {
   12    -1 			this.i_byte += 1;
   13    -1 			this.i_bit = 0;
   14    -1 		}
   15    -1 	}
   16    -1 
   17    -1 	read(size) {
   18    -1 		var bits = 0;
   19    -1 		for (let i = 0; i < size; i++) {
   20    -1 			if (this.bytes.length <= this.i_byte) {
   21    -1 				throw new RangeError();
   22    -1 			}
   23    -1 			bits <<= 1;
   24    -1 			if (this.bytes[this.i_byte] & (1 << (7 - this.i_bit))) {
   25    -1 				bits |= 1;
   26    -1 			}
   27    -1 			this.next();
   28    -1 		}
   29    -1 		return bits;
   30    -1 	}
   31    -1 
   32    -1 	write(bits, size) {
   33    -1 		for (let i = 0; i < size; i++) {
   34    -1 			if (this.bytes.length <= this.i_byte) {
   35    -1 				this.bytes.push(0);
   36    -1 			}
   37    -1 			if (bits & (1 << (size - i - 1))) {
   38    -1 				this.bytes[this.i_byte] |= 1 << (7 - this.i_bit);
   39    -1 			}
   40    -1 			this.next();
   41    -1 		}
   42    -1 	}
   43    -1 }
   44    -1 
   45    -1 var sIndexOf = function(dict, value) {
   46    -1 	var s = value.toString();
   47    -1 	for (let i = 0; i < dict.length; i++) {
   48    -1 		if (s === dict[i].toString()) {
   49    -1 			return i;
   50    -1 		}
   51    -1 	}
   52    -1 	return -1;
   53    -1 };
   54    -1 
   55    -1 export var compress = function(bytes) {
   56    -1 	var result = [];
   57    -1 	var buf = new Buffer(result);
   58    -1 
   59    -1 	var field_size = 9;
   60    -1 	var dict = [];
   61    -1 	dict.push('end');
   62    -1 	for (let i = 0; i < 256; i++) {
   63    -1 		dict.push([i]);
   64    -1 	}
   65    -1 
   66    -1 	var win = [];
   67    -1 	var i = 0;
   68    -1 	while (i < bytes.length) {
   69    -1 		var tmp = [...win, bytes[i]];
   70    -1 		if (sIndexOf(dict, tmp) === -1) {
   71    -1 			buf.write(sIndexOf(dict, win), field_size);
   72    -1 			win = [];
   73    -1 			if (dict.length >> field_size) {
   74    -1 				field_size += 1;
   75    -1 			}
   76    -1 			dict.push(tmp);
   77    -1 		} else {
   78    -1 			win = tmp;
   79    -1 			i += 1;
   80    -1 		}
   81    -1 	}
   82    -1 	buf.write(sIndexOf(dict, win), field_size);
   83    -1 	buf.write(sIndexOf(dict, 'end'), field_size);
   84    -1 
   85    -1 	return new Uint8Array(result);
   86    -1 };
   87    -1 
   88    -1 export var decompress = function(bytes) {
   89    -1 	var result = [];
   90    -1 	var buf = new Buffer(bytes);
   91    -1 	var prev = null;
   92    -1 
   93    -1 	var field_size = 9;
   94    -1 	var dict = [];
   95    -1 	dict.push('end');
   96    -1 	for (let i = 0; i < 256; i++) {
   97    -1 		dict.push([i]);
   98    -1 	}
   99    -1 
  100    -1 	while (true) {
  101    -1 		var index = buf.read(field_size);
  102    -1 		var value = dict[index];
  103    -1 		if (dict.length >> field_size) {
  104    -1 			field_size += 1;
  105    -1 		}
  106    -1 
  107    -1 		if (value === 'end') {
  108    -1 			break;
  109    -1 		}
  110    -1 
  111    -1 		// push to dict with one cycle delay because we need the first
  112    -1 		// item from the next entry.
  113    -1 		//
  114    -1 		// If value is undefined, the next entry is the not-yet-pushed one.
  115    -1 		// Fortunately, we know that its first item is the same as in the entry
  116    -1 		// before that.
  117    -1 		if (!value) {
  118    -1 			value = [...prev, prev[0]];
  119    -1 		}
  120    -1 		result = result.concat(value);
  121    -1 		if (prev) {
  122    -1 			dict.push([...prev, value[0]]);
  123    -1 		}
  124    -1 		prev = value;
  125    -1 	}
  126    -1 
  127    -1 	return new Uint8Array(result);
  128    -1 };

diff --git a/static/main.js b/static/main.js

@@ -1,26 +1,26 @@
    1     1 import * as base64 from './base64.js';
    2    -1 import * as lzw from './lzw.js';
   -1     2 import * as gzip from './gzip.js';
    3     3 
    4    -1 var encode = function(text) {
   -1     4 var encode = async function(text) {
    5     5 	var encoder = new TextEncoder();
    6     6 	var bytes = encoder.encode(text);
    7    -1 	return base64.encode(lzw.compress(bytes));
   -1     7 	return base64.encode(await gzip.compress(bytes));
    8     8 };
    9     9 
   10    -1 var decode = function(string) {
   -1    10 var decode = async function(string) {
   11    11 	var decoder = new TextDecoder();
   12    -1 	var bytes = lzw.decompress(base64.decode(string));
   -1    12 	var bytes = await gzip.decompress(base64.decode(string));
   13    13 	return decoder.decode(bytes);
   14    14 };
   15    15 
   16    16 var textarea = document.querySelector('textarea');
   17    17 
   18    -1 try {
   19    -1 	textarea.value = decode(location.hash.substr(1));
   20    -1 } catch (e) {
   21    -1 	console.exception(e);
   22    -1 }
   -1    18 decode(location.hash.substr(1)).then(text => {
   -1    19 	textarea.value = text;
   -1    20 });
   23    21 
   24    22 textarea.addEventListener('input', event => {
   25    -1 	history.replaceState(null, '', '#' + encode(textarea.value));
   -1    23 	encode(textarea.value).then(data => {
   -1    24 		history.replaceState(null, '', `#${data}`);
   -1    25 	});
   26    26 });