From 45529bcca9d462c12269b81127f7de26aafc47bb Mon Sep 17 00:00:00 2001 From: Andrew Dolgov Date: Tue, 10 Jul 2018 19:03:37 +0300 Subject: add cbr support via junrar library --- .../main/java/org/fox/ttcomics2/ComicPager.java | 15 +- .../java/org/fox/ttcomics2/DatabaseHelper.java | 8 +- .../org/fox/ttcomics2/archive/CbrComicArchive.java | 128 +++ .../org/fox/ttcomics2/archive/CbzComicArchive.java | 6 +- .../java/org/fox/ttcomics2/junrar/Archive.java | 505 +++++++++ .../org/fox/ttcomics2/junrar/UnrarCallback.java | 9 + .../main/java/org/fox/ttcomics2/junrar/Volume.java | 30 + .../org/fox/ttcomics2/junrar/VolumeManager.java | 24 + .../java/org/fox/ttcomics2/junrar/crc/RarCRC.java | 138 +++ .../org/fox/ttcomics2/junrar/crypt/Rijndael.java | 21 + .../ttcomics2/junrar/exception/RarException.java | 59 + .../org/fox/ttcomics2/junrar/impl/FileVolume.java | 55 + .../ttcomics2/junrar/impl/FileVolumeManager.java | 50 + .../fox/ttcomics2/junrar/io/IReadOnlyAccess.java | 36 + .../junrar/io/InputStreamReadOnlyAccessFile.java | 46 + .../ttcomics2/junrar/io/RandomAccessStream.java | 195 ++++ .../main/java/org/fox/ttcomics2/junrar/io/Raw.java | 166 +++ .../junrar/io/ReadOnlyAccessByteArray.java | 74 ++ .../ttcomics2/junrar/io/ReadOnlyAccessFile.java | 45 + .../junrar/io/ReadOnlyAccessInputStream.java | 73 ++ .../org/fox/ttcomics2/junrar/rarfile/AVHeader.java | 60 + .../fox/ttcomics2/junrar/rarfile/BaseBlock.java | 160 +++ .../fox/ttcomics2/junrar/rarfile/BlockHeader.java | 62 + .../ttcomics2/junrar/rarfile/CommentHeader.java | 64 ++ .../org/fox/ttcomics2/junrar/rarfile/EAHeader.java | 68 ++ .../fox/ttcomics2/junrar/rarfile/EndArcHeader.java | 56 + .../fox/ttcomics2/junrar/rarfile/FileHeader.java | 367 ++++++ .../ttcomics2/junrar/rarfile/FileNameDecoder.java | 76 ++ .../fox/ttcomics2/junrar/rarfile/HostSystem.java | 65 ++ .../ttcomics2/junrar/rarfile/MacInfoHeader.java | 60 + .../fox/ttcomics2/junrar/rarfile/MainHeader.java | 108 ++ .../fox/ttcomics2/junrar/rarfile/MarkHeader.java | 73 ++ .../ttcomics2/junrar/rarfile/NewSubHeaderType.java | 48 + .../ttcomics2/junrar/rarfile/ProtectHeader.java | 62 + .../fox/ttcomics2/junrar/rarfile/SignHeader.java | 54 + .../ttcomics2/junrar/rarfile/SubBlockHeader.java | 58 + .../junrar/rarfile/SubBlockHeaderType.java | 60 + .../ttcomics2/junrar/rarfile/UnixOwnersHeader.java | 72 ++ .../ttcomics2/junrar/rarfile/UnrarHeadertype.java | 107 ++ .../fox/ttcomics2/junrar/unpack/ComprDataIO.java | 356 ++++++ .../org/fox/ttcomics2/junrar/unpack/Unpack.java | 1029 +++++++++++++++++ .../org/fox/ttcomics2/junrar/unpack/Unpack15.java | 554 +++++++++ .../org/fox/ttcomics2/junrar/unpack/Unpack20.java | 567 ++++++++++ .../fox/ttcomics2/junrar/unpack/UnpackFilter.java | 87 ++ .../junrar/unpack/decode/AudioVariables.java | 138 +++ .../ttcomics2/junrar/unpack/decode/BitDecode.java | 24 + .../ttcomics2/junrar/unpack/decode/CodeType.java | 20 + .../ttcomics2/junrar/unpack/decode/Compress.java | 39 + .../fox/ttcomics2/junrar/unpack/decode/Decode.java | 46 + .../ttcomics2/junrar/unpack/decode/DistDecode.java | 26 + .../ttcomics2/junrar/unpack/decode/FilterType.java | 24 + .../ttcomics2/junrar/unpack/decode/LitDecode.java | 25 + .../junrar/unpack/decode/LowDistDecode.java | 26 + .../ttcomics2/junrar/unpack/decode/MultDecode.java | 26 + .../ttcomics2/junrar/unpack/decode/RepDecode.java | 25 + .../junrar/unpack/ppm/AnalyzeHeapDump.java | 85 ++ .../ttcomics2/junrar/unpack/ppm/BlockTypes.java | 47 + .../fox/ttcomics2/junrar/unpack/ppm/FreqData.java | 81 ++ .../fox/ttcomics2/junrar/unpack/ppm/ModelPPM.java | 637 +++++++++++ .../ttcomics2/junrar/unpack/ppm/PPMContext.java | 442 ++++++++ .../fox/ttcomics2/junrar/unpack/ppm/Pointer.java | 38 + .../ttcomics2/junrar/unpack/ppm/RangeCoder.java | 153 +++ .../ttcomics2/junrar/unpack/ppm/RarMemBlock.java | 118 ++ .../fox/ttcomics2/junrar/unpack/ppm/RarNode.java | 61 + .../ttcomics2/junrar/unpack/ppm/SEE2Context.java | 96 ++ .../org/fox/ttcomics2/junrar/unpack/ppm/State.java | 113 ++ .../fox/ttcomics2/junrar/unpack/ppm/StateRef.java | 86 ++ .../ttcomics2/junrar/unpack/ppm/SubAllocator.java | 416 +++++++ .../fox/ttcomics2/junrar/unpack/vm/BitInput.java | 71 ++ .../org/fox/ttcomics2/junrar/unpack/vm/RarVM.java | 1196 ++++++++++++++++++++ .../fox/ttcomics2/junrar/unpack/vm/VMCmdFlags.java | 75 ++ .../fox/ttcomics2/junrar/unpack/vm/VMCommands.java | 220 ++++ .../fox/ttcomics2/junrar/unpack/vm/VMFlags.java | 52 + .../fox/ttcomics2/junrar/unpack/vm/VMOpType.java | 60 + .../junrar/unpack/vm/VMPreparedCommand.java | 58 + .../junrar/unpack/vm/VMPreparedOperand.java | 59 + .../junrar/unpack/vm/VMPreparedProgram.java | 112 ++ .../unpack/vm/VMStandardFilterSignature.java | 58 + .../junrar/unpack/vm/VMStandardFilters.java | 73 ++ .../ttcomics2/junrar/unsigned/UnsignedByte.java | 61 + .../ttcomics2/junrar/unsigned/UnsignedInteger.java | 23 + .../ttcomics2/junrar/unsigned/UnsignedLong.java | 23 + .../ttcomics2/junrar/unsigned/UnsignedShort.java | 23 + .../fox/ttcomics2/junrar/util/VolumeHelper.java | 97 ++ 84 files changed, 10997 insertions(+), 12 deletions(-) create mode 100755 org.fox.ttcomics/src/main/java/org/fox/ttcomics2/archive/CbrComicArchive.java mode change 100644 => 100755 org.fox.ttcomics/src/main/java/org/fox/ttcomics2/archive/CbzComicArchive.java create mode 100755 org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/Archive.java create mode 100644 org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/UnrarCallback.java create mode 100755 org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/Volume.java create mode 100644 org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/VolumeManager.java create mode 100644 org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/crc/RarCRC.java create mode 100644 org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/crypt/Rijndael.java create mode 100644 org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/exception/RarException.java create mode 100755 org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/impl/FileVolume.java create mode 100755 org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/impl/FileVolumeManager.java create mode 100644 org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/io/IReadOnlyAccess.java create mode 100644 org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/io/InputStreamReadOnlyAccessFile.java create mode 100644 org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/io/RandomAccessStream.java create mode 100644 org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/io/Raw.java create mode 100644 org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/io/ReadOnlyAccessByteArray.java create mode 100644 org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/io/ReadOnlyAccessFile.java create mode 100644 org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/io/ReadOnlyAccessInputStream.java create mode 100644 org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/rarfile/AVHeader.java create mode 100644 org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/rarfile/BaseBlock.java create mode 100644 org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/rarfile/BlockHeader.java create mode 100644 org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/rarfile/CommentHeader.java create mode 100644 org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/rarfile/EAHeader.java create mode 100644 org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/rarfile/EndArcHeader.java create mode 100755 org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/rarfile/FileHeader.java create mode 100644 org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/rarfile/FileNameDecoder.java create mode 100644 org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/rarfile/HostSystem.java create mode 100644 org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/rarfile/MacInfoHeader.java create mode 100644 org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/rarfile/MainHeader.java create mode 100644 org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/rarfile/MarkHeader.java create mode 100644 org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/rarfile/NewSubHeaderType.java create mode 100644 org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/rarfile/ProtectHeader.java create mode 100644 org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/rarfile/SignHeader.java create mode 100644 org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/rarfile/SubBlockHeader.java create mode 100644 org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/rarfile/SubBlockHeaderType.java create mode 100644 org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/rarfile/UnixOwnersHeader.java create mode 100644 org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/rarfile/UnrarHeadertype.java create mode 100755 org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unpack/ComprDataIO.java create mode 100755 org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unpack/Unpack.java create mode 100755 org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unpack/Unpack15.java create mode 100755 org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unpack/Unpack20.java create mode 100644 org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unpack/UnpackFilter.java create mode 100644 org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unpack/decode/AudioVariables.java create mode 100644 org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unpack/decode/BitDecode.java create mode 100644 org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unpack/decode/CodeType.java create mode 100644 org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unpack/decode/Compress.java create mode 100644 org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unpack/decode/Decode.java create mode 100644 org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unpack/decode/DistDecode.java create mode 100644 org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unpack/decode/FilterType.java create mode 100644 org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unpack/decode/LitDecode.java create mode 100644 org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unpack/decode/LowDistDecode.java create mode 100644 org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unpack/decode/MultDecode.java create mode 100644 org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unpack/decode/RepDecode.java create mode 100644 org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unpack/ppm/AnalyzeHeapDump.java create mode 100644 org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unpack/ppm/BlockTypes.java create mode 100644 org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unpack/ppm/FreqData.java create mode 100755 org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unpack/ppm/ModelPPM.java create mode 100644 org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unpack/ppm/PPMContext.java create mode 100644 org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unpack/ppm/Pointer.java create mode 100755 org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unpack/ppm/RangeCoder.java create mode 100644 org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unpack/ppm/RarMemBlock.java create mode 100644 org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unpack/ppm/RarNode.java create mode 100644 org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unpack/ppm/SEE2Context.java create mode 100644 org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unpack/ppm/State.java create mode 100644 org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unpack/ppm/StateRef.java create mode 100644 org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unpack/ppm/SubAllocator.java create mode 100644 org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unpack/vm/BitInput.java create mode 100755 org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unpack/vm/RarVM.java create mode 100644 org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unpack/vm/VMCmdFlags.java create mode 100644 org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unpack/vm/VMCommands.java create mode 100644 org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unpack/vm/VMFlags.java create mode 100644 org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unpack/vm/VMOpType.java create mode 100644 org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unpack/vm/VMPreparedCommand.java create mode 100644 org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unpack/vm/VMPreparedOperand.java create mode 100644 org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unpack/vm/VMPreparedProgram.java create mode 100644 org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unpack/vm/VMStandardFilterSignature.java create mode 100644 org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unpack/vm/VMStandardFilters.java create mode 100644 org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unsigned/UnsignedByte.java create mode 100644 org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unsigned/UnsignedInteger.java create mode 100644 org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unsigned/UnsignedLong.java create mode 100644 org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unsigned/UnsignedShort.java create mode 100644 org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/util/VolumeHelper.java (limited to 'org.fox.ttcomics') diff --git a/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/ComicPager.java b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/ComicPager.java index 022514e..b421021 100755 --- a/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/ComicPager.java +++ b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/ComicPager.java @@ -18,6 +18,7 @@ import android.widget.TextView; import com.ToxicBakery.viewpager.transforms.DepthPageTransformer; +import org.fox.ttcomics2.archive.CbrComicArchive; import org.fox.ttcomics2.archive.CbzComicArchive; import org.fox.ttcomics2.archive.ComicArchive; import org.fox.ttcomics2.utils.IVTViewPager; @@ -81,7 +82,7 @@ public class ComicPager extends Fragment { } public int getPosition() { - IVTViewPager pager = (IVTViewPager) getView().findViewById(R.id.comics_pager); + IVTViewPager pager = getView().findViewById(R.id.comics_pager); if (pager != null) { return pager.getCurrentItem(); @@ -95,7 +96,7 @@ public class ComicPager extends Fragment { } public void setCurrentItem(int item) { - IVTViewPager pager = (IVTViewPager) getView().findViewById(R.id.comics_pager); + IVTViewPager pager = getView().findViewById(R.id.comics_pager); if (pager != null) { try { @@ -121,7 +122,7 @@ public class ComicPager extends Fragment { m_adapter = new PagerAdapter(getActivity().getSupportFragmentManager()); - final IVTViewPager pager = (IVTViewPager) view.findViewById(R.id.comics_pager); + final IVTViewPager pager = view.findViewById(R.id.comics_pager); if (savedInstanceState != null) { m_fileName = savedInstanceState.getString("fileName"); @@ -130,19 +131,21 @@ public class ComicPager extends Fragment { try { if (m_fileName.toLowerCase().matches(".*\\.(cbz|zip)")) { m_archive = new CbzComicArchive(m_fileName); + } else if (m_fileName.toLowerCase().matches(".*\\.(cbr|rar)")) { + m_archive = new CbrComicArchive(m_fileName); } final int position = m_activity.m_databaseHelper.getLastPosition(m_fileName); - m_currentPage = (TextView) view.findViewById(R.id.comics_page); - m_totalPages = (TextView) view.findViewById(R.id.comics_total_pages); + m_currentPage = view.findViewById(R.id.comics_page); + m_totalPages = view.findViewById(R.id.comics_total_pages); m_currentPage.setText(String.valueOf(position + 1)); m_totalPages.setText(String.valueOf(m_archive.getCount())); m_bottomBar = view.findViewById(R.id.comics_bottom_bar); - m_seekBar = (SeekBar) view.findViewById(R.id.comics_seek_bar); + m_seekBar = view.findViewById(R.id.comics_seek_bar); m_seekBar.setMax(m_archive.getCount() - 1); m_seekBar.setProgress(position); m_seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { diff --git a/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/DatabaseHelper.java b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/DatabaseHelper.java index c37c1d4..ead1e69 100755 --- a/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/DatabaseHelper.java +++ b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/DatabaseHelper.java @@ -1,5 +1,6 @@ package org.fox.ttcomics2; +import android.annotation.SuppressLint; import android.content.Context; import android.database.Cursor; import android.database.SQLException; @@ -9,6 +10,7 @@ import android.database.sqlite.SQLiteStatement; import android.os.AsyncTask; import android.provider.BaseColumns; +import org.fox.ttcomics2.archive.CbrComicArchive; import org.fox.ttcomics2.archive.CbzComicArchive; import org.fox.ttcomics2.archive.ComicArchive; @@ -278,7 +280,7 @@ public class DatabaseHelper extends SQLiteOpenHelper { public void rescanDirectory(String comicsDir, final DirectoryScanListener listener) { - AsyncTask task = new AsyncTask() { + @SuppressLint("StaticFieldLeak") AsyncTask task = new AsyncTask() { @Override protected void onProgressUpdate(Integer... progress) { @@ -310,12 +312,14 @@ public class DatabaseHelper extends SQLiteOpenHelper { if (archive.isDirectory()) { setSize(filePath, ComicListFragment.SIZE_DIR); - } else if (archive.getName().toLowerCase().matches(".*\\.(cbz|zip)")) { + } else if (archive.getName().toLowerCase().matches(".*\\.(cbz|zip|cbr|rar)")) { try { ComicArchive cba = null; if (archive.getName().toLowerCase().matches(".*\\.(cbz|zip)")) { cba = new CbzComicArchive(filePath); + } else if (archive.getName().toLowerCase().matches(".*\\.(cbr|rar)")) { + cba = new CbrComicArchive(filePath); } if (cba != null && cba.getCount() > 0) { diff --git a/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/archive/CbrComicArchive.java b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/archive/CbrComicArchive.java new file mode 100755 index 0000000..9e37bbc --- /dev/null +++ b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/archive/CbrComicArchive.java @@ -0,0 +1,128 @@ +package org.fox.ttcomics2.archive; + +import android.os.Parcel; +import android.os.Parcelable; + +import org.fox.ttcomics2.junrar.Archive; +import org.fox.ttcomics2.junrar.exception.RarException; +import org.fox.ttcomics2.junrar.rarfile.FileHeader; +import org.fox.ttcomics2.utils.NaturalOrderComparator; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.Collections; + +public class CbrComicArchive extends ComicArchive { + private final String TAG = this.getClass().getSimpleName(); + + private String m_fileName; + private Archive m_archive; + private ArrayList m_entries = new ArrayList<>(); + + @Override + public int getCount() { + return m_entries.size(); + } + + @Override + public InputStream getItem(int index) throws IOException { + FileHeader fh = m_entries.get(index).m_fh; + + ByteArrayOutputStream out = new ByteArrayOutputStream(); + + try { + m_archive.extractFile(fh, out); + + return new ByteArrayInputStream(out.toByteArray()); + } catch (RarException e) { + e.printStackTrace(); + + return null; + } + } + + private void initialize() throws IOException { + try { + m_archive = new Archive(new File(m_fileName)); + } catch (RarException e) { + e.printStackTrace(); + return; + } + + while (true) { + FileHeader fh = m_archive.nextFileHeader(); + + if (fh == null) + break; + + if (fh.isDirectory() || fh.isEncrypted()) + continue; + + m_entries.add(new CbrEntry(fh)); + } + + Collections.sort(m_entries, new NaturalOrderComparator()); + } + + public CbrComicArchive(String fileName) throws IOException { + m_fileName = fileName; + + initialize(); + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel out, int flags) { + out.writeString(m_fileName); + } + + public void readFromParcel(Parcel in) { + m_fileName = in.readString(); + } + + public CbrComicArchive(Parcel in) throws IOException { + readFromParcel(in); + + initialize(); + } + + @SuppressWarnings("rawtypes") + public static final Parcelable.Creator CREATOR = + new Parcelable.Creator() { + public CbrComicArchive createFromParcel(Parcel in) { + try { + return new CbrComicArchive(in); + } catch (IOException e) { + e.printStackTrace(); + + return null; + } + } + + public CbrComicArchive[] newArray(int size) { + return new CbrComicArchive[size]; + } + }; + + private class CbrEntry { + FileHeader m_fh; + + CbrEntry(FileHeader fh) { + m_fh = fh; + } + + @Override + public String toString() { + return m_fh.getFileNameString(); + } + + } +} diff --git a/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/archive/CbzComicArchive.java b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/archive/CbzComicArchive.java old mode 100644 new mode 100755 index dc68fd1..8757353 --- a/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/archive/CbzComicArchive.java +++ b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/archive/CbzComicArchive.java @@ -18,12 +18,11 @@ public class CbzComicArchive extends ComicArchive { private String m_fileName; private ZipFile m_zipFile; - private int m_count; private ArrayList m_entries = new ArrayList(); @Override public int getCount() { - return m_count; + return m_entries.size(); } @Override @@ -31,7 +30,7 @@ public class CbzComicArchive extends ComicArchive { return m_zipFile.getInputStream(m_entries.get(index)); } - protected void initialize() throws IOException { + private void initialize() throws IOException { m_zipFile = new ZipFile(m_fileName); Enumeration e = m_zipFile.entries(); @@ -40,7 +39,6 @@ public class CbzComicArchive extends ComicArchive { ZipEntry ze = e.nextElement(); if (!ze.isDirectory() && isValidComic(ze.getName())) { m_entries.add(ze); - m_count++; } } diff --git a/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/Archive.java b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/Archive.java new file mode 100755 index 0000000..ba430aa --- /dev/null +++ b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/Archive.java @@ -0,0 +1,505 @@ +/* + * Copyright (c) 2007 innoSysTec (R) GmbH, Germany. All rights reserved. + * Original author: Edmund Wagner + * Creation date: 22.05.2007 + * + * Source: $HeadURL$ + * Last changed: $LastChangedDate$ + * + * the unrar licence applies to all junrar source and binary distributions + * you are not allowed to use this source to re-create the RAR compression + * algorithm + * + * Here some html entities which can be used for escaping javadoc tags: + * "&": "&" or "&" + * "<": "<" or "<" + * ">": ">" or ">" + * "@": "@" + */ +package org.fox.ttcomics2.junrar; + +import org.fox.ttcomics2.junrar.exception.RarException; +import org.fox.ttcomics2.junrar.exception.RarException.RarExceptionType; +import org.fox.ttcomics2.junrar.impl.FileVolumeManager; +import org.fox.ttcomics2.junrar.io.IReadOnlyAccess; +import org.fox.ttcomics2.junrar.rarfile.AVHeader; +import org.fox.ttcomics2.junrar.rarfile.BaseBlock; +import org.fox.ttcomics2.junrar.rarfile.BlockHeader; +import org.fox.ttcomics2.junrar.rarfile.CommentHeader; +import org.fox.ttcomics2.junrar.rarfile.EAHeader; +import org.fox.ttcomics2.junrar.rarfile.EndArcHeader; +import org.fox.ttcomics2.junrar.rarfile.FileHeader; +import org.fox.ttcomics2.junrar.rarfile.MacInfoHeader; +import org.fox.ttcomics2.junrar.rarfile.MainHeader; +import org.fox.ttcomics2.junrar.rarfile.MarkHeader; +import org.fox.ttcomics2.junrar.rarfile.ProtectHeader; +import org.fox.ttcomics2.junrar.rarfile.SignHeader; +import org.fox.ttcomics2.junrar.rarfile.SubBlockHeader; +import org.fox.ttcomics2.junrar.rarfile.UnixOwnersHeader; +import org.fox.ttcomics2.junrar.rarfile.UnrarHeadertype; +import org.fox.ttcomics2.junrar.unpack.ComprDataIO; +import org.fox.ttcomics2.junrar.unpack.Unpack; + +import java.io.Closeable; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.PipedInputStream; +import java.io.PipedOutputStream; +import java.util.ArrayList; +import java.util.List; +import java.util.logging.Level; +import java.util.logging.Logger; + + +public class Archive implements Closeable { + private static Logger logger = Logger.getLogger(Archive.class.getName()); + private final UnrarCallback unrarCallback; + private final ComprDataIO dataIO; + private final List headers = new ArrayList(); + private IReadOnlyAccess rof; + private MarkHeader markHead = null; + + private MainHeader newMhd = null; + + private Unpack unpack; + + private int currentHeaderIndex; + + private long totalPackedSize = 0L; + + private long totalPackedRead = 0L; + + private VolumeManager volumeManager; + private Volume volume; + + public Archive(VolumeManager volumeManager) throws RarException, + IOException { + this(volumeManager, null); + } + + public Archive(VolumeManager volumeManager, UnrarCallback unrarCallback) + throws RarException, IOException { + this.volumeManager = volumeManager; + this.unrarCallback = unrarCallback; + + setVolume(this.volumeManager.nextArchive(this, null)); + dataIO = new ComprDataIO(this); + } + + public Archive(File firstVolume) throws RarException, IOException { + this(new FileVolumeManager(firstVolume), null); + } + + public Archive(File firstVolume, UnrarCallback unrarCallback) + throws RarException, IOException { + this(new FileVolumeManager(firstVolume), unrarCallback); + } + + // public File getFile() { + // return file; + // } + // + // void setFile(File file) throws IOException { + // this.file = file; + // setFile(new ReadOnlyAccessFile(file), file.length()); + // } + + private void setFile(IReadOnlyAccess file, long length) throws IOException { + totalPackedSize = 0L; + totalPackedRead = 0L; + close(); + rof = file; + try { + readHeaders(length); + } catch (Exception e) { + logger.log(Level.WARNING, + "exception in archive constructor maybe file is encrypted " + + "or currupt", e); + // ignore exceptions to allow exraction of working files in + // corrupt archive + } + // Calculate size of packed data + for (BaseBlock block : headers) { + if (block.getHeaderType() == UnrarHeadertype.FileHeader) { + totalPackedSize += ((FileHeader) block).getFullPackSize(); + } + } + if (unrarCallback != null) { + unrarCallback.volumeProgressChanged(totalPackedRead, + totalPackedSize); + } + } + + public void bytesReadRead(int count) { + if (count > 0) { + totalPackedRead += count; + if (unrarCallback != null) { + unrarCallback.volumeProgressChanged(totalPackedRead, + totalPackedSize); + } + } + } + + public IReadOnlyAccess getRof() { + return rof; + } + + public List getFileHeaders() { + List list = new ArrayList(); + for (BaseBlock block : headers) { + if (block.getHeaderType().equals(UnrarHeadertype.FileHeader)) { + list.add((FileHeader) block); + } + } + return list; + } + + public FileHeader nextFileHeader() { + int n = headers.size(); + while (currentHeaderIndex < n) { + BaseBlock block = headers.get(currentHeaderIndex++); + if (block.getHeaderType() == UnrarHeadertype.FileHeader) { + return (FileHeader) block; + } + } + return null; + } + + public UnrarCallback getUnrarCallback() { + return unrarCallback; + } + + public boolean isEncrypted() { + if (newMhd != null) { + return newMhd.isEncrypted(); + } else { + throw new NullPointerException("mainheader is null"); + } + } + + private void readHeaders(long fileLength) throws IOException, RarException { + markHead = null; + newMhd = null; + headers.clear(); + currentHeaderIndex = 0; + int toRead = 0; + + while (true) { + int size = 0; + long newpos = 0; + byte[] baseBlockBuffer = new byte[BaseBlock.BaseBlockSize]; + + long position = rof.getPosition(); + + // Weird, but is trying to read beyond the end of the file + if (position >= fileLength) { + break; + } + + // logger.info("\n--------reading header--------"); + size = rof.readFully(baseBlockBuffer, BaseBlock.BaseBlockSize); + if (size == 0) { + break; + } + BaseBlock block = new BaseBlock(baseBlockBuffer); + + block.setPositionInFile(position); + + switch (block.getHeaderType()) { + + case MarkHeader: + markHead = new MarkHeader(block); + if (!markHead.isSignature()) { + throw new RarException( + RarExceptionType.badRarArchive); + } + headers.add(markHead); + // markHead.print(); + break; + + case MainHeader: + toRead = block.hasEncryptVersion() ? MainHeader.mainHeaderSizeWithEnc + : MainHeader.mainHeaderSize; + byte[] mainbuff = new byte[toRead]; + rof.readFully(mainbuff, toRead); + MainHeader mainhead = new MainHeader(block, mainbuff); + headers.add(mainhead); + this.newMhd = mainhead; + if (newMhd.isEncrypted()) { + throw new RarException( + RarExceptionType.rarEncryptedException); + } + // mainhead.print(); + break; + + case SignHeader: + toRead = SignHeader.signHeaderSize; + byte[] signBuff = new byte[toRead]; + rof.readFully(signBuff, toRead); + SignHeader signHead = new SignHeader(block, signBuff); + headers.add(signHead); + // logger.info("HeaderType: SignHeader"); + + break; + + case AvHeader: + toRead = AVHeader.avHeaderSize; + byte[] avBuff = new byte[toRead]; + rof.readFully(avBuff, toRead); + AVHeader avHead = new AVHeader(block, avBuff); + headers.add(avHead); + // logger.info("headertype: AVHeader"); + break; + + case CommHeader: + toRead = CommentHeader.commentHeaderSize; + byte[] commBuff = new byte[toRead]; + rof.readFully(commBuff, toRead); + CommentHeader commHead = new CommentHeader(block, commBuff); + headers.add(commHead); + // logger.info("method: "+commHead.getUnpMethod()+"; 0x"+ + // Integer.toHexString(commHead.getUnpMethod())); + newpos = commHead.getPositionInFile() + + commHead.getHeaderSize(); + rof.setPosition(newpos); + + break; + case EndArcHeader: + + toRead = 0; + if (block.hasArchiveDataCRC()) { + toRead += EndArcHeader.endArcArchiveDataCrcSize; + } + if (block.hasVolumeNumber()) { + toRead += EndArcHeader.endArcVolumeNumberSize; + } + EndArcHeader endArcHead; + if (toRead > 0) { + byte[] endArchBuff = new byte[toRead]; + rof.readFully(endArchBuff, toRead); + endArcHead = new EndArcHeader(block, endArchBuff); + // logger.info("HeaderType: endarch\ndatacrc:"+ + // endArcHead.getArchiveDataCRC()); + } else { + // logger.info("HeaderType: endarch - no Data"); + endArcHead = new EndArcHeader(block, null); + } + headers.add(endArcHead); + // logger.info("\n--------end header--------"); + return; + + default: + byte[] blockHeaderBuffer = new byte[BlockHeader.blockHeaderSize]; + rof.readFully(blockHeaderBuffer, BlockHeader.blockHeaderSize); + BlockHeader blockHead = new BlockHeader(block, + blockHeaderBuffer); + + switch (blockHead.getHeaderType()) { + case NewSubHeader: + case FileHeader: + toRead = blockHead.getHeaderSize() + - BlockHeader.BaseBlockSize + - BlockHeader.blockHeaderSize; + byte[] fileHeaderBuffer = new byte[toRead]; + rof.readFully(fileHeaderBuffer, toRead); + + FileHeader fh = new FileHeader(blockHead, fileHeaderBuffer); + headers.add(fh); + newpos = fh.getPositionInFile() + fh.getHeaderSize() + + fh.getFullPackSize(); + rof.setPosition(newpos); + break; + + case ProtectHeader: + toRead = blockHead.getHeaderSize() + - BlockHeader.BaseBlockSize + - BlockHeader.blockHeaderSize; + byte[] protectHeaderBuffer = new byte[toRead]; + rof.readFully(protectHeaderBuffer, toRead); + ProtectHeader ph = new ProtectHeader(blockHead, + protectHeaderBuffer); + + newpos = ph.getPositionInFile() + ph.getHeaderSize() + + ph.getDataSize(); + rof.setPosition(newpos); + break; + + case SubHeader: { + byte[] subHeadbuffer = new byte[SubBlockHeader.SubBlockHeaderSize]; + rof.readFully(subHeadbuffer, + SubBlockHeader.SubBlockHeaderSize); + SubBlockHeader subHead = new SubBlockHeader(blockHead, + subHeadbuffer); + subHead.print(); + switch (subHead.getSubType()) { + case MAC_HEAD: { + byte[] macHeaderbuffer = new byte[MacInfoHeader.MacInfoHeaderSize]; + rof.readFully(macHeaderbuffer, + MacInfoHeader.MacInfoHeaderSize); + MacInfoHeader macHeader = new MacInfoHeader(subHead, + macHeaderbuffer); + macHeader.print(); + headers.add(macHeader); + + break; + } + // TODO implement other subheaders + case BEEA_HEAD: + break; + case EA_HEAD: { + byte[] eaHeaderBuffer = new byte[EAHeader.EAHeaderSize]; + rof.readFully(eaHeaderBuffer, EAHeader.EAHeaderSize); + EAHeader eaHeader = new EAHeader(subHead, + eaHeaderBuffer); + eaHeader.print(); + headers.add(eaHeader); + + break; + } + case NTACL_HEAD: + break; + case STREAM_HEAD: + break; + case UO_HEAD: + toRead = subHead.getHeaderSize(); + toRead -= BaseBlock.BaseBlockSize; + toRead -= BlockHeader.blockHeaderSize; + toRead -= SubBlockHeader.SubBlockHeaderSize; + byte[] uoHeaderBuffer = new byte[toRead]; + rof.readFully(uoHeaderBuffer, toRead); + UnixOwnersHeader uoHeader = new UnixOwnersHeader( + subHead, uoHeaderBuffer); + uoHeader.print(); + headers.add(uoHeader); + break; + default: + break; + } + + break; + } + default: + logger.warning("Unknown Header"); + throw new RarException(RarExceptionType.notRarArchive); + + } + } + // logger.info("\n--------end header--------"); + } + } + + public void extractFile(FileHeader hd, OutputStream os) throws RarException { + if (!headers.contains(hd)) { + throw new RarException(RarExceptionType.headerNotInArchive); + } + try { + doExtractFile(hd, os); + } catch (Exception e) { + if (e instanceof RarException) { + throw (RarException) e; + } else { + throw new RarException(e); + } + } + } + + public InputStream getInputStream(final FileHeader hd) throws RarException, + IOException { + final PipedInputStream in = new PipedInputStream(32 * 1024); + final PipedOutputStream out = new PipedOutputStream(in); + + // creates a new thread that will write data to the pipe. Data will be + // available in another InputStream, connected to the OutputStream. + new Thread(new Runnable() { + public void run() { + try { + extractFile(hd, out); + } catch (RarException e) { + } finally { + try { + out.close(); + } catch (IOException e) { + } + } + } + }).start(); + + return in; + } + + private void doExtractFile(FileHeader hd, OutputStream os) + throws RarException, IOException { + dataIO.init(os); + dataIO.init(hd); + dataIO.setUnpFileCRC(this.isOldFormat() ? 0 : 0xffFFffFF); + if (unpack == null) { + unpack = new Unpack(dataIO); + } + if (!hd.isSolid()) { + unpack.init(null); + } + unpack.setDestSize(hd.getFullUnpackSize()); + try { + unpack.doUnpack(hd.getUnpVersion(), hd.isSolid()); + // Verify file CRC + hd = dataIO.getSubHeader(); + long actualCRC = hd.isSplitAfter() ? ~dataIO.getPackedCRC() + : ~dataIO.getUnpFileCRC(); + int expectedCRC = hd.getFileCRC(); + if (actualCRC != expectedCRC) { + throw new RarException(RarExceptionType.crcError); + } + // if (!hd.isSplitAfter()) { + // // Verify file CRC + // if(~dataIO.getUnpFileCRC() != hd.getFileCRC()){ + // throw new RarException(RarExceptionType.crcError); + // } + // } + } catch (Exception e) { + unpack.cleanUp(); + if (e instanceof RarException) { + // throw new RarException((RarException)e); + throw (RarException) e; + } else { + throw new RarException(e); + } + } + } + + public MainHeader getMainHeader() { + return newMhd; + } + + public boolean isOldFormat() { + return markHead.isOldFormat(); + } + + public void close() throws IOException { + if (rof != null) { + rof.close(); + rof = null; + } + if (unpack != null) { + unpack.cleanUp(); + } + } + + public VolumeManager getVolumeManager() { + return volumeManager; + } + + public void setVolumeManager(VolumeManager volumeManager) { + this.volumeManager = volumeManager; + } + + public Volume getVolume() { + return volume; + } + + public void setVolume(Volume volume) throws IOException { + this.volume = volume; + setFile(volume.getReadOnlyAccess(), volume.getLength()); + } +} diff --git a/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/UnrarCallback.java b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/UnrarCallback.java new file mode 100644 index 0000000..14efb42 --- /dev/null +++ b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/UnrarCallback.java @@ -0,0 +1,9 @@ +package org.fox.ttcomics2.junrar; + + +public interface UnrarCallback { + + boolean isNextVolumeReady(Volume nextVolume); + + void volumeProgressChanged(long current, long total); +} diff --git a/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/Volume.java b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/Volume.java new file mode 100755 index 0000000..a6888b4 --- /dev/null +++ b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/Volume.java @@ -0,0 +1,30 @@ +/* + * This file is part of seedbox . + * + * seedbox 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. + * + * seedbox 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 seedbox. If not, see . + */ +package org.fox.ttcomics2.junrar; + +import org.fox.ttcomics2.junrar.io.IReadOnlyAccess; + +import java.io.IOException; + + +public interface Volume { + IReadOnlyAccess getReadOnlyAccess() throws IOException; + + long getLength(); + + Archive getArchive(); +} diff --git a/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/VolumeManager.java b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/VolumeManager.java new file mode 100644 index 0000000..a6243ee --- /dev/null +++ b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/VolumeManager.java @@ -0,0 +1,24 @@ +/* + * This file is part of seedbox . + * + * seedbox 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. + * + * seedbox 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 seedbox. If not, see . + */ +package org.fox.ttcomics2.junrar; + +import java.io.IOException; + +public interface VolumeManager { + Volume nextArchive(Archive archive, Volume lastVolume) + throws IOException; +} diff --git a/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/crc/RarCRC.java b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/crc/RarCRC.java new file mode 100644 index 0000000..a2aba9b --- /dev/null +++ b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/crc/RarCRC.java @@ -0,0 +1,138 @@ +/* + * Copyright (c) 2007 innoSysTec (R) GmbH, Germany. All rights reserved. + * Original author: Edmund Wagner + * Creation date: 29.05.2007 + * + * Source: $HeadURL$ + * Last changed: $LastChangedDate$ + * + * the unrar licence applies to all junrar source and binary distributions + * you are not allowed to use this source to re-create the RAR compression algorithm + * + * Here some html entities which can be used for escaping javadoc tags: + * "&": "&" or "&" + * "<": "<" or "<" + * ">": ">" or ">" + * "@": "@" + */ +package org.fox.ttcomics2.junrar.crc; + + +public class RarCRC { + + private final static int crcTab[]; + + static { + crcTab = new int[256]; + for (int i = 0; i < 256; i++) { + int c = i; + for (int j = 0; j < 8; j++) { + if ((c & 1) != 0) { + c >>>= 1; + c ^= 0xEDB88320; + } else { + c >>>= 1; + } + } + crcTab[i] = c; + } + } + + private RarCRC() { + } + + public static int checkCrc(int startCrc, byte[] data, int offset, + int count) { + int size = Math.min(data.length - offset, count); + // #if defined(LITTLE_ENDIAN) && defined(PRESENT_INT32) && + // defined(ALLOW_NOT_ALIGNED_INT) + /* + for (int i = 0; (0 < size) && i < data.length - 8 + && ((data[i + 8] & 7) != 0); i++) { + startCrc = crcTab[(short) (startCrc ^ data[i]) & 0x00FF] ^ (startCrc >>> 8); + size--; + } + + for (int i = 0; size >= 8; i += 8) { + startCrc ^= data[i + 0] << 24; + startCrc ^= data[i + 1] << 16; + startCrc ^= data[i + 2] << 8; + startCrc ^= data[i + 3]; + + startCrc = crcTab[(short) startCrc & 0x00FF] ^ (startCrc >>> 8); + startCrc = crcTab[(short) startCrc & 0x00FF] ^ (startCrc >>> 8); + startCrc = crcTab[(short) startCrc & 0x00FF] ^ (startCrc >>> 8); + startCrc = crcTab[(short) startCrc & 0x00FF] ^ (startCrc >>> 8); + + startCrc ^= data[i + 4] << 24; + startCrc ^= data[i + 5] << 16; + startCrc ^= data[i + 6] << 8; + startCrc ^= data[i + 7]; + startCrc = crcTab[(short) startCrc & 0x00FF] ^ (startCrc >>> 8); + startCrc = crcTab[(short) startCrc & 0x00FF] ^ (startCrc >>> 8); + startCrc = crcTab[(short) startCrc & 0x00FF] ^ (startCrc >>> 8); + startCrc = crcTab[(short) startCrc & 0x00FF] ^ (startCrc >>> 8); + size -= 8; + }*/ + + for (int i = 0; i < size; i++) { +/* + // (byte)(StartCRC^Data[I]) + int pos = 0; // pos=0x00000000 + pos |= startCrc; // pos=ffffffff + + pos ^= data[i]; // data[0]=0x73=115dec --> pos=140 + System.out.println(Integer.toHexString(pos)); + + // Only last 8 bit because CRCtab has length 256 + pos = pos & 0x000000FF; + System.out.println("pos:"+pos); + //startCrc >>>= 8; + + + //StartCRC>>8 + int temp =0; + temp|=startCrc; + temp >>>= 8; + System.out.println("temp:"+Integer.toHexString(temp)); + + + startCrc = (crcTab[pos]^temp); + System.out.println("--"+Integer.toHexString(startCrc));*/ + + startCrc = (crcTab[(startCrc ^ + (int) data[offset + i]) & 0xff] ^ (startCrc >>> 8)); + + //System.out.println(Integer.toHexString(startCrc)); + + // Original code: + //StartCRC=CRCTab[(byte)(StartCRC^Data[I])]^(StartCRC>>8); + } + return (startCrc); + } + + public static short checkOldCrc(short startCrc, byte[] data, int count) { + int n = Math.min(data.length, count); + for (int i = 0; i < n; i++) { + startCrc = (short) ((short) (startCrc + (short) (data[i] & 0x00ff)) & -1); + startCrc = (short) (((startCrc << 1) | (startCrc >>> 15)) & -1); + } + return (startCrc); + } + +// public static void main(String[] args) +// { +// RarCRC rc = new RarCRC(); +// //byte[] data = { 0x72, 0x21, 0x1A, 0x07, 0x00}; +// +// byte[] data = {0x73 ,0x00 ,0x00 ,0x0D ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00}; +// +// int crc = 0x90CF; +// +// +// int result = rc.checkCrc(0xFFFFffff, data,0,data.length); +// System.out.println("3: "+Integer.toHexString(~result&0xffff)); +// +// } + +} diff --git a/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/crypt/Rijndael.java b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/crypt/Rijndael.java new file mode 100644 index 0000000..1cc86da --- /dev/null +++ b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/crypt/Rijndael.java @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2007 innoSysTec (R) GmbH, Germany. All rights reserved. + * Original author: Edmund Wagner + * Creation date: 31.05.2007 + * + * the unrar licence applies to all junrar source and binary distributions + * you are not allowed to use this source to re-create the RAR compression algorithm + * Source: $HeadURL$ + * Last changed: $LastChangedDate$ + * + * Here some html entities which can be used for escaping javadoc tags: + * "&": "&" or "&" + * "<": "<" or "<" + * ">": ">" or ">" + * "@": "@" + */ +package org.fox.ttcomics2.junrar.crypt; + +public class Rijndael { + +} diff --git a/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/exception/RarException.java b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/exception/RarException.java new file mode 100644 index 0000000..b03089d --- /dev/null +++ b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/exception/RarException.java @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2007 innoSysTec (R) GmbH, Germany. All rights reserved. + * Original author: Edmund Wagner + * Creation date: 30.07.2007 + * + * Source: $HeadURL$ + * Last changed: $LastChangedDate$ + * + * the unrar licence applies to all junrar source and binary distributions + * you are not allowed to use this source to re-create the RAR compression algorithm + * + * Here some html entities which can be used for escaping javadoc tags: + * "&": "&" or "&" + * "<": "<" or "<" + * ">": ">" or ">" + * "@": "@" + */ +package org.fox.ttcomics2.junrar.exception; + +public class RarException extends Exception { + private static final long serialVersionUID = 1L; + private RarExceptionType type; + + public RarException(Exception e) { + super(RarExceptionType.unkownError.name(), e); + this.type = RarExceptionType.unkownError; + } + + public RarException(RarException e) { + + super(e.getMessage(), e); + this.type = e.getType(); + } + + public RarException(RarExceptionType type) { + super(type.name()); + this.type = type; + } + + public RarExceptionType getType() { + return type; + } + + public void setType(RarExceptionType type) { + this.type = type; + } + + public enum RarExceptionType { + notImplementedYet, + crcError, + notRarArchive, + badRarArchive, + unkownError, + headerNotInArchive, + wrongHeaderType, + ioError, + rarEncryptedException + } +} diff --git a/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/impl/FileVolume.java b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/impl/FileVolume.java new file mode 100755 index 0000000..7350e58 --- /dev/null +++ b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/impl/FileVolume.java @@ -0,0 +1,55 @@ +/* + * This file is part of seedbox . + * + * seedbox 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. + * + * seedbox 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 seedbox. If not, see . + */ +package org.fox.ttcomics2.junrar.impl; + +import org.fox.ttcomics2.junrar.Archive; +import org.fox.ttcomics2.junrar.Volume; +import org.fox.ttcomics2.junrar.io.IReadOnlyAccess; +import org.fox.ttcomics2.junrar.io.ReadOnlyAccessFile; + +import java.io.File; +import java.io.IOException; + + +public class FileVolume implements Volume { + private final Archive archive; + private final File file; + + public FileVolume(Archive archive, File file) { + this.archive = archive; + this.file = file; + } + + @Override + public IReadOnlyAccess getReadOnlyAccess() throws IOException { + return new ReadOnlyAccessFile(file); + } + + @Override + public long getLength() { + return file.length(); + } + + @Override + public Archive getArchive() { + return archive; + } + + public File getFile() { + return file; + } +} diff --git a/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/impl/FileVolumeManager.java b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/impl/FileVolumeManager.java new file mode 100755 index 0000000..5b390c8 --- /dev/null +++ b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/impl/FileVolumeManager.java @@ -0,0 +1,50 @@ +/* + * This file is part of seedbox . + * + * seedbox 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. + * + * seedbox 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 seedbox. If not, see . + */ +package org.fox.ttcomics2.junrar.impl; + +import org.fox.ttcomics2.junrar.Archive; +import org.fox.ttcomics2.junrar.Volume; +import org.fox.ttcomics2.junrar.VolumeManager; +import org.fox.ttcomics2.junrar.util.VolumeHelper; + +import java.io.File; +import java.io.IOException; + + +public class FileVolumeManager implements VolumeManager { + private final File firstVolume; + + public FileVolumeManager(File firstVolume) { + this.firstVolume = firstVolume; + } + + @Override + public Volume nextArchive(Archive archive, Volume last) + throws IOException { + if (last == null) + return new FileVolume(archive, firstVolume); + + FileVolume lastFileVolume = (FileVolume) last; + boolean oldNumbering = !archive.getMainHeader().isNewNumbering() + || archive.isOldFormat(); + String nextName = VolumeHelper.nextVolumeName(lastFileVolume.getFile() + .getAbsolutePath(), oldNumbering); + File nextVolume = new File(nextName); + + return new FileVolume(archive, nextVolume); + } +} diff --git a/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/io/IReadOnlyAccess.java b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/io/IReadOnlyAccess.java new file mode 100644 index 0000000..870c966 --- /dev/null +++ b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/io/IReadOnlyAccess.java @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2007 innoSysTec (R) GmbH, Germany. All rights reserved. + * Original author: Edmund Wagner + * Creation date: 23.05.2007 + * + * Source: $HeadURL$ + * Last changed: $LastChangedDate$ + * + * the unrar licence applies to all junrar source and binary distributions + * you are not allowed to use this source to re-create the RAR compression algorithm + * + * Here some html entities which can be used for escaping javadoc tags: + * "&": "&" or "&" + * "<": "<" or "<" + * ">": ">" or ">" + * "@": "@" + */ +package org.fox.ttcomics2.junrar.io; + +import java.io.IOException; + + +public interface IReadOnlyAccess { + + long getPosition() throws IOException; + + void setPosition(long pos) throws IOException; + + int read() throws IOException; + + int read(byte[] buffer, int off, int count) throws IOException; + + int readFully(byte[] buffer, int count) throws IOException; + + void close() throws IOException; +} diff --git a/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/io/InputStreamReadOnlyAccessFile.java b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/io/InputStreamReadOnlyAccessFile.java new file mode 100644 index 0000000..84602ae --- /dev/null +++ b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/io/InputStreamReadOnlyAccessFile.java @@ -0,0 +1,46 @@ +package org.fox.ttcomics2.junrar.io; + +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.InputStream; + + +public class InputStreamReadOnlyAccessFile implements IReadOnlyAccess { + private RandomAccessStream is; + + public InputStreamReadOnlyAccessFile(final InputStream is) { + this.is = new RandomAccessStream(new BufferedInputStream(is)); + } + + @Override + public long getPosition() throws IOException { + return is.getLongFilePointer(); + } + + @Override + public void setPosition(long pos) throws IOException { + is.seek(pos); + } + + @Override + public int read() throws IOException { + return is.read(); + } + + @Override + public int read(byte[] buffer, int off, int count) throws IOException { + return is.read(buffer, off, count); + } + + @Override + public int readFully(byte[] buffer, int count) throws IOException { + is.readFully(buffer, count); + return count; + } + + @Override + public void close() throws IOException { + is.close(); + } + +} diff --git a/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/io/RandomAccessStream.java b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/io/RandomAccessStream.java new file mode 100644 index 0000000..3f8085f --- /dev/null +++ b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/io/RandomAccessStream.java @@ -0,0 +1,195 @@ +/* + * public domain as of http://rsbweb.nih.gov/ij/disclaimer.html + */ +package org.fox.ttcomics2.junrar.io; + +import java.io.EOFException; +import java.io.IOException; +import java.io.InputStream; +import java.io.RandomAccessFile; +import java.util.Vector; + +@SuppressWarnings("rawtypes") +public final class RandomAccessStream extends InputStream { + + private static final int BLOCK_SIZE = 512; + private static final int BLOCK_MASK = 511; + private static final int BLOCK_SHIFT = 9; + + private InputStream src; + private RandomAccessFile ras; + private long pointer; + private Vector data; + private int length; + private boolean foundEOS; + + public RandomAccessStream(InputStream inputstream) { + pointer = 0L; + data = new Vector(); + length = 0; + foundEOS = false; + src = inputstream; + } + + public RandomAccessStream(RandomAccessFile ras) { + this.ras = ras; + } + + public int getFilePointer() throws IOException { + if (ras != null) + return (int) ras.getFilePointer(); + else + return (int) pointer; + } + + public long getLongFilePointer() throws IOException { + if (ras != null) + return ras.getFilePointer(); + else + return pointer; + } + + public int read() throws IOException { + if (ras != null) + return ras.read(); + long l = pointer + 1L; + long l1 = readUntil(l); + if (l1 >= l) { + byte abyte0[] = (byte[]) data + .elementAt((int) (pointer >> BLOCK_SHIFT)); + return abyte0[(int) (pointer++ & BLOCK_MASK)] & 0xff; + } else + return -1; + } + + public int read(byte[] bytes, int off, int len) throws IOException { + if (bytes == null) + throw new NullPointerException(); + if (ras != null) + return ras.read(bytes, off, len); + if (off < 0 || len < 0 || off + len > bytes.length) + throw new IndexOutOfBoundsException(); + if (len == 0) + return 0; + long l = readUntil(pointer + len); + if (l <= pointer) + return -1; + else { + byte abyte1[] = (byte[]) data + .elementAt((int) (pointer >> BLOCK_SHIFT)); + int k = Math.min(len, BLOCK_SIZE - (int) (pointer & BLOCK_MASK)); + System.arraycopy(abyte1, (int) (pointer & BLOCK_MASK), bytes, off, + k); + pointer += k; + return k; + } + } + + public final void readFully(byte[] bytes) throws IOException { + readFully(bytes, bytes.length); + } + + public final void readFully(byte[] bytes, int len) throws IOException { + int read = 0; + do { + int l = read(bytes, read, len - read); + if (l < 0) + break; + read += l; + } while (read < len); + } + + @SuppressWarnings("unchecked") + private long readUntil(long l) throws IOException { + if (l < length) + return l; + if (foundEOS) + return length; + int i = (int) (l >> BLOCK_SHIFT); + int j = length >> BLOCK_SHIFT; + for (int k = j; k <= i; k++) { + byte abyte0[] = new byte[BLOCK_SIZE]; + data.addElement(abyte0); + int i1 = BLOCK_SIZE; + int j1 = 0; + while (i1 > 0) { + int k1 = src.read(abyte0, j1, i1); + if (k1 == -1) { + foundEOS = true; + return length; + } + j1 += k1; + i1 -= k1; + length += k1; + } + + } + + return length; + } + + public void seek(long loc) throws IOException { + if (ras != null) { + ras.seek(loc); + return; + } + if (loc < 0L) + pointer = 0L; + else + pointer = loc; + } + + public void seek(int loc) throws IOException { + long lloc = ((long) loc) & 0xffffffffL; + if (ras != null) { + ras.seek(lloc); + return; + } + if (lloc < 0L) + pointer = 0L; + else + pointer = lloc; + } + + public final int readInt() throws IOException { + int i = read(); + int j = read(); + int k = read(); + int l = read(); + if ((i | j | k | l) < 0) + throw new EOFException(); + else + return (i << 24) + (j << 16) + (k << 8) + l; + } + + public final long readLong() throws IOException { + return ((long) readInt() << 32) + ((long) readInt() & 0xffffffffL); + } + + public final double readDouble() throws IOException { + return Double.longBitsToDouble(readLong()); + } + + public final short readShort() throws IOException { + int i = read(); + int j = read(); + if ((i | j) < 0) + throw new EOFException(); + else + return (short) ((i << 8) + j); + } + + public final float readFloat() throws IOException { + return Float.intBitsToFloat(readInt()); + } + + public void close() throws IOException { + if (ras != null) + ras.close(); + else { + data.removeAllElements(); + src.close(); + } + } + +} \ No newline at end of file diff --git a/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/io/Raw.java b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/io/Raw.java new file mode 100644 index 0000000..47cc067 --- /dev/null +++ b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/io/Raw.java @@ -0,0 +1,166 @@ +/* + * Copyright (c) 2007 innoSysTec (R) GmbH, Germany. All rights reserved. + * Original author: Edmund Wagner + * Creation date: 18.06.2007 + * + * Source: $HeadURL$ + * Last changed: $LastChangedDate$ + * + * the unrar licence applies to all junrar source and binary distributions + * you are not allowed to use this source to re-create the RAR compression algorithm + * + * Here some html entities which can be used for escaping javadoc tags: + * "&": "&" or "&" + * "<": "<" or "<" + * ">": ">" or ">" + * "@": "@" + */ +package org.fox.ttcomics2.junrar.io; + +public class Raw { + public static final short readShortBigEndian(byte[] array, int pos) { + short temp = 0; + temp |= array[pos] & 0xff; + temp <<= 8; + temp |= array[pos + 1] & 0xff; + return temp; + } + + public static final int readIntBigEndian(byte[] array, int pos) { + int temp = 0; + temp |= array[pos] & 0xff; + temp <<= 8; + temp |= array[pos + 1] & 0xff; + temp <<= 8; + temp |= array[pos + 2] & 0xff; + temp <<= 8; + temp |= array[pos + 3] & 0xff; + return temp; + } + + public static final long readLongBigEndian(byte[] array, int pos) { + int temp = 0; + temp |= array[pos] & 0xff; + temp <<= 8; + temp |= array[pos + 1] & 0xff; + temp <<= 8; + temp |= array[pos + 2] & 0xff; + temp <<= 8; + temp |= array[pos + 3] & 0xff; + temp <<= 8; + temp |= array[pos + 4] & 0xff; + temp <<= 8; + temp |= array[pos + 5] & 0xff; + temp <<= 8; + temp |= array[pos + 6] & 0xff; + temp <<= 8; + temp |= array[pos + 7] & 0xff; + return temp; + } + + public static final short readShortLittleEndian(byte[] array, int pos) { + short result = 0; + result += array[pos + 1] & 0xff; + result <<= 8; + result += array[pos] & 0xff; + return result; + } + + public static final int readIntLittleEndian(byte[] array, int pos) { + return ((array[pos + 3] & 0xff) << 24) + | ((array[pos + 2] & 0xff) << 16) + | ((array[pos + 1] & 0xff) << 8) | ((array[pos] & 0xff)); + } + + public static final long readIntLittleEndianAsLong(byte[] array, int pos) { + return (((long) array[pos + 3] & 0xff) << 24) + | (((long) array[pos + 2] & 0xff) << 16) + | (((long) array[pos + 1] & 0xff) << 8) + | (((long) array[pos] & 0xff)); + } + + public static final long readLongLittleEndian(byte[] array, int pos) { + int temp = 0; + temp |= array[pos + 7] & 0xff; + temp <<= 8; + temp |= array[pos + 6] & 0xff; + temp <<= 8; + temp |= array[pos + 5] & 0xff; + temp <<= 8; + temp |= array[pos + 4] & 0xff; + temp <<= 8; + temp |= array[pos + 3] & 0xff; + temp <<= 8; + temp |= array[pos + 2] & 0xff; + temp <<= 8; + temp |= array[pos + 1] & 0xff; + temp <<= 8; + temp |= array[pos]; + return temp; + } + + public static final void writeShortBigEndian(byte[] array, int pos, + short value) { + array[pos] = (byte) (value >>> 8); + array[pos + 1] = (byte) (value & 0xFF); + + } + + public static final void writeIntBigEndian(byte[] array, int pos, int value) { + array[pos] = (byte) ((value >>> 24) & 0xff); + array[pos + 1] = (byte) ((value >>> 16) & 0xff); + array[pos + 2] = (byte) ((value >>> 8) & 0xff); + array[pos + 3] = (byte) ((value) & 0xff); + + } + + public static final void writeLongBigEndian(byte[] array, int pos, + long value) { + array[pos] = (byte) (value >>> 56); + array[pos + 1] = (byte) (value >>> 48); + array[pos + 2] = (byte) (value >>> 40); + array[pos + 3] = (byte) (value >>> 32); + array[pos + 4] = (byte) (value >>> 24); + array[pos + 5] = (byte) (value >>> 16); + array[pos + 6] = (byte) (value >>> 8); + array[pos + 7] = (byte) (value & 0xFF); + + } + + public static final void writeShortLittleEndian(byte[] array, int pos, + short value) { + array[pos + 1] = (byte) (value >>> 8); + array[pos] = (byte) (value & 0xFF); + + } + + public static final void incShortLittleEndian(byte[] array, int pos, int dv) { + int c = ((array[pos] & 0xff) + (dv & 0xff)) >>> 8; + array[pos] += dv & 0xff; + if ((c > 0) || ((dv & 0xff00) != 0)) { + array[pos + 1] += ((dv >>> 8) & 0xff) + c; + } + } + + public static final void writeIntLittleEndian(byte[] array, int pos, + int value) { + array[pos + 3] = (byte) (value >>> 24); + array[pos + 2] = (byte) (value >>> 16); + array[pos + 1] = (byte) (value >>> 8); + array[pos] = (byte) (value & 0xFF); + + } + + public static final void writeLongLittleEndian(byte[] array, int pos, + long value) { + array[pos + 7] = (byte) (value >>> 56); + array[pos + 6] = (byte) (value >>> 48); + array[pos + 5] = (byte) (value >>> 40); + array[pos + 4] = (byte) (value >>> 32); + array[pos + 3] = (byte) (value >>> 24); + array[pos + 2] = (byte) (value >>> 16); + array[pos + 1] = (byte) (value >>> 8); + array[pos] = (byte) (value & 0xFF); + + } +} diff --git a/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/io/ReadOnlyAccessByteArray.java b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/io/ReadOnlyAccessByteArray.java new file mode 100644 index 0000000..04e845a --- /dev/null +++ b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/io/ReadOnlyAccessByteArray.java @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2007 innoSysTec (R) GmbH, Germany. All rights reserved. + * Original author: Edmund Wagner + * Creation date: 30.05.2007 + * + * Source: $HeadURL$ + * Last changed: $LastChangedDate$ + * + * the unrar licence applies to all junrar source and binary distributions + * you are not allowed to use this source to re-create the RAR compression algorithm + * + * Here some html entities which can be used for escaping javadoc tags: + * "&": "&" or "&" + * "<": "<" or "<" + * ">": ">" or ">" + * "@": "@" + */ +package org.fox.ttcomics2.junrar.io; + +import java.io.EOFException; +import java.io.IOException; + +public class ReadOnlyAccessByteArray implements IReadOnlyAccess { + + private int positionInFile; + private byte[] file; + + public ReadOnlyAccessByteArray(byte[] file) { + if (file == null) { + throw new NullPointerException("file must not be null!!"); + } + this.file = file; + this.positionInFile = 0; + } + + public long getPosition() throws IOException { + return positionInFile; + } + + public void setPosition(long pos) throws IOException { + if (pos < file.length && pos >= 0) { + this.positionInFile = (int) pos; + } else { + throw new EOFException(); + } + } + + public int read() throws IOException { + return file[positionInFile++]; + } + + public int read(byte[] buffer, int off, int count) throws IOException { + int read = Math.min(count, file.length - positionInFile); + System.arraycopy(file, positionInFile, buffer, off, read); + positionInFile += read; + return read; + } + + public int readFully(byte[] buffer, int count) throws IOException { + if (buffer == null) { + throw new NullPointerException("buffer must not be null"); + } + if (count == 0) { + throw new IllegalArgumentException("cannot read 0 bytes ;-)"); + } + int read = Math.min(count, file.length - positionInFile - 1); + System.arraycopy(file, positionInFile, buffer, 0, read); + positionInFile += read; + return read; + } + + public void close() throws IOException { + } +} diff --git a/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/io/ReadOnlyAccessFile.java b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/io/ReadOnlyAccessFile.java new file mode 100644 index 0000000..f141ef2 --- /dev/null +++ b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/io/ReadOnlyAccessFile.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2007 innoSysTec (R) GmbH, Germany. All rights reserved. + * Original author: Edmund Wagner + * Creation date: 23.05.2007 + * + * Source: $HeadURL$ + * Last changed: $LastChangedDate$ + * + * the unrar licence applies to all junrar source and binary distributions + * you are not allowed to use this source to re-create the RAR compression algorithm + * + * Here some html entities which can be used for escaping javadoc tags: + * "&": "&" or "&" + * "<": "<" or "<" + * ">": ">" or ">" + * "@": "@" + */ +package org.fox.ttcomics2.junrar.io; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.RandomAccessFile; + +public class ReadOnlyAccessFile extends RandomAccessFile + implements IReadOnlyAccess { + + public ReadOnlyAccessFile(File file) throws FileNotFoundException { + super(file, "r"); + } + + public int readFully(byte[] buffer, int count) throws IOException { + assert (count > 0) : count; + this.readFully(buffer, 0, count); + return count; + } + + public long getPosition() throws IOException { + return this.getFilePointer(); + } + + public void setPosition(long pos) throws IOException { + this.seek(pos); + } +} diff --git a/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/io/ReadOnlyAccessInputStream.java b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/io/ReadOnlyAccessInputStream.java new file mode 100644 index 0000000..e1b778b --- /dev/null +++ b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/io/ReadOnlyAccessInputStream.java @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2007 innoSysTec (R) GmbH, Germany. All rights reserved. + * Original author: Edmund Wagner + * Creation date: 26.06.2007 + * + * Source: $HeadURL$ + * Last changed: $LastChangedDate$ + * + * the unrar licence applies to all junrar source and binary distributions + * you are not allowed to use this source to re-create the RAR compression + * algorithm + * + * Here some html entities which can be used for escaping javadoc tags: + * "&": "&" or "&" + * "<": "<" or "<" + * ">": ">" or ">" + * "@": "@" + */ +package org.fox.ttcomics2.junrar.io; + +import java.io.IOException; +import java.io.InputStream; + +public class ReadOnlyAccessInputStream extends InputStream { + private final long startPos; + private final long endPos; + private IReadOnlyAccess file; + private long curPos; + + public ReadOnlyAccessInputStream(IReadOnlyAccess file, long startPos, + long endPos) throws IOException { + super(); + this.file = file; + this.startPos = startPos; + curPos = startPos; + this.endPos = endPos; + file.setPosition(curPos); + } + + @Override + public int read() throws IOException { + if (curPos == endPos) { + return -1; + } else { + int b = file.read(); + curPos++; + return b; + } + } + + @Override + public int read(byte[] b, int off, int len) throws IOException { + if (len == 0) { + return 0; + } + if (curPos == endPos) { + return -1; + } + int bytesRead = file.read(b, off, + (int) Math.min(len, endPos - curPos)); + curPos += bytesRead; + return bytesRead; + } + + @Override + public int read(byte[] b) throws IOException { + return read(b, 0, b.length); + } +// +// public void close() throws IOException { +// file.close(); +// } +} diff --git a/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/rarfile/AVHeader.java b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/rarfile/AVHeader.java new file mode 100644 index 0000000..9c1cd2d --- /dev/null +++ b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/rarfile/AVHeader.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2007 innoSysTec (R) GmbH, Germany. All rights reserved. + * Original author: Edmund Wagner + * Creation date: 24.05.2007 + * + * Source: $HeadURL$ + * Last changed: $LastChangedDate$ + * + * + * the unrar licence applies to all junrar source and binary distributions + * you are not allowed to use this source to re-create the RAR compression algorithm + * + * Here some html entities which can be used for escaping javadoc tags: + * "&": "&" or "&" + * "<": "<" or "<" + * ">": ">" or ">" + * "@": "@" + */ +package org.fox.ttcomics2.junrar.rarfile; + +import org.fox.ttcomics2.junrar.io.Raw; + +public class AVHeader extends BaseBlock { + + public static final int avHeaderSize = 7; + + private byte unpackVersion; + private byte method; + private byte avVersion; + private int avInfoCRC; + + public AVHeader(BaseBlock bb, byte[] avHeader) { + super(bb); + + int pos = 0; + unpackVersion |= avHeader[pos] & 0xff; + pos++; + method |= avHeader[pos] & 0xff; + pos++; + avVersion |= avHeader[pos] & 0xff; + pos++; + avInfoCRC = Raw.readIntLittleEndian(avHeader, pos); + } + + public int getAvInfoCRC() { + return avInfoCRC; + } + + public byte getAvVersion() { + return avVersion; + } + + public byte getMethod() { + return method; + } + + public byte getUnpackVersion() { + return unpackVersion; + } +} diff --git a/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/rarfile/BaseBlock.java b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/rarfile/BaseBlock.java new file mode 100644 index 0000000..b20e85f --- /dev/null +++ b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/rarfile/BaseBlock.java @@ -0,0 +1,160 @@ +/* + * Copyright (c) 2007 innoSysTec (R) GmbH, Germany. All rights reserved. + * Original author: Edmund Wagner + * Creation date: 22.05.2007 + * + * Source: $HeadURL$ + * Last changed: $LastChangedDate$ + * + * + * the unrar licence applies to all junrar source and binary distributions + * you are not allowed to use this source to re-create the RAR compression algorithm + * + * Here some html entities which can be used for escaping javadoc tags: + * "&": "&" or "&" + * "<": "<" or "<" + * ">": ">" or ">" + * "@": "@" + */ +package org.fox.ttcomics2.junrar.rarfile; + + +import org.fox.ttcomics2.junrar.io.Raw; + + +public class BaseBlock { + + public static final short BaseBlockSize = 7; + + //TODO move somewhere else + + public static final short MHD_VOLUME = 0x0001; + public static final short MHD_COMMENT = 0x0002; + public static final short MHD_LOCK = 0x0004; + public static final short MHD_SOLID = 0x0008; + public static final short MHD_PACK_COMMENT = 0x0010; + public static final short MHD_NEWNUMBERING = 0x0010; + public static final short MHD_AV = 0x0020; + public static final short MHD_PROTECT = 0x0040; + public static final short MHD_PASSWORD = 0x0080; + public static final short MHD_FIRSTVOLUME = 0x0100; + public static final short MHD_ENCRYPTVER = 0x0200; + + + public static final short LHD_SPLIT_BEFORE = 0x0001; + public static final short LHD_SPLIT_AFTER = 0x0002; + public static final short LHD_PASSWORD = 0x0004; + public static final short LHD_COMMENT = 0x0008; + public static final short LHD_SOLID = 0x0010; + + public static final short LHD_WINDOWMASK = 0x00e0; + public static final short LHD_WINDOW64 = 0x0000; + public static final short LHD_WINDOW128 = 0x0020; + public static final short LHD_WINDOW256 = 0x0040; + public static final short LHD_WINDOW512 = 0x0060; + public static final short LHD_WINDOW1024 = 0x0080; + public static final short LHD_WINDOW2048 = 0x00a0; + public static final short LHD_WINDOW4096 = 0x00c0; + public static final short LHD_DIRECTORY = 0x00e0; + + public static final short LHD_LARGE = 0x0100; + public static final short LHD_UNICODE = 0x0200; + public static final short LHD_SALT = 0x0400; + public static final short LHD_VERSION = 0x0800; + public static final short LHD_EXTTIME = 0x1000; + public static final short LHD_EXTFLAGS = 0x2000; + + public static final short SKIP_IF_UNKNOWN = 0x4000; + public static final short LONG_BLOCK = -0x8000; + + public static final short EARC_NEXT_VOLUME = 0x0001; + public static final short EARC_DATACRC = 0x0002; + public static final short EARC_REVSPACE = 0x0004; + public static final short EARC_VOLNUMBER = 0x0008; + + + protected long positionInFile; + + protected short headCRC = 0; + protected byte headerType = 0; + protected short flags = 0; + protected short headerSize = 0; + + public BaseBlock() { + + } + + public BaseBlock(BaseBlock bb) { + this.flags = bb.getFlags(); + this.headCRC = bb.getHeadCRC(); + this.headerType = bb.getHeaderType().getHeaderByte(); + this.headerSize = bb.getHeaderSize(); + this.positionInFile = bb.getPositionInFile(); + } + + public BaseBlock(byte[] baseBlockHeader) { + + int pos = 0; + this.headCRC = Raw.readShortLittleEndian(baseBlockHeader, pos); + pos += 2; + this.headerType |= baseBlockHeader[pos] & 0xff; + pos++; + this.flags = Raw.readShortLittleEndian(baseBlockHeader, pos); + pos += 2; + this.headerSize = Raw.readShortLittleEndian(baseBlockHeader, pos); + } + + + public boolean hasArchiveDataCRC() { + return (this.flags & EARC_DATACRC) != 0; + } + + public boolean hasVolumeNumber() { + return (this.flags & EARC_VOLNUMBER) != 0; + } + + public boolean hasEncryptVersion() { + return (flags & MHD_ENCRYPTVER) != 0; + } + + public boolean isSubBlock() { + if (UnrarHeadertype.SubHeader.equals(headerType)) { + return (true); + } + return UnrarHeadertype.NewSubHeader.equals(headerType) && (flags & LHD_SOLID) != 0; + + } + + public long getPositionInFile() { + return positionInFile; + } + + public void setPositionInFile(long positionInFile) { + this.positionInFile = positionInFile; + } + + public short getFlags() { + return flags; + } + + public short getHeadCRC() { + return headCRC; + } + + public short getHeaderSize() { + return headerSize; + } + + public UnrarHeadertype getHeaderType() { + return UnrarHeadertype.findType(headerType); + } + + public void print() { + StringBuilder str = new StringBuilder(); + str.append("HeaderType: " + getHeaderType()); + str.append("\nHeadCRC: " + Integer.toHexString(getHeadCRC())); + str.append("\nFlags: " + Integer.toHexString(getFlags())); + str.append("\nHeaderSize: " + getHeaderSize()); + str.append("\nPosition in file: " + getPositionInFile()); + } +} diff --git a/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/rarfile/BlockHeader.java b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/rarfile/BlockHeader.java new file mode 100644 index 0000000..dc3741e --- /dev/null +++ b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/rarfile/BlockHeader.java @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2007 innoSysTec (R) GmbH, Germany. All rights reserved. + * Original author: Edmund Wagner + * Creation date: 22.05.2007 + * + * Source: $HeadURL$ + * Last changed: $LastChangedDate$ + * + * + * the unrar licence applies to all junrar source and binary distributions + * you are not allowed to use this source to re-create the RAR compression algorithm + * + * Here some html entities which can be used for escaping javadoc tags: + * "&": "&" or "&" + * "<": "<" or "<" + * ">": ">" or ">" + * "@": "@" + */ +package org.fox.ttcomics2.junrar.rarfile; + + +import org.fox.ttcomics2.junrar.io.Raw; + + +public class BlockHeader extends BaseBlock { + public static final short blockHeaderSize = 4; + + + private int dataSize; + private int packSize; + + public BlockHeader() { + + } + + public BlockHeader(BlockHeader bh) { + super(bh); + this.packSize = bh.getDataSize(); + this.dataSize = packSize; + this.positionInFile = bh.getPositionInFile(); + } + + public BlockHeader(BaseBlock bb, byte[] blockHeader) { + super(bb); + + this.packSize = Raw.readIntLittleEndian(blockHeader, 0); + this.dataSize = this.packSize; + } + + public int getDataSize() { + return dataSize; + } + + public int getPackSize() { + return packSize; + } + + public void print() { + super.print(); + String s = "DataSize: " + getDataSize() + " packSize: " + getPackSize(); + } +} diff --git a/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/rarfile/CommentHeader.java b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/rarfile/CommentHeader.java new file mode 100644 index 0000000..2bf1c0e --- /dev/null +++ b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/rarfile/CommentHeader.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2007 innoSysTec (R) GmbH, Germany. All rights reserved. + * Original author: Edmund Wagner + * Creation date: 23.05.2007 + * + * Source: $HeadURL$ + * Last changed: $LastChangedDate$ + * + * + * the unrar licence applies to all junrar source and binary distributions + * you are not allowed to use this source to re-create the RAR compression algorithm + * + * Here some html entities which can be used for escaping javadoc tags: + * "&": "&" or "&" + * "<": "<" or "<" + * ">": ">" or ">" + * "@": "@" + */ + +package org.fox.ttcomics2.junrar.rarfile; + +import org.fox.ttcomics2.junrar.io.Raw; + +public class CommentHeader extends BaseBlock { + + public static final short commentHeaderSize = 6; + + private short unpSize; + private byte unpVersion; + private byte unpMethod; + private short commCRC; + + + public CommentHeader(BaseBlock bb, byte[] commentHeader) { + super(bb); + + int pos = 0; + unpSize = Raw.readShortLittleEndian(commentHeader, pos); + pos += 2; + unpVersion |= commentHeader[pos] & 0xff; + pos++; + + unpMethod |= commentHeader[pos] & 0xff; + pos++; + commCRC = Raw.readShortLittleEndian(commentHeader, pos); + + } + + public short getCommCRC() { + return commCRC; + } + + public byte getUnpMethod() { + return unpMethod; + } + + public short getUnpSize() { + return unpSize; + } + + public byte getUnpVersion() { + return unpVersion; + } +} diff --git a/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/rarfile/EAHeader.java b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/rarfile/EAHeader.java new file mode 100644 index 0000000..2de0cb2 --- /dev/null +++ b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/rarfile/EAHeader.java @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2007 innoSysTec (R) GmbH, Germany. All rights reserved. + * Original author: Edmund Wagner + * Creation date: 27.11.2007 + * + * Source: $HeadURL$ + * Last changed: $LastChangedDate$ + * + * + * the unrar licence applies to all junrar source and binary distributions + * you are not allowed to use this source to re-create the RAR compression algorithm + * + * Here some html entities which can be used for escaping javadoc tags: + * "&": "&" or "&" + * "<": "<" or "<" + * ">": ">" or ">" + * "@": "@" + */ +package org.fox.ttcomics2.junrar.rarfile; + + +import org.fox.ttcomics2.junrar.io.Raw; + + +public class EAHeader + extends SubBlockHeader { + + public static final short EAHeaderSize = 10; + + private int unpSize; + private byte unpVer; + private byte method; + private int EACRC; + + public EAHeader(SubBlockHeader sb, byte[] eahead) { + super(sb); + int pos = 0; + unpSize = Raw.readIntLittleEndian(eahead, pos); + pos += 4; + unpVer |= eahead[pos] & 0xff; + pos++; + method |= eahead[pos] & 0xff; + pos++; + EACRC = Raw.readIntLittleEndian(eahead, pos); + } + + public int getEACRC() { + return EACRC; + } + + public byte getMethod() { + return method; + } + + public int getUnpSize() { + return unpSize; + } + + public byte getUnpVer() { + return unpVer; + } + + public void print() { + super.print(); + + } +} + diff --git a/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/rarfile/EndArcHeader.java b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/rarfile/EndArcHeader.java new file mode 100644 index 0000000..ddc1957 --- /dev/null +++ b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/rarfile/EndArcHeader.java @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2007 innoSysTec (R) GmbH, Germany. All rights reserved. + * Original author: Edmund Wagner + * Creation date: 24.05.2007 + * + * Source: $HeadURL$ + * Last changed: $LastChangedDate$ + * + * + * the unrar licence applies to all junrar source and binary distributions + * you are not allowed to use this source to re-create the RAR compression algorithm + * + * Here some html entities which can be used for escaping javadoc tags: + * "&": "&" or "&" + * "<": "<" or "<" + * ">": ">" or ">" + * "@": "@" + */ +package org.fox.ttcomics2.junrar.rarfile; + +import org.fox.ttcomics2.junrar.io.Raw; + +public class EndArcHeader extends BaseBlock { + + public static final short endArcArchiveDataCrcSize = 4; + public static final short endArcVolumeNumberSize = 2; + private static final short EARC_NEXT_VOLUME = 0x0001; + private static final short EARC_DATACRC = 0x0002; + private static final short EARC_REVSPACE = 0x0004; + private static final short EARC_VOLNUMBER = 0x0008; + private static final short endArcHeaderSize = 6; + private int archiveDataCRC; + private short volumeNumber; + + + public EndArcHeader(BaseBlock bb, byte[] endArcHeader) { + super(bb); + + int pos = 0; + if (hasArchiveDataCRC()) { + archiveDataCRC = Raw.readIntLittleEndian(endArcHeader, pos); + pos += 4; + } + if (hasVolumeNumber()) { + volumeNumber = Raw.readShortLittleEndian(endArcHeader, pos); + } + } + + public int getArchiveDataCRC() { + return archiveDataCRC; + } + + public short getVolumeNumber() { + return volumeNumber; + } +} diff --git a/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/rarfile/FileHeader.java b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/rarfile/FileHeader.java new file mode 100755 index 0000000..ad3743b --- /dev/null +++ b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/rarfile/FileHeader.java @@ -0,0 +1,367 @@ +/* + * Copyright (c) 2007 innoSysTec (R) GmbH, Germany. All rights reserved. + * Original author: Edmund Wagner + * Creation date: 22.05.2007 + * + * Source: $HeadURL$ + * Last changed: $LastChangedDate$ + * + * + * the unrar licence applies to all junrar source and binary distributions + * you are not allowed to use this source to re-create the RAR compression algorithm + * + * Here some html entities which can be used for escaping javadoc tags: + * "&": "&" or "&" + * "<": "<" or "<" + * ">": ">" or ">" + * "@": "@" + */ +package org.fox.ttcomics2.junrar.rarfile; + +import org.fox.ttcomics2.junrar.io.Raw; + +import java.util.Calendar; +import java.util.Date; + + +public class FileHeader extends BlockHeader { + + + private static final byte SALT_SIZE = 8; + + private static final byte NEWLHD_SIZE = 32; + private final HostSystem hostOS; + private final int fileCRC; + private final int fileTime; + private final byte[] fileNameBytes; + private final byte[] salt = new byte[SALT_SIZE]; + private long unpSize; + private byte unpVersion; + private byte unpMethod; + private short nameSize; + private int highPackSize; + private int highUnpackSize; + private String fileName; + private String fileNameW; + private byte[] subData; + private Date mTime; + + private Date cTime; + + private Date aTime; + + private Date arcTime; + + private long fullPackSize; + + private long fullUnpackSize; + + private int fileAttr; + + private int subFlags; // same as fileAttr (in header) + + private int recoverySectors = -1; + + public FileHeader(BlockHeader bh, byte[] fileHeader) { + super(bh); + + int position = 0; + unpSize = Raw.readIntLittleEndianAsLong(fileHeader, position); + position += 4; + hostOS = HostSystem.findHostSystem(fileHeader[4]); + position++; + + fileCRC = Raw.readIntLittleEndian(fileHeader, position); + position += 4; + + fileTime = Raw.readIntLittleEndian(fileHeader, position); + position += 4; + + unpVersion |= fileHeader[13] & 0xff; + position++; + unpMethod |= fileHeader[14] & 0xff; + position++; + nameSize = Raw.readShortLittleEndian(fileHeader, position); + position += 2; + + fileAttr = Raw.readIntLittleEndian(fileHeader, position); + position += 4; + if (isLargeBlock()) { + highPackSize = Raw.readIntLittleEndian(fileHeader, position); + position += 4; + + highUnpackSize = Raw.readIntLittleEndian(fileHeader, position); + position += 4; + } else { + highPackSize = 0; + highUnpackSize = 0; + if (unpSize == 0xffffffff) { + + unpSize = 0xffffffff; + highUnpackSize = Integer.MAX_VALUE; + } + + } + fullPackSize |= highPackSize; + fullPackSize <<= 32; + fullPackSize |= getPackSize(); + + fullUnpackSize |= highUnpackSize; + fullUnpackSize <<= 32; + fullUnpackSize += unpSize; + + nameSize = nameSize > 4 * 1024 ? 4 * 1024 : nameSize; + + fileNameBytes = new byte[nameSize]; + for (int i = 0; i < nameSize; i++) { + fileNameBytes[i] = fileHeader[position]; + position++; + } + + if (isFileHeader()) { + if (isUnicode()) { + int length = 0; + fileName = ""; + fileNameW = ""; + while (length < fileNameBytes.length + && fileNameBytes[length] != 0) { + length++; + } + byte[] name = new byte[length]; + System.arraycopy(fileNameBytes, 0, name, 0, name.length); + fileName = new String(name); + if (length != nameSize) { + length++; + fileNameW = FileNameDecoder.decode(fileNameBytes, length); + } + } else { + fileName = new String(fileNameBytes); + fileNameW = ""; + } + } + + if (UnrarHeadertype.NewSubHeader.equals(headerType)) { + int datasize = headerSize - NEWLHD_SIZE - nameSize; + if (hasSalt()) { + datasize -= SALT_SIZE; + } + if (datasize > 0) { + subData = new byte[datasize]; + for (int i = 0; i < datasize; i++) { + subData[i] = (fileHeader[position]); + position++; + } + } + + if (NewSubHeaderType.SUBHEAD_TYPE_RR.byteEquals(fileNameBytes)) { + recoverySectors = subData[8] + (subData[9] << 8) + + (subData[10] << 16) + (subData[11] << 24); + } + } + + if (hasSalt()) { + for (int i = 0; i < SALT_SIZE; i++) { + salt[i] = fileHeader[position]; + position++; + } + } + mTime = getDateDos(fileTime); + // TODO rartime -> extended + + } + + @Override + public void print() { + super.print(); + StringBuilder str = new StringBuilder(); + str.append("unpSize: " + getUnpSize()); + str.append("\nHostOS: " + hostOS.name()); + str.append("\nMDate: " + mTime); + str.append("\nFileName: " + getFileNameString()); + str.append("\nunpMethod: " + Integer.toHexString(getUnpMethod())); + str.append("\nunpVersion: " + Integer.toHexString(getUnpVersion())); + str.append("\nfullpackedsize: " + getFullPackSize()); + str.append("\nfullunpackedsize: " + getFullUnpackSize()); + str.append("\nisEncrypted: " + isEncrypted()); + str.append("\nisfileHeader: " + isFileHeader()); + str.append("\nisSolid: " + isSolid()); + str.append("\nisSplitafter: " + isSplitAfter()); + str.append("\nisSplitBefore:" + isSplitBefore()); + str.append("\nunpSize: " + getUnpSize()); + str.append("\ndataSize: " + getDataSize()); + str.append("\nisUnicode: " + isUnicode()); + str.append("\nhasVolumeNumber: " + hasVolumeNumber()); + str.append("\nhasArchiveDataCRC: " + hasArchiveDataCRC()); + str.append("\nhasSalt: " + hasSalt()); + str.append("\nhasEncryptVersions: " + hasEncryptVersion()); + str.append("\nisSubBlock: " + isSubBlock()); + } + + private Date getDateDos(int time) { + Calendar cal = Calendar.getInstance(); + cal.set(Calendar.YEAR, (time >>> 25) + 1980); + cal.set(Calendar.MONTH, ((time >>> 21) & 0x0f) - 1); + cal.set(Calendar.DAY_OF_MONTH, (time >>> 16) & 0x1f); + cal.set(Calendar.HOUR_OF_DAY, (time >>> 11) & 0x1f); + cal.set(Calendar.MINUTE, (time >>> 5) & 0x3f); + cal.set(Calendar.SECOND, (time & 0x1f) * 2); + return cal.getTime(); + } + + public Date getArcTime() { + return arcTime; + } + + public void setArcTime(Date arcTime) { + this.arcTime = arcTime; + } + + public Date getATime() { + return aTime; + } + + public void setATime(Date time) { + aTime = time; + } + + public Date getCTime() { + return cTime; + } + + public void setCTime(Date time) { + cTime = time; + } + + public int getFileAttr() { + return fileAttr; + } + + public void setFileAttr(int fileAttr) { + this.fileAttr = fileAttr; + } + + public int getFileCRC() { + return fileCRC; + } + + public byte[] getFileNameByteArray() { + return fileNameBytes; + } + + public String getFileNameString() { + return fileName; + } + + public void setFileName(String fileName) { + this.fileName = fileName; + } + + public String getFileNameW() { + return fileNameW; + } + + public void setFileNameW(String fileNameW) { + this.fileNameW = fileNameW; + } + + public int getHighPackSize() { + return highPackSize; + } + + public int getHighUnpackSize() { + return highUnpackSize; + } + + public HostSystem getHostOS() { + return hostOS; + } + + public Date getMTime() { + return mTime; + } + + public void setMTime(Date time) { + mTime = time; + } + + public short getNameSize() { + return nameSize; + } + + public int getRecoverySectors() { + return recoverySectors; + } + + public byte[] getSalt() { + return salt; + } + + public byte[] getSubData() { + return subData; + } + + public int getSubFlags() { + return subFlags; + } + + public byte getUnpMethod() { + return unpMethod; + } + + public long getUnpSize() { + return unpSize; + } + + public byte getUnpVersion() { + return unpVersion; + } + + public long getFullPackSize() { + return fullPackSize; + } + + public long getFullUnpackSize() { + return fullUnpackSize; + } + + @Override + public String toString() { + return super.toString(); + } + + public boolean isSplitAfter() { + return (this.flags & BlockHeader.LHD_SPLIT_AFTER) != 0; + } + + public boolean isSplitBefore() { + return (this.flags & LHD_SPLIT_BEFORE) != 0; + } + + public boolean isSolid() { + return (this.flags & LHD_SOLID) != 0; + } + + public boolean isEncrypted() { + return (this.flags & BlockHeader.LHD_PASSWORD) != 0; + } + + public boolean isUnicode() { + return (flags & LHD_UNICODE) != 0; + } + + public boolean isFileHeader() { + return UnrarHeadertype.FileHeader.equals(headerType); + } + + public boolean hasSalt() { + return (flags & LHD_SALT) != 0; + } + + public boolean isLargeBlock() { + return (flags & LHD_LARGE) != 0; + } + + public boolean isDirectory() { + return (flags & LHD_WINDOWMASK) == LHD_DIRECTORY; + } +} diff --git a/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/rarfile/FileNameDecoder.java b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/rarfile/FileNameDecoder.java new file mode 100644 index 0000000..999ad39 --- /dev/null +++ b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/rarfile/FileNameDecoder.java @@ -0,0 +1,76 @@ +/* + * + * Original author: alpha_lam + * Creation date: ? + * + * Source: $HeadURL$ + * Last changed: $LastChangedDate$ + * + * + * the unrar licence applies to all junrar source and binary distributions + * you are not allowed to use this source to re-create the RAR compression algorithm + * + * Here some html entities which can be used for escaping javadoc tags: + * "&": "&" or "&" + * "<": "<" or "<" + * ">": ">" or ">" + * "@": "@" + */ +package org.fox.ttcomics2.junrar.rarfile; + +public class FileNameDecoder { + public static int getChar(byte[] name, int pos) { + return name[pos] & 0xff; + } + + public static String decode(byte[] name, int encPos) { + int decPos = 0; + int flags = 0; + int flagBits = 0; + + int low = 0; + int high = 0; + int highByte = getChar(name, encPos++); + StringBuffer buf = new StringBuffer(); + while (encPos < name.length) { + if (flagBits == 0) { + flags = getChar(name, encPos++); + flagBits = 8; + } + switch (flags >> 6) { + case 0: + buf.append((char) (getChar(name, encPos++))); + ++decPos; + break; + case 1: + buf.append((char) (getChar(name, encPos++) + (highByte << 8))); + ++decPos; + break; + case 2: + low = getChar(name, encPos); + high = getChar(name, encPos + 1); + buf.append((char) ((high << 8) + low)); + ++decPos; + encPos += 2; + break; + case 3: + int length = getChar(name, encPos++); + if ((length & 0x80) != 0) { + int correction = getChar(name, encPos++); + for (length = (length & 0x7f) + 2; length > 0 && decPos < name.length; length--, decPos++) { + low = (getChar(name, decPos) + correction) & 0xff; + buf.append((char) ((highByte << 8) + low)); + } + } else { + for (length += 2; length > 0 && decPos < name.length; length--, decPos++) { + buf.append((char) (getChar(name, decPos))); + } + } + break; + } + flags = (flags << 2) & 0xff; + flagBits -= 2; + } + return buf.toString(); + } +} diff --git a/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/rarfile/HostSystem.java b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/rarfile/HostSystem.java new file mode 100644 index 0000000..ac3e4a5 --- /dev/null +++ b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/rarfile/HostSystem.java @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2007 innoSysTec (R) GmbH, Germany. All rights reserved. + * Original author: Edmund Wagner + * Creation date: 22.05.2007 + * + * Source: $HeadURL$ + * Last changed: $LastChangedDate$ + * + * + * the unrar licence applies to all junrar source and binary distributions + * you are not allowed to use this source to re-create the RAR compression algorithm + * + * Here some html entities which can be used for escaping javadoc tags: + * "&": "&" or "&" + * "<": "<" or "<" + * ">": ">" or ">" + * "@": "@" + */ +package org.fox.ttcomics2.junrar.rarfile; + +public enum HostSystem { + msdos((byte) 0), + os2((byte) 1), + win32((byte) 2), + unix((byte) 3), + macos((byte) 4), + beos((byte) 5); + + private byte hostByte; + + HostSystem(byte hostByte) { + this.hostByte = hostByte; + } + + public static HostSystem findHostSystem(byte hostByte) { + if (HostSystem.msdos.equals(hostByte)) { + return HostSystem.msdos; + } + if (HostSystem.os2.equals(hostByte)) { + return HostSystem.os2; + } + if (HostSystem.win32.equals(hostByte)) { + return HostSystem.win32; + } + if (HostSystem.unix.equals(hostByte)) { + return HostSystem.unix; + } + if (HostSystem.macos.equals(hostByte)) { + return HostSystem.macos; + } + if (HostSystem.beos.equals(hostByte)) { + return HostSystem.beos; + } + return null; + } + + public boolean equals(byte hostByte) { + return this.hostByte == hostByte; + } + + public byte getHostByte() { + return hostByte; + } + //???? public static final byte max = 6; +} diff --git a/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/rarfile/MacInfoHeader.java b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/rarfile/MacInfoHeader.java new file mode 100644 index 0000000..a4d07d3 --- /dev/null +++ b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/rarfile/MacInfoHeader.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2007 innoSysTec (R) GmbH, Germany. All rights reserved. + * Original author: Edmund Wagner + * Creation date: 26.11.2007 + * + * Source: $HeadURL$ + * Last changed: $LastChangedDate$ + * + * + * the unrar licence applies to all junrar source and binary distributions + * you are not allowed to use this source to re-create the RAR compression algorithm + * + * Here some html entities which can be used for escaping javadoc tags: + * "&": "&" or "&" + * "<": "<" or "<" + * ">": ">" or ">" + * "@": "@" + */ +package org.fox.ttcomics2.junrar.rarfile; + +import org.fox.ttcomics2.junrar.io.Raw; + + +public class MacInfoHeader + extends SubBlockHeader { + + public static final short MacInfoHeaderSize = 8; + + private int fileType; + private int fileCreator; + + public MacInfoHeader(SubBlockHeader sb, byte[] macHeader) { + super(sb); + int pos = 0; + fileType = Raw.readIntLittleEndian(macHeader, pos); + pos += 4; + fileCreator = Raw.readIntLittleEndian(macHeader, pos); + } + + public int getFileCreator() { + return fileCreator; + } + + public void setFileCreator(int fileCreator) { + this.fileCreator = fileCreator; + } + + public int getFileType() { + return fileType; + } + + public void setFileType(int fileType) { + this.fileType = fileType; + } + + public void print() { + super.print(); + } + +} diff --git a/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/rarfile/MainHeader.java b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/rarfile/MainHeader.java new file mode 100644 index 0000000..2f42327 --- /dev/null +++ b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/rarfile/MainHeader.java @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2007 innoSysTec (R) GmbH, Germany. All rights reserved. + * Original author: Edmund Wagner + * Creation date: 22.05.2007 + * + * Source: $HeadURL$ + * Last changed: $LastChangedDate$ + * + * + * the unrar licence applies to all junrar source and binary distributions + * you are not allowed to use this source to re-create the RAR compression algorithm + * + * Here some html entities which can be used for escaping javadoc tags: + * "&": "&" or "&" + * "<": "<" or "<" + * ">": ">" or ">" + * "@": "@" + */ +package org.fox.ttcomics2.junrar.rarfile; + + +import org.fox.ttcomics2.junrar.io.Raw; + + +public class MainHeader extends BaseBlock { + public static final short mainHeaderSizeWithEnc = 7; + public static final short mainHeaderSize = 6; + private short highPosAv; + private int posAv; + private byte encryptVersion; + + public MainHeader(BaseBlock bb, byte[] mainHeader) { + super(bb); + int pos = 0; + highPosAv = Raw.readShortLittleEndian(mainHeader, pos); + pos += 2; + posAv = Raw.readIntLittleEndian(mainHeader, pos); + pos += 4; + + if (hasEncryptVersion()) { + encryptVersion |= mainHeader[pos] & 0xff; + } + } + + public boolean hasArchCmt() { + return (this.flags & BaseBlock.MHD_COMMENT) != 0; + } + + public byte getEncryptVersion() { + return encryptVersion; + } + + public short getHighPosAv() { + return highPosAv; + } + + public int getPosAv() { + return posAv; + } + + public boolean isEncrypted() { + return (this.flags & BaseBlock.MHD_PASSWORD) != 0; + } + + public boolean isMultiVolume() { + return (this.flags & BaseBlock.MHD_VOLUME) != 0; + } + + public boolean isFirstVolume() { + return (this.flags & BaseBlock.MHD_FIRSTVOLUME) != 0; + } + + public void print() { + super.print(); + StringBuilder str = new StringBuilder(); + str.append("posav: " + getPosAv()); + str.append("\nhighposav: " + getHighPosAv()); + str.append("\nhasencversion: " + hasEncryptVersion() + (hasEncryptVersion() ? getEncryptVersion() : "")); + str.append("\nhasarchcmt: " + hasArchCmt()); + str.append("\nisEncrypted: " + isEncrypted()); + str.append("\nisMultivolume: " + isMultiVolume()); + str.append("\nisFirstvolume: " + isFirstVolume()); + str.append("\nisSolid: " + isSolid()); + str.append("\nisLocked: " + isLocked()); + str.append("\nisProtected: " + isProtected()); + str.append("\nisAV: " + isAV()); + } + + public boolean isSolid() { + return (this.flags & MHD_SOLID) != 0; + } + + public boolean isLocked() { + return (this.flags & MHD_LOCK) != 0; + } + + public boolean isProtected() { + return (this.flags & MHD_PROTECT) != 0; + } + + public boolean isAV() { + return (this.flags & MHD_AV) != 0; + } + + public boolean isNewNumbering() { + return (this.flags & MHD_NEWNUMBERING) != 0; + } +} diff --git a/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/rarfile/MarkHeader.java b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/rarfile/MarkHeader.java new file mode 100644 index 0000000..a8366c8 --- /dev/null +++ b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/rarfile/MarkHeader.java @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2007 innoSysTec (R) GmbH, Germany. All rights reserved. + * Original author: Edmund Wagner + * Creation date: 24.05.2007 + * + * Source: $HeadURL$ + * Last changed: $LastChangedDate$ + * + * + * the unrar licence applies to all junrar source and binary distributions + * you are not allowed to use this source to re-create the RAR compression algorithm + * + * Here some html entities which can be used for escaping javadoc tags: + * "&": "&" or "&" + * "<": "<" or "<" + * ">": ">" or ">" + * "@": "@" + */ +package org.fox.ttcomics2.junrar.rarfile; + +import org.fox.ttcomics2.junrar.io.Raw; + + +public class MarkHeader extends BaseBlock { + + private boolean oldFormat = false; + + public MarkHeader(BaseBlock bb) { + super(bb); + } + + public boolean isValid() { + if (!(getHeadCRC() == 0x6152)) { + return false; + } + if (!(getHeaderType() == UnrarHeadertype.MarkHeader)) { + return false; + } + if (!(getFlags() == 0x1a21)) { + return false; + } + return getHeaderSize() == BaseBlockSize; + } + + public boolean isSignature() { + boolean valid = false; + byte[] d = new byte[BaseBlock.BaseBlockSize]; + Raw.writeShortLittleEndian(d, 0, headCRC); + d[2] = headerType; + Raw.writeShortLittleEndian(d, 3, flags); + Raw.writeShortLittleEndian(d, 5, headerSize); + + if (d[0] == 0x52) { + if (d[1] == 0x45 && d[2] == 0x7e && d[3] == 0x5e) { + oldFormat = true; + valid = true; + } else if (d[1] == 0x61 && d[2] == 0x72 && d[3] == 0x21 && d[4] == 0x1a && + d[5] == 0x07 && d[6] == 0x00) { + oldFormat = false; + valid = true; + } + } + return valid; + } + + public boolean isOldFormat() { + return oldFormat; + } + + public void print() { + super.print(); + } +} diff --git a/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/rarfile/NewSubHeaderType.java b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/rarfile/NewSubHeaderType.java new file mode 100644 index 0000000..84af134 --- /dev/null +++ b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/rarfile/NewSubHeaderType.java @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2007 innoSysTec (R) GmbH, Germany. All rights reserved. + * Original author: Edmund Wagner + * Creation date: 24.05.2007 + * + * Source: $HeadURL$ + * Last changed: $LastChangedDate$ + * + * + * the unrar licence applies to all junrar source and binary distributions + * you are not allowed to use this source to re-create the RAR compression algorithm + * + * Here some html entities which can be used for escaping javadoc tags: + * "&": "&" or "&" + * "<": "<" or "<" + * ">": ">" or ">" + * "@": "@" + */ +package org.fox.ttcomics2.junrar.rarfile; + +import java.util.Arrays; + +public class NewSubHeaderType { + + public static final NewSubHeaderType SUBHEAD_TYPE_CMT = new NewSubHeaderType(new byte[]{'C', 'M', 'T'}); + public static final NewSubHeaderType SUBHEAD_TYPE_ACL = new NewSubHeaderType(new byte[]{'A', 'C', 'L'}); + public static final NewSubHeaderType SUBHEAD_TYPE_STREAM = new NewSubHeaderType(new byte[]{'S', 'T', 'M'}); + public static final NewSubHeaderType SUBHEAD_TYPE_UOWNER = new NewSubHeaderType(new byte[]{'U', 'O', 'W'}); + public static final NewSubHeaderType SUBHEAD_TYPE_AV = new NewSubHeaderType(new byte[]{'A', 'V'}); + public static final NewSubHeaderType SUBHEAD_TYPE_RR = new NewSubHeaderType(new byte[]{'R', 'R'}); + public static final NewSubHeaderType SUBHEAD_TYPE_OS2EA = new NewSubHeaderType(new byte[]{'E', 'A', '2'}); + public static final NewSubHeaderType SUBHEAD_TYPE_BEOSEA = new NewSubHeaderType(new byte[]{'E', 'A', 'B', 'E'}); + + private byte[] headerTypes; + + private NewSubHeaderType(byte[] headerTypes) { + this.headerTypes = headerTypes; + } + + public boolean byteEquals(byte[] toCompare) { + return Arrays.equals(this.headerTypes, toCompare); + } + + @Override + public String toString() { + return new String(this.headerTypes); + } +} diff --git a/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/rarfile/ProtectHeader.java b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/rarfile/ProtectHeader.java new file mode 100644 index 0000000..134bc1b --- /dev/null +++ b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/rarfile/ProtectHeader.java @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2007 innoSysTec (R) GmbH, Germany. All rights reserved. + * Original author: Edmund Wagner + * Creation date: 24.05.2007 + * + * Source: $HeadURL$ + * Last changed: $LastChangedDate$ + * + * + * the unrar licence applies to all junrar source and binary distributions + * you are not allowed to use this source to re-create the RAR compression algorithm + * + * Here some html entities which can be used for escaping javadoc tags: + * "&": "&" or "&" + * "<": "<" or "<" + * ">": ">" or ">" + * "@": "@" + */ +package org.fox.ttcomics2.junrar.rarfile; + +import org.fox.ttcomics2.junrar.io.Raw; + +public class ProtectHeader extends BlockHeader { + + public static final int protectHeaderSize = 8; + + private byte version; + private short recSectors; + private int totalBlocks; + private byte mark; + + + public ProtectHeader(BlockHeader bh, byte[] protectHeader) { + super(bh); + + int pos = 0; + version |= protectHeader[pos] & 0xff; + + recSectors = Raw.readShortLittleEndian(protectHeader, pos); + pos += 2; + totalBlocks = Raw.readIntLittleEndian(protectHeader, pos); + pos += 4; + mark |= protectHeader[pos] & 0xff; + } + + + public byte getMark() { + return mark; + } + + public short getRecSectors() { + return recSectors; + } + + public int getTotalBlocks() { + return totalBlocks; + } + + public byte getVersion() { + return version; + } +} diff --git a/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/rarfile/SignHeader.java b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/rarfile/SignHeader.java new file mode 100644 index 0000000..2476cda --- /dev/null +++ b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/rarfile/SignHeader.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2007 innoSysTec (R) GmbH, Germany. All rights reserved. + * Original author: Edmund Wagner + * Creation date: 24.05.2007 + * + * Source: $HeadURL$ + * Last changed: $LastChangedDate$ + * + * + * the unrar licence applies to all junrar source and binary distributions + * you are not allowed to use this source to re-create the RAR compression algorithm + * + * Here some html entities which can be used for escaping javadoc tags: + * "&": "&" or "&" + * "<": "<" or "<" + * ">": ">" or ">" + * "@": "@" + */ +package org.fox.ttcomics2.junrar.rarfile; + +import org.fox.ttcomics2.junrar.io.Raw; + +public class SignHeader extends BaseBlock { + + public static final short signHeaderSize = 8; + + private int creationTime = 0; + private short arcNameSize = 0; + private short userNameSize = 0; + + + public SignHeader(BaseBlock bb, byte[] signHeader) { + super(bb); + + int pos = 0; + creationTime = Raw.readIntLittleEndian(signHeader, pos); + pos += 4; + arcNameSize = Raw.readShortLittleEndian(signHeader, pos); + pos += 2; + userNameSize = Raw.readShortLittleEndian(signHeader, pos); + } + + public short getArcNameSize() { + return arcNameSize; + } + + public int getCreationTime() { + return creationTime; + } + + public short getUserNameSize() { + return userNameSize; + } +} diff --git a/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/rarfile/SubBlockHeader.java b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/rarfile/SubBlockHeader.java new file mode 100644 index 0000000..ae7fd0b --- /dev/null +++ b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/rarfile/SubBlockHeader.java @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2007 innoSysTec (R) GmbH, Germany. All rights reserved. + * Original author: Edmund Wagner + * Creation date: 21.11.2007 + * + * Source: $HeadURL$ + * Last changed: $LastChangedDate$ + * + * + * the unrar licence applies to all junrar source and binary distributions + * you are not allowed to use this source to re-create the RAR compression algorithm + * + * Here some html entities which can be used for escaping javadoc tags: + * "&": "&" or "&" + * "<": "<" or "<" + * ">": ">" or ">" + * "@": "@" + */ +package org.fox.ttcomics2.junrar.rarfile; + + +import org.fox.ttcomics2.junrar.io.Raw; + + +public class SubBlockHeader + extends BlockHeader { + + public static final short SubBlockHeaderSize = 3; + + private short subType; + private byte level; + + public SubBlockHeader(SubBlockHeader sb) { + super(sb); + subType = sb.getSubType().getSubblocktype(); + level = sb.getLevel(); + } + + public SubBlockHeader(BlockHeader bh, byte[] subblock) { + super(bh); + int position = 0; + subType = Raw.readShortLittleEndian(subblock, position); + position += 2; + level |= subblock[position] & 0xff; + } + + public byte getLevel() { + return level; + } + + public SubBlockHeaderType getSubType() { + return SubBlockHeaderType.findSubblockHeaderType(subType); + } + + public void print() { + super.print(); + } +} diff --git a/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/rarfile/SubBlockHeaderType.java b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/rarfile/SubBlockHeaderType.java new file mode 100644 index 0000000..bc911cc --- /dev/null +++ b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/rarfile/SubBlockHeaderType.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2007 innoSysTec (R) GmbH, Germany. All rights reserved. + * Original author: Edmund Wagner + * Creation date: 20.11.2007 + * + * Source: $HeadURL$ + * Last changed: $LastChangedDate$ + * + * + * the unrar licence applies to all junrar source and binary distributions + * you are not allowed to use this source to re-create the RAR compression algorithm + * + * Here some html entities which can be used for escaping javadoc tags: + * "&": "&" or "&" + * "<": "<" or "<" + * ">": ">" or ">" + * "@": "@" + */ + +package org.fox.ttcomics2.junrar.rarfile; + +public enum SubBlockHeaderType { + EA_HEAD((short) 0x100), + UO_HEAD((short) 0x101), + MAC_HEAD((short) 0x102), + BEEA_HEAD((short) 0x103), + NTACL_HEAD((short) 0x104), + STREAM_HEAD((short) 0x105); + + private short subblocktype; + + SubBlockHeaderType(short subblocktype) { + this.subblocktype = subblocktype; + } + + public static SubBlockHeaderType findSubblockHeaderType(short subType) { + if (EA_HEAD.equals(subType)) { + return EA_HEAD; + } else if (UO_HEAD.equals(subType)) { + return UO_HEAD; + } else if (MAC_HEAD.equals(subType)) { + return MAC_HEAD; + } else if (BEEA_HEAD.equals(subType)) { + return BEEA_HEAD; + } else if (NTACL_HEAD.equals(subType)) { + return NTACL_HEAD; + } else if (STREAM_HEAD.equals(subType)) { + return STREAM_HEAD; + } + return null; + } + + public boolean equals(short subblocktype) { + return this.subblocktype == subblocktype; + } + + public short getSubblocktype() { + return subblocktype; + } +} diff --git a/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/rarfile/UnixOwnersHeader.java b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/rarfile/UnixOwnersHeader.java new file mode 100644 index 0000000..8cc237a --- /dev/null +++ b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/rarfile/UnixOwnersHeader.java @@ -0,0 +1,72 @@ +package org.fox.ttcomics2.junrar.rarfile; + + +import org.fox.ttcomics2.junrar.io.Raw; + + +public class UnixOwnersHeader + extends SubBlockHeader { + private int ownerNameSize; + private int groupNameSize; + private String owner; + private String group; + + public UnixOwnersHeader(SubBlockHeader sb, byte[] uoHeader) { + super(sb); + int pos = 0; + ownerNameSize = Raw.readShortLittleEndian(uoHeader, pos) & 0xFFFF; + pos += 2; + groupNameSize = Raw.readShortLittleEndian(uoHeader, pos) & 0xFFFF; + pos += 2; + if (pos + ownerNameSize < uoHeader.length) { + byte[] ownerBuffer = new byte[ownerNameSize]; + System.arraycopy(uoHeader, pos, ownerBuffer, 0, ownerNameSize); + owner = new String(ownerBuffer); + } + pos += ownerNameSize; + if (pos + groupNameSize < uoHeader.length) { + byte[] groupBuffer = new byte[groupNameSize]; + System.arraycopy(uoHeader, pos, groupBuffer, 0, groupNameSize); + group = new String(groupBuffer); + } + } + + public String getGroup() { + return group; + } + + public void setGroup(String group) { + this.group = group; + } + + public int getGroupNameSize() { + return groupNameSize; + } + + public void setGroupNameSize(int groupNameSize) { + this.groupNameSize = groupNameSize; + } + + public String getOwner() { + return owner; + } + + public void setOwner(String owner) { + this.owner = owner; + } + + public int getOwnerNameSize() { + return ownerNameSize; + } + + public void setOwnerNameSize(int ownerNameSize) { + this.ownerNameSize = ownerNameSize; + } + + /* (non-Javadoc) + * @see de.innosystec.unrar.rarfile.SubBlockHeader#print() + */ + public void print() { + super.print(); + } +} diff --git a/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/rarfile/UnrarHeadertype.java b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/rarfile/UnrarHeadertype.java new file mode 100644 index 0000000..9ed04cd --- /dev/null +++ b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/rarfile/UnrarHeadertype.java @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2007 innoSysTec (R) GmbH, Germany. All rights reserved. + * Original author: Edmund Wagner + * Creation date: 22.05.2007 + * + * Source: $HeadURL$ + * Last changed: $LastChangedDate$ + * + * + * the unrar licence applies to all junrar source and binary distributions + * you are not allowed to use this source to re-create the RAR compression algorithm + * + * Here some html entities which can be used for escaping javadoc tags: + * "&": "&" or "&" + * "<": "<" or "<" + * ">": ">" or ">" + * "@": "@" + */ +package org.fox.ttcomics2.junrar.rarfile; + +public enum UnrarHeadertype { + + + MainHeader((byte) 0x73), + + MarkHeader((byte) 0x72), + + FileHeader((byte) 0x74), + + CommHeader((byte) 0x75), + + AvHeader((byte) 0x76), + + SubHeader((byte) 0x77), + + ProtectHeader((byte) 0x78), + + SignHeader((byte) 0x79), + + NewSubHeader((byte) 0x7a), + + EndArcHeader((byte) 0x7b); + + private byte headerByte; + + + UnrarHeadertype(byte headerByte) { + this.headerByte = headerByte; + } + + public static UnrarHeadertype findType(byte headerType) { + if (UnrarHeadertype.MarkHeader.equals(headerType)) { + return UnrarHeadertype.MarkHeader; + } + if (UnrarHeadertype.MainHeader.equals(headerType)) { + return UnrarHeadertype.MainHeader; + } + if (UnrarHeadertype.FileHeader.equals(headerType)) { + return UnrarHeadertype.FileHeader; + } + if (UnrarHeadertype.EndArcHeader.equals(headerType)) { + return UnrarHeadertype.EndArcHeader; + } + if (UnrarHeadertype.NewSubHeader.equals(headerType)) { + return UnrarHeadertype.NewSubHeader; + } + if (UnrarHeadertype.SubHeader.equals(headerType)) { + return UnrarHeadertype.SubHeader; + } + if (UnrarHeadertype.SignHeader.equals(headerType)) { + return UnrarHeadertype.SignHeader; + } + if (UnrarHeadertype.ProtectHeader.equals(headerType)) { + return UnrarHeadertype.ProtectHeader; + } + if (UnrarHeadertype.MarkHeader.equals(headerType)) { + return UnrarHeadertype.MarkHeader; + } + if (UnrarHeadertype.MainHeader.equals(headerType)) { + return UnrarHeadertype.MainHeader; + } + if (UnrarHeadertype.FileHeader.equals(headerType)) { + return UnrarHeadertype.FileHeader; + } + if (UnrarHeadertype.EndArcHeader.equals(headerType)) { + return UnrarHeadertype.EndArcHeader; + } + if (UnrarHeadertype.CommHeader.equals(headerType)) { + return UnrarHeadertype.CommHeader; + } + if (UnrarHeadertype.AvHeader.equals(headerType)) { + return UnrarHeadertype.AvHeader; + } + return null; + } + + public boolean equals(byte header) { + return headerByte == header; + } + + + public byte getHeaderByte() { + return headerByte; + } + + +} diff --git a/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unpack/ComprDataIO.java b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unpack/ComprDataIO.java new file mode 100755 index 0000000..4e0d50f --- /dev/null +++ b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unpack/ComprDataIO.java @@ -0,0 +1,356 @@ +/* + * Copyright (c) 2007 innoSysTec (R) GmbH, Germany. All rights reserved. + * Original author: Edmund Wagner + * Creation date: 31.05.2007 + * + * Source: $HeadURL$ + * Last changed: $LastChangedDate$ + * + * the unrar licence applies to all junrar source and binary distributions + * you are not allowed to use this source to re-create the RAR compression algorithm + * + * Here some html entities which can be used for escaping javadoc tags: + * "&": "&" or "&" + * "<": "<" or "<" + * ">": ">" or ">" + * "@": "@" + */ +package org.fox.ttcomics2.junrar.unpack; + +import org.fox.ttcomics2.junrar.Archive; +import org.fox.ttcomics2.junrar.UnrarCallback; +import org.fox.ttcomics2.junrar.Volume; +import org.fox.ttcomics2.junrar.crc.RarCRC; +import org.fox.ttcomics2.junrar.exception.RarException; +import org.fox.ttcomics2.junrar.exception.RarException.RarExceptionType; +import org.fox.ttcomics2.junrar.io.ReadOnlyAccessInputStream; +import org.fox.ttcomics2.junrar.rarfile.FileHeader; + +import java.io.EOFException; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; + + +public class ComprDataIO { + + private final Archive archive; + + private long unpPackedSize; + + private boolean testMode; + + private boolean skipUnpCRC; + + private InputStream inputStream; + + private OutputStream outputStream; + + private FileHeader subHead; + + // cryptData Crypt; + // cryptData Decrypt; + private boolean packVolume; + + private boolean unpVolume; + + private boolean nextVolumeMissing; + + private long totalPackRead; + + private long unpArcSize; + + private long curPackRead, curPackWrite, curUnpRead, curUnpWrite; + + private long processedArcSize, totalArcSize; + + private long packFileCRC, unpFileCRC, packedCRC; + + private int encryption; + + private int decryption; + + private int lastPercent; + + private char currentCommand; + + public ComprDataIO(Archive arc) { + this.archive = arc; + } + + public void init(OutputStream outputStream) { + this.outputStream = outputStream; + unpPackedSize = 0; + testMode = false; + skipUnpCRC = false; + packVolume = false; + unpVolume = false; + nextVolumeMissing = false; + // command = null; + encryption = 0; + decryption = 0; + totalPackRead = 0; + curPackRead = curPackWrite = curUnpRead = curUnpWrite = 0; + packFileCRC = unpFileCRC = packedCRC = 0xffffffff; + lastPercent = -1; + subHead = null; + + currentCommand = 0; + processedArcSize = totalArcSize = 0; + } + + public void init(FileHeader hd) throws IOException { + long startPos = hd.getPositionInFile() + hd.getHeaderSize(); + unpPackedSize = hd.getFullPackSize(); + inputStream = new ReadOnlyAccessInputStream(archive.getRof(), startPos, + startPos + unpPackedSize); + subHead = hd; + curUnpRead = 0; + curPackWrite = 0; + packedCRC = 0xFFffFFff; + } + + public int unpRead(byte[] addr, int offset, int count) throws IOException, + RarException { + int retCode = 0, totalRead = 0; + while (count > 0) { + int readSize = (count > unpPackedSize) ? (int) unpPackedSize + : count; + retCode = inputStream.read(addr, offset, readSize); + if (retCode < 0) { + throw new EOFException(); + } + if (subHead.isSplitAfter()) { + packedCRC = RarCRC.checkCrc((int) packedCRC, addr, offset, + retCode); + } + + curUnpRead += retCode; + totalRead += retCode; + offset += retCode; + count -= retCode; + unpPackedSize -= retCode; + archive.bytesReadRead(retCode); + if (unpPackedSize == 0 && subHead.isSplitAfter()) { + Volume nextVolume = archive.getVolumeManager().nextArchive( + archive, archive.getVolume()); + if (nextVolume == null) { + nextVolumeMissing = true; + return -1; + } + + FileHeader hd = this.getSubHeader(); + if (hd.getUnpVersion() >= 20 && hd.getFileCRC() != 0xffffffff + && this.getPackedCRC() != ~hd.getFileCRC()) { + throw new RarException(RarExceptionType.crcError); + } + UnrarCallback callback = archive.getUnrarCallback(); + if ((callback != null) + && !callback.isNextVolumeReady(nextVolume)) { + return -1; + } + archive.setVolume(nextVolume); + hd = archive.nextFileHeader(); + if (hd == null) { + return -1; + } + this.init(hd); + } else { + break; + } + } + + if (retCode != -1) { + retCode = totalRead; + } + return retCode; + + } + + public void unpWrite(byte[] addr, int offset, int count) throws IOException { + if (!testMode) { + // DestFile->Write(Addr,Count); + outputStream.write(addr, offset, count); + } + + curUnpWrite += count; + + if (!skipUnpCRC) { + if (archive.isOldFormat()) { + unpFileCRC = RarCRC + .checkOldCrc((short) unpFileCRC, addr, count); + } else { + unpFileCRC = RarCRC.checkCrc((int) unpFileCRC, addr, offset, + count); + } + } + // if (!skipArcCRC) { + // archive.updateDataCRC(Addr, offset, ReadSize); + // } + } + + public void setPackedSizeToRead(long size) { + unpPackedSize = size; + } + + public void setTestMode(boolean mode) { + testMode = mode; + } + + public void setSkipUnpCRC(boolean skip) { + skipUnpCRC = skip; + } + + public long getCurPackRead() { + return curPackRead; + } + + public void setCurPackRead(long curPackRead) { + this.curPackRead = curPackRead; + } + + public long getCurPackWrite() { + return curPackWrite; + } + + public void setCurPackWrite(long curPackWrite) { + this.curPackWrite = curPackWrite; + } + + public long getCurUnpRead() { + return curUnpRead; + } + + public void setCurUnpRead(long curUnpRead) { + this.curUnpRead = curUnpRead; + } + + public long getCurUnpWrite() { + return curUnpWrite; + } + + public void setCurUnpWrite(long curUnpWrite) { + this.curUnpWrite = curUnpWrite; + } + + public int getDecryption() { + return decryption; + } + + public void setDecryption(int decryption) { + this.decryption = decryption; + } + + public int getEncryption() { + return encryption; + } + + public void setEncryption(int encryption) { + this.encryption = encryption; + } + + public boolean isNextVolumeMissing() { + return nextVolumeMissing; + } + + public void setNextVolumeMissing(boolean nextVolumeMissing) { + this.nextVolumeMissing = nextVolumeMissing; + } + + public long getPackedCRC() { + return packedCRC; + } + + public void setPackedCRC(long packedCRC) { + this.packedCRC = packedCRC; + } + + public long getPackFileCRC() { + return packFileCRC; + } + + public void setPackFileCRC(long packFileCRC) { + this.packFileCRC = packFileCRC; + } + + public boolean isPackVolume() { + return packVolume; + } + + public void setPackVolume(boolean packVolume) { + this.packVolume = packVolume; + } + + public long getProcessedArcSize() { + return processedArcSize; + } + + public void setProcessedArcSize(long processedArcSize) { + this.processedArcSize = processedArcSize; + } + + public long getTotalArcSize() { + return totalArcSize; + } + + public void setTotalArcSize(long totalArcSize) { + this.totalArcSize = totalArcSize; + } + + public long getTotalPackRead() { + return totalPackRead; + } + + public void setTotalPackRead(long totalPackRead) { + this.totalPackRead = totalPackRead; + } + + public long getUnpArcSize() { + return unpArcSize; + } + + public void setUnpArcSize(long unpArcSize) { + this.unpArcSize = unpArcSize; + } + + public long getUnpFileCRC() { + return unpFileCRC; + } + + public void setUnpFileCRC(long unpFileCRC) { + this.unpFileCRC = unpFileCRC; + } + + public boolean isUnpVolume() { + return unpVolume; + } + + public void setUnpVolume(boolean unpVolume) { + this.unpVolume = unpVolume; + } + + public FileHeader getSubHeader() { + return subHead; + } + + public void setSubHeader(FileHeader hd) { + subHead = hd; + + } + + // public void setEncryption(int method, char[] Password, byte[] Salt, + // boolean encrypt, boolean handsOffHash) + // { + // + // } + // + // public void setAV15Encryption() + // { + // + // } + // + // public void setCmt13Encryption() + // { + // + // } +} diff --git a/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unpack/Unpack.java b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unpack/Unpack.java new file mode 100755 index 0000000..5cf3438 --- /dev/null +++ b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unpack/Unpack.java @@ -0,0 +1,1029 @@ +/* + * Copyright (c) 2007 innoSysTec (R) GmbH, Germany. All rights reserved. + * Original author: Edmund Wagner + * Creation date: 31.05.2007 + * + * Source: $HeadURL$ + * Last changed: $LastChangedDate$ + * + * the unrar licence applies to all junrar source and binary distributions + * you are not allowed to use this source to re-create the RAR compression algorithm + * + * Here some html entities which can be used for escaping javadoc tags: + * "&": "&" or "&" + * "<": "<" or "<" + * ">": ">" or ">" + * "@": "@" + */ +package org.fox.ttcomics2.junrar.unpack; + +import org.fox.ttcomics2.junrar.exception.RarException; +import org.fox.ttcomics2.junrar.unpack.decode.Compress; +import org.fox.ttcomics2.junrar.unpack.ppm.BlockTypes; +import org.fox.ttcomics2.junrar.unpack.ppm.ModelPPM; +import org.fox.ttcomics2.junrar.unpack.ppm.SubAllocator; +import org.fox.ttcomics2.junrar.unpack.vm.BitInput; +import org.fox.ttcomics2.junrar.unpack.vm.RarVM; +import org.fox.ttcomics2.junrar.unpack.vm.VMPreparedProgram; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Vector; + + +public final class Unpack extends Unpack20 { + + public static int[] DBitLengthCounts = {4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 14, 0, 12}; + private final ModelPPM ppm = new ModelPPM(); + private int ppmEscChar; + private RarVM rarVM = new RarVM(); + /* Filters code, one entry per filter */ + private List filters = new ArrayList(); + /* Filters stack, several entrances of same filter are possible */ + private List prgStack = new ArrayList(); + /* + * lengths of preceding blocks, one length per filter. Used to reduce size + * required to write block length if lengths are repeating + */ + private List oldFilterLengths = new ArrayList(); + private int lastFilter; + private boolean tablesRead; + private byte[] unpOldTable = new byte[Compress.HUFF_TABLE_SIZE]; + private BlockTypes unpBlockType; + private boolean externalWindow; + private long writtenFileSize; + private boolean fileExtracted; + private boolean ppmError; + private int prevLowDist; + private int lowDistRepCount; + + public Unpack(ComprDataIO DataIO) { + unpIO = DataIO; + window = null; + externalWindow = false; + suspended = false; + unpAllBuf = false; + unpSomeRead = false; + } + + public void init(byte[] window) { + if (window == null) { + this.window = new byte[Compress.MAXWINSIZE]; + } else { + this.window = window; + externalWindow = true; + } + inAddr = 0; + unpInitData(false); + } + + public void doUnpack(int method, boolean solid) throws IOException, + RarException { + if (unpIO.getSubHeader().getUnpMethod() == 0x30) { + unstoreFile(); + } + switch (method) { + case 15: // rar 1.5 compression + unpack15(solid); + break; + case 20: // rar 2.x compression + case 26: // files larger than 2GB + unpack20(solid); + break; + case 29: // rar 3.x compression + case 36: // alternative hash + unpack29(solid); + break; + } + } + + private void unstoreFile() throws IOException, RarException { + byte[] buffer = new byte[0x10000]; + while (true) { + int code = unpIO.unpRead(buffer, 0, (int) Math.min(buffer.length, + destUnpSize)); + if (code == 0 || code == -1) + break; + code = code < destUnpSize ? code : (int) destUnpSize; + unpIO.unpWrite(buffer, 0, code); + if (destUnpSize >= 0) + destUnpSize -= code; + } + + } + + private void unpack29(boolean solid) throws IOException, RarException { + + int[] DDecode = new int[Compress.DC]; + byte[] DBits = new byte[Compress.DC]; + + int Bits; + + if (DDecode[1] == 0) { + int Dist = 0, BitLength = 0, Slot = 0; + for (int I = 0; I < DBitLengthCounts.length; I++, BitLength++) { + int count = DBitLengthCounts[I]; + for (int J = 0; J < count; J++, Slot++, Dist += (1 << BitLength)) { + DDecode[Slot] = Dist; + DBits[Slot] = (byte) BitLength; + } + } + } + + fileExtracted = true; + + if (!suspended) { + unpInitData(solid); + if (!unpReadBuf()) { + return; + } + if ((!solid || !tablesRead) && !readTables()) { + return; + } + } + + if (ppmError) { + return; + } + + while (true) { + unpPtr &= Compress.MAXWINMASK; + + if (inAddr > readBorder) { + if (!unpReadBuf()) { + break; + } + } + // System.out.println(((wrPtr - unpPtr) & + // Compress.MAXWINMASK)+":"+wrPtr+":"+unpPtr); + if (((wrPtr - unpPtr) & Compress.MAXWINMASK) < 260 + && wrPtr != unpPtr) { + + UnpWriteBuf(); + if (writtenFileSize > destUnpSize) { + return; + } + if (suspended) { + fileExtracted = false; + return; + } + } + if (unpBlockType == BlockTypes.BLOCK_PPM) { + int Ch = ppm.decodeChar(); + if (Ch == -1) { + ppmError = true; + break; + } + if (Ch == ppmEscChar) { + int NextCh = ppm.decodeChar(); + if (NextCh == 0) { + if (!readTables()) { + break; + } + continue; + } + if (NextCh == 2 || NextCh == -1) { + break; + } + if (NextCh == 3) { + if (!readVMCodePPM()) { + break; + } + continue; + } + if (NextCh == 4) { + int Distance = 0, Length = 0; + boolean failed = false; + for (int I = 0; I < 4 && !failed; I++) { + int ch = ppm.decodeChar(); + if (ch == -1) { + failed = true; + } else { + if (I == 3) { + // Bug fixed + Length = ch & 0xff; + } else { + // Bug fixed + Distance = (Distance << 8) + (ch & 0xff); + } + } + } + if (failed) { + break; + } + copyString(Length + 32, Distance + 2); + continue; + } + if (NextCh == 5) { + int Length = ppm.decodeChar(); + if (Length == -1) { + break; + } + copyString(Length + 4, 1); + continue; + } + } + window[unpPtr++] = (byte) Ch; + continue; + } + + int Number = decodeNumber(LD); + if (Number < 256) { + window[unpPtr++] = (byte) Number; + continue; + } + if (Number >= 271) { + int Length = LDecode[Number -= 271] + 3; + if ((Bits = LBits[Number]) > 0) { + Length += getbits() >>> (16 - Bits); + addbits(Bits); + } + + int DistNumber = decodeNumber(DD); + int Distance = DDecode[DistNumber] + 1; + if ((Bits = DBits[DistNumber]) > 0) { + if (DistNumber > 9) { + if (Bits > 4) { + Distance += ((getbits() >>> (20 - Bits)) << 4); + addbits(Bits - 4); + } + if (lowDistRepCount > 0) { + lowDistRepCount--; + Distance += prevLowDist; + } else { + int LowDist = decodeNumber(LDD); + if (LowDist == 16) { + lowDistRepCount = Compress.LOW_DIST_REP_COUNT - 1; + Distance += prevLowDist; + } else { + Distance += LowDist; + prevLowDist = LowDist; + } + } + } else { + Distance += getbits() >>> (16 - Bits); + addbits(Bits); + } + } + + if (Distance >= 0x2000) { + Length++; + if (Distance >= 0x40000L) { + Length++; + } + } + + insertOldDist(Distance); + insertLastMatch(Length, Distance); + + copyString(Length, Distance); + continue; + } + if (Number == 256) { + if (!readEndOfBlock()) { + break; + } + continue; + } + if (Number == 257) { + if (!readVMCode()) { + break; + } + continue; + } + if (Number == 258) { + if (lastLength != 0) { + copyString(lastLength, lastDist); + } + continue; + } + if (Number < 263) { + int DistNum = Number - 259; + int Distance = oldDist[DistNum]; + for (int I = DistNum; I > 0; I--) { + oldDist[I] = oldDist[I - 1]; + } + oldDist[0] = Distance; + + int LengthNumber = decodeNumber(RD); + int Length = LDecode[LengthNumber] + 2; + if ((Bits = LBits[LengthNumber]) > 0) { + Length += getbits() >>> (16 - Bits); + addbits(Bits); + } + insertLastMatch(Length, Distance); + copyString(Length, Distance); + continue; + } + if (Number < 272) { + int Distance = SDDecode[Number -= 263] + 1; + if ((Bits = SDBits[Number]) > 0) { + Distance += getbits() >>> (16 - Bits); + addbits(Bits); + } + insertOldDist(Distance); + insertLastMatch(2, Distance); + copyString(2, Distance); + continue; + } + } + UnpWriteBuf(); + + } + + private void UnpWriteBuf() throws IOException { + int WrittenBorder = wrPtr; + int WriteSize = (unpPtr - WrittenBorder) & Compress.MAXWINMASK; + for (int I = 0; I < prgStack.size(); I++) { + UnpackFilter flt = prgStack.get(I); + if (flt == null) { + continue; + } + if (flt.isNextWindow()) { + flt.setNextWindow(false);// ->NextWindow=false; + continue; + } + int BlockStart = flt.getBlockStart();// ->BlockStart; + int BlockLength = flt.getBlockLength();// ->BlockLength; + if (((BlockStart - WrittenBorder) & Compress.MAXWINMASK) < WriteSize) { + if (WrittenBorder != BlockStart) { + UnpWriteArea(WrittenBorder, BlockStart); + WrittenBorder = BlockStart; + WriteSize = (unpPtr - WrittenBorder) & Compress.MAXWINMASK; + } + if (BlockLength <= WriteSize) { + int BlockEnd = (BlockStart + BlockLength) + & Compress.MAXWINMASK; + if (BlockStart < BlockEnd || BlockEnd == 0) { + // VM.SetMemory(0,Window+BlockStart,BlockLength); + rarVM.setMemory(0, window, BlockStart, BlockLength); + } else { + int FirstPartLength = Compress.MAXWINSIZE - BlockStart; + // VM.SetMemory(0,Window+BlockStart,FirstPartLength); + rarVM.setMemory(0, window, BlockStart, FirstPartLength); + // VM.SetMemory(FirstPartLength,Window,BlockEnd); + rarVM.setMemory(FirstPartLength, window, 0, BlockEnd); + + } + + VMPreparedProgram ParentPrg = filters.get( + flt.getParentFilter()).getPrg(); + VMPreparedProgram Prg = flt.getPrg(); + + if (ParentPrg.getGlobalData().size() > RarVM.VM_FIXEDGLOBALSIZE) { + // copy global data from previous script execution if + // any + // Prg->GlobalData.Alloc(ParentPrg->GlobalData.Size()); + // memcpy(&Prg->GlobalData[VM_FIXEDGLOBALSIZE],&ParentPrg->GlobalData[VM_FIXEDGLOBALSIZE],ParentPrg->GlobalData.Size()-VM_FIXEDGLOBALSIZE); + Prg.getGlobalData().setSize( + ParentPrg.getGlobalData().size()); + for (int i = 0; i < ParentPrg.getGlobalData().size() + - RarVM.VM_FIXEDGLOBALSIZE; i++) { + Prg.getGlobalData().set( + RarVM.VM_FIXEDGLOBALSIZE + i, + ParentPrg.getGlobalData().get( + RarVM.VM_FIXEDGLOBALSIZE + i)); + } + } + + ExecuteCode(Prg); + + if (Prg.getGlobalData().size() > RarVM.VM_FIXEDGLOBALSIZE) { + // save global data for next script execution + if (ParentPrg.getGlobalData().size() < Prg + .getGlobalData().size()) { + ParentPrg.getGlobalData().setSize( + Prg.getGlobalData().size());// ->GlobalData.Alloc(Prg->GlobalData.Size()); + } + // memcpy(&ParentPrg->GlobalData[VM_FIXEDGLOBALSIZE],&Prg->GlobalData[VM_FIXEDGLOBALSIZE],Prg->GlobalData.Size()-VM_FIXEDGLOBALSIZE); + for (int i = 0; i < Prg.getGlobalData().size() + - RarVM.VM_FIXEDGLOBALSIZE; i++) { + ParentPrg.getGlobalData().set( + RarVM.VM_FIXEDGLOBALSIZE + i, + Prg.getGlobalData().get( + RarVM.VM_FIXEDGLOBALSIZE + i)); + } + } else { + ParentPrg.getGlobalData().clear(); + } + + int FilteredDataOffset = Prg.getFilteredDataOffset(); + int FilteredDataSize = Prg.getFilteredDataSize(); + byte[] FilteredData = new byte[FilteredDataSize]; + + for (int i = 0; i < FilteredDataSize; i++) { + FilteredData[i] = rarVM.getMem()[FilteredDataOffset + i];// Prg.getGlobalData().get(FilteredDataOffset + // + + // i); + } + + prgStack.set(I, null); + while (I + 1 < prgStack.size()) { + UnpackFilter NextFilter = prgStack.get(I + 1); + if (NextFilter == null + || NextFilter.getBlockStart() != BlockStart + || NextFilter.getBlockLength() != FilteredDataSize + || NextFilter.isNextWindow()) { + break; + } + // apply several filters to same data block + + rarVM.setMemory(0, FilteredData, 0, FilteredDataSize);// .SetMemory(0,FilteredData,FilteredDataSize); + + VMPreparedProgram pPrg = filters.get( + NextFilter.getParentFilter()).getPrg(); + VMPreparedProgram NextPrg = NextFilter.getPrg(); + + if (pPrg.getGlobalData().size() > RarVM.VM_FIXEDGLOBALSIZE) { + // copy global data from previous script execution + // if any + // NextPrg->GlobalData.Alloc(ParentPrg->GlobalData.Size()); + NextPrg.getGlobalData().setSize( + pPrg.getGlobalData().size()); + // memcpy(&NextPrg->GlobalData[VM_FIXEDGLOBALSIZE],&ParentPrg->GlobalData[VM_FIXEDGLOBALSIZE],ParentPrg->GlobalData.Size()-VM_FIXEDGLOBALSIZE); + for (int i = 0; i < pPrg.getGlobalData().size() + - RarVM.VM_FIXEDGLOBALSIZE; i++) { + NextPrg.getGlobalData().set( + RarVM.VM_FIXEDGLOBALSIZE + i, + pPrg.getGlobalData().get( + RarVM.VM_FIXEDGLOBALSIZE + i)); + } + } + + ExecuteCode(NextPrg); + + if (NextPrg.getGlobalData().size() > RarVM.VM_FIXEDGLOBALSIZE) { + // save global data for next script execution + if (pPrg.getGlobalData().size() < NextPrg + .getGlobalData().size()) { + pPrg.getGlobalData().setSize( + NextPrg.getGlobalData().size()); + } + // memcpy(&ParentPrg->GlobalData[VM_FIXEDGLOBALSIZE],&NextPrg->GlobalData[VM_FIXEDGLOBALSIZE],NextPrg->GlobalData.Size()-VM_FIXEDGLOBALSIZE); + for (int i = 0; i < NextPrg.getGlobalData().size() + - RarVM.VM_FIXEDGLOBALSIZE; i++) { + pPrg.getGlobalData().set( + RarVM.VM_FIXEDGLOBALSIZE + i, + NextPrg.getGlobalData().get( + RarVM.VM_FIXEDGLOBALSIZE + i)); + } + } else { + pPrg.getGlobalData().clear(); + } + FilteredDataOffset = NextPrg.getFilteredDataOffset(); + FilteredDataSize = NextPrg.getFilteredDataSize(); + + FilteredData = new byte[FilteredDataSize]; + for (int i = 0; i < FilteredDataSize; i++) { + FilteredData[i] = NextPrg.getGlobalData().get( + FilteredDataOffset + i); + } + + I++; + prgStack.set(I, null); + } + unpIO.unpWrite(FilteredData, 0, FilteredDataSize); + unpSomeRead = true; + writtenFileSize += FilteredDataSize; + WrittenBorder = BlockEnd; + WriteSize = (unpPtr - WrittenBorder) & Compress.MAXWINMASK; + } else { + for (int J = I; J < prgStack.size(); J++) { + UnpackFilter filt = prgStack.get(J); + if (filt != null && filt.isNextWindow()) { + filt.setNextWindow(false); + } + } + wrPtr = WrittenBorder; + return; + } + } + } + + UnpWriteArea(WrittenBorder, unpPtr); + wrPtr = unpPtr; + + } + + private void UnpWriteArea(int startPtr, int endPtr) throws IOException { + if (endPtr != startPtr) { + unpSomeRead = true; + } + if (endPtr < startPtr) { + UnpWriteData(window, startPtr, -startPtr & Compress.MAXWINMASK); + UnpWriteData(window, 0, endPtr); + unpAllBuf = true; + } else { + UnpWriteData(window, startPtr, endPtr - startPtr); + } + } + + private void UnpWriteData(byte[] data, int offset, int size) + throws IOException { + if (writtenFileSize >= destUnpSize) { + return; + } + int writeSize = size; + long leftToWrite = destUnpSize - writtenFileSize; + if (writeSize > leftToWrite) { + writeSize = (int) leftToWrite; + } + unpIO.unpWrite(data, offset, writeSize); + + writtenFileSize += size; + + } + + private void insertOldDist(int distance) { + oldDist[3] = oldDist[2]; + oldDist[2] = oldDist[1]; + oldDist[1] = oldDist[0]; + oldDist[0] = distance; + } + + private void insertLastMatch(int length, int distance) { + lastDist = distance; + lastLength = length; + } + + private void copyString(int length, int distance) { + // System.out.println("copyString(" + length + ", " + distance + ")"); + + int destPtr = unpPtr - distance; + // System.out.println(unpPtr+":"+distance); + if (destPtr >= 0 && destPtr < Compress.MAXWINSIZE - 260 + && unpPtr < Compress.MAXWINSIZE - 260) { + + window[unpPtr++] = window[destPtr++]; + + while (--length > 0) + + window[unpPtr++] = window[destPtr++]; + } else + while (length-- != 0) { + window[unpPtr] = window[destPtr++ & Compress.MAXWINMASK]; + unpPtr = (unpPtr + 1) & Compress.MAXWINMASK; + } + } + + protected void unpInitData(boolean solid) { + if (!solid) { + tablesRead = false; + Arrays.fill(oldDist, 0); // memset(oldDist,0,sizeof(OldDist)); + + oldDistPtr = 0; + lastDist = 0; + lastLength = 0; + + Arrays.fill(unpOldTable, (byte) 0);// memset(UnpOldTable,0,sizeof(UnpOldTable)); + + unpPtr = 0; + wrPtr = 0; + ppmEscChar = 2; + + initFilters(); + } + InitBitInput(); + ppmError = false; + writtenFileSize = 0; + readTop = 0; + readBorder = 0; + unpInitData20(solid); + } + + private void initFilters() { + oldFilterLengths.clear(); + lastFilter = 0; + + filters.clear(); + + prgStack.clear(); + } + + private boolean readEndOfBlock() throws IOException, RarException { + int BitField = getbits(); + boolean NewTable, NewFile = false; + if ((BitField & 0x8000) != 0) { + NewTable = true; + addbits(1); + } else { + NewFile = true; + NewTable = (BitField & 0x4000) != 0; + addbits(2); + } + tablesRead = !NewTable; + return !(NewFile || NewTable && !readTables()); + } + + private boolean readTables() throws IOException, RarException { + byte[] bitLength = new byte[Compress.BC]; + + byte[] table = new byte[Compress.HUFF_TABLE_SIZE]; + if (inAddr > readTop - 25) { + if (!unpReadBuf()) { + return (false); + } + } + faddbits((8 - inBit) & 7); + long bitField = fgetbits() & 0xffFFffFF; + if ((bitField & 0x8000) != 0) { + unpBlockType = BlockTypes.BLOCK_PPM; + return (ppm.decodeInit(this, ppmEscChar)); + } + unpBlockType = BlockTypes.BLOCK_LZ; + + prevLowDist = 0; + lowDistRepCount = 0; + + if ((bitField & 0x4000) == 0) { + Arrays.fill(unpOldTable, (byte) 0);// memset(UnpOldTable,0,sizeof(UnpOldTable)); + } + faddbits(2); + + for (int i = 0; i < Compress.BC; i++) { + int length = (fgetbits() >>> 12) & 0xFF; + faddbits(4); + if (length == 15) { + int zeroCount = (fgetbits() >>> 12) & 0xFF; + faddbits(4); + if (zeroCount == 0) { + bitLength[i] = 15; + } else { + zeroCount += 2; + while (zeroCount-- > 0 && i < bitLength.length) { + bitLength[i++] = 0; + } + i--; + } + } else { + bitLength[i] = (byte) length; + } + } + + makeDecodeTables(bitLength, 0, BD, Compress.BC); + + int TableSize = Compress.HUFF_TABLE_SIZE; + + for (int i = 0; i < TableSize; ) { + if (inAddr > readTop - 5) { + if (!unpReadBuf()) { + return (false); + } + } + int Number = decodeNumber(BD); + if (Number < 16) { + table[i] = (byte) ((Number + unpOldTable[i]) & 0xf); + i++; + } else if (Number < 18) { + int N; + if (Number == 16) { + N = (fgetbits() >>> 13) + 3; + faddbits(3); + } else { + N = (fgetbits() >>> 9) + 11; + faddbits(7); + } + while (N-- > 0 && i < TableSize) { + table[i] = table[i - 1]; + i++; + } + } else { + int N; + if (Number == 18) { + N = (fgetbits() >>> 13) + 3; + faddbits(3); + } else { + N = (fgetbits() >>> 9) + 11; + faddbits(7); + } + while (N-- > 0 && i < TableSize) { + table[i++] = 0; + } + } + } + tablesRead = true; + if (inAddr > readTop) { + return (false); + } + makeDecodeTables(table, 0, LD, Compress.NC); + makeDecodeTables(table, Compress.NC, DD, Compress.DC); + makeDecodeTables(table, Compress.NC + Compress.DC, LDD, Compress.LDC); + makeDecodeTables(table, Compress.NC + Compress.DC + Compress.LDC, RD, + Compress.RC); + + // memcpy(unpOldTable,table,sizeof(unpOldTable)); + for (int i = 0; i < unpOldTable.length; i++) { + unpOldTable[i] = table[i]; + } + return (true); + + } + + private boolean readVMCode() throws IOException, RarException { + int FirstByte = getbits() >> 8; + addbits(8); + int Length = (FirstByte & 7) + 1; + if (Length == 7) { + Length = (getbits() >> 8) + 7; + addbits(8); + } else if (Length == 8) { + Length = getbits(); + addbits(16); + } + List vmCode = new ArrayList(); + for (int I = 0; I < Length; I++) { + if (inAddr >= readTop - 1 && !unpReadBuf() && I < Length - 1) { + return (false); + } + vmCode.add(Byte.valueOf((byte) (getbits() >> 8))); + addbits(8); + } + return (addVMCode(FirstByte, vmCode, Length)); + } + + private boolean readVMCodePPM() throws IOException, RarException { + int FirstByte = ppm.decodeChar(); + if (FirstByte == -1) { + return (false); + } + int Length = (FirstByte & 7) + 1; + if (Length == 7) { + int B1 = ppm.decodeChar(); + if (B1 == -1) { + return (false); + } + Length = B1 + 7; + } else if (Length == 8) { + int B1 = ppm.decodeChar(); + if (B1 == -1) { + return (false); + } + int B2 = ppm.decodeChar(); + if (B2 == -1) { + return (false); + } + Length = B1 * 256 + B2; + } + List vmCode = new ArrayList(); + for (int I = 0; I < Length; I++) { + int Ch = ppm.decodeChar(); + if (Ch == -1) { + return (false); + } + vmCode.add(Byte.valueOf((byte) Ch));// VMCode[I]=Ch; + } + return (addVMCode(FirstByte, vmCode, Length)); + } + + private boolean addVMCode(int firstByte, List vmCode, int length) { + BitInput Inp = new BitInput(); + Inp.InitBitInput(); + // memcpy(Inp.InBuf,Code,Min(BitInput::MAX_SIZE,CodeSize)); + for (int i = 0; i < Math.min(BitInput.MAX_SIZE, vmCode.size()); i++) { + Inp.getInBuf()[i] = vmCode.get(i); + } + rarVM.init(); + + int FiltPos; + if ((firstByte & 0x80) != 0) { + FiltPos = RarVM.ReadData(Inp); + if (FiltPos == 0) { + initFilters(); + } else { + FiltPos--; + } + } else + FiltPos = lastFilter; // use the same filter as last time + + if (FiltPos > filters.size() || FiltPos > oldFilterLengths.size()) { + return (false); + } + lastFilter = FiltPos; + boolean NewFilter = (FiltPos == filters.size()); + + UnpackFilter StackFilter = new UnpackFilter(); // new filter for + // PrgStack + + UnpackFilter Filter; + if (NewFilter) // new filter code, never used before since VM reset + { + // too many different filters, corrupt archive + if (FiltPos > 1024) { + return (false); + } + + // Filters[Filters.Size()-1]=Filter=new UnpackFilter; + Filter = new UnpackFilter(); + filters.add(Filter); + StackFilter.setParentFilter(filters.size() - 1); + oldFilterLengths.add(0); + Filter.setExecCount(0); + } else // filter was used in the past + { + Filter = filters.get(FiltPos); + StackFilter.setParentFilter(FiltPos); + Filter.setExecCount(Filter.getExecCount() + 1);// ->ExecCount++; + } + + prgStack.add(StackFilter); + StackFilter.setExecCount(Filter.getExecCount());// ->ExecCount; + + int BlockStart = RarVM.ReadData(Inp); + if ((firstByte & 0x40) != 0) { + BlockStart += 258; + } + StackFilter.setBlockStart((BlockStart + unpPtr) & Compress.MAXWINMASK); + if ((firstByte & 0x20) != 0) { + StackFilter.setBlockLength(RarVM.ReadData(Inp)); + } else { + StackFilter + .setBlockLength(FiltPos < oldFilterLengths.size() ? oldFilterLengths + .get(FiltPos) + : 0); + } + StackFilter.setNextWindow((wrPtr != unpPtr) + && ((wrPtr - unpPtr) & Compress.MAXWINMASK) <= BlockStart); + + // DebugLog("\nNextWindow: UnpPtr=%08x WrPtr=%08x + // BlockStart=%08x",UnpPtr,WrPtr,BlockStart); + + oldFilterLengths.set(FiltPos, StackFilter.getBlockLength()); + + // memset(StackFilter->Prg.InitR,0,sizeof(StackFilter->Prg.InitR)); + Arrays.fill(StackFilter.getPrg().getInitR(), 0); + StackFilter.getPrg().getInitR()[3] = RarVM.VM_GLOBALMEMADDR;// StackFilter->Prg.InitR[3]=VM_GLOBALMEMADDR; + StackFilter.getPrg().getInitR()[4] = StackFilter.getBlockLength();// StackFilter->Prg.InitR[4]=StackFilter->BlockLength; + StackFilter.getPrg().getInitR()[5] = StackFilter.getExecCount();// StackFilter->Prg.InitR[5]=StackFilter->ExecCount; + + if ((firstByte & 0x10) != 0) // set registers to optional parameters + // if any + { + int InitMask = Inp.fgetbits() >>> 9; + Inp.faddbits(7); + for (int I = 0; I < 7; I++) { + if ((InitMask & (1 << I)) != 0) { + // StackFilter->Prg.InitR[I]=RarVM::ReadData(Inp); + StackFilter.getPrg().getInitR()[I] = RarVM.ReadData(Inp); + } + } + } + + if (NewFilter) { + int VMCodeSize = RarVM.ReadData(Inp); + if (VMCodeSize >= 0x10000 || VMCodeSize == 0) { + return (false); + } + byte[] VMCode = new byte[VMCodeSize]; + for (int I = 0; I < VMCodeSize; I++) { + if (Inp.Overflow(3)) { + return (false); + } + VMCode[I] = (byte) (Inp.fgetbits() >> 8); + Inp.faddbits(8); + } + // VM.Prepare(&VMCode[0],VMCodeSize,&Filter->Prg); + rarVM.prepare(VMCode, VMCodeSize, Filter.getPrg()); + } + StackFilter.getPrg().setAltCmd(Filter.getPrg().getCmd());// StackFilter->Prg.AltCmd=&Filter->Prg.Cmd[0]; + StackFilter.getPrg().setCmdCount(Filter.getPrg().getCmdCount());// StackFilter->Prg.CmdCount=Filter->Prg.CmdCount; + + int StaticDataSize = Filter.getPrg().getStaticData().size(); + if (StaticDataSize > 0 && StaticDataSize < RarVM.VM_GLOBALMEMSIZE) { + // read statically defined data contained in DB commands + // StackFilter->Prg.StaticData.Add(StaticDataSize); + StackFilter.getPrg().setStaticData(Filter.getPrg().getStaticData()); + // memcpy(&StackFilter->Prg.StaticData[0],&Filter->Prg.StaticData[0],StaticDataSize); + } + + if (StackFilter.getPrg().getGlobalData().size() < RarVM.VM_FIXEDGLOBALSIZE) { + // StackFilter->Prg.GlobalData.Reset(); + // StackFilter->Prg.GlobalData.Add(VM_FIXEDGLOBALSIZE); + StackFilter.getPrg().getGlobalData().clear(); + StackFilter.getPrg().getGlobalData().setSize( + RarVM.VM_FIXEDGLOBALSIZE); + } + + // byte *GlobalData=&StackFilter->Prg.GlobalData[0]; + Vector globalData = StackFilter.getPrg().getGlobalData(); + for (int I = 0; I < 7; I++) { + rarVM.setLowEndianValue(globalData, I * 4, StackFilter.getPrg() + .getInitR()[I]); + } + + // VM.SetLowEndianValue((uint + // *)&GlobalData[0x1c],StackFilter->BlockLength); + rarVM.setLowEndianValue(globalData, 0x1c, StackFilter.getBlockLength()); + // VM.SetLowEndianValue((uint *)&GlobalData[0x20],0); + rarVM.setLowEndianValue(globalData, 0x20, 0); + rarVM.setLowEndianValue(globalData, 0x24, 0); + rarVM.setLowEndianValue(globalData, 0x28, 0); + + // VM.SetLowEndianValue((uint + // *)&GlobalData[0x2c],StackFilter->ExecCount); + rarVM.setLowEndianValue(globalData, 0x2c, StackFilter.getExecCount()); + // memset(&GlobalData[0x30],0,16); + for (int i = 0; i < 16; i++) { + globalData.set(0x30 + i, Byte.valueOf((byte) (0))); + } + if ((firstByte & 8) != 0) // put data block passed as parameter if any + { + if (Inp.Overflow(3)) { + return (false); + } + int DataSize = RarVM.ReadData(Inp); + if (DataSize > RarVM.VM_GLOBALMEMSIZE - RarVM.VM_FIXEDGLOBALSIZE) { + return (false); + } + int CurSize = StackFilter.getPrg().getGlobalData().size(); + if (CurSize < DataSize + RarVM.VM_FIXEDGLOBALSIZE) { + // StackFilter->Prg.GlobalData.Add(DataSize+VM_FIXEDGLOBALSIZE-CurSize); + StackFilter.getPrg().getGlobalData().setSize( + DataSize + RarVM.VM_FIXEDGLOBALSIZE - CurSize); + } + int offset = RarVM.VM_FIXEDGLOBALSIZE; + globalData = StackFilter.getPrg().getGlobalData(); + for (int I = 0; I < DataSize; I++) { + if (Inp.Overflow(3)) { + return (false); + } + globalData.set(offset + I, Byte + .valueOf((byte) (Inp.fgetbits() >>> 8))); + Inp.faddbits(8); + } + } + return (true); + } + + private void ExecuteCode(VMPreparedProgram Prg) { + if (Prg.getGlobalData().size() > 0) { + // Prg->InitR[6]=int64to32(WrittenFileSize); + Prg.getInitR()[6] = (int) (writtenFileSize); + // rarVM.SetLowEndianValue((uint + // *)&Prg->GlobalData[0x24],int64to32(WrittenFileSize)); + rarVM.setLowEndianValue(Prg.getGlobalData(), 0x24, + (int) writtenFileSize); + // rarVM.SetLowEndianValue((uint + // *)&Prg->GlobalData[0x28],int64to32(WrittenFileSize>>32)); + rarVM.setLowEndianValue(Prg.getGlobalData(), 0x28, + (int) (writtenFileSize >>> 32)); + rarVM.execute(Prg); + } + } + + // Duplicate method + // private boolean ReadEndOfBlock() throws IOException, RarException + // { + // int BitField = getbits(); + // boolean NewTable, NewFile = false; + // if ((BitField & 0x8000) != 0) { + // NewTable = true; + // addbits(1); + // } else { + // NewFile = true; + // NewTable = (BitField & 0x4000) != 0; + // addbits(2); + // } + // tablesRead = !NewTable; + // return !(NewFile || NewTable && !readTables()); + // } + + public boolean isFileExtracted() { + return fileExtracted; + } + + public void setDestSize(long destSize) { + this.destUnpSize = destSize; + this.fileExtracted = false; + } + + public void setSuspended(boolean suspended) { + this.suspended = suspended; + } + + public int getChar() throws IOException, RarException { + if (inAddr > BitInput.MAX_SIZE - 30) { + unpReadBuf(); + } + return (inBuf[inAddr++] & 0xff); + } + + public int getPpmEscChar() { + return ppmEscChar; + } + + public void setPpmEscChar(int ppmEscChar) { + this.ppmEscChar = ppmEscChar; + } + + public void cleanUp() { + if (ppm != null) { + SubAllocator allocator = ppm.getSubAlloc(); + if (allocator != null) { + allocator.stopSubAllocator(); + } + } + } +} diff --git a/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unpack/Unpack15.java b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unpack/Unpack15.java new file mode 100755 index 0000000..2a7695d --- /dev/null +++ b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unpack/Unpack15.java @@ -0,0 +1,554 @@ +/* + * Copyright (c) 2007 innoSysTec (R) GmbH, Germany. All rights reserved. + * Original author: Edmund Wagner + * Creation date: 21.06.2007 + * + * Source: $HeadURL$ + * Last changed: $LastChangedDate$ + * + * the unrar licence applies to all junrar source and binary distributions + * you are not allowed to use this source to re-create the RAR compression algorithm + * + * Here some html entities which can be used for escaping javadoc tags: + * "&": "&" or "&" + * "<": "<" or "<" + * ">": ">" or ">" + * "@": "@" + */ +package org.fox.ttcomics2.junrar.unpack; + +import org.fox.ttcomics2.junrar.exception.RarException; +import org.fox.ttcomics2.junrar.unpack.decode.Compress; +import org.fox.ttcomics2.junrar.unpack.vm.BitInput; + +import java.io.IOException; +import java.util.Arrays; + + +public abstract class Unpack15 extends BitInput { + + private static final int STARTL1 = 2; + private static final int STARTL2 = 3; + private static final int STARTHF0 = 4; + private static final int STARTHF1 = 5; + private static final int STARTHF2 = 5; + private static final int STARTHF3 = 6; + private static final int STARTHF4 = 8; + static int ShortLen1[] = {1, 3, 4, 4, 5, 6, 7, 8, 8, 4, 4, 5, 6, 6, 4, 0}; + static int ShortXor1[] = {0, 0xa0, 0xd0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, + 0xff, 0xc0, 0x80, 0x90, 0x98, 0x9c, 0xb0}; + static int ShortLen2[] = {2, 3, 3, 3, 4, 4, 5, 6, 6, 4, 4, 5, 6, 6, 4, 0}; + static int ShortXor2[] = {0, 0x40, 0x60, 0xa0, 0xd0, 0xe0, 0xf0, 0xf8, + 0xfc, 0xc0, 0x80, 0x90, 0x98, 0x9c, 0xb0}; + private static int DecL1[] = {0x8000, 0xa000, 0xc000, 0xd000, 0xe000, + 0xea00, 0xee00, 0xf000, 0xf200, 0xf200, 0xffff}; + private static int PosL1[] = {0, 0, 0, 2, 3, 5, 7, 11, 16, 20, 24, 32, 32}; + private static int DecL2[] = {0xa000, 0xc000, 0xd000, 0xe000, 0xea00, + 0xee00, 0xf000, 0xf200, 0xf240, 0xffff}; + private static int PosL2[] = {0, 0, 0, 0, 5, 7, 9, 13, 18, 22, 26, 34, 36}; + private static int DecHf0[] = {0x8000, 0xc000, 0xe000, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xffff}; + private static int PosHf0[] = {0, 0, 0, 0, 0, 8, 16, 24, 33, 33, 33, 33, + 33}; + private static int DecHf1[] = {0x2000, 0xc000, 0xe000, 0xf000, 0xf200, + 0xf200, 0xf7e0, 0xffff}; + private static int PosHf1[] = {0, 0, 0, 0, 0, 0, 4, 44, 60, 76, 80, 80, + 127}; + private static int DecHf2[] = {0x1000, 0x2400, 0x8000, 0xc000, 0xfa00, + 0xffff, 0xffff, 0xffff}; + private static int PosHf2[] = {0, 0, 0, 0, 0, 0, 2, 7, 53, 117, 233, 0, 0}; + private static int DecHf3[] = {0x800, 0x2400, 0xee00, 0xfe80, 0xffff, + 0xffff, 0xffff}; + private static int PosHf3[] = {0, 0, 0, 0, 0, 0, 0, 2, 16, 218, 251, 0, 0}; + private static int DecHf4[] = {0xff00, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff}; + private static int PosHf4[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0}; + protected int readBorder; + protected boolean suspended; + protected boolean unpAllBuf; + protected ComprDataIO unpIO; + protected boolean unpSomeRead; + protected int readTop; + protected long destUnpSize; + protected byte[] window; + protected int[] oldDist = new int[4]; + protected int unpPtr, wrPtr; + protected int oldDistPtr; + protected int[] ChSet = new int[256], ChSetA = new int[256], + ChSetB = new int[256], ChSetC = new int[256]; + protected int[] Place = new int[256], PlaceA = new int[256], + PlaceB = new int[256], PlaceC = new int[256]; + protected int[] NToPl = new int[256], NToPlB = new int[256], + NToPlC = new int[256]; + protected int FlagBuf, AvrPlc, AvrPlcB, AvrLn1, AvrLn2, AvrLn3; + protected int Buf60, NumHuf, StMode, LCount, FlagsCnt; + protected int Nhfb, Nlzb, MaxDist3; + protected int lastDist, lastLength; + + protected abstract void unpInitData(boolean solid); + + protected void unpack15(boolean solid) throws IOException, RarException { + if (suspended) { + unpPtr = wrPtr; + } else { + unpInitData(solid); + oldUnpInitData(solid); + unpReadBuf(); + if (!solid) { + initHuff(); + unpPtr = 0; + } else { + unpPtr = wrPtr; + } + --destUnpSize; + } + if (destUnpSize >= 0) { + getFlagsBuf(); + FlagsCnt = 8; + } + + while (destUnpSize >= 0) { + unpPtr &= Compress.MAXWINMASK; + + if (inAddr > readTop - 30 && !unpReadBuf()) { + break; + } + if (((wrPtr - unpPtr) & Compress.MAXWINMASK) < 270 + && wrPtr != unpPtr) { + oldUnpWriteBuf(); + if (suspended) { + return; + } + } + if (StMode != 0) { + huffDecode(); + continue; + } + + if (--FlagsCnt < 0) { + getFlagsBuf(); + FlagsCnt = 7; + } + + if ((FlagBuf & 0x80) != 0) { + FlagBuf <<= 1; + if (Nlzb > Nhfb) { + longLZ(); + } else { + huffDecode(); + } + } else { + FlagBuf <<= 1; + if (--FlagsCnt < 0) { + getFlagsBuf(); + FlagsCnt = 7; + } + if ((FlagBuf & 0x80) != 0) { + FlagBuf <<= 1; + if (Nlzb > Nhfb) { + huffDecode(); + } else { + longLZ(); + } + } else { + FlagBuf <<= 1; + shortLZ(); + } + } + } + oldUnpWriteBuf(); + } + + + protected boolean unpReadBuf() throws IOException, RarException { + int dataSize = readTop - inAddr; + if (dataSize < 0) { + return (false); + } + if (inAddr > BitInput.MAX_SIZE / 2) { + if (dataSize > 0) { + //memmove(InBuf,InBuf+InAddr,DataSize); +// for (int i = 0; i < dataSize; i++) { +// inBuf[i] = inBuf[inAddr + i]; +// } + System.arraycopy(inBuf, inAddr, inBuf, 0, dataSize); + } + inAddr = 0; + readTop = dataSize; + } else { + dataSize = readTop; + } + //int readCode=UnpIO->UnpRead(InBuf+DataSize,(BitInput::MAX_SIZE-DataSize)&~0xf); + int readCode = unpIO.unpRead(inBuf, dataSize, (BitInput.MAX_SIZE - dataSize) & ~0xf); + if (readCode > 0) { + readTop += readCode; + } + readBorder = readTop - 30; + return (readCode != -1); + } + + private int getShortLen1(int pos) { + return pos == 1 ? Buf60 + 3 : ShortLen1[pos]; + } + + private int getShortLen2(int pos) { + return pos == 3 ? Buf60 + 3 : ShortLen2[pos]; + } + + protected void shortLZ() { + int Length, SaveLength; + int LastDistance; + int Distance; + int DistancePlace; + NumHuf = 0; + + int BitField = fgetbits(); + if (LCount == 2) { + faddbits(1); + if (BitField >= 0x8000) { + oldCopyString(lastDist, lastLength); + return; + } + BitField <<= 1; + LCount = 0; + } + BitField >>>= 8; + if (AvrLn1 < 37) { + for (Length = 0; ; Length++) { + if (((BitField ^ ShortXor1[Length]) & (~(0xff >>> getShortLen1(Length)))) == 0) { + break; + } + } + faddbits(getShortLen1(Length)); + } else { + for (Length = 0; ; Length++) { + if (((BitField ^ ShortXor2[Length]) & (~(0xff >> getShortLen2(Length)))) == 0) { + break; + } + } + faddbits(getShortLen2(Length)); + } + + if (Length >= 9) { + if (Length == 9) { + LCount++; + oldCopyString(lastDist, lastLength); + return; + } + if (Length == 14) { + LCount = 0; + Length = decodeNum(fgetbits(), STARTL2, DecL2, PosL2) + 5; + Distance = (fgetbits() >> 1) | 0x8000; + faddbits(15); + lastLength = Length; + lastDist = Distance; + oldCopyString(Distance, Length); + return; + } + + LCount = 0; + SaveLength = Length; + Distance = oldDist[(oldDistPtr - (Length - 9)) & 3]; + Length = decodeNum(fgetbits(), STARTL1, DecL1, PosL1) + 2; + if (Length == 0x101 && SaveLength == 10) { + Buf60 ^= 1; + return; + } + if (Distance > 256) + Length++; + if (Distance >= MaxDist3) + Length++; + + oldDist[oldDistPtr++] = Distance; + oldDistPtr = oldDistPtr & 3; + lastLength = Length; + lastDist = Distance; + oldCopyString(Distance, Length); + return; + } + + LCount = 0; + AvrLn1 += Length; + AvrLn1 -= AvrLn1 >> 4; + + DistancePlace = decodeNum(fgetbits(), STARTHF2, DecHf2, PosHf2) & 0xff; + Distance = ChSetA[DistancePlace]; + if (--DistancePlace != -1) { + PlaceA[Distance]--; + LastDistance = ChSetA[DistancePlace]; + PlaceA[LastDistance]++; + ChSetA[DistancePlace + 1] = LastDistance; + ChSetA[DistancePlace] = Distance; + } + Length += 2; + oldDist[oldDistPtr++] = ++Distance; + oldDistPtr = oldDistPtr & 3; + lastLength = Length; + lastDist = Distance; + oldCopyString(Distance, Length); + } + + protected void longLZ() { + int Length; + int Distance; + int DistancePlace, NewDistancePlace; + int OldAvr2, OldAvr3; + + NumHuf = 0; + Nlzb += 16; + if (Nlzb > 0xff) { + Nlzb = 0x90; + Nhfb >>>= 1; + } + OldAvr2 = AvrLn2; + + int BitField = fgetbits(); + if (AvrLn2 >= 122) { + Length = decodeNum(BitField, STARTL2, DecL2, PosL2); + } else { + if (AvrLn2 >= 64) { + Length = decodeNum(BitField, STARTL1, DecL1, PosL1); + } else { + if (BitField < 0x100) { + Length = BitField; + faddbits(16); + } else { + for (Length = 0; ((BitField << Length) & 0x8000) == 0; Length++) { + } + faddbits(Length + 1); + } + } + } + AvrLn2 += Length; + AvrLn2 -= AvrLn2 >>> 5; + + BitField = fgetbits(); + if (AvrPlcB > 0x28ff) { + DistancePlace = decodeNum(BitField, STARTHF2, DecHf2, PosHf2); + } else { + if (AvrPlcB > 0x6ff) { + DistancePlace = decodeNum(BitField, STARTHF1, DecHf1, PosHf1); + } else { + DistancePlace = decodeNum(BitField, STARTHF0, DecHf0, PosHf0); + } + } + AvrPlcB += DistancePlace; + AvrPlcB -= AvrPlcB >> 8; + while (true) { + Distance = ChSetB[DistancePlace & 0xff]; + NewDistancePlace = NToPlB[Distance++ & 0xff]++; + if ((Distance & 0xff) == 0) { + corrHuff(ChSetB, NToPlB); + } else { + break; + } + } + + ChSetB[DistancePlace] = ChSetB[NewDistancePlace]; + ChSetB[NewDistancePlace] = Distance; + + Distance = ((Distance & 0xff00) | (fgetbits() >>> 8)) >>> 1; + faddbits(7); + + OldAvr3 = AvrLn3; + if (Length != 1 && Length != 4) { + if (Length == 0 && Distance <= MaxDist3) { + AvrLn3++; + AvrLn3 -= AvrLn3 >> 8; + } else { + if (AvrLn3 > 0) { + AvrLn3--; + } + } + } + Length += 3; + if (Distance >= MaxDist3) { + Length++; + } + if (Distance <= 256) { + Length += 8; + } + if (OldAvr3 > 0xb0 || AvrPlc >= 0x2a00 && OldAvr2 < 0x40) { + MaxDist3 = 0x7f00; + } else { + MaxDist3 = 0x2001; + } + oldDist[oldDistPtr++] = Distance; + oldDistPtr = oldDistPtr & 3; + lastLength = Length; + lastDist = Distance; + oldCopyString(Distance, Length); + } + + protected void huffDecode() { + int CurByte, NewBytePlace; + int Length; + int Distance; + int BytePlace; + + int BitField = fgetbits(); + + if (AvrPlc > 0x75ff) { + BytePlace = decodeNum(BitField, STARTHF4, DecHf4, PosHf4); + } else { + if (AvrPlc > 0x5dff) { + BytePlace = decodeNum(BitField, STARTHF3, DecHf3, PosHf3); + } else { + if (AvrPlc > 0x35ff) { + BytePlace = decodeNum(BitField, STARTHF2, DecHf2, PosHf2); + } else { + if (AvrPlc > 0x0dff) { + BytePlace = decodeNum(BitField, STARTHF1, DecHf1, + PosHf1); + } else { + BytePlace = decodeNum(BitField, STARTHF0, DecHf0, + PosHf0); + } + } + } + } + BytePlace &= 0xff; + if (StMode != 0) { + if (BytePlace == 0 && BitField > 0xfff) { + BytePlace = 0x100; + } + if (--BytePlace == -1) { + BitField = fgetbits(); + faddbits(1); + if ((BitField & 0x8000) != 0) { + NumHuf = StMode = 0; + return; + } else { + Length = (BitField & 0x4000) != 0 ? 4 : 3; + faddbits(1); + Distance = decodeNum(fgetbits(), STARTHF2, DecHf2, PosHf2); + Distance = (Distance << 5) | (fgetbits() >>> 11); + faddbits(5); + oldCopyString(Distance, Length); + return; + } + } + } else { + if (NumHuf++ >= 16 && FlagsCnt == 0) { + StMode = 1; + } + } + AvrPlc += BytePlace; + AvrPlc -= AvrPlc >>> 8; + Nhfb += 16; + if (Nhfb > 0xff) { + Nhfb = 0x90; + Nlzb >>>= 1; + } + + window[unpPtr++] = (byte) (ChSet[BytePlace] >>> 8); + --destUnpSize; + + while (true) { + CurByte = ChSet[BytePlace]; + NewBytePlace = NToPl[CurByte++ & 0xff]++; + if ((CurByte & 0xff) > 0xa1) { + corrHuff(ChSet, NToPl); + } else { + break; + } + } + + ChSet[BytePlace] = ChSet[NewBytePlace]; + ChSet[NewBytePlace] = CurByte; + } + + protected void getFlagsBuf() { + int Flags, NewFlagsPlace; + int FlagsPlace = decodeNum(fgetbits(), STARTHF2, DecHf2, PosHf2); + + while (true) { + Flags = ChSetC[FlagsPlace]; + FlagBuf = Flags >>> 8; + NewFlagsPlace = NToPlC[Flags++ & 0xff]++; + if ((Flags & 0xff) != 0) { + break; + } + corrHuff(ChSetC, NToPlC); + } + + ChSetC[FlagsPlace] = ChSetC[NewFlagsPlace]; + ChSetC[NewFlagsPlace] = Flags; + } + + protected void oldUnpInitData(boolean Solid) { + if (!Solid) { + AvrPlcB = AvrLn1 = AvrLn2 = AvrLn3 = NumHuf = Buf60 = 0; + AvrPlc = 0x3500; + MaxDist3 = 0x2001; + Nhfb = Nlzb = 0x80; + } + FlagsCnt = 0; + FlagBuf = 0; + StMode = 0; + LCount = 0; + readTop = 0; + } + + protected void initHuff() { + for (int I = 0; I < 256; I++) { + Place[I] = PlaceA[I] = PlaceB[I] = I; + PlaceC[I] = (~I + 1) & 0xff; + ChSet[I] = ChSetB[I] = I << 8; + ChSetA[I] = I; + ChSetC[I] = ((~I + 1) & 0xff) << 8; + } + + Arrays.fill(NToPl, 0);// memset(NToPl,0,sizeof(NToPl)); + Arrays.fill(NToPlB, 0); // memset(NToPlB,0,sizeof(NToPlB)); + Arrays.fill(NToPlC, 0); // memset(NToPlC,0,sizeof(NToPlC)); + corrHuff(ChSetB, NToPlB); + } + + protected void corrHuff(int[] CharSet, int[] NumToPlace) { + int I, J, pos = 0; + for (I = 7; I >= 0; I--) { + for (J = 0; J < 32; J++, pos++) { + CharSet[pos] = ((CharSet[pos] & ~0xff) | I);// *CharSet=(*CharSet + // & ~0xff) | I; + } + } + Arrays.fill(NumToPlace, 0);// memset(NumToPlace,0,sizeof(NToPl)); + for (I = 6; I >= 0; I--) { + NumToPlace[I] = (7 - I) * 32; + } + } + + protected void oldCopyString(int Distance, int Length) { + destUnpSize -= Length; + while ((Length--) != 0) { + window[unpPtr] = window[(unpPtr - Distance) & Compress.MAXWINMASK]; + unpPtr = (unpPtr + 1) & Compress.MAXWINMASK; + } + } + + protected int decodeNum(int Num, int StartPos, int[] DecTab, int[] PosTab) { + int I; + for (Num &= 0xfff0, I = 0; DecTab[I] <= Num; I++) { + StartPos++; + } + faddbits(StartPos); + return (((Num - (I != 0 ? DecTab[I - 1] : 0)) >>> (16 - StartPos)) + PosTab[StartPos]); + } + + protected void oldUnpWriteBuf() throws IOException { + if (unpPtr != wrPtr) { + unpSomeRead = true; + } + if (unpPtr < wrPtr) { + unpIO.unpWrite(window, wrPtr, -wrPtr & Compress.MAXWINMASK); + unpIO.unpWrite(window, 0, unpPtr); + unpAllBuf = true; + } else { + unpIO.unpWrite(window, wrPtr, unpPtr - wrPtr); + } + wrPtr = unpPtr; + } + + +} diff --git a/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unpack/Unpack20.java b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unpack/Unpack20.java new file mode 100755 index 0000000..971a437 --- /dev/null +++ b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unpack/Unpack20.java @@ -0,0 +1,567 @@ +/* + * Copyright (c) 2007 innoSysTec (R) GmbH, Germany. All rights reserved. + * Original author: Edmund Wagner + * Creation date: 21.06.2007 + * + * Source: $HeadURL$ + * Last changed: $LastChangedDate$ + * + * the unrar licence applies to all junrar source and binary distributions + * you are not allowed to use this source to re-create the RAR compression algorithm + * + * Here some html entities which can be used for escaping javadoc tags: + * "&": "&" or "&" + * "<": "<" or "<" + * ">": ">" or ">" + * "@": "@" + */ +package org.fox.ttcomics2.junrar.unpack; + +import org.fox.ttcomics2.junrar.exception.RarException; +import org.fox.ttcomics2.junrar.unpack.decode.AudioVariables; +import org.fox.ttcomics2.junrar.unpack.decode.BitDecode; +import org.fox.ttcomics2.junrar.unpack.decode.Compress; +import org.fox.ttcomics2.junrar.unpack.decode.Decode; +import org.fox.ttcomics2.junrar.unpack.decode.DistDecode; +import org.fox.ttcomics2.junrar.unpack.decode.LitDecode; +import org.fox.ttcomics2.junrar.unpack.decode.LowDistDecode; +import org.fox.ttcomics2.junrar.unpack.decode.MultDecode; +import org.fox.ttcomics2.junrar.unpack.decode.RepDecode; + +import java.io.IOException; +import java.util.Arrays; + + +public abstract class Unpack20 extends Unpack15 { + + public static final int[] LDecode = {0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, + 14, 16, 20, 24, 28, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, + 224}; + public static final byte[] LBits = {0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, + 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5}; + public static final int[] DDecode = {0, 1, 2, 3, 4, 6, 8, 12, 16, 24, 32, + 48, 64, 96, 128, 192, 256, 384, 512, 768, 1024, 1536, 2048, 3072, + 4096, 6144, 8192, 12288, 16384, 24576, 32768, 49152, 65536, 98304, + 131072, 196608, 262144, 327680, 393216, 458752, 524288, 589824, + 655360, 720896, 786432, 851968, 917504, 983040}; + public static final int[] DBits = {0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, + 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, + 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16}; + public static final int[] SDDecode = {0, 4, 8, 16, 32, 64, 128, 192}; + public static final int[] SDBits = {2, 2, 3, 4, 5, 6, 6, 6}; + protected MultDecode[] MD = new MultDecode[4]; + protected byte[] UnpOldTable20 = new byte[Compress.MC20 * 4]; + protected int UnpAudioBlock, UnpChannels, UnpCurChannel, UnpChannelDelta; + protected AudioVariables[] AudV = new AudioVariables[4]; + protected LitDecode LD = new LitDecode(); + protected DistDecode DD = new DistDecode(); + protected LowDistDecode LDD = new LowDistDecode(); + protected RepDecode RD = new RepDecode(); + protected BitDecode BD = new BitDecode(); + + protected void unpack20(boolean solid) throws IOException, RarException { + + int Bits; + + if (suspended) { + unpPtr = wrPtr; + } else { + unpInitData(solid); + if (!unpReadBuf()) { + return; + } + if (!solid) { + if (!ReadTables20()) { + return; + } + } + --destUnpSize; + } + + while (destUnpSize >= 0) { + unpPtr &= Compress.MAXWINMASK; + + if (inAddr > readTop - 30) + if (!unpReadBuf()) + break; + if (((wrPtr - unpPtr) & Compress.MAXWINMASK) < 270 + && wrPtr != unpPtr) { + oldUnpWriteBuf(); + if (suspended) + return; + } + if (UnpAudioBlock != 0) { + int AudioNumber = decodeNumber(MD[UnpCurChannel]); + + if (AudioNumber == 256) { + if (!ReadTables20()) + break; + continue; + } + window[unpPtr++] = DecodeAudio(AudioNumber); + if (++UnpCurChannel == UnpChannels) + UnpCurChannel = 0; + --destUnpSize; + continue; + } + + int Number = decodeNumber(LD); + if (Number < 256) { + window[unpPtr++] = (byte) Number; + --destUnpSize; + continue; + } + if (Number > 269) { + int Length = LDecode[Number -= 270] + 3; + if ((Bits = LBits[Number]) > 0) { + Length += getbits() >>> (16 - Bits); + addbits(Bits); + } + + int DistNumber = decodeNumber(DD); + int Distance = DDecode[DistNumber] + 1; + if ((Bits = DBits[DistNumber]) > 0) { + Distance += getbits() >>> (16 - Bits); + addbits(Bits); + } + + if (Distance >= 0x2000) { + Length++; + if (Distance >= 0x40000L) + Length++; + } + + CopyString20(Length, Distance); + continue; + } + if (Number == 269) { + if (!ReadTables20()) + break; + continue; + } + if (Number == 256) { + CopyString20(lastLength, lastDist); + continue; + } + if (Number < 261) { + int Distance = oldDist[(oldDistPtr - (Number - 256)) & 3]; + int LengthNumber = decodeNumber(RD); + int Length = LDecode[LengthNumber] + 2; + if ((Bits = LBits[LengthNumber]) > 0) { + Length += getbits() >>> (16 - Bits); + addbits(Bits); + } + if (Distance >= 0x101) { + Length++; + if (Distance >= 0x2000) { + Length++; + if (Distance >= 0x40000) + Length++; + } + } + CopyString20(Length, Distance); + continue; + } + if (Number < 270) { + int Distance = SDDecode[Number -= 261] + 1; + if ((Bits = SDBits[Number]) > 0) { + Distance += getbits() >>> (16 - Bits); + addbits(Bits); + } + CopyString20(2, Distance); + continue; + } + } + ReadLastTables(); + oldUnpWriteBuf(); + + } + + protected void CopyString20(int Length, int Distance) { + lastDist = oldDist[oldDistPtr++ & 3] = Distance; + lastLength = Length; + destUnpSize -= Length; + + int DestPtr = unpPtr - Distance; + if (DestPtr < Compress.MAXWINSIZE - 300 + && unpPtr < Compress.MAXWINSIZE - 300) { + window[unpPtr++] = window[DestPtr++]; + window[unpPtr++] = window[DestPtr++]; + while (Length > 2) { + Length--; + window[unpPtr++] = window[DestPtr++]; + } + } else { + while ((Length--) != 0) { + window[unpPtr] = window[DestPtr++ & Compress.MAXWINMASK]; + unpPtr = (unpPtr + 1) & Compress.MAXWINMASK; + } + } + } + + protected void makeDecodeTables(byte[] lenTab, int offset, Decode dec, + int size) { + int[] lenCount = new int[16]; + int[] tmpPos = new int[16]; + int i; + long M, N; + + Arrays.fill(lenCount, 0);// memset(LenCount,0,sizeof(LenCount)); + + Arrays.fill(dec.getDecodeNum(), 0);// memset(Dec->DecodeNum,0,Size*sizeof(*Dec->DecodeNum)); + + for (i = 0; i < size; i++) { + lenCount[lenTab[offset + i] & 0xF]++; + } + lenCount[0] = 0; + for (tmpPos[0] = 0, dec.getDecodePos()[0] = 0, dec.getDecodeLen()[0] = 0, N = 0, i = 1; i < 16; i++) { + N = 2 * (N + lenCount[i]); + M = N << (15 - i); + if (M > 0xFFFF) { + M = 0xFFFF; + } + dec.getDecodeLen()[i] = (int) M; + tmpPos[i] = dec.getDecodePos()[i] = dec.getDecodePos()[i - 1] + + lenCount[i - 1]; + } + + for (i = 0; i < size; i++) { + if (lenTab[offset + i] != 0) { + dec.getDecodeNum()[tmpPos[lenTab[offset + i] & 0xF]++] = i; + } + } + dec.setMaxNum(size); + } + + protected int decodeNumber(Decode dec) { + int bits; + long bitField = getbits() & 0xfffe; +// if (bitField < dec.getDecodeLen()[8]) { +// if (bitField < dec.getDecodeLen()[4]) { +// if (bitField < dec.getDecodeLen()[2]) { +// if (bitField < dec.getDecodeLen()[1]) { +// bits = 1; +// } else { +// bits = 2; +// } +// } else { +// if (bitField < dec.getDecodeLen()[3]) { +// bits = 3; +// } else { +// bits = 4; +// } +// } +// } else { +// if (bitField < dec.getDecodeLen()[6]) { +// if (bitField < dec.getDecodeLen()[5]) +// bits = 5; +// else +// bits = 6; +// } else { +// if (bitField < dec.getDecodeLen()[7]) { +// bits = 7; +// } else { +// bits = 8; +// } +// } +// } +// } else { +// if (bitField < dec.getDecodeLen()[12]) { +// if (bitField < dec.getDecodeLen()[10]) +// if (bitField < dec.getDecodeLen()[9]) +// bits = 9; +// else +// bits = 10; +// else if (bitField < dec.getDecodeLen()[11]) +// bits = 11; +// else +// bits = 12; +// } else { +// if (bitField < dec.getDecodeLen()[14]) { +// if (bitField < dec.getDecodeLen()[13]) { +// bits = 13; +// } else { +// bits = 14; +// } +// } else { +// bits = 15; +// } +// } +// } +// addbits(bits); +// int N = dec.getDecodePos()[bits] +// + (((int) bitField - dec.getDecodeLen()[bits - 1]) >>> (16 - bits)); +// if (N >= dec.getMaxNum()) { +// N = 0; +// } +// return (dec.getDecodeNum()[N]); + int[] decodeLen = dec.getDecodeLen(); + if (bitField < decodeLen[8]) { + if (bitField < decodeLen[4]) { + if (bitField < decodeLen[2]) { + if (bitField < decodeLen[1]) { + bits = 1; + } else { + bits = 2; + } + } else { + if (bitField < decodeLen[3]) { + bits = 3; + } else { + bits = 4; + } + } + } else { + if (bitField < decodeLen[6]) { + if (bitField < decodeLen[5]) + bits = 5; + else + bits = 6; + } else { + if (bitField < decodeLen[7]) { + bits = 7; + } else { + bits = 8; + } + } + } + } else { + if (bitField < decodeLen[12]) { + if (bitField < decodeLen[10]) + if (bitField < decodeLen[9]) + bits = 9; + else + bits = 10; + else if (bitField < decodeLen[11]) + bits = 11; + else + bits = 12; + } else { + if (bitField < decodeLen[14]) { + if (bitField < decodeLen[13]) { + bits = 13; + } else { + bits = 14; + } + } else { + bits = 15; + } + } + } + addbits(bits); + int N = dec.getDecodePos()[bits] + + (((int) bitField - decodeLen[bits - 1]) >>> (16 - bits)); + if (N >= dec.getMaxNum()) { + N = 0; + } + return (dec.getDecodeNum()[N]); + } + + protected boolean ReadTables20() throws IOException, RarException { + byte[] BitLength = new byte[Compress.BC20]; + byte[] Table = new byte[Compress.MC20 * 4]; + int TableSize, N, I; + if (inAddr > readTop - 25) { + if (!unpReadBuf()) { + return (false); + } + } + int BitField = getbits(); + UnpAudioBlock = (BitField & 0x8000); + + if (0 == (BitField & 0x4000)) { + // memset(UnpOldTable20,0,sizeof(UnpOldTable20)); + Arrays.fill(UnpOldTable20, (byte) 0); + } + addbits(2); + + if (UnpAudioBlock != 0) { + UnpChannels = ((BitField >>> 12) & 3) + 1; + if (UnpCurChannel >= UnpChannels) { + UnpCurChannel = 0; + } + addbits(2); + TableSize = Compress.MC20 * UnpChannels; + } else { + TableSize = Compress.NC20 + Compress.DC20 + Compress.RC20; + } + for (I = 0; I < Compress.BC20; I++) { + BitLength[I] = (byte) (getbits() >>> 12); + addbits(4); + } + makeDecodeTables(BitLength, 0, BD, Compress.BC20); + I = 0; + while (I < TableSize) { + if (inAddr > readTop - 5) { + if (!unpReadBuf()) { + return (false); + } + } + int Number = decodeNumber(BD); + if (Number < 16) { + Table[I] = (byte) ((Number + UnpOldTable20[I]) & 0xf); + I++; + } else if (Number == 16) { + N = (getbits() >>> 14) + 3; + addbits(2); + while (N-- > 0 && I < TableSize) { + Table[I] = Table[I - 1]; + I++; + } + } else { + if (Number == 17) { + N = (getbits() >>> 13) + 3; + addbits(3); + } else { + N = (getbits() >>> 9) + 11; + addbits(7); + } + while (N-- > 0 && I < TableSize) + Table[I++] = 0; + } + } + if (inAddr > readTop) { + return (true); + } + if (UnpAudioBlock != 0) + for (I = 0; I < UnpChannels; I++) + makeDecodeTables(Table, I * Compress.MC20, MD[I], Compress.MC20); + else { + makeDecodeTables(Table, 0, LD, Compress.NC20); + makeDecodeTables(Table, Compress.NC20, DD, Compress.DC20); + makeDecodeTables(Table, Compress.NC20 + Compress.DC20, RD, + Compress.RC20); + } + // memcpy(UnpOldTable20,Table,sizeof(UnpOldTable20)); + for (int i = 0; i < UnpOldTable20.length; i++) { + UnpOldTable20[i] = Table[i]; + } + return (true); + } + + protected void unpInitData20(boolean Solid) { + if (!Solid) { + UnpChannelDelta = UnpCurChannel = 0; + UnpChannels = 1; + // memset(AudV,0,sizeof(AudV)); + Arrays.fill(AudV, new AudioVariables()); + // memset(UnpOldTable20,0,sizeof(UnpOldTable20)); + Arrays.fill(UnpOldTable20, (byte) 0); + } + } + + protected void ReadLastTables() throws IOException, RarException { + if (readTop >= inAddr + 5) { + if (UnpAudioBlock != 0) { + if (decodeNumber(MD[UnpCurChannel]) == 256) { + ReadTables20(); + } + } else { + if (decodeNumber(LD) == 269) { + ReadTables20(); + } + } + } + } + + protected byte DecodeAudio(int Delta) { + AudioVariables v = AudV[UnpCurChannel]; + v.setByteCount(v.getByteCount() + 1); + v.setD4(v.getD3()); + v.setD3(v.getD2());// ->D3=V->D2; + v.setD2(v.getLastDelta() - v.getD1());// ->D2=V->LastDelta-V->D1; + v.setD1(v.getLastDelta());// V->D1=V->LastDelta; + // int PCh=8*V->LastChar+V->K1*V->D1 +V->K2*V->D2 +V->K3*V->D3 + // +V->K4*V->D4+ V->K5*UnpChannelDelta; + int PCh = 8 * v.getLastChar() + v.getK1() * v.getD1(); + PCh += v.getK2() * v.getD2() + v.getK3() * v.getD3(); + PCh += v.getK4() * v.getD4() + v.getK5() * UnpChannelDelta; + PCh = (PCh >>> 3) & 0xFF; + + int Ch = PCh - Delta; + + int D = ((byte) Delta) << 3; + + v.getDif()[0] += Math.abs(D);// V->Dif[0]+=abs(D); + v.getDif()[1] += Math.abs(D - v.getD1());// V->Dif[1]+=abs(D-V->D1); + v.getDif()[2] += Math.abs(D + v.getD1());// V->Dif[2]+=abs(D+V->D1); + v.getDif()[3] += Math.abs(D - v.getD2());// V->Dif[3]+=abs(D-V->D2); + v.getDif()[4] += Math.abs(D + v.getD2());// V->Dif[4]+=abs(D+V->D2); + v.getDif()[5] += Math.abs(D - v.getD3());// V->Dif[5]+=abs(D-V->D3); + v.getDif()[6] += Math.abs(D + v.getD3());// V->Dif[6]+=abs(D+V->D3); + v.getDif()[7] += Math.abs(D - v.getD4());// V->Dif[7]+=abs(D-V->D4); + v.getDif()[8] += Math.abs(D + v.getD4());// V->Dif[8]+=abs(D+V->D4); + v.getDif()[9] += Math.abs(D - UnpChannelDelta);// V->Dif[9]+=abs(D-UnpChannelDelta); + v.getDif()[10] += Math.abs(D + UnpChannelDelta);// V->Dif[10]+=abs(D+UnpChannelDelta); + + v.setLastDelta((byte) (Ch - v.getLastChar())); + UnpChannelDelta = v.getLastDelta(); + v.setLastChar(Ch);// V->LastChar=Ch; + + if ((v.getByteCount() & 0x1F) == 0) { + int MinDif = v.getDif()[0], NumMinDif = 0; + v.getDif()[0] = 0;// ->Dif[0]=0; + for (int I = 1; I < v.getDif().length; I++) { + if (v.getDif()[I] < MinDif) { + MinDif = v.getDif()[I]; + NumMinDif = I; + } + v.getDif()[I] = 0; + } + switch (NumMinDif) { + case 1: + if (v.getK1() >= -16) { + v.setK1(v.getK1() - 1);// V->K1--; + } + break; + case 2: + if (v.getK1() < 16) { + v.setK1(v.getK1() + 1);// V->K1++; + } + break; + case 3: + if (v.getK2() >= -16) { + v.setK2(v.getK2() - 1);// V->K2--; + } + break; + case 4: + if (v.getK2() < 16) { + v.setK2(v.getK2() + 1);// V->K2++; + } + break; + case 5: + if (v.getK3() >= -16) { + v.setK3(v.getK3() - 1); + } + break; + case 6: + if (v.getK3() < 16) { + v.setK3(v.getK3() + 1); + } + break; + case 7: + if (v.getK4() >= -16) { + v.setK4(v.getK4() - 1); + } + break; + case 8: + if (v.getK4() < 16) { + v.setK4(v.getK4() + 1); + } + break; + case 9: + if (v.getK5() >= -16) { + v.setK5(v.getK5() - 1); + } + break; + case 10: + if (v.getK5() < 16) { + v.setK5(v.getK5() + 1); + } + break; + } + } + return ((byte) Ch); + } + +} diff --git a/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unpack/UnpackFilter.java b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unpack/UnpackFilter.java new file mode 100644 index 0000000..b9aae9a --- /dev/null +++ b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unpack/UnpackFilter.java @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2007 innoSysTec (R) GmbH, Germany. All rights reserved. + * Original author: Edmund Wagner + * Creation date: 01.06.2007 + * + * Source: $HeadURL$ + * Last changed: $LastChangedDate$ + * + * the unrar licence applies to all junrar source and binary distributions + * you are not allowed to use this source to re-create the RAR compression algorithm + * + * Here some html entities which can be used for escaping javadoc tags: + * "&": "&" or "&" + * "<": "<" or "<" + * ">": ">" or ">" + * "@": "@" + */ +package org.fox.ttcomics2.junrar.unpack; + +import org.fox.ttcomics2.junrar.unpack.vm.VMPreparedProgram; + +public class UnpackFilter { + + private int BlockStart; + + private int BlockLength; + + private int ExecCount; + + private boolean NextWindow; + + // position of parent filter in Filters array used as prototype for filter + // in PrgStack array. Not defined for filters in Filters array. + private int ParentFilter; + + private VMPreparedProgram Prg = new VMPreparedProgram(); + + public int getBlockLength() { + return BlockLength; + } + + public void setBlockLength(int blockLength) { + BlockLength = blockLength; + } + + public int getBlockStart() { + return BlockStart; + } + + public void setBlockStart(int blockStart) { + BlockStart = blockStart; + } + + public int getExecCount() { + return ExecCount; + } + + public void setExecCount(int execCount) { + ExecCount = execCount; + } + + public boolean isNextWindow() { + return NextWindow; + } + + public void setNextWindow(boolean nextWindow) { + NextWindow = nextWindow; + } + + public int getParentFilter() { + return ParentFilter; + } + + public void setParentFilter(int parentFilter) { + ParentFilter = parentFilter; + } + + public VMPreparedProgram getPrg() { + return Prg; + } + + public void setPrg(VMPreparedProgram prg) { + Prg = prg; + } + + +} diff --git a/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unpack/decode/AudioVariables.java b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unpack/decode/AudioVariables.java new file mode 100644 index 0000000..5128cd4 --- /dev/null +++ b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unpack/decode/AudioVariables.java @@ -0,0 +1,138 @@ +/* + * Copyright (c) 2007 innoSysTec (R) GmbH, Germany. All rights reserved. + * Original author: Edmund Wagner + * Creation date: 01.06.2007 + * + * Source: $HeadURL$ + * Last changed: $LastChangedDate$ + * + * the unrar licence applies to all junrar source and binary distributions + * you are not allowed to use this source to re-create the RAR compression algorithm + * + * Here some html entities which can be used for escaping javadoc tags: + * "&": "&" or "&" + * "<": "<" or "<" + * ">": ">" or ">" + * "@": "@" + */ +package org.fox.ttcomics2.junrar.unpack.decode; + +public class AudioVariables { + int k1, k2, k3, k4, k5; + + int d1, d2, d3, d4; + + int lastDelta; + + int dif[] = new int[11]; + + int byteCount; + + int lastChar; + + public int getByteCount() { + return byteCount; + } + + public void setByteCount(int byteCount) { + this.byteCount = byteCount; + } + + public int getD1() { + return d1; + } + + public void setD1(int d1) { + this.d1 = d1; + } + + public int getD2() { + return d2; + } + + public void setD2(int d2) { + this.d2 = d2; + } + + public int getD3() { + return d3; + } + + public void setD3(int d3) { + this.d3 = d3; + } + + public int getD4() { + return d4; + } + + public void setD4(int d4) { + this.d4 = d4; + } + + public int[] getDif() { + return dif; + } + + public void setDif(int[] dif) { + this.dif = dif; + } + + public int getK1() { + return k1; + } + + public void setK1(int k1) { + this.k1 = k1; + } + + public int getK2() { + return k2; + } + + public void setK2(int k2) { + this.k2 = k2; + } + + public int getK3() { + return k3; + } + + public void setK3(int k3) { + this.k3 = k3; + } + + public int getK4() { + return k4; + } + + public void setK4(int k4) { + this.k4 = k4; + } + + public int getK5() { + return k5; + } + + public void setK5(int k5) { + this.k5 = k5; + } + + public int getLastChar() { + return lastChar; + } + + public void setLastChar(int lastChar) { + this.lastChar = lastChar; + } + + public int getLastDelta() { + return lastDelta; + } + + public void setLastDelta(int lastDelta) { + this.lastDelta = lastDelta; + } + + +} diff --git a/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unpack/decode/BitDecode.java b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unpack/decode/BitDecode.java new file mode 100644 index 0000000..6128afe --- /dev/null +++ b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unpack/decode/BitDecode.java @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2007 innoSysTec (R) GmbH, Germany. All rights reserved. + * Original author: Edmund Wagner + * Creation date: 01.06.2007 + * + * Source: $HeadURL$ + * Last changed: $LastChangedDate$ + * + * the unrar licence applies to all junrar source and binary distributions + * you are not allowed to use this source to re-create the RAR compression algorithm + * + * Here some html entities which can be used for escaping javadoc tags: + * "&": "&" or "&" + * "<": "<" or "<" + * ">": ">" or ">" + * "@": "@" + */ +package org.fox.ttcomics2.junrar.unpack.decode; + +public class BitDecode extends Decode { + public BitDecode() { + decodeNum = new int[Compress.BC]; + } +} diff --git a/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unpack/decode/CodeType.java b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unpack/decode/CodeType.java new file mode 100644 index 0000000..4d6108f --- /dev/null +++ b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unpack/decode/CodeType.java @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2007 innoSysTec (R) GmbH, Germany. All rights reserved. + * Original author: Edmund Wagner + * Creation date: 01.06.2007 + * + * Source: $HeadURL$ + * Last changed: $LastChangedDate$ + * + * Here some html entities which can be used for escaping javadoc tags: + * "&": "&" or "&" + * "<": "<" or "<" + * ">": ">" or ">" + * "@": "@" + */ +package org.fox.ttcomics2.junrar.unpack.decode; + +public enum CodeType { + CODE_HUFFMAN, CODE_LZ, CODE_LZ2, CODE_REPEATLZ, CODE_CACHELZ, + CODE_STARTFILE, CODE_ENDFILE, CODE_VM, CODE_VMDATA +} diff --git a/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unpack/decode/Compress.java b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unpack/decode/Compress.java new file mode 100644 index 0000000..edb5c3e --- /dev/null +++ b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unpack/decode/Compress.java @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2007 innoSysTec (R) GmbH, Germany. All rights reserved. + * Original author: Edmund Wagner + * Creation date: 01.06.2007 + * + * Source: $HeadURL$ + * Last changed: $LastChangedDate$ + * + * the unrar licence applies to all junrar source and binary distributions + * you are not allowed to use this source to re-create the RAR compression algorithm + * + * Here some html entities which can be used for escaping javadoc tags: + * "&": "&" or "&" + * "<": "<" or "<" + * ">": ">" or ">" + * "@": "@" + */ +package org.fox.ttcomics2.junrar.unpack.decode; + +public class Compress { + public static final int CODEBUFSIZE = 0x4000; + public static final int MAXWINSIZE = 0x400000; + public static final int MAXWINMASK = (MAXWINSIZE - 1); + + public static final int LOW_DIST_REP_COUNT = 16; + + public static final int NC = 299; /* alphabet = {0, 1, 2, ..., NC - 1} */ + public static final int DC = 60; + public static final int LDC = 17; + public static final int RC = 28; + public static final int HUFF_TABLE_SIZE = (NC + DC + RC + LDC); + public static final int BC = 20; + + public static final int NC20 = 298; /* alphabet = {0, 1, 2, ..., NC - 1} */ + public static final int DC20 = 48; + public static final int RC20 = 28; + public static final int BC20 = 19; + public static final int MC20 = 257; +} diff --git a/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unpack/decode/Decode.java b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unpack/decode/Decode.java new file mode 100644 index 0000000..0580cb8 --- /dev/null +++ b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unpack/decode/Decode.java @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2007 innoSysTec (R) GmbH, Germany. All rights reserved. + * Original author: Edmund Wagner + * Creation date: 01.06.2007 + * + * Source: $HeadURL$ + * Last changed: $LastChangedDate$ + * + * the unrar licence applies to all junrar source and binary distributions + * you are not allowed to use this source to re-create the RAR compression algorithm + * + * Here some html entities which can be used for escaping javadoc tags: + * "&": "&" or "&" + * "<": "<" or "<" + * ">": ">" or ">" + * "@": "@" + */ +package org.fox.ttcomics2.junrar.unpack.decode; + +public class Decode { + private final int[] decodeLen = new int[16]; + private final int[] decodePos = new int[16]; + protected int[] decodeNum = new int[2]; + private int maxNum; + + public int[] getDecodeLen() { + return decodeLen; + } + + public int[] getDecodeNum() { + return decodeNum; + } + + public int[] getDecodePos() { + return decodePos; + } + + public int getMaxNum() { + return maxNum; + } + + public void setMaxNum(int maxNum) { + this.maxNum = maxNum; + } + +} diff --git a/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unpack/decode/DistDecode.java b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unpack/decode/DistDecode.java new file mode 100644 index 0000000..e4f29b9 --- /dev/null +++ b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unpack/decode/DistDecode.java @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2007 innoSysTec (R) GmbH, Germany. All rights reserved. + * Original author: Edmund Wagner + * Creation date: 01.06.2007 + * + * Source: $HeadURL$ + * Last changed: $LastChangedDate$ + * + * the unrar licence applies to all junrar source and binary distributions + * you are not allowed to use this source to re-create the RAR compression algorithm + * + * Here some html entities which can be used for escaping javadoc tags: + * "&": "&" or "&" + * "<": "<" or "<" + * ">": ">" or ">" + * "@": "@" + */ +package org.fox.ttcomics2.junrar.unpack.decode; + +public class DistDecode extends Decode { + + public DistDecode() { + decodeNum = new int[Compress.DC]; + } + +} diff --git a/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unpack/decode/FilterType.java b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unpack/decode/FilterType.java new file mode 100644 index 0000000..697de1b --- /dev/null +++ b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unpack/decode/FilterType.java @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2007 innoSysTec (R) GmbH, Germany. All rights reserved. + * Original author: Edmund Wagner + * Creation date: 01.06.2007 + * + * Source: $HeadURL$ + * Last changed: $LastChangedDate$ + * + * the unrar licence applies to all junrar source and binary distributions + * you are not allowed to use this source to re-create the RAR compression algorithm + * + * Here some html entities which can be used for escaping javadoc tags: + * "&": "&" or "&" + * "<": "<" or "<" + * ">": ">" or ">" + * "@": "@" + */ +package org.fox.ttcomics2.junrar.unpack.decode; + +public enum FilterType { + FILTER_NONE, FILTER_PPM /*dummy*/, FILTER_E8, FILTER_E8E9, + FILTER_UPCASETOLOW, FILTER_AUDIO, FILTER_RGB, FILTER_DELTA, + FILTER_ITANIUM, FILTER_E8E9V2 +} diff --git a/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unpack/decode/LitDecode.java b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unpack/decode/LitDecode.java new file mode 100644 index 0000000..6c6ce6e --- /dev/null +++ b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unpack/decode/LitDecode.java @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2007 innoSysTec (R) GmbH, Germany. All rights reserved. + * Original author: Edmund Wagner + * Creation date: 01.06.2007 + * + * Source: $HeadURL$ + * Last changed: $LastChangedDate$ + * + * the unrar licence applies to all junrar source and binary distributions + * you are not allowed to use this source to re-create the RAR compression algorithm + * + * Here some html entities which can be used for escaping javadoc tags: + * "&": "&" or "&" + * "<": "<" or "<" + * ">": ">" or ">" + * "@": "@" + */ +package org.fox.ttcomics2.junrar.unpack.decode; + +public class LitDecode extends Decode { + public LitDecode() { + decodeNum = new int[Compress.NC]; + } + +} diff --git a/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unpack/decode/LowDistDecode.java b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unpack/decode/LowDistDecode.java new file mode 100644 index 0000000..54c5aad --- /dev/null +++ b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unpack/decode/LowDistDecode.java @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2007 innoSysTec (R) GmbH, Germany. All rights reserved. + * Original author: Edmund Wagner + * Creation date: 01.06.2007 + * + * Source: $HeadURL$ + * Last changed: $LastChangedDate$ + * + * the unrar licence applies to all junrar source and binary distributions + * you are not allowed to use this source to re-create the RAR compression algorithm + * + * Here some html entities which can be used for escaping javadoc tags: + * "&": "&" or "&" + * "<": "<" or "<" + * ">": ">" or ">" + * "@": "@" + */ +package org.fox.ttcomics2.junrar.unpack.decode; + +public class LowDistDecode extends Decode { + + public LowDistDecode() { + decodeNum = new int[Compress.LDC]; + } + +} diff --git a/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unpack/decode/MultDecode.java b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unpack/decode/MultDecode.java new file mode 100644 index 0000000..c1206e9 --- /dev/null +++ b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unpack/decode/MultDecode.java @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2007 innoSysTec (R) GmbH, Germany. All rights reserved. + * Original author: Edmund Wagner + * Creation date: 01.06.2007 + * + * Source: $HeadURL$ + * Last changed: $LastChangedDate$ + * + * the unrar licence applies to all junrar source and binary distributions + * you are not allowed to use this source to re-create the RAR compression algorithm + * + * Here some html entities which can be used for escaping javadoc tags: + * "&": "&" or "&" + * "<": "<" or "<" + * ">": ">" or ">" + * "@": "@" + */ +package org.fox.ttcomics2.junrar.unpack.decode; + +public class MultDecode extends Decode { + + public MultDecode() { + decodeNum = new int[Compress.MC20]; + } + +} diff --git a/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unpack/decode/RepDecode.java b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unpack/decode/RepDecode.java new file mode 100644 index 0000000..14ddad7 --- /dev/null +++ b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unpack/decode/RepDecode.java @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2007 innoSysTec (R) GmbH, Germany. All rights reserved. + * Original author: Edmund Wagner + * Creation date: 01.06.2007 + * + * Source: $HeadURL$ + * Last changed: $LastChangedDate$ + * + * the unrar licence applies to all junrar source and binary distributions + * you are not allowed to use this source to re-create the RAR compression algorithm + * + * Here some html entities which can be used for escaping javadoc tags: + * "&": "&" or "&" + * "<": "<" or "<" + * ">": ">" or ">" + * "@": "@" + */ +package org.fox.ttcomics2.junrar.unpack.decode; + +public class RepDecode extends Decode { + public RepDecode() { + decodeNum = new int[Compress.RC]; + } + +} diff --git a/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unpack/ppm/AnalyzeHeapDump.java b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unpack/ppm/AnalyzeHeapDump.java new file mode 100644 index 0000000..9ba997d --- /dev/null +++ b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unpack/ppm/AnalyzeHeapDump.java @@ -0,0 +1,85 @@ +package org.fox.ttcomics2.junrar.unpack.ppm; + +import java.io.BufferedInputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; + +public class AnalyzeHeapDump { + + public AnalyzeHeapDump() { + } + + public static void main(String[] argv) { + File cfile = new File("P:\\test\\heapdumpc"); + File jfile = new File("P:\\test\\heapdumpj"); + if (!cfile.exists()) { + System.err.println("File not found: " + cfile.getAbsolutePath()); + return; + } + if (!jfile.exists()) { + System.err.println("File not found: " + jfile.getAbsolutePath()); + return; + } + long clen = cfile.length(); + long jlen = jfile.length(); + if (clen != jlen) { + System.out.println("File size mismatch"); + System.out.println("clen = " + clen); + System.out.println("jlen = " + jlen); + } + // Do byte comparison + long len = Math.min(clen, jlen); + InputStream cin = null; + InputStream jin = null; + int bufferLen = 256 * 1024; + try { + cin = new BufferedInputStream( + new FileInputStream(cfile), bufferLen); + jin = new BufferedInputStream( + new FileInputStream(jfile), bufferLen); + boolean matching = true; + boolean mismatchFound = false; + long startOff = 0L; + long off = 0L; + while (off < len) { + if (cin.read() != jin.read()) { + if (matching) { + startOff = off; + matching = false; + mismatchFound = true; + } + } else { // match + if (!matching) { + printMismatch(startOff, off); + matching = true; + } + } + off++; + } + if (!matching) { + printMismatch(startOff, off); + } + if (!mismatchFound) { + System.out.println("Files are identical"); + } + System.out.println("Done"); + } catch (IOException e) { + e.printStackTrace(); + } finally { + try { + cin.close(); + jin.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + + private static void printMismatch(long startOff, long bytesRead) { + System.out.println("Mismatch: off=" + startOff + + "(0x" + Long.toHexString(startOff) + + "), len=" + (bytesRead - startOff)); + } +} diff --git a/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unpack/ppm/BlockTypes.java b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unpack/ppm/BlockTypes.java new file mode 100644 index 0000000..67ee63d --- /dev/null +++ b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unpack/ppm/BlockTypes.java @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2007 innoSysTec (R) GmbH, Germany. All rights reserved. + * Original author: Edmund Wagner + * Creation date: 01.06.2007 + * + * Source: $HeadURL$ + * Last changed: $LastChangedDate$ + * + * the unrar licence applies to all junrar source and binary distributions + * you are not allowed to use this source to re-create the RAR compression algorithm + * + * Here some html entities which can be used for escaping javadoc tags: + * "&": "&" or "&" + * "<": "<" or "<" + * ">": ">" or ">" + * "@": "@" + */ +package org.fox.ttcomics2.junrar.unpack.ppm; + + +public enum BlockTypes { + BLOCK_LZ(0), BLOCK_PPM(1); + + private int blockType; + + BlockTypes(int blockType) { + this.blockType = blockType; + } + + public static BlockTypes findBlockType(int blockType) { + if (BLOCK_LZ.equals(blockType)) { + return BLOCK_LZ; + } + if (BLOCK_PPM.equals(blockType)) { + return BLOCK_PPM; + } + return null; + } + + public int getBlockType() { + return blockType; + } + + public boolean equals(int blockType) { + return this.blockType == blockType; + } +} diff --git a/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unpack/ppm/FreqData.java b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unpack/ppm/FreqData.java new file mode 100644 index 0000000..680eaa1 --- /dev/null +++ b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unpack/ppm/FreqData.java @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2007 innoSysTec (R) GmbH, Germany. All rights reserved. + * Original author: Edmund Wagner + * Creation date: 04.06.2007 + * + * Source: $HeadURL$ + * Last changed: $LastChangedDate$ + * + * the unrar licence applies to all junrar source and binary distributions + * you are not allowed to use this source to re-create the RAR compression algorithm + * + * Here some html entities which can be used for escaping javadoc tags: + * "&": "&" or "&" + * "<": "<" or "<" + * ">": ">" or ">" + * "@": "@" + */ +package org.fox.ttcomics2.junrar.unpack.ppm; + +import org.fox.ttcomics2.junrar.io.Raw; + +public class FreqData extends Pointer { + + public static final int size = 6; + +// struct FreqData +// { +// ushort SummFreq; +// STATE _PACK_ATTR * Stats; +// }; + + public FreqData(byte[] mem) { + super(mem); + } + + public FreqData init(byte[] mem) { + this.mem = mem; + pos = 0; + return this; + } + + public int getSummFreq() { + return Raw.readShortLittleEndian(mem, pos) & 0xffff; + } + + public void setSummFreq(int summFreq) { + Raw.writeShortLittleEndian(mem, pos, (short) summFreq); + } + + public void incSummFreq(int dSummFreq) { + Raw.incShortLittleEndian(mem, pos, dSummFreq); + } + + public int getStats() { + return Raw.readIntLittleEndian(mem, pos + 2); + } + + public void setStats(int state) { + Raw.writeIntLittleEndian(mem, pos + 2, state); + } + + public void setStats(State state) { + setStats(state.getAddress()); + } + + public String toString() { + StringBuilder buffer = new StringBuilder(); + buffer.append("FreqData["); + buffer.append("\n pos="); + buffer.append(pos); + buffer.append("\n size="); + buffer.append(size); + buffer.append("\n summFreq="); + buffer.append(getSummFreq()); + buffer.append("\n stats="); + buffer.append(getStats()); + buffer.append("\n]"); + return buffer.toString(); + } + +} diff --git a/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unpack/ppm/ModelPPM.java b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unpack/ppm/ModelPPM.java new file mode 100755 index 0000000..d627faf --- /dev/null +++ b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unpack/ppm/ModelPPM.java @@ -0,0 +1,637 @@ +/* + * Copyright (c) 2007 innoSysTec (R) GmbH, Germany. All rights reserved. + * Original author: Edmund Wagner + * Creation date: 31.05.2007 + * + * Source: $HeadURL$ + * Last changed: $LastChangedDate$ + * + * the unrar licence applies to all junrar source and binary distributions + * you are not allowed to use this source to re-create the RAR compression algorithm + * + * Here some html entities which can be used for escaping javadoc tags: + * "&": "&" or "&" + * "<": "<" or "<" + * ">": ">" or ">" + * "@": "@" + */ +package org.fox.ttcomics2.junrar.unpack.ppm; + +import org.fox.ttcomics2.junrar.exception.RarException; +import org.fox.ttcomics2.junrar.unpack.Unpack; + +import java.io.IOException; +import java.util.Arrays; + + +public class ModelPPM { + public static final int MAX_O = 64; /* maximum allowed model order */ + + public static final int INT_BITS = 7; + + public static final int PERIOD_BITS = 7; + + public static final int TOT_BITS = INT_BITS + PERIOD_BITS; + + public static final int INTERVAL = 1 << INT_BITS; + + public static final int BIN_SCALE = 1 << TOT_BITS; + + public static final int MAX_FREQ = 124; + private static int InitBinEsc[] = {0x3CDD, 0x1F3F, 0x59BF, 0x48F3, + 0x64A1, 0x5ABC, 0x6632, 0x6051}; + // Temp fields + private final State tempState1 = new State(null); + private final State tempState2 = new State(null); + private final State tempState3 = new State(null); + private final State tempState4 = new State(null); + private final StateRef tempStateRef1 = new StateRef(); + private final StateRef tempStateRef2 = new StateRef(); + private final PPMContext tempPPMContext1 = new PPMContext(null); + private final PPMContext tempPPMContext2 = new PPMContext(null); + private final PPMContext tempPPMContext3 = new PPMContext(null); + private final PPMContext tempPPMContext4 = new PPMContext(null); + private final int[] ps = new int[MAX_O]; + private SEE2Context[][] SEE2Cont = new SEE2Context[25][16]; + private SEE2Context dummySEE2Cont; + private PPMContext minContext, medContext, maxContext; + private State foundState; // found next state transition + private int numMasked, initEsc, orderFall, maxOrder, runLength, initRL; + private int[] charMask = new int[256]; + private int[] NS2Indx = new int[256]; + private int[] NS2BSIndx = new int[256]; + private int[] HB2Flag = new int[256]; + // byte EscCount, PrevSuccess, HiBitsFlag; + private int escCount, prevSuccess, hiBitsFlag; + private int[][] binSumm = new int[128][64]; // binary SEE-contexts + private RangeCoder coder = new RangeCoder(); + private SubAllocator subAlloc = new SubAllocator(); + + public ModelPPM() { + minContext = null; + maxContext = null; + medContext = null; + } + + public SubAllocator getSubAlloc() { + return subAlloc; + } + + private void restartModelRare() { + Arrays.fill(charMask, 0); + subAlloc.initSubAllocator(); + initRL = -(maxOrder < 12 ? maxOrder : 12) - 1; + int addr = subAlloc.allocContext(); + minContext.setAddress(addr); + maxContext.setAddress(addr); + minContext.setSuffix(0); + orderFall = maxOrder; + minContext.setNumStats(256); + minContext.getFreqData().setSummFreq(minContext.getNumStats() + 1); + + addr = subAlloc.allocUnits(256 / 2); + foundState.setAddress(addr); + minContext.getFreqData().setStats(addr); + + State state = new State(subAlloc.getHeap()); + addr = minContext.getFreqData().getStats(); + runLength = initRL; + prevSuccess = 0; + for (int i = 0; i < 256; i++) { + state.setAddress(addr + i * State.size); + state.setSymbol(i); + state.setFreq(1); + state.setSuccessor(0); + } + + for (int i = 0; i < 128; i++) { + for (int k = 0; k < 8; k++) { + for (int m = 0; m < 64; m += 8) { + binSumm[i][k + m] = BIN_SCALE - InitBinEsc[k] / (i + 2); + } + } + } + for (int i = 0; i < 25; i++) { + for (int k = 0; k < 16; k++) { + SEE2Cont[i][k].init(5 * i + 10); + } + } + } + + private void startModelRare(int MaxOrder) { + int i, k, m, Step; + escCount = 1; + this.maxOrder = MaxOrder; + restartModelRare(); + // Bug Fixed + NS2BSIndx[0] = 0; + NS2BSIndx[1] = 2; + for (int j = 0; j < 9; j++) { + NS2BSIndx[2 + j] = 4; + } + for (int j = 0; j < 256 - 11; j++) { + NS2BSIndx[11 + j] = 6; + } + for (i = 0; i < 3; i++) { + NS2Indx[i] = i; + } + for (m = i, k = 1, Step = 1; i < 256; i++) { + NS2Indx[i] = m; + if ((--k) == 0) { + k = ++Step; + m++; + } + } + for (int j = 0; j < 0x40; j++) { + HB2Flag[j] = 0; + } + for (int j = 0; j < 0x100 - 0x40; j++) { + HB2Flag[0x40 + j] = 0x08; + } + dummySEE2Cont.setShift(PERIOD_BITS); + + } + + private void clearMask() { + escCount = 1; + Arrays.fill(charMask, 0); + } + + public boolean decodeInit(Unpack unpackRead, int escChar/* ref */) + throws IOException, RarException { + + int MaxOrder = unpackRead.getChar() & 0xff; + boolean reset = ((MaxOrder & 0x20) != 0); + + int MaxMB = 0; + if (reset) { + MaxMB = unpackRead.getChar(); + } else { + if (subAlloc.GetAllocatedMemory() == 0) { + return (false); + } + } + if ((MaxOrder & 0x40) != 0) { + escChar = unpackRead.getChar(); + unpackRead.setPpmEscChar(escChar); + } + coder.initDecoder(unpackRead); + if (reset) { + MaxOrder = (MaxOrder & 0x1f) + 1; + if (MaxOrder > 16) { + MaxOrder = 16 + (MaxOrder - 16) * 3; + } + if (MaxOrder == 1) { + subAlloc.stopSubAllocator(); + return (false); + } + subAlloc.startSubAllocator(MaxMB + 1); + minContext = new PPMContext(getHeap()); + medContext = new PPMContext(getHeap()); + maxContext = new PPMContext(getHeap()); + foundState = new State(getHeap()); + dummySEE2Cont = new SEE2Context(); + for (int i = 0; i < 25; i++) { + for (int j = 0; j < 16; j++) { + SEE2Cont[i][j] = new SEE2Context(); + } + } + startModelRare(MaxOrder); + } + return (minContext.getAddress() != 0); + } + + public int decodeChar() throws IOException, RarException { + // Debug + //subAlloc.dumpHeap(); + + if (minContext.getAddress() <= subAlloc.getPText() + || minContext.getAddress() > subAlloc.getHeapEnd()) { + return (-1); + } + + if (minContext.getNumStats() != 1) { + if (minContext.getFreqData().getStats() <= subAlloc.getPText() + || minContext.getFreqData().getStats() > subAlloc.getHeapEnd()) { + return (-1); + } + if (!minContext.decodeSymbol1(this)) { + return (-1); + } + } else { + minContext.decodeBinSymbol(this); + } + coder.decode(); + while (foundState.getAddress() == 0) { + coder.ariDecNormalize(); + do { + orderFall++; + minContext.setAddress(minContext.getSuffix());// =MinContext->Suffix; + if (minContext.getAddress() <= subAlloc.getPText() + || minContext.getAddress() > subAlloc.getHeapEnd()) { + return (-1); + } + } while (minContext.getNumStats() == numMasked); + if (!minContext.decodeSymbol2(this)) { + return (-1); + } + coder.decode(); + } + int Symbol = foundState.getSymbol(); + if ((orderFall == 0) && foundState.getSuccessor() > subAlloc.getPText()) { + // MinContext=MaxContext=FoundState->Successor; + int addr = foundState.getSuccessor(); + minContext.setAddress(addr); + maxContext.setAddress(addr); + } else { + updateModel(); + //this.foundState.setAddress(foundState.getAddress());//TODO just 4 debugging + if (escCount == 0) { + clearMask(); + } + } + coder.ariDecNormalize();// ARI_DEC_NORMALIZE(Coder.code,Coder.low,Coder.range,Coder.UnpackRead); + return (Symbol); + } + + public SEE2Context[][] getSEE2Cont() { + return SEE2Cont; + } + + public SEE2Context getDummySEE2Cont() { + return dummySEE2Cont; + } + + public int getInitRL() { + return initRL; + } + + public int getEscCount() { + return escCount; + } + + public void setEscCount(int escCount) { + this.escCount = escCount & 0xff; + } + + public void incEscCount(int dEscCount) { + setEscCount(getEscCount() + dEscCount); + } + + public int[] getCharMask() { + return charMask; + } + + public int getNumMasked() { + return numMasked; + } + + public void setNumMasked(int numMasked) { + this.numMasked = numMasked; + } + + public int getInitEsc() { + return initEsc; + } + + public void setInitEsc(int initEsc) { + this.initEsc = initEsc; + } + + public int getRunLength() { + return runLength; + } + + public void setRunLength(int runLength) { + this.runLength = runLength; + } + + public void incRunLength(int dRunLength) { + setRunLength(getRunLength() + dRunLength); + } + + public int getPrevSuccess() { + return prevSuccess; + } + + public void setPrevSuccess(int prevSuccess) { + this.prevSuccess = prevSuccess & 0xff; + } + + public int getHiBitsFlag() { + return hiBitsFlag; + } + + public void setHiBitsFlag(int hiBitsFlag) { + this.hiBitsFlag = hiBitsFlag & 0xff; + } + + public int[][] getBinSumm() { + return binSumm; + } + + public RangeCoder getCoder() { + return coder; + } + + public int[] getHB2Flag() { + return HB2Flag; + } + + public int[] getNS2BSIndx() { + return NS2BSIndx; + } + + public int[] getNS2Indx() { + return NS2Indx; + } + + public State getFoundState() { + return foundState; + } + + public byte[] getHeap() { + return subAlloc.getHeap(); + } + + public int getOrderFall() { + return orderFall; + } + + private int /* ppmcontext ptr */createSuccessors(boolean Skip, + State p1 /* state ptr */) { + //State upState = tempState1.init(null); + StateRef upState = tempStateRef2; + State tempState = tempState1.init(getHeap()); + + // PPM_CONTEXT* pc=MinContext, * UpBranch=FoundState->Successor; + PPMContext pc = tempPPMContext1.init(getHeap()); + pc.setAddress(minContext.getAddress()); + PPMContext upBranch = tempPPMContext2.init(getHeap()); + upBranch.setAddress(foundState.getSuccessor()); + + // STATE * p, * ps[MAX_O], ** pps=ps; + State p = tempState2.init(getHeap()); + int pps = 0; + + boolean noLoop = false; + + if (!Skip) { + ps[pps++] = foundState.getAddress();// *pps++ = FoundState; + if (pc.getSuffix() == 0) { + noLoop = true; + } + } + if (!noLoop) { + boolean loopEntry = false; + if (p1.getAddress() != 0) { + p.setAddress(p1.getAddress()); + pc.setAddress(pc.getSuffix());// =pc->Suffix; + loopEntry = true; + } + do { + if (!loopEntry) { + pc.setAddress(pc.getSuffix());// pc=pc->Suffix; + if (pc.getNumStats() != 1) { + p.setAddress(pc.getFreqData().getStats());// p=pc->U.Stats + if (p.getSymbol() != foundState.getSymbol()) { + do { + p.incAddress(); + } while (p.getSymbol() != foundState.getSymbol()); + } + } else { + p.setAddress(pc.getOneState().getAddress());// p=&(pc->OneState); + } + }// LOOP_ENTRY: + loopEntry = false; + if (p.getSuccessor() != upBranch.getAddress()) { + pc.setAddress(p.getSuccessor());// =p->Successor; + break; + } + ps[pps++] = p.getAddress(); + } while (pc.getSuffix() != 0); + + } // NO_LOOP: + if (pps == 0) { + return pc.getAddress(); + } + upState.setSymbol(getHeap()[upBranch.getAddress()]);// UpState.Symbol=*(byte*) + // UpBranch; + // UpState.Successor=(PPM_CONTEXT*) (((byte*) UpBranch)+1); + upState.setSuccessor(upBranch.getAddress() + 1); //TODO check if +1 necessary + if (pc.getNumStats() != 1) { + if (pc.getAddress() <= subAlloc.getPText()) { + return (0); + } + p.setAddress(pc.getFreqData().getStats()); + if (p.getSymbol() != upState.getSymbol()) { + do { + p.incAddress(); + } while (p.getSymbol() != upState.getSymbol()); + } + int cf = p.getFreq() - 1; + int s0 = pc.getFreqData().getSummFreq() - pc.getNumStats() - cf; + // UpState.Freq=1+((2*cf <= s0)?(5*cf > s0):((2*cf+3*s0-1)/(2*s0))); + upState.setFreq(1 + ((2 * cf <= s0) ? (5 * cf > s0 ? 1 : 0) : + ((2 * cf + 3 * s0 - 1) / (2 * s0)))); + } else { + upState.setFreq(pc.getOneState().getFreq());// UpState.Freq=pc->OneState.Freq; + } + do { + // pc = pc->createChild(this,*--pps,UpState); + tempState.setAddress(ps[--pps]); + pc.setAddress(pc.createChild(this, tempState, upState)); + if (pc.getAddress() == 0) { + return 0; + } + } while (pps != 0); + return pc.getAddress(); + } + + private void updateModelRestart() { + restartModelRare(); + escCount = 0; + } + + private void updateModel() { + //System.out.println("ModelPPM.updateModel()"); + // STATE fs = *FoundState, *p = NULL; + StateRef fs = tempStateRef1; + fs.setValues(foundState); + State p = tempState3.init(getHeap()); + State tempState = tempState4.init(getHeap()); + + PPMContext pc = tempPPMContext3.init(getHeap()); + PPMContext successor = tempPPMContext4.init(getHeap()); + + int ns1, ns, cf, sf, s0; + pc.setAddress(minContext.getSuffix()); + if (fs.getFreq() < MAX_FREQ / 4 && pc.getAddress() != 0) { + if (pc.getNumStats() != 1) { + p.setAddress(pc.getFreqData().getStats()); + if (p.getSymbol() != fs.getSymbol()) { + do { + p.incAddress(); + } while (p.getSymbol() != fs.getSymbol()); + tempState.setAddress(p.getAddress() - State.size); + if (p.getFreq() >= tempState.getFreq()) { + State.ppmdSwap(p, tempState); + p.decAddress(); + } + } + if (p.getFreq() < MAX_FREQ - 9) { + p.incFreq(2); + pc.getFreqData().incSummFreq(2); + } + } else { + p.setAddress(pc.getOneState().getAddress()); + if (p.getFreq() < 32) { + p.incFreq(1); + } + } + } + if (orderFall == 0) { + foundState.setSuccessor(createSuccessors(true, p)); + minContext.setAddress(foundState.getSuccessor()); + maxContext.setAddress(foundState.getSuccessor()); + if (minContext.getAddress() == 0) { + updateModelRestart(); + return; + } + return; + } + subAlloc.getHeap()[subAlloc.getPText()] = (byte) fs.getSymbol(); + subAlloc.incPText(); + successor.setAddress(subAlloc.getPText()); + if (subAlloc.getPText() >= subAlloc.getFakeUnitsStart()) { + updateModelRestart(); + return; + } +// // Debug +// subAlloc.dumpHeap(); + if (fs.getSuccessor() != 0) { + if (fs.getSuccessor() <= subAlloc.getPText()) { + fs.setSuccessor(createSuccessors(false, p)); + if (fs.getSuccessor() == 0) { + updateModelRestart(); + return; + } + } + if (--orderFall == 0) { + successor.setAddress(fs.getSuccessor()); + if (maxContext.getAddress() != minContext.getAddress()) { + subAlloc.decPText(1); + } + } + } else { + foundState.setSuccessor(successor.getAddress()); + fs.setSuccessor(minContext); + } +// // Debug +// subAlloc.dumpHeap(); + ns = minContext.getNumStats(); + s0 = minContext.getFreqData().getSummFreq() - (ns) - (fs.getFreq() - 1); + for (pc.setAddress(maxContext.getAddress()); + pc.getAddress() != minContext.getAddress(); + pc.setAddress(pc.getSuffix())) { + if ((ns1 = pc.getNumStats()) != 1) { + if ((ns1 & 1) == 0) { + //System.out.println(ns1); + pc.getFreqData().setStats( + subAlloc.expandUnits(pc.getFreqData().getStats(), + ns1 >>> 1)); + if (pc.getFreqData().getStats() == 0) { + updateModelRestart(); + return; + } + } + // bug fixed +// int sum = ((2 * ns1 < ns) ? 1 : 0) + +// 2 * ((4 * ((ns1 <= ns) ? 1 : 0)) & ((pc.getFreqData() +// .getSummFreq() <= 8 * ns1) ? 1 : 0)); + int sum = ((2 * ns1 < ns) ? 1 : 0) + 2 * ( + ((4 * ns1 <= ns) ? 1 : 0) & + ((pc.getFreqData().getSummFreq() <= 8 * ns1) ? 1 : 0) + ); + pc.getFreqData().incSummFreq(sum); + } else { + p.setAddress(subAlloc.allocUnits(1)); + if (p.getAddress() == 0) { + updateModelRestart(); + return; + } + p.setValues(pc.getOneState()); + pc.getFreqData().setStats(p); + if (p.getFreq() < MAX_FREQ / 4 - 1) { + p.incFreq(p.getFreq()); + } else { + p.setFreq(MAX_FREQ - 4); + } + pc.getFreqData().setSummFreq( + (p.getFreq() + initEsc + (ns > 3 ? 1 : 0))); + } + cf = 2 * fs.getFreq() * (pc.getFreqData().getSummFreq() + 6); + sf = s0 + pc.getFreqData().getSummFreq(); + if (cf < 6 * sf) { + cf = 1 + (cf > sf ? 1 : 0) + (cf >= 4 * sf ? 1 : 0); + pc.getFreqData().incSummFreq(3); + } else { + cf = 4 + (cf >= 9 * sf ? 1 : 0) + (cf >= 12 * sf ? 1 : 0) + + (cf >= 15 * sf ? 1 : 0); + pc.getFreqData().incSummFreq(cf); + } + p.setAddress(pc.getFreqData().getStats() + ns1 * State.size); + p.setSuccessor(successor); + p.setSymbol(fs.getSymbol()); + p.setFreq(cf); + pc.setNumStats(++ns1); + } + + int address = fs.getSuccessor(); + maxContext.setAddress(address); + minContext.setAddress(address); + //TODO-----debug +// int pos = minContext.getFreqData().getStats(); +// State a = new State(getHeap()); +// a.setAddress(pos); +// pos+=State.size; +// a.setAddress(pos); + //--dbg end + return; + } + + // Debug + public String toString() { + StringBuilder buffer = new StringBuilder(); + buffer.append("ModelPPM["); + buffer.append("\n numMasked="); + buffer.append(numMasked); + buffer.append("\n initEsc="); + buffer.append(initEsc); + buffer.append("\n orderFall="); + buffer.append(orderFall); + buffer.append("\n maxOrder="); + buffer.append(maxOrder); + buffer.append("\n runLength="); + buffer.append(runLength); + buffer.append("\n initRL="); + buffer.append(initRL); + buffer.append("\n escCount="); + buffer.append(escCount); + buffer.append("\n prevSuccess="); + buffer.append(prevSuccess); + buffer.append("\n foundState="); + buffer.append(foundState); + buffer.append("\n coder="); + buffer.append(coder); + buffer.append("\n subAlloc="); + buffer.append(subAlloc); + buffer.append("\n]"); + return buffer.toString(); + } + + // Debug +// public void dumpHeap() { +// subAlloc.dumpHeap(); +// } +} diff --git a/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unpack/ppm/PPMContext.java b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unpack/ppm/PPMContext.java new file mode 100644 index 0000000..5f893b6 --- /dev/null +++ b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unpack/ppm/PPMContext.java @@ -0,0 +1,442 @@ +/* + * Copyright (c) 2007 innoSysTec (R) GmbH, Germany. All rights reserved. + * Original author: Edmund Wagner + * Creation date: 31.05.2007 + * + * Source: $HeadURL$ + * Last changed: $LastChangedDate$ + * + * the unrar licence applies to all junrar source and binary distributions + * you are not allowed to use this source to re-create the RAR compression algorithm + * + * Here some html entities which can be used for escaping javadoc tags: + * "&": "&" or "&" + * "<": "<" or "<" + * ">": ">" or ">" + * "@": "@" + */ +package org.fox.ttcomics2.junrar.unpack.ppm; + +import org.fox.ttcomics2.junrar.io.Raw; + +public class PPMContext extends Pointer { + + public final static int[] ExpEscape = + {25, 14, 9, 7, 5, 5, 4, 4, 4, 3, 3, 3, 2, 2, 2, 2}; + private static final int unionSize = Math.max(FreqData.size, State.size); + public static final int size = 2 + unionSize + 4; // 12 + + // (1==onestate) + private final FreqData freqData; // -\ + + // |-> union + private final State oneState; // -/ + // Temp fields + private final State tempState1 = new State(null); + private final State tempState2 = new State(null); + private final State tempState3 = new State(null); + private final State tempState4 = new State(null); + private final State tempState5 = new State(null); + private final int[] ps = new int[256]; + // ushort NumStats; + private int numStats; // determines if feqData or onstate is used + private int suffix; // pointer ppmcontext + private PPMContext tempPPMContext = null; + + public PPMContext(byte[] mem) { + super(mem); + oneState = new State(mem); + freqData = new FreqData(mem); + } + + public PPMContext init(byte[] mem) { + this.mem = mem; + pos = 0; + oneState.init(mem); + freqData.init(mem); + return this; + } + + public FreqData getFreqData() { + return freqData; + } + + public void setFreqData(FreqData freqData) { + this.freqData.setSummFreq(freqData.getSummFreq()); + this.freqData.setStats(freqData.getStats()); + } + + public final int getNumStats() { + if (mem != null) { + numStats = Raw.readShortLittleEndian(mem, pos) & 0xffff; + } + return numStats; + } + + public final void setNumStats(int numStats) { + this.numStats = numStats & 0xffff; + if (mem != null) { + Raw.writeShortLittleEndian(mem, pos, (short) numStats); + } + } + + public State getOneState() { + return oneState; + } + + public void setOneState(StateRef oneState) { + this.oneState.setValues(oneState); + } + + public int getSuffix() { + if (mem != null) { + suffix = Raw.readIntLittleEndian(mem, pos + 8); + } + return suffix; + } + + public void setSuffix(int suffix) { + this.suffix = suffix; + if (mem != null) { + Raw.writeIntLittleEndian(mem, pos + 8, suffix); + } + } + + public void setSuffix(PPMContext suffix) { + setSuffix(suffix.getAddress()); + } + + @Override + public void setAddress(int pos) { + super.setAddress(pos); + oneState.setAddress(pos + 2); + freqData.setAddress(pos + 2); + } + + private PPMContext getTempPPMContext(byte[] mem) { + if (tempPPMContext == null) { + tempPPMContext = new PPMContext(null); + } + return tempPPMContext.init(mem); + } + + public int createChild(ModelPPM model, State pStats/* ptr */, + StateRef firstState /* ref */) { + PPMContext pc = getTempPPMContext(model.getSubAlloc().getHeap()); + pc.setAddress(model.getSubAlloc().allocContext()); + if (pc != null) { + pc.setNumStats(1); + pc.setOneState(firstState); + pc.setSuffix(this); + pStats.setSuccessor(pc); + } + return pc.getAddress(); + } + + public void rescale(ModelPPM model) { + int OldNS = getNumStats(), i = getNumStats() - 1, Adder, EscFreq; + // STATE* p1, * p; + State p1 = new State(model.getHeap()); + State p = new State(model.getHeap()); + State temp = new State(model.getHeap()); + + for (p.setAddress(model.getFoundState().getAddress()); + p.getAddress() != freqData.getStats(); + p.decAddress()) { + temp.setAddress(p.getAddress() - State.size); + State.ppmdSwap(p, temp); + } + temp.setAddress(freqData.getStats()); + temp.incFreq(4); + freqData.incSummFreq(4); + EscFreq = freqData.getSummFreq() - p.getFreq(); + Adder = (model.getOrderFall() != 0) ? 1 : 0; + p.setFreq((p.getFreq() + Adder) >>> 1); + freqData.setSummFreq(p.getFreq()); + do { + p.incAddress(); + EscFreq -= p.getFreq(); + p.setFreq((p.getFreq() + Adder) >>> 1); + freqData.incSummFreq(p.getFreq()); + temp.setAddress(p.getAddress() - State.size); + if (p.getFreq() > temp.getFreq()) { + p1.setAddress(p.getAddress()); + StateRef tmp = new StateRef(); + tmp.setValues(p1); + State temp2 = new State(model.getHeap()); + State temp3 = new State(model.getHeap()); + do { + // p1[0]=p1[-1]; + temp2.setAddress(p1.getAddress() - State.size); + p1.setValues(temp2); + p1.decAddress(); + temp3.setAddress(p1.getAddress() - State.size); + } while (p1.getAddress() != freqData.getStats() && tmp.getFreq() > temp3.getFreq()); + p1.setValues(tmp); + } + } while (--i != 0); + if (p.getFreq() == 0) { + do { + i++; + p.decAddress(); + } while (p.getFreq() == 0); + EscFreq += i; + setNumStats(getNumStats() - i); + if (getNumStats() == 1) { + StateRef tmp = new StateRef(); + temp.setAddress(freqData.getStats()); + tmp.setValues(temp); + // STATE tmp=*U.Stats; + do { + // tmp.Freq-=(tmp.Freq >> 1) + tmp.decFreq(tmp.getFreq() >>> 1); + EscFreq >>>= 1; + } while (EscFreq > 1); + model.getSubAlloc().freeUnits(freqData.getStats(), (OldNS + 1) >>> 1); + oneState.setValues(tmp); + model.getFoundState().setAddress(oneState.getAddress()); + return; + } + } + EscFreq -= EscFreq >>> 1; + freqData.incSummFreq(EscFreq); + int n0 = (OldNS + 1) >>> 1, n1 = (getNumStats() + 1) >>> 1; + if (n0 != n1) { + freqData.setStats(model.getSubAlloc().shrinkUnits(freqData.getStats(), n0, n1)); + } + model.getFoundState().setAddress(freqData.getStats()); + } + + private int getArrayIndex(ModelPPM Model, State rs) { + PPMContext tempSuffix = getTempPPMContext(Model.getSubAlloc().getHeap()); + tempSuffix.setAddress(getSuffix()); + int ret = 0; + ret += Model.getPrevSuccess(); + ret += Model.getNS2BSIndx()[tempSuffix.getNumStats() - 1]; + ret += Model.getHiBitsFlag() + 2 * Model.getHB2Flag()[rs.getSymbol()]; + ret += ((Model.getRunLength() >>> 26) & 0x20); + return ret; + } + + public int getMean(int summ, int shift, int round) { + return ((summ + (1 << (shift - round))) >>> (shift)); + } + + public void decodeBinSymbol(ModelPPM model) { + State rs = tempState1.init(model.getHeap()); + rs.setAddress(oneState.getAddress());// State& + model.setHiBitsFlag(model.getHB2Flag()[model.getFoundState().getSymbol()]); + int off1 = rs.getFreq() - 1; + int off2 = getArrayIndex(model, rs); + int bs = model.getBinSumm()[off1][off2]; + if (model.getCoder().getCurrentShiftCount(ModelPPM.TOT_BITS) < bs) { + model.getFoundState().setAddress(rs.getAddress()); + rs.incFreq((rs.getFreq() < 128) ? 1 : 0); + model.getCoder().getSubRange().setLowCount(0); + model.getCoder().getSubRange().setHighCount(bs); + bs = ((bs + ModelPPM.INTERVAL - getMean(bs, ModelPPM.PERIOD_BITS, 2)) & 0xffff); + model.getBinSumm()[off1][off2] = bs; + model.setPrevSuccess(1); + model.incRunLength(1); + } else { + model.getCoder().getSubRange().setLowCount(bs); + bs = (bs - getMean(bs, ModelPPM.PERIOD_BITS, 2)) & 0xFFFF; + model.getBinSumm()[off1][off2] = bs; + model.getCoder().getSubRange().setHighCount(ModelPPM.BIN_SCALE); + model.setInitEsc(ExpEscape[bs >>> 10]); + model.setNumMasked(1); + model.getCharMask()[rs.getSymbol()] = model.getEscCount(); + model.setPrevSuccess(0); + model.getFoundState().setAddress(0); + } + //int a = 0;//TODO just 4 debugging + } + +// public static void ppmdSwap(ModelPPM model, StatePtr state1, StatePtr state2) +// { +// byte[] bytes = model.getSubAlloc().getHeap(); +// int p1 = state1.getAddress(); +// int p2 = state2.getAddress(); +// +// for (int i = 0; i < StatePtr.size; i++) { +// byte temp = bytes[p1+i]; +// bytes[p1+i] = bytes[p2+i]; +// bytes[p2+i] = temp; +// } +// state1.setAddress(p1); +// state2.setAddress(p2); +// } + + public void update1(ModelPPM model, int p/* ptr */) { + model.getFoundState().setAddress(p); + model.getFoundState().incFreq(4); + freqData.incSummFreq(4); + State p0 = tempState3.init(model.getHeap()); + State p1 = tempState4.init(model.getHeap()); + p0.setAddress(p); + p1.setAddress(p - State.size); + if (p0.getFreq() > p1.getFreq()) { + State.ppmdSwap(p0, p1); + model.getFoundState().setAddress(p1.getAddress()); + if (p1.getFreq() > ModelPPM.MAX_FREQ) + rescale(model); + } + } + + public boolean decodeSymbol2(ModelPPM model) { + long count; + int hiCnt, i = getNumStats() - model.getNumMasked(); + SEE2Context psee2c = makeEscFreq2(model, i); + RangeCoder coder = model.getCoder(); + // STATE* ps[256], ** pps=ps, * p=U.Stats-1; + State p = tempState1.init(model.getHeap()); + State temp = tempState2.init(model.getHeap()); + p.setAddress(freqData.getStats() - State.size); + int pps = 0; + hiCnt = 0; + + do { + do { + p.incAddress();// p++; + } while (model.getCharMask()[p.getSymbol()] == model.getEscCount()); + hiCnt += p.getFreq(); + ps[pps++] = p.getAddress(); + } while (--i != 0); + coder.getSubRange().incScale(hiCnt); + count = coder.getCurrentCount(); + if (count >= coder.getSubRange().getScale()) { + return false; + } + pps = 0; + p.setAddress(ps[pps]); + if (count < hiCnt) { + hiCnt = 0; + while ((hiCnt += p.getFreq()) <= count) { + p.setAddress(ps[++pps]);// p=*++pps; + } + coder.getSubRange().setHighCount(hiCnt); + coder.getSubRange().setLowCount(hiCnt - p.getFreq()); + psee2c.update(); + update2(model, p.getAddress()); + } else { + coder.getSubRange().setLowCount(hiCnt); + coder.getSubRange().setHighCount(coder.getSubRange().getScale()); + i = getNumStats() - model.getNumMasked();// ->NumMasked; + pps--; + do { + temp.setAddress(ps[++pps]);// (*++pps) + model.getCharMask()[temp.getSymbol()] = model.getEscCount(); + } while (--i != 0); + psee2c.incSumm((int) coder.getSubRange().getScale()); + model.setNumMasked(getNumStats()); + } + return (true); + } + + public void update2(ModelPPM model, int p/* state ptr */) { + State temp = tempState5.init(model.getHeap()); + temp.setAddress(p); + model.getFoundState().setAddress(p); + model.getFoundState().incFreq(4); + freqData.incSummFreq(4); + if (temp.getFreq() > ModelPPM.MAX_FREQ) { + rescale(model); + } + model.incEscCount(1); + model.setRunLength(model.getInitRL()); + } + + private SEE2Context makeEscFreq2(ModelPPM model, int Diff) { + SEE2Context psee2c; + int numStats = getNumStats(); + if (numStats != 256) { + PPMContext suff = getTempPPMContext(model.getHeap()); + suff.setAddress(getSuffix()); + int idx1 = model.getNS2Indx()[Diff - 1]; + int idx2 = 0; + idx2 += (Diff < suff.getNumStats() - numStats) ? 1 : 0; + idx2 += 2 * ((freqData.getSummFreq() < 11 * numStats) ? 1 : 0); + idx2 += 4 * ((model.getNumMasked() > Diff) ? 1 : 0); + idx2 += model.getHiBitsFlag(); + psee2c = model.getSEE2Cont()[idx1][idx2]; + model.getCoder().getSubRange().setScale(psee2c.getMean()); + } else { + psee2c = model.getDummySEE2Cont(); + model.getCoder().getSubRange().setScale(1); + } + return psee2c; + } + + public boolean decodeSymbol1(ModelPPM model) { + + RangeCoder coder = model.getCoder(); + coder.getSubRange().setScale(freqData.getSummFreq()); + State p = new State(model.getHeap()); + p.setAddress(freqData.getStats()); + int i, HiCnt; + long count = coder.getCurrentCount(); + if (count >= coder.getSubRange().getScale()) { + return false; + } + if (count < (HiCnt = p.getFreq())) { + coder.getSubRange().setHighCount(HiCnt); + model.setPrevSuccess((2 * HiCnt > coder.getSubRange().getScale()) ? 1 : 0); + model.incRunLength(model.getPrevSuccess()); + HiCnt += 4; + model.getFoundState().setAddress(p.getAddress()); + model.getFoundState().setFreq(HiCnt); + freqData.incSummFreq(4); + if (HiCnt > ModelPPM.MAX_FREQ) { + rescale(model); + } + coder.getSubRange().setLowCount(0); + return true; + } else { + if (model.getFoundState().getAddress() == 0) { + return (false); + } + } + model.setPrevSuccess(0); + int numStats = getNumStats(); + i = numStats - 1; + while ((HiCnt += p.incAddress().getFreq()) <= count) { + if (--i == 0) { + model.setHiBitsFlag(model.getHB2Flag()[model.getFoundState().getSymbol()]); + coder.getSubRange().setLowCount(HiCnt); + model.getCharMask()[p.getSymbol()] = model.getEscCount(); + model.setNumMasked(numStats); + i = numStats - 1; + model.getFoundState().setAddress(0); + do { + model.getCharMask()[p.decAddress().getSymbol()] = model.getEscCount(); + } while (--i != 0); + coder.getSubRange().setHighCount(coder.getSubRange().getScale()); + return (true); + } + } + coder.getSubRange().setLowCount(HiCnt - p.getFreq()); + coder.getSubRange().setHighCount(HiCnt); + update1(model, p.getAddress()); + return (true); + } + + public String toString() { + StringBuilder buffer = new StringBuilder(); + buffer.append("PPMContext["); + buffer.append("\n pos="); + buffer.append(pos); + buffer.append("\n size="); + buffer.append(size); + buffer.append("\n numStats="); + buffer.append(getNumStats()); + buffer.append("\n Suffix="); + buffer.append(getSuffix()); + buffer.append("\n freqData="); + buffer.append(freqData); + buffer.append("\n oneState="); + buffer.append(oneState); + buffer.append("\n]"); + return buffer.toString(); + } + +} diff --git a/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unpack/ppm/Pointer.java b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unpack/ppm/Pointer.java new file mode 100644 index 0000000..8df140e --- /dev/null +++ b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unpack/ppm/Pointer.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2007 innoSysTec (R) GmbH, Germany. All rights reserved. + * Original author: Edmund Wagner + * Creation date: 14.06.2007 + * + * Source: $HeadURL$ + * Last changed: $LastChangedDate$ + * + * the unrar licence applies to all junrar source and binary distributions + * you are not allowed to use this source to re-create the RAR compression algorithm + * + * Here some html entities which can be used for escaping javadoc tags: + * "&": "&" or "&" + * "<": "<" or "<" + * ">": ">" or ">" + * "@": "@" + */ +package org.fox.ttcomics2.junrar.unpack.ppm; + +public abstract class Pointer { + protected byte[] mem; + protected int pos; + + public Pointer(byte[] mem) { + this.mem = mem; + } + + public int getAddress() { + assert (mem != null); + return pos; + } + + public void setAddress(int pos) { + assert (mem != null); + assert (pos >= 0) && (pos < mem.length) : pos; + this.pos = pos; + } +} diff --git a/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unpack/ppm/RangeCoder.java b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unpack/ppm/RangeCoder.java new file mode 100755 index 0000000..57b0013 --- /dev/null +++ b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unpack/ppm/RangeCoder.java @@ -0,0 +1,153 @@ +/* + * Copyright (c) 2007 innoSysTec (R) GmbH, Germany. All rights reserved. + * Original author: Edmund Wagner + * Creation date: 31.05.2007 + * + * Source: $HeadURL$ + * Last changed: $LastChangedDate$ + * + * the unrar licence applies to all junrar source and binary distributions + * you are not allowed to use this source to re-create the RAR compression algorithm + * + * Here some html entities which can be used for escaping javadoc tags: + * "&": "&" or "&" + * "<": "<" or "<" + * ">": ">" or ">" + * "@": "@" + */ +package org.fox.ttcomics2.junrar.unpack.ppm; + +import org.fox.ttcomics2.junrar.exception.RarException; +import org.fox.ttcomics2.junrar.unpack.Unpack; + +import java.io.IOException; + + +public class RangeCoder { + public static final int TOP = 1 << 24; + + public static final int BOT = 1 << 15; + + private static final long uintMask = 0xFFFFffffL; + private final SubRange subRange = new SubRange(); + // uint low, code, range; + private long low, code, range; + private Unpack unpackRead; + + public SubRange getSubRange() { + return subRange; + } + + public void initDecoder(Unpack unpackRead) throws IOException, RarException { + this.unpackRead = unpackRead; + + low = code = 0L; + range = 0xFFFFffffL; + for (int i = 0; i < 4; i++) { + code = ((code << 8) | getChar()) & uintMask; + } + } + + public int getCurrentCount() { + range = (range / subRange.getScale()) & uintMask; + return (int) ((code - low) / (range)); + } + + public long getCurrentShiftCount(int SHIFT) { + range = range >>> SHIFT; + return ((code - low) / (range)) & uintMask; + } + + public void decode() { + low = (low + (range * subRange.getLowCount())) & uintMask; + range = (range * (subRange.getHighCount() - subRange.getLowCount())) & uintMask; + } + + private int getChar() throws IOException, RarException { + return (unpackRead.getChar()); + } + + public void ariDecNormalize() throws IOException, RarException { +// while ((low ^ (low + range)) < TOP || range < BOT && ((range = -low & (BOT - 1)) != 0 ? true : true)) +// { +// code = ((code << 8) | unpackRead.getChar()&0xff)&uintMask; +// range = (range << 8)&uintMask; +// low = (low << 8)&uintMask; +// } + + // Rewrote for clarity + boolean c2 = false; + while ((low ^ (low + range)) < TOP || (c2 = range < BOT)) { + if (c2) { + range = (-low & (BOT - 1)) & uintMask; + c2 = false; + } + code = ((code << 8) | getChar()) & uintMask; + range = (range << 8) & uintMask; + low = (low << 8) & uintMask; + } + } + + // Debug + public String toString() { + StringBuilder buffer = new StringBuilder(); + buffer.append("RangeCoder["); + buffer.append("\n low="); + buffer.append(low); + buffer.append("\n code="); + buffer.append(code); + buffer.append("\n range="); + buffer.append(range); + buffer.append("\n subrange="); + buffer.append(subRange); + buffer.append("]"); + return buffer.toString(); + } + + public static class SubRange { + // uint LowCount, HighCount, scale; + private long lowCount, highCount, scale; + + public long getHighCount() { + return highCount; + } + + public void setHighCount(long highCount) { + this.highCount = highCount & uintMask; + } + + public long getLowCount() { + return lowCount & uintMask; + } + + public void setLowCount(long lowCount) { + this.lowCount = lowCount & uintMask; + } + + public long getScale() { + return scale; + } + + public void setScale(long scale) { + this.scale = scale & uintMask; + } + + public void incScale(int dScale) { + setScale(getScale() + dScale); + } + + // Debug + public String toString() { + StringBuilder buffer = new StringBuilder(); + buffer.append("SubRange["); + buffer.append("\n lowCount="); + buffer.append(lowCount); + buffer.append("\n highCount="); + buffer.append(highCount); + buffer.append("\n scale="); + buffer.append(scale); + buffer.append("]"); + return buffer.toString(); + } + } +} diff --git a/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unpack/ppm/RarMemBlock.java b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unpack/ppm/RarMemBlock.java new file mode 100644 index 0000000..05c831e --- /dev/null +++ b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unpack/ppm/RarMemBlock.java @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2007 innoSysTec (R) GmbH, Germany. All rights reserved. + * Original author: Edmund Wagner + * Creation date: 05.06.2007 + * + * Source: $HeadURL$ + * Last changed: $LastChangedDate$ + * + * the unrar licence applies to all junrar source and binary distributions + * you are not allowed to use this source to re-create the RAR compression algorithm + * + * Here some html entities which can be used for escaping javadoc tags: + * "&": "&" or "&" + * "<": "<" or "<" + * ">": ">" or ">" + * "@": "@" + */ +package org.fox.ttcomics2.junrar.unpack.ppm; + +import org.fox.ttcomics2.junrar.io.Raw; + + +public class RarMemBlock extends Pointer { + + public static final int size = 12; + + private int stamp, NU; + + private int next, prev; // Pointer RarMemBlock + + public RarMemBlock(byte[] mem) { + super(mem); + } + + public void insertAt(RarMemBlock p) { + RarMemBlock temp = new RarMemBlock(mem); + setPrev(p.getAddress()); + temp.setAddress(getPrev()); + setNext(temp.getNext());// prev.getNext(); + temp.setNext(this);// prev.setNext(this); + temp.setAddress(getNext()); + temp.setPrev(this);// next.setPrev(this); + } + + public void remove() { + RarMemBlock temp = new RarMemBlock(mem); + temp.setAddress(getPrev()); + temp.setNext(getNext());// prev.setNext(next); + temp.setAddress(getNext()); + temp.setPrev(getPrev());// next.setPrev(prev); +// next = -1; +// prev = -1; + } + + public int getNext() { + if (mem != null) { + next = Raw.readIntLittleEndian(mem, pos + 4); + } + return next; + } + + public void setNext(int next) { + this.next = next; + if (mem != null) { + Raw.writeIntLittleEndian(mem, pos + 4, next); + } + } + + public void setNext(RarMemBlock next) { + setNext(next.getAddress()); + } + + public int getNU() { + if (mem != null) { + NU = Raw.readShortLittleEndian(mem, pos + 2) & 0xffff; + } + return NU; + } + + public void setNU(int nu) { + NU = nu & 0xffff; + if (mem != null) { + Raw.writeShortLittleEndian(mem, pos + 2, (short) nu); + } + } + + public int getPrev() { + if (mem != null) { + prev = Raw.readIntLittleEndian(mem, pos + 8); + } + return prev; + } + + public void setPrev(int prev) { + this.prev = prev; + if (mem != null) { + Raw.writeIntLittleEndian(mem, pos + 8, prev); + } + } + + public void setPrev(RarMemBlock prev) { + setPrev(prev.getAddress()); + } + + public int getStamp() { + if (mem != null) { + stamp = Raw.readShortLittleEndian(mem, pos) & 0xffff; + } + return stamp; + } + + public void setStamp(int stamp) { + this.stamp = stamp; + if (mem != null) { + Raw.writeShortLittleEndian(mem, pos, (short) stamp); + } + } +} diff --git a/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unpack/ppm/RarNode.java b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unpack/ppm/RarNode.java new file mode 100644 index 0000000..8d743d0 --- /dev/null +++ b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unpack/ppm/RarNode.java @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2007 innoSysTec (R) GmbH, Germany. All rights reserved. + * Original author: Edmund Wagner + * Creation date: 05.06.2007 + * + * Source: $HeadURL$ + * Last changed: $LastChangedDate$ + * + * the unrar licence applies to all junrar source and binary distributions + * you are not allowed to use this source to re-create the RAR compression algorithm + * + * Here some html entities which can be used for escaping javadoc tags: + * "&": "&" or "&" + * "<": "<" or "<" + * ">": ">" or ">" + * "@": "@" + */ +package org.fox.ttcomics2.junrar.unpack.ppm; + +import org.fox.ttcomics2.junrar.io.Raw; + + +public class RarNode extends Pointer { + public static final int size = 4; + private int next; //rarnode pointer + + public RarNode(byte[] mem) { + super(mem); + } + + public int getNext() { + if (mem != null) { + next = Raw.readIntLittleEndian(mem, pos); + } + return next; + } + + public void setNext(int next) { + this.next = next; + if (mem != null) { + Raw.writeIntLittleEndian(mem, pos, next); + } + } + + public void setNext(RarNode next) { + setNext(next.getAddress()); + } + + public String toString() { + StringBuilder buffer = new StringBuilder(); + buffer.append("State["); + buffer.append("\n pos="); + buffer.append(pos); + buffer.append("\n size="); + buffer.append(size); + buffer.append("\n next="); + buffer.append(getNext()); + buffer.append("\n]"); + return buffer.toString(); + } +} diff --git a/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unpack/ppm/SEE2Context.java b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unpack/ppm/SEE2Context.java new file mode 100644 index 0000000..378c0d3 --- /dev/null +++ b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unpack/ppm/SEE2Context.java @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2007 innoSysTec (R) GmbH, Germany. All rights reserved. + * Original author: Edmund Wagner + * Creation date: 31.05.2007 + * + * Source: $HeadURL$ + * Last changed: $LastChangedDate$ + * + * the unrar licence applies to all junrar source and binary distributions + * you are not allowed to use this source to re-create the RAR compression algorithm + * + * Here some html entities which can be used for escaping javadoc tags: + * "&": "&" or "&" + * "<": "<" or "<" + * ">": ">" or ">" + * "@": "@" + */ +package org.fox.ttcomics2.junrar.unpack.ppm; + +public class SEE2Context { + public static final int size = 4; + + // ushort Summ; + private int summ; + + // byte Shift; + private int shift; + + // byte Count; + private int count; + + public void init(int initVal) { + shift = (ModelPPM.PERIOD_BITS - 4) & 0xff; + summ = (initVal << shift) & 0xffff; + count = 4; + } + + public int getMean() { + int retVal = summ >>> shift; + summ -= retVal; + return retVal + ((retVal == 0) ? 1 : 0); + } + + public void update() { + if (shift < ModelPPM.PERIOD_BITS && --count == 0) { + summ += summ; + count = (3 << shift++); + } + summ &= 0xffff; + count &= 0xff; + shift &= 0xff; + } + + public int getCount() { + return count; + } + + public void setCount(int count) { + this.count = count & 0xff; + } + + public int getShift() { + return shift; + } + + public void setShift(int shift) { + this.shift = shift & 0xff; + } + + public int getSumm() { + return summ; + } + + public void setSumm(int summ) { + this.summ = summ & 0xffff; + } + + public void incSumm(int dSumm) { + setSumm(getSumm() + dSumm); + } + + public String toString() { + StringBuilder buffer = new StringBuilder(); + buffer.append("SEE2Context["); + buffer.append("\n size="); + buffer.append(size); + buffer.append("\n summ="); + buffer.append(summ); + buffer.append("\n shift="); + buffer.append(shift); + buffer.append("\n count="); + buffer.append(count); + buffer.append("\n]"); + return buffer.toString(); + } +} diff --git a/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unpack/ppm/State.java b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unpack/ppm/State.java new file mode 100644 index 0000000..ec131f2 --- /dev/null +++ b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unpack/ppm/State.java @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2007 innoSysTec (R) GmbH, Germany. All rights reserved. + * Original author: Edmund Wagner + * Creation date: 01.06.2007 + * + * Source: $HeadURL$ + * Last changed: $LastChangedDate$ + * + * the unrar licence applies to all junrar source and binary distributions + * you are not allowed to use this source to re-create the RAR compression algorithm + * + * Here some html entities which can be used for escaping javadoc tags: + * "&": "&" or "&" + * "<": "<" or "<" + * ">": ">" or ">" + * "@": "@" + */ +package org.fox.ttcomics2.junrar.unpack.ppm; + +import org.fox.ttcomics2.junrar.io.Raw; + +public class State extends Pointer { + + public static final int size = 6; + + public State(byte[] mem) { + super(mem); + } + + public static void ppmdSwap(State ptr1, State ptr2) { + byte[] mem1 = ptr1.mem, mem2 = ptr2.mem; + for (int i = 0, pos1 = ptr1.pos, pos2 = ptr2.pos; i < size; i++, pos1++, pos2++) { + byte temp = mem1[pos1]; + mem1[pos1] = mem2[pos2]; + mem2[pos2] = temp; + } + } + + public State init(byte[] mem) { + this.mem = mem; + pos = 0; + return this; + } + + public int getSymbol() { + return mem[pos] & 0xff; + } + + public void setSymbol(int symbol) { + mem[pos] = (byte) symbol; + } + + public int getFreq() { + return mem[pos + 1] & 0xff; + } + + public void setFreq(int freq) { + mem[pos + 1] = (byte) freq; + } + + public void incFreq(int dFreq) { + mem[pos + 1] += dFreq; + } + + public int getSuccessor() { + return Raw.readIntLittleEndian(mem, pos + 2); + } + + public void setSuccessor(int successor) { + Raw.writeIntLittleEndian(mem, pos + 2, successor); + } + + public void setSuccessor(PPMContext successor) { + setSuccessor(successor.getAddress()); + } + + public void setValues(StateRef state) { + setSymbol(state.getSymbol()); + setFreq(state.getFreq()); + setSuccessor(state.getSuccessor()); + } + + public void setValues(State ptr) { + System.arraycopy(ptr.mem, ptr.pos, mem, pos, size); + } + + public State decAddress() { + setAddress(pos - size); + return this; + } + + public State incAddress() { + setAddress(pos + size); + return this; + } + + public String toString() { + StringBuilder buffer = new StringBuilder(); + buffer.append("State["); + buffer.append("\n pos="); + buffer.append(pos); + buffer.append("\n size="); + buffer.append(size); + buffer.append("\n symbol="); + buffer.append(getSymbol()); + buffer.append("\n freq="); + buffer.append(getFreq()); + buffer.append("\n successor="); + buffer.append(getSuccessor()); + buffer.append("\n]"); + return buffer.toString(); + } +} diff --git a/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unpack/ppm/StateRef.java b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unpack/ppm/StateRef.java new file mode 100644 index 0000000..82c1323 --- /dev/null +++ b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unpack/ppm/StateRef.java @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2007 innoSysTec (R) GmbH, Germany. All rights reserved. + * Original author: Edmund Wagner + * Creation date: 01.06.2007 + * + * Source: $HeadURL$ + * Last changed: $LastChangedDate$ + * + * the unrar licence applies to all junrar source and binary distributions + * you are not allowed to use this source to re-create the RAR compression algorithm + * + * Here some html entities which can be used for escaping javadoc tags: + * "&": "&" or "&" + * "<": "<" or "<" + * ">": ">" or ">" + * "@": "@" + */ +package org.fox.ttcomics2.junrar.unpack.ppm; + + +public class StateRef { + + private int symbol; + + private int freq; + + private int successor; // pointer ppmcontext + + public StateRef() { + } + + public int getSymbol() { + return symbol; + } + + public void setSymbol(int symbol) { + this.symbol = symbol & 0xff; + } + + public int getFreq() { + return freq; + } + + public void setFreq(int freq) { + this.freq = freq & 0xff; + } + + public void incFreq(int dFreq) { + freq = (freq + dFreq) & 0xff; + } + + public void decFreq(int dFreq) { + freq = (freq - dFreq) & 0xff; + } + + public void setValues(State statePtr) { + setFreq(statePtr.getFreq()); + setSuccessor(statePtr.getSuccessor()); + setSymbol(statePtr.getSymbol()); + } + + public int getSuccessor() { + return successor; + } + + public void setSuccessor(int successor) { + this.successor = successor; + } + + public void setSuccessor(PPMContext successor) { + setSuccessor(successor.getAddress()); + } + + public String toString() { + StringBuilder buffer = new StringBuilder(); + buffer.append("State["); + buffer.append("\n symbol="); + buffer.append(getSymbol()); + buffer.append("\n freq="); + buffer.append(getFreq()); + buffer.append("\n successor="); + buffer.append(getSuccessor()); + buffer.append("\n]"); + return buffer.toString(); + } +} diff --git a/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unpack/ppm/SubAllocator.java b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unpack/ppm/SubAllocator.java new file mode 100644 index 0000000..267eb85 --- /dev/null +++ b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unpack/ppm/SubAllocator.java @@ -0,0 +1,416 @@ +/* + * Copyright (c) 2007 innoSysTec (R) GmbH, Germany. All rights reserved. + * Original author: Edmund Wagner + * Creation date: 31.05.2007 + * + * Source: $HeadURL$ + * Last changed: $LastChangedDate$ + * + * the unrar licence applies to all junrar source and binary distributions + * you are not allowed to use this source to re-create the RAR compression algorithm + * + * Here some html entities which can be used for escaping javadoc tags: + * "&": "&" or "&" + * "<": "<" or "<" + * ">": ">" or ">" + * "@": "@" + */ +package org.fox.ttcomics2.junrar.unpack.ppm; + +import java.util.Arrays; + +public class SubAllocator { + public static final int N1 = 4, N2 = 4, N3 = 4, N4 = (128 + 3 - 1 * N1 - 2 + * N2 - 3 * N3) / 4; + + public static final int N_INDEXES = N1 + N2 + N3 + N4; + + public static final int UNIT_SIZE = Math.max(PPMContext.size, + RarMemBlock.size); + + public static final int FIXED_UNIT_SIZE = 12; + private final RarNode[] freeList = new RarNode[N_INDEXES]; + private int subAllocatorSize; + // byte Indx2Units[N_INDEXES], Units2Indx[128], GlueCount; + private int[] indx2Units = new int[N_INDEXES]; + private int[] units2Indx = new int[128]; + private int glueCount; + // byte *HeapStart,*LoUnit, *HiUnit; + private int heapStart, loUnit, hiUnit; + // byte *pText, *UnitsStart,*HeapEnd,*FakeUnitsStart; + private int pText, unitsStart, heapEnd, fakeUnitsStart; + + private byte[] heap; + + private int freeListPos; + + private int tempMemBlockPos; + + // Temp fields + private RarNode tempRarNode = null; + private RarMemBlock tempRarMemBlock1 = null; + private RarMemBlock tempRarMemBlock2 = null; + private RarMemBlock tempRarMemBlock3 = null; + + public SubAllocator() { + clean(); + } + + public void clean() { + subAllocatorSize = 0; + } + + private void insertNode(int p/* rarnode ptr */, int indx) { + RarNode temp = tempRarNode; + temp.setAddress(p); + temp.setNext(freeList[indx].getNext()); + freeList[indx].setNext(temp); + } + + public void incPText() { + pText++; + } + + private int removeNode(int indx) { + int retVal = freeList[indx].getNext(); + RarNode temp = tempRarNode; + temp.setAddress(retVal); + freeList[indx].setNext(temp.getNext()); + return retVal; + } + + private int U2B(int NU) { + return /* 8*NU+4*NU */UNIT_SIZE * NU; + } + + /* memblockptr */ + private int MBPtr(int BasePtr, int Items) { + return (BasePtr + U2B(Items)); + } + + private void splitBlock(int pv/* ptr */, int oldIndx, int newIndx) { + int i, uDiff = indx2Units[oldIndx] - indx2Units[newIndx]; + int p = pv + U2B(indx2Units[newIndx]); + if (indx2Units[i = units2Indx[uDiff - 1]] != uDiff) { + insertNode(p, --i); + p += U2B(i = indx2Units[i]); + uDiff -= i; + } + insertNode(p, units2Indx[uDiff - 1]); + } + + public void stopSubAllocator() { + if (subAllocatorSize != 0) { + subAllocatorSize = 0; + heap = null; + heapStart = 1; + // rarfree(HeapStart); + // Free temp fields + tempRarNode = null; + tempRarMemBlock1 = null; + tempRarMemBlock2 = null; + tempRarMemBlock3 = null; + } + } + + public int GetAllocatedMemory() { + return subAllocatorSize; + } + + public boolean startSubAllocator(int SASize) { + int t = SASize << 20; + if (subAllocatorSize == t) { + return true; + } + stopSubAllocator(); + int allocSize = t / FIXED_UNIT_SIZE * UNIT_SIZE + UNIT_SIZE; + + // adding space for freelist (needed for poiters) + // 1+ for null pointer + int realAllocSize = 1 + allocSize + 4 * N_INDEXES; + // adding space for an additional memblock + tempMemBlockPos = realAllocSize; + realAllocSize += RarMemBlock.size; + + heap = new byte[realAllocSize]; + heapStart = 1; + heapEnd = heapStart + allocSize - UNIT_SIZE; + subAllocatorSize = t; + // Bug fixed + freeListPos = heapStart + allocSize; + assert (realAllocSize - tempMemBlockPos == RarMemBlock.size) : realAllocSize + + " " + tempMemBlockPos + " " + RarMemBlock.size; + + // Init freeList + for (int i = 0, pos = freeListPos; i < freeList.length; i++, pos += RarNode.size) { + freeList[i] = new RarNode(heap); + freeList[i].setAddress(pos); + } + + // Init temp fields + tempRarNode = new RarNode(heap); + tempRarMemBlock1 = new RarMemBlock(heap); + tempRarMemBlock2 = new RarMemBlock(heap); + tempRarMemBlock3 = new RarMemBlock(heap); + + return true; + } + + private void glueFreeBlocks() { + RarMemBlock s0 = tempRarMemBlock1; + s0.setAddress(tempMemBlockPos); + RarMemBlock p = tempRarMemBlock2; + RarMemBlock p1 = tempRarMemBlock3; + int i, k, sz; + if (loUnit != hiUnit) { + heap[loUnit] = 0; + } + for (i = 0, s0.setPrev(s0), s0.setNext(s0); i < N_INDEXES; i++) { + while (freeList[i].getNext() != 0) { + p.setAddress(removeNode(i));// =(RAR_MEM_BLK*)RemoveNode(i); + p.insertAt(s0);// p->insertAt(&s0); + p.setStamp(0xFFFF);// p->Stamp=0xFFFF; + p.setNU(indx2Units[i]);// p->NU=Indx2Units[i]; + } + } + for (p.setAddress(s0.getNext()); p.getAddress() != s0.getAddress(); p + .setAddress(p.getNext())) { + // while ((p1=MBPtr(p,p->NU))->Stamp == 0xFFFF && int(p->NU)+p1->NU + // < 0x10000) + // Bug fixed + p1.setAddress(MBPtr(p.getAddress(), p.getNU())); + while (p1.getStamp() == 0xFFFF && p.getNU() + p1.getNU() < 0x10000) { + p1.remove(); + p.setNU(p.getNU() + p1.getNU());// ->NU += p1->NU; + p1.setAddress(MBPtr(p.getAddress(), p.getNU())); + } + } + // while ((p=s0.next) != &s0) + // Bug fixed + p.setAddress(s0.getNext()); + while (p.getAddress() != s0.getAddress()) { + for (p.remove(), sz = p.getNU(); sz > 128; sz -= 128, p + .setAddress(MBPtr(p.getAddress(), 128))) { + insertNode(p.getAddress(), N_INDEXES - 1); + } + if (indx2Units[i = units2Indx[sz - 1]] != sz) { + k = sz - indx2Units[--i]; + insertNode(MBPtr(p.getAddress(), sz - k), k - 1); + } + insertNode(p.getAddress(), i); + p.setAddress(s0.getNext()); + } + } + + private int allocUnitsRare(int indx) { + if (glueCount == 0) { + glueCount = 255; + glueFreeBlocks(); + if (freeList[indx].getNext() != 0) { + return removeNode(indx); + } + } + int i = indx; + do { + if (++i == N_INDEXES) { + glueCount--; + i = U2B(indx2Units[indx]); + int j = FIXED_UNIT_SIZE * indx2Units[indx]; + if (fakeUnitsStart - pText > j) { + fakeUnitsStart -= j; + unitsStart -= i; + return unitsStart; + } + return (0); + } + } while (freeList[i].getNext() == 0); + int retVal = removeNode(i); + splitBlock(retVal, i, indx); + return retVal; + } + + public int allocUnits(int NU) { + int indx = units2Indx[NU - 1]; + if (freeList[indx].getNext() != 0) { + return removeNode(indx); + } + int retVal = loUnit; + loUnit += U2B(indx2Units[indx]); + if (loUnit <= hiUnit) { + return retVal; + } + loUnit -= U2B(indx2Units[indx]); + return allocUnitsRare(indx); + } + + public int allocContext() { + if (hiUnit != loUnit) + return (hiUnit -= UNIT_SIZE); + if (freeList[0].getNext() != 0) { + return removeNode(0); + } + return allocUnitsRare(0); + } + + public int expandUnits(int oldPtr, int OldNU) { + int i0 = units2Indx[OldNU - 1]; + int i1 = units2Indx[OldNU - 1 + 1]; + if (i0 == i1) { + return oldPtr; + } + int ptr = allocUnits(OldNU + 1); + if (ptr != 0) { + // memcpy(ptr,OldPtr,U2B(OldNU)); + System.arraycopy(heap, oldPtr, heap, ptr, U2B(OldNU)); + insertNode(oldPtr, i0); + } + return ptr; + } + + public int shrinkUnits(int oldPtr, int oldNU, int newNU) { + // System.out.println("SubAllocator.shrinkUnits(" + OldPtr + ", " + + // OldNU + ", " + NewNU + ")"); + int i0 = units2Indx[oldNU - 1]; + int i1 = units2Indx[newNU - 1]; + if (i0 == i1) { + return oldPtr; + } + if (freeList[i1].getNext() != 0) { + int ptr = removeNode(i1); + // memcpy(ptr,OldPtr,U2B(NewNU)); + // for (int i = 0; i < U2B(NewNU); i++) { + // heap[ptr + i] = heap[OldPtr + i]; + // } + System.arraycopy(heap, oldPtr, heap, ptr, U2B(newNU)); + insertNode(oldPtr, i0); + return ptr; + } else { + splitBlock(oldPtr, i0, i1); + return oldPtr; + } + } + + public void freeUnits(int ptr, int OldNU) { + insertNode(ptr, units2Indx[OldNU - 1]); + } + + public int getFakeUnitsStart() { + return fakeUnitsStart; + } + + public void setFakeUnitsStart(int fakeUnitsStart) { + this.fakeUnitsStart = fakeUnitsStart; + } + + public int getHeapEnd() { + return heapEnd; + } + + public int getPText() { + return pText; + } + + public void setPText(int text) { + pText = text; + } + + public void decPText(int dPText) { + setPText(getPText() - dPText); + } + + public int getUnitsStart() { + return unitsStart; + } + + public void setUnitsStart(int unitsStart) { + this.unitsStart = unitsStart; + } + + public void initSubAllocator() { + int i, k; + Arrays + .fill(heap, freeListPos, freeListPos + sizeOfFreeList(), + (byte) 0); + + pText = heapStart; + + int size2 = FIXED_UNIT_SIZE + * (subAllocatorSize / 8 / FIXED_UNIT_SIZE * 7); + int realSize2 = size2 / FIXED_UNIT_SIZE * UNIT_SIZE; + int size1 = subAllocatorSize - size2; + int realSize1 = size1 / FIXED_UNIT_SIZE * UNIT_SIZE + size1 + % FIXED_UNIT_SIZE; + hiUnit = heapStart + subAllocatorSize; + loUnit = unitsStart = heapStart + realSize1; + fakeUnitsStart = heapStart + size1; + hiUnit = loUnit + realSize2; + + for (i = 0, k = 1; i < N1; i++, k += 1) { + indx2Units[i] = k & 0xff; + } + for (k++; i < N1 + N2; i++, k += 2) { + indx2Units[i] = k & 0xff; + } + for (k++; i < N1 + N2 + N3; i++, k += 3) { + indx2Units[i] = k & 0xff; + } + for (k++; i < (N1 + N2 + N3 + N4); i++, k += 4) { + indx2Units[i] = k & 0xff; + } + + for (glueCount = 0, k = 0, i = 0; k < 128; k++) { + i += ((indx2Units[i] < (k + 1)) ? 1 : 0); + units2Indx[k] = i & 0xff; + } + + } + + private int sizeOfFreeList() { + return freeList.length * RarNode.size; + } + + public byte[] getHeap() { + return heap; + } + + // Debug + // public void dumpHeap() { + // File file = new File("P:\\test\\heapdumpj"); + // OutputStream out = null; + // try { + // out = new FileOutputStream(file); + // out.write(heap, heapStart, heapEnd - heapStart); + // out.flush(); + // System.out.println("Heap dumped to " + file.getAbsolutePath()); + // } + // catch (IOException e) { + // e.printStackTrace(); + // } + // finally { + // FileUtil.close(out); + // } + // } + + // Debug + public String toString() { + StringBuilder buffer = new StringBuilder(); + buffer.append("SubAllocator["); + buffer.append("\n subAllocatorSize="); + buffer.append(subAllocatorSize); + buffer.append("\n glueCount="); + buffer.append(glueCount); + buffer.append("\n heapStart="); + buffer.append(heapStart); + buffer.append("\n loUnit="); + buffer.append(loUnit); + buffer.append("\n hiUnit="); + buffer.append(hiUnit); + buffer.append("\n pText="); + buffer.append(pText); + buffer.append("\n unitsStart="); + buffer.append(unitsStart); + buffer.append("\n]"); + return buffer.toString(); + } + +} diff --git a/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unpack/vm/BitInput.java b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unpack/vm/BitInput.java new file mode 100644 index 0000000..f1a7e07 --- /dev/null +++ b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unpack/vm/BitInput.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2007 innoSysTec (R) GmbH, Germany. All rights reserved. + * Original author: Edmund Wagner + * Creation date: 31.05.2007 + * + * Source: $HeadURL$ + * Last changed: $LastChangedDate$ + * + * the unrar licence applies to all junrar source and binary distributions + * you are not allowed to use this source to re-create the RAR compression algorithm + * + * Here some html entities which can be used for escaping javadoc tags: + * "&": "&" or "&" + * "<": "<" or "<" + * ">": ">" or ">" + * "@": "@" + */ +package org.fox.ttcomics2.junrar.unpack.vm; + +public class BitInput { + public static final int MAX_SIZE = 0x8000; + protected int inAddr; + protected int inBit; + protected byte[] inBuf; + + public BitInput() { + inBuf = new byte[MAX_SIZE]; + } + + public void InitBitInput() { + inAddr = 0; + inBit = 0; + } + + public void addbits(int Bits) { + Bits += inBit; + inAddr += Bits >> 3; + inBit = Bits & 7; + } + + public int getbits() { +// int BitField=0; +// BitField|=(int)(inBuf[inAddr] << 16)&0xFF0000; +// BitField|=(int)(inBuf[inAddr+1] << 8)&0xff00; +// BitField|=(int)(inBuf[inAddr+2])&0xFF; +// BitField >>>= (8-inBit); +// return (BitField & 0xffff); + return (((((inBuf[inAddr] & 0xff) << 16) + + ((inBuf[inAddr + 1] & 0xff) << 8) + + ((inBuf[inAddr + 2] & 0xff))) >>> (8 - inBit)) & 0xffff); + } + + public void faddbits(int Bits) { + addbits(Bits); + } + + + public int fgetbits() { + return (getbits()); + } + + public boolean Overflow(int IncPtr) { + return (inAddr + IncPtr >= MAX_SIZE); + } + + public byte[] getInBuf() { + return inBuf; + } + + +} diff --git a/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unpack/vm/RarVM.java b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unpack/vm/RarVM.java new file mode 100755 index 0000000..56a3ccb --- /dev/null +++ b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unpack/vm/RarVM.java @@ -0,0 +1,1196 @@ +/* + * Copyright (c) 2007 innoSysTec (R) GmbH, Germany. All rights reserved. + * Original author: Edmund Wagner + * Creation date: 31.05.2007 + * + * Source: $HeadURL$ + * Last changed: $LastChangedDate$ + * + * the unrar licence applies to all junrar source and binary distributions + * you are not allowed to use this source to re-create the RAR compression algorithm + * + * Here some html entities which can be used for escaping javadoc tags: + * "&": "&" or "&" + * "<": "<" or "<" + * ">": ">" or ">" + * "@": "@" + */ +package org.fox.ttcomics2.junrar.unpack.vm; + +import org.fox.ttcomics2.junrar.crc.RarCRC; +import org.fox.ttcomics2.junrar.io.Raw; + +import java.util.List; +import java.util.Vector; + + +public class RarVM extends BitInput { + + public static final int VM_MEMSIZE = 0x40000; + + public static final int VM_MEMMASK = (VM_MEMSIZE - 1); + + public static final int VM_GLOBALMEMADDR = 0x3C000; + + public static final int VM_GLOBALMEMSIZE = 0x2000; + + public static final int VM_FIXEDGLOBALSIZE = 64; + + private static final int regCount = 8; + + private static final long UINT_MASK = 0xffffFFFF;//((long)2*(long)Integer.MAX_VALUE); + + private byte[] mem; + + private int[] R = new int[regCount]; + + private int flags; + + private int maxOpCount = 25000000; + + private int codeSize; + + private int IP; + + public RarVM() { + mem = null; + } + + public static int ReadData(BitInput rarVM) { + int data = rarVM.fgetbits(); + switch (data & 0xc000) { + case 0: + rarVM.faddbits(6); + return ((data >> 10) & 0xf); + case 0x4000: + if ((data & 0x3c00) == 0) { + data = 0xffffff00 | ((data >> 2) & 0xff); + rarVM.faddbits(14); + } else { + data = (data >> 6) & 0xff; + rarVM.faddbits(10); + } + return (data); + case 0x8000: + rarVM.faddbits(2); + data = rarVM.fgetbits(); + rarVM.faddbits(16); + return (data); + default: + rarVM.faddbits(2); + data = (rarVM.fgetbits() << 16); + rarVM.faddbits(16); + data |= rarVM.fgetbits(); + rarVM.faddbits(16); + return (data); + } + } + + public void init() { + if (mem == null) { + mem = new byte[VM_MEMSIZE + 4]; + } + } + + private boolean isVMMem(byte[] mem) { + return this.mem == mem; + } + + private int getValue(boolean byteMode, byte[] mem, int offset) { + if (byteMode) { + if (isVMMem(mem)) { + return (mem[offset]); + } else { + return (mem[offset] & 0xff); + } + } else { + if (isVMMem(mem)) { + //little + return Raw.readIntLittleEndian(mem, offset); + } else + //big endian + return Raw.readIntBigEndian(mem, offset); + } + } + + private void setValue(boolean byteMode, byte[] mem, int offset, int value) { + if (byteMode) { + if (isVMMem(mem)) { + mem[offset] = (byte) value; + } else { + mem[offset] = (byte) ((mem[offset] & 0x00) | (byte) (value & 0xff)); + } + } else { + if (isVMMem(mem)) { + Raw.writeIntLittleEndian(mem, offset, value); +// mem[offset + 0] = (byte) value; +// mem[offset + 1] = (byte) (value >>> 8); +// mem[offset + 2] = (byte) (value >>> 16); +// mem[offset + 3] = (byte) (value >>> 24); + } else { + Raw.writeIntBigEndian(mem, offset, value); +// mem[offset + 3] = (byte) value; +// mem[offset + 2] = (byte) (value >>> 8); +// mem[offset + 1] = (byte) (value >>> 16); +// mem[offset + 0] = (byte) (value >>> 24); + } + + } + // #define SET_VALUE(ByteMode,Addr,Value) SetValue(ByteMode,(uint + // *)Addr,Value) + } + + public void setLowEndianValue(byte[] mem, int offset, int value) { + Raw.writeIntLittleEndian(mem, offset, value); +// mem[offset + 0] = (byte) (value&0xff); +// mem[offset + 1] = (byte) ((value >>> 8)&0xff); +// mem[offset + 2] = (byte) ((value >>> 16)&0xff); +// mem[offset + 3] = (byte) ((value >>> 24)&0xff); + } + + public void setLowEndianValue(Vector mem, int offset, int value) { + mem.set(offset + 0, Byte.valueOf((byte) (value & 0xff))); + mem.set(offset + 1, Byte.valueOf((byte) ((value >>> 8) & 0xff))); + mem.set(offset + 2, Byte.valueOf((byte) ((value >>> 16) & 0xff))); + mem.set(offset + 3, Byte.valueOf((byte) ((value >>> 24) & 0xff))); + } + + private int getOperand(VMPreparedOperand cmdOp) { + int ret = 0; + if (cmdOp.getType() == VMOpType.VM_OPREGMEM) { + int pos = (cmdOp.getOffset() + cmdOp.getBase()) & VM_MEMMASK; + ret = Raw.readIntLittleEndian(mem, pos); + } else { + int pos = cmdOp.getOffset(); + ret = Raw.readIntLittleEndian(mem, pos); + } + return ret; + } + + public void execute(VMPreparedProgram prg) { + for (int i = 0; i < prg.getInitR().length; i++) // memcpy(R,Prg->InitR,sizeof(Prg->InitR)); + { + R[i] = prg.getInitR()[i]; + } + + long globalSize = Math + .min(prg.getGlobalData().size(), VM_GLOBALMEMSIZE) & 0xffFFffFF; + if (globalSize != 0) { + for (int i = 0; i < globalSize; i++) // memcpy(Mem+VM_GLOBALMEMADDR,&Prg->GlobalData[0],GlobalSize); + { + mem[VM_GLOBALMEMADDR + i] = prg.getGlobalData().get(i); + } + + } + long staticSize = Math.min(prg.getStaticData().size(), VM_GLOBALMEMSIZE + - globalSize) & 0xffFFffFF; + if (staticSize != 0) { + for (int i = 0; i < staticSize; i++) // memcpy(Mem+VM_GLOBALMEMADDR+GlobalSize,&Prg->StaticData[0],StaticSize); + { + mem[VM_GLOBALMEMADDR + (int) globalSize + i] = prg + .getStaticData().get(i); + } + + } + R[7] = VM_MEMSIZE; + flags = 0; + + List preparedCode = prg.getAltCmd().size() != 0 ? prg + .getAltCmd() + : prg.getCmd(); + + if (!ExecuteCode(preparedCode, prg.getCmdCount())) { + preparedCode.get(0).setOpCode(VMCommands.VM_RET); + } + int newBlockPos = getValue(false, mem, VM_GLOBALMEMADDR + 0x20) + & VM_MEMMASK; + int newBlockSize = getValue(false, mem, VM_GLOBALMEMADDR + 0x1c) + & VM_MEMMASK; + if ((newBlockPos + newBlockSize) >= VM_MEMSIZE) { + newBlockPos = 0; + newBlockSize = 0; + } + + prg.setFilteredDataOffset(newBlockPos); + prg.setFilteredDataSize(newBlockSize); + + prg.getGlobalData().clear(); + + int dataSize = Math.min(getValue(false, mem, VM_GLOBALMEMADDR + 0x30), + VM_GLOBALMEMSIZE - VM_FIXEDGLOBALSIZE); + if (dataSize != 0) { + prg.getGlobalData().setSize(dataSize + VM_FIXEDGLOBALSIZE); + // ->GlobalData.Add(dataSize+VM_FIXEDGLOBALSIZE); + + for (int i = 0; i < dataSize + VM_FIXEDGLOBALSIZE; i++) // memcpy(&Prg->GlobalData[0],&Mem[VM_GLOBALMEMADDR],DataSize+VM_FIXEDGLOBALSIZE); + { + prg.getGlobalData().set(i, mem[VM_GLOBALMEMADDR + i]); + } + } + } + + public byte[] getMem() { + return mem; + } + + private boolean setIP(int ip) { + if ((ip) >= codeSize) { + return (true); + } + + if (--maxOpCount <= 0) { + return (false); + } + + IP = ip; + return true; + } + + private boolean ExecuteCode(List preparedCode, + int cmdCount) { + + maxOpCount = 25000000; + this.codeSize = cmdCount; + this.IP = 0; + + while (true) { + VMPreparedCommand cmd = preparedCode.get(IP); + int op1 = getOperand(cmd.getOp1()); + int op2 = getOperand(cmd.getOp2()); + switch (cmd.getOpCode()) { + case VM_MOV: + setValue(cmd.isByteMode(), mem, op1, getValue(cmd.isByteMode(), + mem, op2)); // SET_VALUE(Cmd->ByteMode,Op1,GET_VALUE(Cmd->ByteMode,Op2)); + break; + case VM_MOVB: + setValue(true, mem, op1, getValue(true, mem, op2)); + break; + case VM_MOVD: + setValue(false, mem, op1, getValue(false, mem, op2)); + break; + + case VM_CMP: { + int value1 = getValue(cmd.isByteMode(), mem, op1); + int result = value1 - getValue(cmd.isByteMode(), mem, op2); + + if (result == 0) { + flags = VMFlags.VM_FZ.getFlag(); + } else { + flags = (result > value1) ? 1 : 0 | (result & VMFlags.VM_FS + .getFlag()); + } + } + break; + + case VM_CMPB: { + int value1 = getValue(true, mem, op1); + int result = value1 - getValue(true, mem, op2); + if (result == 0) { + flags = VMFlags.VM_FZ.getFlag(); + } else { + flags = (result > value1) ? 1 : 0 | (result & VMFlags.VM_FS + .getFlag()); + } + } + break; + case VM_CMPD: { + int value1 = getValue(false, mem, op1); + int result = value1 - getValue(false, mem, op2); + if (result == 0) { + flags = VMFlags.VM_FZ.getFlag(); + } else { + flags = (result > value1) ? 1 : 0 | (result & VMFlags.VM_FS + .getFlag()); + } + } + break; + + case VM_ADD: { + int value1 = getValue(cmd.isByteMode(), mem, op1); + int result = (int) ((((long) value1 + (long) getValue(cmd + .isByteMode(), mem, op2))) & 0xffffffff); + if (cmd.isByteMode()) { + result &= 0xff; + flags = (result < value1) ? 1 + : 0 | (result == 0 ? VMFlags.VM_FZ.getFlag() + : ((result & 0x80) != 0) ? VMFlags.VM_FS + .getFlag() : 0); + // Flags=(Result value1) ? 1 : 0 | (result & VMFlags.VM_FS + .getFlag()); + setValue(cmd.isByteMode(), mem, op1, result);// (Cmd->ByteMode,Op1,Result); + } + break; + + case VM_SUBB: + setValue(true, mem, op1, + (int) ((long) getValue(true, mem, op1) & 0xFFffFFff + - (long) getValue(true, mem, op2) & 0xFFffFFff)); + break; + case VM_SUBD: + setValue( + false, + mem, + op1, + (int) ((long) getValue(false, mem, op1) & 0xFFffFFff + - (long) getValue(false, mem, op2) & 0xFFffFFff)); + break; + + case VM_JZ: + if ((flags & VMFlags.VM_FZ.getFlag()) != 0) { + setIP(getValue(false, mem, op1)); + continue; + } + break; + case VM_JNZ: + if ((flags & VMFlags.VM_FZ.getFlag()) == 0) { + setIP(getValue(false, mem, op1)); + continue; + } + break; + case VM_INC: { + int result = (int) ((long) getValue(cmd.isByteMode(), mem, op1) & 0xFFffFFff + 1); + if (cmd.isByteMode()) { + result &= 0xff; + } + + setValue(cmd.isByteMode(), mem, op1, result); + flags = result == 0 ? VMFlags.VM_FZ.getFlag() : result + & VMFlags.VM_FS.getFlag(); + } + break; + + case VM_INCB: + setValue( + true, + mem, + op1, + (int) ((long) getValue(true, mem, op1) & 0xFFffFFff + 1)); + break; + case VM_INCD: + setValue(false, mem, op1, (int) ((long) getValue(false, mem, + op1) & 0xFFffFFff + 1)); + break; + + case VM_DEC: { + int result = (int) ((long) getValue(cmd.isByteMode(), mem, op1) & 0xFFffFFff - 1); + setValue(cmd.isByteMode(), mem, op1, result); + flags = result == 0 ? VMFlags.VM_FZ.getFlag() : result + & VMFlags.VM_FS.getFlag(); + } + break; + + case VM_DECB: + setValue( + true, + mem, + op1, + (int) ((long) getValue(true, mem, op1) & 0xFFffFFff - 1)); + break; + case VM_DECD: + setValue(false, mem, op1, (int) ((long) getValue(false, mem, + op1) & 0xFFffFFff - 1)); + break; + + case VM_JMP: + setIP(getValue(false, mem, op1)); + continue; + case VM_XOR: { + int result = getValue(cmd.isByteMode(), mem, op1) + ^ getValue(cmd.isByteMode(), mem, op2); + flags = result == 0 ? VMFlags.VM_FZ.getFlag() : result + & VMFlags.VM_FS.getFlag(); + setValue(cmd.isByteMode(), mem, op1, result); + } + break; + case VM_AND: { + int result = getValue(cmd.isByteMode(), mem, op1) + & getValue(cmd.isByteMode(), mem, op2); + flags = result == 0 ? VMFlags.VM_FZ.getFlag() : result + & VMFlags.VM_FS.getFlag(); + setValue(cmd.isByteMode(), mem, op1, result); + } + break; + case VM_OR: { + int result = getValue(cmd.isByteMode(), mem, op1) + | getValue(cmd.isByteMode(), mem, op2); + flags = result == 0 ? VMFlags.VM_FZ.getFlag() : result + & VMFlags.VM_FS.getFlag(); + setValue(cmd.isByteMode(), mem, op1, result); + } + break; + case VM_TEST: { + int result = getValue(cmd.isByteMode(), mem, op1) + & getValue(cmd.isByteMode(), mem, op2); + flags = result == 0 ? VMFlags.VM_FZ.getFlag() : result + & VMFlags.VM_FS.getFlag(); + } + break; + case VM_JS: + if ((flags & VMFlags.VM_FS.getFlag()) != 0) { + setIP(getValue(false, mem, op1)); + continue; + } + break; + case VM_JNS: + if ((flags & VMFlags.VM_FS.getFlag()) == 0) { + setIP(getValue(false, mem, op1)); + continue; + } + break; + case VM_JB: + if ((flags & VMFlags.VM_FC.getFlag()) != 0) { + setIP(getValue(false, mem, op1)); + continue; + } + break; + case VM_JBE: + if ((flags & (VMFlags.VM_FC.getFlag() | VMFlags.VM_FZ.getFlag())) != 0) { + setIP(getValue(false, mem, op1)); + continue; + } + break; + case VM_JA: + if ((flags & (VMFlags.VM_FC.getFlag() | VMFlags.VM_FZ.getFlag())) == 0) { + setIP(getValue(false, mem, op1)); + continue; + } + break; + case VM_JAE: + if ((flags & VMFlags.VM_FC.getFlag()) == 0) { + setIP(getValue(false, mem, op1)); + continue; + } + break; + case VM_PUSH: + R[7] -= 4; + setValue(false, mem, R[7] & VM_MEMMASK, getValue(false, mem, + op1)); + break; + case VM_POP: + setValue(false, mem, op1, getValue(false, mem, R[7] + & VM_MEMMASK)); + R[7] += 4; + break; + case VM_CALL: + R[7] -= 4; + setValue(false, mem, R[7] & VM_MEMMASK, IP + 1); + setIP(getValue(false, mem, op1)); + continue; + case VM_NOT: + setValue(cmd.isByteMode(), mem, op1, ~getValue( + cmd.isByteMode(), mem, op1)); + break; + case VM_SHL: { + int value1 = getValue(cmd.isByteMode(), mem, op1); + int value2 = getValue(cmd.isByteMode(), mem, op2); + int result = value1 << value2; + flags = (result == 0 ? VMFlags.VM_FZ.getFlag() + : (result & VMFlags.VM_FS.getFlag())) + | (((value1 << (value2 - 1)) & 0x80000000) != 0 ? VMFlags.VM_FC + .getFlag() + : 0); + setValue(cmd.isByteMode(), mem, op1, result); + } + break; + case VM_SHR: { + int value1 = getValue(cmd.isByteMode(), mem, op1); + int value2 = getValue(cmd.isByteMode(), mem, op2); + int result = value1 >>> value2; + flags = (result == 0 ? VMFlags.VM_FZ.getFlag() + : (result & VMFlags.VM_FS.getFlag())) + | ((value1 >>> (value2 - 1)) & VMFlags.VM_FC.getFlag()); + setValue(cmd.isByteMode(), mem, op1, result); + } + break; + case VM_SAR: { + int value1 = getValue(cmd.isByteMode(), mem, op1); + int value2 = getValue(cmd.isByteMode(), mem, op2); + int result = value1 >> value2; + flags = (result == 0 ? VMFlags.VM_FZ.getFlag() + : (result & VMFlags.VM_FS.getFlag())) + | ((value1 >> (value2 - 1)) & VMFlags.VM_FC.getFlag()); + setValue(cmd.isByteMode(), mem, op1, result); + } + break; + case VM_NEG: { + int result = -getValue(cmd.isByteMode(), mem, op1); + flags = result == 0 ? VMFlags.VM_FZ.getFlag() : VMFlags.VM_FC + .getFlag() + | (result & VMFlags.VM_FS.getFlag()); + setValue(cmd.isByteMode(), mem, op1, result); + } + break; + + case VM_NEGB: + setValue(true, mem, op1, -getValue(true, mem, op1)); + break; + case VM_NEGD: + setValue(false, mem, op1, -getValue(false, mem, op1)); + break; + case VM_PUSHA: { + for (int i = 0, SP = R[7] - 4; i < regCount; i++, SP -= 4) { + setValue(false, mem, SP & VM_MEMMASK, R[i]); + } + R[7] -= regCount * 4; + } + break; + case VM_POPA: { + for (int i = 0, SP = R[7]; i < regCount; i++, SP += 4) + R[7 - i] = getValue(false, mem, SP & VM_MEMMASK); + } + break; + case VM_PUSHF: + R[7] -= 4; + setValue(false, mem, R[7] & VM_MEMMASK, flags); + break; + case VM_POPF: + flags = getValue(false, mem, R[7] & VM_MEMMASK); + R[7] += 4; + break; + case VM_MOVZX: + setValue(false, mem, op1, getValue(true, mem, op2)); + break; + case VM_MOVSX: + setValue(false, mem, op1, (byte) getValue(true, mem, op2)); + break; + case VM_XCHG: { + int value1 = getValue(cmd.isByteMode(), mem, op1); + setValue(cmd.isByteMode(), mem, op1, getValue(cmd.isByteMode(), + mem, op2)); + setValue(cmd.isByteMode(), mem, op2, value1); + } + break; + case VM_MUL: { + int result = (int) (((long) getValue(cmd.isByteMode(), mem, op1) + & 0xFFffFFff + * (long) getValue(cmd.isByteMode(), mem, op2) & 0xFFffFFff) & 0xFFffFFff); + setValue(cmd.isByteMode(), mem, op1, result); + } + break; + case VM_DIV: { + int divider = getValue(cmd.isByteMode(), mem, op2); + if (divider != 0) { + int result = getValue(cmd.isByteMode(), mem, op1) / divider; + setValue(cmd.isByteMode(), mem, op1, result); + } + } + break; + case VM_ADC: { + int value1 = getValue(cmd.isByteMode(), mem, op1); + int FC = (flags & VMFlags.VM_FC.getFlag()); + int result = (int) ((long) value1 & 0xFFffFFff + + (long) getValue(cmd.isByteMode(), mem, op2) + & 0xFFffFFff + (long) FC & 0xFFffFFff); + if (cmd.isByteMode()) { + result &= 0xff; + } + + flags = (result < value1 || result == value1 && FC != 0) ? 1 + : 0 | (result == 0 ? VMFlags.VM_FZ.getFlag() + : (result & VMFlags.VM_FS.getFlag())); + setValue(cmd.isByteMode(), mem, op1, result); + } + break; + case VM_SBB: { + int value1 = getValue(cmd.isByteMode(), mem, op1); + int FC = (flags & VMFlags.VM_FC.getFlag()); + int result = (int) ((long) value1 & 0xFFffFFff + - (long) getValue(cmd.isByteMode(), mem, op2) + & 0xFFffFFff - (long) FC & 0xFFffFFff); + if (cmd.isByteMode()) { + result &= 0xff; + } + flags = (result > value1 || result == value1 && FC != 0) ? 1 + : 0 | (result == 0 ? VMFlags.VM_FZ.getFlag() + : (result & VMFlags.VM_FS.getFlag())); + setValue(cmd.isByteMode(), mem, op1, result); + } + break; + + case VM_RET: + if (R[7] >= VM_MEMSIZE) { + return (true); + } + setIP(getValue(false, mem, R[7] & VM_MEMMASK)); + R[7] += 4; + continue; + + case VM_STANDARD: + ExecuteStandardFilter(VMStandardFilters.findFilter(cmd.getOp1() + .getData())); + break; + case VM_PRINT: + break; + } + IP++; + --maxOpCount; + } + } + + public void prepare(byte[] code, int codeSize, VMPreparedProgram prg) { + InitBitInput(); + int cpLength = Math.min(MAX_SIZE, codeSize); + for (int i = 0; i < cpLength; i++) // memcpy(inBuf,Code,Min(CodeSize,BitInput::MAX_SIZE)); + { + inBuf[i] |= code[i]; + } + + byte xorSum = 0; + for (int i = 1; i < codeSize; i++) { + xorSum ^= code[i]; + } + + faddbits(8); + + prg.setCmdCount(0); + if (xorSum == code[0]) { + VMStandardFilters filterType = IsStandardFilter(code, codeSize); + if (filterType != VMStandardFilters.VMSF_NONE) { + + VMPreparedCommand curCmd = new VMPreparedCommand(); + curCmd.setOpCode(VMCommands.VM_STANDARD); + curCmd.getOp1().setData(filterType.getFilter()); + curCmd.getOp1().setType(VMOpType.VM_OPNONE); + curCmd.getOp2().setType(VMOpType.VM_OPNONE); + codeSize = 0; + prg.getCmd().add(curCmd); + prg.setCmdCount(prg.getCmdCount() + 1); + // TODO + // curCmd->Op1.Data=FilterType; + // >>>>>> CurCmd->Op1.Addr=&CurCmd->Op1.Data; <<<<<<<<<< not set + // do i need to ? + // >>>>>> CurCmd->Op2.Addr=&CurCmd->Op2.Data; <<<<<<<<<< " + // CurCmd->Op1.Type=CurCmd->Op2.Type=VM_OPNONE; + // CodeSize=0; + } + int dataFlag = fgetbits(); + faddbits(1); + + // Read static data contained in DB operators. This data cannot be + // changed, + // it is a part of VM code, not a filter parameter. + + if ((dataFlag & 0x8000) != 0) { + long dataSize = (long) ReadData(this) & 0xffFFffFF + 1; + for (int i = 0; inAddr < codeSize && i < dataSize; i++) { + prg.getStaticData().add( + Byte.valueOf((byte) (fgetbits() >> 8))); + faddbits(8); + } + } + + while (inAddr < codeSize) { + VMPreparedCommand curCmd = new VMPreparedCommand(); + int data = fgetbits(); + if ((data & 0x8000) == 0) { + curCmd.setOpCode(VMCommands.findVMCommand((data >> 12))); + faddbits(4); + } else { + curCmd.setOpCode(VMCommands + .findVMCommand((data >> 10) - 24)); + faddbits(6); + } + if ((VMCmdFlags.VM_CmdFlags[curCmd.getOpCode().getVMCommand()] & VMCmdFlags.VMCF_BYTEMODE) != 0) { + curCmd.setByteMode((fgetbits() >> 15) == 1); + faddbits(1); + } else { + curCmd.setByteMode(false); + } + curCmd.getOp1().setType(VMOpType.VM_OPNONE); + curCmd.getOp2().setType(VMOpType.VM_OPNONE); + + int opNum = (VMCmdFlags.VM_CmdFlags[curCmd.getOpCode() + .getVMCommand()] & VMCmdFlags.VMCF_OPMASK); + // TODO >>> CurCmd->Op1.Addr=CurCmd->Op2.Addr=NULL; << 0) { + decodeArg(curCmd.getOp1(), curCmd.isByteMode()); + if (opNum == 2) + decodeArg(curCmd.getOp2(), curCmd.isByteMode()); + else { + if (curCmd.getOp1().getType() == VMOpType.VM_OPINT + && (VMCmdFlags.VM_CmdFlags[curCmd.getOpCode() + .getVMCommand()] & (VMCmdFlags.VMCF_JUMP | VMCmdFlags.VMCF_PROC)) != 0) { + int distance = curCmd.getOp1().getData(); + if (distance >= 256) + distance -= 256; + else { + if (distance >= 136) { + distance -= 264; + } else { + if (distance >= 16) { + distance -= 8; + } else { + if (distance >= 8) { + distance -= 16; + } + } + } + distance += prg.getCmdCount(); + } + curCmd.getOp1().setData(distance); + } + } + } + prg.setCmdCount(prg.getCmdCount() + 1); + prg.getCmd().add(curCmd); + } + } + VMPreparedCommand curCmd = new VMPreparedCommand(); + curCmd.setOpCode(VMCommands.VM_RET); + // TODO CurCmd->Op1.Addr=&CurCmd->Op1.Data; + // CurCmd->Op2.Addr=&CurCmd->Op2.Data; + curCmd.getOp1().setType(VMOpType.VM_OPNONE); + curCmd.getOp2().setType(VMOpType.VM_OPNONE); + + // for (int i=0;iCmd[I]; + // if (Cmd->Op1.Addr==NULL) + // Cmd->Op1.Addr=&Cmd->Op1.Data; + // if (Cmd->Op2.Addr==NULL) + // Cmd->Op2.Addr=&Cmd->Op2.Data; + // } + + prg.getCmd().add(curCmd); + prg.setCmdCount(prg.getCmdCount() + 1); + // #ifdef VM_OPTIMIZE + if (codeSize != 0) { + optimize(prg); + } + } + + private void decodeArg(VMPreparedOperand op, boolean byteMode) { + int data = fgetbits(); + if ((data & 0x8000) != 0) { + op.setType(VMOpType.VM_OPREG); + op.setData((data >> 12) & 7); + op.setOffset(op.getData()); + faddbits(4); + } else { + if ((data & 0xc000) == 0) { + op.setType(VMOpType.VM_OPINT); + if (byteMode) { + op.setData((data >> 6) & 0xff); + faddbits(10); + } else { + faddbits(2); + op.setData(ReadData(this)); + } + } else { + op.setType(VMOpType.VM_OPREGMEM); + if ((data & 0x2000) == 0) { + op.setData((data >> 10) & 7); + op.setOffset(op.getData()); + op.setBase(0); + faddbits(6); + } else { + if ((data & 0x1000) == 0) { + op.setData((data >> 9) & 7); + op.setOffset(op.getData()); + faddbits(7); + } else { + op.setData(0); + faddbits(4); + } + op.setBase(ReadData(this)); + } + } + } + + } + + private void optimize(VMPreparedProgram prg) { + List commands = prg.getCmd(); + + for (VMPreparedCommand cmd : commands) { + switch (cmd.getOpCode()) { + case VM_MOV: + cmd.setOpCode(cmd.isByteMode() ? VMCommands.VM_MOVB + : VMCommands.VM_MOVD); + continue; + case VM_CMP: + cmd.setOpCode(cmd.isByteMode() ? VMCommands.VM_CMPB + : VMCommands.VM_CMPD); + continue; + } + if ((VMCmdFlags.VM_CmdFlags[cmd.getOpCode().getVMCommand()] & VMCmdFlags.VMCF_CHFLAGS) == 0) { + continue; + } + boolean flagsRequired = false; + + for (int i = commands.indexOf(cmd) + 1; i < commands.size(); i++) { + int flags = VMCmdFlags.VM_CmdFlags[commands.get(i).getOpCode() + .getVMCommand()]; + if ((flags & (VMCmdFlags.VMCF_JUMP | VMCmdFlags.VMCF_PROC | VMCmdFlags.VMCF_USEFLAGS)) != 0) { + flagsRequired = true; + break; + } + if ((flags & VMCmdFlags.VMCF_CHFLAGS) != 0) { + break; + } + } + if (flagsRequired) { + continue; + } + switch (cmd.getOpCode()) { + case VM_ADD: + cmd.setOpCode(cmd.isByteMode() ? VMCommands.VM_ADDB + : VMCommands.VM_ADDD); + continue; + case VM_SUB: + cmd.setOpCode(cmd.isByteMode() ? VMCommands.VM_SUBB + : VMCommands.VM_SUBD); + continue; + case VM_INC: + cmd.setOpCode(cmd.isByteMode() ? VMCommands.VM_INCB + : VMCommands.VM_INCD); + continue; + case VM_DEC: + cmd.setOpCode(cmd.isByteMode() ? VMCommands.VM_DECB + : VMCommands.VM_DECD); + continue; + case VM_NEG: + cmd.setOpCode(cmd.isByteMode() ? VMCommands.VM_NEGB + : VMCommands.VM_NEGD); + continue; + } + } + + } + + private VMStandardFilters IsStandardFilter(byte[] code, int codeSize) { + VMStandardFilterSignature stdList[] = { + new VMStandardFilterSignature(53, 0xad576887, VMStandardFilters.VMSF_E8), + new VMStandardFilterSignature(57, 0x3cd7e57e, VMStandardFilters.VMSF_E8E9), + new VMStandardFilterSignature(120, 0x3769893f, VMStandardFilters.VMSF_ITANIUM), + new VMStandardFilterSignature(29, 0x0e06077d, VMStandardFilters.VMSF_DELTA), + new VMStandardFilterSignature(149, 0x1c2c5dc8, VMStandardFilters.VMSF_RGB), + new VMStandardFilterSignature(216, 0xbc85e701, VMStandardFilters.VMSF_AUDIO), + new VMStandardFilterSignature(40, 0x46b9c560, VMStandardFilters.VMSF_UPCASE) + }; + int CodeCRC = RarCRC.checkCrc(0xffffffff, code, 0, code.length) ^ 0xffffffff; + for (int i = 0; i < stdList.length; i++) { + if (stdList[i].getCRC() == CodeCRC && stdList[i].getLength() == code.length) { + return (stdList[i].getType()); + } + + } + return (VMStandardFilters.VMSF_NONE); + } + + private void ExecuteStandardFilter(VMStandardFilters filterType) { + switch (filterType) { + case VMSF_E8: + case VMSF_E8E9: { + int dataSize = R[4]; + long fileOffset = R[6] & 0xFFffFFff; + + if (dataSize >= VM_GLOBALMEMADDR) { + break; + } + int fileSize = 0x1000000; + byte cmpByte2 = (byte) ((filterType == VMStandardFilters.VMSF_E8E9) ? 0xe9 : 0xe8); + for (int curPos = 0; curPos < dataSize - 4; ) { + byte curByte = mem[curPos++]; + if (curByte == 0xe8 || curByte == cmpByte2) { +// #ifdef PRESENT_INT32 +// sint32 Offset=CurPos+FileOffset; +// sint32 Addr=GET_VALUE(false,Data); +// if (Addr<0) +// { +// if (Addr+Offset>=0) +// SET_VALUE(false,Data,Addr+FileSize); +// } +// else +// if (Addr= VM_GLOBALMEMADDR) { + break; + } + int curPos = 0; + final byte Masks[] = {4, 4, 6, 6, 0, 0, 7, 7, 4, 4, 0, 0, 4, 4, 0, 0}; + fileOffset >>>= 4; + + while (curPos < dataSize - 21) { + int Byte = (mem[curPos] & 0x1f) - 0x10; + if (Byte >= 0) { + + byte cmdMask = Masks[Byte]; + if (cmdMask != 0) + for (int i = 0; i <= 2; i++) + if ((cmdMask & (1 << i)) != 0) { + int startPos = i * 41 + 5; + int opType = filterItanium_GetBits(curPos, startPos + 37, 4); + if (opType == 5) { + int offset = filterItanium_GetBits(curPos, startPos + 13, 20); + filterItanium_SetBits(curPos, (int) (offset - fileOffset) & 0xfffff, startPos + 13, 20); + } + } + } + curPos += 16; + fileOffset++; + } + } + break; + case VMSF_DELTA: { + int dataSize = R[4] & 0xFFffFFff; + int channels = R[0] & 0xFFffFFff; + int srcPos = 0; + int border = (dataSize * 2) & 0xFFffFFff; + setValue(false, mem, VM_GLOBALMEMADDR + 0x20, dataSize); + if (dataSize >= VM_GLOBALMEMADDR / 2) { + break; + } +// bytes from same channels are grouped to continual data blocks, +// so we need to place them back to their interleaving positions + + for (int curChannel = 0; curChannel < channels; curChannel++) { + byte PrevByte = 0; + for (int destPos = dataSize + curChannel; destPos < border; destPos += channels) { + mem[destPos] = (PrevByte -= mem[srcPos++]); + } + + } + } + break; + case VMSF_RGB: { + // byte *SrcData=Mem,*DestData=SrcData+DataSize; + int dataSize = R[4], width = R[0] - 3, posR = R[1]; + int channels = 3; + int srcPos = 0; + int destDataPos = dataSize; + setValue(false, mem, VM_GLOBALMEMADDR + 0x20, dataSize); + if (dataSize >= VM_GLOBALMEMADDR / 2 || posR < 0) { + break; + } + for (int curChannel = 0; curChannel < channels; curChannel++) { + long prevByte = 0; + + for (int i = curChannel; i < dataSize; i += channels) { + long predicted; + int upperPos = i - width; + if (upperPos >= 3) { + int upperDataPos = destDataPos + upperPos; + int upperByte = mem[upperDataPos] & 0xff; + int upperLeftByte = mem[upperDataPos - 3] & 0xff; + predicted = prevByte + upperByte - upperLeftByte; + int pa = Math.abs((int) (predicted - prevByte)); + int pb = Math.abs((int) (predicted - upperByte)); + int pc = Math.abs((int) (predicted - upperLeftByte)); + if (pa <= pb && pa <= pc) { + predicted = prevByte; + } else { + if (pb <= pc) { + predicted = upperByte; + } else { + predicted = upperLeftByte; + } + } + } else { + predicted = prevByte; + } + + prevByte = (predicted - mem[srcPos++] & 0xff) & 0xff; + mem[destDataPos + i] = (byte) (prevByte & 0xff); + + } + } + for (int i = posR, border = dataSize - 2; i < border; i += 3) { + byte G = mem[destDataPos + i + 1]; + mem[destDataPos + i] += G; + mem[destDataPos + i + 2] += G; + } + } + break; + case VMSF_AUDIO: { + int dataSize = R[4], channels = R[0]; + int srcPos = 0; + int destDataPos = dataSize; + //byte *SrcData=Mem,*DestData=SrcData+DataSize; + setValue(false, mem, VM_GLOBALMEMADDR + 0x20, dataSize); + if (dataSize >= VM_GLOBALMEMADDR / 2) { + break; + } + for (int curChannel = 0; curChannel < channels; curChannel++) { + long prevByte = 0; + long prevDelta = 0; + long Dif[] = new long[7]; + int D1 = 0, D2 = 0, D3; + int K1 = 0, K2 = 0, K3 = 0; + + for (int i = curChannel, byteCount = 0; i < dataSize; i += channels, byteCount++) { + D3 = D2; + D2 = (int) prevDelta - D1; + D1 = (int) prevDelta; + + long predicted = 8 * prevByte + K1 * D1 + K2 * D2 + K3 * D3; + predicted = (predicted >>> 3) & 0xff; + + long curByte = mem[srcPos++] & 0xff; + + predicted = (predicted - curByte) & UINT_MASK; + mem[destDataPos + i] = (byte) predicted; + prevDelta = (byte) (predicted - prevByte); + prevByte = predicted; + + int D = ((byte) curByte) << 3; + + Dif[0] += Math.abs(D); + Dif[1] += Math.abs(D - D1); + Dif[2] += Math.abs(D + D1); + Dif[3] += Math.abs(D - D2); + Dif[4] += Math.abs(D + D2); + Dif[5] += Math.abs(D - D3); + Dif[6] += Math.abs(D + D3); + + if ((byteCount & 0x1f) == 0) { + long minDif = Dif[0], numMinDif = 0; + Dif[0] = 0; + for (int j = 1; j < Dif.length; j++) { + if (Dif[j] < minDif) { + minDif = Dif[j]; + numMinDif = j; + } + Dif[j] = 0; + } + switch ((int) numMinDif) { + case 1: + if (K1 >= -16) K1--; + break; + case 2: + if (K1 < 16) K1++; + break; + case 3: + if (K2 >= -16) K2--; + break; + case 4: + if (K2 < 16) K2++; + break; + case 5: + if (K3 >= -16) K3--; + break; + case 6: + if (K3 < 16) K3++; + break; + } + } + } + } + } + break; + case VMSF_UPCASE: { + int dataSize = R[4], srcPos = 0, destPos = dataSize; + if (dataSize >= VM_GLOBALMEMADDR / 2) { + break; + } + while (srcPos < dataSize) { + byte curByte = mem[srcPos++]; + if (curByte == 2 && (curByte = mem[srcPos++]) != 2) { + curByte -= 32; + } + mem[destPos++] = curByte; + } + setValue(false, mem, VM_GLOBALMEMADDR + 0x1c, destPos - dataSize); + setValue(false, mem, VM_GLOBALMEMADDR + 0x20, dataSize); + } + break; + } + + } + + private void filterItanium_SetBits(int curPos, int bitField, int bitPos, int bitCount) { + int inAddr = bitPos / 8; + int inBit = bitPos & 7; + int andMask = 0xffffffff >>> (32 - bitCount); + andMask = ~(andMask << inBit); + + bitField <<= inBit; + + for (int i = 0; i < 4; i++) { + mem[curPos + inAddr + i] &= andMask; + mem[curPos + inAddr + i] |= bitField; + andMask = (andMask >>> 8) | 0xff000000; + bitField >>>= 8; + } + + } + + private int filterItanium_GetBits(int curPos, int bitPos, int bitCount) { + int inAddr = bitPos / 8; + int inBit = bitPos & 7; + int bitField = mem[curPos + inAddr++] & 0xff; + bitField |= (mem[curPos + inAddr++] & 0xff) << 8; + bitField |= (mem[curPos + inAddr++] & 0xff) << 16; + bitField |= (mem[curPos + inAddr] & 0xff) << 24; + bitField >>>= inBit; + return (bitField & (0xffffffff >>> (32 - bitCount))); + } + + + public void setMemory(int pos, byte[] data, int offset, int dataSize) { + if (pos < VM_MEMSIZE) { //&& data!=Mem+Pos) + //memmove(Mem+Pos,Data,Min(DataSize,VM_MEMSIZE-Pos)); + for (int i = 0; i < Math.min(data.length - offset, dataSize); i++) { + if ((VM_MEMSIZE - pos) < i) { + break; + } + mem[pos + i] = data[offset + i]; + } + } + } + + +} + +// \ No newline at end of file diff --git a/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unpack/vm/VMCmdFlags.java b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unpack/vm/VMCmdFlags.java new file mode 100644 index 0000000..75f1ecb --- /dev/null +++ b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unpack/vm/VMCmdFlags.java @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2007 innoSysTec (R) GmbH, Germany. All rights reserved. + * Original author: Edmund Wagner + * Creation date: 01.06.2007 + * + * Source: $HeadURL$ + * Last changed: $LastChangedDate$ + * + * the unrar licence applies to all junrar source and binary distributions + * you are not allowed to use this source to re-create the RAR compression algorithm + * + * Here some html entities which can be used for escaping javadoc tags: + * "&": "&" or "&" + * "<": "<" or "<" + * ">": ">" or ">" + * "@": "@" + */ +package org.fox.ttcomics2.junrar.unpack.vm; + +public class VMCmdFlags { + public static final byte VMCF_OP0 = 0; + public static final byte VMCF_OP1 = 1; + public static final byte VMCF_OP2 = 2; + public static final byte VMCF_OPMASK = 3; + public static final byte VMCF_BYTEMODE = 4; + public static final byte VMCF_JUMP = 8; + public static final byte VMCF_PROC = 16; + public static final byte VMCF_USEFLAGS = 32; + public static final byte VMCF_CHFLAGS = 64; + + public static byte VM_CmdFlags[] = + { + /* VM_MOV */ VMCF_OP2 | VMCF_BYTEMODE, + /* VM_CMP */ VMCF_OP2 | VMCF_BYTEMODE | VMCF_CHFLAGS, + /* VM_ADD */ VMCF_OP2 | VMCF_BYTEMODE | VMCF_CHFLAGS, + /* VM_SUB */ VMCF_OP2 | VMCF_BYTEMODE | VMCF_CHFLAGS, + /* VM_JZ */ VMCF_OP1 | VMCF_JUMP | VMCF_USEFLAGS, + /* VM_JNZ */ VMCF_OP1 | VMCF_JUMP | VMCF_USEFLAGS, + /* VM_INC */ VMCF_OP1 | VMCF_BYTEMODE | VMCF_CHFLAGS, + /* VM_DEC */ VMCF_OP1 | VMCF_BYTEMODE | VMCF_CHFLAGS, + /* VM_JMP */ VMCF_OP1 | VMCF_JUMP, + /* VM_XOR */ VMCF_OP2 | VMCF_BYTEMODE | VMCF_CHFLAGS, + /* VM_AND */ VMCF_OP2 | VMCF_BYTEMODE | VMCF_CHFLAGS, + /* VM_OR */ VMCF_OP2 | VMCF_BYTEMODE | VMCF_CHFLAGS, + /* VM_TEST */ VMCF_OP2 | VMCF_BYTEMODE | VMCF_CHFLAGS, + /* VM_JS */ VMCF_OP1 | VMCF_JUMP | VMCF_USEFLAGS, + /* VM_JNS */ VMCF_OP1 | VMCF_JUMP | VMCF_USEFLAGS, + /* VM_JB */ VMCF_OP1 | VMCF_JUMP | VMCF_USEFLAGS, + /* VM_JBE */ VMCF_OP1 | VMCF_JUMP | VMCF_USEFLAGS, + /* VM_JA */ VMCF_OP1 | VMCF_JUMP | VMCF_USEFLAGS, + /* VM_JAE */ VMCF_OP1 | VMCF_JUMP | VMCF_USEFLAGS, + /* VM_PUSH */ VMCF_OP1, + /* VM_POP */ VMCF_OP1, + /* VM_CALL */ VMCF_OP1 | VMCF_PROC, + /* VM_RET */ VMCF_OP0 | VMCF_PROC, + /* VM_NOT */ VMCF_OP1 | VMCF_BYTEMODE, + /* VM_SHL */ VMCF_OP2 | VMCF_BYTEMODE | VMCF_CHFLAGS, + /* VM_SHR */ VMCF_OP2 | VMCF_BYTEMODE | VMCF_CHFLAGS, + /* VM_SAR */ VMCF_OP2 | VMCF_BYTEMODE | VMCF_CHFLAGS, + /* VM_NEG */ VMCF_OP1 | VMCF_BYTEMODE | VMCF_CHFLAGS, + /* VM_PUSHA */ VMCF_OP0, + /* VM_POPA */ VMCF_OP0, + /* VM_PUSHF */ VMCF_OP0 | VMCF_USEFLAGS, + /* VM_POPF */ VMCF_OP0 | VMCF_CHFLAGS, + /* VM_MOVZX */ VMCF_OP2, + /* VM_MOVSX */ VMCF_OP2, + /* VM_XCHG */ VMCF_OP2 | VMCF_BYTEMODE, + /* VM_MUL */ VMCF_OP2 | VMCF_BYTEMODE, + /* VM_DIV */ VMCF_OP2 | VMCF_BYTEMODE, + /* VM_ADC */ VMCF_OP2 | VMCF_BYTEMODE | VMCF_USEFLAGS | VMCF_CHFLAGS, + /* VM_SBB */ VMCF_OP2 | VMCF_BYTEMODE | VMCF_USEFLAGS | VMCF_CHFLAGS, + /* VM_PRINT */ VMCF_OP0 + }; + +} diff --git a/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unpack/vm/VMCommands.java b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unpack/vm/VMCommands.java new file mode 100644 index 0000000..d635c7d --- /dev/null +++ b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unpack/vm/VMCommands.java @@ -0,0 +1,220 @@ +/* + * Copyright (c) 2007 innoSysTec (R) GmbH, Germany. All rights reserved. + * Original author: Edmund Wagner + * Creation date: 31.05.2007 + * + * Source: $HeadURL$ + * Last changed: $LastChangedDate$ + * + * the unrar licence applies to all junrar source and binary distributions + * you are not allowed to use this source to re-create the RAR compression algorithm + * + * Here some html entities which can be used for escaping javadoc tags: + * "&": "&" or "&" + * "<": "<" or "<" + * ">": ">" or ">" + * "@": "@" + */ +package org.fox.ttcomics2.junrar.unpack.vm; + +public enum VMCommands { + VM_MOV(0), VM_CMP(1), VM_ADD(2), VM_SUB(3), VM_JZ(4), VM_JNZ(5), VM_INC(6), VM_DEC( + 7), VM_JMP(8), VM_XOR(9), VM_AND(10), VM_OR(11), VM_TEST(12), VM_JS( + 13), VM_JNS(14), VM_JB(15), VM_JBE(16), VM_JA(17), VM_JAE(18), VM_PUSH( + 19), VM_POP(20), VM_CALL(21), VM_RET(22), VM_NOT(23), VM_SHL(24), VM_SHR( + 25), VM_SAR(26), VM_NEG(27), VM_PUSHA(28), VM_POPA(29), VM_PUSHF(30), VM_POPF( + 31), VM_MOVZX(32), VM_MOVSX(33), VM_XCHG(34), VM_MUL(35), VM_DIV(36), VM_ADC( + 37), VM_SBB(38), VM_PRINT(39), + + // #ifdef VM_OPTIMIZE + VM_MOVB(40), VM_MOVD(41), VM_CMPB(42), VM_CMPD(43), + + VM_ADDB(44), VM_ADDD(45), VM_SUBB(46), VM_SUBD(47), VM_INCB(48), VM_INCD(49), VM_DECB( + 50), VM_DECD(51), VM_NEGB(52), VM_NEGD(53), + // #endif*/ + + VM_STANDARD(54); + + private int vmCommand; + + VMCommands(int vmCommand) { + this.vmCommand = vmCommand; + } + + public static VMCommands findVMCommand(int vmCommand) { + if (VM_MOV.equals(vmCommand)) { + return VM_MOV; + } + if (VM_CMP.equals(vmCommand)) { + return VM_CMP; + } + if (VM_ADD.equals(vmCommand)) { + return VM_ADD; + } + if (VM_SUB.equals(vmCommand)) { + return VM_SUB; + } + if (VM_JZ.equals(vmCommand)) { + return VM_JZ; + } + if (VM_JNZ.equals(vmCommand)) { + return VM_JNZ; + } + if (VM_INC.equals(vmCommand)) { + return VM_INC; + } + if (VM_DEC.equals(vmCommand)) { + return VM_DEC; + } + if (VM_JMP.equals(vmCommand)) { + return VM_JMP; + } + if (VM_XOR.equals(vmCommand)) { + return VM_XOR; + } + if (VM_AND.equals(vmCommand)) { + return VM_AND; + } + if (VM_OR.equals(vmCommand)) { + return VM_OR; + } + if (VM_TEST.equals(vmCommand)) { + return VM_TEST; + } + if (VM_JS.equals(vmCommand)) { + return VM_JS; + } + if (VM_JNS.equals(vmCommand)) { + return VM_JNS; + } + if (VM_JB.equals(vmCommand)) { + return VM_JB; + } + if (VM_JBE.equals(vmCommand)) { + return VM_JBE; + } + if (VM_JA.equals(vmCommand)) { + return VM_JA; + } + if (VM_JAE.equals(vmCommand)) { + return VM_JAE; + } + if (VM_PUSH.equals(vmCommand)) { + return VM_PUSH; + } + if (VM_POP.equals(vmCommand)) { + return VM_POP; + } + if (VM_CALL.equals(vmCommand)) { + return VM_CALL; + } + if (VM_RET.equals(vmCommand)) { + return VM_RET; + } + if (VM_NOT.equals(vmCommand)) { + return VM_NOT; + } + if (VM_SHL.equals(vmCommand)) { + return VM_SHL; + } + if (VM_SHR.equals(vmCommand)) { + return VM_SHR; + } + if (VM_SAR.equals(vmCommand)) { + return VM_SAR; + } + if (VM_NEG.equals(vmCommand)) { + return VM_NEG; + } + if (VM_PUSHA.equals(vmCommand)) { + return VM_PUSHA; + } + if (VM_POPA.equals(vmCommand)) { + return VM_POPA; + } + if (VM_PUSHF.equals(vmCommand)) { + return VM_PUSHF; + } + if (VM_POPF.equals(vmCommand)) { + return VM_POPF; + } + if (VM_MOVZX.equals(vmCommand)) { + return VM_MOVZX; + } + if (VM_MOVSX.equals(vmCommand)) { + return VM_MOVSX; + } + if (VM_XCHG.equals(vmCommand)) { + return VM_XCHG; + } + if (VM_MUL.equals(vmCommand)) { + return VM_MUL; + } + if (VM_DIV.equals(vmCommand)) { + return VM_DIV; + } + if (VM_ADC.equals(vmCommand)) { + return VM_ADC; + } + if (VM_SBB.equals(vmCommand)) { + return VM_SBB; + } + if (VM_PRINT.equals(vmCommand)) { + return VM_PRINT; + } + if (VM_MOVB.equals(vmCommand)) { + return VM_MOVB; + } + if (VM_MOVD.equals(vmCommand)) { + return VM_MOVD; + } + if (VM_CMPB.equals(vmCommand)) { + return VM_CMPB; + } + if (VM_CMPD.equals(vmCommand)) { + return VM_CMPD; + } + if (VM_ADDB.equals(vmCommand)) { + return VM_ADDB; + } + if (VM_ADDD.equals(vmCommand)) { + return VM_ADDD; + } + if (VM_SUBB.equals(vmCommand)) { + return VM_SUBB; + } + if (VM_SUBD.equals(vmCommand)) { + return VM_SUBD; + } + if (VM_INCB.equals(vmCommand)) { + return VM_INCB; + } + if (VM_INCD.equals(vmCommand)) { + return VM_INCD; + } + if (VM_DECB.equals(vmCommand)) { + return VM_DECB; + } + if (VM_DECD.equals(vmCommand)) { + return VM_DECD; + } + if (VM_NEGB.equals(vmCommand)) { + return VM_NEGB; + } + if (VM_NEGD.equals(vmCommand)) { + return VM_NEGD; + } + if (VM_STANDARD.equals(vmCommand)) { + return VM_STANDARD; + } + return null; + } + + public int getVMCommand() { + return vmCommand; + } + + public boolean equals(int vmCommand) { + return this.vmCommand == vmCommand; + } +} diff --git a/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unpack/vm/VMFlags.java b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unpack/vm/VMFlags.java new file mode 100644 index 0000000..d64813c --- /dev/null +++ b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unpack/vm/VMFlags.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2007 innoSysTec (R) GmbH, Germany. All rights reserved. + * Original author: Edmund Wagner + * Creation date: 31.05.2007 + * + * Source: $HeadURL$ + * Last changed: $LastChangedDate$ + * + * the unrar licence applies to all junrar source and binary distributions + * you are not allowed to use this source to re-create the RAR compression algorithm + * + * Here some html entities which can be used for escaping javadoc tags: + * "&": "&" or "&" + * "<": "<" or "<" + * ">": ">" or ">" + * "@": "@" + */ +package org.fox.ttcomics2.junrar.unpack.vm; + +public enum VMFlags { + VM_FC(1), + VM_FZ(2), + VM_FS(0x80000000); + + private int flag; + + VMFlags(int flag) { + this.flag = flag; + } + + public static VMFlags findFlag(int flag) { + if (VM_FC.equals(flag)) { + return VM_FC; + } + if (VM_FS.equals(flag)) { + return VM_FS; + } + if (VM_FZ.equals(flag)) { + return VM_FZ; + } + return null; + } + + public boolean equals(int flag) { + return this.flag == flag; + } + + public int getFlag() { + return flag; + } + +} diff --git a/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unpack/vm/VMOpType.java b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unpack/vm/VMOpType.java new file mode 100644 index 0000000..b5ebd87 --- /dev/null +++ b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unpack/vm/VMOpType.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2007 innoSysTec (R) GmbH, Germany. All rights reserved. + * Original author: Edmund Wagner + * Creation date: 31.05.2007 + * + * Source: $HeadURL$ + * Last changed: $LastChangedDate$ + * + * the unrar licence applies to all junrar source and binary distributions + * you are not allowed to use this source to re-create the RAR compression algorithm + * + * Here some html entities which can be used for escaping javadoc tags: + * "&": "&" or "&" + * "<": "<" or "<" + * ">": ">" or ">" + * "@": "@" + */ +package org.fox.ttcomics2.junrar.unpack.vm; + +public enum VMOpType { + VM_OPREG(0), + VM_OPINT(1), + VM_OPREGMEM(2), + VM_OPNONE(3); + + private int opType; + + VMOpType(int opType) { + this.opType = opType; + } + + public static VMOpType findOpType(int opType) { + + if (VM_OPREG.equals(opType)) { + return VM_OPREG; + } + + + if (VM_OPINT.equals(opType)) { + return VM_OPINT; + } + + if (VM_OPREGMEM.equals(opType)) { + return VM_OPREGMEM; + } + + if (VM_OPNONE.equals(opType)) { + return VM_OPNONE; + } + return null; + } + + public int getOpType() { + return opType; + } + + public boolean equals(int opType) { + return this.opType == opType; + } +} diff --git a/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unpack/vm/VMPreparedCommand.java b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unpack/vm/VMPreparedCommand.java new file mode 100644 index 0000000..3c93cac --- /dev/null +++ b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unpack/vm/VMPreparedCommand.java @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2007 innoSysTec (R) GmbH, Germany. All rights reserved. + * Original author: Edmund Wagner + * Creation date: 31.05.2007 + * + * Source: $HeadURL$ + * Last changed: $LastChangedDate$ + * + * the unrar licence applies to all junrar source and binary distributions + * you are not allowed to use this source to re-create the RAR compression algorithm + * + * Here some html entities which can be used for escaping javadoc tags: + * "&": "&" or "&" + * "<": "<" or "<" + * ">": ">" or ">" + * "@": "@" + */ +package org.fox.ttcomics2.junrar.unpack.vm; + +public class VMPreparedCommand { + private VMCommands OpCode; + private boolean ByteMode; + private VMPreparedOperand Op1 = new VMPreparedOperand(); + private VMPreparedOperand Op2 = new VMPreparedOperand(); + + public boolean isByteMode() { + return ByteMode; + } + + public void setByteMode(boolean byteMode) { + ByteMode = byteMode; + } + + public VMPreparedOperand getOp1() { + return Op1; + } + + public void setOp1(VMPreparedOperand op1) { + Op1 = op1; + } + + public VMPreparedOperand getOp2() { + return Op2; + } + + public void setOp2(VMPreparedOperand op2) { + Op2 = op2; + } + + public VMCommands getOpCode() { + return OpCode; + } + + public void setOpCode(VMCommands opCode) { + OpCode = opCode; + } + +} diff --git a/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unpack/vm/VMPreparedOperand.java b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unpack/vm/VMPreparedOperand.java new file mode 100644 index 0000000..fde02c7 --- /dev/null +++ b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unpack/vm/VMPreparedOperand.java @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2007 innoSysTec (R) GmbH, Germany. All rights reserved. + * Original author: Edmund Wagner + * Creation date: 31.05.2007 + * + * Source: $HeadURL$ + * Last changed: $LastChangedDate$ + * + * the unrar licence applies to all junrar source and binary distributions + * you are not allowed to use this source to re-create the RAR compression algorithm + * + * Here some html entities which can be used for escaping javadoc tags: + * "&": "&" or "&" + * "<": "<" or "<" + * ">": ">" or ">" + * "@": "@" + */ +package org.fox.ttcomics2.junrar.unpack.vm; + +public class VMPreparedOperand { + private VMOpType Type; + private int Data; + private int Base; + private int offset; + + + public int getBase() { + return Base; + } + + public void setBase(int base) { + Base = base; + } + + public int getData() { + return Data; + } + + public void setData(int data) { + Data = data; + } + + public VMOpType getType() { + return Type; + } + + public void setType(VMOpType type) { + Type = type; + } + + public int getOffset() { + return offset; + } + + public void setOffset(int offset) { + this.offset = offset; + } + +} diff --git a/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unpack/vm/VMPreparedProgram.java b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unpack/vm/VMPreparedProgram.java new file mode 100644 index 0000000..b47ba3d --- /dev/null +++ b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unpack/vm/VMPreparedProgram.java @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2007 innoSysTec (R) GmbH, Germany. All rights reserved. + * Original author: Edmund Wagner + * Creation date: 31.05.2007 + * + * Source: $HeadURL$ + * Last changed: $LastChangedDate$ + * + * the unrar licence applies to all junrar source and binary distributions + * you are not allowed to use this source to re-create the RAR compression algorithm + * + * Here some html entities which can be used for escaping javadoc tags: + * "&": "&" or "&" + * "<": "<" or "<" + * ">": ">" or ">" + * "@": "@" + */ +package org.fox.ttcomics2.junrar.unpack.vm; + +import java.util.ArrayList; +import java.util.List; +import java.util.Vector; + +public class VMPreparedProgram { + private List Cmd = new ArrayList(); + private List AltCmd = new ArrayList(); + private int CmdCount; + + + private Vector GlobalData = new Vector(); + private Vector StaticData = new Vector(); // static data contained in DB operators + private int InitR[] = new int[7]; + + private int FilteredDataOffset; + private int FilteredDataSize; + + public VMPreparedProgram() { + AltCmd = null; + } + + + public List getAltCmd() { + return AltCmd; + } + + + public void setAltCmd(List altCmd) { + AltCmd = altCmd; + } + + + public List getCmd() { + return Cmd; + } + + public void setCmd(List cmd) { + Cmd = cmd; + } + + public int getCmdCount() { + return CmdCount; + } + + public void setCmdCount(int cmdCount) { + CmdCount = cmdCount; + } + + + public int getFilteredDataOffset() { + return FilteredDataOffset; + } + + + public void setFilteredDataOffset(int filteredDataOffset) { + FilteredDataOffset = filteredDataOffset; + } + + + public int getFilteredDataSize() { + return FilteredDataSize; + } + + public void setFilteredDataSize(int filteredDataSize) { + FilteredDataSize = filteredDataSize; + } + + public Vector getGlobalData() { + return GlobalData; + } + + public void setGlobalData(Vector globalData) { + GlobalData = globalData; + } + + public int[] getInitR() { + return InitR; + } + + public void setInitR(int[] initR) { + InitR = initR; + } + + public Vector getStaticData() { + return StaticData; + } + + public void setStaticData(Vector staticData) { + StaticData = staticData; + } + + +} diff --git a/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unpack/vm/VMStandardFilterSignature.java b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unpack/vm/VMStandardFilterSignature.java new file mode 100644 index 0000000..f1264de --- /dev/null +++ b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unpack/vm/VMStandardFilterSignature.java @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2007 innoSysTec (R) GmbH, Germany. All rights reserved. + * Original author: Edmund Wagner + * Creation date: 04.06.2007 + * + * Source: $HeadURL$ + * Last changed: $LastChangedDate$ + * + * the unrar licence applies to all junrar source and binary distributions + * you are not allowed to use this source to re-create the RAR compression algorithm + * + * Here some html entities which can be used for escaping javadoc tags: + * "&": "&" or "&" + * "<": "<" or "<" + * ">": ">" or ">" + * "@": "@" + */ +package org.fox.ttcomics2.junrar.unpack.vm; + +public class VMStandardFilterSignature { + private int length; + + private int CRC; + + private VMStandardFilters type; + + public VMStandardFilterSignature(int length, int crc, VMStandardFilters type) { + super(); + this.length = length; + CRC = crc; + this.type = type; + } + + public int getCRC() { + return CRC; + } + + public void setCRC(int crc) { + CRC = crc; + } + + public int getLength() { + return length; + } + + public void setLength(int length) { + this.length = length; + } + + public VMStandardFilters getType() { + return type; + } + + public void setType(VMStandardFilters type) { + this.type = type; + } + +} diff --git a/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unpack/vm/VMStandardFilters.java b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unpack/vm/VMStandardFilters.java new file mode 100644 index 0000000..543d4f6 --- /dev/null +++ b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unpack/vm/VMStandardFilters.java @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2007 innoSysTec (R) GmbH, Germany. All rights reserved. + * Original author: Edmund Wagner + * Creation date: 31.05.2007 + * + * Source: $HeadURL$ + * Last changed: $LastChangedDate$ + * + * the unrar licence applies to all junrar source and binary distributions + * you are not allowed to use this source to re-create the RAR compression algorithm + * + * Here some html entities which can be used for escaping javadoc tags: + * "&": "&" or "&" + * "<": "<" or "<" + * ">": ">" or ">" + * "@": "@" + */ +package org.fox.ttcomics2.junrar.unpack.vm; + +public enum VMStandardFilters { + VMSF_NONE(0), + VMSF_E8(1), + VMSF_E8E9(2), + VMSF_ITANIUM(3), + VMSF_RGB(4), + VMSF_AUDIO(5), + VMSF_DELTA(6), + VMSF_UPCASE(7); + + private int filter; + + VMStandardFilters(int filter) { + this.filter = filter; + } + + public static VMStandardFilters findFilter(int filter) { + if (VMSF_NONE.equals(filter)) { + return VMSF_NONE; + } + + if (VMSF_E8.equals(filter)) { + return VMSF_E8; + } + + if (VMSF_E8E9.equals(filter)) { + return VMSF_E8E9; + } + if (VMSF_ITANIUM.equals(filter)) { + return VMSF_ITANIUM; + } + + if (VMSF_RGB.equals(filter)) { + return VMSF_RGB; + } + + if (VMSF_AUDIO.equals(filter)) { + return VMSF_AUDIO; + } + if (VMSF_DELTA.equals(filter)) { + return VMSF_DELTA; + } + return null; + } + + public int getFilter() { + return filter; + } + + public boolean equals(int filter) { + return this.filter == filter; + } + +} diff --git a/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unsigned/UnsignedByte.java b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unsigned/UnsignedByte.java new file mode 100644 index 0000000..06f1d9b --- /dev/null +++ b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unsigned/UnsignedByte.java @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2007 innoSysTec (R) GmbH, Germany. All rights reserved. + * Original author: Edmund Wagner + * Creation date: 04.06.2007 + * + * Source: $HeadURL$ + * Last changed: $LastChangedDate$ + * + * + * the unrar licence applies to all junrar source and binary distributions + * you are not allowed to use this source to re-create the RAR compression algorithm + * + * Here some html entities which can be used for escaping javadoc tags: + * "&": "&" or "&" + * "<": "<" or "<" + * ">": ">" or ">" + * "@": "@" + */ +package org.fox.ttcomics2.junrar.unsigned; + +public class UnsignedByte { + + public static byte longToByte(long unsignedByte1) { + return (byte) (unsignedByte1 & 0xff); + } + + public static byte intToByte(int unsignedByte1) { + return (byte) (unsignedByte1 & 0xff); + } + + public static byte shortToByte(short unsignedByte1) { + return (byte) (unsignedByte1 & 0xff); + } + + + public static short add(byte unsignedByte1, byte unsignedByte2) { + return (short) (unsignedByte1 + unsignedByte2); + } + + public static short sub(byte unsignedByte1, byte unsignedByte2) { + + return (short) (unsignedByte1 - unsignedByte2); + } + + + public static void main(String[] args) { + //tests unsigned (signed) + //add + System.out.println(add((byte) 0xfe, (byte) 0x01)); //255 (-1) + System.out.println(add((byte) 0xff, (byte) 0x01)); //0 (0) + System.out.println(add((byte) 0x7f, (byte) 0x01)); //128 (-128) + System.out.println(add((byte) 0xff, (byte) 0xff)); //254 (-2) + + //sub + System.out.println(sub((byte) 0xfe, (byte) 0x01)); //253 (-3) + System.out.println(sub((byte) 0x00, (byte) 0x01)); //255 (-1) + System.out.println(sub((byte) 0x80, (byte) 0x01)); //127 (127) + //mul + System.out.println((byte) -1 * (byte) -1); + } +} diff --git a/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unsigned/UnsignedInteger.java b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unsigned/UnsignedInteger.java new file mode 100644 index 0000000..4674b74 --- /dev/null +++ b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unsigned/UnsignedInteger.java @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2007 innoSysTec (R) GmbH, Germany. All rights reserved. + * Original author: Edmund Wagner + * Creation date: 04.06.2007 + * + * Source: $HeadURL$ + * Last changed: $LastChangedDate$ + * + * + * the unrar licence applies to all junrar source and binary distributions + * you are not allowed to use this source to re-create the RAR compression algorithm + * + * Here some html entities which can be used for escaping javadoc tags: + * "&": "&" or "&" + * "<": "<" or "<" + * ">": ">" or ">" + * "@": "@" + */ +package org.fox.ttcomics2.junrar.unsigned; + +public class UnsignedInteger { + +} diff --git a/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unsigned/UnsignedLong.java b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unsigned/UnsignedLong.java new file mode 100644 index 0000000..e421287 --- /dev/null +++ b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unsigned/UnsignedLong.java @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2007 innoSysTec (R) GmbH, Germany. All rights reserved. + * Original author: Edmund Wagner + * Creation date: 04.06.2007 + * + * Source: $HeadURL$ + * Last changed: $LastChangedDate$ + * + * + * the unrar licence applies to all junrar source and binary distributions + * you are not allowed to use this source to re-create the RAR compression algorithm + * + * Here some html entities which can be used for escaping javadoc tags: + * "&": "&" or "&" + * "<": "<" or "<" + * ">": ">" or ">" + * "@": "@" + */ +package org.fox.ttcomics2.junrar.unsigned; + +public class UnsignedLong { + +} diff --git a/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unsigned/UnsignedShort.java b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unsigned/UnsignedShort.java new file mode 100644 index 0000000..e9a7820 --- /dev/null +++ b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/unsigned/UnsignedShort.java @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2007 innoSysTec (R) GmbH, Germany. All rights reserved. + * Original author: Edmund Wagner + * Creation date: 04.06.2007 + * + * Source: $HeadURL$ + * Last changed: $LastChangedDate$ + * + * + * the unrar licence applies to all junrar source and binary distributions + * you are not allowed to use this source to re-create the RAR compression algorithm + * + * Here some html entities which can be used for escaping javadoc tags: + * "&": "&" or "&" + * "<": "<" or "<" + * ">": ">" or ">" + * "@": "@" + */ +package org.fox.ttcomics2.junrar.unsigned; + +public class UnsignedShort { + +} diff --git a/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/util/VolumeHelper.java b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/util/VolumeHelper.java new file mode 100644 index 0000000..a22ccff --- /dev/null +++ b/org.fox.ttcomics/src/main/java/org/fox/ttcomics2/junrar/util/VolumeHelper.java @@ -0,0 +1,97 @@ +package org.fox.ttcomics2.junrar.util; + +public class VolumeHelper { + private VolumeHelper() { + } + + // public static boolean mergeArchive(Archive archive, ComprDataIO dataIO) + // throws IOException { + // FileHeader hd = dataIO.getSubHeader(); + // if (hd.getUnpVersion() >= 20 && hd.getFileCRC() != 0xffffffff + // && dataIO.getPackedCRC() != ~hd.getFileCRC()) { + // System.err.println("Data Bad CRC"); + // } + // + // boolean oldNumbering = !archive.getMainHeader().isNewNumbering() + // || archive.isOldFormat(); + // String nextName = nextVolumeName(archive.getFile().getAbsolutePath(), + // oldNumbering); + // File nextVolume = new File(nextName); + // UnrarCallback callback = archive.getUnrarCallback(); + // if ((callback != null) && !callback.isNextVolumeReady(nextVolume)) { + // return false; + // } + // if (!nextVolume.exists()) { + // return false; + // } + // archive.setFile(nextVolume); + // hd = archive.nextFileHeader(); + // if (hd == null) { + // return false; + // } + // dataIO.init(hd); + // return true; + // } + + public static String nextVolumeName(String arcName, boolean oldNumbering) { + if (!oldNumbering) { + // part1.rar, part2.rar, ... + int len = arcName.length(); + int indexR = len - 1; + while ((indexR >= 0) && !isDigit(arcName.charAt(indexR))) { + indexR--; + } + int index = indexR + 1; + int indexL = indexR - 1; + while ((indexL >= 0) && isDigit(arcName.charAt(indexL))) { + indexL--; + } + if (indexL < 0) { + return null; + } + indexL++; + StringBuilder buffer = new StringBuilder(len); + buffer.append(arcName, 0, indexL); + char[] digits = new char[indexR - indexL + 1]; + arcName.getChars(indexL, indexR + 1, digits, 0); + indexR = digits.length - 1; + while ((indexR >= 0) && (++digits[indexR]) == '9' + 1) { + digits[indexR] = '0'; + indexR--; + } + if (indexR < 0) { + buffer.append('1'); + } + buffer.append(digits); + buffer.append(arcName, index, len); + return buffer.toString(); + } else { + // .rar, .r00, .r01, ... + int len = arcName.length(); + if ((len <= 4) || (arcName.charAt(len - 4) != '.')) { + return null; + } + StringBuilder buffer = new StringBuilder(); + int off = len - 3; + buffer.append(arcName, 0, off); + if (!isDigit(arcName.charAt(off + 1)) + || !isDigit(arcName.charAt(off + 2))) { + buffer.append("r00"); + } else { + char[] ext = new char[3]; + arcName.getChars(off, len, ext, 0); + int i = ext.length - 1; + while ((++ext[i]) == '9' + 1) { + ext[i] = '0'; + i--; + } + buffer.append(ext); + } + return buffer.toString(); + } + } + + private static boolean isDigit(char c) { + return (c >= '0') && (c <= '9'); + } +} -- cgit v1.2.3