arccmt.cpp 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  1. bool IsAnsiComment(const char *Data,int Size);
  2. bool Archive::GetComment(Array<byte> *CmtData,Array<wchar> *CmtDataW)
  3. {
  4. if (!MainComment)
  5. return(false);
  6. SaveFilePos SavePos(*this);
  7. #ifndef SFX_MODULE
  8. ushort CmtLength;
  9. if (OldFormat)
  10. {
  11. Seek(SFXSize+SIZEOF_OLDMHD,SEEK_SET);
  12. CmtLength=GetByte();
  13. CmtLength+=(GetByte()<<8);
  14. }
  15. else
  16. #endif
  17. {
  18. if ((NewMhd.Flags & MHD_COMMENT)!=0)
  19. {
  20. // Old style (RAR 2.9) archive comment embedded into the main
  21. // archive header.
  22. Seek(SFXSize+SIZEOF_MARKHEAD+SIZEOF_NEWMHD,SEEK_SET);
  23. ReadHeader();
  24. }
  25. else
  26. {
  27. // Current (RAR 3.0+) version of archive comment.
  28. Seek(SFXSize+SIZEOF_MARKHEAD+NewMhd.HeadSize,SEEK_SET);
  29. return(SearchSubBlock(SUBHEAD_TYPE_CMT)!=0 && ReadCommentData(CmtData,CmtDataW)!=0);
  30. }
  31. #ifndef SFX_MODULE
  32. // Old style (RAR 2.9) comment header embedded into the main
  33. // archive header.
  34. if (CommHead.HeadCRC!=HeaderCRC)
  35. {
  36. Log(FileName,St(MLogCommHead));
  37. Alarm();
  38. return(false);
  39. }
  40. CmtLength=CommHead.HeadSize-SIZEOF_COMMHEAD;
  41. #endif
  42. }
  43. #ifndef SFX_MODULE
  44. if (OldFormat && (OldMhd.Flags & MHD_PACK_COMMENT)!=0 || !OldFormat && CommHead.Method!=0x30)
  45. {
  46. if (!OldFormat && (CommHead.UnpVer < 15 || CommHead.UnpVer > UNP_VER || CommHead.Method > 0x35))
  47. return(false);
  48. ComprDataIO DataIO;
  49. Unpack Unpack(&DataIO);
  50. Unpack.Init();
  51. DataIO.SetTestMode(true);
  52. uint UnpCmtLength;
  53. if (OldFormat)
  54. {
  55. #ifdef RAR_NOCRYPT
  56. return(false);
  57. #else
  58. UnpCmtLength=GetByte();
  59. UnpCmtLength+=(GetByte()<<8);
  60. CmtLength-=2;
  61. DataIO.SetCmt13Encryption();
  62. #endif
  63. }
  64. else
  65. UnpCmtLength=CommHead.UnpSize;
  66. DataIO.SetFiles(this,NULL);
  67. DataIO.EnableShowProgress(false);
  68. DataIO.SetPackedSizeToRead(CmtLength);
  69. Unpack.SetDestSize(UnpCmtLength);
  70. Unpack.DoUnpack(CommHead.UnpVer,false);
  71. if (!OldFormat && ((~DataIO.UnpFileCRC)&0xffff)!=CommHead.CommCRC)
  72. {
  73. Log(FileName,St(MLogCommBrk));
  74. Alarm();
  75. return(false);
  76. }
  77. else
  78. {
  79. byte *UnpData;
  80. size_t UnpDataSize;
  81. DataIO.GetUnpackedData(&UnpData,&UnpDataSize);
  82. CmtData->Alloc(UnpDataSize);
  83. memcpy(&((*CmtData)[0]),UnpData,UnpDataSize);
  84. }
  85. }
  86. else
  87. {
  88. CmtData->Alloc(CmtLength);
  89. Read(&((*CmtData)[0]),CmtLength);
  90. if (!OldFormat && CommHead.CommCRC!=(~CRC(0xffffffff,&((*CmtData)[0]),CmtLength)&0xffff))
  91. {
  92. Log(FileName,St(MLogCommBrk));
  93. Alarm();
  94. CmtData->Reset();
  95. return(false);
  96. }
  97. }
  98. #endif
  99. #if defined(_WIN_ALL) && !defined(_WIN_CE)
  100. if (CmtData->Size()>0)
  101. {
  102. size_t CmtSize=CmtData->Size();
  103. char *DataA=(char *)CmtData->Addr();
  104. OemToCharBuffA(DataA,DataA,(DWORD)CmtSize);
  105. if (CmtDataW!=NULL)
  106. {
  107. CmtDataW->Alloc(CmtSize+1);
  108. // It can cause reallocation, so we should not use 'DataA' variable
  109. // with previosuly saved CmtData->Addr() after Push() call.
  110. CmtData->Push(0);
  111. CharToWide((char *)CmtData->Addr(),CmtDataW->Addr(),CmtSize+1);
  112. CmtData->Alloc(CmtSize);
  113. CmtDataW->Alloc(wcslen(CmtDataW->Addr()));
  114. }
  115. }
  116. #endif
  117. return(CmtData->Size()>0);
  118. }
  119. size_t Archive::ReadCommentData(Array<byte> *CmtData,Array<wchar> *CmtDataW)
  120. {
  121. bool Unicode=SubHead.SubFlags & SUBHEAD_FLAGS_CMT_UNICODE;
  122. if (!ReadSubData(CmtData,NULL))
  123. return(0);
  124. size_t CmtSize=CmtData->Size();
  125. if (Unicode)
  126. {
  127. CmtSize/=2;
  128. Array<wchar> DataW(CmtSize+1);
  129. RawToWide(CmtData->Addr(),DataW.Addr(),CmtSize);
  130. DataW[CmtSize]=0;
  131. size_t DestSize=CmtSize*4;
  132. CmtData->Alloc(DestSize+1);
  133. WideToChar(DataW.Addr(),(char *)CmtData->Addr(),DestSize);
  134. (*CmtData)[DestSize]=0;
  135. CmtSize=strlen((char *)CmtData->Addr());
  136. CmtData->Alloc(CmtSize);
  137. if (CmtDataW!=NULL)
  138. {
  139. *CmtDataW=DataW;
  140. CmtDataW->Alloc(CmtSize);
  141. }
  142. }
  143. else
  144. if (CmtDataW!=NULL)
  145. {
  146. CmtData->Push(0);
  147. CmtDataW->Alloc(CmtSize+1);
  148. CharToWide((char *)CmtData->Addr(),CmtDataW->Addr(),CmtSize+1);
  149. CmtData->Alloc(CmtSize);
  150. CmtDataW->Alloc(wcslen(CmtDataW->Addr()));
  151. }
  152. return(CmtSize);
  153. }
  154. void Archive::ViewComment()
  155. {
  156. #ifndef GUI
  157. if (Cmd->DisableComment)
  158. return;
  159. Array<byte> CmtBuf;
  160. if (GetComment(&CmtBuf,NULL))
  161. {
  162. size_t CmtSize=CmtBuf.Size();
  163. char *ChPtr=(char *)memchr(&CmtBuf[0],0x1A,CmtSize);
  164. if (ChPtr!=NULL)
  165. CmtSize=ChPtr-(char *)&CmtBuf[0];
  166. mprintf("\n");
  167. OutComment((char *)&CmtBuf[0],CmtSize);
  168. }
  169. #endif
  170. }
  171. #ifndef SFX_MODULE
  172. // Used for archives created by old RAR versions up to and including RAR 2.9.
  173. // New RAR versions store file comments in separate headers and such comments
  174. // are displayed in ListNewSubHeader function.
  175. void Archive::ViewFileComment()
  176. {
  177. if (!(NewLhd.Flags & LHD_COMMENT) || Cmd->DisableComment || OldFormat)
  178. return;
  179. #ifndef GUI
  180. mprintf(St(MFileComment));
  181. #endif
  182. const int MaxSize=0x8000;
  183. Array<char> CmtBuf(MaxSize);
  184. SaveFilePos SavePos(*this);
  185. Seek(CurBlockPos+SIZEOF_NEWLHD+NewLhd.NameSize,SEEK_SET);
  186. int64 SaveCurBlockPos=CurBlockPos;
  187. int64 SaveNextBlockPos=NextBlockPos;
  188. size_t Size=ReadHeader();
  189. CurBlockPos=SaveCurBlockPos;
  190. NextBlockPos=SaveNextBlockPos;
  191. if (Size<7 || CommHead.HeadType!=COMM_HEAD)
  192. return;
  193. if (CommHead.HeadCRC!=HeaderCRC)
  194. {
  195. #ifndef GUI
  196. Log(FileName,St(MLogCommHead));
  197. #endif
  198. return;
  199. }
  200. if (CommHead.UnpVer < 15 || CommHead.UnpVer > UNP_VER ||
  201. CommHead.Method > 0x30 || CommHead.UnpSize > MaxSize)
  202. return;
  203. Read(&CmtBuf[0],CommHead.UnpSize);
  204. if (CommHead.CommCRC!=((~CRC(0xffffffff,&CmtBuf[0],CommHead.UnpSize)&0xffff)))
  205. {
  206. Log(FileName,St(MLogBrokFCmt));
  207. }
  208. else
  209. {
  210. OutComment(&CmtBuf[0],CommHead.UnpSize);
  211. #ifndef GUI
  212. mprintf("\n");
  213. #endif
  214. }
  215. }
  216. #endif