diff --git a/CHANGELOG.md b/CHANGELOG.md
index ae352128..af2026dd 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,7 +4,7 @@
* ADDED: Translations for Swedish & Persian
* CHANGED: Deduplicate JSON error message translations
* CHANGED: Refactored translation of exception messages
-* CHANGED: Upgrading libraries to: DOMpurify 3.3.2, ip-lib 1.22.0 & polyfill-php80 1.33.0
+* CHANGED: Upgrading libraries to: DOMpurify 3.3.2, ip-lib 1.22.0, polyfill-php80 1.33.0 & zlib 1.3.2
* FIXED: Some exceptions not getting translated
* FIXED: Attachment disappears after a "paste" in the message area (#1731)
* FIXED: The content format is not reset when creating a new document (#1707)
diff --git a/js/common.js b/js/common.js
index 36b5cdaa..c360eef4 100644
--- a/js/common.js
+++ b/js/common.js
@@ -10,7 +10,7 @@ global.WebCrypto = require('@peculiar/webcrypto').Crypto;
// application libraries to test
global.$ = global.jQuery = require('./jquery-3.7.1');
-global.zlib = require('./zlib-1.3.1-2').zlib;
+global.zlib = require('./zlib').zlib;
require('./prettify');
global.prettyPrint = window.PR.prettyPrint;
global.prettyPrintOne = window.PR.prettyPrintOne;
diff --git a/js/zlib-1.3.1.wasm b/js/zlib-1.3.1.wasm
deleted file mode 100644
index 2fbc9169..00000000
Binary files a/js/zlib-1.3.1.wasm and /dev/null differ
diff --git a/js/zlib-1.3.2.mjs b/js/zlib-1.3.2.mjs
new file mode 100644
index 00000000..b4997f84
--- /dev/null
+++ b/js/zlib-1.3.2.mjs
@@ -0,0 +1,2 @@
+async function Module(moduleArg={}){var moduleRtn;var Module=moduleArg;var ENVIRONMENT_IS_WEB=!!globalThis.window;var ENVIRONMENT_IS_WORKER=!!globalThis.WorkerGlobalScope;var ENVIRONMENT_IS_NODE=globalThis.process?.versions?.node&&globalThis.process?.type!="renderer";if(ENVIRONMENT_IS_NODE){const{createRequire}=await import("node:module");var require=createRequire(import.meta.url)}var arguments_=[];var thisProgram="./this.program";var quit_=(status,toThrow)=>{throw toThrow};var _scriptName=import.meta.url;var scriptDirectory="";function locateFile(path){if(Module["locateFile"]){return Module["locateFile"](path,scriptDirectory)}return scriptDirectory+path}var readAsync,readBinary;if(ENVIRONMENT_IS_NODE){var fs=require("node:fs");if(_scriptName.startsWith("file:")){scriptDirectory=require("node:path").dirname(require("node:url").fileURLToPath(_scriptName))+"/"}readBinary=filename=>{filename=isFileURI(filename)?new URL(filename):filename;var ret=fs.readFileSync(filename);return ret};readAsync=async(filename,binary=true)=>{filename=isFileURI(filename)?new URL(filename):filename;var ret=fs.readFileSync(filename,binary?undefined:"utf8");return ret};if(process.argv.length>1){thisProgram=process.argv[1].replace(/\\/g,"/")}arguments_=process.argv.slice(2);quit_=(status,toThrow)=>{process.exitCode=status;throw toThrow}}else if(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER){try{scriptDirectory=new URL(".",_scriptName).href}catch{}{if(ENVIRONMENT_IS_WORKER){readBinary=url=>{var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.responseType="arraybuffer";xhr.send(null);return new Uint8Array(xhr.response)}}readAsync=async url=>{if(isFileURI(url)){return new Promise((resolve,reject)=>{var xhr=new XMLHttpRequest;xhr.open("GET",url,true);xhr.responseType="arraybuffer";xhr.onload=()=>{if(xhr.status==200||xhr.status==0&&xhr.response){resolve(xhr.response);return}reject(xhr.status)};xhr.onerror=reject;xhr.send(null)})}var response=await fetch(url,{credentials:"same-origin"});if(response.ok){return response.arrayBuffer()}throw new Error(response.status+" : "+response.url)}}}else{}var out=console.log.bind(console);var err=console.error.bind(console);var wasmBinary;var ABORT=false;var isFileURI=filename=>filename.startsWith("file://");var readyPromiseResolve,readyPromiseReject;var HEAP8,HEAPU8,HEAP16,HEAPU16,HEAP32,HEAPU32,HEAPF32,HEAPF64;var HEAP64,HEAPU64;var runtimeInitialized=false;function updateMemoryViews(){var b=wasmMemory.buffer;HEAP8=new Int8Array(b);HEAP16=new Int16Array(b);Module["HEAPU8"]=HEAPU8=new Uint8Array(b);HEAPU16=new Uint16Array(b);HEAP32=new Int32Array(b);HEAPU32=new Uint32Array(b);HEAPF32=new Float32Array(b);HEAPF64=new Float64Array(b);HEAP64=new BigInt64Array(b);HEAPU64=new BigUint64Array(b)}function preRun(){if(Module["preRun"]){if(typeof Module["preRun"]=="function")Module["preRun"]=[Module["preRun"]];while(Module["preRun"].length){addOnPreRun(Module["preRun"].shift())}}callRuntimeCallbacks(onPreRuns)}function initRuntime(){runtimeInitialized=true;wasmExports["d"]()}function postRun(){if(Module["postRun"]){if(typeof Module["postRun"]=="function")Module["postRun"]=[Module["postRun"]];while(Module["postRun"].length){addOnPostRun(Module["postRun"].shift())}}callRuntimeCallbacks(onPostRuns)}function abort(what){Module["onAbort"]?.(what);what="Aborted("+what+")";err(what);ABORT=true;what+=". Build with -sASSERTIONS for more info.";var e=new WebAssembly.RuntimeError(what);readyPromiseReject?.(e);throw e}var wasmBinaryFile;function findWasmBinary(){if(Module["locateFile"]){return locateFile("zlib.wasm")}return new URL("zlib.wasm",import.meta.url).href}function getBinarySync(file){if(file==wasmBinaryFile&&wasmBinary){return new Uint8Array(wasmBinary)}if(readBinary){return readBinary(file)}throw"both async and sync fetching of the wasm failed"}async function getWasmBinary(binaryFile){if(!wasmBinary){try{var response=await readAsync(binaryFile);return new Uint8Array(response)}catch{}}return getBinarySync(binaryFile)}async function instantiateArrayBuffer(binaryFile,imports){try{var binary=await getWasmBinary(binaryFile);var instance=await WebAssembly.instantiate(binary,imports);return instance}catch(reason){err(`failed to asynchronously prepare wasm: ${reason}`);abort(reason)}}async function instantiateAsync(binary,binaryFile,imports){if(!binary&&!isFileURI(binaryFile)&&!ENVIRONMENT_IS_NODE){try{var response=fetch(binaryFile,{credentials:"same-origin"});var instantiationResult=await WebAssembly.instantiateStreaming(response,imports);return instantiationResult}catch(reason){err(`wasm streaming compile failed: ${reason}`);err("falling back to ArrayBuffer instantiation")}}return instantiateArrayBuffer(binaryFile,imports)}function getWasmImports(){var imports={a:wasmImports};return imports}async function createWasm(){function receiveInstance(instance,module){wasmExports=instance.exports;assignWasmExports(wasmExports);updateMemoryViews();return wasmExports}function receiveInstantiationResult(result){return receiveInstance(result["instance"])}var info=getWasmImports();if(Module["instantiateWasm"]){return new Promise((resolve,reject)=>{Module["instantiateWasm"](info,(inst,mod)=>{resolve(receiveInstance(inst,mod))})})}wasmBinaryFile??=findWasmBinary();var result=await instantiateAsync(wasmBinary,wasmBinaryFile,info);var exports=receiveInstantiationResult(result);return exports}class ExitStatus{name="ExitStatus";constructor(status){this.message=`Program terminated with exit(${status})`;this.status=status}}var callRuntimeCallbacks=callbacks=>{while(callbacks.length>0){callbacks.shift()(Module)}};var onPostRuns=[];var addOnPostRun=cb=>onPostRuns.push(cb);var onPreRuns=[];var addOnPreRun=cb=>onPreRuns.push(cb);var noExitRuntime=true;var abortOnCannotGrowMemory=requestedSize=>{abort("OOM")};var _emscripten_resize_heap=requestedSize=>{var oldSize=HEAPU8.length;requestedSize>>>=0;abortOnCannotGrowMemory(requestedSize)};{if(Module["noExitRuntime"])noExitRuntime=Module["noExitRuntime"];if(Module["print"])out=Module["print"];if(Module["printErr"])err=Module["printErr"];if(Module["wasmBinary"])wasmBinary=Module["wasmBinary"];if(Module["arguments"])arguments_=Module["arguments"];if(Module["thisProgram"])thisProgram=Module["thisProgram"];if(Module["preInit"]){if(typeof Module["preInit"]=="function")Module["preInit"]=[Module["preInit"]];while(Module["preInit"].length>0){Module["preInit"].shift()()}}}function writeToJs(ptr,dst,size){const o=Module.map[ptr];if(o&&typeof o.onData==="function"){o.onData(Module.HEAPU8.subarray(dst,dst+size))}else{console.error("No handler found for pointer:",ptr)}}var __malloc,__free,__createDeflateContext,__deflate,__freeDeflateContext,__createInflateContext,__inflate,__freeInflateContext,memory,__indirect_function_table,wasmMemory;function assignWasmExports(wasmExports){__malloc=Module["__malloc"]=wasmExports["e"];__free=Module["__free"]=wasmExports["f"];__createDeflateContext=Module["__createDeflateContext"]=wasmExports["g"];__deflate=Module["__deflate"]=wasmExports["h"];__freeDeflateContext=Module["__freeDeflateContext"]=wasmExports["i"];__createInflateContext=Module["__createInflateContext"]=wasmExports["j"];__inflate=Module["__inflate"]=wasmExports["k"];__freeInflateContext=Module["__freeInflateContext"]=wasmExports["l"];memory=wasmMemory=wasmExports["c"];__indirect_function_table=wasmExports["__indirect_function_table"]}var wasmImports={b:_emscripten_resize_heap,a:writeToJs};function run(){preRun();function doRun(){Module["calledRun"]=true;if(ABORT)return;initRuntime();readyPromiseResolve?.(Module);Module["onRuntimeInitialized"]?.();postRun()}if(Module["setStatus"]){Module["setStatus"]("Running...");setTimeout(()=>{setTimeout(()=>Module["setStatus"](""),1);doRun()},1)}else{doRun()}}var wasmExports;wasmExports=await (createWasm());run();if(runtimeInitialized){moduleRtn=Module}else{moduleRtn=new Promise((resolve,reject)=>{readyPromiseResolve=resolve;readyPromiseReject=reject})}
+;return moduleRtn}export default Module;
diff --git a/js/zlib-1.3.2.wasm b/js/zlib-1.3.2.wasm
new file mode 100644
index 00000000..7c5b0674
Binary files /dev/null and b/js/zlib-1.3.2.wasm differ
diff --git a/js/zlib-1.3.1-2.js b/js/zlib.js
similarity index 58%
rename from js/zlib-1.3.1-2.js
rename to js/zlib.js
index 3e38c3ea..c59b620b 100644
--- a/js/zlib-1.3.1-2.js
+++ b/js/zlib.js
@@ -9,37 +9,22 @@
const COMPRESSION_LEVEL = 7;
const NO_ZLIB_HEADER = -1;
const CHUNK_SIZE = 32 * 1024;
- const map = {};
- const memory = new WebAssembly.Memory({
- initial: 1,
- maximum: 1024, // 64MB
- });
- const env = {
- memory,
- writeToJs(ptr, size) {
- const o = map[ptr];
- o.onData(new Uint8Array(memory.buffer, dstPtr, size));
- },
- _abort: errno => { console.error(`Error: ${errno}`) },
- _grow: () => { },
- };
- const ins = (await WebAssembly.instantiateStreaming(fetch('js/zlib-1.3.1.wasm'), { env })).instance;
-
- const srcPtr = ins.exports._malloc(CHUNK_SIZE);
- const dstPtr = ins.exports._malloc(CHUNK_SIZE);
+ const Module = await import('zlib-1.3.2.mjs');
+ Module.map = {};
+ const srcPtr = Module.__malloc(CHUNK_SIZE);
+ const dstPtr = Module.__malloc(CHUNK_SIZE);
class RawDef {
constructor() {
- this.zstreamPtr = ins.exports._createDeflateContext(COMPRESSION_LEVEL, NO_ZLIB_HEADER);
- map[this.zstreamPtr] = this;
+ this.zstreamPtr = Module.__createDeflateContext(COMPRESSION_LEVEL, NO_ZLIB_HEADER);
+ Module.map[this.zstreamPtr] = this;
this.offset = 0;
this.buff = new Uint8Array(CHUNK_SIZE);
}
deflate(chunk, flush) {
- const src = new Uint8Array(memory.buffer, srcPtr, chunk.length);
- src.set(chunk);
- ins.exports._deflate(this.zstreamPtr, srcPtr, dstPtr, chunk.length, CHUNK_SIZE, flush);
+ Module.HEAPU8.set(chunk, srcPtr);
+ Module.__deflate(this.zstreamPtr, srcPtr, dstPtr, chunk.length, CHUNK_SIZE, flush);
}
onData(chunk) {
@@ -53,32 +38,27 @@
}
destroy() {
- ins.exports._freeDeflateContext(this.zstreamPtr);
- delete map[this.zstreamPtr];
+ Module.__freeDeflateContext(this.zstreamPtr);
+ delete Module.map[this.zstreamPtr];
this.buff = null;
}
getBuffer() {
- const res = new Uint8Array(this.offset);
- for (let i = 0; i < this.offset; ++i) {
- res[i] = this.buff[i];
- }
- return res;
+ return Buffer.from(this.buff.buffer, 0, this.offset);
}
}
class RawInf {
constructor() {
- this.zstreamPtr = ins.exports._createInflateContext(NO_ZLIB_HEADER);
- map[this.zstreamPtr] = this;
+ this.zstreamPtr = Module.__createInflateContext(NO_ZLIB_HEADER);
+ Module.map[this.zstreamPtr] = this;
this.offset = 0;
this.buff = new Uint8Array(CHUNK_SIZE);
}
inflate(chunk) {
- const src = new Uint8Array(memory.buffer, srcPtr, chunk.length);
- src.set(chunk);
- ins.exports._inflate(this.zstreamPtr, srcPtr, dstPtr, chunk.length, CHUNK_SIZE);
+ Module.HEAPU8.set(chunk, srcPtr);
+ Module.__inflate(this.zstreamPtr, srcPtr, dstPtr, chunk.length, CHUNK_SIZE);
}
onData(chunk) {
@@ -92,17 +72,13 @@
}
destroy() {
- ins.exports._freeInflateContext(this.zstreamPtr);
- delete map[this.zstreamPtr];
+ Module.__freeInflateContext(this.zstreamPtr);
+ delete Module.map[this.zstreamPtr];
this.buff = null;
}
getBuffer() {
- const res = new Uint8Array(this.offset);
- for (let i = 0; i < this.offset; ++i) {
- res[i] = this.buff[i];
- }
- return res;
+ return Buffer.from(this.buff.buffer, 0, this.offset);
}
}
diff --git a/lib/Configuration.php b/lib/Configuration.php
index 950cf069..1395048b 100644
--- a/lib/Configuration.php
+++ b/lib/Configuration.php
@@ -125,7 +125,8 @@ class Configuration
'js/privatebin.js' => 'sha512-6SwOJniNN8RBmAK7yCt4ly2qYyH8OALxB74/K1AJgw+YnZgRCfTDVq1qY1K5Y2QCxCODGGTpAjTqQRExzCqV7g==',
'js/purify-3.3.2.js' => 'sha512-I6igPVpf3xNghG92mujwqB6Zi3LpUTsni4bRuLnMThEGH6BDbsumv7373+AXHzA4OUlxGsym8ZxKFHy4xjYvkQ==',
'js/showdown-2.1.0.js' => 'sha512-WYXZgkTR0u/Y9SVIA4nTTOih0kXMEd8RRV6MLFdL6YU8ymhR528NLlYQt1nlJQbYz4EW+ZsS0fx1awhiQJme1Q==',
- 'js/zlib-1.3.1-2.js' => 'sha512-4gT+v+BkBqdVBbKOO4qKGOAzuay+v1FmOLksS+bMgQ08Oo4xEb3X48Xq1Kv2b4HtiCQA7xq9dFRzxal7jmQI7w==',
+ 'js/zlib-1.3.2.mjs' => 'sha512-rv8vIHS886FB1BwNSDK2ePuAlQ2kjuCKyKfu6R6xrUaBW74XJwUkgBkYwb2Qo48JGcfenzJuJWnj7aunxXkyIw==',
+ 'js/zlib.js' => 'sha512-WrCFRc7+7FdFDhN86LQ0g8GHzwhGIqPJ29NBGu2xM3cqkCC9GSMZf/24dhg6+iQs1xjcnWjandBFIOP7xCBUpg==',
),
);
diff --git a/lib/View.php b/lib/View.php
index 514ac2b1..14b3d852 100644
--- a/lib/View.php
+++ b/lib/View.php
@@ -62,6 +62,49 @@ class View
include $path;
}
+ /**
+ * get cache buster query string
+ *
+ * if the file isn't versioned (ends in a digit), adds our own version as a query string
+ *
+ * @access private
+ * @param string $file
+ */
+ private function _getCacheBuster($file)
+ {
+ //
+ if ((bool) preg_match('#[0-9]\.m?js$#', (string) $file)) {
+ return '';
+ }
+ return '?' . rawurlencode($this->_variables['VERSION']);
+ }
+
+ /**
+ * get SRI hash for given file
+ *
+ * @access private
+ * @param string $file
+ */
+ private function _getSri($file)
+ {
+ if (array_key_exists($file, $this->_variables['SRI'])) {
+ return ' integrity="' . $this->_variables['SRI'][$file] . '"';
+ }
+ return '';
+ }
+
+ /**
+ * echo module preload link tag incl. SRI hash for given script file
+ *
+ * @access private
+ * @param string $file
+ */
+ private function _linkTag($file)
+ {
+ echo '_getSri($file), ' />', PHP_EOL;
+ }
+
/**
* echo script tag incl. SRI hash for given script file
*
@@ -71,13 +114,9 @@ class View
*/
private function _scriptTag($file, $attributes = '')
{
- $sri = array_key_exists($file, $this->_variables['SRI']) ?
- ' integrity="' . $this->_variables['SRI'][$file] . '"' : '';
- // if the file isn't versioned (ends in a digit), add our own version
- $cacheBuster = (bool) preg_match('#[0-9]\.js$#', (string) $file) ?
- '' : '?' . rawurlencode($this->_variables['VERSION']);
echo '', PHP_EOL;
+ ' type="text/javascript" data-cfasync="false" src="', $file,
+ $this->_getCacheBuster($file), '"', $this->_getSri($file),
+ ' crossorigin="anonymous">', PHP_EOL;
}
}
diff --git a/tpl/bootstrap.php b/tpl/bootstrap.php
index 283c84ab..64b1eae9 100644
--- a/tpl/bootstrap.php
+++ b/tpl/bootstrap.php
@@ -42,6 +42,7 @@ if ($SYNTAXHIGHLIGHTING) :
endif;
?>
+ _linkTag('js/zlib-1.3.2.mjs'); ?>
_scriptTag('js/jquery-3.7.1.js', 'defer'); ?>
- _scriptTag('js/zlib-1.3.1-2.js', 'defer'); ?>
+ _scriptTag('js/zlib.js', 'defer'); ?>
_scriptTag('js/base-x-5.0.1.js', 'defer'); ?>
_scriptTag('js/bootstrap-3.4.1.js', 'defer'); ?>
+ _linkTag('js/zlib-1.3.2.mjs'); ?>
_scriptTag('js/jquery-3.7.1.js', 'defer'); ?>
- _scriptTag('js/zlib-1.3.1-2.js', 'defer'); ?>
+ _scriptTag('js/zlib.js', 'defer'); ?>
_scriptTag('js/base-x-5.0.1.js', 'defer'); ?>
_scriptTag('js/bootstrap-5.3.8.js', 'defer'); ?>
_scriptTag('js/dark-mode-switch.js', 'defer'); ?>
diff --git a/tst/Bootstrap.php b/tst/Bootstrap.php
index ea83e791..0c24da89 100644
--- a/tst/Bootstrap.php
+++ b/tst/Bootstrap.php
@@ -341,7 +341,7 @@ class Helper
*/
public static function updateSubresourceIntegrity(): void
{
- foreach (new GlobIterator(PATH . 'js' . DIRECTORY_SEPARATOR . '*.js') as $file) {
+ foreach (new GlobIterator(PATH . 'js' . DIRECTORY_SEPARATOR . '*.*js') as $file) {
if ($file->getBasename() === 'common.js' || $file->getBasename() === 'eslint.config.js') {
continue; // ignore JS unit test bootstrap
}