|
@@ -1,741 +1,742 @@
|
|
|
-/*
|
|
|
- * Copyright (C) 2015 iZc
|
|
|
- *
|
|
|
- * 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 3 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, see <http://www.gnu.org/licenses/>.
|
|
|
- */
|
|
|
-package de.nplusc.izc.tools.IOtools.iZformats;
|
|
|
-
|
|
|
-import de.nplusc.izc.tools.IOtools.FileTK;
|
|
|
-import de.nplusc.izc.tools.baseTools.arraytools;
|
|
|
-import java.io.File;
|
|
|
-import java.io.FileInputStream;
|
|
|
-import java.io.FileNotFoundException;
|
|
|
-import java.io.IOException;
|
|
|
-import java.io.PipedInputStream;
|
|
|
-import java.io.PipedOutputStream;
|
|
|
-import java.io.RandomAccessFile;
|
|
|
-import java.nio.ByteBuffer;
|
|
|
-import java.util.ArrayList;
|
|
|
-import java.util.zip.GZIPInputStream;
|
|
|
-import java.util.zip.GZIPOutputStream;
|
|
|
-import org.apache.logging.log4j.LogManager;
|
|
|
-import org.apache.logging.log4j.Logger;
|
|
|
-
|
|
|
-/**
|
|
|
- *
|
|
|
- * @author LH
|
|
|
- */
|
|
|
-public class IZpackage
|
|
|
-{
|
|
|
- private static final Logger l = LogManager.getLogger();
|
|
|
- static final byte[] magicHeader = new byte[]{(byte)0x00, (byte)0x14, (byte)0x19, (byte)0x40, (byte)0xFA ,(byte)0xC4 ,(byte)0x0A};
|
|
|
- public static final int CHUNK_SIZE=4096;
|
|
|
-
|
|
|
-
|
|
|
- //Formatspezifikation
|
|
|
- //magicHEader=0x00 00 14 19 40 FA C4 0A
|
|
|
- //länge desy eigentlichen headers in byte >in 4 bytes speichern
|
|
|
- //anzahl eintrage; 4 bytes//wichtig beim einlesen
|
|
|
- //Headerformat: 1 byte Länge des pfades; Pfad (0-255 lang; relativ)8 bytes Offset innerhalb Datei; 8 byte Größe 4 bytes flags
|
|
|
- //Dann dateien in einem Bytestrom aneinandergehängt
|
|
|
-
|
|
|
- private String packageToRead;
|
|
|
- //private boolean archiveIsreadOnly;//TODO: erkennen ob medium Disk ist
|
|
|
- private RandomAccessFile achv=null;
|
|
|
- private String[] header_fnames = null;;
|
|
|
- private long[] header_fsizes=null;
|
|
|
- private long[] header_fcompsizes=null;
|
|
|
- private long[] header_foffsets=null;
|
|
|
- private int[] header_flags = null;
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- public IZpackage(String path)
|
|
|
- {
|
|
|
- packageToRead = path;
|
|
|
- try
|
|
|
- {
|
|
|
- //NOP
|
|
|
- achv = new RandomAccessFile(packageToRead, "rwd");//VOID:readonly als absicherung gegen derps
|
|
|
- if(FileTK.checkDirExist(path))
|
|
|
- {
|
|
|
- preloadHeader();
|
|
|
- }
|
|
|
- }
|
|
|
- catch (FileNotFoundException ex)
|
|
|
- {
|
|
|
- ex.printStackTrace();
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- void preloadHeader()
|
|
|
- {
|
|
|
- try
|
|
|
- {
|
|
|
- achv.seek(8);//headergröße anspringen
|
|
|
- byte[] hr = new byte[4];
|
|
|
- achv.readFully(hr);
|
|
|
- int hs = ByteBuffer.allocate(4).put(hr).getInt(0);
|
|
|
-
|
|
|
- achv.seek(12);//elementeanzahl anspringen
|
|
|
- byte[] fc = new byte[4];
|
|
|
- achv.readFully(fc);
|
|
|
- int elemcount= ByteBuffer.allocate(4).put(fc).getInt(0);
|
|
|
-
|
|
|
- achv.seek(16);
|
|
|
- byte[] hdrr = new byte[hs];
|
|
|
- achv.readFully(hdrr);//einlesen des headers
|
|
|
- ByteBuffer hdr = ByteBuffer.allocate(hs).put(hdrr);
|
|
|
- int pos = 0;//position innerhalb headers
|
|
|
-
|
|
|
-
|
|
|
- String[] filenames = new String[elemcount];
|
|
|
- int[] flags = new int[elemcount];
|
|
|
- long[] filesizes=new long[elemcount],filesizescomp=new long[elemcount],fileoffsets=new long[elemcount];//die 4 arrays initialisieren um den header abzubilden //dateinamenlänge wird nur intern benötigt
|
|
|
-
|
|
|
-
|
|
|
- for (int i = 0; i < elemcount; i++)
|
|
|
- {
|
|
|
- int flength = hdr.get(pos)&0xFF;//vorzeichen rausbügeln; danke javaquirk
|
|
|
- pos++;
|
|
|
- byte[] filenameraw = new byte[flength];
|
|
|
- hdr.position(pos);
|
|
|
- hdr.get(filenameraw);
|
|
|
- pos+=flength;
|
|
|
- filenames[i]=new String(filenameraw);//etwas unkonventionell :P dürfte nicht jeder wissen dass das geht
|
|
|
- filesizes[i]=hdr.getLong(pos);
|
|
|
- pos+=8;
|
|
|
- filesizescomp[i]=hdr.getLong(pos);
|
|
|
- pos+=8;
|
|
|
- fileoffsets[i]=hdr.getLong(pos);
|
|
|
- pos+=8;
|
|
|
- flags[i] = hdr.getInt();
|
|
|
- pos+=4;
|
|
|
- }
|
|
|
- //header eingelesen;
|
|
|
- //header dumpen
|
|
|
- header_fnames = filenames;
|
|
|
- header_foffsets = fileoffsets;
|
|
|
- header_fsizes = filesizes;
|
|
|
- header_flags = flags;
|
|
|
- header_fcompsizes = filesizescomp;
|
|
|
- }
|
|
|
- catch(IOException e)
|
|
|
- {
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- public static int FLAG_COMPRESSED = 0;
|
|
|
- public static int FLAG_GZIP = 1;
|
|
|
- String pbasedir,pfn;
|
|
|
-
|
|
|
- /**
|
|
|
- * erstellt ein neues iZpack-archiv unter dem im Objekt hinterlegtren archiv
|
|
|
- * @param baseDir Wurzelverzeichnis der input-files
|
|
|
- * @param files Dateien; relativ zu basedir; da dies die struktur im archiv spieschelt
|
|
|
- */
|
|
|
- PipedInputStream s;
|
|
|
- public void createArchive(String baseDir,String... files)
|
|
|
- {
|
|
|
- byte[] filenamelengths = new byte[files.length];
|
|
|
- byte[][] fileBytes = new byte[files.length][];
|
|
|
- byte[][] fileSizes = new byte[files.length][8];
|
|
|
- byte[][] fileSizesComp = new byte[files.length][8];
|
|
|
- byte[][] flags = new byte[files.length][4];
|
|
|
- //boolean[][]flagsreadable = new boolean[files.length][32];//32 flags maximum
|
|
|
- long[] fileSizesRaw = new long[files.length];//nötig für uncompress
|
|
|
- long[] fileSizesRawComp = new long[files.length];//nötig um Offset auszurechnen und einzuspeixern
|
|
|
- byte[][] offsets = new byte[files.length][8];//wird erst zum schluss befüllt;
|
|
|
- int headerSize=0;
|
|
|
- //oFFSET0ALLE VORHERIGEN OFFSETS + HEADERSIZE+ 8DA MAGISCHE KENNUNG9
|
|
|
- for (int i = 0; i < files.length; i++)
|
|
|
- {
|
|
|
- String fileToGetSize = baseDir+File.separator+files[i];
|
|
|
-
|
|
|
- long fileSize = new File(fileToGetSize).length();
|
|
|
- fileSizesRaw[i] = fileSize;
|
|
|
- //byte[] filesizearr = new byte[8];
|
|
|
- /*for (int j = 0; j < 8; j++)
|
|
|
- {
|
|
|
- filesizearr[7-j] = (byte)(fileSize%256);//schneidet niederwertigstes bit heraus;
|
|
|
- fileSize/=256;//ein byte nach rechts dudeln;
|
|
|
-
|
|
|
- }*/
|
|
|
- int flag=0; //TODO compresshandler //zzz_sfx=nocompress; jpg;png;mp3 etc=noCOmpress, too
|
|
|
- /*
|
|
|
- String ftype = FileTK.getFileExt(files[i]);
|
|
|
- String[] nocompress = new String[]{"docx","rar","7z","gz","bz2","jpg","png","xlsx","wmv","mp4","flv","mov","mp3","flac","m4a","wma"};
|
|
|
- for (String ble : nocompress)
|
|
|
- {
|
|
|
- if(ftype!=null&&(ftype.equalsIgnoreCase(ble)||(files[i].equalsIgnoreCase("zzz_sfxmod.jar"))))//erkennt die gesperrten dateinamen/typen für kkomprimieren
|
|
|
- {
|
|
|
- flag = flag&(3^0xffffffff); //rausnehmen der compres und gzip-bits
|
|
|
- }
|
|
|
- }*/
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- fileSizes[i]=ByteBuffer.allocate(8).putLong(fileSize).array();
|
|
|
- fileSizesComp[i]=ByteBuffer.allocate(8).putLong(fileSize).array();
|
|
|
- fileBytes[i]=files[i].getBytes();
|
|
|
- flags[i] = ByteBuffer.allocate(4).putInt(flag).array();
|
|
|
- filenamelengths[i] = (byte)(fileBytes[i].length);
|
|
|
- //size //compsize //offset //dateinamenlänge //längenmarkerbyte //flags
|
|
|
- headerSize += 8+ 8+ 8+ filenamelengths[i]+1 +4;
|
|
|
- }
|
|
|
- long baseoffset = headerSize+16; //Header+magischeKennung;
|
|
|
-
|
|
|
- //create_offsets
|
|
|
- for (int i = 0; i < fileSizesRaw.length; i++)
|
|
|
- {
|
|
|
-
|
|
|
- offsets[i] = ByteBuffer.allocate(8).putLong(baseoffset).array();
|
|
|
- baseoffset +=fileSizesRawComp[i]; //offset für nxte datei vorbereiten;
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- byte[] header;//= new byte[headerSize+4];//headerSizeFlag wird mit eingebettet//elemcount auch;
|
|
|
- byte[] headerSizeattrib = ByteBuffer.allocate(4).putInt(headerSize).array();
|
|
|
- ByteBuffer headerAssem = ByteBuffer.allocate(headerSize+8);
|
|
|
- //header zusammensetzen;
|
|
|
- byte[] headerElemCount = ByteBuffer.allocate(4).putInt(files.length).array();
|
|
|
- int bo = 0;
|
|
|
- headerAssem.put(headerSizeattrib);
|
|
|
- bo+=4;//weiterschieben
|
|
|
- headerAssem.position(bo);
|
|
|
- headerAssem.put(headerElemCount);
|
|
|
- bo+=4;
|
|
|
- headerAssem.position(bo);
|
|
|
-
|
|
|
- for (int i = 0; i < offsets.length; i++)
|
|
|
- {
|
|
|
- headerAssem.put(bo,filenamelengths[i]);
|
|
|
- bo++;
|
|
|
- headerAssem.position(bo);
|
|
|
- headerAssem.put(fileBytes[i]);
|
|
|
- bo+=((int)filenamelengths[i]&0xff);
|
|
|
- headerAssem.position(bo);
|
|
|
- headerAssem.put(fileSizes[i]);
|
|
|
- bo+=8;
|
|
|
- headerAssem.position(bo);
|
|
|
- headerAssem.put(fileSizesComp[i]);
|
|
|
- bo+=8;
|
|
|
- headerAssem.position(bo);
|
|
|
- headerAssem.put(offsets[i]);
|
|
|
- bo+=8;
|
|
|
- headerAssem.position(bo);
|
|
|
- headerAssem.put(flags[i]);
|
|
|
- bo+=4;
|
|
|
- headerAssem.position(bo);
|
|
|
- }
|
|
|
- header=headerAssem.array();
|
|
|
- //RandomAccessFile achv=null;
|
|
|
- try
|
|
|
- {
|
|
|
- achv.seek(0);//zurücksetzen der datei;
|
|
|
- achv.write(magicHeader);
|
|
|
- achv.seek(8);
|
|
|
- achv.write(header); //header wird am schluss erzeugt da Komprimierung vorhanden
|
|
|
- //achv.write(header);
|
|
|
- l.info("Filecount:{}",files.length);
|
|
|
- try
|
|
|
- {
|
|
|
- //for (String fn : files)
|
|
|
- Thread.sleep(50);
|
|
|
- }
|
|
|
- catch (InterruptedException ex)
|
|
|
- {
|
|
|
- ex.printStackTrace();
|
|
|
- }
|
|
|
- for(int i = 0;i<files.length;i++)
|
|
|
- {
|
|
|
- String fn = files[i];
|
|
|
- int flag = ByteBuffer.allocate(4).put(flags[i]).getInt(0);
|
|
|
- l.trace(flag+"|"+fn);
|
|
|
- if((flag&0x0000_0001)==0) //compressed-flag ausmaskieren
|
|
|
- {
|
|
|
- //java.io.FileNotFoundException: /buildpipeline/iZsetup/64b/predist\lib/ToolKit.jar
|
|
|
- //ARSCHFICKRIGE BACKSLASHE HABEN HIER NIX ZU SUCHEN
|
|
|
- RandomAccessFile readIn = new RandomAccessFile(baseDir+File.separator+fn, "rwd");
|
|
|
- long readInVol = readIn.length();
|
|
|
- while(readIn.getFilePointer()<readIn.length())
|
|
|
- {
|
|
|
- byte[] buf;
|
|
|
- if(readInVol>CHUNK_SIZE)
|
|
|
- {
|
|
|
- buf = new byte[CHUNK_SIZE];
|
|
|
- readInVol-=CHUNK_SIZE;
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- buf = new byte[(int)readInVol];
|
|
|
- }
|
|
|
- readIn.read(buf, 0, buf.length); //TODO effizioenteren weg finden!!!
|
|
|
- achv.write(buf);
|
|
|
- fileSizesRawComp[i] = fileSizesRaw[i];
|
|
|
- }
|
|
|
- readIn.close();
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- l.info("compressing "+fn);
|
|
|
- if((flag&0x0000_0002)==2)//Gzip
|
|
|
- {
|
|
|
- s = new PipedInputStream(65536);
|
|
|
- pbasedir=baseDir;
|
|
|
- pfn=fn;
|
|
|
- new Thread(new Runnable(){
|
|
|
- public void run()
|
|
|
- {
|
|
|
- int rw=0;
|
|
|
- GZIPOutputStream compdata = null;
|
|
|
- try
|
|
|
- {
|
|
|
- compdata = new GZIPOutputStream(new PipedOutputStream(s), true);
|
|
|
- FileInputStream FI = new FileInputStream(pbasedir+"\\"+pfn);
|
|
|
- int returned=4096;
|
|
|
-
|
|
|
- byte[] bdata = new byte[4096];
|
|
|
- do
|
|
|
- {
|
|
|
- returned = FI.read(bdata);
|
|
|
- compdata.write(bdata,0,returned);
|
|
|
- compdata.flush();
|
|
|
- rw+=returned;
|
|
|
- l.trace(rw);
|
|
|
- l.trace("<<"+returned);
|
|
|
-
|
|
|
- }
|
|
|
- while(returned==4096);
|
|
|
- }
|
|
|
- catch (IOException ex)
|
|
|
- {
|
|
|
- l.trace("GAH!");
|
|
|
- ex.printStackTrace();
|
|
|
- }
|
|
|
- finally
|
|
|
- {
|
|
|
- try
|
|
|
- {
|
|
|
- compdata.close();
|
|
|
- }
|
|
|
- catch (IOException ex)
|
|
|
- {
|
|
|
- l.trace(">>GAH!");
|
|
|
- ex.printStackTrace();
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }).start();
|
|
|
- Thread.sleep(10);
|
|
|
- //komprimiermich :P
|
|
|
- int returned=4096;
|
|
|
- long filesizecomp = 0;
|
|
|
- int rw=0;
|
|
|
- byte[] bdata = new byte[4096];
|
|
|
- do
|
|
|
- {
|
|
|
- returned = s.read(bdata);
|
|
|
- achv.write(bdata,0,returned);
|
|
|
- filesizecomp+=returned;
|
|
|
- rw+=returned;
|
|
|
- l.trace(">>"+rw);
|
|
|
- }
|
|
|
- while(returned==4096);
|
|
|
- fileSizesRawComp[i] = filesizecomp;
|
|
|
- l.info("finished COmpressing");
|
|
|
- }
|
|
|
-
|
|
|
- }
|
|
|
- }
|
|
|
- //recreate_offsets
|
|
|
- for (int i = 0; i < fileSizesRaw.length; i++)
|
|
|
- {
|
|
|
- offsets[i] = ByteBuffer.allocate(8).putLong(baseoffset).array();
|
|
|
- baseoffset +=fileSizesRawComp[i]; //offset für nxte datei vorbereiten;
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- headerAssem = ByteBuffer.allocate(headerSize+8);
|
|
|
- //header zusammensetzen;
|
|
|
- bo = 0;
|
|
|
- headerAssem.put(headerSizeattrib);
|
|
|
- bo+=4;//weiterschieben
|
|
|
- headerAssem.position(bo);
|
|
|
- headerAssem.put(headerElemCount);
|
|
|
- bo+=4;
|
|
|
- headerAssem.position(bo);
|
|
|
-
|
|
|
- for (int i = 0; i < offsets.length; i++)
|
|
|
- {
|
|
|
- headerAssem.put(bo,filenamelengths[i]);
|
|
|
- bo++;
|
|
|
- headerAssem.position(bo);
|
|
|
- headerAssem.put(fileBytes[i]);
|
|
|
- bo+=((int)filenamelengths[i]&0xff);
|
|
|
- headerAssem.position(bo);
|
|
|
- headerAssem.put(fileSizes[i]);
|
|
|
- bo+=8;
|
|
|
- headerAssem.position(bo);
|
|
|
- headerAssem.put(fileSizesComp[i]);
|
|
|
- bo+=8;
|
|
|
- headerAssem.position(bo);
|
|
|
- headerAssem.put(offsets[i]);
|
|
|
- bo+=8;
|
|
|
- headerAssem.position(bo);
|
|
|
- headerAssem.put(flags[i]);
|
|
|
- bo+=4;
|
|
|
- headerAssem.position(bo);
|
|
|
- }
|
|
|
- header=headerAssem.array();
|
|
|
- achv.seek(8);
|
|
|
- achv.write(header);
|
|
|
- }
|
|
|
- catch(IOException e)
|
|
|
- {
|
|
|
- e.printStackTrace();
|
|
|
- }
|
|
|
- catch (InterruptedException ex)
|
|
|
- {
|
|
|
- ex.printStackTrace();
|
|
|
- }
|
|
|
- preloadHeader();
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- public void dumpAllIntoDirectory(String path)
|
|
|
- {
|
|
|
- try
|
|
|
- {
|
|
|
- long[] fileoffsets = header_foffsets;
|
|
|
- long[] filesizes = header_fsizes;
|
|
|
- String[] filenames = header_fnames;
|
|
|
- int[] flags = header_flags;
|
|
|
- long[] cprsize = header_fcompsizes;
|
|
|
- for (int i = 0; i < fileoffsets.length; i++)
|
|
|
- {
|
|
|
- long offs = fileoffsets[i];
|
|
|
- String fn = path+File.separator+filenames[i];
|
|
|
- long fs = cprsize[i];
|
|
|
- achv.seek(offs);
|
|
|
- FileTK.ensuredirExistence(fn);
|
|
|
- final RandomAccessFile dump = new RandomAccessFile(fn,"rwd");
|
|
|
- long dist = fs;
|
|
|
- if((flags[i]&0x0000_0003)!=3)
|
|
|
- {
|
|
|
- while(achv.getFilePointer()<fs+offs)
|
|
|
- {
|
|
|
- byte[] buf;
|
|
|
- if(dist>CHUNK_SIZE)
|
|
|
- {
|
|
|
- buf = new byte[CHUNK_SIZE];
|
|
|
- dist-=CHUNK_SIZE;
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- buf = new byte[(int)dist];
|
|
|
- }
|
|
|
- achv.read(buf, 0, buf.length); //TODO effizioenteren weg finden!!!
|
|
|
- dump.write(buf);
|
|
|
- /*
|
|
|
- byte[] buf = new byte[1];
|
|
|
- achv.read(buf, 0, 1); //TODO effizioenteren weg finden!!!
|
|
|
- dump.write(buf);*/
|
|
|
- }
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- final PipedOutputStream s = new PipedOutputStream();
|
|
|
- new Thread(new Runnable()
|
|
|
- {
|
|
|
- public void run()
|
|
|
- {
|
|
|
- try
|
|
|
- {
|
|
|
- GZIPInputStream decomp = new GZIPInputStream(new PipedInputStream(s,65536));
|
|
|
- Thread.sleep(30);
|
|
|
- int readamount = 4096;
|
|
|
- byte[] buffer = new byte[4096];
|
|
|
- do
|
|
|
- {
|
|
|
- readamount=decomp.read(buffer);
|
|
|
- dump.write(buffer,0,readamount);
|
|
|
- }
|
|
|
- while(readamount==4096);
|
|
|
- }
|
|
|
- catch (IOException ex)
|
|
|
- {
|
|
|
- ex.printStackTrace();
|
|
|
- }
|
|
|
- catch (InterruptedException ex)
|
|
|
- {
|
|
|
- ex.printStackTrace();
|
|
|
- }
|
|
|
- }
|
|
|
- }).start();
|
|
|
- while(achv.getFilePointer()<fs+offs)
|
|
|
- {
|
|
|
- byte[] buf;
|
|
|
- if(dist>CHUNK_SIZE)
|
|
|
- {
|
|
|
- buf = new byte[CHUNK_SIZE];
|
|
|
- dist-=CHUNK_SIZE;
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- buf = new byte[(int)dist];
|
|
|
- }
|
|
|
- achv.read(buf, 0, buf.length); //TODO effizioenteren weg finden!!!
|
|
|
- s.write(buf);
|
|
|
- /*
|
|
|
- byte[] buf = new byte[1];
|
|
|
- achv.read(buf, 0, 1); //TODO effizioenteren weg finden!!!
|
|
|
- dump.write(buf);*/
|
|
|
- }
|
|
|
- }
|
|
|
- dump.close();
|
|
|
-
|
|
|
- }
|
|
|
- }
|
|
|
- catch(IOException e)
|
|
|
- {
|
|
|
-
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- public void extractFileToDisk(String achvpath,String destdir)
|
|
|
- {
|
|
|
- try
|
|
|
- {
|
|
|
- int pos = arraytools.getElemPosInArray(header_fnames, achvpath);
|
|
|
- //byte[] target = new byte[(int)header_fsizes[pos]];
|
|
|
- achv.seek(header_foffsets[pos]);
|
|
|
- FileTK.ensuredirExistence(destdir+File.separator+achvpath);
|
|
|
- final RandomAccessFile dump = new RandomAccessFile(destdir+File.separator+achvpath, "rwd");
|
|
|
- long fs=header_fsizes[pos],readInVol=header_fsizes[pos],offs=header_foffsets[pos];
|
|
|
- if((header_flags[pos]&0x0000_0003)!=3)
|
|
|
- {
|
|
|
- while(achv.getFilePointer()<fs+offs)
|
|
|
- {
|
|
|
- byte[] buf;
|
|
|
- if(fs>CHUNK_SIZE)
|
|
|
- {
|
|
|
- buf = new byte[CHUNK_SIZE];
|
|
|
- fs-=CHUNK_SIZE;
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- buf = new byte[(int)fs];
|
|
|
- }
|
|
|
- achv.read(buf, 0, buf.length); //TODO effizioenteren weg finden!!!
|
|
|
- dump.write(buf);
|
|
|
- /*
|
|
|
- byte[] buf = new byte[1];
|
|
|
- achv.read(buf, 0, 1); //TODO effizioenteren weg finden!!!
|
|
|
- dump.write(buf);*/
|
|
|
- }
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- final PipedOutputStream s = new PipedOutputStream();
|
|
|
- new Thread(new Runnable()
|
|
|
- {
|
|
|
- public void run()
|
|
|
- {
|
|
|
- try
|
|
|
- {
|
|
|
- GZIPInputStream decomp = new GZIPInputStream(new PipedInputStream(s,65536));
|
|
|
- Thread.sleep(30);
|
|
|
- int readamount = 4096;
|
|
|
- byte[] buffer = new byte[4096];
|
|
|
- do
|
|
|
- {
|
|
|
- readamount=decomp.read(buffer);
|
|
|
- dump.write(buffer,0,readamount);
|
|
|
- }
|
|
|
- while(readamount==4096);
|
|
|
- }
|
|
|
- catch (IOException ex)
|
|
|
- {
|
|
|
- ex.printStackTrace();
|
|
|
- }
|
|
|
- catch (InterruptedException ex)
|
|
|
- {
|
|
|
- ex.printStackTrace();
|
|
|
- }
|
|
|
- }
|
|
|
- }).start();
|
|
|
- while(achv.getFilePointer()<fs+offs)
|
|
|
- {
|
|
|
- byte[] buf;
|
|
|
- if(fs>CHUNK_SIZE)
|
|
|
- {
|
|
|
- buf = new byte[CHUNK_SIZE];
|
|
|
- fs-=CHUNK_SIZE;
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- buf = new byte[(int)fs];
|
|
|
- }
|
|
|
- achv.read(buf, 0, buf.length); //TODO effizioenteren weg finden!!!
|
|
|
- s.write(buf);
|
|
|
- /*
|
|
|
- byte[] buf = new byte[1];
|
|
|
- achv.read(buf, 0, 1); //TODO effizioenteren weg finden!!!
|
|
|
- dump.write(buf);*/
|
|
|
- }
|
|
|
- }
|
|
|
- dump.close();
|
|
|
- }
|
|
|
- catch (IOException ex)
|
|
|
- {
|
|
|
- ex.printStackTrace();
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- /**
|
|
|
- * Liest eine Datei in jnen String aus. wird nur für kleine files empfohlen;
|
|
|
- * @param archivefile Datei im Archiv; muss in achvfile sein
|
|
|
- * @return Inhalt als String
|
|
|
- */
|
|
|
- public String getFileContent(String archivefile)
|
|
|
- {
|
|
|
- try
|
|
|
- {
|
|
|
-
|
|
|
- extractFileToDisk(archivefile, System.getenv("temp"));
|
|
|
- RandomAccessFile temp = new RandomAccessFile(System.getenv("temp")+File.separator+archivefile, "r");
|
|
|
- byte[] target = new byte[(int)temp.length()];
|
|
|
- temp.read(target);
|
|
|
- return new String(target);
|
|
|
- }
|
|
|
- catch (IOException ex)
|
|
|
- {
|
|
|
- ex.printStackTrace();
|
|
|
- }
|
|
|
- return "";
|
|
|
- }
|
|
|
-
|
|
|
- public String[] getFileList()
|
|
|
- {
|
|
|
- //hauptarbeit wird beim einlesen der datei gemacht;
|
|
|
- return header_fnames;
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- /*
|
|
|
- public void AddFile(String pathOnDisk)
|
|
|
- {
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- throw new UnsupportedOperationException("Muss dies noch machen");
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- public void removeFile(String path)
|
|
|
- {
|
|
|
- throw new UnsupportedOperationException("Muss dies noch machen");
|
|
|
- }*/
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- public void unload()
|
|
|
- {
|
|
|
- try
|
|
|
- {
|
|
|
- achv.close();
|
|
|
- }
|
|
|
- catch (IOException ex)
|
|
|
- {
|
|
|
- ex.printStackTrace();
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- //#################################################################################################################
|
|
|
- //#################################################################################################################
|
|
|
- //#################################################################################################################
|
|
|
- //#################################################################################################################
|
|
|
- //#################################################################################################################
|
|
|
- //static utility methods for faster archivehandling
|
|
|
-
|
|
|
-
|
|
|
- public static void ExtractFilesToPath(String archivefile, String path)
|
|
|
- {
|
|
|
- IZpackage temp = new IZpackage(archivefile);
|
|
|
- temp.dumpAllIntoDirectory(path);
|
|
|
- temp.unload();
|
|
|
- }
|
|
|
-
|
|
|
- public static void wrapArchive(String archive,String packdir)
|
|
|
- {
|
|
|
-
|
|
|
- String[] filecontent = FileTK.walkDirectoryRecursively(packdir);
|
|
|
- ArrayList<String> fnp = new ArrayList<>();
|
|
|
- String sfxmodpath=null;
|
|
|
- IZpackage temp = new IZpackage(archive);
|
|
|
- for (int i=0;i<filecontent.length;i++)//String fn : filecontent)
|
|
|
- {
|
|
|
- String fn=filecontent[i];
|
|
|
-
|
|
|
- if(!FileTK.isDir(fn))
|
|
|
- {
|
|
|
- l.trace("adding FN:"+fn);
|
|
|
- fn=FileTK.getRelativePath(fn, packdir);
|
|
|
- if(File.separator.equals("(.)(.)")) //sollte nicht sein :P
|
|
|
- fn = fn.substring(2);
|
|
|
- else
|
|
|
- fn = fn.substring(3);
|
|
|
-
|
|
|
- if(fn.contains("sfxmod.jar")&&!fn.contains(File.separator))
|
|
|
- {
|
|
|
- sfxmodpath=fn;
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- fnp.add(fn);
|
|
|
- }
|
|
|
- l.trace("added FName:"+fn);
|
|
|
-
|
|
|
- }
|
|
|
- }
|
|
|
- if(sfxmodpath!=null)
|
|
|
- {fnp.add(sfxmodpath);}
|
|
|
- temp.createArchive(packdir, fnp.toArray(new String[0]));
|
|
|
- temp.unload();
|
|
|
- }
|
|
|
- public String getPath()
|
|
|
- {
|
|
|
- return packageToRead;
|
|
|
- }
|
|
|
-}
|
|
|
+/*
|
|
|
+ * Copyright (C) 2015 iZc
|
|
|
+ *
|
|
|
+ * 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 3 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, see <http://www.gnu.org/licenses/>.
|
|
|
+ */
|
|
|
+package de.nplusc.izc.tools.IOtools.iZformats;
|
|
|
+
|
|
|
+import de.nplusc.izc.tools.IOtools.FileTK;
|
|
|
+import de.nplusc.izc.tools.baseTools.arraytools;
|
|
|
+import java.io.File;
|
|
|
+import java.io.FileInputStream;
|
|
|
+import java.io.FileNotFoundException;
|
|
|
+import java.io.IOException;
|
|
|
+import java.io.PipedInputStream;
|
|
|
+import java.io.PipedOutputStream;
|
|
|
+import java.io.RandomAccessFile;
|
|
|
+import java.nio.ByteBuffer;
|
|
|
+import java.util.ArrayList;
|
|
|
+import java.util.zip.GZIPInputStream;
|
|
|
+import java.util.zip.GZIPOutputStream;
|
|
|
+import org.apache.logging.log4j.LogManager;
|
|
|
+import org.apache.logging.log4j.Logger;
|
|
|
+
|
|
|
+/**
|
|
|
+ *
|
|
|
+ * @author LH
|
|
|
+ */
|
|
|
+public class IZpackage
|
|
|
+{
|
|
|
+ private static final Logger l = LogManager.getLogger();
|
|
|
+ static final byte[] magicHeader = new byte[]{(byte)0x00, (byte)0x14, (byte)0x19, (byte)0x40, (byte)0xFA ,(byte)0xC4 ,(byte)0x0A};
|
|
|
+ public static final int CHUNK_SIZE=4096;
|
|
|
+
|
|
|
+
|
|
|
+ //Formatspezifikation
|
|
|
+ //magicHEader=0x00 00 14 19 40 FA C4 0A
|
|
|
+ //länge desy eigentlichen headers in byte >in 4 bytes speichern
|
|
|
+ //anzahl eintrage; 4 bytes//wichtig beim einlesen
|
|
|
+ //Headerformat: 1 byte Länge des pfades; Pfad (0-255 lang; relativ)8 bytes Offset innerhalb Datei; 8 byte Größe 4 bytes flags
|
|
|
+ //Dann dateien in einem Bytestrom aneinandergehängt
|
|
|
+
|
|
|
+ private String packageToRead;
|
|
|
+ //private boolean archiveIsreadOnly;//TODO: erkennen ob medium Disk ist
|
|
|
+ private RandomAccessFile achv=null;
|
|
|
+ private String[] header_fnames = null;;
|
|
|
+ private long[] header_fsizes=null;
|
|
|
+ private long[] header_fcompsizes=null;
|
|
|
+ private long[] header_foffsets=null;
|
|
|
+ private int[] header_flags = null;
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ public IZpackage(String path)
|
|
|
+ {
|
|
|
+ packageToRead = path;
|
|
|
+ try
|
|
|
+ {
|
|
|
+ //NOP
|
|
|
+ achv = new RandomAccessFile(packageToRead, "rwd");//VOID:readonly als absicherung gegen derps
|
|
|
+ if(FileTK.checkDirExist(path))
|
|
|
+ {
|
|
|
+ preloadHeader();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ catch (FileNotFoundException ex)
|
|
|
+ {
|
|
|
+ ex.printStackTrace();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ void preloadHeader()
|
|
|
+ {
|
|
|
+ try
|
|
|
+ {
|
|
|
+ achv.seek(8);//headergröße anspringen
|
|
|
+ byte[] hr = new byte[4];
|
|
|
+ achv.readFully(hr);
|
|
|
+ int hs = ByteBuffer.allocate(4).put(hr).getInt(0);
|
|
|
+
|
|
|
+ achv.seek(12);//elementeanzahl anspringen
|
|
|
+ byte[] fc = new byte[4];
|
|
|
+ achv.readFully(fc);
|
|
|
+ int elemcount= ByteBuffer.allocate(4).put(fc).getInt(0);
|
|
|
+
|
|
|
+ achv.seek(16);
|
|
|
+ byte[] hdrr = new byte[hs];
|
|
|
+ achv.readFully(hdrr);//einlesen des headers
|
|
|
+ ByteBuffer hdr = ByteBuffer.allocate(hs).put(hdrr);
|
|
|
+ int pos = 0;//position innerhalb headers
|
|
|
+
|
|
|
+
|
|
|
+ String[] filenames = new String[elemcount];
|
|
|
+ int[] flags = new int[elemcount];
|
|
|
+ long[] filesizes=new long[elemcount],filesizescomp=new long[elemcount],fileoffsets=new long[elemcount];//die 4 arrays initialisieren um den header abzubilden //dateinamenlänge wird nur intern benötigt
|
|
|
+
|
|
|
+
|
|
|
+ for (int i = 0; i < elemcount; i++)
|
|
|
+ {
|
|
|
+ int flength = hdr.get(pos)&0xFF;//vorzeichen rausbügeln; danke javaquirk
|
|
|
+ pos++;
|
|
|
+ byte[] filenameraw = new byte[flength];
|
|
|
+ hdr.position(pos);
|
|
|
+ hdr.get(filenameraw);
|
|
|
+ pos+=flength;
|
|
|
+ filenames[i]=new String(filenameraw);//etwas unkonventionell :P dürfte nicht jeder wissen dass das geht
|
|
|
+ filesizes[i]=hdr.getLong(pos);
|
|
|
+ pos+=8;
|
|
|
+ filesizescomp[i]=hdr.getLong(pos);
|
|
|
+ pos+=8;
|
|
|
+ fileoffsets[i]=hdr.getLong(pos);
|
|
|
+ pos+=8;
|
|
|
+ flags[i] = hdr.getInt();
|
|
|
+ pos+=4;
|
|
|
+ }
|
|
|
+ //header eingelesen;
|
|
|
+ //header dumpen
|
|
|
+ header_fnames = filenames;
|
|
|
+ header_foffsets = fileoffsets;
|
|
|
+ header_fsizes = filesizes;
|
|
|
+ header_flags = flags;
|
|
|
+ header_fcompsizes = filesizescomp;
|
|
|
+ }
|
|
|
+ catch(IOException e)
|
|
|
+ {
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public static int FLAG_COMPRESSED = 0;
|
|
|
+ public static int FLAG_GZIP = 1;
|
|
|
+ String pbasedir,pfn;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * erstellt ein neues iZpack-archiv unter dem im Objekt hinterlegtren archiv
|
|
|
+ * @param baseDir Wurzelverzeichnis der input-files
|
|
|
+ * @param files Dateien; relativ zu basedir; da dies die struktur im archiv spieschelt
|
|
|
+ */
|
|
|
+ PipedInputStream s;
|
|
|
+ public void createArchive(String baseDir,String... files)
|
|
|
+ {
|
|
|
+ byte[] filenamelengths = new byte[files.length];
|
|
|
+ byte[][] fileBytes = new byte[files.length][];
|
|
|
+ byte[][] fileSizes = new byte[files.length][8];
|
|
|
+ byte[][] fileSizesComp = new byte[files.length][8];
|
|
|
+ byte[][] flags = new byte[files.length][4];
|
|
|
+ //boolean[][]flagsreadable = new boolean[files.length][32];//32 flags maximum
|
|
|
+ long[] fileSizesRaw = new long[files.length];//nötig für uncompress
|
|
|
+ long[] fileSizesRawComp = new long[files.length];//nötig um Offset auszurechnen und einzuspeixern
|
|
|
+ byte[][] offsets = new byte[files.length][8];//wird erst zum schluss befüllt;
|
|
|
+ int headerSize=0;
|
|
|
+ //oFFSET0ALLE VORHERIGEN OFFSETS + HEADERSIZE+ 8DA MAGISCHE KENNUNG9
|
|
|
+ for (int i = 0; i < files.length; i++)
|
|
|
+ {
|
|
|
+ String fileToGetSize = baseDir+File.separator+files[i];
|
|
|
+
|
|
|
+ long fileSize = new File(fileToGetSize).length();
|
|
|
+ fileSizesRaw[i] = fileSize;
|
|
|
+ //byte[] filesizearr = new byte[8];
|
|
|
+ /*for (int j = 0; j < 8; j++)
|
|
|
+ {
|
|
|
+ filesizearr[7-j] = (byte)(fileSize%256);//schneidet niederwertigstes bit heraus;
|
|
|
+ fileSize/=256;//ein byte nach rechts dudeln;
|
|
|
+
|
|
|
+ }*/
|
|
|
+ int flag=0; //TODO compresshandler //zzz_sfx=nocompress; jpg;png;mp3 etc=noCOmpress, too
|
|
|
+ /*
|
|
|
+ String ftype = FileTK.getFileExt(files[i]);
|
|
|
+ String[] nocompress = new String[]{"docx","rar","7z","gz","bz2","jpg","png","xlsx","wmv","mp4","flv","mov","mp3","flac","m4a","wma"};
|
|
|
+ for (String ble : nocompress)
|
|
|
+ {
|
|
|
+ if(ftype!=null&&(ftype.equalsIgnoreCase(ble)||(files[i].equalsIgnoreCase("zzz_sfxmod.jar"))))//erkennt die gesperrten dateinamen/typen für kkomprimieren
|
|
|
+ {
|
|
|
+ flag = flag&(3^0xffffffff); //rausnehmen der compres und gzip-bits
|
|
|
+ }
|
|
|
+ }*/
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ fileSizes[i]=ByteBuffer.allocate(8).putLong(fileSize).array();
|
|
|
+ fileSizesComp[i]=ByteBuffer.allocate(8).putLong(fileSize).array();
|
|
|
+ fileBytes[i]=files[i].getBytes();
|
|
|
+ flags[i] = ByteBuffer.allocate(4).putInt(flag).array();
|
|
|
+ filenamelengths[i] = (byte)(fileBytes[i].length);
|
|
|
+ //size //compsize //offset //dateinamenlänge //längenmarkerbyte //flags
|
|
|
+ headerSize += 8+ 8+ 8+ filenamelengths[i]+1 +4;
|
|
|
+ }
|
|
|
+ long baseoffset = headerSize+16; //Header+magischeKennung;
|
|
|
+
|
|
|
+ //create_offsets
|
|
|
+ for (int i = 0; i < fileSizesRaw.length; i++)
|
|
|
+ {
|
|
|
+
|
|
|
+ offsets[i] = ByteBuffer.allocate(8).putLong(baseoffset).array();
|
|
|
+ baseoffset +=fileSizesRawComp[i]; //offset für nxte datei vorbereiten;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ byte[] header;//= new byte[headerSize+4];//headerSizeFlag wird mit eingebettet//elemcount auch;
|
|
|
+ byte[] headerSizeattrib = ByteBuffer.allocate(4).putInt(headerSize).array();
|
|
|
+ ByteBuffer headerAssem = ByteBuffer.allocate(headerSize+8);
|
|
|
+ //header zusammensetzen;
|
|
|
+ byte[] headerElemCount = ByteBuffer.allocate(4).putInt(files.length).array();
|
|
|
+ int bo = 0;
|
|
|
+ headerAssem.put(headerSizeattrib);
|
|
|
+ bo+=4;//weiterschieben
|
|
|
+ headerAssem.position(bo);
|
|
|
+ headerAssem.put(headerElemCount);
|
|
|
+ bo+=4;
|
|
|
+ headerAssem.position(bo);
|
|
|
+
|
|
|
+ for (int i = 0; i < offsets.length; i++)
|
|
|
+ {
|
|
|
+ headerAssem.put(bo,filenamelengths[i]);
|
|
|
+ bo++;
|
|
|
+ headerAssem.position(bo);
|
|
|
+ headerAssem.put(fileBytes[i]);
|
|
|
+ bo+=((int)filenamelengths[i]&0xff);
|
|
|
+ headerAssem.position(bo);
|
|
|
+ headerAssem.put(fileSizes[i]);
|
|
|
+ bo+=8;
|
|
|
+ headerAssem.position(bo);
|
|
|
+ headerAssem.put(fileSizesComp[i]);
|
|
|
+ bo+=8;
|
|
|
+ headerAssem.position(bo);
|
|
|
+ headerAssem.put(offsets[i]);
|
|
|
+ bo+=8;
|
|
|
+ headerAssem.position(bo);
|
|
|
+ headerAssem.put(flags[i]);
|
|
|
+ bo+=4;
|
|
|
+ headerAssem.position(bo);
|
|
|
+ }
|
|
|
+ header=headerAssem.array();
|
|
|
+ //RandomAccessFile achv=null;
|
|
|
+ try
|
|
|
+ {
|
|
|
+ achv.seek(0);//zurücksetzen der datei;
|
|
|
+ achv.write(magicHeader);
|
|
|
+ achv.seek(8);
|
|
|
+ achv.write(header); //header wird am schluss erzeugt da Komprimierung vorhanden
|
|
|
+ //achv.write(header);
|
|
|
+ l.info("Filecount:{}",files.length);
|
|
|
+ try
|
|
|
+ {
|
|
|
+ //for (String fn : files)
|
|
|
+ Thread.sleep(50);
|
|
|
+ }
|
|
|
+ catch (InterruptedException ex)
|
|
|
+ {
|
|
|
+ ex.printStackTrace();
|
|
|
+ }
|
|
|
+ for(int i = 0;i<files.length;i++)
|
|
|
+ {
|
|
|
+ String fn = files[i];
|
|
|
+ int flag = ByteBuffer.allocate(4).put(flags[i]).getInt(0);
|
|
|
+ l.trace(flag+"|"+fn);
|
|
|
+ if((flag&0x0000_0001)==0) //compressed-flag ausmaskieren
|
|
|
+ {
|
|
|
+ //java.io.FileNotFoundException: /buildpipeline/iZsetup/64b/predist\lib/ToolKit.jar
|
|
|
+ //ARSCHFICKRIGE BACKSLASHE HABEN HIER NIX ZU SUCHEN
|
|
|
+ RandomAccessFile readIn = new RandomAccessFile(baseDir+File.separator+fn, "rwd");
|
|
|
+ long readInVol = readIn.length();
|
|
|
+ while(readIn.getFilePointer()<readIn.length())
|
|
|
+ {
|
|
|
+ byte[] buf;
|
|
|
+ if(readInVol>CHUNK_SIZE)
|
|
|
+ {
|
|
|
+ buf = new byte[CHUNK_SIZE];
|
|
|
+ readInVol-=CHUNK_SIZE;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ buf = new byte[(int)readInVol];
|
|
|
+ }
|
|
|
+ readIn.read(buf, 0, buf.length); //TODO effizioenteren weg finden!!!
|
|
|
+ achv.write(buf);
|
|
|
+ fileSizesRawComp[i] = fileSizesRaw[i];
|
|
|
+ }
|
|
|
+ readIn.close();
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ l.info("compressing "+fn);
|
|
|
+ if((flag&0x0000_0002)==2)//Gzip
|
|
|
+ {
|
|
|
+ s = new PipedInputStream(65536);
|
|
|
+ pbasedir=baseDir;
|
|
|
+ pfn=fn;
|
|
|
+ new Thread(new Runnable(){
|
|
|
+ public void run()
|
|
|
+ {
|
|
|
+ int rw=0;
|
|
|
+ GZIPOutputStream compdata = null;
|
|
|
+ try
|
|
|
+ {
|
|
|
+ compdata = new GZIPOutputStream(new PipedOutputStream(s), true);
|
|
|
+ FileInputStream FI = new FileInputStream(pbasedir+"\\"+pfn);
|
|
|
+ int returned=4096;
|
|
|
+
|
|
|
+ byte[] bdata = new byte[4096];
|
|
|
+ do
|
|
|
+ {
|
|
|
+ returned = FI.read(bdata);
|
|
|
+ compdata.write(bdata,0,returned);
|
|
|
+ compdata.flush();
|
|
|
+ rw+=returned;
|
|
|
+ l.trace(rw);
|
|
|
+ l.trace("<<"+returned);
|
|
|
+
|
|
|
+ }
|
|
|
+ while(returned==4096);
|
|
|
+ }
|
|
|
+ catch (IOException ex)
|
|
|
+ {
|
|
|
+ l.trace("GAH!");
|
|
|
+ ex.printStackTrace();
|
|
|
+ }
|
|
|
+ finally
|
|
|
+ {
|
|
|
+ try
|
|
|
+ {
|
|
|
+ compdata.close();
|
|
|
+ }
|
|
|
+ catch (IOException ex)
|
|
|
+ {
|
|
|
+ l.trace(">>GAH!");
|
|
|
+ ex.printStackTrace();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }).start();
|
|
|
+ Thread.sleep(10);
|
|
|
+ //komprimiermich :P
|
|
|
+ int returned=4096;
|
|
|
+ long filesizecomp = 0;
|
|
|
+ int rw=0;
|
|
|
+ byte[] bdata = new byte[4096];
|
|
|
+ do
|
|
|
+ {
|
|
|
+ returned = s.read(bdata);
|
|
|
+ achv.write(bdata,0,returned);
|
|
|
+ filesizecomp+=returned;
|
|
|
+ rw+=returned;
|
|
|
+ l.trace(">>"+rw);
|
|
|
+ }
|
|
|
+ while(returned==4096);
|
|
|
+ fileSizesRawComp[i] = filesizecomp;
|
|
|
+ l.info("finished COmpressing");
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+ }
|
|
|
+ //recreate_offsets
|
|
|
+ for (int i = 0; i < fileSizesRaw.length; i++)
|
|
|
+ {
|
|
|
+ offsets[i] = ByteBuffer.allocate(8).putLong(baseoffset).array();
|
|
|
+ baseoffset +=fileSizesRawComp[i]; //offset für nxte datei vorbereiten;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ headerAssem = ByteBuffer.allocate(headerSize+8);
|
|
|
+ //header zusammensetzen;
|
|
|
+ bo = 0;
|
|
|
+ headerAssem.put(headerSizeattrib);
|
|
|
+ bo+=4;//weiterschieben
|
|
|
+ headerAssem.position(bo);
|
|
|
+ headerAssem.put(headerElemCount);
|
|
|
+ bo+=4;
|
|
|
+ headerAssem.position(bo);
|
|
|
+
|
|
|
+ for (int i = 0; i < offsets.length; i++)
|
|
|
+ {
|
|
|
+ headerAssem.put(bo,filenamelengths[i]);
|
|
|
+ bo++;
|
|
|
+ headerAssem.position(bo);
|
|
|
+ headerAssem.put(fileBytes[i]);
|
|
|
+ bo+=((int)filenamelengths[i]&0xff);
|
|
|
+ headerAssem.position(bo);
|
|
|
+ headerAssem.put(fileSizes[i]);
|
|
|
+ bo+=8;
|
|
|
+ headerAssem.position(bo);
|
|
|
+ headerAssem.put(fileSizesComp[i]);
|
|
|
+ bo+=8;
|
|
|
+ headerAssem.position(bo);
|
|
|
+ headerAssem.put(offsets[i]);
|
|
|
+ bo+=8;
|
|
|
+ headerAssem.position(bo);
|
|
|
+ headerAssem.put(flags[i]);
|
|
|
+ bo+=4;
|
|
|
+ headerAssem.position(bo);
|
|
|
+ }
|
|
|
+ header=headerAssem.array();
|
|
|
+ achv.seek(8);
|
|
|
+ achv.write(header);
|
|
|
+ }
|
|
|
+ catch(IOException e)
|
|
|
+ {
|
|
|
+ e.printStackTrace();
|
|
|
+ }
|
|
|
+ catch (InterruptedException ex)
|
|
|
+ {
|
|
|
+ ex.printStackTrace();
|
|
|
+ }
|
|
|
+ preloadHeader();
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ public void dumpAllIntoDirectory(String path)
|
|
|
+ {
|
|
|
+ try
|
|
|
+ {
|
|
|
+ long[] fileoffsets = header_foffsets;
|
|
|
+ long[] filesizes = header_fsizes;
|
|
|
+ String[] filenames = header_fnames;
|
|
|
+ int[] flags = header_flags;
|
|
|
+ long[] cprsize = header_fcompsizes;
|
|
|
+ for (int i = 0; i < fileoffsets.length; i++)
|
|
|
+ {
|
|
|
+ long offs = fileoffsets[i];
|
|
|
+ String fn = path+File.separator+filenames[i];
|
|
|
+ long fs = cprsize[i];
|
|
|
+ achv.seek(offs);
|
|
|
+ FileTK.ensuredirExistence(fn);
|
|
|
+ final RandomAccessFile dump = new RandomAccessFile(fn,"rwd");
|
|
|
+ long dist = fs;
|
|
|
+ if((flags[i]&0x0000_0003)!=3)
|
|
|
+ {
|
|
|
+ while(achv.getFilePointer()<fs+offs)
|
|
|
+ {
|
|
|
+ byte[] buf;
|
|
|
+ if(dist>CHUNK_SIZE)
|
|
|
+ {
|
|
|
+ buf = new byte[CHUNK_SIZE];
|
|
|
+ dist-=CHUNK_SIZE;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ buf = new byte[(int)dist];
|
|
|
+ }
|
|
|
+ achv.read(buf, 0, buf.length); //TODO effizioenteren weg finden!!!
|
|
|
+ dump.write(buf);
|
|
|
+ /*
|
|
|
+ byte[] buf = new byte[1];
|
|
|
+ achv.read(buf, 0, 1); //TODO effizioenteren weg finden!!!
|
|
|
+ dump.write(buf);*/
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ final PipedOutputStream s = new PipedOutputStream();
|
|
|
+ new Thread(new Runnable()
|
|
|
+ {
|
|
|
+ public void run()
|
|
|
+ {
|
|
|
+ try
|
|
|
+ {
|
|
|
+ GZIPInputStream decomp = new GZIPInputStream(new PipedInputStream(s,65536));
|
|
|
+ Thread.sleep(30);
|
|
|
+ int readamount = 4096;
|
|
|
+ byte[] buffer = new byte[4096];
|
|
|
+ do
|
|
|
+ {
|
|
|
+ readamount=decomp.read(buffer);
|
|
|
+ dump.write(buffer,0,readamount);
|
|
|
+ }
|
|
|
+ while(readamount==4096);
|
|
|
+ }
|
|
|
+ catch (IOException ex)
|
|
|
+ {
|
|
|
+ ex.printStackTrace();
|
|
|
+ }
|
|
|
+ catch (InterruptedException ex)
|
|
|
+ {
|
|
|
+ ex.printStackTrace();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }).start();
|
|
|
+ while(achv.getFilePointer()<fs+offs)
|
|
|
+ {
|
|
|
+ byte[] buf;
|
|
|
+ if(dist>CHUNK_SIZE)
|
|
|
+ {
|
|
|
+ buf = new byte[CHUNK_SIZE];
|
|
|
+ dist-=CHUNK_SIZE;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ buf = new byte[(int)dist];
|
|
|
+ }
|
|
|
+ achv.read(buf, 0, buf.length); //TODO effizioenteren weg finden!!!
|
|
|
+ s.write(buf);
|
|
|
+ /*
|
|
|
+ byte[] buf = new byte[1];
|
|
|
+ achv.read(buf, 0, 1); //TODO effizioenteren weg finden!!!
|
|
|
+ dump.write(buf);*/
|
|
|
+ }
|
|
|
+ }
|
|
|
+ dump.close();
|
|
|
+
|
|
|
+ }
|
|
|
+ }
|
|
|
+ catch(IOException e)
|
|
|
+ {
|
|
|
+
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public void extractFileToDisk(String achvpath,String destdir)
|
|
|
+ {
|
|
|
+ try
|
|
|
+ {
|
|
|
+ int pos = arraytools.getElemPosInArray(header_fnames, achvpath);
|
|
|
+ //byte[] target = new byte[(int)header_fsizes[pos]];
|
|
|
+ achv.seek(header_foffsets[pos]);
|
|
|
+ FileTK.ensuredirExistence(destdir+File.separator+achvpath);
|
|
|
+ final RandomAccessFile dump = new RandomAccessFile(destdir+File.separator+achvpath, "rwd");
|
|
|
+ long fs=header_fsizes[pos],readInVol=header_fsizes[pos],offs=header_foffsets[pos];
|
|
|
+ if((header_flags[pos]&0x0000_0003)!=3)
|
|
|
+ {
|
|
|
+ while(achv.getFilePointer()<fs+offs)
|
|
|
+ {
|
|
|
+ byte[] buf;
|
|
|
+ if(fs>CHUNK_SIZE)
|
|
|
+ {
|
|
|
+ buf = new byte[CHUNK_SIZE];
|
|
|
+ fs-=CHUNK_SIZE;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ buf = new byte[(int)fs];
|
|
|
+ }
|
|
|
+ achv.read(buf, 0, buf.length); //TODO effizioenteren weg finden!!!
|
|
|
+ dump.write(buf);
|
|
|
+ /*
|
|
|
+ byte[] buf = new byte[1];
|
|
|
+ achv.read(buf, 0, 1); //TODO effizioenteren weg finden!!!
|
|
|
+ dump.write(buf);*/
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ final PipedOutputStream s = new PipedOutputStream();
|
|
|
+ new Thread(new Runnable()
|
|
|
+ {
|
|
|
+ public void run()
|
|
|
+ {
|
|
|
+ try
|
|
|
+ {
|
|
|
+ GZIPInputStream decomp = new GZIPInputStream(new PipedInputStream(s,65536));
|
|
|
+ Thread.sleep(30);
|
|
|
+ int readamount = 4096;
|
|
|
+ byte[] buffer = new byte[4096];
|
|
|
+ do
|
|
|
+ {
|
|
|
+ readamount=decomp.read(buffer);
|
|
|
+ dump.write(buffer,0,readamount);
|
|
|
+ }
|
|
|
+ while(readamount==4096);
|
|
|
+ }
|
|
|
+ catch (IOException ex)
|
|
|
+ {
|
|
|
+ ex.printStackTrace();
|
|
|
+ }
|
|
|
+ catch (InterruptedException ex)
|
|
|
+ {
|
|
|
+ ex.printStackTrace();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }).start();
|
|
|
+ while(achv.getFilePointer()<fs+offs)
|
|
|
+ {
|
|
|
+ byte[] buf;
|
|
|
+ if(fs>CHUNK_SIZE)
|
|
|
+ {
|
|
|
+ buf = new byte[CHUNK_SIZE];
|
|
|
+ fs-=CHUNK_SIZE;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ buf = new byte[(int)fs];
|
|
|
+ }
|
|
|
+ achv.read(buf, 0, buf.length); //TODO effizioenteren weg finden!!!
|
|
|
+ s.write(buf);
|
|
|
+ /*
|
|
|
+ byte[] buf = new byte[1];
|
|
|
+ achv.read(buf, 0, 1); //TODO effizioenteren weg finden!!!
|
|
|
+ dump.write(buf);*/
|
|
|
+ }
|
|
|
+ }
|
|
|
+ dump.close();
|
|
|
+ }
|
|
|
+ catch (IOException ex)
|
|
|
+ {
|
|
|
+ ex.printStackTrace();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Liest eine Datei in jnen String aus. wird nur für kleine files empfohlen;
|
|
|
+ * @param archivefile Datei im Archiv; muss in achvfile sein
|
|
|
+ * @return Inhalt als String
|
|
|
+ */
|
|
|
+ public String getFileContent(String archivefile)
|
|
|
+ {
|
|
|
+ try
|
|
|
+ {
|
|
|
+
|
|
|
+ extractFileToDisk(archivefile, System.getenv("temp"));
|
|
|
+ RandomAccessFile temp = new RandomAccessFile(System.getenv("temp")+File.separator+archivefile, "r");
|
|
|
+ byte[] target = new byte[(int)temp.length()];
|
|
|
+ temp.read(target);
|
|
|
+ return new String(target);
|
|
|
+ }
|
|
|
+ catch (IOException ex)
|
|
|
+ {
|
|
|
+ ex.printStackTrace();
|
|
|
+ }
|
|
|
+ return "";
|
|
|
+ }
|
|
|
+
|
|
|
+ public String[] getFileList()
|
|
|
+ {
|
|
|
+ //hauptarbeit wird beim einlesen der datei gemacht;
|
|
|
+ return header_fnames;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ /*
|
|
|
+ public void AddFile(String pathOnDisk)
|
|
|
+ {
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ throw new UnsupportedOperationException("Muss dies noch machen");
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ public void removeFile(String path)
|
|
|
+ {
|
|
|
+ throw new UnsupportedOperationException("Muss dies noch machen");
|
|
|
+ }*/
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ public void unload()
|
|
|
+ {
|
|
|
+ try
|
|
|
+ {
|
|
|
+ achv.close();
|
|
|
+ }
|
|
|
+ catch (IOException ex)
|
|
|
+ {
|
|
|
+ ex.printStackTrace();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ //#################################################################################################################
|
|
|
+ //#################################################################################################################
|
|
|
+ //#################################################################################################################
|
|
|
+ //#################################################################################################################
|
|
|
+ //#################################################################################################################
|
|
|
+ //static utility methods for faster archivehandling
|
|
|
+
|
|
|
+
|
|
|
+ public static void ExtractFilesToPath(String archivefile, String path)
|
|
|
+ {
|
|
|
+ IZpackage temp = new IZpackage(archivefile);
|
|
|
+ temp.dumpAllIntoDirectory(path);
|
|
|
+ temp.unload();
|
|
|
+ }
|
|
|
+
|
|
|
+ public static void wrapArchive(String archive,String packdir)
|
|
|
+ {
|
|
|
+
|
|
|
+ String[] filecontent = FileTK.walkDirectoryRecursively(packdir);
|
|
|
+ ArrayList<String> fnp = new ArrayList<>();
|
|
|
+ String sfxmodpath=null;
|
|
|
+ IZpackage temp = new IZpackage(archive);
|
|
|
+ for (int i=0;i<filecontent.length;i++)//String fn : filecontent)
|
|
|
+ {
|
|
|
+ String fn=filecontent[i];
|
|
|
+
|
|
|
+ if(!FileTK.isDir(fn))
|
|
|
+ {
|
|
|
+ l.trace("adding FN:"+fn);
|
|
|
+ fn=FileTK.getRelativePath(fn, packdir);
|
|
|
+ if(File.separator.equals("(.)(.)")) //sollte nicht sein :P
|
|
|
+ fn = fn.substring(2);
|
|
|
+ else
|
|
|
+ if(fn.startsWith(".."+File.separator))
|
|
|
+ fn = fn.substring(3);
|
|
|
+
|
|
|
+ if(fn.contains("sfxmod.jar")&&!fn.contains(File.separator))
|
|
|
+ {
|
|
|
+ sfxmodpath=fn;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ fnp.add(fn);
|
|
|
+ }
|
|
|
+ l.trace("added FName:"+fn);
|
|
|
+
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if(sfxmodpath!=null)
|
|
|
+ {fnp.add(sfxmodpath);}
|
|
|
+ temp.createArchive(packdir, fnp.toArray(new String[0]));
|
|
|
+ temp.unload();
|
|
|
+ }
|
|
|
+ public String getPath()
|
|
|
+ {
|
|
|
+ return packageToRead;
|
|
|
+ }
|
|
|
+}
|