kerry001 发表于 2013-1-28 18:49:37

unrar/Archive.java

/* * 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: * &quot;&amp;&quot;:&quot;&&quot; or &quot;&amp;amp;&quot; * &quot;&lt;&quot;:&quot;<&quot; or &quot;&amp;lt;&quot; * &quot;&gt;&quot;:&quot;>&quot; or &quot;&amp;gt;&quot; * &quot;@&quot;:&quot;@&quot; */package de.innosystec.unrar;import java.io.Closeable;import java.io.File;import java.io.IOException;import java.io.OutputStream;import java.util.ArrayList;import java.util.List;import java.util.logging.Level;import java.util.logging.Logger;import de.innosystec.unrar.exception.RarException;import de.innosystec.unrar.exception.RarException.RarExceptionType;import de.innosystec.unrar.io.IReadOnlyAccess;import de.innosystec.unrar.io.ReadOnlyAccessFile;import de.innosystec.unrar.rarfile.AVHeader;import de.innosystec.unrar.rarfile.BaseBlock;import de.innosystec.unrar.rarfile.BlockHeader;import de.innosystec.unrar.rarfile.CommentHeader;import de.innosystec.unrar.rarfile.EAHeader;import de.innosystec.unrar.rarfile.EndArcHeader;import de.innosystec.unrar.rarfile.FileHeader;import de.innosystec.unrar.rarfile.MacInfoHeader;import de.innosystec.unrar.rarfile.MainHeader;import de.innosystec.unrar.rarfile.MarkHeader;import de.innosystec.unrar.rarfile.ProtectHeader;import de.innosystec.unrar.rarfile.SignHeader;import de.innosystec.unrar.rarfile.SubBlockHeader;import de.innosystec.unrar.rarfile.UnixOwnersHeader;import de.innosystec.unrar.rarfile.UnrarHeadertype;import de.innosystec.unrar.unpack.ComprDataIO;import de.innosystec.unrar.unpack.Unpack;/** * DOCUMENT ME * * @author $LastChangedBy$ * @version $LastChangedRevision$ */public class Archive implements Closeable {      private static Logger logger = Logger.getLogger(Archive.class.getName());    private File file;    private IReadOnlyAccess rof;    private final UnrarCallback unrarCallback;    private final ComprDataIO dataIO;    private final List&lt;BaseBlock&gt; headers = new ArrayList&lt;BaseBlock&gt;();    private MarkHeader markHead = null;    private MainHeader newMhd = null;      private EndArcHeader endHeader = null;      private Unpack unpack;    /** Archive data CRC. */    private long arcDataCRC = 0xffffffff;    private int currentHeaderIndex;    private boolean encrypted = false;    private int sfxSize = 0;    /** Size of packed data in current file. */    private long totalPackedSize = 0L;    /** Number of bytes of compressed data read from current file. */    private long totalPackedRead = 0L;    public Archive(File file) throws RarException, IOException {      this(file, null);    }    /**   * create a new archive object using the given file   * @param file the file to extract   * @throws RarException   */    public Archive(File file, UnrarCallback unrarCallback)            throws RarException, IOException {      setFile(file);      this.unrarCallback = unrarCallback;      dataIO = new ComprDataIO(this);    }    public File getFile() {      return file;    }    void setFile(File file) throws IOException {      this.file = file;      totalPackedSize = 0L;      totalPackedRead = 0L;      close();      rof = new ReadOnlyAccessFile(file);      try {            readHeaders();      }      catch (Exception e) {            logger.log(Level.WARNING,                  &quot;exception in archive constructor maybe file is encrypted &quot; +                  &quot;or currupt&quot;, 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 &gt; 0) {            totalPackedRead += count;            if (unrarCallback != null) {                unrarCallback.volumeProgressChanged(totalPackedRead,                        totalPackedSize);            }      }    }    public IReadOnlyAccess getRof() {      return rof;    }      /** * @return returns all file headers of the archive */public List&lt;FileHeader&gt; getFileHeaders(){List&lt;FileHeader&gt; list = new ArrayList&lt;FileHeader&gt;();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 &lt; n) {            BaseBlock block = headers.get(currentHeaderIndex++);            if (block.getHeaderType() == UnrarHeadertype.FileHeader) {                return (FileHeader)block;            }      }      return null;    }    public UnrarCallback getUnrarCallback() {      return unrarCallback;    }    /**   *   * @return whether the archive is encrypted   */    public boolean isEncrypted() {      if(newMhd!=null){            return newMhd.isEncrypted();      }else{            throw new NullPointerException(&quot;mainheader is null&quot;);      }    }      /**   * Read the headers of the archive   * @throws RarException   */    private void readHeaders() throws IOException, RarException{      markHead = null;      newMhd = null;      endHeader = null;      headers.clear();      currentHeaderIndex = 0;      int toRead = 0;                long fileLength = this.file.length();      while(true){            int size = 0;            long newpos = 0;            byte[] baseBlockBuffer =new byte;                        long position = rof.getPosition();                        // Weird, but is trying to read beyond the end of the file            if (position &gt;= fileLength) {            break;            }            //            logger.info(&quot;\n--------reading header--------&quot;);            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(                              RarException.RarExceptionType.badRarArchive);                  }                  headers.add(markHead);//                  markHead.print();                  break;                                    case MainHeader:                  int mainHeaderSize = 0;                  toRead = block.hasEncryptVersion() ?                            MainHeader.mainHeaderSizeWithEnc :                            MainHeader.mainHeaderSize;                  byte[] mainbuff = new byte;                  mainHeaderSize = 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:                  int signHeaderSize = 0;                  toRead = SignHeader.signHeaderSize;                  byte[] signBuff = new byte;                  signHeaderSize = rof.readFully(signBuff, toRead);                  SignHeader signHead = new SignHeader(block,signBuff);                  headers.add(signHead);//                  logger.info(&quot;HeaderType: SignHeader&quot;);                                        break;                                    case AvHeader:                  int avHeaderSize = 0;                  toRead = AVHeader.avHeaderSize;                  byte[] avBuff = new byte;                  avHeaderSize = rof.readFully(avBuff, toRead);                  AVHeader avHead = new AVHeader(block,avBuff);                  headers.add(avHead);//                  logger.info(&quot;headertype: AVHeader&quot;);                  break;                                    case CommHeader:                  int commHeaderSize = 0;                  toRead = CommentHeader.commentHeaderSize;                  byte[] commBuff = new byte;                  commHeaderSize = rof.readFully(commBuff, toRead);                  CommentHeader commHead = new CommentHeader(block,commBuff);                  headers.add(commHead);//                  logger.info(&quot;method: &quot;+commHead.getUnpMethod()+&quot;; 0x&quot;+//                            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 &gt; 0){                        int endArcHeaderSize = 0;                        byte[] endArchBuff = new byte;                        endArcHeaderSize = rof.readFully(endArchBuff, toRead);                        endArcHead = new EndArcHeader(block,endArchBuff);//                        logger.info(&quot;HeaderType: endarch\ndatacrc:&quot;+//                              endArcHead.getArchiveDataCRC());                  }else{//                        logger.info(&quot;HeaderType: endarch - no Data&quot;);                        endArcHead = new EndArcHeader(block,null);                  }                  headers.add(endArcHead);                  this.endHeader = endArcHead;//                  logger.info(&quot;\n--------end header--------&quot;);                  return;                                    default:                  byte[] blockHeaderBuffer =                            new byte;                  int bhsize = 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;                            int fhsize = rof.readFully(fileHeaderBuffer,                                    toRead);                                                      FileHeader fh = new FileHeader(blockHead,                                    fileHeaderBuffer);//                            if (DEBUG) {//                              fh.print();//                            }                            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;                            int phsize = rof.readFully(protectHeaderBuffer,                                    toRead);                            ProtectHeader ph = new ProtectHeader(blockHead,                                    protectHeaderBuffer);                            //                            logger.info(&quot;totalblocks&quot;+ph.getTotalBlocks());                            newpos = ph.getPositionInFile() +                                    ph.getHeaderSize();                            rof.setPosition(newpos);                            break;                                                    case SubHeader:{byte[] subHeadbuffer = new byte;int subheadersize = rof.readFully(subHeadbuffer, SubBlockHeader.SubBlockHeaderSize);SubBlockHeader subHead = new SubBlockHeader(blockHead,subHeadbuffer);subHead.print();switch (subHead.getSubType()) {case MAC_HEAD:{byte[] macHeaderbuffer = new byte;int macheadersize = rof.readFully(macHeaderbuffer, MacInfoHeader.MacInfoHeaderSize);MacInfoHeader macHeader = new MacInfoHeader(subHead,macHeaderbuffer);macHeader.print();headers.add(macHeader);break;}//TODO implement other subheaderscase BEEA_HEAD:break;case EA_HEAD:{byte[] eaHeaderBuffer = new byte;int 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;int uoHeaderSize = rof.readFully(uoHeaderBuffer, toRead);UnixOwnersHeader uoHeader = new UnixOwnersHeader(subHead,uoHeaderBuffer);uoHeader.print();headers.add(uoHeader);break;default:break;}break;}                        default:                            logger.warning(&quot;Unknown Header&quot;);                            throw new RarException(                                    RarExceptionType.notRarArchive);                                                }            }//            logger.info(&quot;\n--------end header--------&quot;);      }    }    /**   * Extract the file specified by the given header and write it   * to the supplied output stream   *   * @param header the header to be extracted   * @param os the outputstream   * @throws RarException   */    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);            }      }    }    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);            }      }    }      /**   * @return returns the main header of this archive   */    public MainHeader getMainHeader() {      return newMhd;    }      /**   * @return whether the archive is old format   */    public boolean isOldFormat() {      return markHead.isOldFormat();    }    /** Close the underlying compressed file. */    public void close() throws IOException {      if (rof != null) {            rof.close();            rof = null;      }    }}
URL:http://svn.atlassian.com/svn/public/atlassian/vendor/java-unrar/trunk/src/main/java/de/innosystec/unrar/Archive.java
页: [1]
查看完整版本: unrar/Archive.java