OSDN Git Service

2013.10.24
[uclinux-h8/uClinux-dist.git] / user / unrar / archive.cpp
1 #include "rar.hpp"
2
3 #ifndef SHELL_EXT
4 #include "arccmt.cpp"
5 #endif
6
7
8 Archive::Archive(RAROptions *InitCmd)
9 {
10   Cmd=InitCmd==NULL ? &DummyCmd:InitCmd;
11   OpenShared=Cmd->OpenShared;
12   OldFormat=false;
13   Solid=false;
14   Volume=false;
15   MainComment=false;
16   Locked=false;
17   Signed=false;
18   NotFirstVolume=false;
19   SFXSize=0;
20   LatestTime.Reset();
21   Protected=false;
22   Encrypted=false;
23   BrokenFileHeader=false;
24   LastReadBlock=0;
25
26   CurBlockPos=0;
27   NextBlockPos=0;
28
29   RecoveryPos=SIZEOF_MARKHEAD;
30   RecoverySectors=-1;
31
32   memset(&NewMhd,0,sizeof(NewMhd));
33   NewMhd.HeadType=MAIN_HEAD;
34   NewMhd.HeadSize=SIZEOF_NEWMHD;
35   HeaderCRC=0;
36   VolWrite=0;
37   AddingFilesSize=0;
38   AddingHeadersSize=0;
39 #if !defined(SHELL_EXT) && !defined(NOCRYPT)
40   *HeadersSalt=0;
41   *SubDataSalt=0;
42 #endif
43   *FirstVolumeName=0;
44   *FirstVolumeNameW=0;
45
46   Splitting=false;
47   NewArchive=false;
48
49   SilentOpen=false;
50 }
51
52
53 #ifndef SHELL_EXT
54 void Archive::CheckArc(bool EnableBroken)
55 {
56   if (!IsArchive(EnableBroken))
57   {
58     Log(FileName,St(MBadArc),FileName);
59     ErrHandler.Exit(FATAL_ERROR);
60   }
61 }
62 #endif
63
64
65 #if !defined(SHELL_EXT) && !defined(SFX_MODULE)
66 void Archive::CheckOpen(char *Name,wchar *NameW)
67 {
68   TOpen(Name,NameW);
69   CheckArc(false);
70 }
71 #endif
72
73
74 bool Archive::WCheckOpen(char *Name,wchar *NameW)
75 {
76   if (!WOpen(Name,NameW))
77     return(false);
78   if (!IsArchive(false))
79   {
80 #ifndef SHELL_EXT
81     Log(FileName,St(MNotRAR),FileName);
82 #endif
83     Close();
84     return(false);
85   }
86   return(true);
87 }
88
89
90 bool Archive::IsSignature(byte *D)
91 {
92   bool Valid=false;
93   if (D[0]==0x52)
94 #ifndef SFX_MODULE
95     if (D[1]==0x45 && D[2]==0x7e && D[3]==0x5e)
96     {
97       OldFormat=true;
98       Valid=true;
99     }
100     else
101 #endif
102       if (D[1]==0x61 && D[2]==0x72 && D[3]==0x21 && D[4]==0x1a && D[5]==0x07 && D[6]==0x00)
103       {
104         OldFormat=false;
105         Valid=true;
106       }
107   return(Valid);
108 }
109
110
111 bool Archive::IsArchive(bool EnableBroken)
112 {
113   Encrypted=false;
114 #ifndef SFX_MODULE
115   if (IsDevice())
116   {
117 #ifndef SHELL_EXT
118     Log(FileName,St(MInvalidName),FileName);
119 #endif
120     return(false);
121   }
122 #endif
123   if (Read(MarkHead.Mark,SIZEOF_MARKHEAD)!=SIZEOF_MARKHEAD)
124     return(false);
125   SFXSize=0;
126   if (IsSignature(MarkHead.Mark))
127   {
128     if (OldFormat)
129       Seek(0,SEEK_SET);
130   }
131   else
132   {
133     Array<char> Buffer(0x40000);
134     long CurPos=int64to32(Tell());
135     int ReadSize=Read(&Buffer[0],Buffer.Size()-16);
136     for (int I=0;I<ReadSize;I++)
137       if (Buffer[I]==0x52 && IsSignature((byte *)&Buffer[I]))
138       {
139         if (OldFormat && I>0 && CurPos<28 && ReadSize>31)
140         {
141           char *D=&Buffer[28-CurPos];
142           if (D[0]!=0x52 || D[1]!=0x53 || D[2]!=0x46 || D[3]!=0x58)
143             continue;
144         }
145         SFXSize=CurPos+I;
146         Seek(SFXSize,SEEK_SET);
147         if (!OldFormat)
148           Read(MarkHead.Mark,SIZEOF_MARKHEAD);
149         break;
150       }
151     if (SFXSize==0)
152       return(false);
153   }
154   ReadHeader();
155   SeekToNext();
156 #ifndef SFX_MODULE
157   if (OldFormat)
158   {
159     NewMhd.Flags=OldMhd.Flags & 0x3f;
160     NewMhd.HeadSize=OldMhd.HeadSize;
161   }
162   else
163 #endif
164   {
165     if (HeaderCRC!=NewMhd.HeadCRC)
166     {
167 #ifndef SHELL_EXT
168       Log(FileName,St(MLogMainHead));
169 #endif
170       Alarm();
171       if (!EnableBroken)
172         return(false);
173     }
174   }
175   Volume=(NewMhd.Flags & MHD_VOLUME);
176   Solid=(NewMhd.Flags & MHD_SOLID)!=0;
177   MainComment=(NewMhd.Flags & MHD_COMMENT)!=0;
178   Locked=(NewMhd.Flags & MHD_LOCK)!=0;
179   Signed=(NewMhd.PosAV!=0);
180   Protected=(NewMhd.Flags & MHD_PROTECT)!=0;
181   Encrypted=(NewMhd.Flags & MHD_PASSWORD)!=0;
182
183 #ifdef RARDLL
184   SilentOpen=true;
185 #endif
186   if (!SilentOpen || !Encrypted)
187   {
188     SaveFilePos SavePos(*this);
189     Int64 SaveCurBlockPos=CurBlockPos,SaveNextBlockPos=NextBlockPos;
190
191     NotFirstVolume=false;
192     while (ReadHeader())
193     {
194       int HeaderType=GetHeaderType();
195       if (HeaderType==NEWSUB_HEAD)
196       {
197         if (SubHead.CmpName(SUBHEAD_TYPE_CMT))
198           MainComment=true;
199         if ((SubHead.Flags & LHD_SPLIT_BEFORE) ||
200             Volume && (NewMhd.Flags & MHD_FIRSTVOLUME)==0)
201           NotFirstVolume=true;
202       }
203       else
204       {
205         if (HeaderType==FILE_HEAD && ((NewLhd.Flags & LHD_SPLIT_BEFORE)!=0 ||
206             Volume && NewLhd.UnpVer>=29 && (NewMhd.Flags & MHD_FIRSTVOLUME)==0))
207           NotFirstVolume=true;
208         break;
209       }
210       SeekToNext();
211     }
212     CurBlockPos=SaveCurBlockPos;
213     NextBlockPos=SaveNextBlockPos;
214   }
215   return(true);
216 }
217
218
219
220
221 void Archive::SeekToNext()
222 {
223   Seek(NextBlockPos,SEEK_SET);
224 }
225
226
227 #ifndef SFX_MODULE
228 int Archive::GetRecoverySize(bool Required)
229 {
230   if (!Protected)
231     return(0);
232   if (RecoverySectors!=-1 || !Required)
233     return(RecoverySectors);
234   SaveFilePos SavePos(*this);
235   Seek(SFXSize,SEEK_SET);
236   SearchSubBlock(SUBHEAD_TYPE_RR);
237   return(RecoverySectors);
238 }
239 #endif
240
241