/* * Copyright (C) 2015-2017 PÂRIS Quentin * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ package org.phoenicis.tools.archive.cab; import java.io.*; import java.util.ArrayList; import java.util.Collection; public class Cabfile { private final InputStream archiveStream; private long readBytes = 0; public Cabfile(File archiveFile) { try { this.archiveStream = new FileInputStream(archiveFile); } catch (FileNotFoundException e) { throw new CabException(String.format("The file %s is not found", archiveFile), e); } } private int findCabOffset() { try { int i = 0; int successBytes = 0; while (true) { byte[] nextRead = new byte[1]; int numRead = archiveStream.read(nextRead); if (numRead == -1) { throw new CabException("This file does not contain any cabinet archive"); } if ((nextRead[0] & 0xFF) == 0x4D && successBytes == 0) { successBytes++; } else if ((nextRead[0] & 0xFF) == 0x53 && successBytes == 1) { successBytes++; } else if ((nextRead[0] & 0xFF) == 0x43 && successBytes == 2) { successBytes++; } else if ((nextRead[0] & 0xFF) == 0x46 && successBytes == 3) { successBytes++; } else if ((nextRead[0] & 0xFF) == 0x00 && successBytes == 4) { successBytes++; } else if ((nextRead[0] & 0xFF) == 0x00 && successBytes == 5) { successBytes++; } else if ((nextRead[0] & 0xFF) == 0x00 && successBytes == 6) { successBytes++; } else if ((nextRead[0] & 0xFF) == 0x00 && successBytes == 7) { return i - 7; } else { successBytes = 0; } i++; } } catch (IOException e) { throw new CabException("Unable to find cab header", e); } } private CFHeader getHeader() { CFHeader cfHeader = new CFHeader(readBytes); cfHeader.populate(archiveStream); readBytes += (long) cfHeader.getStructureSize(); return cfHeader; } public CFFolder getFolder() { CFFolder cfFolder = new CFFolder(readBytes); cfFolder.populate(archiveStream); readBytes += (long) cfFolder.getStructureSize(); return cfFolder; } public CFFile getFile() { CFFile cfFile = new CFFile(readBytes); cfFile.populate(archiveStream); readBytes += (long) cfFile.getStructureSize(); return cfFile; } public CFData getData(CompressionType compressionType) { CFData cfData = new CFData(readBytes, compressionType); cfData.populate(archiveStream); readBytes += (long) cfData.getStructureSize(); return cfData; } private void skipBytes(long numberToSkip) throws IOException { readBytes += numberToSkip; archiveStream.skip(numberToSkip); } private void jumpTo(long offset) throws IOException { this.skipBytes(offset - readBytes); } public static void main(String[] args) throws IOException { File tahoma32 = new File("/Users/tinou/Downloads/arial32.exe"); Cabfile cabfile = new Cabfile(tahoma32); int offset = cabfile.findCabOffset(); //System.out.println(offset); CFHeader header = cabfile.getHeader(); Collection<CFFolder> cfFolders = new ArrayList<>(); for (int i = 0; i < header.getNumberOfFolders(); i++) { CFFolder cfFolder = cabfile.getFolder(); cfFolders.add(cfFolder); //System.out.println(cfFolder); } cabfile.jumpTo(header.coffFiles[0]); Collection<CFFile> cfiles = new ArrayList<>(); for (int i = 0; i < header.getNumberOfFiles(); i++) { CFFile cfile = cabfile.getFile(); cfiles.add(cfile); //System.out.println(cfile); } CFData cfData = cabfile.getData(CompressionType.NONE); //System.out.println(cfData); //System.out.println(Hex.encodeHexString(cfData.ab)); CFData cfData2 = cabfile.getData(CompressionType.NONE); //System.out.println(cfData2); //System.out.println(Hex.encodeHexString(cfData2.ab)); /* for(CFFile cfFile: cfiles) { if("fontinst.inf".equals(cfFile.getFilename())) { CFFolder cfFolder = cfFolders.get((int) cfFile.getFolderIndex()); long dataIndex = cfFolder.getOffsetStartData() + cfFile.getOffsetStartDataInsideFolder(); System.out.println("Index: "); System.out.println(dataIndex); cabfile.jumpTo(dataIndex); CFData cfData = cabfile.getData(); cfFolder.dump(); System.out.println(cfFile); System.out.println(cfData); File test = new File("/tmp/test"); FileOutputStream stream = new FileOutputStream(test); stream.write(cfData.ab); System.out.println(Arrays.toString(cfData.ab)); } } */ } }