ソースを参照

Update zip.js

Lutz Roeder 4 年 前
コミット
2999fc4f30
1 ファイル変更57 行追加48 行削除
  1. 57 48
      source/zip.js

+ 57 - 48
source/zip.js

@@ -7,57 +7,67 @@ zip.Archive = class {
 
     static open(buffer) {
         const stream = buffer instanceof Uint8Array ? new zip.BinaryReader(buffer) : buffer;
-        if (stream.length > 2 && stream.peek(1)[0] === 0x78) { // zlib
-            return new zlib.Archive(stream);
-        }
-        const signature = [ 0x50, 0x4B, 0x01, 0x02 ];
-        if (stream.length > 4 && stream.peek(2).every((value, index) => value === signature[index])) {
-            return new zip.Archive(stream);
-        }
-        return null;
-    }
-
-    constructor(stream) {
-        this._entries = [];
-        const position = stream.position;
-        const lookup = (stream, signature) => {
-            let position = stream.length;
-            do {
-                position = Math.max(0, position - 64000);
-                stream.seek(position);
-                const buffer = stream.read(Math.min(stream.length - position, 65536));
-                for (let i = buffer.length - 4; i >= 0; i--) {
-                    if (signature[0] === buffer[i] && signature[1] === buffer[i + 1] && signature[2] === buffer[i + 2] && signature[3] === buffer[i + 3]) {
-                        stream.seek(position + i + 4);
-                        return true;
+        if (stream.length > 2) {
+            const buffer = stream.peek(2);
+            if (buffer[0] === 0x78) { // zlib
+                return new zlib.Archive(stream);
+            }
+            const signature = buffer[0] === 0x50 && buffer[1] === 0x4B;
+            const position = stream.position;
+            const seek = (content) => {
+                let position = stream.length;
+                do {
+                    position = Math.max(0, position - 66000);
+                    stream.seek(position);
+                    const length = Math.min(stream.length - position, 66000 + 4);
+                    const buffer = stream.read(length);
+                    for (let i = buffer.length - 4; i >= 0; i--) {
+                        if (content[0] === buffer[i] && content[1] === buffer[i + 1] && content[2] === buffer[i + 2] && content[3] === buffer[i + 3]) {
+                            stream.seek(position + i + 4);
+                            return true;
+                        }
                     }
                 }
+                while (position > 0 && signature);
+                return false;
+            };
+            if (!seek([ 0x50, 0x4B, 0x05, 0x06 ])) {
+                stream.seek(position);
+                if (!signature) {
+                    return null;
+                }
+                throw new zip.Error('End of Zip central directory not found.');
             }
-            while (position > 0);
-            return false;
-        };
-        if (!lookup(stream, [ 0x50, 0x4B, 0x05, 0x06 ])) {
-            throw new zip.Error('End of Zip central directory not found.');
-        }
-        let reader = new zip.BinaryReader(stream.read(16));
-        reader.skip(12);
-        let offset = reader.uint32(); // central directory offset
-        if (offset > stream.length) {
-            if (!lookup(stream, [ 0x50, 0x4B, 0x06, 0x06 ])) {
-                throw new zip.Error('Zip64 end of central directory not found.');
+            const reader = new zip.BinaryReader(stream.read(16));
+            reader.skip(12);
+            let offset = reader.uint32(); // central directory offset
+            if (offset > stream.length) {
+                if (!seek([ 0x50, 0x4B, 0x06, 0x06 ])) {
+                    stream.seek(position);
+                    throw new zip.Error('End of Zip64 central directory not found.');
+                }
+                const reader = new zip.BinaryReader(stream.read(52));
+                reader.skip(44);
+                offset = reader.uint32();
+                if (reader.uint32() !== 0) {
+                    stream.seek(position);
+                    throw new zip.Error('Zip 64-bit central directory offset not supported.');
+                }
             }
-            reader = new zip.BinaryReader(stream.read(52));
-            reader.skip(44);
-            offset = reader.uint32();
-            if (reader.uint32() !== 0) {
-                throw new zip.Error('Zip 64-bit central directory offset not supported.');
+            if (offset > stream.length) {
+                stream.seek(position);
+                throw new zip.Error('Invalid Zip central directory offset.');
             }
+            stream.seek(offset);
+            const archive = new zip.Archive(stream);
+            stream.seek(position);
+            return archive;
         }
-        if (offset > stream.length) {
-            throw new zip.Error('Invalid Zip central directory offset.');
-        }
-        stream.seek(offset); // central directory offset
+        return null;
+    }
 
+    constructor(stream) {
+        this._entries = [];
         const entries = [];
         const signature = [ 0x50, 0x4B, 0x01, 0x02 ];
         while (stream.position + 4 < stream.length && stream.read(4).every((value, index) => value === signature[index])) {
@@ -130,7 +140,6 @@ zip.Archive = class {
             }
             this._entries.push(new zip.Entry(stream, entry));
         }
-        stream.seek(position);
     }
 
     get entries() {
@@ -156,14 +165,13 @@ zip.Entry = class {
         this._name = decoder.decode(entry.nameBuffer);
         this._stream = stream.stream(entry.compressedSize);
         switch (entry.compressionMethod) {
-            case 0: { // Stored
+            case 0: { // stored
                 if (entry.size !== entry.compressedSize) {
                     throw new zip.Error('Invalid compression size.');
                 }
                 break;
             }
-            case 8: {
-                // Deflate
+            case 8: { // deflate
                 this._stream = new zip.InflaterStream(this._stream, entry.size);
                 break;
             }
@@ -696,6 +704,7 @@ zip.Error = class extends Error {
     constructor(message) {
         super(message);
         this.name = 'Zip Error';
+        this.stack = undefined;
     }
 };