Terraria v1.4.4.9
Terraria source code documentation
Loading...
Searching...
No Matches
ZipArchiveEntry.cs
Go to the documentation of this file.
4using System.Text;
7
9
10public class ZipArchiveEntry
11{
12 private sealed class DirectToArchiveWriterStream : Stream
13 {
14 private long _position;
15
17
18 private bool _everWritten;
19
20 private bool _isDisposed;
21
22 private readonly ZipArchiveEntry _entry;
23
24 private bool _usedZip64inLH;
25
26 private bool _canWrite;
27
28 public override long Length
29 {
30 get
31 {
34 }
35 }
36
37 public override long Position
38 {
39 get
40 {
42 return _position;
43 }
44 set
45 {
48 }
49 }
50
51 public override bool CanRead => false;
52
53 public override bool CanSeek => false;
54
55 public override bool CanWrite => _canWrite;
56
67
68 private void ThrowIfDisposed()
69 {
70 if (_isDisposed)
71 {
73 }
74 }
75
76 public override int Read(byte[] buffer, int offset, int count)
77 {
80 }
81
82 public override long Seek(long offset, SeekOrigin origin)
83 {
86 }
87
88 public override void SetLength(long value)
89 {
92 }
93
94 public override void Write(byte[] buffer, int offset, int count)
95 {
98 if (count != 0)
99 {
100 if (!_everWritten)
101 {
102 _everWritten = true;
104 }
106 _position += count;
107 }
108 }
109
110 public override void Write(ReadOnlySpan<byte> source)
111 {
113 if (source.Length != 0)
114 {
115 if (!_everWritten)
116 {
117 _everWritten = true;
119 }
121 _position += source.Length;
122 }
123 }
124
125 public override void WriteByte(byte value)
126 {
127 Write(MemoryMarshal.CreateReadOnlySpan(ref value, 1));
128 }
129
135
155
156 public override void Flush()
157 {
160 }
161
167
168 protected override void Dispose(bool disposing)
169 {
170 if (disposing && !_isDisposed)
171 {
173 if (!_everWritten)
174 {
176 }
178 {
180 }
181 else
182 {
184 }
185 _canWrite = false;
186 _isDisposed = true;
187 }
188 base.Dispose(disposing);
189 }
190 }
191
192 [Flags]
193 internal enum BitFlagValues : ushort
194 {
195 DataDescriptor = 8,
196 UnicodeFileName = 0x800
197 }
198
199 internal enum CompressionMethodValues : ushort
200 {
201 Stored = 0,
202 Deflate = 8,
203 Deflate64 = 9,
204 BZip2 = 12,
205 LZMA = 14
206 }
207
209
210 private readonly bool _originallyInArchive;
211
212 private readonly int _diskNumberStart;
213
215
217
219
221
223
225
226 private long _compressedSize;
227
228 private long _uncompressedSize;
229
231
233
234 private uint _crc32;
235
236 private byte[][] _compressedBytes;
237
239
241
243
245
246 private uint _externalFileAttr;
247
248 private string _storedEntryName;
249
250 private byte[] _storedEntryNameBytes;
251
253
255
256 private readonly byte[] _fileComment;
257
259
260 private static readonly bool s_allowLargeZipArchiveEntriesInUpdateMode = IntPtr.Size > 4;
261
263
264 [CLSCompliant(false)]
265 public uint Crc32 => _crc32;
266
268 {
269 get
270 {
272 {
274 }
275 return _compressedSize;
276 }
277 }
278
280 {
281 get
282 {
283 return (int)_externalFileAttr;
284 }
285 set
286 {
288 _externalFileAttr = (uint)value;
289 }
290 }
291
292 public string FullName
293 {
294 get
295 {
296 return _storedEntryName;
297 }
298 [MemberNotNull("_storedEntryNameBytes")]
299 [MemberNotNull("_storedEntryName")]
300 private set
301 {
302 if (value == null)
303 {
304 throw new ArgumentNullException("FullName");
305 }
308 if (isUTF)
309 {
310 _generalPurposeBitFlag |= BitFlagValues.UnicodeFileName;
311 }
312 else
313 {
314 _generalPurposeBitFlag &= ~BitFlagValues.UnicodeFileName;
315 }
317 {
319 }
320 }
321 }
322
324 {
325 get
326 {
327 return _lastModified;
328 }
329 set
330 {
332 if (_archive.Mode == ZipArchiveMode.Read)
333 {
335 }
337 {
339 }
340 if (value.DateTime.Year < 1980 || value.DateTime.Year > 2107)
341 {
343 }
345 }
346 }
347
348 public long Length
349 {
350 get
351 {
353 {
355 }
356 return _uncompressedSize;
357 }
358 }
359
361
363
380
382 {
383 get
384 {
385 if (_storedUncompressedData == null)
386 {
389 {
391 try
392 {
394 }
396 {
400 _everOpenedForWrite = false;
401 throw;
402 }
403 }
404 if (CompressionMethod != 0)
405 {
407 }
408 }
410 }
411 }
412
414 {
415 get
416 {
418 }
419 set
420 {
421 switch (value)
422 {
423 case CompressionMethodValues.Deflate:
425 break;
426 case CompressionMethodValues.Deflate64:
428 break;
429 }
431 }
432 }
433
435 {
438 _diskNumberStart = cd.DiskNumberStart;
439 _versionMadeByPlatform = (ZipVersionMadeByPlatform)cd.VersionMadeByCompatibility;
440 _versionMadeBySpecification = (ZipVersionNeededValues)cd.VersionMadeBySpecification;
441 _versionToExtract = (ZipVersionNeededValues)cd.VersionNeededToExtract;
442 _generalPurposeBitFlag = (BitFlagValues)cd.GeneralPurposeBitFlag;
443 CompressionMethod = (CompressionMethodValues)cd.CompressionMethod;
445 _compressedSize = cd.CompressedSize;
446 _uncompressedSize = cd.UncompressedSize;
447 _externalFileAttr = cd.ExternalFileAttributes;
448 _offsetOfLocalHeader = cd.RelativeOffsetOfLocalHeader;
450 _crc32 = cd.Crc32;
451 _compressedBytes = null;
454 _everOpenedForWrite = false;
456 FullName = DecodeEntryName(cd.Filename);
458 _cdUnknownExtraFields = cd.ExtraFields;
459 _fileComment = cd.FileComment;
460 _compressionLevel = null;
461 }
462
472
509
510 public void Delete()
511 {
512 if (_archive != null)
513 {
515 {
517 }
518 if (_archive.Mode != ZipArchiveMode.Update)
519 {
521 }
523 _archive.RemoveEntry(this);
524 _archive = null;
526 }
527 }
528
529 public Stream Open()
530 {
532 return _archive.Mode switch
533 {
534 ZipArchiveMode.Read => OpenInReadMode(checkOpenable: true),
535 ZipArchiveMode.Create => OpenInWriteMode(),
536 _ => OpenInUpdateMode(),
537 };
538 }
539
540 public override string ToString()
541 {
542 return FullName;
543 }
544
545 private string DecodeEntryName(byte[] entryNameBytes)
546 {
547 Encoding encoding = (((_generalPurposeBitFlag & BitFlagValues.UnicodeFileName) != 0) ? Encoding.UTF8 : ((_archive == null) ? Encoding.UTF8 : (_archive.EntryNameEncoding ?? Encoding.UTF8)));
548 return encoding.GetString(entryNameBytes);
549 }
550
551 private byte[] EncodeEntryName(string entryName, out bool isUTF8)
552 {
553 Encoding encoding = ((_archive == null || _archive.EntryNameEncoding == null) ? (ZipHelper.RequiresUnicode(entryName) ? Encoding.UTF8 : Encoding.ASCII) : _archive.EntryNameEncoding);
554 isUTF8 = encoding.Equals(Encoding.UTF8);
555 return encoding.GetBytes(entryName);
556 }
557
564
566 {
569 bool flag = false;
570 uint value;
571 uint value2;
572 if (SizesTooLarge())
573 {
574 flag = true;
575 value = uint.MaxValue;
576 value2 = uint.MaxValue;
577 zip64ExtraField.CompressedSize = _compressedSize;
578 zip64ExtraField.UncompressedSize = _uncompressedSize;
579 }
580 else
581 {
582 value = (uint)_compressedSize;
584 }
585 uint value3;
586 if (_offsetOfLocalHeader > uint.MaxValue)
587 {
588 flag = true;
589 value3 = uint.MaxValue;
590 zip64ExtraField.LocalHeaderOffset = _offsetOfLocalHeader;
591 }
592 else
593 {
595 }
596 if (flag)
597 {
599 }
600 int num = (flag ? zip64ExtraField.TotalSize : 0) + ((_cdUnknownExtraFields != null) ? ZipGenericExtraField.TotalSize(_cdUnknownExtraFields) : 0);
601 ushort value4;
602 if (num > 65535)
603 {
604 value4 = (ushort)(flag ? zip64ExtraField.TotalSize : 0);
606 }
607 else
608 {
609 value4 = (ushort)num;
610 }
611 binaryWriter.Write(33639248u);
613 binaryWriter.Write((byte)0);
614 binaryWriter.Write((ushort)_versionToExtract);
616 binaryWriter.Write((ushort)CompressionMethod);
618 binaryWriter.Write(_crc32);
619 binaryWriter.Write(value);
620 binaryWriter.Write(value2);
621 binaryWriter.Write((ushort)_storedEntryNameBytes.Length);
622 binaryWriter.Write(value4);
623 binaryWriter.Write((ushort)((_fileComment != null) ? ((ushort)_fileComment.Length) : 0));
624 binaryWriter.Write((ushort)0);
625 binaryWriter.Write((ushort)0);
627 binaryWriter.Write(value3);
629 if (flag)
630 {
632 }
633 if (_cdUnknownExtraFields != null)
634 {
636 }
637 if (_fileComment != null)
638 {
640 }
641 }
642
644 {
646 {
649 }
651 {
652 int maxLength = Array.MaxLength;
653 _compressedBytes = new byte[_compressedSize / maxLength + 1][];
654 for (int i = 0; i < _compressedBytes.Length - 1; i++)
655 {
656 _compressedBytes[i] = new byte[maxLength];
657 }
658 _compressedBytes[_compressedBytes.Length - 1] = new byte[_compressedSize % maxLength];
660 for (int j = 0; j < _compressedBytes.Length - 1; j++)
661 {
663 }
665 }
666 return true;
667 }
668
670 {
672 {
673 throw new InvalidDataException(message);
674 }
675 }
676
678 {
679 bool flag = true;
681 switch (CompressionMethod)
682 {
683 case CompressionMethodValues.Stored:
685 flag = false;
686 break;
687 default:
689 break;
690 }
693 {
694 thisRef._crc32 = checkSum;
695 thisRef._uncompressedSize = currentPosition;
696 thisRef._compressedSize = backing.Position - initialPosition;
698 });
699 }
700
702 {
703 Stream stream = null;
704 return CompressionMethod switch
705 {
706 CompressionMethodValues.Deflate => new DeflateStream(compressedStreamToRead, CompressionMode.Decompress, _uncompressedSize),
707 CompressionMethodValues.Deflate64 => new DeflateManagedStream(compressedStreamToRead, CompressionMethodValues.Deflate64, _uncompressedSize),
709 };
710 }
711
721
738
740 {
742 {
744 }
746 _everOpenedForWrite = true;
750 {
751 thisRef._currentlyOpenForWrite = false;
752 });
753 }
754
755 private bool IsOpenable(bool needToUncompress, bool needToLoadIntoMemory, out string message)
756 {
757 message = null;
759 {
761 {
764 {
766 }
767 else
768 {
770 }
771 return false;
772 }
774 {
775 message = System.SR.SplitSpanned;
776 return false;
777 }
779 {
781 return false;
782 }
785 {
787 return false;
788 }
790 {
792 return false;
793 }
795 {
796 message = System.SR.EntryTooLarge;
797 return false;
798 }
799 }
800 return true;
801 }
802
803 private bool SizesTooLarge()
804 {
805 if (_compressedSize <= uint.MaxValue)
806 {
807 return _uncompressedSize > uint.MaxValue;
808 }
809 return true;
810 }
811
813 {
816 bool flag = false;
817 uint value;
818 uint value2;
819 if (isEmptyFile)
820 {
822 value = 0u;
823 value2 = 0u;
824 }
826 {
827 _generalPurposeBitFlag |= BitFlagValues.DataDescriptor;
828 flag = false;
829 value = 0u;
830 value2 = 0u;
831 }
832 else
833 {
834 _generalPurposeBitFlag &= ~BitFlagValues.DataDescriptor;
835 if (SizesTooLarge())
836 {
837 flag = true;
838 value = uint.MaxValue;
839 value2 = uint.MaxValue;
840 zip64ExtraField.CompressedSize = _compressedSize;
841 zip64ExtraField.UncompressedSize = _uncompressedSize;
843 }
844 else
845 {
846 flag = false;
847 value = (uint)_compressedSize;
849 }
850 }
851 _offsetOfLocalHeader = binaryWriter.BaseStream.Position;
852 int num = (flag ? zip64ExtraField.TotalSize : 0) + ((_lhUnknownExtraFields != null) ? ZipGenericExtraField.TotalSize(_lhUnknownExtraFields) : 0);
853 ushort value3;
854 if (num > 65535)
855 {
856 value3 = (ushort)(flag ? zip64ExtraField.TotalSize : 0);
858 }
859 else
860 {
861 value3 = (ushort)num;
862 }
863 binaryWriter.Write(67324752u);
864 binaryWriter.Write((ushort)_versionToExtract);
866 binaryWriter.Write((ushort)CompressionMethod);
868 binaryWriter.Write(_crc32);
869 binaryWriter.Write(value);
870 binaryWriter.Write(value2);
871 binaryWriter.Write((ushort)_storedEntryNameBytes.Length);
872 binaryWriter.Write(value3);
874 if (flag)
875 {
877 }
878 if (_lhUnknownExtraFields != null)
879 {
881 }
882 return flag;
883 }
884
886 {
887 if (_storedUncompressedData != null || _compressedBytes != null)
888 {
889 if (_storedUncompressedData != null)
890 {
897 return;
898 }
899 if (_uncompressedSize == 0L)
900 {
902 }
904 if (_uncompressedSize != 0L)
905 {
907 foreach (byte[] array in compressedBytes)
908 {
910 }
911 }
912 }
913 else if (_archive.Mode == ZipArchiveMode.Update || !_everOpenedForWrite)
914 {
915 _everOpenedForWrite = true;
917 }
918 }
919
921 {
922 long position = _archive.ArchiveStream.Position;
924 bool flag = SizesTooLarge();
925 bool flag2 = flag && !zip64HeaderUsed;
926 uint value = (uint)(flag ? uint.MaxValue : _compressedSize);
927 uint value2 = (uint)(flag ? uint.MaxValue : _uncompressedSize);
928 if (flag2)
929 {
931 _generalPurposeBitFlag |= BitFlagValues.DataDescriptor;
933 binaryWriter.Write((ushort)_versionToExtract);
935 }
937 if (!flag2)
938 {
939 binaryWriter.Write(_crc32);
940 binaryWriter.Write(value);
941 binaryWriter.Write(value2);
942 }
943 else
944 {
945 binaryWriter.Write(0u);
946 binaryWriter.Write(0u);
947 binaryWriter.Write(0u);
948 }
949 if (zip64HeaderUsed)
950 {
954 }
955 _archive.ArchiveStream.Seek(position, SeekOrigin.Begin);
956 if (flag2)
957 {
958 binaryWriter.Write(_crc32);
961 }
962 }
963
964 private void WriteDataDescriptor()
965 {
967 binaryWriter.Write(134695760u);
968 binaryWriter.Write(_crc32);
969 if (SizesTooLarge())
970 {
973 }
974 else
975 {
976 binaryWriter.Write((uint)_compressedSize);
977 binaryWriter.Write((uint)_uncompressedSize);
978 }
979 }
980
981 private void UnloadStreams()
982 {
983 if (_storedUncompressedData != null)
984 {
986 }
987 _compressedBytes = null;
989 }
990
991 private void CloseStreams()
992 {
993 if (_outstandingWriteStream != null)
994 {
996 }
997 }
998
1000 {
1001 if ((int)_versionToExtract < (int)value)
1002 {
1004 }
1005 if ((int)_versionMadeBySpecification < (int)value)
1006 {
1008 }
1009 }
1010
1012 {
1013 if (_archive == null)
1014 {
1016 }
1018 }
1019
1020 private static string GetFileName_Windows(string path)
1021 {
1022 int length = path.Length;
1023 int num = length;
1024 while (--num >= 0)
1025 {
1026 char c = path[num];
1027 if (c == '\\' || c == '/' || c == ':')
1028 {
1029 return path.Substring(num + 1);
1030 }
1031 }
1032 return path;
1033 }
1034
1035 private static string GetFileName_Unix(string path)
1036 {
1037 int length = path.Length;
1038 int num = length;
1039 while (--num >= 0)
1040 {
1041 if (path[num] == '/')
1042 {
1043 return path.Substring(num + 1);
1044 }
1045 }
1046 return path;
1047 }
1048
1050 {
1052 {
1053 return GetFileName_Windows(path);
1054 }
1055 return GetFileName_Unix(path);
1056 }
1057}
static int MaxLength
Definition Array.cs:471
static readonly EventArgs Empty
Definition EventArgs.cs:9
override void Write(byte[] buffer, int offset, int count)
override Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
override Task FlushAsync(CancellationToken cancellationToken)
override int Read(byte[] buffer, int offset, int count)
override ValueTask WriteAsync(ReadOnlyMemory< byte > buffer, CancellationToken cancellationToken=default(CancellationToken))
override long Seek(long offset, SeekOrigin origin)
override void Write(byte[] buffer, int offset, int count)
DirectToArchiveWriterStream(CheckSumAndSizeWriteStream crcSizeStream, ZipArchiveEntry entry)
override Task FlushAsync(CancellationToken cancellationToken)
override Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
void WriteCrcAndSizesInLocalHeader(bool zip64HeaderUsed)
readonly? CompressionLevel _compressionLevel
void VersionToExtractAtLeast(ZipVersionNeededValues value)
CompressionMethodValues _storedCompressionMethod
ZipArchiveEntry(ZipArchive archive, ZipCentralDirectoryFileHeader cd)
static string GetFileName_Windows(string path)
ZipArchiveEntry(ZipArchive archive, string entryName)
List< ZipGenericExtraField > _cdUnknownExtraFields
ZipArchiveEntry(ZipArchive archive, string entryName, CompressionLevel compressionLevel)
void ThrowIfNotOpenable(bool needToUncompress, bool needToLoadIntoMemory)
List< ZipGenericExtraField > _lhUnknownExtraFields
Stream GetDataDecompressor(Stream compressedStreamToRead)
readonly ZipVersionMadeByPlatform _versionMadeByPlatform
CheckSumAndSizeWriteStream GetDataCompressor(Stream backingStream, bool leaveBackingStreamOpen, EventHandler onClose)
string DecodeEntryName(byte[] entryNameBytes)
ZipVersionNeededValues _versionMadeBySpecification
CompressionMethodValues CompressionMethod
bool WriteLocalFileHeader(bool isEmptyFile)
bool IsOpenable(bool needToUncompress, bool needToLoadIntoMemory, out string message)
static string ParseFileName(string path, ZipVersionMadeByPlatform madeByPlatform)
static string GetFileName_Unix(string path)
static readonly bool s_allowLargeZipArchiveEntriesInUpdateMode
Stream OpenInReadMode(bool checkOpenable)
byte[] EncodeEntryName(string entryName, out bool isUTF8)
void AcquireArchiveStream(ZipArchiveEntry entry)
void RemoveEntry(ZipArchiveEntry entry)
static bool RequiresUnicode(string test)
Definition ZipHelper.cs:7
static void ReadBytes(Stream stream, byte[] buffer, int bytesToRead)
Definition ZipHelper.cs:19
static DateTime DosTimeToDateTime(uint dateTime)
Definition ZipHelper.cs:35
static uint DateTimeToDosTime(DateTime dateTime)
Definition ZipHelper.cs:61
override long Seek(long offset, SeekOrigin loc)
override void Dispose(bool disposing)
override void CopyTo(Stream destination, int bufferSize)
static void ValidateBufferArguments(byte[] buffer, int offset, int count)
Definition Stream.cs:1044
long Seek(long offset, SeekOrigin origin)
void CopyTo(Stream destination)
Definition Stream.cs:540
void Dispose()
Definition Stream.cs:639
void Write(byte[] buffer, int offset, int count)
static string UnsupportedCompression
Definition SR.cs:122
static string LengthAfterWrite
Definition SR.cs:102
static string UpdateModeOneStream
Definition SR.cs:128
static string FrozenAfterWrite
Definition SR.cs:98
static string SeekingNotSupported
Definition SR.cs:114
static string SetLengthRequiresSeekingAndWriting
Definition SR.cs:116
static string ReadingNotSupported
Definition SR.cs:108
static string CreateModeWriteOnceAndOneEntryAtATime
Definition SR.cs:64
static string ReadOnlyArchive
Definition SR.cs:112
static string Format(string resourceFormat, object p1)
Definition SR.cs:118
static string DeleteOpenEntry
Definition SR.cs:72
static string UnsupportedCompressionMethod
Definition SR.cs:124
static string DeletedEntry
Definition SR.cs:68
static string LocalFileHeaderCorrupt
Definition SR.cs:104
static string DeleteOnlyInUpdate
Definition SR.cs:70
static string SplitSpanned
Definition SR.cs:118
static string EntryTooLarge
Definition SR.cs:80
static string EntryNamesTooLong
Definition SR.cs:78
static string DateTimeOutOfRange
Definition SR.cs:66
static string HiddenStreamName
Definition SR.cs:100
Definition SR.cs:7
static Encoding UTF8
Definition Encoding.cs:526
static Encoding ASCII
Definition Encoding.cs:511
override bool Equals([NotNullWhen(true)] object? value)
Definition Encoding.cs:1032
virtual byte[] GetBytes(char[] chars)
Definition Encoding.cs:781
unsafe string GetString(byte *bytes, int byteCount)
Definition Encoding.cs:973
static DateTimeOffset Now
static int TotalSize(List< ZipGenericExtraField > fields)
static void WriteAllBlocks(List< ZipGenericExtraField > fields, Stream stream)
static List< ZipGenericExtraField > GetExtraFields(BinaryReader reader)
static bool TrySkipBlock(BinaryReader reader)