forked from svn2github/dotnetzip
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathZipEntry.cs
More file actions
2968 lines (2765 loc) · 129 KB
/
Copy pathZipEntry.cs
File metadata and controls
2968 lines (2765 loc) · 129 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
// ZipEntry.cs
// ------------------------------------------------------------------
//
// Copyright (c) 2006-2010 Dino Chiesa.
// All rights reserved.
//
// This code module is part of DotNetZip, a zipfile class library.
//
// ------------------------------------------------------------------
//
// This code is licensed under the Microsoft Public License.
// See the file License.txt for the license details.
// More info on: http://dotnetzip.codeplex.com
//
// ------------------------------------------------------------------
//
// last saved (in emacs):
// Time-stamp: <2011-August-06 17:25:53>
//
// ------------------------------------------------------------------
//
// This module defines the ZipEntry class, which models the entries within a zip file.
//
// Created: Tue, 27 Mar 2007 15:30
//
// ------------------------------------------------------------------
using System;
using System.IO;
using Interop = System.Runtime.InteropServices;
namespace Ionic.Zip
{
/// <summary>
/// Represents a single entry in a ZipFile. Typically, applications get a ZipEntry
/// by enumerating the entries within a ZipFile, or by adding an entry to a ZipFile.
/// </summary>
[Interop.GuidAttribute("ebc25cf6-9120-4283-b972-0e5520d00004")]
[Interop.ComVisible(true)]
#if !NETCF
[Interop.ClassInterface(Interop.ClassInterfaceType.AutoDispatch)] // AutoDual
#endif
public partial class ZipEntry
{
/// <summary>
/// Default constructor.
/// </summary>
/// <remarks>
/// Applications should never need to call this directly. It is exposed to
/// support COM Automation environments.
/// </remarks>
public ZipEntry()
{
_CompressionMethod = (Int16)CompressionMethod.Deflate;
_CompressionLevel = Ionic.Zlib.CompressionLevel.Default;
_Encryption = EncryptionAlgorithm.None;
_Source = ZipEntrySource.None;
AlternateEncoding = System.Text.Encoding.GetEncoding("IBM437");
AlternateEncodingUsage = ZipOption.Never;
}
/// <summary>
/// The time and date at which the file indicated by the <c>ZipEntry</c> was
/// last modified.
/// </summary>
///
/// <remarks>
/// <para>
/// The DotNetZip library sets the LastModified value for an entry, equal to
/// the Last Modified time of the file in the filesystem. If an entry is
/// added from a stream, the library uses <c>System.DateTime.Now</c> for this
/// value, for the given entry.
/// </para>
///
/// <para>
/// This property allows the application to retrieve and possibly set the
/// LastModified value on an entry, to an arbitrary value. <see
/// cref="System.DateTime"/> values with a <see cref="System.DateTimeKind" />
/// setting of <c>DateTimeKind.Unspecified</c> are taken to be expressed as
/// <c>DateTimeKind.Local</c>.
/// </para>
///
/// <para>
/// Be aware that because of the way <see
/// href="http://www.pkware.com/documents/casestudies/APPNOTE.TXT">PKWare's
/// Zip specification</see> describes how times are stored in the zip file,
/// the full precision of the <c>System.DateTime</c> datatype is not stored
/// for the last modified time when saving zip files. For more information on
/// how times are formatted, see the PKZip specification.
/// </para>
///
/// <para>
/// The actual last modified time of a file can be stored in multiple ways in
/// the zip file, and they are not mutually exclusive:
/// </para>
///
/// <list type="bullet">
/// <item>
/// In the so-called "DOS" format, which has a 2-second precision. Values
/// are rounded to the nearest even second. For example, if the time on the
/// file is 12:34:43, then it will be stored as 12:34:44. This first value
/// is accessible via the <c>LastModified</c> property. This value is always
/// present in the metadata for each zip entry. In some cases the value is
/// invalid, or zero.
/// </item>
///
/// <item>
/// In the so-called "Windows" or "NTFS" format, as an 8-byte integer
/// quantity expressed as the number of 1/10 milliseconds (in other words
/// the number of 100 nanosecond units) since January 1, 1601 (UTC). This
/// format is how Windows represents file times. This time is accessible
/// via the <c>ModifiedTime</c> property.
/// </item>
///
/// <item>
/// In the "Unix" format, a 4-byte quantity specifying the number of seconds since
/// January 1, 1970 UTC.
/// </item>
///
/// <item>
/// In an older format, now deprecated but still used by some current
/// tools. This format is also a 4-byte quantity specifying the number of
/// seconds since January 1, 1970 UTC.
/// </item>
///
/// </list>
///
/// <para>
/// Zip tools and libraries will always at least handle (read or write) the
/// DOS time, and may also handle the other time formats. Keep in mind that
/// while the names refer to particular operating systems, there is nothing in
/// the time formats themselves that prevents their use on other operating
/// systems.
/// </para>
///
/// <para>
/// When reading ZIP files, the DotNetZip library reads the Windows-formatted
/// time, if it is stored in the entry, and sets both <c>LastModified</c> and
/// <c>ModifiedTime</c> to that value. When writing ZIP files, the DotNetZip
/// library by default will write both time quantities. It can also emit the
/// Unix-formatted time if desired (See <see
/// cref="EmitTimesInUnixFormatWhenSaving"/>.)
/// </para>
///
/// <para>
/// The last modified time of the file created upon a call to
/// <c>ZipEntry.Extract()</c> may be adjusted during extraction to compensate
/// for differences in how the .NET Base Class Library deals with daylight
/// saving time (DST) versus how the Windows filesystem deals with daylight
/// saving time. Raymond Chen <see
/// href="http://blogs.msdn.com/oldnewthing/archive/2003/10/24/55413.aspx">provides
/// some good context</see>.
/// </para>
///
/// <para>
/// In a nutshell: Daylight savings time rules change regularly. In 2007, for
/// example, the inception week of DST changed. In 1977, DST was in place all
/// year round. In 1945, likewise. And so on. Win32 does not attempt to
/// guess which time zone rules were in effect at the time in question. It
/// will render a time as "standard time" and allow the app to change to DST
/// as necessary. .NET makes a different choice.
/// </para>
///
/// <para>
/// Compare the output of FileInfo.LastWriteTime.ToString("f") with what you
/// see in the Windows Explorer property sheet for a file that was last
/// written to on the other side of the DST transition. For example, suppose
/// the file was last modified on October 17, 2003, during DST but DST is not
/// currently in effect. Explorer's file properties reports Thursday, October
/// 17, 2003, 8:45:38 AM, but .NETs FileInfo reports Thursday, October 17,
/// 2003, 9:45 AM.
/// </para>
///
/// <para>
/// Win32 says, "Thursday, October 17, 2002 8:45:38 AM PST". Note: Pacific
/// STANDARD Time. Even though October 17 of that year occurred during Pacific
/// Daylight Time, Win32 displays the time as standard time because that's
/// what time it is NOW.
/// </para>
///
/// <para>
/// .NET BCL assumes that the current DST rules were in place at the time in
/// question. So, .NET says, "Well, if the rules in effect now were also in
/// effect on October 17, 2003, then that would be daylight time" so it
/// displays "Thursday, October 17, 2003, 9:45 AM PDT" - daylight time.
/// </para>
///
/// <para>
/// So .NET gives a value which is more intuitively correct, but is also
/// potentially incorrect, and which is not invertible. Win32 gives a value
/// which is intuitively incorrect, but is strictly correct.
/// </para>
///
/// <para>
/// Because of this funkiness, this library adds one hour to the LastModified
/// time on the extracted file, if necessary. That is to say, if the time in
/// question had occurred in what the .NET Base Class Library assumed to be
/// DST. This assumption may be wrong given the constantly changing DST rules,
/// but it is the best we can do.
/// </para>
///
/// </remarks>
///
public DateTime LastModified
{
get { return _LastModified.ToLocalTime(); }
set
{
_LastModified = (value.Kind == DateTimeKind.Unspecified)
? DateTime.SpecifyKind(value, DateTimeKind.Local)
: value.ToLocalTime();
_Mtime = Ionic.Zip.SharedUtilities.AdjustTime_Reverse(_LastModified).ToUniversalTime();
_metadataChanged = true;
}
}
private int BufferSize
{
get
{
return this._container.BufferSize;
}
}
/// <summary>
/// Last Modified time for the file represented by the entry.
/// </summary>
///
/// <remarks>
///
/// <para>
/// This value corresponds to the "last modified" time in the NTFS file times
/// as described in <see
/// href="http://www.pkware.com/documents/casestudies/APPNOTE.TXT">the Zip
/// specification</see>. When getting this property, the value may be
/// different from <see cref="LastModified" />. When setting the property,
/// the <see cref="LastModified"/> property also gets set, but with a lower
/// precision.
/// </para>
///
/// <para>
/// Let me explain. It's going to take a while, so get
/// comfortable. Originally, waaaaay back in 1989 when the ZIP specification
/// was originally described by the esteemed Mr. Phil Katz, the dominant
/// operating system of the time was MS-DOS. MSDOS stored file times with a
/// 2-second precision, because, c'mon, <em>who is ever going to need better
/// resolution than THAT?</em> And so ZIP files, regardless of the platform on
/// which the zip file was created, store file times in exactly <see
/// href="http://www.vsft.com/hal/dostime.htm">the same format that DOS used
/// in 1989</see>.
/// </para>
///
/// <para>
/// Since then, the ZIP spec has evolved, but the internal format for file
/// timestamps remains the same. Despite the fact that the way times are
/// stored in a zip file is rooted in DOS heritage, any program on any
/// operating system can format a time in this way, and most zip tools and
/// libraries DO - they round file times to the nearest even second and store
/// it just like DOS did 25+ years ago.
/// </para>
///
/// <para>
/// PKWare extended the ZIP specification to allow a zip file to store what
/// are called "NTFS Times" and "Unix(tm) times" for a file. These are the
/// <em>last write</em>, <em>last access</em>, and <em>file creation</em>
/// times of a particular file. These metadata are not actually specific
/// to NTFS or Unix. They are tracked for each file by NTFS and by various
/// Unix filesystems, but they are also tracked by other filesystems, too.
/// The key point is that the times are <em>formatted in the zip file</em>
/// in the same way that NTFS formats the time (ticks since win32 epoch),
/// or in the same way that Unix formats the time (seconds since Unix
/// epoch). As with the DOS time, any tool or library running on any
/// operating system is capable of formatting a time in one of these ways
/// and embedding it into the zip file.
/// </para>
///
/// <para>
/// These extended times are higher precision quantities than the DOS time.
/// As described above, the (DOS) LastModified has a precision of 2 seconds.
/// The Unix time is stored with a precision of 1 second. The NTFS time is
/// stored with a precision of 0.0000001 seconds. The quantities are easily
/// convertible, except for the loss of precision you may incur.
/// </para>
///
/// <para>
/// A zip archive can store the {C,A,M} times in NTFS format, in Unix format,
/// or not at all. Often a tool running on Unix or Mac will embed the times
/// in Unix format (1 second precision), while WinZip running on Windows might
/// embed the times in NTFS format (precision of of 0.0000001 seconds). When
/// reading a zip file with these "extended" times, in either format,
/// DotNetZip represents the values with the
/// <c>ModifiedTime</c>, <c>AccessedTime</c> and <c>CreationTime</c>
/// properties on the <c>ZipEntry</c>.
/// </para>
///
/// <para>
/// While any zip application or library, regardless of the platform it
/// runs on, could use any of the time formats allowed by the ZIP
/// specification, not all zip tools or libraries do support all these
/// formats. Storing the higher-precision times for each entry is
/// optional for zip files, and many tools and libraries don't use the
/// higher precision quantities at all. The old DOS time, represented by
/// <see cref="LastModified"/>, is guaranteed to be present, though it
/// sometimes unset.
/// </para>
///
/// <para>
/// Ok, getting back to the question about how the <c>LastModified</c>
/// property relates to this <c>ModifiedTime</c>
/// property... <c>LastModified</c> is always set, while
/// <c>ModifiedTime</c> is not. (The other times stored in the <em>NTFS
/// times extension</em>, <c>CreationTime</c> and <c>AccessedTime</c> also
/// may not be set on an entry that is read from an existing zip file.)
/// When reading a zip file, then <c>LastModified</c> takes the DOS time
/// that is stored with the file. If the DOS time has been stored as zero
/// in the zipfile, then this library will use <c>DateTime.Now</c> for the
/// <c>LastModified</c> value. If the ZIP file was created by an evolved
/// tool, then there will also be higher precision NTFS or Unix times in
/// the zip file. In that case, this library will read those times, and
/// set <c>LastModified</c> and <c>ModifiedTime</c> to the same value, the
/// one corresponding to the last write time of the file. If there are no
/// higher precision times stored for the entry, then <c>ModifiedTime</c>
/// remains unset (likewise <c>AccessedTime</c> and <c>CreationTime</c>),
/// and <c>LastModified</c> keeps its DOS time.
/// </para>
///
/// <para>
/// When creating zip files with this library, by default the extended time
/// properties (<c>ModifiedTime</c>, <c>AccessedTime</c>, and
/// <c>CreationTime</c>) are set on the ZipEntry instance, and these data are
/// stored in the zip archive for each entry, in NTFS format. If you add an
/// entry from an actual filesystem file, then the entry gets the actual file
/// times for that file, to NTFS-level precision. If you add an entry from a
/// stream, or a string, then the times get the value <c>DateTime.Now</c>. In
/// this case <c>LastModified</c> and <c>ModifiedTime</c> will be identical,
/// to 2 seconds of precision. You can explicitly set the
/// <c>CreationTime</c>, <c>AccessedTime</c>, and <c>ModifiedTime</c> of an
/// entry using the property setters. If you want to set all of those
/// quantities, it's more efficient to use the <see
/// cref="SetEntryTimes(DateTime, DateTime, DateTime)"/> method. Those
/// changes are not made permanent in the zip file until you call <see
/// cref="ZipFile.Save()"/> or one of its cousins.
/// </para>
///
/// <para>
/// When creating a zip file, you can override the default behavior of
/// this library for formatting times in the zip file, disabling the
/// embedding of file times in NTFS format or enabling the storage of file
/// times in Unix format, or both. You may want to do this, for example,
/// when creating a zip file on Windows, that will be consumed on a Mac,
/// by an application that is not hip to the "NTFS times" format. To do
/// this, use the <see cref="EmitTimesInWindowsFormatWhenSaving"/> and
/// <see cref="EmitTimesInUnixFormatWhenSaving"/> properties. A valid zip
/// file may store the file times in both formats. But, there are no
/// guarantees that a program running on Mac or Linux will gracefully
/// handle the NTFS-formatted times when Unix times are present, or that a
/// non-DotNetZip-powered application running on Windows will be able to
/// handle file times in Unix format. DotNetZip will always do something
/// reasonable; other libraries or tools may not. When in doubt, test.
/// </para>
///
/// <para>
/// I'll bet you didn't think one person could type so much about time, eh?
/// And reading it was so enjoyable, too! Well, in appreciation, <see
/// href="http://cheeso.members.winisp.net/DotNetZipDonate.aspx">maybe you
/// should donate</see>?
/// </para>
/// </remarks>
///
/// <seealso cref="AccessedTime"/>
/// <seealso cref="CreationTime"/>
/// <seealso cref="Ionic.Zip.ZipEntry.LastModified"/>
/// <seealso cref="SetEntryTimes"/>
public DateTime ModifiedTime
{
get { return _Mtime; }
set
{
SetEntryTimes(_Ctime, _Atime, value);
}
}
/// <summary>
/// Last Access time for the file represented by the entry.
/// </summary>
/// <remarks>
/// This value may or may not be meaningful. If the <c>ZipEntry</c> was read from an existing
/// Zip archive, this information may not be available. For an explanation of why, see
/// <see cref="ModifiedTime"/>.
/// </remarks>
/// <seealso cref="ModifiedTime"/>
/// <seealso cref="CreationTime"/>
/// <seealso cref="SetEntryTimes"/>
public DateTime AccessedTime
{
get { return _Atime; }
set
{
SetEntryTimes(_Ctime, value, _Mtime);
}
}
/// <summary>
/// The file creation time for the file represented by the entry.
/// </summary>
///
/// <remarks>
/// This value may or may not be meaningful. If the <c>ZipEntry</c> was read
/// from an existing zip archive, and the creation time was not set on the entry
/// when the zip file was created, then this property may be meaningless. For an
/// explanation of why, see <see cref="ModifiedTime"/>.
/// </remarks>
/// <seealso cref="ModifiedTime"/>
/// <seealso cref="AccessedTime"/>
/// <seealso cref="SetEntryTimes"/>
public DateTime CreationTime
{
get { return _Ctime; }
set
{
SetEntryTimes(value, _Atime, _Mtime);
}
}
/// <summary>
/// Sets the NTFS Creation, Access, and Modified times for the given entry.
/// </summary>
///
/// <remarks>
/// <para>
/// When adding an entry from a file or directory, the Creation, Access, and
/// Modified times for the given entry are automatically set from the
/// filesystem values. When adding an entry from a stream or string, the
/// values are implicitly set to DateTime.Now. The application may wish to
/// set these values to some arbitrary value, before saving the archive, and
/// can do so using the various setters. If you want to set all of the times,
/// this method is more efficient.
/// </para>
///
/// <para>
/// The values you set here will be retrievable with the <see
/// cref="ModifiedTime"/>, <see cref="CreationTime"/> and <see
/// cref="AccessedTime"/> properties.
/// </para>
///
/// <para>
/// When this method is called, if both <see
/// cref="EmitTimesInWindowsFormatWhenSaving"/> and <see
/// cref="EmitTimesInUnixFormatWhenSaving"/> are false, then the
/// <c>EmitTimesInWindowsFormatWhenSaving</c> flag is automatically set.
/// </para>
///
/// <para>
/// DateTime values provided here without a DateTimeKind are assumed to be Local Time.
/// </para>
///
/// </remarks>
/// <param name="created">the creation time of the entry.</param>
/// <param name="accessed">the last access time of the entry.</param>
/// <param name="modified">the last modified time of the entry.</param>
///
/// <seealso cref="EmitTimesInWindowsFormatWhenSaving" />
/// <seealso cref="EmitTimesInUnixFormatWhenSaving" />
/// <seealso cref="AccessedTime"/>
/// <seealso cref="CreationTime"/>
/// <seealso cref="ModifiedTime"/>
public void SetEntryTimes(DateTime created, DateTime accessed, DateTime modified)
{
_ntfsTimesAreSet = true;
if (created == _zeroHour && created.Kind == _zeroHour.Kind) created = _win32Epoch;
if (accessed == _zeroHour && accessed.Kind == _zeroHour.Kind) accessed = _win32Epoch;
if (modified == _zeroHour && modified.Kind == _zeroHour.Kind) modified = _win32Epoch;
_Ctime = created.ToUniversalTime();
_Atime = accessed.ToUniversalTime();
_Mtime = modified.ToUniversalTime();
_LastModified = _Mtime;
if (!_emitUnixTimes && !_emitNtfsTimes)
_emitNtfsTimes = true;
_metadataChanged = true;
}
/// <summary>
/// Specifies whether the Creation, Access, and Modified times for the given
/// entry will be emitted in "Windows format" when the zip archive is saved.
/// </summary>
///
/// <remarks>
/// <para>
/// An application creating a zip archive can use this flag to explicitly
/// specify that the file times for the entry should or should not be stored
/// in the zip archive in the format used by Windows. The default value of
/// this property is <c>true</c>.
/// </para>
///
/// <para>
/// When adding an entry from a file or directory, the Creation (<see
/// cref="CreationTime"/>), Access (<see cref="AccessedTime"/>), and Modified
/// (<see cref="ModifiedTime"/>) times for the given entry are automatically
/// set from the filesystem values. When adding an entry from a stream or
/// string, all three values are implicitly set to DateTime.Now. Applications
/// can also explicitly set those times by calling <see
/// cref="SetEntryTimes(DateTime, DateTime, DateTime)" />.
/// </para>
///
/// <para>
/// <see
/// href="http://www.pkware.com/documents/casestudies/APPNOTE.TXT">PKWARE's
/// zip specification</see> describes multiple ways to format these times in a
/// zip file. One is the format Windows applications normally use: 100ns ticks
/// since Jan 1, 1601 UTC. The other is a format Unix applications typically
/// use: seconds since January 1, 1970 UTC. Each format can be stored in an
/// "extra field" in the zip entry when saving the zip archive. The former
/// uses an extra field with a Header Id of 0x000A, while the latter uses a
/// header ID of 0x5455.
/// </para>
///
/// <para>
/// Not all zip tools and libraries can interpret these fields. Windows
/// compressed folders is one that can read the Windows Format timestamps,
/// while I believe the <see href="http://www.info-zip.org/">Infozip</see>
/// tools can read the Unix format timestamps. Although the time values are
/// easily convertible, subject to a loss of precision, some tools and
/// libraries may be able to read only one or the other. DotNetZip can read or
/// write times in either or both formats.
/// </para>
///
/// <para>
/// The times stored are taken from <see cref="ModifiedTime"/>, <see
/// cref="AccessedTime"/>, and <see cref="CreationTime"/>.
/// </para>
///
/// <para>
/// This property is not mutually exclusive from the <see
/// cref="ZipEntry.EmitTimesInUnixFormatWhenSaving"/> property. It is
/// possible that a zip entry can embed the timestamps in both forms, one
/// form, or neither. But, there are no guarantees that a program running on
/// Mac or Linux will gracefully handle NTFS Formatted times, or that a
/// non-DotNetZip-powered application running on Windows will be able to
/// handle file times in Unix format. When in doubt, test.
/// </para>
///
/// <para>
/// Normally you will use the <see
/// cref="ZipFile.EmitTimesInWindowsFormatWhenSaving">ZipFile.EmitTimesInWindowsFormatWhenSaving</see>
/// property, to specify the behavior for all entries in a zip, rather than
/// the property on each individual entry.
/// </para>
///
/// </remarks>
///
/// <seealso cref="SetEntryTimes(DateTime, DateTime, DateTime)"/>
/// <seealso cref="EmitTimesInUnixFormatWhenSaving"/>
/// <seealso cref="CreationTime"/>
/// <seealso cref="AccessedTime"/>
/// <seealso cref="ModifiedTime"/>
public bool EmitTimesInWindowsFormatWhenSaving
{
get
{
return _emitNtfsTimes;
}
set
{
_emitNtfsTimes = value;
_metadataChanged = true;
}
}
/// <summary>
/// Specifies whether the Creation, Access, and Modified times for the given
/// entry will be emitted in "Unix(tm) format" when the zip archive is saved.
/// </summary>
///
/// <remarks>
/// <para>
/// An application creating a zip archive can use this flag to explicitly
/// specify that the file times for the entry should or should not be stored
/// in the zip archive in the format used by Unix. By default this flag is
/// <c>false</c>, meaning the Unix-format times are not stored in the zip
/// archive.
/// </para>
///
/// <para>
/// When adding an entry from a file or directory, the Creation (<see
/// cref="CreationTime"/>), Access (<see cref="AccessedTime"/>), and Modified
/// (<see cref="ModifiedTime"/>) times for the given entry are automatically
/// set from the filesystem values. When adding an entry from a stream or
/// string, all three values are implicitly set to DateTime.Now. Applications
/// can also explicitly set those times by calling <see
/// cref="SetEntryTimes(DateTime, DateTime, DateTime)"/>.
/// </para>
///
/// <para>
/// <see
/// href="http://www.pkware.com/documents/casestudies/APPNOTE.TXT">PKWARE's
/// zip specification</see> describes multiple ways to format these times in a
/// zip file. One is the format Windows applications normally use: 100ns ticks
/// since Jan 1, 1601 UTC. The other is a format Unix applications typically
/// use: seconds since Jan 1, 1970 UTC. Each format can be stored in an
/// "extra field" in the zip entry when saving the zip archive. The former
/// uses an extra field with a Header Id of 0x000A, while the latter uses a
/// header ID of 0x5455.
/// </para>
///
/// <para>
/// Not all tools and libraries can interpret these fields. Windows
/// compressed folders is one that can read the Windows Format timestamps,
/// while I believe the <see href="http://www.info-zip.org/">Infozip</see>
/// tools can read the Unix format timestamps. Although the time values are
/// easily convertible, subject to a loss of precision, some tools and
/// libraries may be able to read only one or the other. DotNetZip can read or
/// write times in either or both formats.
/// </para>
///
/// <para>
/// The times stored are taken from <see cref="ModifiedTime"/>, <see
/// cref="AccessedTime"/>, and <see cref="CreationTime"/>.
/// </para>
///
/// <para>
/// This property is not mutually exclusive from the <see
/// cref="ZipEntry.EmitTimesInWindowsFormatWhenSaving"/> property. It is
/// possible that a zip entry can embed the timestamps in both forms, one
/// form, or neither. But, there are no guarantees that a program running on
/// Mac or Linux will gracefully handle NTFS Formatted times, or that a
/// non-DotNetZip-powered application running on Windows will be able to
/// handle file times in Unix format. When in doubt, test.
/// </para>
///
/// <para>
/// Normally you will use the <see
/// cref="ZipFile.EmitTimesInUnixFormatWhenSaving">ZipFile.EmitTimesInUnixFormatWhenSaving</see>
/// property, to specify the behavior for all entries, rather than the
/// property on each individual entry.
/// </para>
/// </remarks>
///
/// <seealso cref="SetEntryTimes(DateTime, DateTime, DateTime)"/>
/// <seealso cref="EmitTimesInWindowsFormatWhenSaving"/>
/// <seealso cref="ZipFile.EmitTimesInUnixFormatWhenSaving"/>
/// <seealso cref="CreationTime"/>
/// <seealso cref="AccessedTime"/>
/// <seealso cref="ModifiedTime"/>
public bool EmitTimesInUnixFormatWhenSaving
{
get
{
return _emitUnixTimes;
}
set
{
_emitUnixTimes = value;
_metadataChanged = true;
}
}
/// <summary>
/// The type of timestamp attached to the ZipEntry.
/// </summary>
///
/// <remarks>
/// This property is valid only for a ZipEntry that was read from a zip archive.
/// It indicates the type of timestamp attached to the entry.
/// </remarks>
///
/// <seealso cref="EmitTimesInWindowsFormatWhenSaving"/>
/// <seealso cref="EmitTimesInUnixFormatWhenSaving"/>
public ZipEntryTimestamp Timestamp
{
get
{
return _timestamp;
}
}
/// <summary>
/// The file attributes for the entry.
/// </summary>
///
/// <remarks>
///
/// <para>
/// The <see cref="System.IO.FileAttributes">attributes</see> in NTFS include
/// ReadOnly, Archive, Hidden, System, and Indexed. When adding a
/// <c>ZipEntry</c> to a ZipFile, these attributes are set implicitly when
/// adding an entry from the filesystem. When adding an entry from a stream
/// or string, the Attributes are not set implicitly. Regardless of the way
/// an entry was added to a <c>ZipFile</c>, you can set the attributes
/// explicitly if you like.
/// </para>
///
/// <para>
/// When reading a <c>ZipEntry</c> from a <c>ZipFile</c>, the attributes are
/// set according to the data stored in the <c>ZipFile</c>. If you extract the
/// entry from the archive to a filesystem file, DotNetZip will set the
/// attributes on the resulting file accordingly.
/// </para>
///
/// <para>
/// The attributes can be set explicitly by the application. For example the
/// application may wish to set the <c>FileAttributes.ReadOnly</c> bit for all
/// entries added to an archive, so that on unpack, this attribute will be set
/// on the extracted file. Any changes you make to this property are made
/// permanent only when you call a <c>Save()</c> method on the <c>ZipFile</c>
/// instance that contains the ZipEntry.
/// </para>
///
/// <para>
/// For example, an application may wish to zip up a directory and set the
/// ReadOnly bit on every file in the archive, so that upon later extraction,
/// the resulting files will be marked as ReadOnly. Not every extraction tool
/// respects these attributes, but if you unpack with DotNetZip, as for
/// example in a self-extracting archive, then the attributes will be set as
/// they are stored in the <c>ZipFile</c>.
/// </para>
///
/// <para>
/// These attributes may not be interesting or useful if the resulting archive
/// is extracted on a non-Windows platform. How these attributes get used
/// upon extraction depends on the platform and tool used.
/// </para>
///
/// <para>
/// This property is only partially supported in the Silverlight version
/// of the library: applications can read attributes on entries within
/// ZipFiles. But extracting entries within Silverlight will not set the
/// attributes on the extracted files.
/// </para>
///
/// </remarks>
public System.IO.FileAttributes Attributes
{
// workitem 7071
get { return (System.IO.FileAttributes)_ExternalFileAttrs; }
set
{
_ExternalFileAttrs = (int)value;
// Since the application is explicitly setting the attributes, overwriting
// whatever was there, we will explicitly set the Version made by field.
// workitem 7926 - "version made by" OS should be zero for compat with WinZip
_VersionMadeBy = (0 << 8) + 45; // v4.5 of the spec
_metadataChanged = true;
}
}
/// <summary>
/// The name of the filesystem file, referred to by the ZipEntry.
/// </summary>
///
/// <remarks>
/// <para>
/// This property specifies the thing-to-be-zipped on disk, and is set only
/// when the <c>ZipEntry</c> is being created from a filesystem file. If the
/// <c>ZipFile</c> is instantiated by reading an existing .zip archive, then
/// the LocalFileName will be <c>null</c> (<c>Nothing</c> in VB).
/// </para>
///
/// <para>
/// When it is set, the value of this property may be different than <see
/// cref="FileName"/>, which is the path used in the archive itself. If you
/// call <c>Zip.AddFile("foop.txt", AlternativeDirectory)</c>, then the path
/// used for the <c>ZipEntry</c> within the zip archive will be different
/// than this path.
/// </para>
///
/// <para>
/// If the entry is being added from a stream, then this is null (Nothing in VB).
/// </para>
///
/// </remarks>
/// <seealso cref="FileName"/>
internal string LocalFileName
{
get { return _LocalFileName; }
}
/// <summary>
/// The name of the file contained in the ZipEntry.
/// </summary>
///
/// <remarks>
///
/// <para>
/// This is the name of the entry in the <c>ZipFile</c> itself. When creating
/// a zip archive, if the <c>ZipEntry</c> has been created from a filesystem
/// file, via a call to <see cref="ZipFile.AddFile(String,String)"/> or <see
/// cref="ZipFile.AddItem(String,String)"/>, or a related overload, the value
/// of this property is derived from the name of that file. The
/// <c>FileName</c> property does not include drive letters, and may include a
/// different directory path, depending on the value of the
/// <c>directoryPathInArchive</c> parameter used when adding the entry into
/// the <c>ZipFile</c>.
/// </para>
///
/// <para>
/// In some cases there is no related filesystem file - for example when a
/// <c>ZipEntry</c> is created using <see cref="ZipFile.AddEntry(string,
/// string)"/> or one of the similar overloads. In this case, the value of
/// this property is derived from the fileName and the directory path passed
/// to that method.
/// </para>
///
/// <para>
/// When reading a zip file, this property takes the value of the entry name
/// as stored in the zip file. If you extract such an entry, the extracted
/// file will take the name given by this property.
/// </para>
///
/// <para>
/// Applications can set this property when creating new zip archives or when
/// reading existing archives. When setting this property, the actual value
/// that is set will replace backslashes with forward slashes, in accordance
/// with <see
/// href="http://www.pkware.com/documents/casestudies/APPNOTE.TXT">the Zip
/// specification</see>, for compatibility with Unix(tm) and ... get
/// this.... Amiga!
/// </para>
///
/// <para>
/// If an application reads a <c>ZipFile</c> via <see
/// cref="ZipFile.Read(String)"/> or a related overload, and then explicitly
/// sets the FileName on an entry contained within the <c>ZipFile</c>, and
/// then calls <see cref="ZipFile.Save()"/>, the application will effectively
/// rename the entry within the zip archive.
/// </para>
///
/// <para>
/// If an application sets the value of <c>FileName</c>, then calls
/// <c>Extract()</c> on the entry, the entry is extracted to a file using the
/// newly set value as the filename. The <c>FileName</c> value is made
/// permanent in the zip archive only <em>after</em> a call to one of the
/// <c>ZipFile.Save()</c> methods on the <c>ZipFile</c> that contains the
/// ZipEntry.
/// </para>
///
/// <para>
/// If an application attempts to set the <c>FileName</c> to a value that
/// would result in a duplicate entry in the <c>ZipFile</c>, an exception is
/// thrown.
/// </para>
///
/// <para>
/// When a <c>ZipEntry</c> is contained within a <c>ZipFile</c>, applications
/// cannot rename the entry within the context of a <c>foreach</c> (<c>For
/// Each</c> in VB) loop, because of the way the <c>ZipFile</c> stores
/// entries. If you need to enumerate through all the entries and rename one
/// or more of them, use <see
/// cref="ZipFile.EntriesSorted">ZipFile.EntriesSorted</see> as the
/// collection. See also, <see
/// cref="ZipFile.GetEnumerator()">ZipFile.GetEnumerator()</see>.
/// </para>
///
/// </remarks>
public string FileName
{
get { return _FileNameInArchive; }
set
{
if (_container.ZipFile == null)
throw new ZipException("Cannot rename; this is not supported in ZipOutputStream/ZipInputStream.");
// rename the entry!
if (String.IsNullOrEmpty(value)) throw new ZipException("The FileName must be non empty and non-null.");
var filename = ZipEntry.NameInArchive(value, null);
// workitem 8180
if (_FileNameInArchive == filename) return; // nothing to do
// workitem 8047 - when renaming, must remove old and then add a new entry
this._container.ZipFile.RemoveEntry(this);
this._container.ZipFile.InternalAddEntry(filename, this);
_FileNameInArchive = filename;
_container.ZipFile.NotifyEntryChanged();
_metadataChanged = true;
}
}
/// <summary>
/// The stream that provides content for the ZipEntry.
/// </summary>
///
/// <remarks>
///
/// <para>
/// The application can use this property to set the input stream for an
/// entry on a just-in-time basis. Imagine a scenario where the application
/// creates a <c>ZipFile</c> comprised of content obtained from hundreds of
/// files, via calls to <c>AddFile()</c>. The DotNetZip library opens streams
/// on these files on a just-in-time basis, only when writing the entry out to
/// an external store within the scope of a <c>ZipFile.Save()</c> call. Only
/// one input stream is opened at a time, as each entry is being written out.
/// </para>
///
/// <para>
/// Now imagine a different application that creates a <c>ZipFile</c>
/// with content obtained from hundreds of streams, added through <see
/// cref="ZipFile.AddEntry(string, System.IO.Stream)"/>. Normally the
/// application would supply an open stream to that call. But when large
/// numbers of streams are being added, this can mean many open streams at one
/// time, unnecessarily.
/// </para>
///
/// <para>
/// To avoid this, call <see cref="ZipFile.AddEntry(String, OpenDelegate,
/// CloseDelegate)"/> and specify delegates that open and close the stream at
/// the time of Save.
/// </para>
///
///
/// <para>
/// Setting the value of this property when the entry was not added from a
/// stream (for example, when the <c>ZipEntry</c> was added with <see
/// cref="ZipFile.AddFile(String)"/> or <see
/// cref="ZipFile.AddDirectory(String)"/>, or when the entry was added by
/// reading an existing zip archive) will throw an exception.
/// </para>
///
/// </remarks>
///
public Stream InputStream
{
get { return _sourceStream; }
set
{
if (this._Source != ZipEntrySource.Stream)
throw new ZipException("You must not set the input stream for this entry.");
_sourceWasJitProvided = true;
_sourceStream = value;
}
}
/// <summary>
/// A flag indicating whether the InputStream was provided Just-in-time.
/// </summary>
///
/// <remarks>
///
/// <para>
/// When creating a zip archive, an application can obtain content for one or
/// more of the <c>ZipEntry</c> instances from streams, using the <see
/// cref="ZipFile.AddEntry(string, System.IO.Stream)"/> method. At the time
/// of calling that method, the application can supply null as the value of
/// the stream parameter. By doing so, the application indicates to the
/// library that it will provide a stream for the entry on a just-in-time
/// basis, at the time one of the <c>ZipFile.Save()</c> methods is called and
/// the data for the various entries are being compressed and written out.
/// </para>
///
/// <para>
/// In this case, the application can set the <see cref="InputStream"/>
/// property, typically within the SaveProgress event (event type: <see
/// cref="ZipProgressEventType.Saving_BeforeWriteEntry"/>) for that entry.
/// </para>
///
/// <para>
/// The application will later want to call Close() and Dispose() on that
/// stream. In the SaveProgress event, when the event type is <see
/// cref="ZipProgressEventType.Saving_AfterWriteEntry"/>, the application can
/// do so. This flag indicates that the stream has been provided by the
/// application on a just-in-time basis and that it is the application's
/// responsibility to call Close/Dispose on that stream.
/// </para>
///
/// </remarks>
/// <seealso cref="InputStream"/>
public bool InputStreamWasJitProvided
{
get { return _sourceWasJitProvided; }
}
/// <summary>
/// An enum indicating the source of the ZipEntry.
/// </summary>
public ZipEntrySource Source
{
get { return _Source; }
}
/// <summary>
/// The version of the zip engine needed to read the ZipEntry.
/// </summary>
///
/// <remarks>
/// <para>
/// This is a readonly property, indicating the version of <a