You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@flex.apache.org by cd...@apache.org on 2016/07/27 17:24:06 UTC
git commit: [flex-utilities] [refs/heads/feature/flash-downloader] -
- Implement a Flash auto downloader
Repository: flex-utilities
Updated Branches:
refs/heads/feature/flash-downloader [created] cf75f0e01
- Implement a Flash auto downloader
Project: http://git-wip-us.apache.org/repos/asf/flex-utilities/repo
Commit: http://git-wip-us.apache.org/repos/asf/flex-utilities/commit/cf75f0e0
Tree: http://git-wip-us.apache.org/repos/asf/flex-utilities/tree/cf75f0e0
Diff: http://git-wip-us.apache.org/repos/asf/flex-utilities/diff/cf75f0e0
Branch: refs/heads/feature/flash-downloader
Commit: cf75f0e014a29d1c354f3f33b339a60f3d180b0f
Parents: e5c3d36
Author: Christofer Dutz <ch...@codecentric.de>
Authored: Wed Jul 27 19:23:50 2016 +0200
Committer: Christofer Dutz <ch...@codecentric.de>
Committed: Wed Jul 27 19:23:50 2016 +0200
----------------------------------------------------------------------
flex-maven-tools/flex-sdk-converter/cli/pom.xml | 5 +
.../converter/core/SdkConverterCLI.java | 14 +-
flex-maven-tools/flex-sdk-converter/pom.xml | 4 +-
.../retrievers/download/pom.xml | 25 ++
.../retrievers/download/DownloadRetriever.java | 81 +++++
.../retrievers/download/utils/DmgExtractor.java | 319 +++++++++++++++++++
.../download/utils/utils/ApplePartitionMap.java | 197 ++++++++++++
.../utils/utils/DmgBlockChunkEntry.java | 96 ++++++
.../utils/utils/DmgPropertyListMishBlock.java | 101 ++++++
.../download/utils/utils/DmgTrailer.java | 158 +++++++++
.../download/utils/utils/DmgUdifChecksum.java | 42 +++
.../download/utils/utils/DriverDescriptor.java | 38 +++
.../utils/utils/DriverDescriptorMap.java | 85 +++++
.../download/utils/utils/HFSPlusExtent.java | 40 +++
.../download/utils/utils/HFSPlusForkData.java | 59 ++++
.../utils/utils/HFSPlusVolumeHeader.java | 217 +++++++++++++
.../download/utils/utils/HFSVolumeFactory.java | 24 ++
.../download/utils/utils/HFSVolumeHeader.java | 13 +
.../download/utils/utils/IHFSVolumeHeader.java | 10 +
19 files changed, 1520 insertions(+), 8 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/cf75f0e0/flex-maven-tools/flex-sdk-converter/cli/pom.xml
----------------------------------------------------------------------
diff --git a/flex-maven-tools/flex-sdk-converter/cli/pom.xml b/flex-maven-tools/flex-sdk-converter/cli/pom.xml
index 7176ed1..095617f 100644
--- a/flex-maven-tools/flex-sdk-converter/cli/pom.xml
+++ b/flex-maven-tools/flex-sdk-converter/cli/pom.xml
@@ -104,6 +104,11 @@
<version>3.3.2</version>
</dependency>
<dependency>
+ <groupId>commons-io</groupId>
+ <artifactId>commons-io</artifactId>
+ <version>2.4</version>
+ </dependency>
+ <dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>1.7.7</version>
http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/cf75f0e0/flex-maven-tools/flex-sdk-converter/cli/src/main/java/org/apache/flex/utilities/converter/core/SdkConverterCLI.java
----------------------------------------------------------------------
diff --git a/flex-maven-tools/flex-sdk-converter/cli/src/main/java/org/apache/flex/utilities/converter/core/SdkConverterCLI.java b/flex-maven-tools/flex-sdk-converter/cli/src/main/java/org/apache/flex/utilities/converter/core/SdkConverterCLI.java
index 8cf0522..eb85d70 100644
--- a/flex-maven-tools/flex-sdk-converter/cli/src/main/java/org/apache/flex/utilities/converter/core/SdkConverterCLI.java
+++ b/flex-maven-tools/flex-sdk-converter/cli/src/main/java/org/apache/flex/utilities/converter/core/SdkConverterCLI.java
@@ -301,12 +301,14 @@ public class SdkConverterCLI {
String flashVersions = cmd.getOptionValue(OPTION_FLASH_VERSIONS, "");
if(!flashVersions.isEmpty()) {
- for(String flashVersion : flashVersions.split(",")) {
- System.out.println("- Downloading Flash SDK version: " + flashVersion +
- " to directory: " + fdkDir.getAbsolutePath());
- File flashDownloadDiretory = retriever.retrieve(SdkType.FLASH, flashVersion);
- // Integrate the download into the FDK directory.
- mergeDirectories(flashDownloadDiretory, fdkDir);
+ for(PlatformType platformType : platforms) {
+ for (String flashVersion : flashVersions.split(",")) {
+ System.out.println("- Downloading Flash SDK version: " + flashVersion +
+ " to directory: " + fdkDir.getAbsolutePath());
+ File flashDownloadDirectory = retriever.retrieve(SdkType.FLASH, flashVersion, platformType);
+ // Integrate the download into the FDK directory.
+ mergeDirectories(flashDownloadDirectory, fdkDir);
+ }
}
}
http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/cf75f0e0/flex-maven-tools/flex-sdk-converter/pom.xml
----------------------------------------------------------------------
diff --git a/flex-maven-tools/flex-sdk-converter/pom.xml b/flex-maven-tools/flex-sdk-converter/pom.xml
index 81109d9..f044a18 100644
--- a/flex-maven-tools/flex-sdk-converter/pom.xml
+++ b/flex-maven-tools/flex-sdk-converter/pom.xml
@@ -71,8 +71,8 @@
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
- <source>1.5</source>
- <target>1.5</target>
+ <source>1.6</source>
+ <target>1.6</target>
<encoding>${project.build.sourceEncoding}</encoding>
</configuration>
</plugin>
http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/cf75f0e0/flex-maven-tools/flex-sdk-converter/retrievers/download/pom.xml
----------------------------------------------------------------------
diff --git a/flex-maven-tools/flex-sdk-converter/retrievers/download/pom.xml b/flex-maven-tools/flex-sdk-converter/retrievers/download/pom.xml
index ffa2665..bfb3cbf 100644
--- a/flex-maven-tools/flex-sdk-converter/retrievers/download/pom.xml
+++ b/flex-maven-tools/flex-sdk-converter/retrievers/download/pom.xml
@@ -44,6 +44,31 @@
</dependency>
<dependency>
+ <groupId>commons-io</groupId>
+ <artifactId>commons-io</artifactId>
+ <version>2.4</version>
+ </dependency>
+
+ <!-- 7Zip with JNI Wrapper to call it from Java -->
+ <dependency>
+ <groupId>net.sf.sevenzipjbinding</groupId>
+ <artifactId>sevenzipjbinding</artifactId>
+ <version>9.20-2.00beta</version>
+ </dependency>
+ <dependency>
+ <groupId>net.sf.sevenzipjbinding</groupId>
+ <artifactId>sevenzipjbinding-all-platforms</artifactId>
+ <version>9.20-2.00beta</version>
+ </dependency>
+ <!--dependency>
+ <groupId>org.catacombae</groupId>
+ <artifactId>dmgextractor</artifactId>
+ <version>0.7</version>
+ <scope>system</scope>
+ <systemPath>${basedir}/libs/dmgextractor-0_70-standalone.jar</systemPath>
+ </dependency-->
+
+ <dependency>
<groupId>org.mock-server</groupId>
<artifactId>mockserver-netty</artifactId>
<version>RELEASE</version>
http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/cf75f0e0/flex-maven-tools/flex-sdk-converter/retrievers/download/src/main/java/org/apache/flex/utilities/converter/retrievers/download/DownloadRetriever.java
----------------------------------------------------------------------
diff --git a/flex-maven-tools/flex-sdk-converter/retrievers/download/src/main/java/org/apache/flex/utilities/converter/retrievers/download/DownloadRetriever.java b/flex-maven-tools/flex-sdk-converter/retrievers/download/src/main/java/org/apache/flex/utilities/converter/retrievers/download/DownloadRetriever.java
index 6843d17..e1570e7 100644
--- a/flex-maven-tools/flex-sdk-converter/retrievers/download/src/main/java/org/apache/flex/utilities/converter/retrievers/download/DownloadRetriever.java
+++ b/flex-maven-tools/flex-sdk-converter/retrievers/download/src/main/java/org/apache/flex/utilities/converter/retrievers/download/DownloadRetriever.java
@@ -16,6 +16,10 @@
*/
package org.apache.flex.utilities.converter.retrievers.download;
+import net.sf.sevenzipjbinding.ArchiveFormat;
+import net.sf.sevenzipjbinding.IInArchive;
+import net.sf.sevenzipjbinding.SevenZip;
+import net.sf.sevenzipjbinding.impl.RandomAccessFileInStream;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.apache.flex.utilities.converter.api.ProxySettings;
@@ -129,6 +133,7 @@ public class DownloadRetriever extends BaseRetriever {
////////////////////////////////////////////////////////////////////////////////
if (type.equals(SdkType.FLASH)) {
+ // Initialize the framework libs.
final File targetDirectory = new File(targetFile.getParent(),
targetFile.getName().substring(0, targetFile.getName().lastIndexOf(".") - 1));
final File libDestFile = new File(targetDirectory, "frameworks/libs/player/" + version +
@@ -139,6 +144,58 @@ public class DownloadRetriever extends BaseRetriever {
}
}
FileUtils.moveFile(targetFile, libDestFile);
+
+ ///////////////////////////////////////////////////////////////
+ // Download the Flash projector for the given flash version
+ // NOTE: This is not part of the official Flex SDK !!!
+ ///////////////////////////////////////////////////////////////
+
+ // Initialize the runtime resources.
+ String executableName = (platformType == PlatformType.WINDOWS) ? "flashplayer.exe" : "flashplayer";
+ final File runtimeDestFile = new File(targetDirectory, "runtimes/flash/" + platformType.name() +
+ "/" + version + "/" + executableName);
+ final String majorVersion = version.contains(".") ?
+ version.substring(0, version.indexOf(".")) : version;
+
+ // The urls for downloading are:
+ // https://fpdownload.macromedia.com/pub/flashplayer/updaters/19/flashplayer_19_sa_debug.exe
+ // https://fpdownload.macromedia.com/pub/flashplayer/updaters/19/flashplayer_19_sa_debug.dmg
+ // https://fpdownload.macromedia.com/pub/flashplayer/updaters/11/flashplayer_11_sa_debug.i386.tar.gz
+ String flashplayerUrl = "https://fpdownload.macromedia.com/pub/flashplayer/updaters/" +
+ majorVersion + "/flashplayer_" + majorVersion + "_sa_debug";
+ String fileEnding = "";
+ switch (platformType) {
+ case LINUX:
+ fileEnding = ".i386.tar.gz";
+ break;
+ case MAC:
+ fileEnding = ".dmg";
+ break;
+ case WINDOWS:
+ fileEnding = ".exe";
+ break;
+ }
+ flashplayerUrl += fileEnding;
+ final File runtimeTargetFile = File.createTempFile("FlashRuntime-" + version + "-" + platformType +
+ "-", fileEnding);
+ performFastDownload(new URL(flashplayerUrl), runtimeTargetFile);
+
+ // The Windows version of the download is executable directly, for all others
+ // we have to unpack the downloaded archive and extract the content.
+ if(platformType != PlatformType.WINDOWS) {
+ extractArchive(runtimeTargetFile, new File(runtimeTargetFile.getParentFile(), runtimeTargetFile.getName()));
+ switch (platformType) {
+ case LINUX:
+ extractArchive(runtimeTargetFile, new File(runtimeTargetFile.getParentFile(), runtimeTargetFile.getName()));
+ break;
+ case MAC:
+ extractArchive(runtimeTargetFile, new File(runtimeTargetFile.getParentFile(), runtimeTargetFile.getName()));
+ break;
+ }
+ }
+
+
+
return targetDirectory;
} else {
System.out.println("Extracting archive to temp directory.");
@@ -499,4 +556,28 @@ public class DownloadRetriever extends BaseRetriever {
}
return result;
}
+
+ protected void extractArchive(File archive, File targetDirectory) throws RetrieverException {
+
+ }
+
+ public static void main(String[] args) throws Exception {
+ String[] upargs = new String[] {"/Users/christoferdutz/Downloads/install_flash_player_18_osx.dmg", "/Users/christoferdutz/Temp/unpack/test.img"};
+
+ IInArchive archive;
+ RandomAccessFile randomAccessFile;
+
+ randomAccessFile = new RandomAccessFile(new File("/Users/christoferdutz/Downloads/install_flash_player_18_osx.dmg"), "r");
+
+ archive = SevenZip.openInArchive(ArchiveFormat.ISO, // null - autodetect
+ new RandomAccessFileInStream(
+ randomAccessFile));
+
+ int numberOfItems = archive.getNumberOfItems();
+
+ archive.close();
+ randomAccessFile.close();
+
+ System.out.println(numberOfItems);
+ }
}
http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/cf75f0e0/flex-maven-tools/flex-sdk-converter/retrievers/download/src/main/java/org/apache/flex/utilities/converter/retrievers/download/utils/DmgExtractor.java
----------------------------------------------------------------------
diff --git a/flex-maven-tools/flex-sdk-converter/retrievers/download/src/main/java/org/apache/flex/utilities/converter/retrievers/download/utils/DmgExtractor.java b/flex-maven-tools/flex-sdk-converter/retrievers/download/src/main/java/org/apache/flex/utilities/converter/retrievers/download/utils/DmgExtractor.java
new file mode 100644
index 0000000..8c4b768
--- /dev/null
+++ b/flex-maven-tools/flex-sdk-converter/retrievers/download/src/main/java/org/apache/flex/utilities/converter/retrievers/download/utils/DmgExtractor.java
@@ -0,0 +1,319 @@
+package org.apache.flex.utilities.converter.retrievers.download.utils;
+
+import org.apache.commons.compress.compressors.bzip2.BZip2CompressorInputStream;
+import org.apache.commons.io.input.NullInputStream;
+import org.apache.flex.utilities.converter.retrievers.download.utils.utils.*;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NodeList;
+import org.xml.sax.SAXException;
+
+import javax.xml.bind.DatatypeConverter;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.transform.OutputKeys;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+import javax.xml.xpath.XPath;
+import javax.xml.xpath.XPathConstants;
+import javax.xml.xpath.XPathExpressionException;
+import javax.xml.xpath.XPathFactory;
+import java.io.*;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
+/**
+ * Tool to read and unpack a dmg image. Based upon the format description at:
+ * http://newosxbook.com/DMG.html
+ *
+ * HFSleuth> fs flashplayer_20_sa_debug.dmg
+ * KOLY header found at 14457517:
+ * UDIF version 4, Header Size: 512
+ * Flags:1
+ * Rsrc fork: None
+ * Data fork: from 0, spanning 14444891 bytes
+ * XML plist: from 14444891, spanning 12626 bytes (to 14457517)
+ * Segment #: 1, Count: 1
+ * Segment UUID: 8a7e1df1-6648ad9f-78cb06a4-2c5be967
+ * Running Data fork offset 0
+ * Sectors: 70816
+ * Apple_HFS detected
+ * Found Terminator in last block. Good
+ * decompression done - Writing to /tmp/decompressed.dmg..
+ * processBTree: Node kind 0, 0 records - should be kind 1, 3 records - but it isn't!
+ * node is 0
+ * RC was 0
+ *
+ * Created by christoferdutz on 24.02.16.
+ */
+public class DmgExtractor {
+
+ // Hex for "koly", which are the DMG magic bytes.
+ private static final byte[] DMG_TRAILER_MAGIC_BYTES = {0x6B, 0x6F, 0x6C, 0x79};
+
+ public File extract(File inputFile) {
+ try {
+ // Try to find the DMG trailer.
+ // (A header containing the metadata, but located at the end)
+ DmgTrailer dmgTrailer = findDmgTrailer(inputFile);
+ if(dmgTrailer != null) {
+ float sizeInMegabytes = dmgTrailer.getDataForkLength() / (1024 * 1024);
+ System.out.println(" - Preparing to extract " + sizeInMegabytes + " MB");
+
+ // Read the property-list Xml document in the DMG file.
+ List<DmgPropertyListMishBlock> mishBlocks = getPropertyList(inputFile, dmgTrailer);
+
+ byte[] buffer = new byte[1024];
+ int blockCounter = 0;
+ for(DmgPropertyListMishBlock mishBlock : mishBlocks) {
+ System.out.println(" - Processing block: " + blockCounter + " - " + mishBlock.getBlockName());
+ int chunkCounter = 0;
+ for(DmgBlockChunkEntry blockChunkEntry : mishBlock.getBlockChunkEntries()) {
+ System.out.println(" - Processing chunk: " + chunkCounter + " - " + blockChunkEntry.toString());
+ FileInputStream fis = new FileInputStream(inputFile);
+
+ try {
+ // Position the read head at the beginning of this entry.
+ fis.skip(mishBlock.getDataOffset() + blockChunkEntry.getCompressedOffset());
+
+ // Depending on the chunk entry type, process the input data.
+ InputStream is = null;
+ switch (blockChunkEntry.getEntryType()) {
+ case 0x00000000:
+ //entryTypeName = "Zero-Fill";
+ is = new NullInputStream(blockChunkEntry.getCompressedLength());
+ break;
+ case 0x00000001:
+ //entryTypeName = "UDRW/UDRO - RAW or NULL compression (uncompressed)";
+ is = fis;
+ break;
+ case 0x00000002:
+ //entryTypeName = "Ignored/unknown";
+ // TODO: Implement
+ break;
+ case 0x80000004:
+ //entryTypeName = "UDCO - Apple Data Compression (ADC)";
+ // TODO: Implement
+ break;
+ case 0x80000005:
+ //entryTypeName = "UDZO - zLib data compression";
+ // TODO: Implement
+ break;
+ case 0x80000006:
+ //entryTypeName = "UDBZ - bz2lib data compression";
+ is = new BZip2CompressorInputStream(fis);
+ break;
+ case 0x7ffffffe:
+ //entryTypeName = "No blocks - Comment: +beg and +end";
+ // TODO: Implement
+ default:
+ }
+
+ if (is != null) {
+ // Read the data into a byte-buffer.
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ int n;
+ while ((n = is.read(buffer)) != -1) {
+ baos.write(buffer, 0, n);
+ }
+
+ System.out.println(" - Number of sectors: " + blockChunkEntry.getSectorCount() +
+ " sector size: " + (baos.size() / blockChunkEntry.getSectorCount()));
+
+ ByteArrayInputStream bis = new ByteArrayInputStream(baos.toByteArray());
+ DataInputStream dis = new DataInputStream(bis);
+ // Depending on the type, process the data in the buffer.
+ if (mishBlock.getBlockName().contains("Driver Descriptor Map")) {
+ DriverDescriptorMap driverDescriptorMap = new DriverDescriptorMap(dis);
+ System.out.println(" - " + driverDescriptorMap.toString());
+ }
+ if (mishBlock.getBlockName().contains("Apple_partition_map")) {
+ List<ApplePartitionMap> partitionMaps =
+ new ArrayList<ApplePartitionMap>((int) blockChunkEntry.getSectorCount());
+ for(int i = 0; i < blockChunkEntry.getSectorCount(); i++) {
+ try {
+ ApplePartitionMap partitionMap = new ApplePartitionMap(dis);
+ System.out.println(" - Partition " + i + " - " +
+ partitionMap.getTypeOfPartition() + " - " +
+ partitionMap.toString());
+ partitionMaps.add(partitionMap);
+ } catch(Exception e) {
+ break;
+ }
+ }
+ }
+ // See: https://en.wikipedia.org/wiki/Hierarchical_File_System
+ else if (mishBlock.getBlockName().contains("Apple_HFS")) {
+ // Block 0 and 1 contain the boot blocks (each 512 bytes)
+ // We need to skip these.
+ // TODO: Eventually implement.
+ dis.skipBytes(1024);
+ System.out.println(" - Skipped boot block (0 and 1)");
+ // Block 2 contains the master directory block
+ // TODO: Actually this could also be a normal HFS volume ...
+ IHFSVolumeHeader iHfsVolumeHeader = HFSVolumeFactory.readHfsVolumeHeader(dis);
+ System.out.println(" - " + iHfsVolumeHeader.toString());
+ // In the old HFS format the third block contains the volume
+ // bitmap, in HFS+ this is located as a normal file in the volume.
+ if(iHfsVolumeHeader instanceof HFSVolumeHeader) {
+ HFSVolumeHeader hfsVolumeHeader = (HFSVolumeHeader) iHfsVolumeHeader;
+ // Block 3 contains the volume bitmap
+ // (one bit represents the usage of one block)
+ // https://en.wikipedia.org/wiki/Hierarchical_File_System
+ /*int volumeBitmapSize = hfsVolumeHeader.getTotalBlocks() / 8;
+ byte[] volumeBitmap = new byte[volumeBitmapSize];
+ dis.read(volumeBitmap);
+ System.out.println(volumeBitmap);*/
+ }
+ else if(iHfsVolumeHeader instanceof HFSPlusVolumeHeader) {
+ HFSPlusVolumeHeader hfsPlusVolumeHeader =
+ (HFSPlusVolumeHeader) iHfsVolumeHeader;
+ // https://en.wikipedia.org/wiki/HFS_Plus
+ // http://pages.cs.wisc.edu/~legault/miniproj-736.pdf
+ }
+ }
+ chunkCounter++;
+ }
+ } catch(IOException ioe) {
+ ioe.printStackTrace();
+ } finally {
+ try {
+ fis.close();
+ } catch(IOException e) {
+ // Ignore
+ }
+ }
+ }
+ blockCounter++;
+ }
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ } catch (ParserConfigurationException e) {
+ e.printStackTrace();
+ } catch (SAXException e) {
+ e.printStackTrace();
+ } catch (XPathExpressionException e) {
+ e.printStackTrace();
+ }
+ return null;
+ }
+
+ private DmgTrailer findDmgTrailer(File inputFile) throws IOException {
+ long startTime = new Date().getTime();
+
+ RandomAccessFile raf = new RandomAccessFile(inputFile, "r");
+ // The size of the DMG trailer is 512 bytes. As it's located at the
+ // end of the file there is no use starting to search for it from the
+ // beginning. So we read a block that's slightly bigger than the
+ // trailer and search for the magic words in this block.
+ long curBlockStartPosition = raf.length() - 600;
+ long dmgTrailerPosition = -1;
+ do {
+ // Position the read "head".
+ raf.seek(curBlockStartPosition);
+
+ // Read a block of 600 bytes.
+ byte[] curBlock = new byte[600];
+ raf.read(curBlock);
+
+ // Scan the current block for the magic bytes.
+ int curMagicWordPosition = 0;
+ for (int curBlockPosition = 0; curBlockPosition < 600; curBlockPosition++) {
+ if (curBlock[curBlockPosition] == DMG_TRAILER_MAGIC_BYTES[curMagicWordPosition]) {
+ curMagicWordPosition++;
+ } else {
+ curMagicWordPosition = 0;
+ }
+ if (curMagicWordPosition == 4) {
+ // We are just comparing the last byte of the magic word
+ // so we only have to go back 3 bytes.
+ dmgTrailerPosition = curBlockStartPosition + (long) curBlockPosition - 3;
+ break;
+ }
+ }
+
+ // If we were in the first block, quit searching.
+ if(curBlockStartPosition == 0) {
+ break;
+ }
+ // We shift the search box back, but keep 4 bytes of overlap
+ // just in case the magic word was at the boundary of the block.
+ // This way we will be able to read it in the next pass.
+ curBlockStartPosition = Math.max(0, curBlockStartPosition - 596);
+ } while(dmgTrailerPosition == -1);
+ long endTime = new Date().getTime();
+ System.out.println("Found DMG trailer at position " + dmgTrailerPosition + " in " + (endTime - startTime) + "ms");
+
+ // Read and parse the trailer data.
+ if(dmgTrailerPosition != -1) {
+ raf.seek(dmgTrailerPosition);
+ byte[] dmgTrailerData = new byte[512];
+ raf.read(dmgTrailerData);
+ return new DmgTrailer(dmgTrailerData);
+ }
+
+ return null;
+ }
+
+ private List<DmgPropertyListMishBlock> getPropertyList(File inputFile, DmgTrailer dmgTrailer) throws IOException,
+ ParserConfigurationException, SAXException, XPathExpressionException {
+ // Read the block of bytes containing the property list data.
+ byte[] propertyListData = new byte[(int) dmgTrailer.getXmlLength()];
+ RandomAccessFile raf = new RandomAccessFile(inputFile, "r");
+ raf.seek(dmgTrailer.getXmlOffset());
+ raf.read(propertyListData);
+
+ // Parse the xml document data.
+ DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+ factory.setNamespaceAware(true);
+ DocumentBuilder builder = factory.newDocumentBuilder();
+ Document propertyListDoc = builder.parse(new ByteArrayInputStream(propertyListData));
+
+ try {
+ TransformerFactory tf = TransformerFactory.newInstance();
+ Transformer transformer = tf.newTransformer();
+ transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "no");
+ transformer.setOutputProperty(OutputKeys.METHOD, "xml");
+ transformer.setOutputProperty(OutputKeys.INDENT, "yes");
+ transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
+ transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4");
+
+ transformer.transform(new DOMSource(propertyListDoc),
+ new StreamResult(new OutputStreamWriter(System.out, "UTF-8")));
+ } catch(Exception e) {
+ // Ignore ...
+ }
+
+ List<DmgPropertyListMishBlock> mishBlocks = new ArrayList<DmgPropertyListMishBlock>();
+ XPath xPath = XPathFactory.newInstance().newXPath();
+ NodeList nodes = (NodeList) xPath.evaluate("//array/dict[key='CFName']/data",
+ propertyListDoc.getDocumentElement(), XPathConstants.NODESET);
+ for (int i = 0; i < nodes.getLength(); ++i) {
+ Element dataElement = (Element) nodes.item(i);
+ Element nameElement = (Element) dataElement.getPreviousSibling().getPreviousSibling()
+ .getPreviousSibling().getPreviousSibling();
+ byte[] dataBlock = DatatypeConverter.parseBase64Binary(dataElement.getTextContent());
+ DmgPropertyListMishBlock mishBlock = new DmgPropertyListMishBlock(nameElement.getTextContent(), dataBlock);
+ mishBlocks.add(mishBlock);
+ }
+ return mishBlocks;
+ }
+
+ public static void main(String[] args) throws Exception {
+ File input = new File("/Users/christoferdutz/Downloads/flashplayer_20_sa_debug.dmg");
+ DmgExtractor dmgExtractor = new DmgExtractor();
+ dmgExtractor.extract(input);
+ }
+
+ public static String getStringFromZeroTerminatedByteArray(byte[] data) {
+ int i;
+ for (i = 0; i < data.length && data[i] != 0; i++) { }
+ return new String(data, 0, i);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/cf75f0e0/flex-maven-tools/flex-sdk-converter/retrievers/download/src/main/java/org/apache/flex/utilities/converter/retrievers/download/utils/utils/ApplePartitionMap.java
----------------------------------------------------------------------
diff --git a/flex-maven-tools/flex-sdk-converter/retrievers/download/src/main/java/org/apache/flex/utilities/converter/retrievers/download/utils/utils/ApplePartitionMap.java b/flex-maven-tools/flex-sdk-converter/retrievers/download/src/main/java/org/apache/flex/utilities/converter/retrievers/download/utils/utils/ApplePartitionMap.java
new file mode 100644
index 0000000..07a7211
--- /dev/null
+++ b/flex-maven-tools/flex-sdk-converter/retrievers/download/src/main/java/org/apache/flex/utilities/converter/retrievers/download/utils/utils/ApplePartitionMap.java
@@ -0,0 +1,197 @@
+package org.apache.flex.utilities.converter.retrievers.download.utils.utils;
+
+import org.apache.flex.utilities.converter.retrievers.download.utils.DmgExtractor;
+
+import java.io.DataInputStream;
+import java.io.IOException;
+
+/**
+ * https://en.wikipedia.org/wiki/Apple_Partition_Map
+ *
+ * Created by christoferdutz on 25.02.16.
+ */
+public class ApplePartitionMap {
+
+ public static int STATUS_ENTRY_IS_VALID = 0x00000001;
+ public static int STATUS_ENTRY_IS_ALLOCATED = 0x00000002;
+ public static int STATUS_ENTRY_IN_USE = 0x00000004;
+ public static int STATUS_ENTRY_CONTAINS_BOOT_INFORMATION = 0x00000008;
+ public static int STATUS_PARTITION_IS_READABLE = 0x00000010;
+ public static int STATUS_PARTITION_IS_WRITABLE = 0x00000020;
+ public static int STATUS_BOOT_CODE_IS_POSITION_INDEPENDENT = 0x00000040;
+ public static int STATUS_PARTITION_CONTAINS_CHAIN_COMPATIBLE_DRIVER = 0x00000100;
+ public static int STATUS_PARTITION_CONTAINS_A_REAL_DRIVER = 0x00000200;
+ public static int STATUS_PARTITION_CONTAINS_A_CHAIN_DRIVER = 0x00000400;
+ public static int STATUS_AUTOMATICALLY_MOUNT_AT_STARTUP = 0x40000000;
+ public static int STATUS_THE_STARTUP_PARTITION = 0x80000000;
+
+ private int numPartitions;
+ private int startingSectorOfPartition;
+ private int sizeOfPartitionInSectors;
+ private String nameOfPartition;
+ private String typeOfPartition;
+ private int startingSectorOfDataAreaInPartition;
+ private int sizeOfDataAreaInPartitionInSectors;
+ private int statusOfPartition;
+ private int startingSectorOfBootCode;
+ private int sizeOfBootCodeInSectors;
+ private int addressOfBootloaderCode;
+ private int bootCodeEntryPoint;
+ private int bootCodeChecksum;
+ private String processorType;
+
+ public ApplePartitionMap(DataInputStream dis) {
+ // Initialize the fields by parsing the input bytes.
+ try {
+ if(dis.readShort() != 0x504D) {
+ throw new IllegalArgumentException("Invalid ApplePartitionMap data. Expected magic number 0x504D");
+ }
+ dis.skipBytes(2);
+ numPartitions = dis.readInt();
+ startingSectorOfPartition = dis.readInt();
+ sizeOfPartitionInSectors = dis.readInt();
+ byte[] buffer = new byte[32];
+ dis.read(buffer);
+ nameOfPartition = DmgExtractor.getStringFromZeroTerminatedByteArray(buffer);
+ buffer = new byte[32];
+ dis.read(buffer);
+ typeOfPartition = DmgExtractor.getStringFromZeroTerminatedByteArray(buffer);
+ startingSectorOfDataAreaInPartition = dis.readInt();
+ sizeOfDataAreaInPartitionInSectors = dis.readInt();
+ statusOfPartition = dis.readInt();
+ startingSectorOfBootCode = dis.readInt();
+ sizeOfBootCodeInSectors = dis.readInt();
+ addressOfBootloaderCode = dis.readInt();
+ dis.skipBytes(4);
+ bootCodeEntryPoint = dis.readInt();
+ dis.skipBytes(4);
+ bootCodeChecksum = dis.readInt();
+ buffer = new byte[16];
+ dis.read(buffer);
+ processorType = DmgExtractor.getStringFromZeroTerminatedByteArray(buffer);
+ dis.skipBytes(376);
+ } catch (IOException e) {
+ throw new IllegalArgumentException("Invalid DmgPropertyListMishBlock data.");
+ }
+ }
+
+ public int getNumPartitions() {
+ return numPartitions;
+ }
+
+ public int getStartingSectorOfPartition() {
+ return startingSectorOfPartition;
+ }
+
+ public int getSizeOfPartitionInSectors() {
+ return sizeOfPartitionInSectors;
+ }
+
+ public String getNameOfPartition() {
+ return nameOfPartition;
+ }
+
+ public String getTypeOfPartition() {
+ return typeOfPartition;
+ }
+
+ public int getStartingSectorOfDataAreaInPartition() {
+ return startingSectorOfDataAreaInPartition;
+ }
+
+ public int getSizeOfDataAreaInPartitionInSectors() {
+ return sizeOfDataAreaInPartitionInSectors;
+ }
+
+ public int getStatusOfPartition() {
+ return statusOfPartition;
+ }
+
+ public String getStatusOfPartitionName() {
+ StringBuilder sb = new StringBuilder();
+ if((statusOfPartition & STATUS_ENTRY_IS_VALID) != 0) {
+ sb.append(", Entry is valid");
+ }
+ if((statusOfPartition & STATUS_ENTRY_IS_ALLOCATED) != 0) {
+ sb.append(", Entry is allocated");
+ }
+ if((statusOfPartition & STATUS_ENTRY_IN_USE) != 0) {
+ sb.append(", Entry in use");
+ }
+ if((statusOfPartition & STATUS_ENTRY_CONTAINS_BOOT_INFORMATION) != 0) {
+ sb.append(", Entry contains boot information");
+ }
+ if((statusOfPartition & STATUS_PARTITION_IS_READABLE) != 0) {
+ sb.append(", Partition is readable");
+ }
+ if((statusOfPartition & STATUS_PARTITION_IS_WRITABLE) != 0) {
+ sb.append(", Partition is writable");
+ }
+ if((statusOfPartition & STATUS_BOOT_CODE_IS_POSITION_INDEPENDENT) != 0) {
+ sb.append(", Boot code is position independent");
+ }
+ if((statusOfPartition & STATUS_PARTITION_CONTAINS_CHAIN_COMPATIBLE_DRIVER) != 0) {
+ sb.append(", Partition contains chain-compatible driver");
+ }
+ if((statusOfPartition & STATUS_PARTITION_CONTAINS_A_REAL_DRIVER) != 0) {
+ sb.append(", Partition contains a real driver");
+ }
+ if((statusOfPartition & STATUS_PARTITION_CONTAINS_A_CHAIN_DRIVER) != 0) {
+ sb.append(", Partition contains a chain driver");
+ }
+ if((statusOfPartition & STATUS_AUTOMATICALLY_MOUNT_AT_STARTUP) != 0) {
+ sb.append(", Automatically mount at startup");
+ }
+ if((statusOfPartition & STATUS_THE_STARTUP_PARTITION) != 0) {
+ sb.append(", The startup partition");
+ }
+ if(sb.length() > 0) {
+ return sb.toString().substring(2);
+ }
+ return "- none -";
+ }
+
+ public int getStartingSectorOfBootCode() {
+ return startingSectorOfBootCode;
+ }
+
+ public int getSizeOfBootCodeInSectors() {
+ return sizeOfBootCodeInSectors;
+ }
+
+ public int getAddressOfBootloaderCode() {
+ return addressOfBootloaderCode;
+ }
+
+ public int getBootCodeEntryPoint() {
+ return bootCodeEntryPoint;
+ }
+
+ public int getBootCodeChecksum() {
+ return bootCodeChecksum;
+ }
+
+ public String getProcessorType() {
+ return processorType;
+ }
+
+ @Override
+ public String toString() {
+ return "ApplePartitionMap{" +
+ "numPartitions=" + numPartitions +
+ ", startingSectorOfPartition=" + startingSectorOfPartition +
+ ", sizeOfPartitionInSectors=" + sizeOfPartitionInSectors +
+ ", nameOfPartition='" + nameOfPartition + '\'' +
+ ", typeOfPartition='" + typeOfPartition + '\'' +
+ ", startingSectorOfDataAreaInPartition=" + startingSectorOfDataAreaInPartition +
+ ", sizeOfDataAreaInPartitionInSectors=" + sizeOfDataAreaInPartitionInSectors +
+ ", statusOfPartition=" + statusOfPartition +
+ ", startingSectorOfBootCode=" + startingSectorOfBootCode +
+ ", sizeOfBootCodeInSectors=" + sizeOfBootCodeInSectors +
+ ", addressOfBootloaderCode=" + addressOfBootloaderCode +
+ ", bootCodeEntryPoint=" + bootCodeEntryPoint +
+ ", bootCodeChecksum=" + bootCodeChecksum +
+ ", processorType='" + processorType + '\'' +
+ '}';
+ }
+}
http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/cf75f0e0/flex-maven-tools/flex-sdk-converter/retrievers/download/src/main/java/org/apache/flex/utilities/converter/retrievers/download/utils/utils/DmgBlockChunkEntry.java
----------------------------------------------------------------------
diff --git a/flex-maven-tools/flex-sdk-converter/retrievers/download/src/main/java/org/apache/flex/utilities/converter/retrievers/download/utils/utils/DmgBlockChunkEntry.java b/flex-maven-tools/flex-sdk-converter/retrievers/download/src/main/java/org/apache/flex/utilities/converter/retrievers/download/utils/utils/DmgBlockChunkEntry.java
new file mode 100644
index 0000000..58c4737
--- /dev/null
+++ b/flex-maven-tools/flex-sdk-converter/retrievers/download/src/main/java/org/apache/flex/utilities/converter/retrievers/download/utils/utils/DmgBlockChunkEntry.java
@@ -0,0 +1,96 @@
+package org.apache.flex.utilities.converter.retrievers.download.utils.utils;
+
+import java.io.ByteArrayInputStream;
+import java.io.DataInputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+
+/**
+ * Created by christoferdutz on 25.02.16.
+ */
+public class DmgBlockChunkEntry {
+
+ int entryType; // Compression type used or entry type (see next table)
+ int comment; // "+beg" or "+end", if EntryType is comment (0x7FFFFFFE). Else reserved.
+ long sectorNumber; // Start sector of this chunk
+ long sectorCount; // Number of sectors in this chunk
+ long compressedOffset; // Start of chunk in data fork
+ long compressedLength; // Count of bytes of chunk, in data fork
+
+ public DmgBlockChunkEntry(byte[] data) {
+ // Initialize the fields by parsing the input bytes.
+ ByteArrayInputStream bis = new ByteArrayInputStream(data);
+ DataInputStream dis = new DataInputStream(bis);
+ try {
+ entryType = dis.readInt();
+ comment = dis.readInt();
+ sectorNumber = dis.readLong();
+ sectorCount = dis.readLong();
+ compressedOffset = dis.readLong();
+ compressedLength = dis.readLong();
+ } catch (IOException e) {
+ throw new IllegalArgumentException("Invalid DmgBlockChunkEntry data.");
+ }
+ }
+
+ public int getEntryType() {
+ return entryType;
+ }
+
+ public int getComment() {
+ return comment;
+ }
+
+ public long getSectorNumber() {
+ return sectorNumber;
+ }
+
+ public long getSectorCount() {
+ return sectorCount;
+ }
+
+ public long getCompressedOffset() {
+ return compressedOffset;
+ }
+
+ public long getCompressedLength() {
+ return compressedLength;
+ }
+
+ @Override
+ public String toString() {
+ String entryTypeName;
+ switch(entryType) {
+ case 0x00000000:
+ entryTypeName = "Zero-Fill";
+ break;
+ case 0x00000001:
+ entryTypeName = "UDRW/UDRO - RAW or NULL compression (uncompressed)";
+ break;
+ case 0x00000002:
+ entryTypeName = "Ignored/unknown";
+ break;
+ case 0x80000004:
+ entryTypeName = "UDCO - Apple Data Compression (ADC)";
+ break;
+ case 0x80000005:
+ entryTypeName = "UDZO - zLib data compression";
+ break;
+ case 0x80000006:
+ entryTypeName = "UDBZ - bz2lib data compression";
+ break;
+ case 0x7ffffffe:
+ entryTypeName = "No blocks - Comment: +beg and +end";
+ default:
+ entryTypeName = "Unknown entry type " + entryType;
+ }
+ return "DmgBlockChunkEntry{" +
+ "entryType=" + entryTypeName +
+ ", comment=" + comment +
+ ", sectorNumber=" + sectorNumber +
+ ", sectorCount=" + sectorCount +
+ ", compressedOffset=" + compressedOffset +
+ ", compressedLength=" + compressedLength +
+ '}';
+ }
+}
http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/cf75f0e0/flex-maven-tools/flex-sdk-converter/retrievers/download/src/main/java/org/apache/flex/utilities/converter/retrievers/download/utils/utils/DmgPropertyListMishBlock.java
----------------------------------------------------------------------
diff --git a/flex-maven-tools/flex-sdk-converter/retrievers/download/src/main/java/org/apache/flex/utilities/converter/retrievers/download/utils/utils/DmgPropertyListMishBlock.java b/flex-maven-tools/flex-sdk-converter/retrievers/download/src/main/java/org/apache/flex/utilities/converter/retrievers/download/utils/utils/DmgPropertyListMishBlock.java
new file mode 100644
index 0000000..a5b4e02
--- /dev/null
+++ b/flex-maven-tools/flex-sdk-converter/retrievers/download/src/main/java/org/apache/flex/utilities/converter/retrievers/download/utils/utils/DmgPropertyListMishBlock.java
@@ -0,0 +1,101 @@
+package org.apache.flex.utilities.converter.retrievers.download.utils.utils;
+
+import java.io.ByteArrayInputStream;
+import java.io.DataInputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Created by christoferdutz on 25.02.16.
+ */
+public class DmgPropertyListMishBlock {
+
+ private String blockName;
+
+ private int version; // Current version is 1
+ private long sectorNumber; // Starting disk sector in this blkx descriptor
+ private long sectorCount; // Number of disk sectors in this blkx descriptor
+
+ private long dataOffset;
+ private int buffersNeeded;
+ private int blockDescriptors; // Number of descriptors
+
+ private DmgUdifChecksum checksum;
+
+ private List<DmgBlockChunkEntry> blockChunkEntries;
+
+ public DmgPropertyListMishBlock(String blockName, byte[] data) {
+ this.blockName = blockName;
+
+ // Initialize the fields by parsing the input bytes.
+ ByteArrayInputStream bis = new ByteArrayInputStream(data);
+ DataInputStream dis = new DataInputStream(bis);
+ try {
+ dis.readInt();
+ version = dis.readInt();
+ sectorNumber = dis.readLong();
+ sectorCount = dis.readLong();
+ dataOffset = dis.readLong();
+ buffersNeeded = dis.readInt();
+ blockDescriptors = dis.readInt();
+ dis.skipBytes(24);
+ byte[] checksumData = new byte[136];
+ dis.read(checksumData, 0, 136);
+ checksum = new DmgUdifChecksum(checksumData);
+ int numberOfBlockChunks = dis.readInt();
+
+ blockChunkEntries = new ArrayList<DmgBlockChunkEntry>();
+ byte[] blockChunkData = new byte[40];
+ for(int i = 0; i < numberOfBlockChunks; i++) {
+ dis.read(blockChunkData);
+ DmgBlockChunkEntry entry = new DmgBlockChunkEntry(blockChunkData);
+ // The block with the type "0xFFFFFFFF" is the end-block and contains
+ // no data we could need, so we simply end here.
+ if(entry.getEntryType() == 0xFFFFFFFF) {
+ break;
+ }
+ blockChunkEntries.add(entry);
+ }
+ } catch (IOException e) {
+ throw new IllegalArgumentException("Invalid DmgPropertyListMishBlock data.");
+ }
+ }
+
+ public String getBlockName() {
+ return blockName;
+ }
+
+ public int getVersion() {
+ return version;
+ }
+
+ public long getSectorNumber() {
+ return sectorNumber;
+ }
+
+ public long getSectorCount() {
+ return sectorCount;
+ }
+
+ public long getDataOffset() {
+ return dataOffset;
+ }
+
+ public int getBuffersNeeded() {
+ return buffersNeeded;
+ }
+
+ public int getBlockDescriptors() {
+ return blockDescriptors;
+ }
+
+ public DmgUdifChecksum getChecksum() {
+ return checksum;
+ }
+
+ public List<DmgBlockChunkEntry> getBlockChunkEntries() {
+ return blockChunkEntries;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/cf75f0e0/flex-maven-tools/flex-sdk-converter/retrievers/download/src/main/java/org/apache/flex/utilities/converter/retrievers/download/utils/utils/DmgTrailer.java
----------------------------------------------------------------------
diff --git a/flex-maven-tools/flex-sdk-converter/retrievers/download/src/main/java/org/apache/flex/utilities/converter/retrievers/download/utils/utils/DmgTrailer.java b/flex-maven-tools/flex-sdk-converter/retrievers/download/src/main/java/org/apache/flex/utilities/converter/retrievers/download/utils/utils/DmgTrailer.java
new file mode 100644
index 0000000..aa0ba9e
--- /dev/null
+++ b/flex-maven-tools/flex-sdk-converter/retrievers/download/src/main/java/org/apache/flex/utilities/converter/retrievers/download/utils/utils/DmgTrailer.java
@@ -0,0 +1,158 @@
+package org.apache.flex.utilities.converter.retrievers.download.utils.utils;
+
+import java.io.ByteArrayInputStream;
+import java.io.DataInputStream;
+import java.io.IOException;
+
+/**
+ * Created by christoferdutz on 24.02.16.
+ */
+public class DmgTrailer {
+
+ private int version; // Current version is 4
+ private int headerSize; // sizeof(this), always 512
+ private int flags; // Flags
+ private long runningDataForkOffset; //
+ private long dataForkOffset; // Data fork offset (usually 0, beginning of file)
+ private long dataForkLength; // Size of data fork (usually up to the XMLOffset, below)
+ private long rsrcForkOffset; // Resource fork offset, if any
+ private long rsrcForkLength; // Resource fork length, if any
+ private int segmentNumber; // Usually 1, may be 0
+ private int segmentCount; // Usually 1, may be 0
+ private byte[] segmentID; // 128-bit (16 byte) GUID identifier of segment (if SegmentNumber !=0)
+
+ private int dataChecksumType; // Data fork
+ private int dataChecksumSize; // Checksum Information
+ private byte[] dataChecksum; // Up to 128-bytes (32 x 4) of checksum
+
+ private long xmlOffset; // Offset of property list in DMG, from beginning
+ private long xmlLength; // Length of property list
+
+ private int checksumType; // Master
+ private int checksumSize; // Checksum information
+ private byte[] checksum; // Up to 128-bytes (32 x 4) of checksum
+
+ private int imageVariant; // Commonly 1
+ private long sectorCount; // Size of DMG when expanded, in sectors
+
+ public DmgTrailer(byte[] data) {
+ // Initialize the fields by parsing the input bytes.
+ ByteArrayInputStream bis = new ByteArrayInputStream(data);
+ DataInputStream dis = new DataInputStream(bis);
+ try {
+ dis.readInt();
+ version = dis.readInt();
+ headerSize = dis.readInt();
+ flags = dis.readInt();
+ runningDataForkOffset = dis.readLong();
+ dataForkOffset = dis.readLong();
+ dataForkLength = dis.readLong();
+ rsrcForkOffset = dis.readLong();
+ rsrcForkLength = dis.readLong();
+ segmentNumber = dis.readInt();
+ segmentCount = dis.readInt();
+ segmentID = new byte[16];
+ dis.read(segmentID, 0, 16);
+ dataChecksumType = dis.readInt();
+ dataChecksumSize = dis.readInt();
+ dataChecksum = new byte[128];
+ dis.read(dataChecksum, 0, 128);
+ xmlOffset = dis.readLong();
+ xmlLength = dis.readLong();
+ byte[] reserved = new byte[120];
+ dis.read(reserved, 0, 120);
+ checksumType = dis.readInt();
+ checksumSize = dis.readInt();
+ checksum = new byte[120];
+ dis.read(checksum, 0, 120);
+ imageVariant = dis.readInt();
+ sectorCount = dis.readLong();
+ } catch (IOException e) {
+ throw new IllegalArgumentException("Invalid DmgTrailer data.");
+ }
+ }
+
+ public int getVersion() {
+ return version;
+ }
+
+ public int getHeaderSize() {
+ return headerSize;
+ }
+
+ public int getFlags() {
+ return flags;
+ }
+
+ public long getRunningDataForkOffset() {
+ return runningDataForkOffset;
+ }
+
+ public long getDataForkOffset() {
+ return dataForkOffset;
+ }
+
+ public long getDataForkLength() {
+ return dataForkLength;
+ }
+
+ public long getRsrcForkOffset() {
+ return rsrcForkOffset;
+ }
+
+ public long getRsrcForkLength() {
+ return rsrcForkLength;
+ }
+
+ public int getSegmentNumber() {
+ return segmentNumber;
+ }
+
+ public int getSegmentCount() {
+ return segmentCount;
+ }
+
+ public byte[] getSegmentID() {
+ return segmentID;
+ }
+
+ public int getDataChecksumType() {
+ return dataChecksumType;
+ }
+
+ public int getDataChecksumSize() {
+ return dataChecksumSize;
+ }
+
+ public byte[] getDataChecksum() {
+ return dataChecksum;
+ }
+
+ public long getXmlOffset() {
+ return xmlOffset;
+ }
+
+ public long getXmlLength() {
+ return xmlLength;
+ }
+
+ public int getChecksumType() {
+ return checksumType;
+ }
+
+ public int getChecksumSize() {
+ return checksumSize;
+ }
+
+ public byte[] getChecksum() {
+ return checksum;
+ }
+
+ public int getImageVariant() {
+ return imageVariant;
+ }
+
+ public long getSectorCount() {
+ return sectorCount;
+ }
+}
http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/cf75f0e0/flex-maven-tools/flex-sdk-converter/retrievers/download/src/main/java/org/apache/flex/utilities/converter/retrievers/download/utils/utils/DmgUdifChecksum.java
----------------------------------------------------------------------
diff --git a/flex-maven-tools/flex-sdk-converter/retrievers/download/src/main/java/org/apache/flex/utilities/converter/retrievers/download/utils/utils/DmgUdifChecksum.java b/flex-maven-tools/flex-sdk-converter/retrievers/download/src/main/java/org/apache/flex/utilities/converter/retrievers/download/utils/utils/DmgUdifChecksum.java
new file mode 100644
index 0000000..52ec113
--- /dev/null
+++ b/flex-maven-tools/flex-sdk-converter/retrievers/download/src/main/java/org/apache/flex/utilities/converter/retrievers/download/utils/utils/DmgUdifChecksum.java
@@ -0,0 +1,42 @@
+package org.apache.flex.utilities.converter.retrievers.download.utils.utils;
+
+import java.io.ByteArrayInputStream;
+import java.io.DataInputStream;
+import java.io.IOException;
+
+/**
+ * Created by christoferdutz on 25.02.16.
+ */
+public class DmgUdifChecksum {
+
+ private int type;
+ private int size;
+ private byte[] data;
+
+ public DmgUdifChecksum(byte[] data) {
+ // Initialize the fields by parsing the input bytes.
+ ByteArrayInputStream bis = new ByteArrayInputStream(data);
+ DataInputStream dis = new DataInputStream(bis);
+ try {
+ type = dis.readInt();
+ size = dis.readInt();
+ this.data = new byte[128];
+ dis.read(this.data, 0, 128);
+ } catch (IOException e) {
+ throw new IllegalArgumentException("Invalid DmgUdifChecksum data.");
+ }
+ }
+
+ public int getType() {
+ return type;
+ }
+
+ public int getSize() {
+ return size;
+ }
+
+ public byte[] getData() {
+ return data;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/cf75f0e0/flex-maven-tools/flex-sdk-converter/retrievers/download/src/main/java/org/apache/flex/utilities/converter/retrievers/download/utils/utils/DriverDescriptor.java
----------------------------------------------------------------------
diff --git a/flex-maven-tools/flex-sdk-converter/retrievers/download/src/main/java/org/apache/flex/utilities/converter/retrievers/download/utils/utils/DriverDescriptor.java b/flex-maven-tools/flex-sdk-converter/retrievers/download/src/main/java/org/apache/flex/utilities/converter/retrievers/download/utils/utils/DriverDescriptor.java
new file mode 100644
index 0000000..61beb26
--- /dev/null
+++ b/flex-maven-tools/flex-sdk-converter/retrievers/download/src/main/java/org/apache/flex/utilities/converter/retrievers/download/utils/utils/DriverDescriptor.java
@@ -0,0 +1,38 @@
+package org.apache.flex.utilities.converter.retrievers.download.utils.utils;
+
+import java.io.DataInputStream;
+import java.io.IOException;
+
+/**
+ * Created by christoferdutz on 26.02.16.
+ */
+public class DriverDescriptor {
+
+ private int driverBlockStart;
+ private short driverBlockCount;
+ private short driverSystemType;
+
+ public DriverDescriptor(DataInputStream dis) {
+ // Initialize the fields by parsing the input bytes.
+ try {
+ driverBlockStart = dis.readInt();
+ driverBlockCount = dis.readShort();
+ driverSystemType = dis.readShort();
+ } catch (IOException e) {
+ throw new IllegalArgumentException("Invalid DriverDescriptor data.");
+ }
+ }
+
+ public int getDriverBlockStart() {
+ return driverBlockStart;
+ }
+
+ public short getDriverBlockCount() {
+ return driverBlockCount;
+ }
+
+ public short getDriverSystemType() {
+ return driverSystemType;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/cf75f0e0/flex-maven-tools/flex-sdk-converter/retrievers/download/src/main/java/org/apache/flex/utilities/converter/retrievers/download/utils/utils/DriverDescriptorMap.java
----------------------------------------------------------------------
diff --git a/flex-maven-tools/flex-sdk-converter/retrievers/download/src/main/java/org/apache/flex/utilities/converter/retrievers/download/utils/utils/DriverDescriptorMap.java b/flex-maven-tools/flex-sdk-converter/retrievers/download/src/main/java/org/apache/flex/utilities/converter/retrievers/download/utils/utils/DriverDescriptorMap.java
new file mode 100644
index 0000000..da9117a
--- /dev/null
+++ b/flex-maven-tools/flex-sdk-converter/retrievers/download/src/main/java/org/apache/flex/utilities/converter/retrievers/download/utils/utils/DriverDescriptorMap.java
@@ -0,0 +1,85 @@
+package org.apache.flex.utilities.converter.retrievers.download.utils.utils;
+
+import java.io.DataInputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Created by christoferdutz on 26.02.16.
+ */
+public class DriverDescriptorMap {
+
+ private short blockSize;
+ private int blockCount;
+ private short deviceType;
+ private short deviceId;
+ private int driverData;
+ private short driverDescriptorCount;
+ private List<DriverDescriptor> driverDescroiptors;
+
+ public DriverDescriptorMap(DataInputStream dis) {
+ // Initialize the fields by parsing the input bytes.
+ try {
+ if (dis.readShort() != 0x4552) {
+ throw new IllegalArgumentException("Invalid DriverDescriptorMap data. Expected magic number 0x4552");
+ }
+ blockSize = dis.readShort();
+ blockCount = dis.readInt();
+ deviceType = dis.readShort();
+ deviceId = dis.readShort();
+ driverData = dis.readInt();
+ driverDescriptorCount = dis.readShort();
+ driverDescroiptors = new ArrayList<DriverDescriptor>();
+ for(int i = 0; i < 8; i++) {
+ DriverDescriptor dd = new DriverDescriptor(dis);
+ driverDescroiptors.add(dd);
+ }
+ dis.skipBytes(430);
+
+ } catch (IOException e) {
+ throw new IllegalArgumentException("Invalid DriverDescriptorMap data.");
+ }
+ }
+
+ public short getBlockSize() {
+ return blockSize;
+ }
+
+ public int getBlockCount() {
+ return blockCount;
+ }
+
+ public short getDeviceType() {
+ return deviceType;
+ }
+
+ public short getDeviceId() {
+ return deviceId;
+ }
+
+ public int getDriverData() {
+ return driverData;
+ }
+
+ public short getDriverDescriptorCount() {
+ return driverDescriptorCount;
+ }
+
+ public List<DriverDescriptor> getDriverDescroiptors() {
+ return driverDescroiptors;
+ }
+
+ @Override
+ public String toString() {
+ return "DriverDescriptorMap{" +
+ "blockSize=" + blockSize +
+ ", blockCount=" + blockCount +
+ ", deviceType=" + deviceType +
+ ", deviceId=" + deviceId +
+ ", driverData=" + driverData +
+ ", driverDescriptorCount=" + driverDescriptorCount +
+ ", driverDescroiptors=" + driverDescroiptors +
+ '}';
+ }
+}
http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/cf75f0e0/flex-maven-tools/flex-sdk-converter/retrievers/download/src/main/java/org/apache/flex/utilities/converter/retrievers/download/utils/utils/HFSPlusExtent.java
----------------------------------------------------------------------
diff --git a/flex-maven-tools/flex-sdk-converter/retrievers/download/src/main/java/org/apache/flex/utilities/converter/retrievers/download/utils/utils/HFSPlusExtent.java b/flex-maven-tools/flex-sdk-converter/retrievers/download/src/main/java/org/apache/flex/utilities/converter/retrievers/download/utils/utils/HFSPlusExtent.java
new file mode 100644
index 0000000..a0dd5c9
--- /dev/null
+++ b/flex-maven-tools/flex-sdk-converter/retrievers/download/src/main/java/org/apache/flex/utilities/converter/retrievers/download/utils/utils/HFSPlusExtent.java
@@ -0,0 +1,40 @@
+package org.apache.flex.utilities.converter.retrievers.download.utils.utils;
+
+import java.io.DataInputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+
+/**
+ * Created by christoferdutz on 27.02.16.
+ */
+public class HFSPlusExtent {
+
+ private int startBlock;
+ private int blockCount;
+
+ public HFSPlusExtent(DataInputStream dis) {
+ try {
+ startBlock = dis.readInt();
+ blockCount = dis.readInt();
+ } catch (IOException e) {
+ throw new IllegalArgumentException("Invalid HFSPlusVolumeHeader data.");
+ }
+ }
+
+ public int getStartBlock() {
+ return startBlock;
+ }
+
+ public int getBlockCount() {
+ return blockCount;
+ }
+
+ @Override
+ public String toString() {
+ return "HFSPlusExtent{" +
+ "startBlock=" + startBlock +
+ ", blockCount=" + blockCount +
+ '}';
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/cf75f0e0/flex-maven-tools/flex-sdk-converter/retrievers/download/src/main/java/org/apache/flex/utilities/converter/retrievers/download/utils/utils/HFSPlusForkData.java
----------------------------------------------------------------------
diff --git a/flex-maven-tools/flex-sdk-converter/retrievers/download/src/main/java/org/apache/flex/utilities/converter/retrievers/download/utils/utils/HFSPlusForkData.java b/flex-maven-tools/flex-sdk-converter/retrievers/download/src/main/java/org/apache/flex/utilities/converter/retrievers/download/utils/utils/HFSPlusForkData.java
new file mode 100644
index 0000000..dcec76f
--- /dev/null
+++ b/flex-maven-tools/flex-sdk-converter/retrievers/download/src/main/java/org/apache/flex/utilities/converter/retrievers/download/utils/utils/HFSPlusForkData.java
@@ -0,0 +1,59 @@
+package org.apache.flex.utilities.converter.retrievers.download.utils.utils;
+
+import java.io.DataInputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * Created by christoferdutz on 26.02.16.
+ */
+public class HFSPlusForkData {
+
+ private long logicalSize;
+ int clumpSize;
+ int totalBlocks;
+ List<HFSPlusExtent> extents;
+
+ public HFSPlusForkData(DataInputStream dis) {
+ try {
+ logicalSize = dis.readLong();
+ clumpSize = dis.readInt();
+ totalBlocks = dis.readInt();
+ extents = new ArrayList<HFSPlusExtent>(8);
+ for(int i = 0; i < 8; i++) {
+ HFSPlusExtent extent = new HFSPlusExtent(dis);
+ extents.add(extent);
+ }
+ } catch (IOException e) {
+ throw new IllegalArgumentException("Invalid HFSPlusVolumeHeader data.");
+ }
+ }
+
+ public long getLogicalSize() {
+ return logicalSize;
+ }
+
+ public int getClumpSize() {
+ return clumpSize;
+ }
+
+ public int getTotalBlocks() {
+ return totalBlocks;
+ }
+
+ public List<HFSPlusExtent> getExtents() {
+ return extents;
+ }
+
+ @Override
+ public String toString() {
+ return "HFSPlusForkData{" +
+ "logicalSize=" + logicalSize +
+ ", clumpSize=" + clumpSize +
+ ", totalBlocks=" + totalBlocks +
+ ", extents=" + extents +
+ '}';
+ }
+}
http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/cf75f0e0/flex-maven-tools/flex-sdk-converter/retrievers/download/src/main/java/org/apache/flex/utilities/converter/retrievers/download/utils/utils/HFSPlusVolumeHeader.java
----------------------------------------------------------------------
diff --git a/flex-maven-tools/flex-sdk-converter/retrievers/download/src/main/java/org/apache/flex/utilities/converter/retrievers/download/utils/utils/HFSPlusVolumeHeader.java b/flex-maven-tools/flex-sdk-converter/retrievers/download/src/main/java/org/apache/flex/utilities/converter/retrievers/download/utils/utils/HFSPlusVolumeHeader.java
new file mode 100644
index 0000000..b355c05
--- /dev/null
+++ b/flex-maven-tools/flex-sdk-converter/retrievers/download/src/main/java/org/apache/flex/utilities/converter/retrievers/download/utils/utils/HFSPlusVolumeHeader.java
@@ -0,0 +1,217 @@
+package org.apache.flex.utilities.converter.retrievers.download.utils.utils;
+
+import java.io.DataInputStream;
+import java.io.IOException;
+import java.util.Arrays;
+
+/**
+ * http://www.dubeyko.com/development/FileSystems/HFSPLUS/hexdumps/hfsplus_volume_header.html
+ *
+ * Created by christoferdutz on 24.02.16.
+ */
+public class HFSPlusVolumeHeader implements IHFSVolumeHeader {
+
+ private short version;
+ private int attributes;
+ private int lastMountedVersion;
+ private int journalInfoBlock;
+
+ private int createDate;
+ private int modifyDate;
+ private int backupDate;
+ private int checkedDate;
+
+ private int fileCount;
+ private int folderCount;
+
+ private int blockSize;
+ private int totalBlocks;
+ private int freeBlocks;
+
+ private int nextAllocation;
+ private int rsrcClumpSize;
+ private int nextCatalogID;
+ private int dataClumpSize;
+
+ private int writeCount;
+ private long encodingsBitmap;
+
+ private byte[] finderInfo;
+
+ private HFSPlusForkData allocationFile;
+ private HFSPlusForkData extentsFile;
+ private HFSPlusForkData catalogFile;
+ private HFSPlusForkData attributesFile;
+ private HFSPlusForkData startupFile;
+
+ public HFSPlusVolumeHeader(DataInputStream dis) {
+ try {
+ version = dis.readShort();
+ attributes = dis.readInt();
+ lastMountedVersion = dis.readInt();
+ journalInfoBlock = dis.readInt();
+
+ createDate = dis.readInt();
+ modifyDate = dis.readInt();
+ backupDate = dis.readInt();
+ checkedDate = dis.readInt();
+
+ fileCount = dis.readInt();
+ folderCount = dis.readInt();
+
+ blockSize = dis.readInt();
+ totalBlocks = dis.readInt();
+ freeBlocks = dis.readInt();
+
+ nextAllocation = dis.readInt();
+ rsrcClumpSize = dis.readInt();
+ dataClumpSize = dis.readInt();
+ nextCatalogID = dis.readInt();
+
+ writeCount = dis.readInt();
+ encodingsBitmap = dis.readLong();
+
+ finderInfo = new byte[32];
+ dis.read(finderInfo);
+
+ allocationFile = new HFSPlusForkData(dis);
+ extentsFile = new HFSPlusForkData(dis);
+ catalogFile = new HFSPlusForkData(dis);
+ attributesFile = new HFSPlusForkData(dis);
+ startupFile = new HFSPlusForkData(dis);
+ } catch (IOException e) {
+ throw new IllegalArgumentException("Invalid HFSPlusVolumeHeader data.");
+ }
+ }
+
+ public short getVersion() {
+ return version;
+ }
+
+ public int getAttributes() {
+ return attributes;
+ }
+
+ public int getLastMountedVersion() {
+ return lastMountedVersion;
+ }
+
+ public int getJournalInfoBlock() {
+ return journalInfoBlock;
+ }
+
+ public int getCreateDate() {
+ return createDate;
+ }
+
+ public int getModifyDate() {
+ return modifyDate;
+ }
+
+ public int getBackupDate() {
+ return backupDate;
+ }
+
+ public int getCheckedDate() {
+ return checkedDate;
+ }
+
+ public int getFileCount() {
+ return fileCount;
+ }
+
+ public int getFolderCount() {
+ return folderCount;
+ }
+
+ public int getBlockSize() {
+ return blockSize;
+ }
+
+ public int getTotalBlocks() {
+ return totalBlocks;
+ }
+
+ public int getFreeBlocks() {
+ return freeBlocks;
+ }
+
+ public int getNextAllocation() {
+ return nextAllocation;
+ }
+
+ public int getRsrcClumpSize() {
+ return rsrcClumpSize;
+ }
+
+ public int getDataClumpSize() {
+ return dataClumpSize;
+ }
+
+ public int getWriteCount() {
+ return writeCount;
+ }
+
+ public long getEncodingsBitmap() {
+ return encodingsBitmap;
+ }
+
+ public int getNextCatalogID() {
+ return nextCatalogID;
+ }
+
+ public byte[] getFinderInfo() {
+ return finderInfo;
+ }
+
+ public HFSPlusForkData getAllocationFile() {
+ return allocationFile;
+ }
+
+ public HFSPlusForkData getExtentsFile() {
+ return extentsFile;
+ }
+
+ public HFSPlusForkData getCatalogFile() {
+ return catalogFile;
+ }
+
+ public HFSPlusForkData getAttributesFile() {
+ return attributesFile;
+ }
+
+ public HFSPlusForkData getStartupFile() {
+ return startupFile;
+ }
+
+ @Override
+ public String toString() {
+ return "HFSPlusVolumeHeader{" +
+ "version=" + version +
+ ", attributes=" + attributes +
+ ", lastMountedVersion=" + lastMountedVersion +
+ ", journalInfoBlock=" + journalInfoBlock +
+ ", createDate=" + createDate +
+ ", modifyDate=" + modifyDate +
+ ", backupDate=" + backupDate +
+ ", checkedDate=" + checkedDate +
+ ", fileCount=" + fileCount +
+ ", folderCount=" + folderCount +
+ ", blockSize=" + blockSize +
+ ", totalBlocks=" + totalBlocks +
+ ", freeBlocks=" + freeBlocks +
+ ", nextAllocation=" + nextAllocation +
+ ", rsrcClumpSize=" + rsrcClumpSize +
+ ", nextCatalogID=" + nextCatalogID +
+ ", dataClumpSize=" + dataClumpSize +
+ ", writeCount=" + writeCount +
+ ", encodingsBitmap=" + encodingsBitmap +
+ ", finderInfo=" + Arrays.toString(finderInfo) +
+ ", allocationFile=" + allocationFile +
+ ", extentsFile=" + extentsFile +
+ ", catalogFile=" + catalogFile +
+ ", attributesFile=" + attributesFile +
+ ", startupFile=" + startupFile +
+ '}';
+ }
+}
http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/cf75f0e0/flex-maven-tools/flex-sdk-converter/retrievers/download/src/main/java/org/apache/flex/utilities/converter/retrievers/download/utils/utils/HFSVolumeFactory.java
----------------------------------------------------------------------
diff --git a/flex-maven-tools/flex-sdk-converter/retrievers/download/src/main/java/org/apache/flex/utilities/converter/retrievers/download/utils/utils/HFSVolumeFactory.java b/flex-maven-tools/flex-sdk-converter/retrievers/download/src/main/java/org/apache/flex/utilities/converter/retrievers/download/utils/utils/HFSVolumeFactory.java
new file mode 100644
index 0000000..24536e3
--- /dev/null
+++ b/flex-maven-tools/flex-sdk-converter/retrievers/download/src/main/java/org/apache/flex/utilities/converter/retrievers/download/utils/utils/HFSVolumeFactory.java
@@ -0,0 +1,24 @@
+package org.apache.flex.utilities.converter.retrievers.download.utils.utils;
+
+import java.io.DataInputStream;
+import java.io.IOException;
+
+/**
+ * Created by christoferdutz on 27.02.16.
+ */
+public class HFSVolumeFactory {
+
+ public static IHFSVolumeHeader readHfsVolumeHeader(DataInputStream dis) {
+ try {
+ short magicNumber = dis.readShort();
+ if(magicNumber == 0x482B) {
+ return new HFSPlusVolumeHeader(dis);
+ } else {
+ return new HFSVolumeHeader(dis);
+ }
+ } catch (IOException e) {
+ throw new IllegalArgumentException("Invalid IHFSPVolumeHeader data.");
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/cf75f0e0/flex-maven-tools/flex-sdk-converter/retrievers/download/src/main/java/org/apache/flex/utilities/converter/retrievers/download/utils/utils/HFSVolumeHeader.java
----------------------------------------------------------------------
diff --git a/flex-maven-tools/flex-sdk-converter/retrievers/download/src/main/java/org/apache/flex/utilities/converter/retrievers/download/utils/utils/HFSVolumeHeader.java b/flex-maven-tools/flex-sdk-converter/retrievers/download/src/main/java/org/apache/flex/utilities/converter/retrievers/download/utils/utils/HFSVolumeHeader.java
new file mode 100644
index 0000000..e2bb8b3
--- /dev/null
+++ b/flex-maven-tools/flex-sdk-converter/retrievers/download/src/main/java/org/apache/flex/utilities/converter/retrievers/download/utils/utils/HFSVolumeHeader.java
@@ -0,0 +1,13 @@
+package org.apache.flex.utilities.converter.retrievers.download.utils.utils;
+
+import java.io.DataInputStream;
+
+/**
+ * Created by christoferdutz on 27.02.16.
+ */
+public class HFSVolumeHeader implements IHFSVolumeHeader {
+
+ public HFSVolumeHeader(DataInputStream dis) {
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/cf75f0e0/flex-maven-tools/flex-sdk-converter/retrievers/download/src/main/java/org/apache/flex/utilities/converter/retrievers/download/utils/utils/IHFSVolumeHeader.java
----------------------------------------------------------------------
diff --git a/flex-maven-tools/flex-sdk-converter/retrievers/download/src/main/java/org/apache/flex/utilities/converter/retrievers/download/utils/utils/IHFSVolumeHeader.java b/flex-maven-tools/flex-sdk-converter/retrievers/download/src/main/java/org/apache/flex/utilities/converter/retrievers/download/utils/utils/IHFSVolumeHeader.java
new file mode 100644
index 0000000..470fad0
--- /dev/null
+++ b/flex-maven-tools/flex-sdk-converter/retrievers/download/src/main/java/org/apache/flex/utilities/converter/retrievers/download/utils/utils/IHFSVolumeHeader.java
@@ -0,0 +1,10 @@
+package org.apache.flex.utilities.converter.retrievers.download.utils.utils;
+
+/**
+ * http://www.dubeyko.com/development/FileSystems/HFSPLUS/hexdumps/hfsplus_volume_header.html
+ *
+ * Created by christoferdutz on 24.02.16.
+ */
+public interface IHFSVolumeHeader {
+
+}