From 9d5f51f513b8f0d5559d881d4cd797c16029b8aa Mon Sep 17 00:00:00 2001 From: Alexander Rose <alexander.rose@weirdbyte.de> Date: Sun, 6 Mar 2022 17:32:32 -0800 Subject: [PATCH] improve handling of compressed files - fix loading of some compressed files within sessions - ignore some hidden MACOSX files --- CHANGELOG.md | 1 + src/mol-plugin-state/manager/snapshots.ts | 6 +++--- src/mol-util/data-source.ts | 4 +++- src/mol-util/zip/zip.ts | 6 +++++- 4 files changed, 12 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index db302d901..da5f9bd68 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 698764e46..1b9f6cc33 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 794c2e4d4..265bfaa80 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 b81bccf49..ea838f5c3 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); -- GitLab