Skip to content

Commit 36d2e89

Browse files
ctruedenclaude
andcommitted
Detect archive format by magic bytes when extension is missing
The micro.mamba.pm server stopped redirecting to versioned URLs like micromamba-2.5.0-2.tar.bz2 and now serves files directly via GET with a Content-Disposition header. Since the download URL (/latest) has no file extension, the temp file landed with no extension, causing unpack() to throw "Unsupported archive type". Fix by falling back to magic byte detection (GZip: 1F 8B, BZip2: BZh, ZIP: PK) when the extension is absent or unrecognized. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
1 parent 30d9c88 commit 36d2e89

File tree

1 file changed

+34
-1
lines changed

1 file changed

+34
-1
lines changed

src/main/java/org/apposed/appose/util/Downloads.java

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,40 @@ public static void unpack(final File inputFile, final File outputDir) throws Fil
193193
else if (filename.endsWith(".tar.bz2")) unTarBz2(inputFile, outputDir);
194194
else if (filename.endsWith(".tar.gz")) unTarGz(inputFile, outputDir);
195195
else if (filename.endsWith(".zip")) unZip(inputFile, outputDir);
196-
else throw new IllegalArgumentException("Unsupported archive type for file: " + inputFile.getName());
196+
else unpackByMagicBytes(inputFile, outputDir);
197+
}
198+
199+
/**
200+
* Detects archive format from magic bytes and unpacks accordingly.
201+
* Used when the file extension is missing or unrecognized (e.g. when the
202+
* server serves the file directly without a redirect to a named URL).
203+
*
204+
* @param inputFile the archive file to detect and unpack
205+
* @param outputDir the output directory
206+
* @throws IOException if an I/O error occurs or the format is unrecognized
207+
* @throws InterruptedException if the thread is interrupted
208+
*/
209+
private static void unpackByMagicBytes(final File inputFile, final File outputDir) throws IOException, InterruptedException {
210+
byte[] magic = new byte[6];
211+
try (InputStream is = new BufferedInputStream(new FileInputStream(inputFile))) {
212+
int read = is.read(magic);
213+
if (read < 2) throw new IOException("File too small to detect archive type: " + inputFile.getName());
214+
}
215+
// GZip magic: 1F 8B
216+
if (magic[0] == (byte)0x1F && magic[1] == (byte)0x8B) {
217+
unTarGz(inputFile, outputDir);
218+
}
219+
// BZip2 magic: 42 5A 68 ("BZh")
220+
else if (magic[0] == (byte)0x42 && magic[1] == (byte)0x5A && magic[2] == (byte)0x68) {
221+
unTarBz2(inputFile, outputDir);
222+
}
223+
// ZIP magic: 50 4B 03 04 ("PK\x03\x04")
224+
else if (magic[0] == (byte)0x50 && magic[1] == (byte)0x4B && magic[2] == (byte)0x03 && magic[3] == (byte)0x04) {
225+
unZip(inputFile, outputDir);
226+
}
227+
else {
228+
throw new IllegalArgumentException("Unsupported archive type for file: " + inputFile.getName());
229+
}
197230
}
198231

199232
/**

0 commit comments

Comments
 (0)