diff --git a/CHANGELOG.md b/CHANGELOG.md index db302d901ac30dba3e8f90f1dfd9157ed24fa60e..da5f9bd6840bc7fcc006aebf7536e58e9c8838e9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ Note that since we don't clearly distinguish between a public and private interf - Fix handling of mmcif with empty ``label_*`` fields - Add LoadTrajectory action - Add Zenodo import extension (load structures, trajectories, and volumes) +- Fix loading of some compressed files within sessions ## [v3.3.1] - 2022-02-27 diff --git a/src/mol-plugin-state/manager/snapshots.ts b/src/mol-plugin-state/manager/snapshots.ts index 698764e4608a32bf1898334e3d41a2178e7596b8..1b9f6cc33b6badd8ac8f9a9d2c2c0b8af4e205f8 100644 --- a/src/mol-plugin-state/manager/snapshots.ts +++ b/src/mol-plugin-state/manager/snapshots.ts @@ -238,12 +238,12 @@ class PluginStateSnapshotManager extends StatefulPluginComponent<{ } } else { const data = await this.plugin.runTask(readFromFile(file, 'zip')); - const assets = Object.create(null); + const assetData = Object.create(null); objectForEach(data, (v, k) => { if (k === 'state.json' || k === 'assets.json') return; const name = k.substring(k.indexOf('/') + 1); - assets[name] = new File([v], name); + assetData[name] = v; }); const stateFile = new File([data['state.json']], 'state.json'); const stateData = await this.plugin.runTask(readFromFile(stateFile, 'string')); @@ -253,7 +253,7 @@ class PluginStateSnapshotManager extends StatefulPluginComponent<{ const json = JSON.parse(await this.plugin.runTask(readFromFile(file, 'string'))); for (const [id, asset] of json) { - this.plugin.managers.asset.set(asset, assets[id]); + this.plugin.managers.asset.set(asset, new File([assetData[id]], asset.name)); } } diff --git a/src/mol-util/data-source.ts b/src/mol-util/data-source.ts index 794c2e4d4e8040e7e6f9e2cb0780f1c387eb4de3..265bfaa804aac3ef1f1e85775ae3a549831895ec 100644 --- a/src/mol-util/data-source.ts +++ b/src/mol-util/data-source.ts @@ -130,13 +130,15 @@ function getCompression(name: string) { DataCompressionMethod.None; } +const reFilterPath = /^(__MACOSX|.DS_Store)/; + async function decompress(ctx: RuntimeContext, data: Uint8Array, compression: DataCompressionMethod): Promise<Uint8Array> { switch (compression) { case DataCompressionMethod.None: return data; case DataCompressionMethod.Gzip: return ungzip(ctx, data); case DataCompressionMethod.Zip: const parsed = await unzip(ctx, data.buffer); - const names = Object.keys(parsed); + const names = Object.keys(parsed).filter(n => !reFilterPath.test(n)); if (names.length !== 1) throw new Error('can only decompress zip files with a single entry'); return parsed[names[0]] as Uint8Array; } diff --git a/src/mol-util/zip/zip.ts b/src/mol-util/zip/zip.ts index b81bccf49d8c6b31ba263a903c8c417e17c78a09..ea838f5c3f5707c0384d4ba6f9ea9bf834cf1116 100644 --- a/src/mol-util/zip/zip.ts +++ b/src/mol-util/zip/zip.ts @@ -1,5 +1,5 @@ /** - * Copyright (c) 2020 mol* contributors, licensed under MIT, See LICENSE file for more info. + * Copyright (c) 2020-2022 mol* contributors, licensed under MIT, See LICENSE file for more info. * * @author Alexander Rose <alexander.rose@weirdbyte.de> * @@ -15,6 +15,10 @@ import { _inflate } from './inflate'; import { _deflateRaw } from './deflate'; import { RuntimeContext, Task } from '../../mol-task'; +export function Unzip(buf: ArrayBuffer, onlyNames = false) { + return Task.create('Unzip', ctx => unzip(ctx, buf, onlyNames)); +} + export async function unzip(runtime: RuntimeContext, buf: ArrayBuffer, onlyNames = false) { const out: { [k: string]: Uint8Array | { size: number, csize: number } } = Object.create(null); const data = new Uint8Array(buf);