archive.cpp 5.8 KB

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