99 lines
2.3 KiB
C++
99 lines
2.3 KiB
C++
#include <stdio.h>
|
|
#include "rar.hpp"
|
|
|
|
#include "unrar.h"
|
|
|
|
Archive::Archive() : Raw( this )
|
|
{
|
|
Format=RARFMT15;
|
|
Solid=false;
|
|
|
|
CurBlockPos=0;
|
|
NextBlockPos=0;
|
|
|
|
memset(&MainHead,0,sizeof(MainHead));
|
|
memset(&EndArcHead,0,sizeof(EndArcHead));
|
|
|
|
HeaderCRC=0;
|
|
}
|
|
|
|
RARFORMAT Archive::IsSignature(const byte *D,size_t Size)
|
|
{
|
|
RARFORMAT Type=RARFMT_NONE;
|
|
if (Size>=1 && D[0]==0x52)
|
|
{
|
|
#ifndef SFX_MODULE
|
|
if (Size>=4 && D[1]==0x45 && D[2]==0x7e && D[3]==0x5e)
|
|
Type=RARFMT14;
|
|
else
|
|
#endif
|
|
if (Size>=7 && D[1]==0x61 && D[2]==0x72 && D[3]==0x21 && D[4]==0x1a && D[5]==0x07)
|
|
{
|
|
// We check for non-zero last signature byte, so we can return
|
|
// a sensible warning in case we'll want to change the archive
|
|
// format sometimes in the future.
|
|
if (D[6]==0)
|
|
Type=RARFMT15;
|
|
else if (D[6]==1)
|
|
Type=RARFMT50;
|
|
else if (D[6]==2)
|
|
Type=RARFMT_FUTURE;
|
|
}
|
|
}
|
|
return Type;
|
|
}
|
|
|
|
|
|
unrar_err_t Archive::IsArchive()
|
|
{
|
|
if (Read(MarkHead.Mark,SIZEOF_MARKHEAD3)!=SIZEOF_MARKHEAD3)
|
|
return unrar_err_not_arc;
|
|
|
|
RARFORMAT Type;
|
|
if ((Type=IsSignature(MarkHead.Mark,SIZEOF_MARKHEAD3))!=RARFMT_NONE)
|
|
{
|
|
Format=Type;
|
|
if (Format==RARFMT14)
|
|
Seek(Tell()-SIZEOF_MARKHEAD3,SEEK_SET);
|
|
}
|
|
else
|
|
{
|
|
if (SFXSize==0)
|
|
return unrar_err_not_arc;
|
|
}
|
|
if (Format==RARFMT_FUTURE)
|
|
return unrar_err_new_algo;
|
|
if (Format==RARFMT50) // RAR 5.0 signature is one byte longer.
|
|
{
|
|
Read(MarkHead.Mark+SIZEOF_MARKHEAD3,1);
|
|
if (MarkHead.Mark[SIZEOF_MARKHEAD3]!=0)
|
|
return unrar_err_not_arc;
|
|
MarkHead.HeadSize=SIZEOF_MARKHEAD5;
|
|
}
|
|
else
|
|
MarkHead.HeadSize=SIZEOF_MARKHEAD3;
|
|
|
|
unrar_err_t error;
|
|
size_t HeaderSize;
|
|
while ((error=ReadHeader(&HeaderSize))==unrar_ok && HeaderSize!=0)
|
|
{
|
|
HEADER_TYPE Type=GetHeaderType();
|
|
// In RAR 5.0 we need to quit after reading HEAD_CRYPT if we wish to
|
|
// avoid the password prompt.
|
|
if (Type==HEAD_MAIN)
|
|
break;
|
|
SeekToNext();
|
|
}
|
|
if ( error != unrar_ok )
|
|
return error;
|
|
|
|
SeekToNext();
|
|
|
|
return unrar_ok;
|
|
}
|
|
|
|
void Archive::SeekToNext()
|
|
{
|
|
Seek(NextBlockPos,SEEK_SET);
|
|
}
|