六狼论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

新浪微博账号登陆

只需一步,快速开始

搜索
查看: 105|回复: 0

unrar/Archive.java

[复制链接]

升级  68%

8

主题

8

主题

8

主题

童生

Rank: 1

积分
34
 楼主| 发表于 2013-1-15 02:27:36 | 显示全部楼层 |阅读模式
/* * 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 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<BaseBlock> headers = new ArrayList<BaseBlock>();    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,                    "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;    }        /** * @return returns all file headers of the archive */public List<FileHeader> getFileHeaders(){List<FileHeader> list = new ArrayList<FileHeader>();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;    }    /**     *     * @return whether the archive is encrypted     */    public boolean isEncrypted() {        if(newMhd!=null){            return newMhd.isEncrypted();        }else{            throw new NullPointerException("mainheader is null");        }    }        /**     * 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[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(                                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[toRead];                    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[toRead];                    signHeaderSize = rof.readFully(signBuff, toRead);                    SignHeader signHead = new SignHeader(block,signBuff);                    headers.add(signHead);//                    logger.info("HeaderType: SignHeader");                                        break;                                    case AvHeader:                    int avHeaderSize = 0;                    toRead = AVHeader.avHeaderSize;                    byte[] avBuff = new byte[toRead];                    avHeaderSize = rof.readFully(avBuff, toRead);                    AVHeader avHead = new AVHeader(block,avBuff);                    headers.add(avHead);//                    logger.info("headertype: AVHeader");                    break;                                    case CommHeader:                    int commHeaderSize = 0;                    toRead = CommentHeader.commentHeaderSize;                    byte[] commBuff = new byte[toRead];                    commHeaderSize = 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){                        int endArcHeaderSize = 0;                        byte[] endArchBuff = new byte[toRead];                        endArcHeaderSize = 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);                    this.endHeader = endArcHead;//                    logger.info("\n--------end header--------");                    return;                                    default:                    byte[] blockHeaderBuffer =                            new byte[BlockHeader.blockHeaderSize];                    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[toRead];                            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[toRead];                            int phsize = rof.readFully(protectHeaderBuffer,                                    toRead);                            ProtectHeader ph = new ProtectHeader(blockHead,                                    protectHeaderBuffer);                            //                            logger.info("totalblocks"+ph.getTotalBlocks());                            newpos = ph.getPositionInFile() +                                    ph.getHeaderSize();                            rof.setPosition(newpos);                            break;                                                    case SubHeader:{byte[] subHeadbuffer = new byte[SubBlockHeader.SubBlockHeaderSize];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[MacInfoHeader.MacInfoHeaderSize];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[EAHeader.EAHeaderSize];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[toRead];int uoHeaderSize = 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--------");        }    }    /**     * 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
您需要登录后才可以回帖 登录 | 立即注册 新浪微博账号登陆

本版积分规则

快速回复 返回顶部 返回列表