Skip to content

Commit e9da18b

Browse files
Proposal: Opening/Closing Mechanism for Zip Files
The Eclipse IDE has no built in functionality to open Zip Files and read or manipulate their content. Because of this, other operations like searching inside of Zip Files or comparing two Zip Files were also not possible. This pull request introduces a mechanism for handling Zip Files within the Eclipse workspace, enhancing the functionality to read and write Zip files. The primary goal is to provide a seamless experience for developers working with zip archives directly within Eclipse. Zip files must be opened manually within the workspace by using the new command "Open Zip File" in the menu when right clicking the zip file. It is also possible to open nested zip files. Zip Files are opened by replacing the file in the workspace with a linked folder that reads and writes the Zip File in the file system. By closing the Zip FIle, the linked folder will be deleted and the file can be seen in the workspace again. Please note that only ZIP Archives are supported in this current implementation. Other archive types can be added in future improvements. Also linked Zip Files can not be opened with this implementation because the Zip File must be local. An additional PR for the repository **eclipse.platform.ui** that grants access to the open/close mechanism for zip files over UI can be found in the following: eclipse-platform/eclipse.platform.ui#1947 Co-Authored-By: David Erdös <David.Erdoes@vector.com>
1 parent a5bbdf4 commit e9da18b

File tree

37 files changed

+2303
-569
lines changed

37 files changed

+2303
-569
lines changed
19 Bytes
Binary file not shown.
469 Bytes
Binary file not shown.

resources/bundles/org.eclipse.core.filesystem/plugin.xml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,11 @@
1616
<run class="org.eclipse.core.internal.filesystem.NullFileSystem"/>
1717
</filesystem>
1818
</extension>
19+
<extension
20+
id="org.eclipse.core.filesystem.zip"
21+
point="org.eclipse.core.filesystem.filesystems">
22+
<filesystem scheme="zip">
23+
<run class="org.eclipse.core.internal.filesystem.zip.ZipFileSystem"/>
24+
</filesystem>
25+
</extension>
1926
</plugin>
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
/*******************************************************************************
2+
* Copyright (c) 2024 Vector Informatik GmbH and others.
3+
*
4+
* This program and the accompanying materials are made available under the terms of the Eclipse
5+
* Public License 2.0 which accompanies this distribution, and is available at
6+
* https://www.eclipse.org/legal/epl-2.0/
7+
*
8+
* SPDX-License-Identifier: EPL-2.0
9+
*
10+
* Contributors: Vector Informatik GmbH - initial API and implementation
11+
*******************************************************************************/
12+
13+
package org.eclipse.core.filesystem;
14+
15+
import java.io.IOException;
16+
import java.io.InputStream;
17+
import java.net.URI;
18+
import java.nio.ByteBuffer;
19+
import java.nio.ByteOrder;
20+
import java.util.Set;
21+
import org.eclipse.core.internal.filesystem.zip.ZipFileStore;
22+
import org.eclipse.core.runtime.CoreException;
23+
24+
/**
25+
* Utility class to determine if a file is an archive based on file header information.
26+
* This class checks for known file signatures to identify if a given file is a ZIP archive
27+
* or a format based on ZIP, such as EPUB, JAR, ODF, and OOXML.
28+
*
29+
* @since 1.11
30+
*/
31+
public class ZipFileUtil {
32+
33+
// Initializes known archive file signatures from Wikipedia's list of file signatures in the following order:
34+
// 1. Standard ZIP file, 2. Empty archive, 3. Spanned archive
35+
// (https://en.wikipedia.org/wiki/List_of_file_signatures)
36+
private static final Set<Integer> ARCHIVE_FILE_SIGNATURES = Set.of(0x504B0304, 0x504B0506, 0x504B0708);
37+
38+
/**
39+
* Determines if the given {@link IFileStore} represents an open ZIP file.
40+
* This can be used to check if operations on a ZIP file should be allowed or handled differently.
41+
*
42+
* @param store The file store to check.
43+
* @return true if the store is an instance of {@link ZipFileStore}, false otherwise.
44+
*/
45+
public static boolean isInsideOpenZipFile(IFileStore store) {
46+
return store instanceof ZipFileStore;
47+
}
48+
49+
public static boolean isInsideOpenZipFile(URI locationURI) {
50+
IFileStore store;
51+
try {
52+
store = EFS.getStore(locationURI);
53+
} catch (CoreException e) {
54+
return false;
55+
}
56+
return isInsideOpenZipFile(store);
57+
}
58+
59+
//TODO Implement this method
60+
public static boolean isOpenZipFile(IFileStore store) {
61+
if (isInsideOpenZipFile(store)) {
62+
ZipFileStore zipStore = (ZipFileStore) store;
63+
return zipStore.getPath().isEmpty(); //if path is empty its the root
64+
}
65+
return false;
66+
}
67+
68+
public static boolean isOpenZipFile(URI locationURI) {
69+
IFileStore store;
70+
try {
71+
store = EFS.getStore(locationURI);
72+
} catch (CoreException e) {
73+
return false;
74+
}
75+
return isOpenZipFile(store);
76+
}
77+
78+
public static boolean isNested(URI fileURI) {
79+
if (fileURI.getScheme().contains("zip")) { //$NON-NLS-1$
80+
return true;
81+
}
82+
return false;
83+
}
84+
85+
/**
86+
* Checks if the provided {@link InputStream} represents a ZIP archive
87+
* by reading its first four bytes and comparing them against known ZIP file signatures.
88+
* This method throws {@link IOException} if the file signature does not match any known ZIP archive signatures.
89+
*
90+
* @param fis The {@link InputStream} of the file to check.
91+
* @throws IOException If the file signature does not match known ZIP archive signatures
92+
* or an I/O error occurs during reading from the stream.
93+
*/
94+
public static void checkFileForZipHeader(InputStream fis) throws IOException {
95+
byte[] bytes = new byte[4];
96+
if (fis.read(bytes) == bytes.length) {
97+
ByteBuffer buffer = ByteBuffer.wrap(bytes).order(ByteOrder.BIG_ENDIAN);
98+
int header = buffer.getInt();
99+
100+
if (!ARCHIVE_FILE_SIGNATURES.contains(header)) {
101+
throw new IOException("Invalid archive file signature."); // Throws IOException if header is not recognized //$NON-NLS-1$
102+
}
103+
} else {
104+
// Handle the case where not enough bytes are read
105+
throw new IOException("Could not read enough data to check ZIP file header."); //$NON-NLS-1$
106+
}
107+
}
108+
}

0 commit comments

Comments
 (0)