ArchiveHeader.cs 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  1. using SharpCompress.IO;
  2. namespace SharpCompress.Common.Rar.Headers
  3. {
  4. internal class ArchiveHeader : RarHeader
  5. {
  6. public ArchiveHeader(RarHeader header, RarCrcBinaryReader reader)
  7. : base(header, reader, HeaderType.Archive)
  8. {
  9. }
  10. protected override void ReadFinish(MarkingBinaryReader reader)
  11. {
  12. if (IsRar5)
  13. {
  14. Flags = reader.ReadRarVIntUInt16();
  15. if (HasFlag(ArchiveFlagsV5.HAS_VOLUME_NUMBER))
  16. {
  17. VolumeNumber = (int)reader.ReadRarVIntUInt32();
  18. }
  19. // later: we may have a locator record if we need it
  20. //if (ExtraSize != 0) {
  21. // ReadLocator(reader);
  22. //}
  23. }
  24. else
  25. {
  26. Flags = HeaderFlags;
  27. HighPosAv = reader.ReadInt16();
  28. PosAv = reader.ReadInt32();
  29. if (HasFlag(ArchiveFlagsV4.ENCRYPT_VER))
  30. {
  31. EncryptionVersion = reader.ReadByte();
  32. }
  33. }
  34. }
  35. private void ReadLocator(MarkingBinaryReader reader) {
  36. var size = reader.ReadRarVIntUInt16();
  37. var type = reader.ReadRarVIntUInt16();
  38. if (type != 1) throw new InvalidFormatException("expected locator record");
  39. var flags = reader.ReadRarVIntUInt16();
  40. const ushort hasQuickOpenOffset = 0x01;
  41. const ushort hasRecoveryOffset = 0x02;
  42. ulong quickOpenOffset = 0;
  43. if ((flags & hasQuickOpenOffset) == hasQuickOpenOffset) {
  44. quickOpenOffset = reader.ReadRarVInt();
  45. }
  46. ulong recoveryOffset = 0;
  47. if ((flags & hasRecoveryOffset) == hasRecoveryOffset) {
  48. recoveryOffset = reader.ReadRarVInt();
  49. }
  50. }
  51. private ushort Flags { get; set; }
  52. private bool HasFlag(ushort flag)
  53. {
  54. return (Flags & flag) == flag;
  55. }
  56. internal int? VolumeNumber { get; private set; }
  57. internal short? HighPosAv { get; private set; }
  58. internal int? PosAv { get; private set; }
  59. private byte? EncryptionVersion { get; set; }
  60. public bool? IsEncrypted => IsRar5 ? (bool?)null : HasFlag(ArchiveFlagsV4.PASSWORD);
  61. public bool OldNumberingFormat => !IsRar5 && !HasFlag(ArchiveFlagsV4.NEW_NUMBERING);
  62. public bool IsVolume => HasFlag(IsRar5 ? ArchiveFlagsV5.VOLUME : ArchiveFlagsV4.VOLUME);
  63. // RAR5: Volume number field is present. True for all volumes except first.
  64. public bool IsFirstVolume => IsRar5 ? VolumeNumber == null : HasFlag(ArchiveFlagsV4.FIRST_VOLUME);
  65. public bool IsSolid => HasFlag(IsRar5 ? ArchiveFlagsV5.SOLID : ArchiveFlagsV4.SOLID);
  66. }
  67. }