I'm trying to load a specific JNLP file from a Java program and get its .jar files. I've downloaded the .pack.gz files (because it uses compressing), but now I can't unpack them. I'm trying it by using the class java.util.jar.Pack200.Unpacker, but it throws an Exception with the following information:
SEVERE: null
java.io.IOException: Corrupted pack file: magic/ver = 1F8B0800/0.0 should be CAFED00D/150.7 OR CAFED00D/160.1 OR CAFED00D/170.1 OR CAFED00D/171.0
at com.sun.java.util.jar.pack.NativeUnpack.start(Native Method)
at com.sun.java.util.jar.pack.NativeUnpack.run(NativeUnpack.java:198)
at com.sun.java.util.jar.pack.NativeUnpack.run(NativeUnpack.java:247)
at com.sun.java.util.jar.pack.UnpackerImpl.unpack(UnpackerImpl.java:138)
at com.sun.java.util.jar.pack.UnpackerImpl.unpack(UnpackerImpl.java:174)
at rmiattack.Util.loadJNLP(Util.java:186)
at rmiattack.RmiAttack.debugFunction(RmiAttack.java:50)
at rmiattack.RmiAttack.main(RmiAttack.java:74)
I've looked for that error and then I tried to unpack the file with the command "unpack200" and it works. Then I tried to find the unpack200 sources in the openjdk project, but I didn't found them. So, could anyone tell me where can I find those sources to know how to use the Unpacker class? I'm attaching the code I'm using:
public static void loadJNLP(String file, String outDir) throws IOException, ParserConfigurationException, SAXException {
byte[] encoded = Files.readAllBytes(Paths.get(file));
Document document = stringToXML(new String(encoded, Charset.defaultCharset()), false);
System.out.println(document.getElementsByTagName("title").item(0));
String baseURL = document.getElementsByTagName("jnlp").item(0).getAttributes().getNamedItem("codebase").getTextContent();
int i;
NodeList nodeList = document.getElementsByTagName("jar");
Unpacker unpacker = Pack200.newUnpacker();
SortedMap<String,String> properties = unpacker.properties();
properties.entrySet().stream().forEach((entry) -> {
System.out.println(entry.getKey() + " - " + entry.getValue());
});
for (i = 0; i < nodeList.getLength(); i++) {
//This can be threaded
NamedNodeMap attributes = nodeList.item(i).getAttributes();
String fileName = attributes.getNamedItem("href").getTextContent().replace(".jar", "") + "__V" + attributes.getNamedItem("version").getTextContent() + ".jar.pack.gz";
File packedJar = new File(outDir + '/' + fileName); //File path to download packed jar
FileUtils.copyURLToFile(new URL(baseURL + '/' + fileName), packedJar); //Download packed jar
FileOutputStream fileOutputStream = new FileOutputStream(outDir+'/'+attributes.getNamedItem("href").getTextContent()); //Save jar without version
try (JarOutputStream jarOutputStream = new JarOutputStream(fileOutputStream)) {
unpacker.unpack(packedJar, jarOutputStream);
} finally {
fileOutputStream.close();
}
packedJar.delete();
}
System.out.println("Save to " + outDir);
}
The output before the exception is this:
[title: null]
com.sun.java.util.jar.pack.class.format.error - pass
com.sun.java.util.jar.pack.default.timezone - false
com.sun.java.util.jar.pack.disable.native - false
com.sun.java.util.jar.pack.verbose - 0
pack.class.attribute.CompilationID - RUH
pack.class.attribute.SourceID - RUH
pack.code.attribute.CharacterRangeTable - NH[PHPOHIIH]
pack.code.attribute.CoverageTable - NH[PHHII]
pack.deflate.hint - keep
pack.effort - 5
pack.keep.file.order - true
pack.modification.time - keep
pack.segment.limit - -1
pack.unknown.attribute - pass
Thanks in advance.
Edit: Thanks to @Thorbjoern comment I've solved it. I just had to uncompress files and then unpack them. File code looks like this:
public static void loadJNLP(String file, String outDir) throws IOException, ParserConfigurationException, SAXException {
byte[] encoded = Files.readAllBytes(Paths.get(file));
Document document = stringToXML(new String(encoded, Charset.defaultCharset()), false);
System.out.println(document.getElementsByTagName("title").item(0));
String baseURL = document.getElementsByTagName("jnlp").item(0).getAttributes().getNamedItem("codebase").getTextContent();
int i;
int length;
byte[] buffer = new byte[1024];
NodeList nodeList = document.getElementsByTagName("jar");
Unpacker unpacker = Pack200.newUnpacker();
for (i = 0; i < nodeList.getLength(); i++) {
//This can be threaded
NamedNodeMap attributes = nodeList.item(i).getAttributes();
String fileName = attributes.getNamedItem("href").getTextContent().replace(".jar", "") + "__V" + attributes.getNamedItem("version").getTextContent() + ".jar";
File compressedPackedIn = new File(outDir + '/' + fileName + ".pack.gz"); //File path to download compressed packed jar
FileUtils.copyURLToFile(new URL(baseURL + '/' + fileName + ".pack.gz"), compressedPackedIn); //Download packed jar
FileOutputStream uncompressedPackedOut;
try (GZIPInputStream compressed = new GZIPInputStream(new FileInputStream(outDir + '/' + fileName + ".pack.gz"))) {
uncompressedPackedOut = new FileOutputStream(outDir + '/' + fileName + ".pack");
//http://www.mkyong.com/java/how-to-decompress-file-from-gzip-file/
while ((length = compressed.read(buffer))> 0) {
uncompressedPackedOut.write(buffer, 0, length);
}
}
uncompressedPackedOut.close();
File uncompressedPackedIn = new File(outDir + '/' + fileName + ".pack");
FileOutputStream uncompressedUnpacked = new FileOutputStream(outDir + '/' + fileName);
try (JarOutputStream jarOutputStream = new JarOutputStream(uncompressedUnpacked)) {
unpacker.unpack(uncompressedPackedIn, jarOutputStream);
} finally {
uncompressedUnpacked.close();
}
compressedPackedIn.delete();
uncompressedPackedIn.delete();
}
}