Statistics
| Branch: | Revision:

root / trunk / hammock / src / net35 / ICSharpCode.SharpZipLib.Silverlight.Tests / Zip / ZipTests.cs @ 0eea575a

History | View | Annotate | Download (121.8 kB)

1
using System;
2
using System.IO;
3
using System.Reflection;
4
using System.Security;
5
using System.Text;
6
using System.Threading;
7
using ICSharpCode.SharpZipLib.Silverlight.Checksums;
8
using ICSharpCode.SharpZipLib.Silverlight.Core;
9
using ICSharpCode.SharpZipLib.Silverlight.Serialization;
10
using ICSharpCode.SharpZipLib.Silverlight.Zip;
11
using ICSharpCode.SharpZipLib.Tests.TestSupport;
12
using ICSharpCode.SharpZipLib.Zip;
13
using NUnit.Framework;
14

    
15
namespace ICSharpCode.SharpZipLib.Tests.Zip
16
{
17

    
18
    #region Local Support Classes
19

    
20
    internal class RuntimeInfo
21
    {
22
        public RuntimeInfo(CompressionMethod method, int compressionLevel, int size, string password, bool getCrc)
23
        {
24
            this.method = method;
25
            this.compressionLevel = compressionLevel;
26
            this.password = password;
27
            this.size = size;
28
            random = false;
29

    
30
            original = new byte[Size];
31
            if (random)
32
            {
33
                var rnd = new Random();
34
                rnd.NextBytes(original);
35
            }
36
            else
37
            {
38
                for (var i = 0; i < size; ++i)
39
                {
40
                    original[i] = (byte) 'A';
41
                }
42
            }
43

    
44
            if (getCrc)
45
            {
46
                var crc32 = new Crc32();
47
                crc32.Update(original, 0, size);
48
                crc = crc32.Value;
49
            }
50
        }
51

    
52

    
53
        public RuntimeInfo(string password, bool isDirectory)
54
        {
55
            method = CompressionMethod.Stored;
56
            compressionLevel = 1;
57
            this.password = password;
58
            size = 0;
59
            random = false;
60
            isDirectory_ = isDirectory;
61
            original = new byte[0];
62
        }
63

    
64

    
65
        public byte[] Original
66
        {
67
            get { return original; }
68
        }
69

    
70
        public CompressionMethod Method
71
        {
72
            get { return method; }
73
        }
74

    
75
        public int CompressionLevel
76
        {
77
            get { return compressionLevel; }
78
        }
79

    
80
        public int Size
81
        {
82
            get { return size; }
83
        }
84

    
85
        public string Password
86
        {
87
            get { return password; }
88
        }
89

    
90
        private bool Random
91
        {
92
            get { return random; }
93
        }
94

    
95
        public long Crc
96
        {
97
            get { return crc; }
98
        }
99

    
100
        public bool IsDirectory
101
        {
102
            get { return isDirectory_; }
103
        }
104

    
105
        #region Instance Fields
106

    
107
        private readonly int compressionLevel;
108
        private readonly long crc = -1;
109
        private readonly bool isDirectory_;
110
        private readonly CompressionMethod method;
111
        private readonly byte[] original;
112
        private readonly string password;
113
        private readonly bool random;
114
        private readonly int size;
115

    
116
        #endregion
117
    }
118

    
119
    internal class MemoryDataSource : IStaticDataSource
120
    {
121
        #region Constructors
122

    
123
        /// <summary>
124
        /// Initialise a new instance.
125
        /// </summary>
126
        /// <param name="data">The data to provide.</param>
127
        public MemoryDataSource(byte[] data)
128
        {
129
            data_ = data;
130
        }
131

    
132
        #endregion
133

    
134
        #region IStaticDataSource Members
135

    
136
        /// <summary>
137
        /// Get a Stream for this <see cref="DataSource"/>
138
        /// </summary>
139
        /// <returns>Returns a <see cref="Stream"/></returns>
140
        public Stream GetSource()
141
        {
142
            return new MemoryStream(data_);
143
        }
144

    
145
        #endregion
146

    
147
        #region Instance Fields
148

    
149
        private readonly byte[] data_;
150

    
151
        #endregion
152
    }
153

    
154
    internal class StringMemoryDataSource : MemoryDataSource
155
    {
156
        public StringMemoryDataSource(string data)
157
            : base(Encoding.UTF8.GetBytes(data))
158
        {
159
        }
160
    }
161

    
162
    #endregion
163

    
164
    #region ZipBase
165

    
166
    public class ZipBase
167
    {
168
        protected static string GetTempFilePath()
169
        {
170
            string result = null;
171
            try
172
            {
173
                result = Path.GetTempPath();
174
            }
175
            catch (SecurityException)
176
            {
177
            }
178
            return result;
179
        }
180

    
181
        protected byte[] MakeInMemoryZip(bool withSeek, params object[] createSpecs)
182
        {
183
            MemoryStream ms;
184

    
185
            if (withSeek)
186
            {
187
                ms = new MemoryStream();
188
            }
189
            else
190
            {
191
                ms = new MemoryStreamWithoutSeek();
192
            }
193

    
194
            using (var outStream = new ZipOutputStream(ms))
195
            {
196
                for (var counter = 0; counter < createSpecs.Length; ++counter)
197
                {
198
                    var info = createSpecs[counter] as RuntimeInfo;
199
                    outStream.Password = info.Password;
200

    
201
                    if (info.Method != CompressionMethod.Stored)
202
                    {
203
                        outStream.SetLevel(info.CompressionLevel); // 0 - store only to 9 - means best compression
204
                    }
205

    
206
                    string entryName;
207

    
208
                    if (info.IsDirectory)
209
                    {
210
                        entryName = "dir" + counter + "/";
211
                    }
212
                    else
213
                    {
214
                        entryName = "entry" + counter + ".tst";
215
                    }
216

    
217
                    var entry = new ZipEntry(entryName);
218
                    entry.CompressionMethod = info.Method;
219
                    if (info.Crc >= 0)
220
                    {
221
                        entry.Crc = info.Crc;
222
                    }
223

    
224
                    outStream.PutNextEntry(entry);
225

    
226
                    if (info.Size > 0)
227
                    {
228
                        outStream.Write(info.Original, 0, info.Original.Length);
229
                    }
230
                }
231
            }
232
            return ms.ToArray();
233
        }
234

    
235
        protected byte[] MakeInMemoryZip(ref byte[] original, CompressionMethod method,
236
                                         int compressionLevel, int size, string password, bool withSeek)
237
        {
238
            MemoryStream ms;
239

    
240
            if (withSeek)
241
            {
242
                ms = new MemoryStream();
243
            }
244
            else
245
            {
246
                ms = new MemoryStreamWithoutSeek();
247
            }
248

    
249
            using (var outStream = new ZipOutputStream(ms))
250
            {
251
                outStream.Password = password;
252

    
253
                if (method != CompressionMethod.Stored)
254
                {
255
                    outStream.SetLevel(compressionLevel); // 0 - store only to 9 - means best compression
256
                }
257

    
258
                var entry = new ZipEntry("dummyfile.tst");
259
                entry.CompressionMethod = method;
260

    
261
                outStream.PutNextEntry(entry);
262

    
263
                if (size > 0)
264
                {
265
                    var rnd = new Random();
266
                    original = new byte[size];
267
                    rnd.NextBytes(original);
268

    
269
                    outStream.Write(original, 0, original.Length);
270
                }
271
            }
272
            return ms.ToArray();
273
        }
274

    
275
        protected static void MakeTempFile(string name, int size)
276
        {
277
            using (var fs = File.Create(name))
278
            {
279
                var buffer = new byte[4096];
280
                while (size > 0)
281
                {
282
                    fs.Write(buffer, 0, Math.Min(size, buffer.Length));
283
                    size -= buffer.Length;
284
                }
285
            }
286
        }
287

    
288
        protected static byte ScatterValue(byte rhs)
289
        {
290
            return (byte) ((rhs*253 + 7) & 0xff);
291
        }
292

    
293

    
294
        private static void AddKnownDataToEntry(ZipOutputStream zipStream, int size)
295
        {
296
            if (size > 0)
297
            {
298
                byte nextValue = 0;
299
                var bufferSize = Math.Min(size, 65536);
300
                var data = new byte[bufferSize];
301
                var currentIndex = 0;
302
                for (var i = 0; i < size; ++i)
303
                {
304
                    data[currentIndex] = nextValue;
305
                    nextValue = ScatterValue(nextValue);
306

    
307
                    currentIndex += 1;
308
                    if ((currentIndex >= data.Length) || (i + 1 == size))
309
                    {
310
                        zipStream.Write(data, 0, currentIndex);
311
                        currentIndex = 0;
312
                    }
313
                }
314
            }
315
        }
316

    
317
        public void WriteToFile(string fileName, byte[] data)
318
        {
319
            using (var fs = File.Open(fileName, FileMode.Create, FileAccess.ReadWrite, FileShare.Read))
320
            {
321
                fs.Write(data, 0, data.Length);
322
            }
323
        }
324

    
325
        protected static void CheckKnownEntry(Stream inStream, int expectedCount)
326
        {
327
            var buffer = new byte[1024];
328

    
329
            int bytesRead;
330
            var total = 0;
331
            byte nextValue = 0;
332
            while ((bytesRead = inStream.Read(buffer, 0, buffer.Length)) > 0)
333
            {
334
                total += bytesRead;
335
                for (var i = 0; i < bytesRead; ++i)
336
                {
337
                    Assert.AreEqual(nextValue, buffer[i], "Wrong value read from entry");
338
                    nextValue = ScatterValue(nextValue);
339
                }
340
            }
341
            Assert.AreEqual(expectedCount, total, "Wrong number of bytes read from entry");
342
        }
343

    
344
        protected byte ReadByteChecked(Stream stream)
345
        {
346
            var rawValue = stream.ReadByte();
347
            Assert.IsTrue(rawValue >= 0);
348
            return (byte) rawValue;
349
        }
350

    
351
        protected int ReadInt(Stream stream)
352
        {
353
            return ReadByteChecked(stream) |
354
                   (ReadByteChecked(stream) << 8) |
355
                   (ReadByteChecked(stream) << 16) |
356
                   (ReadByteChecked(stream) << 24);
357
        }
358

    
359
        protected long ReadLong(Stream stream)
360
        {
361
            var result = ReadInt(stream) & 0xffffffff;
362
            return result | (((long) ReadInt(stream)) << 32);
363
        }
364

    
365
        #region MakeZipFile Names
366

    
367
        protected void MakeZipFile(Stream storage, bool isOwner, string[] names, int size, string comment)
368
        {
369
            using (var zOut = new ZipOutputStream(storage))
370
            {
371
                zOut.IsStreamOwner = isOwner;
372
                zOut.SetComment(comment);
373
                for (var i = 0; i < names.Length; ++i)
374
                {
375
                    zOut.PutNextEntry(new ZipEntry(names[i]));
376
                    AddKnownDataToEntry(zOut, size);
377
                }
378
                zOut.Close();
379
            }
380
        }
381

    
382
        protected void MakeZipFile(string name, string[] names, int size, string comment)
383
        {
384
            using (var fs = File.Create(name))
385
            {
386
                using (var zOut = new ZipOutputStream(fs))
387
                {
388
                    zOut.SetComment(comment);
389
                    for (var i = 0; i < names.Length; ++i)
390
                    {
391
                        zOut.PutNextEntry(new ZipEntry(names[i]));
392
                        AddKnownDataToEntry(zOut, size);
393
                    }
394
                    zOut.Close();
395
                }
396
                fs.Close();
397
            }
398
        }
399

    
400
        #endregion
401

    
402
        #region MakeZipFile Entries
403

    
404
        protected void MakeZipFile(string name, string entryNamePrefix, int entries, int size, string comment)
405
        {
406
            using (var fs = File.Create(name))
407
            {
408
                using (var zOut = new ZipOutputStream(fs))
409
                {
410
                    zOut.SetComment(comment);
411
                    for (var i = 0; i < entries; ++i)
412
                    {
413
                        zOut.PutNextEntry(new ZipEntry(entryNamePrefix + (i + 1)));
414
                        AddKnownDataToEntry(zOut, size);
415
                    }
416
                }
417
            }
418
        }
419

    
420
        protected void MakeZipFile(Stream storage, bool isOwner,
421
                                   string entryNamePrefix, int entries, int size, string comment)
422
        {
423
            using (var zOut = new ZipOutputStream(storage))
424
            {
425
                zOut.IsStreamOwner = isOwner;
426
                zOut.SetComment(comment);
427
                for (var i = 0; i < entries; ++i)
428
                {
429
                    zOut.PutNextEntry(new ZipEntry(entryNamePrefix + (i + 1)));
430
                    AddKnownDataToEntry(zOut, size);
431
                }
432
            }
433
        }
434

    
435
        #endregion
436
    }
437

    
438
    #endregion
439

    
440
    internal class TestHelper
441
    {
442
        public static void SaveMemoryStream(MemoryStream ms, string fileName)
443
        {
444
            var data = ms.ToArray();
445
            using (var fs = File.Open(fileName, FileMode.Create, FileAccess.ReadWrite, FileShare.Read))
446
            {
447
                fs.Write(data, 0, data.Length);
448
            }
449
        }
450

    
451
        public static int CompareDosDateTimes(DateTime l, DateTime r)
452
        {
453
            // Compare dates to dos accuracy...
454
            // Ticks can be different yet all these values are still the same!
455
            var result = l.Year - r.Year;
456
            if (result == 0)
457
            {
458
                result = l.Month - r.Month;
459
                if (result == 0)
460
                {
461
                    result = l.Day - r.Day;
462
                    if (result == 0)
463
                    {
464
                        result = l.Hour - r.Hour;
465
                        if (result == 0)
466
                        {
467
                            result = l.Minute - r.Minute;
468
                            if (result == 0)
469
                            {
470
                                result = (l.Second/2) - (r.Second/2);
471
                            }
472
                        }
473
                    }
474
                }
475
            }
476

    
477
            return result;
478
        }
479
    }
480

    
481
    [TestFixture]
482
    public class ZipEntryHandling : ZipBase
483
    {
484
        private void PiecewiseCompare(ZipEntry lhs, ZipEntry rhs)
485
        {
486
            var entryType = typeof (ZipEntry);
487
            var binding = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance;
488

    
489
            var fields = entryType.GetFields(binding);
490

    
491
            Assert.Greater(fields.Length, 8, "Failed to find fields");
492

    
493
            foreach (var info in fields)
494
            {
495
                var lValue = info.GetValue(lhs);
496
                var rValue = info.GetValue(rhs);
497

    
498
                Assert.AreEqual(lValue, rValue);
499
            }
500
        }
501

    
502
        /// <summary>
503
        /// Check that cloned entries are correct.
504
        /// </summary>
505
        [Test]
506
        [Category("Zip")]
507
        public void Cloning()
508
        {
509
            long testCrc = 3456;
510
            long testSize = 99874276;
511
            long testCompressedSize = 72347;
512
            var testExtraData = new byte[]{0x00, 0x01, 0x00, 0x02, 0x0EF, 0xFE};
513
            var testName = "Namu";
514
            var testFlags = 4567;
515
            long testDosTime = 23434536;
516
            var testMethod = CompressionMethod.Deflated;
517

    
518
            var testComment = "A comment";
519

    
520
            var source = new ZipEntry(testName);
521
            source.Crc = testCrc;
522
            source.Comment = testComment;
523
            source.Size = testSize;
524
            source.CompressedSize = testCompressedSize;
525
            source.ExtraData = testExtraData;
526
            source.Flags = testFlags;
527
            source.DosTime = testDosTime;
528
            source.CompressionMethod = testMethod;
529

    
530
            var clone = (ZipEntry) source.Clone();
531

    
532
            // Check values against originals
533
            Assert.AreEqual(testName, clone.Name, "Cloned name mismatch");
534
            Assert.AreEqual(testCrc, clone.Crc, "Cloned crc mismatch");
535
            Assert.AreEqual(testComment, clone.Comment, "Cloned comment mismatch");
536
            Assert.AreEqual(testExtraData, clone.ExtraData, "Cloned Extra data mismatch");
537
            Assert.AreEqual(testSize, clone.Size, "Cloned size mismatch");
538
            Assert.AreEqual(testCompressedSize, clone.CompressedSize, "Cloned compressed size mismatch");
539
            Assert.AreEqual(testFlags, clone.Flags, "Cloned flags mismatch");
540
            Assert.AreEqual(testDosTime, clone.DosTime, "Cloned DOSTime mismatch");
541
            Assert.AreEqual(testMethod, clone.CompressionMethod, "Cloned Compression method mismatch");
542

    
543
            // Check against source
544
            PiecewiseCompare(source, clone);
545
        }
546

    
547
        /// <summary>
548
        /// Test that obsolete copy constructor works correctly.
549
        /// </summary>
550
        [Test]
551
        [Category("Zip")]
552
        public void Copying()
553
        {
554
            long testCrc = 3456;
555
            long testSize = 99874276;
556
            long testCompressedSize = 72347;
557
            var testExtraData = new byte[]{0x00, 0x01, 0x00, 0x02, 0x0EF, 0xFE};
558
            var testName = "Namu";
559
            var testFlags = 4567;
560
            long testDosTime = 23434536;
561
            var testMethod = CompressionMethod.Deflated;
562

    
563
            var testComment = "A comment";
564

    
565
            var source = new ZipEntry(testName);
566
            source.Crc = testCrc;
567
            source.Comment = testComment;
568
            source.Size = testSize;
569
            source.CompressedSize = testCompressedSize;
570
            source.ExtraData = testExtraData;
571
            source.Flags = testFlags;
572
            source.DosTime = testDosTime;
573
            source.CompressionMethod = testMethod;
574

    
575
#pragma warning disable 0618
576
            var clone = new ZipEntry(source);
577
#pragma warning restore
578

    
579
            PiecewiseCompare(source, clone);
580
        }
581

    
582
        [Test]
583
        [Category("Zip")]
584
        public void DateAndTime()
585
        {
586
            var ze = new ZipEntry("Pok");
587

    
588
            // -1 is not strictly a valid MS-DOS DateTime value.
589
            // ZipEntry is lenient about handling invalid values.
590
            ze.DosTime = -1;
591

    
592
            Assert.AreEqual(new DateTime(2107, 12, 31, 23, 59, 59), ze.DateTime);
593

    
594
            // 0 is a special value meaning Now.
595
            ze.DosTime = 0;
596
            var diff = DateTime.Now - ze.DateTime;
597

    
598
            // Value == 2 seconds!
599
            ze.DosTime = 1;
600
            Assert.AreEqual(new DateTime(1980, 1, 1, 0, 0, 2), ze.DateTime);
601

    
602
            // Over the limit are set to max.
603
            ze.DateTime = new DateTime(2108, 1, 1);
604
            Assert.AreEqual(new DateTime(2107, 12, 31, 23, 59, 58), ze.DateTime);
605

    
606
            // Under the limit are set to min.
607
            ze.DateTime = new DateTime(1906, 12, 4);
608
            Assert.AreEqual(new DateTime(1980, 1, 1, 0, 0, 0), ze.DateTime);
609
        }
610

    
611
        [Test]
612
        [Category("Zip")]
613
        public void DateTimeSetsDosTime()
614
        {
615
            var ze = new ZipEntry("Pok");
616

    
617
            var original = ze.DosTime;
618

    
619
            ze.DateTime = new DateTime(1987, 9, 12);
620
            Assert.AreNotEqual(original, ze.DosTime);
621
            Assert.AreEqual(0, TestHelper.CompareDosDateTimes(new DateTime(1987, 9, 12), ze.DateTime));
622
        }
623

    
624
        /// <summary>
625
        /// Setting entry comments to null should be allowed
626
        /// </summary>
627
        [Test]
628
        [Category("Zip")]
629
        public void NullEntryComment()
630
        {
631
            var test = new ZipEntry("null");
632
            test.Comment = null;
633
        }
634

    
635
        /// <summary>
636
        /// Entries with null names arent allowed
637
        /// </summary>
638
        [Test]
639
        [Category("Zip")]
640
        [ExpectedException(typeof (ArgumentNullException))]
641
        public void NullNameInConstructor()
642
        {
643
            string name = null;
644
            var test = new ZipEntry(name);
645
        }
646
    }
647

    
648
    /// <summary>
649
    /// This contains newer tests for stream handling. Much of this is still in GeneralHandling
650
    /// </summary>
651
    [TestFixture]
652
    public class StreamHandling : ZipBase
653
    {
654
        private void MustFailRead(Stream s, byte[] buffer, int offset, int count)
655
        {
656
            var exception = false;
657
            try
658
            {
659
                s.Read(buffer, offset, count);
660
            }
661
            catch
662
            {
663
                exception = true;
664
            }
665
            Assert.IsTrue(exception, "Read should fail");
666
        }
667

    
668
        private void Reader()
669
        {
670
            const int Size = 8192;
671
            var readBytes = 1;
672
            var buffer = new byte[Size];
673

    
674
            var passifierLevel = readTarget_ - 0x10000000;
675
            var single = inStream_.GetNextEntry();
676

    
677
            Assert.AreEqual(single.Name, "CantSeek");
678
            Assert.IsTrue((single.Flags & (int) GeneralBitFlags.Descriptor) != 0);
679

    
680
            while ((readTarget_ > 0) && (readBytes > 0))
681
            {
682
                var count = Size;
683
                if (count > readTarget_)
684
                {
685
                    count = (int) readTarget_;
686
                }
687

    
688
                readBytes = inStream_.Read(buffer, 0, count);
689
                readTarget_ -= readBytes;
690

    
691
                if (readTarget_ <= passifierLevel)
692
                {
693
                    Console.WriteLine("Reader {0} bytes remaining", readTarget_);
694
                    passifierLevel = readTarget_ - 0x10000000;
695
                }
696
            }
697

    
698
            Assert.IsTrue(window_.IsClosed, "Window should be closed");
699

    
700
            // This shouldnt read any data but should read the footer
701
            readBytes = inStream_.Read(buffer, 0, 1);
702
            Assert.AreEqual(0, readBytes, "Stream should be empty");
703
            Assert.AreEqual(0, window_.Length, "Window should be closed");
704
            inStream_.Close();
705
        }
706

    
707
        private void WriteTargetBytes()
708
        {
709
            const int Size = 8192;
710

    
711
            var buffer = new byte[Size];
712

    
713
            while (writeTarget_ > 0)
714
            {
715
                var thisTime = Size;
716
                if (thisTime > writeTarget_)
717
                {
718
                    thisTime = (int) writeTarget_;
719
                }
720

    
721
                outStream_.Write(buffer, 0, thisTime);
722
                writeTarget_ -= thisTime;
723
            }
724
        }
725

    
726
        private void Writer()
727
        {
728
            outStream_.PutNextEntry(new ZipEntry("CantSeek"));
729
            WriteTargetBytes();
730
            outStream_.Close();
731
        }
732

    
733
        private WindowedStream window_;
734
        private ZipOutputStream outStream_;
735
        private ZipInputStream inStream_;
736
        private long readTarget_;
737
        private long writeTarget_;
738

    
739
        /// <summary>
740
        /// Check that base stream is not closed when IsOwner is false;
741
        /// </summary>
742
        [Test]
743
        public void BaseClosedAfterFailure()
744
        {
745
            var ms = new MemoryStreamEx(new byte[32]);
746

    
747
            Assert.IsFalse(ms.IsClosed, "Underlying stream should NOT be closed initially");
748
            var blewUp = false;
749
            try
750
            {
751
                using (var stream = new ZipOutputStream(ms))
752
                {
753
                    Assert.IsTrue(stream.IsStreamOwner, "Should be stream owner by default");
754
                    try
755
                    {
756
                        stream.PutNextEntry(new ZipEntry("Tiny"));
757
                        stream.Write(new byte[32], 0, 32);
758
                    }
759
                    finally
760
                    {
761
                        Assert.IsFalse(ms.IsClosed, "Stream should still not be closed.");
762
                        stream.Close();
763
                        Assert.Fail("Exception not thrown");
764
                    }
765
                }
766
            }
767
            catch
768
            {
769
                blewUp = true;
770
            }
771

    
772
            Assert.IsTrue(blewUp, "Should have failed to write to stream");
773
            Assert.IsTrue(ms.IsClosed, "Underlying stream should be closed");
774
        }
775

    
776
        /// <summary>
777
        /// Base stream is closed when IsOwner is true ( default);
778
        /// </summary>
779
        [Test]
780
        public void BaseClosedWhenOwner()
781
        {
782
            var ms = new MemoryStreamEx();
783

    
784
            Assert.IsFalse(ms.IsClosed, "Underlying stream should NOT be closed");
785

    
786
            using (var stream = new ZipOutputStream(ms))
787
            {
788
                Assert.IsTrue(stream.IsStreamOwner, "Should be stream owner by default");
789
            }
790

    
791
            Assert.IsTrue(ms.IsClosed, "Underlying stream should be closed");
792
        }
793

    
794
        /// <summary>
795
        /// Check that base stream is not closed when IsOwner is false;
796
        /// </summary>
797
        [Test]
798
        public void BaseNotClosedWhenNotOwner()
799
        {
800
            var ms = new MemoryStreamEx();
801

    
802
            Assert.IsFalse(ms.IsClosed, "Underlying stream should NOT be closed");
803

    
804
            using (var stream = new ZipOutputStream(ms))
805
            {
806
                Assert.IsTrue(stream.IsStreamOwner, "Should be stream owner by default");
807
                stream.IsStreamOwner = false;
808
            }
809
            Assert.IsFalse(ms.IsClosed, "Underlying stream should still NOT be closed");
810
        }
811

    
812
        /// <summary>
813
        /// Empty zips can be created and read?
814
        /// </summary>
815
        [Test]
816
        [Category("Zip")]
817
        public void CreateAndReadEmptyZip()
818
        {
819
            var ms = new MemoryStream();
820
            var outStream = new ZipOutputStream(ms);
821
            outStream.Finish();
822

    
823
            ms.Seek(0, SeekOrigin.Begin);
824

    
825
            var inStream = new ZipInputStream(ms);
826
            ZipEntry entry;
827
            while ((entry = inStream.GetNextEntry()) != null)
828
            {
829
                Assert.Fail("No entries should be found in empty zip");
830
            }
831
        }
832

    
833
        /// <summary>
834
        /// Empty zip entries can be created and read?
835
        /// </summary>
836
        [Test]
837
        [Category("Zip")]
838
        public void EmptyZipEntries()
839
        {
840
            var ms = new MemoryStream();
841
            var outStream = new ZipOutputStream(ms);
842
            for (var i = 0; i < 10; ++i)
843
            {
844
                outStream.PutNextEntry(new ZipEntry(i.ToString()));
845
            }
846
            outStream.Finish();
847

    
848
            ms.Seek(0, SeekOrigin.Begin);
849

    
850
            var inStream = new ZipInputStream(ms);
851

    
852
            var extractCount = 0;
853
            ZipEntry entry;
854
            var decompressedData = new byte[100];
855

    
856
            while ((entry = inStream.GetNextEntry()) != null)
857
            {
858
                while (true)
859
                {
860
                    var numRead = inStream.Read(decompressedData, extractCount, decompressedData.Length);
861
                    if (numRead <= 0)
862
                    {
863
                        break;
864
                    }
865
                    extractCount += numRead;
866
                }
867
            }
868
            inStream.Close();
869
            Assert.AreEqual(extractCount, 0, "No data should be read from empty entries");
870
        }
871

    
872
        /// <summary>
873
        /// Check that adding an entry with no data and Zip64 works OK
874
        /// </summary>
875
        [Test]
876
        [Category("Zip")]
877
        public void EntryWithNoDataAndZip64()
878
        {
879
            MemoryStream msw = new MemoryStreamWithoutSeek();
880
            var outStream = new ZipOutputStream(msw);
881

    
882
            outStream.IsStreamOwner = false;
883
            var ze = new ZipEntry("Striped Marlin");
884
            ze.ForceZip64();
885
            ze.Size = 0;
886
            outStream.PutNextEntry(ze);
887
            outStream.CloseEntry();
888
            outStream.Finish();
889
            outStream.Close();
890

    
891
            var ms = new MemoryStream(msw.ToArray());
892
            using (var zf = new ZipFile(ms))
893
            {
894
                Assert.IsTrue(zf.TestArchive(true));
895
            }
896
        }
897

    
898
        [Test]
899
        [Category("Zip")]
900
        public void ParameterHandling()
901
        {
902
            var buffer = new byte[10];
903
            var emptyBuffer = new byte[0];
904

    
905
            var ms = new MemoryStream();
906
            var outStream = new ZipOutputStream(ms);
907
            outStream.IsStreamOwner = false;
908
            outStream.PutNextEntry(new ZipEntry("Floyd"));
909
            outStream.Write(buffer, 0, 10);
910
            outStream.Finish();
911

    
912
            ms.Seek(0, SeekOrigin.Begin);
913

    
914
            var inStream = new ZipInputStream(ms);
915
            var e = inStream.GetNextEntry();
916

    
917
            MustFailRead(inStream, null, 0, 0);
918
            MustFailRead(inStream, buffer, -1, 1);
919
            MustFailRead(inStream, buffer, 0, 11);
920
            MustFailRead(inStream, buffer, 7, 5);
921
            MustFailRead(inStream, buffer, 0, -1);
922

    
923
            MustFailRead(inStream, emptyBuffer, 0, 1);
924

    
925
            var bytesRead = inStream.Read(buffer, 10, 0);
926
            Assert.AreEqual(0, bytesRead, "Should be able to read zero bytes");
927

    
928
            bytesRead = inStream.Read(emptyBuffer, 0, 0);
929
            Assert.AreEqual(0, bytesRead, "Should be able to read zero bytes");
930
        }
931

    
932
        [Test]
933
        [Category("Zip")]
934
        [Category("Long Running")]
935
        public void SingleLargeEntry()
936
        {
937
            window_ = new WindowedStream(0x10000);
938
            outStream_ = new ZipOutputStream(window_);
939
            inStream_ = new ZipInputStream(window_);
940

    
941
            long target = 0x10000000;
942
            readTarget_ = writeTarget_ = target;
943

    
944
            var reader = new Thread(Reader);
945
            reader.Name = "Reader";
946

    
947
            var writer = new Thread(Writer);
948
            writer.Name = "Writer";
949

    
950
            var startTime = DateTime.Now;
951
            reader.Start();
952
            writer.Start();
953

    
954
            writer.Join();
955
            reader.Join();
956

    
957
            var endTime = DateTime.Now;
958
            var span = endTime - startTime;
959
            Console.WriteLine("Time {0} throughput {1} KB/Sec", span, (target/1024)/span.TotalSeconds);
960
        }
961

    
962
        [Test]
963
        [Category("Zip")]
964
        public void WriteThroughput()
965
        {
966
            outStream_ = new ZipOutputStream(new NullStream());
967

    
968
            var startTime = DateTime.Now;
969

    
970
            long target = 0x10000000;
971

    
972
            writeTarget_ = target;
973
            outStream_.PutNextEntry(new ZipEntry("0"));
974
            WriteTargetBytes();
975

    
976
            outStream_.Close();
977

    
978
            var endTime = DateTime.Now;
979
            var span = endTime - startTime;
980
            Console.WriteLine("Time {0} throughput {1} KB/Sec", span, (target/1024)/span.TotalSeconds);
981
        }
982

    
983
        /// <summary>
984
        /// Check that Zip64 descriptor is added to an entry OK.
985
        /// </summary>
986
        [Test]
987
        [Category("Zip")]
988
        public void Zip64Descriptor()
989
        {
990
            MemoryStream msw = new MemoryStreamWithoutSeek();
991
            var outStream = new ZipOutputStream(msw);
992
            outStream.UseZip64 = UseZip64.Off;
993

    
994
            outStream.IsStreamOwner = false;
995
            outStream.PutNextEntry(new ZipEntry("StripedMarlin"));
996
            outStream.WriteByte(89);
997
            outStream.Close();
998

    
999
            var ms = new MemoryStream(msw.ToArray());
1000
            using (var zf = new ZipFile(ms))
1001
            {
1002
                Assert.IsTrue(zf.TestArchive(true));
1003
            }
1004

    
1005

    
1006
            msw = new MemoryStreamWithoutSeek();
1007
            outStream = new ZipOutputStream(msw);
1008
            outStream.UseZip64 = UseZip64.On;
1009

    
1010
            outStream.IsStreamOwner = false;
1011
            outStream.PutNextEntry(new ZipEntry("StripedMarlin"));
1012
            outStream.WriteByte(89);
1013
            outStream.Close();
1014

    
1015
            ms = new MemoryStream(msw.ToArray());
1016
            using (var zf = new ZipFile(ms))
1017
            {
1018
                Assert.IsTrue(zf.TestArchive(true));
1019
            }
1020
        }
1021
    }
1022

    
1023
    [TestFixture]
1024
    public class NameHandling : ZipBase
1025
    {
1026
        private void TestFile(ZipNameTransform t, string original, string expected)
1027
        {
1028
            var transformed = t.TransformFile(original);
1029
            Assert.AreEqual(expected, transformed, "Should be equal");
1030
        }
1031

    
1032
        [Test]
1033
        [Category("Zip")]
1034
        public void Basic()
1035
        {
1036
            var t = new ZipNameTransform();
1037

    
1038
            TestFile(t, "abcdef", "abcdef");
1039
            TestFile(t, @"\\uncpath\d1\file1", "file1");
1040
            TestFile(t, @"C:\absolute\file2", "absolute/file2");
1041

    
1042
            // This is ignored but could be converted to 'file3'
1043
            TestFile(t, @"./file3", "./file3");
1044

    
1045
            // The following relative paths cant be handled and are ignored
1046
            TestFile(t, @"../file3", "../file3");
1047
            TestFile(t, @".../file3", ".../file3");
1048

    
1049
            // Trick filenames.
1050
            TestFile(t, @".....file3", ".....file3");
1051
        }
1052

    
1053
        /// <summary>
1054
        /// Test ZipEntry static file name cleaning methods
1055
        /// </summary>
1056
        [Test]
1057
        [Category("Zip")]
1058
        public void FilenameCleaning()
1059
        {
1060
            Assert.AreEqual(0, string.Compare(ZipEntry.CleanName("hello"), "hello"));
1061
            Assert.AreEqual(0, string.Compare(ZipEntry.CleanName(@"z:\eccles"), "eccles"));
1062
            Assert.AreEqual(0, string.Compare(ZipEntry.CleanName(@"\\server\share\eccles"), "eccles"));
1063
            Assert.AreEqual(0, string.Compare(ZipEntry.CleanName(@"\\server\share\dir\eccles"), "dir/eccles"));
1064
        }
1065

    
1066
        [Test]
1067
        [Category("Zip")]
1068
        public void NameTransforms()
1069
        {
1070
            INameTransform t = new ZipNameTransform(@"C:\Slippery");
1071
            Assert.AreEqual("Pongo/Directory/", t.TransformDirectory(@"C:\Slippery\Pongo\Directory"),
1072
                            "Value should be trimmed and converted");
1073
            Assert.AreEqual("PoNgo/Directory/", t.TransformDirectory(@"c:\slipperY\PoNgo\Directory"),
1074
                            "Trimming should be case insensitive");
1075
            Assert.AreEqual("slippery/Pongo/Directory/", t.TransformDirectory(@"d:\slippery\Pongo\Directory"),
1076
                            "Trimming should be case insensitive");
1077
        }
1078

    
1079
        [Test]
1080
        [Category("Zip")]
1081
        public void PathalogicalNames()
1082
        {
1083
            var badName = ".*:\\zy3$";
1084

    
1085
            Assert.IsFalse(ZipNameTransform.IsValidName(badName));
1086

    
1087
            var t = new ZipNameTransform();
1088
            var result = t.TransformFile(badName);
1089

    
1090
            Assert.IsTrue(ZipNameTransform.IsValidName(result));
1091
        }
1092
    }
1093

    
1094
    /// <summary>
1095
    /// This class contains test cases for Zip compression and decompression
1096
    /// </summary>
1097
    [TestFixture]
1098
    public class GeneralHandling : ZipBase
1099
    {
1100
        private void AddRandomDataToEntry(ZipOutputStream zipStream, int size)
1101
        {
1102
            if (size > 0)
1103
            {
1104
                var data = new byte[size];
1105
                var rnd = new Random();
1106
                rnd.NextBytes(data);
1107

    
1108
                zipStream.Write(data, 0, data.Length);
1109
            }
1110
        }
1111

    
1112
        private void ExerciseZip(CompressionMethod method, int compressionLevel,
1113
                                 int size, string password, bool canSeek)
1114
        {
1115
            byte[] originalData = null;
1116
            var compressedData = MakeInMemoryZip(ref originalData, method, compressionLevel, size, password, canSeek);
1117

    
1118
            var ms = new MemoryStream(compressedData);
1119
            ms.Seek(0, SeekOrigin.Begin);
1120

    
1121
            using (var inStream = new ZipInputStream(ms))
1122
            {
1123
                var decompressedData = new byte[size];
1124
                if (password != null)
1125
                {
1126
                    inStream.Password = password;
1127
                }
1128

    
1129
                var entry2 = inStream.GetNextEntry();
1130

    
1131
                if ((entry2.Flags & 8) == 0)
1132
                {
1133
                    Assert.AreEqual(size, entry2.Size, "Entry size invalid");
1134
                }
1135

    
1136
                var currentIndex = 0;
1137

    
1138
                if (size > 0)
1139
                {
1140
                    var count = decompressedData.Length;
1141

    
1142
                    while (true)
1143
                    {
1144
                        var numRead = inStream.Read(decompressedData, currentIndex, count);
1145
                        if (numRead <= 0)
1146
                        {
1147
                            break;
1148
                        }
1149
                        currentIndex += numRead;
1150
                        count -= numRead;
1151
                    }
1152
                }
1153

    
1154
                Assert.AreEqual(currentIndex, size, "Original and decompressed data different sizes");
1155

    
1156
                if (originalData != null)
1157
                {
1158
                    for (var i = 0; i < originalData.Length; ++i)
1159
                    {
1160
                        Assert.AreEqual(decompressedData[i], originalData[i],
1161
                                        "Decompressed data doesnt match original, compression level: " +
1162
                                        compressionLevel);
1163
                    }
1164
                }
1165
            }
1166
        }
1167

    
1168
        private string DescribeAttributes(FieldAttributes attributes)
1169
        {
1170
            var att = string.Empty;
1171
            if ((FieldAttributes.Public & attributes) != 0)
1172
            {
1173
                att = att + "Public,";
1174
            }
1175

    
1176
            if ((FieldAttributes.Static & attributes) != 0)
1177
            {
1178
                att = att + "Static,";
1179
            }
1180

    
1181
            if ((FieldAttributes.Literal & attributes) != 0)
1182
            {
1183
                att = att + "Literal,";
1184
            }
1185

    
1186
            if ((FieldAttributes.HasDefault & attributes) != 0)
1187
            {
1188
                att = att + "HasDefault,";
1189
            }
1190

    
1191
            if ((FieldAttributes.InitOnly & attributes) != 0)
1192
            {
1193
                att = att + "InitOnly,";
1194
            }
1195

    
1196
            if ((FieldAttributes.Assembly & attributes) != 0)
1197
            {
1198
                att = att + "Assembly,";
1199
            }
1200

    
1201
            if ((FieldAttributes.FamANDAssem & attributes) != 0)
1202
            {
1203
                att = att + "FamANDAssembly,";
1204
            }
1205

    
1206
            if ((FieldAttributes.FamORAssem & attributes) != 0)
1207
            {
1208
                att = att + "FamORAssembly,";
1209
            }
1210

    
1211
            if ((FieldAttributes.HasFieldMarshal & attributes) != 0)
1212
            {
1213
                att = att + "HasFieldMarshal,";
1214
            }
1215

    
1216
            return att;
1217
        }
1218

    
1219
        private void TestLargeZip(string tempFile, int targetFiles)
1220
        {
1221
            const int BlockSize = 4096;
1222

    
1223
            var data = new byte[BlockSize];
1224
            byte nextValue = 0;
1225
            for (var i = 0; i < BlockSize; ++i)
1226
            {
1227
                nextValue = ScatterValue(nextValue);
1228
                data[i] = nextValue;
1229
            }
1230

    
1231
            using (var zFile = new ZipFile(tempFile))
1232
            {
1233
                Assert.AreEqual(targetFiles, zFile.Count);
1234
                var readData = new byte[BlockSize];
1235
                int readIndex;
1236
                foreach (ZipEntry ze in zFile)
1237
                {
1238
                    var s = zFile.GetInputStream(ze);
1239
                    readIndex = 0;
1240
                    while (readIndex < readData.Length)
1241
                    {
1242
                        readIndex += s.Read(readData, readIndex, data.Length - readIndex);
1243
                    }
1244

    
1245
                    for (var ii = 0; ii < BlockSize; ++ii)
1246
                    {
1247
                        Assert.AreEqual(data[ii], readData[ii]);
1248
                    }
1249
                }
1250
                zFile.Close();
1251
            }
1252
        }
1253

    
1254
        //      [Test]
1255
        //      [Category("Zip")]
1256
        //      [Category("CreatesTempFile")]
1257
        public void TestLargeZipFile()
1258
        {
1259
            var tempFile = @"g:\\tmp";
1260
            tempFile = Path.Combine(tempFile, "SharpZipTest.Zip");
1261
            TestLargeZip(tempFile, 8100);
1262
        }
1263

    
1264
        //      [Test]
1265
        //      [Category("Zip")]
1266
        //      [Category("CreatesTempFile")]
1267
        public void MakeLargeZipFile()
1268
        {
1269
            string tempFile = null;
1270
            try
1271
            {
1272
                //            tempFile = Path.GetTempPath();
1273
                tempFile = @"g:\\tmp";
1274
            }
1275
            catch (SecurityException)
1276
            {
1277
            }
1278

    
1279
            Assert.IsNotNull(tempFile, "No permission to execute this test?");
1280

    
1281
            if (tempFile != null)
1282
            {
1283
                const int blockSize = 4096;
1284

    
1285
                var data = new byte[blockSize];
1286
                byte nextValue = 0;
1287
                for (var i = 0; i < blockSize; ++i)
1288
                {
1289
                    nextValue = ScatterValue(nextValue);
1290
                    data[i] = nextValue;
1291
                }
1292

    
1293
                tempFile = Path.Combine(tempFile, "SharpZipTest.Zip");
1294
                Console.WriteLine("Starting at {0}", DateTime.Now);
1295
                try
1296
                {
1297
                    //               MakeZipFile(tempFile, new String[] {"1", "2" }, int.MaxValue, "C1");
1298
                    using (var fs = File.Create(tempFile))
1299
                    {
1300
                        var zOut = new ZipOutputStream(fs);
1301
                        zOut.SetLevel(4);
1302
                        const int TargetFiles = 8100;
1303
                        for (var i = 0; i < TargetFiles; ++i)
1304
                        {
1305
                            var e = new ZipEntry(i.ToString());
1306
                            e.CompressionMethod = CompressionMethod.Stored;
1307

    
1308
                            zOut.PutNextEntry(e);
1309
                            for (var block = 0; block < 128; ++block)
1310
                            {
1311
                                zOut.Write(data, 0, blockSize);
1312
                            }
1313
                        }
1314
                        zOut.Close();
1315
                        fs.Close();
1316

    
1317
                        TestLargeZip(tempFile, TargetFiles);
1318
                    }
1319
                }
1320
                finally
1321
                {
1322
                    Console.WriteLine("Starting at {0}", DateTime.Now);
1323
                    //               File.Delete(tempFile);
1324
                }
1325
            }
1326
        }
1327

    
1328
        private byte[] ZipZeroLength(ISerializable data)
1329
        {
1330
            var formatter = new XmlFormatter();
1331
            var memStream = new MemoryStream();
1332

    
1333
            using (var zipStream = new ZipOutputStream(memStream))
1334
            {
1335
                zipStream.PutNextEntry(new ZipEntry("data"));
1336
                formatter.Serialize(zipStream, data);
1337
                zipStream.CloseEntry();
1338
                zipStream.Close();
1339
            }
1340

    
1341
            var result = memStream.ToArray();
1342
            memStream.Close();
1343

    
1344
            return result;
1345
        }
1346

    
1347
        private ISerializable UnZipZeroLength(byte[] zipped)
1348
        {
1349
            if (zipped == null)
1350
            {
1351
                return null;
1352
            }
1353

    
1354
            object result = null;
1355
            var formatter = new XmlFormatter();
1356
            var memStream = new MemoryStream(zipped);
1357
            using (var zipStream = new ZipInputStream(memStream))
1358
            {
1359
                var zipEntry = zipStream.GetNextEntry();
1360
                if (zipEntry != null)
1361
                {
1362
                    result = formatter.Deserialize(zipStream);
1363
                }
1364
                zipStream.Close();
1365
            }
1366
            memStream.Close();
1367

    
1368
            return (ISerializable)result;
1369
        }
1370

    
1371
        private void CheckNameConversion(string toCheck)
1372
        {
1373
            var intermediate = ZipConstants.ConvertToArray(toCheck);
1374
            var final = ZipConstants.ConvertToString(intermediate);
1375

    
1376
            Assert.AreEqual(toCheck, final, "Expected identical result");
1377
        }
1378

    
1379
        /// <summary>
1380
        /// Adding an entry after the stream has Finished should fail
1381
        /// </summary>
1382
        [Test]
1383
        [Category("Zip")]
1384
        [ExpectedException(typeof (InvalidOperationException))]
1385
        public void AddEntryAfterFinish()
1386
        {
1387
            var ms = new MemoryStream();
1388
            var s = new ZipOutputStream(ms);
1389
            s.Finish();
1390
            s.PutNextEntry(new ZipEntry("dummyfile.tst"));
1391
        }
1392

    
1393
        /// <summary>
1394
        /// Basic compress/decompress test, no encryption, size is important here as its big enough
1395
        /// to force multiple write to output which was a problem...
1396
        /// </summary>
1397
        [Test]
1398
        [Category("Zip")]
1399
        public void BasicDeflated()
1400
        {
1401
            for (var i = 0; i <= 9; ++i)
1402
            {
1403
                ExerciseZip(CompressionMethod.Deflated, i, 50000, null, true);
1404
            }
1405
        }
1406

    
1407
        /// <summary>
1408
        /// Basic compress/decompress test, with encryption, size is important here as its big enough
1409
        /// to force multiple write to output which was a problem...
1410
        /// </summary>
1411
        [Test]
1412
        [Category("Zip")]
1413
        public void BasicDeflatedEncrypted()
1414
        {
1415
            for (var i = 0; i <= 9; ++i)
1416
            {
1417
                ExerciseZip(CompressionMethod.Deflated, i, 50000, "Rosebud", true);
1418
            }
1419
        }
1420

    
1421
        /// <summary>
1422
        /// Basic compress/decompress test, with encryption, size is important here as its big enough
1423
        /// to force multiple write to output which was a problem...
1424
        /// </summary>
1425
        [Test]
1426
        [Category("Zip")]
1427
        public void BasicDeflatedEncryptedNonSeekable()
1428
        {
1429
            for (var i = 0; i <= 9; ++i)
1430
            {
1431
                ExerciseZip(CompressionMethod.Deflated, i, 50000, "Rosebud", false);
1432
            }
1433
        }
1434

    
1435
        /// <summary>
1436
        /// Basic compress/decompress test, no encryption, size is important here as its big enough
1437
        /// to force multiple write to output which was a problem...
1438
        /// </summary>
1439
        [Test]
1440
        [Category("Zip")]
1441
        public void BasicDeflatedNonSeekable()
1442
        {
1443
            for (var i = 0; i <= 9; ++i)
1444
            {
1445
                ExerciseZip(CompressionMethod.Deflated, i, 50000, null, false);
1446
            }
1447
        }
1448

    
1449
        /// <summary>
1450
        /// Basic stored file test, no encryption.
1451
        /// </summary>
1452
        [Test]
1453
        [Category("Zip")]
1454
        public void BasicStored()
1455
        {
1456
            ExerciseZip(CompressionMethod.Stored, 0, 50000, null, true);
1457
        }
1458

    
1459
        /// <summary>
1460
        /// Basic stored file test, with encryption.
1461
        /// </summary>
1462
        [Test]
1463
        [Category("Zip")]
1464
        public void BasicStoredEncrypted()
1465
        {
1466
            ExerciseZip(CompressionMethod.Stored, 0, 50000, "Rosebud", true);
1467
        }
1468

    
1469
        /// <summary>
1470
        /// Basic stored file test, with encryption, non seekable output.
1471
        /// NOTE this gets converted deflate level 0
1472
        /// </summary>
1473
        [Test]
1474
        [Category("Zip")]
1475
        public void BasicStoredEncryptedNonSeekable()
1476
        {
1477
            ExerciseZip(CompressionMethod.Stored, 0, 50000, "Rosebud", false);
1478
        }
1479

    
1480
        /// <summary>
1481
        /// Basic stored file test, no encryption, non seekable output
1482
        /// NOTE this gets converted to deflate level 0
1483
        /// </summary>
1484
        [Test]
1485
        [Category("Zip")]
1486
        public void BasicStoredNonSeekable()
1487
        {
1488
            ExerciseZip(CompressionMethod.Stored, 0, 50000, null, false);
1489
        }
1490

    
1491
        /// <summary>
1492
        /// Check that simply closing ZipOutputStream finishes the zip correctly
1493
        /// </summary>
1494
        [Test]
1495
        [Category("Zip")]
1496
        public void CloseOnlyHandled()
1497
        {
1498
            var ms = new MemoryStream();
1499
            var s = new ZipOutputStream(ms);
1500
            s.PutNextEntry(new ZipEntry("dummyfile.tst"));
1501
            s.Close();
1502

    
1503
            Assert.IsTrue(s.IsFinished, "Output stream should be finished");
1504
        }
1505

    
1506
        /// <summary>
1507
        /// Check that GetNextEntry can handle the situation where part of the entry data has been read
1508
        /// before the call is made.  ZipInputStream.CloseEntry wasnt handling this at all.
1509
        /// </summary>
1510
        [Test]
1511
        [Category("Zip")]
1512
        public void ExerciseGetNextEntry()
1513
        {
1514
            var compressedData = MakeInMemoryZip(
1515
                true,
1516
                new RuntimeInfo(CompressionMethod.Deflated, 9, 50, null, true),
1517
                new RuntimeInfo(CompressionMethod.Deflated, 2, 50, null, true),
1518
                new RuntimeInfo(CompressionMethod.Deflated, 9, 50, null, true),
1519
                new RuntimeInfo(CompressionMethod.Deflated, 2, 50, null, true),
1520
                new RuntimeInfo(null, true),
1521
                new RuntimeInfo(CompressionMethod.Stored, 2, 50, null, true),
1522
                new RuntimeInfo(CompressionMethod.Deflated, 9, 50, null, true)
1523
                );
1524

    
1525
            var ms = new MemoryStream(compressedData);
1526
            ms.Seek(0, SeekOrigin.Begin);
1527

    
1528
            using (var inStream = new ZipInputStream(ms))
1529
            {
1530
                var buffer = new byte[10];
1531

    
1532
                ZipEntry entry;
1533
                while ((entry = inStream.GetNextEntry()) != null)
1534
                {
1535
                    // Read a portion of the data, so GetNextEntry has some work to do.
1536
                    inStream.Read(buffer, 0, 10);
1537
                }
1538
            }
1539
        }
1540

    
1541
        /// <summary>
1542
        /// Invalid passwords should be detected early if possible, non seekable stream
1543
        /// </summary>
1544
        [Test]
1545
        [Category("Zip")]
1546
        [ExpectedException(typeof (ZipException))]
1547
        public void InvalidPasswordNonSeekable()
1548
        {
1549
            byte[] originalData = null;
1550
            var compressedData = MakeInMemoryZip(ref originalData, CompressionMethod.Deflated, 3, 500, "Hola", false);
1551

    
1552
            var ms = new MemoryStream(compressedData);
1553
            ms.Seek(0, SeekOrigin.Begin);
1554

    
1555
            var buf2 = new byte[originalData.Length];
1556
            var pos = 0;
1557

    
1558
            var inStream = new ZipInputStream(ms);
1559
            inStream.Password = "redhead";
1560

    
1561
            var entry2 = inStream.GetNextEntry();
1562

    
1563
            while (true)
1564
            {
1565
                var numRead = inStream.Read(buf2, pos, buf2.Length);
1566
                if (numRead <= 0)
1567
                {
1568
                    break;
1569
                }
1570
                pos += numRead;
1571
            }
1572
        }
1573

    
1574
        /// <summary>
1575
        /// Invalid passwords should be detected early if possible, seekable stream
1576
        /// </summary>
1577
        [Test]
1578
        [Category("Zip")]
1579
        [ExpectedException(typeof (ZipException))]
1580
        public void InvalidPasswordSeekable()
1581
        {
1582
            byte[] originalData = null;
1583
            var compressedData = MakeInMemoryZip(ref originalData, CompressionMethod.Deflated, 3, 500, "Hola", true);
1584

    
1585
            var ms = new MemoryStream(compressedData);
1586
            ms.Seek(0, SeekOrigin.Begin);
1587

    
1588
            var buf2 = new byte[originalData.Length];
1589
            var pos = 0;
1590

    
1591
            var inStream = new ZipInputStream(ms);
1592
            inStream.Password = "redhead";
1593

    
1594
            var entry2 = inStream.GetNextEntry();
1595

    
1596
            while (true)
1597
            {
1598
                var numRead = inStream.Read(buf2, pos, buf2.Length);
1599
                if (numRead <= 0)
1600
                {
1601
                    break;
1602
                }
1603
                pos += numRead;
1604
            }
1605
        }
1606

    
1607
        [Test]
1608
        [Category("Zip")]
1609
        public void MixedEncryptedAndPlain()
1610
        {
1611
            var compressedData = MakeInMemoryZip(true,
1612
                                                 new RuntimeInfo(CompressionMethod.Deflated, 2, 1, null, true),
1613
                                                 new RuntimeInfo(CompressionMethod.Deflated, 9, 1, "1234", false),
1614
                                                 new RuntimeInfo(CompressionMethod.Deflated, 2, 1, null, false),
1615
                                                 new RuntimeInfo(CompressionMethod.Deflated, 9, 1, "1234", true)
1616
                );
1617

    
1618
            var ms = new MemoryStream(compressedData);
1619
            using (var inStream = new ZipInputStream(ms))
1620
            {
1621
                inStream.Password = "1234";
1622

    
1623
                var extractCount = 0;
1624
                var extractIndex = 0;
1625
                ZipEntry entry;
1626
                var decompressedData = new byte[100];
1627

    
1628
                while ((entry = inStream.GetNextEntry()) != null)
1629
                {
1630
                    extractCount = decompressedData.Length;
1631
                    extractIndex = 0;
1632
                    while (true)
1633
                    {
1634
                        var numRead = inStream.Read(decompressedData, extractIndex, extractCount);
1635
                        if (numRead <= 0)
1636
                        {
1637
                            break;
1638
                        }
1639
                        extractIndex += numRead;
1640
                        extractCount -= numRead;
1641
                    }
1642
                }
1643
                inStream.Close();
1644
            }
1645
        }
1646

    
1647
        [Test]
1648
        [Category("Zip")]
1649
        public void NameConversion()
1650
        {
1651
            CheckNameConversion("Hello");
1652
            CheckNameConversion("a/b/c/d/e/f/g/h/SomethingLikeAnArchiveName.txt");
1653
        }
1654

    
1655
        [Test]
1656
        [Category("Zip")]
1657
        [Category("CreatesTempFile")]
1658
        public void PartialStreamClosing()
1659
        {
1660
            var tempFile = GetTempFilePath();
1661
            Assert.IsNotNull(tempFile, "No permission to execute this test?");
1662

    
1663
            if (tempFile != null)
1664
            {
1665
                tempFile = Path.Combine(tempFile, "SharpZipTest.Zip");
1666
                MakeZipFile(tempFile, new[]{"Farriera", "Champagne", "Urban myth"}, 10, "Aha");
1667

    
1668
                using (var zipFile = new ZipFile(tempFile))
1669
                {
1670
                    var stream = zipFile.GetInputStream(0);
1671
                    stream.Close();
1672

    
1673
                    stream = zipFile.GetInputStream(1);
1674
                    zipFile.Close();
1675
                }
1676
                File.Delete(tempFile);
1677
            }
1678
        }
1679

    
1680
        /// <summary>
1681
        /// Regression test for problem where the password check would fail for an archive whose
1682
        /// date was updated from the extra data.
1683
        /// This applies to archives where the crc wasnt know at the time of encryption.
1684
        /// The date of the entry is used in its place.
1685
        /// </summary>
1686
        [Test]
1687
        [Category("Zip")]
1688
        public void PasswordCheckingWithDateInExtraData()
1689
        {
1690
            var ms = new MemoryStream();
1691
            var checkTime = new DateTime(2010, 10, 16, 0, 3, 28);
1692

    
1693
            using (var zos = new ZipOutputStream(ms))
1694
            {
1695
                zos.IsStreamOwner = false;
1696
                zos.Password = "secret";
1697
                var ze = new ZipEntry("uno");
1698
                ze.DateTime = new DateTime(1998, 6, 5, 4, 3, 2);
1699

    
1700
                var zed = new ZipExtraData();
1701

    
1702
                zed.StartNewEntry();
1703

    
1704
                zed.AddData(1);
1705

    
1706
                var delta = checkTime.ToUniversalTime() - new DateTime(1970, 1, 1, 0, 0, 0).ToUniversalTime();
1707
                var seconds = (int) delta.TotalSeconds;
1708
                zed.AddLeInt(seconds);
1709
                zed.AddNewEntry(0x5455);
1710

    
1711
                ze.ExtraData = zed.GetEntryData();
1712
                zos.PutNextEntry(ze);
1713
                zos.WriteByte(54);
1714
            }
1715

    
1716
            ms.Position = 0;
1717
            using (var zis = new ZipInputStream(ms))
1718
            {
1719
                zis.Password = "secret";
1720
                var uno = zis.GetNextEntry();
1721
                var theByte = (byte) zis.ReadByte();
1722
                Assert.AreEqual(54, theByte);
1723
                Assert.AreEqual(-1, zis.ReadByte());
1724
                Assert.AreEqual(checkTime, uno.DateTime);
1725
            }
1726
        }
1727

    
1728
        /// <summary>
1729
        /// Test for handling of serialized reference and value objects.
1730
        /// </summary>
1731
        [Test]
1732
        [Category("Zip")]
1733
        public void SerializedObject()
1734
        {
1735
            var sampleDateTime = new SerializableDateTime(1853, 8, 26);
1736
            ISerializable data = sampleDateTime;
1737

    
1738
            var zipped = ZipZeroLength(data);
1739
            var rawObject = UnZipZeroLength(zipped);
1740

    
1741
            var returnedDateTime = (SerializableDateTime) rawObject;
1742

    
1743
            Assert.AreEqual(sampleDateTime, returnedDateTime);
1744

    
1745
            var sampleString = new SerializableString("Mary had a giant cat its ears were green and smelly");
1746
            zipped = ZipZeroLength(sampleString);
1747

    
1748
            rawObject = UnZipZeroLength(zipped);
1749

    
1750
            var returnedString = rawObject as SerializableString;
1751

    
1752
            Assert.AreEqual(sampleString, returnedString);
1753
        }
1754

    
1755
        /// <summary>
1756
        /// Test for handling of zero lengths in compression using a formatter which
1757
        /// will request reads of zero length...
1758
        /// </summary>
1759
        [Test]
1760
        [Category("Zip")]
1761
        public void SerializedObjectZeroLength()
1762
        {
1763
//            object data = new SerializableByteArray[0];
1764
//            // This wont be zero length here due to serialisation.
1765
//            var zipped = ZipZeroLength(data);
1766
//            var o = UnZipZeroLength(zipped);
1767
//
1768
//            var returned = o as byte[];
1769
//
1770
//            Assert.IsNotNull(returned, "Expected a byte[]");
1771
//            Assert.AreEqual(0, returned.Length);
1772
        }
1773

    
1774
        /// <summary>
1775
        /// Test setting file commment to a value that is too long
1776
        /// </summary>
1777
        [Test]
1778
        [Category("Zip")]
1779
        [ExpectedException(typeof (ArgumentOutOfRangeException))]
1780
        public void SetCommentOversize()
1781
        {
1782
            var ms = new MemoryStream();
1783
            var s = new ZipOutputStream(ms);
1784
            s.SetComment(new String('A', 65536));
1785
        }
1786

    
1787
        [Test]
1788
        [Category("Zip")]
1789
        public void SkipEncryptedEntriesWithoutSettingPassword()
1790
        {
1791
            var compressedData = MakeInMemoryZip(true,
1792
                                                 new RuntimeInfo("1234", true),
1793
                                                 new RuntimeInfo(CompressionMethod.Deflated, 2, 1, null, true),
1794
                                                 new RuntimeInfo(CompressionMethod.Deflated, 9, 1, "1234", true),
1795
                                                 new RuntimeInfo(CompressionMethod.Deflated, 2, 1, null, true),
1796
                                                 new RuntimeInfo(null, true),
1797
                                                 new RuntimeInfo(CompressionMethod.Stored, 2, 1, "4321", true),
1798
                                                 new RuntimeInfo(CompressionMethod.Deflated, 9, 1, "1234", true)
1799
                );
1800

    
1801
            var ms = new MemoryStream(compressedData);
1802
            var inStream = new ZipInputStream(ms);
1803

    
1804
            ZipEntry entry;
1805
            while ((entry = inStream.GetNextEntry()) != null)
1806
            {
1807
            }
1808

    
1809
            inStream.Close();
1810
        }
1811

    
1812
        /// <summary>
1813
        /// Check that when the output stream cannot seek that requests for stored
1814
        /// are in fact converted to defalted level 0
1815
        /// </summary>
1816
        [Test]
1817
        [Category("Zip")]
1818
        public void StoredNonSeekableConvertToDeflate()
1819
        {
1820
            var ms = new MemoryStreamWithoutSeek();
1821

    
1822
            var outStream = new ZipOutputStream(ms);
1823
            outStream.SetLevel(8);
1824
            Assert.AreEqual(8, outStream.GetLevel(), "Compression level invalid");
1825

    
1826
            var entry = new ZipEntry("1.tst");
1827
            entry.CompressionMethod = CompressionMethod.Stored;
1828
            outStream.PutNextEntry(entry);
1829
            Assert.AreEqual(0, outStream.GetLevel(), "Compression level invalid");
1830

    
1831
            AddRandomDataToEntry(outStream, 100);
1832
            entry = new ZipEntry("2.tst");
1833
            entry.CompressionMethod = CompressionMethod.Deflated;
1834
            outStream.PutNextEntry(entry);
1835
            Assert.AreEqual(8, outStream.GetLevel(), "Compression level invalid");
1836
            AddRandomDataToEntry(outStream, 100);
1837

    
1838
            outStream.Close();
1839
        }
1840

    
1841
        /// <summary>
1842
        /// Check that adding more than the 2.0 limit for entry numbers is detected and handled
1843
        /// </summary>
1844
        [Test]
1845
        [Category("Zip")]
1846
        [Category("Long Running")]
1847
        public void Stream_64KPlusOneEntries()
1848
        {
1849
            const int target = 65537;
1850
            var ms = new MemoryStream();
1851
            using (var s = new ZipOutputStream(ms))
1852
            {
1853
                for (var i = 0; i < target; ++i)
1854
                {
1855
                    s.PutNextEntry(new ZipEntry("dummyfile.tst"));
1856
                }
1857

    
1858
                s.Finish();
1859
                ms.Seek(0, SeekOrigin.Begin);
1860
                using (var zipFile = new ZipFile(ms))
1861
                {
1862
                    Assert.AreEqual(target, zipFile.Count, "Incorrect number of entries stored");
1863
                }
1864
            }
1865
        }
1866

    
1867
        /// <summary>
1868
        /// Check that Unicode filename support works.
1869
        /// </summary>
1870
        [Test]
1871
        [Category("Zip")]
1872
        public void Stream_UnicodeEntries()
1873
        {
1874
            var ms = new MemoryStream();
1875
            using (var s = new ZipOutputStream(ms))
1876
            {
1877
                s.IsStreamOwner = false;
1878

    
1879
                var sampleName = "\u03A5\u03d5\u03a3";
1880
                var sample = new ZipEntry(sampleName);
1881
                sample.IsUnicodeText = true;
1882
                s.PutNextEntry(sample);
1883

    
1884
                s.Finish();
1885
                ms.Seek(0, SeekOrigin.Begin);
1886

    
1887
                using (var zis = new ZipInputStream(ms))
1888
                {
1889
                    var ze = zis.GetNextEntry();
1890
                    Assert.AreEqual(sampleName, ze.Name, "Expected name to match original");
1891
                    Assert.IsTrue(ze.IsUnicodeText, "Expected IsUnicodeText flag to be set");
1892
                }
1893
            }
1894
        }
1895

    
1896
        [Test]
1897
        [Category("Zip")]
1898
        public void UnicodeNameConversion()
1899
        {
1900
            var sample = "Hello world";
1901

    
1902
            byte[] rawData = Encoding.UTF8.GetBytes(sample);
1903

    
1904
            var converted = ZipConstants.ConvertToStringExt(0, rawData);
1905
            Assert.AreEqual(sample, converted);
1906

    
1907
            converted = ZipConstants.ConvertToStringExt((int) GeneralBitFlags.UnicodeText, rawData);
1908
            Assert.AreEqual(sample, converted);
1909

    
1910
            // This time use some greek characters
1911
            sample = "\u03A5\u03d5\u03a3";
1912
            rawData = Encoding.UTF8.GetBytes(sample);
1913

    
1914
            converted = ZipConstants.ConvertToStringExt((int) GeneralBitFlags.UnicodeText, rawData);
1915
            Assert.AreEqual(sample, converted);
1916
        }
1917

    
1918
        [Test]
1919
        [Category("Zip")]
1920
        [ExpectedException(typeof (NotSupportedException))]
1921
        public void UnsupportedCompressionMethod()
1922
        {
1923
            var ze = new ZipEntry("HumblePie");
1924
            var type = typeof (CompressionMethod);
1925
            //			System.Reflection.FieldInfo[] info = type.GetFields(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance);
1926
            var info = type.GetFields();
1927

    
1928
            var aValue = CompressionMethod.Deflated;
1929
            for (var i = 0; i < info.Length; i++)
1930
            {
1931
                var attributes = info[i].Attributes;
1932
                DescribeAttributes(attributes);
1933
                if ((FieldAttributes.Static & attributes) != 0)
1934
                {
1935
                    var obj = info[i].GetValue(null);
1936
                    var bb = obj.ToString();
1937
                    if (bb == null)
1938
                    {
1939
                        throw new Exception();
1940
                    }
1941
                }
1942
                var x = string.Format("The value of {0} is: {1}",
1943
                                      info[i].Name, info[i].GetValue(aValue));
1944
            }
1945

    
1946
            ze.CompressionMethod = CompressionMethod.BZip2;
1947
        }
1948
    }
1949

    
1950
    [TestFixture]
1951
    public class ZipExtraDataHandling : ZipBase
1952
    {
1953
        [Test]
1954
        [Category("Zip")]
1955
        public void BasicOperations()
1956
        {
1957
            var zed = new ZipExtraData(null);
1958
            Assert.AreEqual(0, zed.Length);
1959

    
1960
            zed = new ZipExtraData(new byte[]{1, 0, 0, 0});
1961
            Assert.AreEqual(4, zed.Length, "A length should be 4");
1962

    
1963
            var zed2 = new ZipExtraData();
1964
            Assert.AreEqual(0, zed2.Length);
1965

    
1966
            zed2.AddEntry(1, new byte[]{});
1967

    
1968
            var data = zed.GetEntryData();
1969
            for (var i = 0; i < data.Length; ++i)
1970
            {
1971
                Assert.AreEqual(zed2.GetEntryData()[i], data[i]);
1972
            }
1973

    
1974
            Assert.AreEqual(4, zed2.Length, "A1 length should be 4");
1975

    
1976
            var findResult = zed.Find(2);
1977
            Assert.IsFalse(findResult, "A - Shouldnt find tag 2");
1978

    
1979
            findResult = zed.Find(1);
1980
            Assert.IsTrue(findResult, "A - Should find tag 1");
1981
            Assert.AreEqual(0, zed.ValueLength, "A- Length of entry should be 0");
1982
            Assert.AreEqual(-1, zed.ReadByte());
1983
            Assert.AreEqual(0, zed.GetStreamForTag(1).Length, "A - Length of stream should be 0");
1984

    
1985
            zed = new ZipExtraData(new byte[]{1, 0, 3, 0, 1, 2, 3});
1986
            Assert.AreEqual(7, zed.Length, "Expected a length of 7");
1987

    
1988
            findResult = zed.Find(1);
1989
            Assert.IsTrue(findResult, "B - Should find tag 1");
1990
            Assert.AreEqual(3, zed.ValueLength, "B - Length of entry should be 3");
1991
            for (var i = 1; i <= 3; ++i)
1992
            {
1993
                Assert.AreEqual(i, zed.ReadByte());
1994
            }
1995
            Assert.AreEqual(-1, zed.ReadByte());
1996

    
1997
            var s = zed.GetStreamForTag(1);
1998
            Assert.AreEqual(3, s.Length, "B.1 Stream length should be 3");
1999
            for (var i = 1; i <= 3; ++i)
2000
            {
2001
                Assert.AreEqual(i, s.ReadByte());
2002
            }
2003
            Assert.AreEqual(-1, s.ReadByte());
2004

    
2005
            zed = new ZipExtraData(new byte[]{1, 0, 3, 0, 1, 2, 3, 2, 0, 1, 0, 56});
2006
            Assert.AreEqual(12, zed.Length, "Expected a length of 12");
2007

    
2008
            findResult = zed.Find(1);
2009
            Assert.IsTrue(findResult, "C.1 - Should find tag 1");
2010
            Assert.AreEqual(3, zed.ValueLength, "C.1 - Length of entry should be 3");
2011
            for (var i = 1; i <= 3; ++i)
2012
            {
2013
                Assert.AreEqual(i, zed.ReadByte());
2014
            }
2015
            Assert.AreEqual(-1, zed.ReadByte());
2016

    
2017
            findResult = zed.Find(2);
2018
            Assert.IsTrue(findResult, "C.2 - Should find tag 2");
2019
            Assert.AreEqual(1, zed.ValueLength, "C.2 - Length of entry should be 1");
2020
            Assert.AreEqual(56, zed.ReadByte());
2021
            Assert.AreEqual(-1, zed.ReadByte());
2022

    
2023
            s = zed.GetStreamForTag(2);
2024
            Assert.AreEqual(1, s.Length);
2025
            Assert.AreEqual(56, s.ReadByte());
2026
            Assert.AreEqual(-1, s.ReadByte());
2027

    
2028
            zed = new ZipExtraData();
2029
            zed.AddEntry(7, new byte[]{33, 44, 55});
2030
            findResult = zed.Find(7);
2031
            Assert.IsTrue(findResult, "Add.1 should find new tag");
2032
            Assert.AreEqual(3, zed.ValueLength, "Add.1 length should be 3");
2033
            Assert.AreEqual(33, zed.ReadByte());
2034
            Assert.AreEqual(44, zed.ReadByte());
2035
            Assert.AreEqual(55, zed.ReadByte());
2036
            Assert.AreEqual(-1, zed.ReadByte());
2037

    
2038
            zed.AddEntry(7, null);
2039
            findResult = zed.Find(7);
2040
            Assert.IsTrue(findResult, "Add.2 should find new tag");
2041
            Assert.AreEqual(0, zed.ValueLength, "Add.2 length should be 0");
2042

    
2043
            zed.StartNewEntry();
2044
            zed.AddData(0xae);
2045
            zed.AddNewEntry(55);
2046

    
2047
            findResult = zed.Find(55);
2048
            Assert.IsTrue(findResult, "Add.3 should find new tag");
2049
            Assert.AreEqual(1, zed.ValueLength, "Add.3 length should be 1");
2050
            Assert.AreEqual(0xae, zed.ReadByte());
2051
            Assert.AreEqual(-1, zed.ReadByte());
2052

    
2053
            zed = new ZipExtraData();
2054
            zed.StartNewEntry();
2055
            zed.AddLeLong(0);
2056
            zed.AddLeLong(-4);
2057
            zed.AddLeLong(-1);
2058
            zed.AddLeLong(long.MaxValue);
2059
            zed.AddLeLong(long.MinValue);
2060
            zed.AddLeLong(0x123456789ABCDEF0);
2061
            zed.AddLeLong(unchecked((long) 0xFEDCBA9876543210));
2062
            zed.AddNewEntry(567);
2063

    
2064
            s = zed.GetStreamForTag(567);
2065
            var longValue = ReadLong(s);
2066
            Assert.AreEqual(longValue, zed.ReadLong(), "Read/stream mismatch");
2067
            Assert.AreEqual(0, longValue, "Expected long value of zero");
2068

    
2069
            longValue = ReadLong(s);
2070
            Assert.AreEqual(longValue, zed.ReadLong(), "Read/stream mismatch");
2071
            Assert.AreEqual(-4, longValue, "Expected long value of -4");
2072

    
2073
            longValue = ReadLong(s);
2074
            Assert.AreEqual(longValue, zed.ReadLong(), "Read/stream mismatch");
2075
            Assert.AreEqual(-1, longValue, "Expected long value of -1");
2076

    
2077
            longValue = ReadLong(s);
2078
            Assert.AreEqual(longValue, zed.ReadLong(), "Read/stream mismatch");
2079
            Assert.AreEqual(long.MaxValue, longValue, "Expected long value of MaxValue");
2080

    
2081
            longValue = ReadLong(s);
2082
            Assert.AreEqual(longValue, zed.ReadLong(), "Read/stream mismatch");
2083
            Assert.AreEqual(long.MinValue, longValue, "Expected long value of MinValue");
2084

    
2085
            longValue = ReadLong(s);
2086
            Assert.AreEqual(longValue, zed.ReadLong(), "Read/stream mismatch");
2087
            Assert.AreEqual(0x123456789abcdef0, longValue, "Expected long value of MinValue");
2088

    
2089
            longValue = ReadLong(s);
2090
            Assert.AreEqual(longValue, zed.ReadLong(), "Read/stream mismatch");
2091
            Assert.AreEqual(unchecked((long) 0xFEDCBA9876543210), longValue, "Expected long value of MinValue");
2092
        }
2093

    
2094
        [Test]
2095
        [Category("Zip")]
2096
        public void Deleting()
2097
        {
2098
            var zed = new ZipExtraData();
2099
            Assert.AreEqual(0, zed.Length);
2100

    
2101
            // Tag 1 Totoal length 10
2102
            zed.AddEntry(1, new byte[]{10, 11, 12, 13, 14, 15});
2103
            Assert.AreEqual(10, zed.Length, "Length should be 10");
2104
            Assert.AreEqual(10, zed.GetEntryData().Length, "Data length should be 10");
2105

    
2106
            // Tag 2 total length  9
2107
            zed.AddEntry(2, new byte[]{20, 21, 22, 23, 24});
2108
            Assert.AreEqual(19, zed.Length, "Length should be 19");
2109
            Assert.AreEqual(19, zed.GetEntryData().Length, "Data length should be 19");
2110

    
2111
            // Tag 3 Total Length 6
2112
            zed.AddEntry(3, new byte[]{30, 31});
2113
            Assert.AreEqual(25, zed.Length, "Length should be 25");
2114
            Assert.AreEqual(25, zed.GetEntryData().Length, "Data length should be 25");
2115

    
2116
            zed.Delete(2);
2117
            Assert.AreEqual(16, zed.Length, "Length should be 16");
2118
            Assert.AreEqual(16, zed.GetEntryData().Length, "Data length should be 16");
2119

    
2120
            // Tag 2 total length  9
2121
            zed.AddEntry(2, new byte[]{20, 21, 22, 23, 24});
2122
            Assert.AreEqual(25, zed.Length, "Length should be 25");
2123
            Assert.AreEqual(25, zed.GetEntryData().Length, "Data length should be 25");
2124

    
2125
            zed.AddEntry(3, null);
2126
            Assert.AreEqual(23, zed.Length, "Length should be 23");
2127
            Assert.AreEqual(23, zed.GetEntryData().Length, "Data length should be 23");
2128
        }
2129

    
2130
        [Test]
2131
        [Category("Zip")]
2132
        public void ExceedSize()
2133
        {
2134
            var zed = new ZipExtraData();
2135
            var buffer = new byte[65506];
2136
            zed.AddEntry(1, buffer);
2137
            Assert.AreEqual(65510, zed.Length);
2138
            zed.AddEntry(2, new byte[21]);
2139
            Assert.AreEqual(65535, zed.Length);
2140

    
2141
            var caught = false;
2142
            try
2143
            {
2144
                zed.AddEntry(3, null);
2145
            }
2146
            catch
2147
            {
2148
                caught = true;
2149
            }
2150
            Assert.IsTrue(caught, "Expected an exception when max size exceeded");
2151
            Assert.AreEqual(65535, zed.Length);
2152

    
2153
            zed.Delete(2);
2154
            Assert.AreEqual(65510, zed.Length);
2155

    
2156
            caught = false;
2157
            try
2158
            {
2159
                zed.AddEntry(2, new byte[22]);
2160
            }
2161
            catch
2162
            {
2163
                caught = true;
2164
            }
2165
            Assert.IsTrue(caught, "Expected an exception when max size exceeded");
2166
            Assert.AreEqual(65510, zed.Length);
2167
        }
2168

    
2169
        /// <summary>
2170
        /// Extra data for separate entries should be unique to that entry
2171
        /// </summary>
2172
        [Test]
2173
        [Category("Zip")]
2174
        public void IsDataUnique()
2175
        {
2176
            var a = new ZipEntry("Basil");
2177
            var extra = new byte[4];
2178
            extra[0] = 27;
2179
            a.ExtraData = extra;
2180

    
2181
            var b = (ZipEntry) a.Clone();
2182
            b.ExtraData[0] = 89;
2183
            Assert.IsTrue(b.ExtraData[0] != a.ExtraData[0],
2184
                          "Extra data not unique " + b.ExtraData[0] + " " + a.ExtraData[0]);
2185

    
2186
            var c = (ZipEntry) a.Clone();
2187
            c.ExtraData[0] = 45;
2188
            Assert.IsTrue(a.ExtraData[0] != c.ExtraData[0],
2189
                          "Extra data not unique " + a.ExtraData[0] + " " + c.ExtraData[0]);
2190
        }
2191

    
2192
        [Test]
2193
        [Category("Zip")]
2194
        public void ReadOverrunInt()
2195
        {
2196
            var zed = new ZipExtraData(new byte[]{1, 0, 0, 0});
2197
            Assert.AreEqual(4, zed.Length, "Length should be 4");
2198
            Assert.IsTrue(zed.Find(1), "Should find tag 1");
2199

    
2200
            // Empty Tag
2201
            var exceptionCaught = false;
2202
            try
2203
            {
2204
                zed.ReadInt();
2205
            }
2206
            catch (ZipException)
2207
            {
2208
                exceptionCaught = true;
2209
            }
2210
            Assert.IsTrue(exceptionCaught, "Expected EOS exception");
2211

    
2212
            // three bytes
2213
            zed = new ZipExtraData(new byte[]{1, 0, 3, 0, 1, 2, 3});
2214
            Assert.IsTrue(zed.Find(1), "Should find tag 1");
2215

    
2216
            exceptionCaught = false;
2217
            try
2218
            {
2219
                zed.ReadInt();
2220
            }
2221
            catch (ZipException)
2222
            {
2223
                exceptionCaught = true;
2224
            }
2225
            Assert.IsTrue(exceptionCaught, "Expected EOS exception");
2226

    
2227
            zed = new ZipExtraData(new byte[]{1, 0, 7, 0, 1, 2, 3, 4, 5, 6, 7});
2228
            Assert.IsTrue(zed.Find(1), "Should find tag 1");
2229

    
2230
            zed.ReadInt();
2231

    
2232
            exceptionCaught = false;
2233
            try
2234
            {
2235
                zed.ReadInt();
2236
            }
2237
            catch (ZipException)
2238
            {
2239
                exceptionCaught = true;
2240
            }
2241
            Assert.IsTrue(exceptionCaught, "Expected EOS exception");
2242
        }
2243

    
2244
        [Test]
2245
        [Category("Zip")]
2246
        public void ReadOverrunLong()
2247
        {
2248
            var zed = new ZipExtraData(new byte[]{1, 0, 0, 0});
2249
            Assert.AreEqual(4, zed.Length, "Length should be 4");
2250
            Assert.IsTrue(zed.Find(1), "Should find tag 1");
2251

    
2252
            // Empty Tag
2253
            var exceptionCaught = false;
2254
            try
2255
            {
2256
                zed.ReadLong();
2257
            }
2258
            catch (ZipException)
2259
            {
2260
                exceptionCaught = true;
2261
            }
2262
            Assert.IsTrue(exceptionCaught, "Expected EOS exception");
2263

    
2264
            // seven bytes
2265
            zed = new ZipExtraData(new byte[]{1, 0, 7, 0, 1, 2, 3, 4, 5, 6, 7});
2266
            Assert.IsTrue(zed.Find(1), "Should find tag 1");
2267

    
2268
            exceptionCaught = false;
2269
            try
2270
            {
2271
                zed.ReadLong();
2272
            }
2273
            catch (ZipException)
2274
            {
2275
                exceptionCaught = true;
2276
            }
2277
            Assert.IsTrue(exceptionCaught, "Expected EOS exception");
2278

    
2279
            zed = new ZipExtraData(new byte[]{1, 0, 15, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15});
2280
            Assert.IsTrue(zed.Find(1), "Should find tag 1");
2281

    
2282
            zed.ReadLong();
2283

    
2284
            exceptionCaught = false;
2285
            try
2286
            {
2287
                zed.ReadLong();
2288
            }
2289
            catch (ZipException)
2290
            {
2291
                exceptionCaught = true;
2292
            }
2293
            Assert.IsTrue(exceptionCaught, "Expected EOS exception");
2294
        }
2295

    
2296
        [Test]
2297
        [Category("Zip")]
2298
        public void ReadOverrunShort()
2299
        {
2300
            var zed = new ZipExtraData(new byte[]{1, 0, 0, 0});
2301
            Assert.AreEqual(4, zed.Length, "Length should be 4");
2302
            Assert.IsTrue(zed.Find(1), "Should find tag 1");
2303

    
2304
            // Empty Tag
2305
            var exceptionCaught = false;
2306
            try
2307
            {
2308
                zed.ReadShort();
2309
            }
2310
            catch (ZipException)
2311
            {
2312
                exceptionCaught = true;
2313
            }
2314
            Assert.IsTrue(exceptionCaught, "Expected EOS exception");
2315

    
2316
            // Single byte
2317
            zed = new ZipExtraData(new byte[]{1, 0, 1, 0, 1});
2318
            Assert.IsTrue(zed.Find(1), "Should find tag 1");
2319

    
2320
            exceptionCaught = false;
2321
            try
2322
            {
2323
                zed.ReadShort();
2324
            }
2325
            catch (ZipException)
2326
            {
2327
                exceptionCaught = true;
2328
            }
2329
            Assert.IsTrue(exceptionCaught, "Expected EOS exception");
2330

    
2331
            zed = new ZipExtraData(new byte[]{1, 0, 2, 0, 1, 2});
2332
            Assert.IsTrue(zed.Find(1), "Should find tag 1");
2333

    
2334
            zed.ReadShort();
2335

    
2336
            exceptionCaught = false;
2337
            try
2338
            {
2339
                zed.ReadShort();
2340
            }
2341
            catch (ZipException)
2342
            {
2343
                exceptionCaught = true;
2344
            }
2345
            Assert.IsTrue(exceptionCaught, "Expected EOS exception");
2346
        }
2347

    
2348
        [Test]
2349
        [Category("Zip")]
2350
        public void Skipping()
2351
        {
2352
            var zed = new ZipExtraData(new byte[]{1, 0, 7, 0, 1, 2, 3, 4, 5, 6, 7});
2353
            Assert.AreEqual(11, zed.Length, "Length should be 11");
2354
            Assert.IsTrue(zed.Find(1), "Should find tag 1");
2355

    
2356
            Assert.AreEqual(7, zed.UnreadCount);
2357
            Assert.AreEqual(4, zed.CurrentReadIndex);
2358

    
2359
            zed.ReadByte();
2360
            Assert.AreEqual(6, zed.UnreadCount);
2361
            Assert.AreEqual(5, zed.CurrentReadIndex);
2362

    
2363
            zed.Skip(1);
2364
            Assert.AreEqual(5, zed.UnreadCount);
2365
            Assert.AreEqual(6, zed.CurrentReadIndex);
2366

    
2367
            zed.Skip(-1);
2368
            Assert.AreEqual(6, zed.UnreadCount);
2369
            Assert.AreEqual(5, zed.CurrentReadIndex);
2370

    
2371
            zed.Skip(6);
2372
            Assert.AreEqual(0, zed.UnreadCount);
2373
            Assert.AreEqual(11, zed.CurrentReadIndex);
2374

    
2375
            var exceptionCaught = false;
2376

    
2377
            try
2378
            {
2379
                zed.Skip(1);
2380
            }
2381
            catch (ZipException)
2382
            {
2383
                exceptionCaught = true;
2384
            }
2385
            Assert.IsTrue(exceptionCaught, "Should fail to skip past end");
2386

    
2387
            Assert.AreEqual(0, zed.UnreadCount);
2388
            Assert.AreEqual(11, zed.CurrentReadIndex);
2389

    
2390
            zed.Skip(-7);
2391
            Assert.AreEqual(7, zed.UnreadCount);
2392
            Assert.AreEqual(4, zed.CurrentReadIndex);
2393

    
2394
            try
2395
            {
2396
                zed.Skip(-1);
2397
            }
2398
            catch (ZipException)
2399
            {
2400
                exceptionCaught = true;
2401
            }
2402
            Assert.IsTrue(exceptionCaught, "Should fail to skip before beginning");
2403
        }
2404

    
2405
        [Test]
2406
        [Category("Zip")]
2407
        public void TaggedDataHandling()
2408
        {
2409
            var tagData = new NTTaggedData();
2410
            var modTime = tagData.LastModificationTime;
2411
            var rawData = tagData.GetData();
2412
            tagData.LastModificationTime = tagData.LastModificationTime + TimeSpan.FromSeconds(40);
2413
            tagData.SetData(rawData, 0, rawData.Length);
2414
            Assert.AreEqual(10, tagData.TagID, "TagID mismatch");
2415
            Assert.AreEqual(modTime, tagData.LastModificationTime, "NT Mod time incorrect");
2416

    
2417
            tagData.CreateTime = DateTime.FromFileTimeUtc(0);
2418
            tagData.LastAccessTime = new DateTime(9999, 12, 31, 23, 59, 59);
2419
            rawData = tagData.GetData();
2420

    
2421
            var unixData = new ExtendedUnixData();
2422
            modTime = unixData.ModificationTime;
2423
            unixData.ModificationTime = modTime; // Ensure flag is set.
2424

    
2425
            rawData = unixData.GetData();
2426
            unixData.ModificationTime += TimeSpan.FromSeconds(100);
2427
            unixData.SetData(rawData, 0, rawData.Length);
2428
            Assert.AreEqual(0x5455, unixData.TagID, "TagID mismatch");
2429
            Assert.AreEqual(modTime, unixData.ModificationTime, "Unix mod time incorrect");
2430
        }
2431

    
2432
        [Test]
2433
        [Category("Zip")]
2434
        public void UnreadCountValid()
2435
        {
2436
            var zed = new ZipExtraData(new byte[]{1, 0, 0, 0});
2437
            Assert.AreEqual(4, zed.Length, "Length should be 4");
2438
            Assert.IsTrue(zed.Find(1), "Should find tag 1");
2439
            Assert.AreEqual(0, zed.UnreadCount);
2440

    
2441
            // seven bytes
2442
            zed = new ZipExtraData(new byte[]{1, 0, 7, 0, 1, 2, 3, 4, 5, 6, 7});
2443
            Assert.IsTrue(zed.Find(1), "Should find tag 1");
2444

    
2445
            for (var i = 0; i < 7; ++i)
2446
            {
2447
                Assert.AreEqual(7 - i, zed.UnreadCount);
2448
                zed.ReadByte();
2449
            }
2450

    
2451
            zed.ReadByte();
2452
            Assert.AreEqual(0, zed.UnreadCount);
2453
        }
2454
    }
2455

    
2456
    [TestFixture]
2457
    public class FastZipHandling : ZipBase
2458
    {
2459
        private const string ZipTempDir = "SharpZipLibTest";
2460

    
2461
        private void EnsureTestDirectoryIsEmpty(string baseDir)
2462
        {
2463
            var name = Path.Combine(baseDir, ZipTempDir);
2464

    
2465
            if (Directory.Exists(name))
2466
            {
2467
                Directory.Delete(name, true);
2468
            }
2469

    
2470
            Directory.CreateDirectory(name);
2471
        }
2472

    
2473
        [Test]
2474
        [Category("Zip")]
2475
        [Category("CreatesTempFile")]
2476
        public void Basics()
2477
        {
2478
            const string tempName1 = "a.dat";
2479

    
2480
            var target = new MemoryStream();
2481

    
2482
            var tempFilePath = GetTempFilePath();
2483
            Assert.IsNotNull(tempFilePath, "No permission to execute this test?");
2484

    
2485
            var addFile = Path.Combine(tempFilePath, tempName1);
2486
            MakeTempFile(addFile, 1);
2487

    
2488
            try
2489
            {
2490
                var fastZip = new FastZip();
2491
                fastZip.CreateZip(target, tempFilePath, false, @"a\.dat", null);
2492

    
2493
                var archive = new MemoryStream(target.ToArray());
2494
                using (var zf = new ZipFile(archive))
2495
                {
2496
                    Assert.AreEqual(1, zf.Count);
2497
                    var entry = zf[0];
2498
                    Assert.AreEqual(tempName1, entry.Name);
2499
                    Assert.AreEqual(1, entry.Size);
2500
                    Assert.IsTrue(zf.TestArchive(true));
2501

    
2502
                    zf.Close();
2503
                }
2504
            }
2505
            finally
2506
            {
2507
                File.Delete(tempName1);
2508
            }
2509
        }
2510

    
2511
        [Test]
2512
        [Category("Zip")]
2513
        public void Encryption()
2514
        {
2515
            const string tempName1 = "a.dat";
2516

    
2517
            var target = new MemoryStream();
2518

    
2519
            var tempFilePath = GetTempFilePath();
2520
            Assert.IsNotNull(tempFilePath, "No permission to execute this test?");
2521

    
2522
            var addFile = Path.Combine(tempFilePath, tempName1);
2523
            MakeTempFile(addFile, 1);
2524

    
2525
            try
2526
            {
2527
                var fastZip = new FastZip();
2528
                fastZip.Password = "Ahoy";
2529

    
2530
                fastZip.CreateZip(target, tempFilePath, false, @"a\.dat", null);
2531

    
2532
                var archive = new MemoryStream(target.ToArray());
2533
                using (var zf = new ZipFile(archive))
2534
                {
2535
                    zf.Password = "Ahoy";
2536
                    Assert.AreEqual(1, zf.Count);
2537
                    var entry = zf[0];
2538
                    Assert.AreEqual(tempName1, entry.Name);
2539
                    Assert.AreEqual(1, entry.Size);
2540
                    Assert.IsTrue(zf.TestArchive(true));
2541
                    Assert.IsTrue(entry.IsCrypted);
2542
                }
2543
            }
2544
            finally
2545
            {
2546
                File.Delete(tempName1);
2547
            }
2548
        }
2549

    
2550
        [Test]
2551
        [Category("Zip")]
2552
        [Category("CreatesTempFile")]
2553
        public void ExtractEmptyDirectories()
2554
        {
2555
            var tempFilePath = GetTempFilePath();
2556
            Assert.IsNotNull(tempFilePath, "No permission to execute this test?");
2557

    
2558
            var name = Path.Combine(tempFilePath, "x.zip");
2559

    
2560
            EnsureTestDirectoryIsEmpty(tempFilePath);
2561

    
2562
            var targetDir = Path.Combine(tempFilePath, ZipTempDir + @"\floyd");
2563
            using (var fs = File.Create(name))
2564
            {
2565
                using (var zOut = new ZipOutputStream(fs))
2566
                {
2567
                    zOut.PutNextEntry(new ZipEntry("floyd/"));
2568
                }
2569
            }
2570

    
2571
            var fastZip = new FastZip();
2572
            fastZip.CreateEmptyDirectories = true;
2573
            fastZip.ExtractZip(name, targetDir, "zz");
2574

    
2575
            File.Delete(name);
2576
            Assert.IsTrue(Directory.Exists(targetDir), "Empty directory should be created");
2577
        }
2578

    
2579
        [Test]
2580
        [Category("Zip")]
2581
        public void NonAsciiPasswords()
2582
        {
2583
            const string tempName1 = "a.dat";
2584

    
2585
            var target = new MemoryStream();
2586

    
2587
            var tempFilePath = GetTempFilePath();
2588
            Assert.IsNotNull(tempFilePath, "No permission to execute this test?");
2589

    
2590
            var addFile = Path.Combine(tempFilePath, tempName1);
2591
            MakeTempFile(addFile, 1);
2592

    
2593
            var password = "abc\u0066\u0393";
2594
            try
2595
            {
2596
                var fastZip = new FastZip();
2597
                fastZip.Password = password;
2598

    
2599
                fastZip.CreateZip(target, tempFilePath, false, @"a\.dat", null);
2600

    
2601
                var archive = new MemoryStream(target.ToArray());
2602
                using (var zf = new ZipFile(archive))
2603
                {
2604
                    zf.Password = password;
2605
                    Assert.AreEqual(1, zf.Count);
2606
                    var entry = zf[0];
2607
                    Assert.AreEqual(tempName1, entry.Name);
2608
                    Assert.AreEqual(1, entry.Size);
2609
                    Assert.IsTrue(zf.TestArchive(true));
2610
                    Assert.IsTrue(entry.IsCrypted);
2611
                }
2612
            }
2613
            finally
2614
            {
2615
                File.Delete(tempName1);
2616
            }
2617
        }
2618
    }
2619

    
2620
    [TestFixture]
2621
    public class ZipFileHandling : ZipBase
2622
    {
2623
        private void Compare(byte[] a, byte[] b)
2624
        {
2625
            Assert.AreEqual(a.Length, b.Length);
2626
            for (var i = 0; i < a.Length; ++i)
2627
            {
2628
                Assert.AreEqual(a[i], b[i]);
2629
            }
2630
        }
2631

    
2632
        private void TryDeleting(byte[] master, int totalEntries, int additions, params string[] toDelete)
2633
        {
2634
            var ms = new MemoryStream();
2635
            ms.Write(master, 0, master.Length);
2636

    
2637
            using (var f = new ZipFile(ms))
2638
            {
2639
                f.IsStreamOwner = false;
2640
                Assert.AreEqual(totalEntries, f.Count);
2641
                Assert.IsTrue(f.TestArchive(true));
2642
                f.BeginUpdate(new MemoryArchiveStorage());
2643

    
2644
                for (var i = 0; i < additions; ++i)
2645
                {
2646
                    f.Add(new StringMemoryDataSource("Another great file"),
2647
                          string.Format("Add{0}.dat", i + 1));
2648
                }
2649

    
2650
                foreach (var name in toDelete)
2651
                {
2652
                    f.Delete(name);
2653
                }
2654
                f.CommitUpdate();
2655

    
2656
                // write stream to file to assist debugging.
2657
                // WriteToFile(@"c:\aha.zip", ms.ToArray());
2658

    
2659
                var newTotal = totalEntries + additions - toDelete.Length;
2660
                Assert.AreEqual(newTotal, f.Count,
2661
                                string.Format("Expected {0} entries after update found {1}", newTotal, f.Count));
2662
                Assert.IsTrue(f.TestArchive(true), "Archive test should pass");
2663
            }
2664
        }
2665

    
2666
        private void TryDeleting(byte[] master, int totalEntries, int additions, params int[] toDelete)
2667
        {
2668
            var ms = new MemoryStream();
2669
            ms.Write(master, 0, master.Length);
2670

    
2671
            using (var f = new ZipFile(ms))
2672
            {
2673
                f.IsStreamOwner = false;
2674
                Assert.AreEqual(totalEntries, f.Count);
2675
                Assert.IsTrue(f.TestArchive(true));
2676
                f.BeginUpdate(new MemoryArchiveStorage());
2677

    
2678
                for (var i = 0; i < additions; ++i)
2679
                {
2680
                    f.Add(new StringMemoryDataSource("Another great file"),
2681
                          string.Format("Add{0}.dat", i + 1));
2682
                }
2683

    
2684
                foreach (var i in toDelete)
2685
                {
2686
                    f.Delete(f[i]);
2687
                }
2688
                f.CommitUpdate();
2689

    
2690
                /* write stream to file to assist debugging.
2691
								byte[] data = ms.ToArray();
2692
								using ( FileStream fs = File.Open(@"c:\aha.zip", FileMode.Create, FileAccess.ReadWrite, FileShare.Read) ) {
2693
									fs.Write(data, 0, data.Length);
2694
								}
2695
				*/
2696
                var newTotal = totalEntries + additions - toDelete.Length;
2697
                Assert.AreEqual(newTotal, f.Count,
2698
                                string.Format("Expected {0} entries after update found {1}", newTotal, f.Count));
2699
                Assert.IsTrue(f.TestArchive(true), "Archive test should pass");
2700
            }
2701
        }
2702

    
2703
        [Test]
2704
        [Category("Zip")]
2705
        [Category("CreatesTempFile")]
2706
        public void AddAndDeleteEntries()
2707
        {
2708
            var tempFile = GetTempFilePath();
2709
            Assert.IsNotNull(tempFile, "No permission to execute this test?");
2710

    
2711
            var addFile = Path.Combine(tempFile, "a.dat");
2712
            MakeTempFile(addFile, 1);
2713

    
2714
            var addFile2 = Path.Combine(tempFile, "b.dat");
2715
            MakeTempFile(addFile2, 259);
2716

    
2717
            tempFile = Path.Combine(tempFile, "SharpZipTest.Zip");
2718

    
2719
            using (var f = ZipFile.Create(tempFile))
2720
            {
2721
                f.BeginUpdate();
2722
                f.Add(addFile);
2723
                f.Add(addFile2);
2724
                f.CommitUpdate();
2725
                Assert.IsTrue(f.TestArchive(true));
2726
            }
2727

    
2728
            using (var f = new ZipFile(tempFile))
2729
            {
2730
                Assert.AreEqual(2, f.Count);
2731
                Assert.IsTrue(f.TestArchive(true));
2732
                f.BeginUpdate();
2733
                f.Delete(f[0]);
2734
                f.CommitUpdate();
2735
                Assert.AreEqual(1, f.Count);
2736
                Assert.IsTrue(f.TestArchive(true));
2737
            }
2738

    
2739
            File.Delete(addFile);
2740
            File.Delete(addFile2);
2741
            File.Delete(tempFile);
2742
        }
2743

    
2744
        [Test]
2745
        [Category("Zip")]
2746
        public void AddAndDeleteEntriesMemory()
2747
        {
2748
            var memStream = new MemoryStream();
2749

    
2750
            using (var f = new ZipFile(memStream))
2751
            {
2752
                f.IsStreamOwner = false;
2753

    
2754
                f.BeginUpdate(new MemoryArchiveStorage());
2755
                f.Add(new StringMemoryDataSource("Hello world"), @"z:\a\a.dat");
2756
                f.Add(new StringMemoryDataSource("Another"), @"\b\b.dat");
2757
                f.Add(new StringMemoryDataSource("Mr C"), @"c\c.dat");
2758
                f.Add(new StringMemoryDataSource("Mrs D was a star"), @"d\d.dat");
2759
                f.CommitUpdate();
2760
                Assert.IsTrue(f.TestArchive(true));
2761
            }
2762

    
2763
            var master = memStream.ToArray();
2764

    
2765
            TryDeleting(master, 4, 1, @"z:\a\a.dat");
2766
            TryDeleting(master, 4, 1, @"\a\a.dat");
2767
            TryDeleting(master, 4, 1, @"a/a.dat");
2768

    
2769
            TryDeleting(master, 4, 0, 0);
2770
            TryDeleting(master, 4, 0, 1);
2771
            TryDeleting(master, 4, 0, 2);
2772
            TryDeleting(master, 4, 0, 3);
2773
            TryDeleting(master, 4, 0, 0, 1);
2774
            TryDeleting(master, 4, 0, 0, 2);
2775
            TryDeleting(master, 4, 0, 0, 3);
2776
            TryDeleting(master, 4, 0, 1, 2);
2777
            TryDeleting(master, 4, 0, 1, 3);
2778
            TryDeleting(master, 4, 0, 2);
2779

    
2780
            TryDeleting(master, 4, 1, 0);
2781
            TryDeleting(master, 4, 1, 1);
2782
            TryDeleting(master, 4, 3, 2);
2783
            TryDeleting(master, 4, 4, 3);
2784
            TryDeleting(master, 4, 10, 0, 1);
2785
            TryDeleting(master, 4, 10, 0, 2);
2786
            TryDeleting(master, 4, 10, 0, 3);
2787
            TryDeleting(master, 4, 20, 1, 2);
2788
            TryDeleting(master, 4, 30, 1, 3);
2789
            TryDeleting(master, 4, 40, 2);
2790
        }
2791

    
2792
        [Test]
2793
        [Category("Zip")]
2794
        public void AddEncryptedEntriesToExistingArchive()
2795
        {
2796
            const string TestValue = "0001000";
2797
            var memStream = new MemoryStream();
2798
            using (var f = new ZipFile(memStream))
2799
            {
2800
                f.IsStreamOwner = false;
2801
                f.UseZip64 = UseZip64.Off;
2802

    
2803
                var m = new StringMemoryDataSource(TestValue);
2804
                f.BeginUpdate(new MemoryArchiveStorage());
2805
                f.Add(m, "a.dat");
2806
                f.CommitUpdate();
2807
                Assert.IsTrue(f.TestArchive(true), "Archive test should pass");
2808
            }
2809

    
2810
            using (var g = new ZipFile(memStream))
2811
            {
2812
                var ze = g[0];
2813

    
2814
                Assert.IsFalse(ze.IsCrypted, "Entry should NOT be encrypted");
2815
                using (var r = new StreamReader(g.GetInputStream(0)))
2816
                {
2817
                    var data = r.ReadToEnd();
2818
                    Assert.AreEqual(TestValue, data);
2819
                }
2820

    
2821
                var n = new StringMemoryDataSource(TestValue);
2822

    
2823
                g.Password = "Axolotyl";
2824
                g.UseZip64 = UseZip64.Off;
2825
                g.IsStreamOwner = false;
2826
                g.BeginUpdate();
2827
                g.Add(n, "a1.dat");
2828
                g.CommitUpdate();
2829
                Assert.IsTrue(g.TestArchive(true), "Archive test should pass");
2830
                ze = g[1];
2831
                Assert.IsTrue(ze.IsCrypted, "New entry should be encrypted");
2832
                using (var r = new StreamReader(g.GetInputStream(0)))
2833
                {
2834
                    var data = r.ReadToEnd();
2835
                    Assert.AreEqual(TestValue, data);
2836
                }
2837
            }
2838
        }
2839

    
2840
        [Test]
2841
        [Category("Zip")]
2842
        public void AddToEmptyArchive()
2843
        {
2844
            var tempFile = GetTempFilePath();
2845
            Assert.IsNotNull(tempFile, "No permission to execute this test?");
2846
            if (tempFile != null)
2847
            {
2848
                var addFile = Path.Combine(tempFile, "a.dat");
2849
                MakeTempFile(addFile, 1);
2850

    
2851
                tempFile = Path.Combine(tempFile, "SharpZipTest.Zip");
2852

    
2853
                using (var f = ZipFile.Create(tempFile))
2854
                {
2855
                    f.BeginUpdate();
2856
                    f.Add(addFile);
2857
                    f.CommitUpdate();
2858
                    Assert.AreEqual(1, f.Count);
2859
                    Assert.IsTrue(f.TestArchive(true));
2860
                }
2861

    
2862
                using (var f = new ZipFile(tempFile))
2863
                {
2864
                    Assert.AreEqual(1, f.Count);
2865
                    f.BeginUpdate();
2866
                    f.Delete(f[0]);
2867
                    f.CommitUpdate();
2868
                    Assert.AreEqual(0, f.Count);
2869
                    Assert.IsTrue(f.TestArchive(true));
2870
                    f.Close();
2871
                }
2872

    
2873
                File.Delete(addFile);
2874
                File.Delete(tempFile);
2875
            }
2876
        }
2877

    
2878
        [Test]
2879
        [Category("Zip")]
2880
        public void ArchiveTesting()
2881
        {
2882
            byte[] originalData = null;
2883
            var compressedData = MakeInMemoryZip(ref originalData, CompressionMethod.Deflated,
2884
                                                 6, 1024, null, true);
2885

    
2886
            var ms = new MemoryStream(compressedData);
2887
            ms.Seek(0, SeekOrigin.Begin);
2888

    
2889
            using (var testFile = new ZipFile(ms))
2890
            {
2891
                Assert.IsTrue(testFile.TestArchive(true), "Unexpected error in archive detected");
2892

    
2893
                var corrupted = new byte[compressedData.Length];
2894
                Array.Copy(compressedData, corrupted, compressedData.Length);
2895

    
2896
                corrupted[123] = (byte) (~corrupted[123] & 0xff);
2897
                ms = new MemoryStream(corrupted);
2898
            }
2899

    
2900
            using (var testFile = new ZipFile(ms))
2901
            {
2902
                Assert.IsFalse(testFile.TestArchive(true), "Error in archive not detected");
2903
            }
2904
        }
2905

    
2906
        [Test]
2907
        [Category("Zip")]
2908
        public void BasicEncryption()
2909
        {
2910
            const string TestValue = "0001000";
2911
            var memStream = new MemoryStream();
2912
            using (var f = new ZipFile(memStream))
2913
            {
2914
                f.IsStreamOwner = false;
2915
                f.Password = "Hello";
2916

    
2917
                var m = new StringMemoryDataSource(TestValue);
2918
                f.BeginUpdate(new MemoryArchiveStorage());
2919
                f.Add(m, "a.dat");
2920
                f.CommitUpdate();
2921
                Assert.IsTrue(f.TestArchive(true), "Archive test should pass");
2922
            }
2923

    
2924
            using (var g = new ZipFile(memStream))
2925
            {
2926
                g.Password = "Hello";
2927
                var ze = g[0];
2928

    
2929
                Assert.IsTrue(ze.IsCrypted, "Entry should be encrypted");
2930
                using (var r = new StreamReader(g.GetInputStream(0)))
2931
                {
2932
                    var data = r.ReadToEnd();
2933
                    Assert.AreEqual(TestValue, data);
2934
                }
2935
            }
2936
        }
2937

    
2938
        [Test]
2939
        [Category("Zip")]
2940
        [Category("CreatesTempFile")]
2941
        public void BasicEncryptionToDisk()
2942
        {
2943
            const string TestValue = "0001000";
2944
            var tempFile = GetTempFilePath();
2945
            Assert.IsNotNull(tempFile, "No permission to execute this test?");
2946

    
2947
            tempFile = Path.Combine(tempFile, "SharpZipTest.Zip");
2948

    
2949
            using (var f = ZipFile.Create(tempFile))
2950
            {
2951
                f.Password = "Hello";
2952

    
2953
                var m = new StringMemoryDataSource(TestValue);
2954
                f.BeginUpdate();
2955
                f.Add(m, "a.dat");
2956
                f.CommitUpdate();
2957
            }
2958

    
2959
            using (var f = new ZipFile(tempFile))
2960
            {
2961
                f.Password = "Hello";
2962
                Assert.IsTrue(f.TestArchive(true), "Archive test should pass");
2963
            }
2964

    
2965
            using (var g = new ZipFile(tempFile))
2966
            {
2967
                g.Password = "Hello";
2968
                var ze = g[0];
2969

    
2970
                Assert.IsTrue(ze.IsCrypted, "Entry should be encrypted");
2971
                using (var r = new StreamReader(g.GetInputStream(0)))
2972
                {
2973
                    var data = r.ReadToEnd();
2974
                    Assert.AreEqual(TestValue, data);
2975
                }
2976
            }
2977

    
2978
            File.Delete(tempFile);
2979
        }
2980

    
2981
        [Test]
2982
        [Category("Zip")]
2983
        public void CreateEmptyArchive()
2984
        {
2985
            var tempFile = GetTempFilePath();
2986
            Assert.IsNotNull(tempFile, "No permission to execute this test?");
2987

    
2988
            if (tempFile != null)
2989
            {
2990
                tempFile = Path.Combine(tempFile, "SharpZipTest.Zip");
2991

    
2992
                using (var f = ZipFile.Create(tempFile))
2993
                {
2994
                    f.BeginUpdate();
2995
                    f.CommitUpdate();
2996
                    Assert.IsTrue(f.TestArchive(true));
2997
                    f.Close();
2998
                }
2999

    
3000
                using (var f = new ZipFile(tempFile))
3001
                {
3002
                    Assert.AreEqual(0, f.Count);
3003
                }
3004
            }
3005
        }
3006

    
3007
        [Test]
3008
        [Category("Zip")]
3009
        public void Crypto_AddEncryptedEntryToExistingArchiveDirect()
3010
        {
3011
            var ms = new MemoryStream();
3012

    
3013
            byte[] rawData;
3014

    
3015
            using (var testFile = new ZipFile(ms))
3016
            {
3017
                testFile.IsStreamOwner = false;
3018
                testFile.BeginUpdate();
3019
                testFile.Add(new StringMemoryDataSource("Aha"), "No1", CompressionMethod.Stored);
3020
                testFile.Add(new StringMemoryDataSource("And so it goes"), "No2", CompressionMethod.Stored);
3021
                testFile.Add(new StringMemoryDataSource("No3"), "No3", CompressionMethod.Stored);
3022
                testFile.CommitUpdate();
3023

    
3024
                Assert.IsTrue(testFile.TestArchive(true));
3025
                rawData = ms.ToArray();
3026
            }
3027

    
3028
            using (var testFile = new ZipFile(ms))
3029
            {
3030
                Assert.IsTrue(testFile.TestArchive(true));
3031
                testFile.IsStreamOwner = false;
3032

    
3033
                testFile.BeginUpdate();
3034
                testFile.Password = "pwd";
3035
                testFile.Add(new StringMemoryDataSource("Zapata!"), "encrypttest.xml");
3036
                testFile.CommitUpdate();
3037

    
3038
                Assert.IsTrue(testFile.TestArchive(true));
3039

    
3040
                var entryIndex = testFile.FindEntry("encrypttest.xml", true);
3041
                Assert.IsNotNull(entryIndex >= 0);
3042
                Assert.IsTrue(testFile[entryIndex].IsCrypted);
3043
            }
3044
        }
3045

    
3046
        [Test]
3047
        [Category("Zip")]
3048
        public void Crypto_AddEncryptedEntryToExistingArchiveSafe()
3049
        {
3050
            var ms = new MemoryStream();
3051

    
3052
            byte[] rawData;
3053

    
3054
            using (var testFile = new ZipFile(ms))
3055
            {
3056
                testFile.IsStreamOwner = false;
3057
                testFile.BeginUpdate();
3058
                testFile.Add(new StringMemoryDataSource("Aha"), "No1", CompressionMethod.Stored);
3059
                testFile.Add(new StringMemoryDataSource("And so it goes"), "No2", CompressionMethod.Stored);
3060
                testFile.Add(new StringMemoryDataSource("No3"), "No3", CompressionMethod.Stored);
3061
                testFile.CommitUpdate();
3062

    
3063
                Assert.IsTrue(testFile.TestArchive(true));
3064
                rawData = ms.ToArray();
3065
            }
3066

    
3067
            ms = new MemoryStream(rawData);
3068

    
3069
            using (var testFile = new ZipFile(ms))
3070
            {
3071
                Assert.IsTrue(testFile.TestArchive(true));
3072

    
3073
                testFile.BeginUpdate(new MemoryArchiveStorage(FileUpdateMode.Safe));
3074
                testFile.Password = "pwd";
3075
                testFile.Add(new StringMemoryDataSource("Zapata!"), "encrypttest.xml");
3076
                testFile.CommitUpdate();
3077

    
3078
                Assert.IsTrue(testFile.TestArchive(true));
3079

    
3080
                var entryIndex = testFile.FindEntry("encrypttest.xml", true);
3081
                Assert.IsNotNull(entryIndex >= 0);
3082
                Assert.IsTrue(testFile[entryIndex].IsCrypted);
3083
            }
3084
        }
3085

    
3086
        [Test]
3087
        [Category("Zip")]
3088
        public void EmbeddedArchive()
3089
        {
3090
            var memStream = new MemoryStream();
3091
            using (var f = new ZipFile(memStream))
3092
            {
3093
                f.IsStreamOwner = false;
3094

    
3095
                var m = new StringMemoryDataSource("0000000");
3096
                f.BeginUpdate(new MemoryArchiveStorage());
3097
                f.Add(m, "a.dat");
3098
                f.Add(m, "b.dat");
3099
                f.CommitUpdate();
3100
                Assert.IsTrue(f.TestArchive(true));
3101
            }
3102

    
3103
            var rawArchive = memStream.ToArray();
3104
            var pseudoSfx = new byte[1049 + rawArchive.Length];
3105
            Array.Copy(rawArchive, 0, pseudoSfx, 1049, rawArchive.Length);
3106

    
3107
            memStream = new MemoryStream(pseudoSfx);
3108
            using (var f = new ZipFile(memStream))
3109
            {
3110
                for (var index = 0; index < f.Count; ++index)
3111
                {
3112
                    var entryStream = f.GetInputStream(index);
3113
                    var data = new MemoryStream();
3114
                    StreamUtils.Copy(entryStream, data, new byte[128]);
3115

    
3116
                    var bytes = data.ToArray();
3117
                    string contents = Encoding.UTF8.GetString(bytes, 0, bytes.Length);
3118
                    Assert.AreEqual("0000000", contents);
3119
                }
3120
            }
3121
        }
3122

    
3123
        /// <summary>
3124
        /// Check that ZipFile doesnt find entries when there is more than 64K of data at the end.
3125
        /// </summary>
3126
        /// <remarks>
3127
        /// This may well be flawed but is the current behaviour.
3128
        /// </remarks>
3129
        [Test]
3130
        [Category("Zip")]
3131
        [Category("CreatesTempFile")]
3132
        public void FindEntriesInArchiveExtraData()
3133
        {
3134
            var tempFile = GetTempFilePath();
3135
            Assert.IsNotNull(tempFile, "No permission to execute this test?");
3136

    
3137
            if (tempFile != null)
3138
            {
3139
                tempFile = Path.Combine(tempFile, "SharpZipTest.Zip");
3140
                var longComment = new String('A', 65535);
3141
                var tempStream = File.Create(tempFile);
3142
                MakeZipFile(tempStream, false, "", 1, 1, longComment);
3143

    
3144
                tempStream.WriteByte(85);
3145
                tempStream.Close();
3146

    
3147
                var fails = false;
3148
                try
3149
                {
3150
                    using (var zipFile = new ZipFile(tempFile))
3151
                    {
3152
                        foreach (ZipEntry e in zipFile)
3153
                        {
3154
                            var instream = zipFile.GetInputStream(e);
3155
                            CheckKnownEntry(instream, 1);
3156
                        }
3157
                        zipFile.Close();
3158
                    }
3159
                }
3160
                catch
3161
                {
3162
                    fails = true;
3163
                }
3164

    
3165
                File.Delete(tempFile);
3166
                Assert.IsTrue(fails, "Currently zip file wont be found");
3167
            }
3168
        }
3169

    
3170
        /// <summary>
3171
        /// Check that ZipFile finds entries when its got a long comment
3172
        /// </summary>
3173
        [Test]
3174
        [Category("Zip")]
3175
        [Category("CreatesTempFile")]
3176
        public void FindEntriesInArchiveWithLongComment()
3177
        {
3178
            var tempFile = GetTempFilePath();
3179
            Assert.IsNotNull(tempFile, "No permission to execute this test?");
3180

    
3181
            if (tempFile != null)
3182
            {
3183
                tempFile = Path.Combine(tempFile, "SharpZipTest.Zip");
3184
                var longComment = new String('A', 65535);
3185
                MakeZipFile(tempFile, "", 1, 1, longComment);
3186
                using (var zipFile = new ZipFile(tempFile))
3187
                {
3188
                    foreach (ZipEntry e in zipFile)
3189
                    {
3190
                        var instream = zipFile.GetInputStream(e);
3191
                        CheckKnownEntry(instream, 1);
3192
                    }
3193
                    zipFile.Close();
3194
                }
3195
                File.Delete(tempFile);
3196
            }
3197
        }
3198

    
3199
        /// <summary>
3200
        /// Test ZipFile Find method operation
3201
        /// </summary>
3202
        [Test]
3203
        [Category("Zip")]
3204
        [Category("CreatesTempFile")]
3205
        public void FindEntry()
3206
        {
3207
            var tempFile = GetTempFilePath();
3208
            Assert.IsNotNull(tempFile, "No permission to execute this test?");
3209

    
3210
            if (tempFile != null)
3211
            {
3212
                tempFile = Path.Combine(tempFile, "SharpZipTest.Zip");
3213
                MakeZipFile(tempFile, new[]{"Farriera", "Champagne", "Urban myth"}, 10, "Aha");
3214

    
3215
                using (var zipFile = new ZipFile(tempFile))
3216
                {
3217
                    Assert.AreEqual(3, zipFile.Count, "Expected 1 entry");
3218

    
3219
                    var testIndex = zipFile.FindEntry("Farriera", false);
3220
                    Assert.AreEqual(0, testIndex, "Case sensitive find failure");
3221
                    Assert.IsTrue(string.Compare(zipFile[testIndex].Name, "Farriera", StringComparison.InvariantCulture) == 0);
3222

    
3223
                    testIndex = zipFile.FindEntry("Farriera", true);
3224
                    Assert.AreEqual(0, testIndex, "Case insensitive find failure");
3225
                    Assert.IsTrue(string.Compare(zipFile[testIndex].Name, "Farriera", StringComparison.InvariantCultureIgnoreCase) == 0);
3226

    
3227
                    testIndex = zipFile.FindEntry("urban mYTH", false);
3228
                    Assert.AreEqual(-1, testIndex, "Case sensitive find failure");
3229

    
3230
                    testIndex = zipFile.FindEntry("urban mYTH", true);
3231
                    Assert.AreEqual(2, testIndex, "Case insensitive find failure");
3232
                    Assert.IsTrue(string.Compare(zipFile[testIndex].Name, "urban mYTH", StringComparison.InvariantCultureIgnoreCase) == 0);
3233

    
3234
                    testIndex = zipFile.FindEntry("Champane.", false);
3235
                    Assert.AreEqual(-1, testIndex, "Case sensitive find failure");
3236

    
3237
                    testIndex = zipFile.FindEntry("Champane.", true);
3238
                    Assert.AreEqual(-1, testIndex, "Case insensitive find failure");
3239

    
3240
                    zipFile.Close();
3241
                }
3242
                File.Delete(tempFile);
3243
            }
3244
        }
3245

    
3246
        /// <summary>
3247
        /// Check that ZipFile class handles no entries in zip file
3248
        /// </summary>
3249
        [Test]
3250
        [Category("Zip")]
3251
        [Category("CreatesTempFile")]
3252
        public void HandlesNoEntries()
3253
        {
3254
            var tempFile = GetTempFilePath();
3255
            Assert.IsNotNull(tempFile, "No permission to execute this test?");
3256

    
3257
            if (tempFile != null)
3258
            {
3259
                tempFile = Path.Combine(tempFile, "SharpZipTest.Zip");
3260
                MakeZipFile(tempFile, "", 0, 1, "Aha");
3261

    
3262
                using (var zipFile = new ZipFile(tempFile))
3263
                {
3264
                    Assert.AreEqual(0, zipFile.Count);
3265
                    zipFile.Close();
3266
                }
3267

    
3268
                File.Delete(tempFile);
3269
            }
3270
        }
3271

    
3272
        [Test]
3273
        [Category("Zip")]
3274
        public void NameFactory()
3275
        {
3276
            var memStream = new MemoryStream();
3277
            var fixedTime = new DateTime(1981, 4, 3);
3278
            using (var f = new ZipFile(memStream))
3279
            {
3280
                f.IsStreamOwner = false;
3281
                ((ZipEntryFactory) f.EntryFactory).IsUnicodeText = true;
3282
                ((ZipEntryFactory) f.EntryFactory).Setting = ZipEntryFactory.TimeSetting.Fixed;
3283
                ((ZipEntryFactory) f.EntryFactory).FixedDateTime = fixedTime;
3284
                ((ZipEntryFactory) f.EntryFactory).SetAttributes = 1;
3285
                f.BeginUpdate(new MemoryArchiveStorage());
3286

    
3287
                var names = new[]{
3288
                                     "\u030A\u03B0", // Greek
3289
                                     "\u0680\u0685", // Arabic
3290
                                 };
3291

    
3292
                foreach (var name in names)
3293
                {
3294
                    f.Add(new StringMemoryDataSource("Hello world"), name,
3295
                          CompressionMethod.Deflated, true);
3296
                }
3297
                f.CommitUpdate();
3298
                Assert.IsTrue(f.TestArchive(true));
3299

    
3300
                foreach (var name in names)
3301
                {
3302
                    var index = f.FindEntry(name, true);
3303

    
3304
                    Assert.IsTrue(index >= 0);
3305
                    var found = f[index];
3306
                    Assert.AreEqual(name, found.Name);
3307
                    Assert.IsTrue(found.IsUnicodeText);
3308
                    Assert.AreEqual(fixedTime, found.DateTime);
3309
                    Assert.IsTrue(found.IsDOSEntry);
3310
                }
3311
            }
3312
        }
3313

    
3314
        [Test]
3315
        [Category("Zip")]
3316
        public void NullStreamDetected()
3317
        {
3318
            ZipFile bad = null;
3319
            FileStream nullStream = null;
3320

    
3321
            var nullStreamDetected = false;
3322

    
3323
            try
3324
            {
3325
                bad = new ZipFile(nullStream);
3326
            }
3327
            catch
3328
            {
3329
                nullStreamDetected = true;
3330
            }
3331

    
3332
            Assert.IsTrue(nullStreamDetected, "Null stream should be detected in ZipFile constructor");
3333
            Assert.IsNull(bad, "ZipFile instance should not be created");
3334
        }
3335

    
3336
        /// <summary>
3337
        /// Simple round trip test for ZipFile class
3338
        /// </summary>
3339
        [Test]
3340
        [Category("Zip")]
3341
        [Category("CreatesTempFile")]
3342
        public void RoundTrip()
3343
        {
3344
            var tempFile = GetTempFilePath();
3345
            Assert.IsNotNull(tempFile, "No permission to execute this test?");
3346

    
3347
            if (tempFile != null)
3348
            {
3349
                tempFile = Path.Combine(tempFile, "SharpZipTest.Zip");
3350
                MakeZipFile(tempFile, "", 10, 1024, "");
3351

    
3352
                using (var zipFile = new ZipFile(tempFile))
3353
                {
3354
                    foreach (ZipEntry e in zipFile)
3355
                    {
3356
                        var instream = zipFile.GetInputStream(e);
3357
                        CheckKnownEntry(instream, 1024);
3358
                    }
3359
                    zipFile.Close();
3360
                }
3361

    
3362
                File.Delete(tempFile);
3363
            }
3364
        }
3365

    
3366
        /// <summary>
3367
        /// Simple round trip test for ZipFile class
3368
        /// </summary>
3369
        [Test]
3370
        [Category("Zip")]
3371
        public void RoundTripInMemory()
3372
        {
3373
            var storage = new MemoryStream();
3374
            MakeZipFile(storage, false, "", 10, 1024, "");
3375

    
3376
            using (var zipFile = new ZipFile(storage))
3377
            {
3378
                foreach (ZipEntry e in zipFile)
3379
                {
3380
                    var instream = zipFile.GetInputStream(e);
3381
                    CheckKnownEntry(instream, 1024);
3382
                }
3383
                zipFile.Close();
3384
            }
3385
        }
3386

    
3387
        [Test]
3388
        [Category("Zip")]
3389
        public void UnicodeNames()
3390
        {
3391
            var memStream = new MemoryStream();
3392
            using (var f = new ZipFile(memStream))
3393
            {
3394
                f.IsStreamOwner = false;
3395

    
3396
                f.BeginUpdate(new MemoryArchiveStorage());
3397

    
3398
                var names = new[]{
3399
                                     "\u030A\u03B0", // Greek
3400
                                     "\u0680\u0685", // Arabic
3401
                                 };
3402

    
3403
                foreach (var name in names)
3404
                {
3405
                    f.Add(new StringMemoryDataSource("Hello world"), name,
3406
                          CompressionMethod.Deflated, true);
3407
                }
3408
                f.CommitUpdate();
3409
                Assert.IsTrue(f.TestArchive(true));
3410

    
3411
                foreach (var name in names)
3412
                {
3413
                    var index = f.FindEntry(name, true);
3414

    
3415
                    Assert.IsTrue(index >= 0);
3416
                    var found = f[index];
3417
                    Assert.AreEqual(name, found.Name);
3418
                }
3419
            }
3420
        }
3421

    
3422
        [Test]
3423
        [Category("Zip")]
3424
        public void UpdateCommentOnlyInMemory()
3425
        {
3426
            var ms = new MemoryStream();
3427

    
3428
            using (var testFile = new ZipFile(ms))
3429
            {
3430
                testFile.IsStreamOwner = false;
3431
                testFile.BeginUpdate();
3432
                testFile.Add(new StringMemoryDataSource("Aha"), "No1", CompressionMethod.Stored);
3433
                testFile.Add(new StringMemoryDataSource("And so it goes"), "No2", CompressionMethod.Stored);
3434
                testFile.Add(new StringMemoryDataSource("No3"), "No3", CompressionMethod.Stored);
3435
                testFile.CommitUpdate();
3436

    
3437
                Assert.IsTrue(testFile.TestArchive(true));
3438
            }
3439

    
3440
            using (var testFile = new ZipFile(ms))
3441
            {
3442
                Assert.IsTrue(testFile.TestArchive(true));
3443
                Assert.AreEqual("", testFile.ZipFileComment);
3444
                testFile.IsStreamOwner = false;
3445

    
3446
                testFile.BeginUpdate();
3447
                testFile.SetComment("Here is my comment");
3448
                testFile.CommitUpdate();
3449

    
3450
                Assert.IsTrue(testFile.TestArchive(true));
3451
            }
3452

    
3453
            using (var testFile = new ZipFile(ms))
3454
            {
3455
                Assert.IsTrue(testFile.TestArchive(true));
3456
                Assert.AreEqual("Here is my comment", testFile.ZipFileComment);
3457
            }
3458
        }
3459

    
3460
        [Test]
3461
        [Category("Zip")]
3462
        [Category("CreatesTempFile")]
3463
        public void UpdateCommentOnlyOnDisk()
3464
        {
3465
            var tempFile = GetTempFilePath();
3466
            Assert.IsNotNull(tempFile, "No permission to execute this test?");
3467

    
3468
            tempFile = Path.Combine(tempFile, "SharpZipTest.Zip");
3469
            if (File.Exists(tempFile))
3470
            {
3471
                File.Delete(tempFile);
3472
            }
3473

    
3474
            using (var testFile = ZipFile.Create(tempFile))
3475
            {
3476
                testFile.BeginUpdate();
3477
                testFile.Add(new StringMemoryDataSource("Aha"), "No1", CompressionMethod.Stored);
3478
                testFile.Add(new StringMemoryDataSource("And so it goes"), "No2", CompressionMethod.Stored);
3479
                testFile.Add(new StringMemoryDataSource("No3"), "No3", CompressionMethod.Stored);
3480
                testFile.CommitUpdate();
3481

    
3482
                Assert.IsTrue(testFile.TestArchive(true));
3483
            }
3484

    
3485
            using (var testFile = new ZipFile(tempFile))
3486
            {
3487
                Assert.IsTrue(testFile.TestArchive(true));
3488
                Assert.AreEqual("", testFile.ZipFileComment);
3489

    
3490
                testFile.BeginUpdate(new DiskArchiveStorage(testFile, FileUpdateMode.Direct));
3491
                testFile.SetComment("Here is my comment");
3492
                testFile.CommitUpdate();
3493

    
3494
                Assert.IsTrue(testFile.TestArchive(true));
3495
            }
3496

    
3497
            using (var testFile = new ZipFile(tempFile))
3498
            {
3499
                Assert.IsTrue(testFile.TestArchive(true));
3500
                Assert.AreEqual("Here is my comment", testFile.ZipFileComment);
3501
            }
3502
            File.Delete(tempFile);
3503

    
3504
            // Variant using indirect updating.
3505
            using (var testFile = ZipFile.Create(tempFile))
3506
            {
3507
                testFile.BeginUpdate();
3508
                testFile.Add(new StringMemoryDataSource("Aha"), "No1", CompressionMethod.Stored);
3509
                testFile.Add(new StringMemoryDataSource("And so it goes"), "No2", CompressionMethod.Stored);
3510
                testFile.Add(new StringMemoryDataSource("No3"), "No3", CompressionMethod.Stored);
3511
                testFile.CommitUpdate();
3512

    
3513
                Assert.IsTrue(testFile.TestArchive(true));
3514
            }
3515

    
3516
            using (var testFile = new ZipFile(tempFile))
3517
            {
3518
                Assert.IsTrue(testFile.TestArchive(true));
3519
                Assert.AreEqual("", testFile.ZipFileComment);
3520

    
3521
                testFile.BeginUpdate();
3522
                testFile.SetComment("Here is my comment");
3523
                testFile.CommitUpdate();
3524

    
3525
                Assert.IsTrue(testFile.TestArchive(true));
3526
            }
3527

    
3528
            using (var testFile = new ZipFile(tempFile))
3529
            {
3530
                Assert.IsTrue(testFile.TestArchive(true));
3531
                Assert.AreEqual("Here is my comment", testFile.ZipFileComment);
3532
            }
3533
            File.Delete(tempFile);
3534
        }
3535

    
3536
        /// <summary>
3537
        /// Check that adding too many entries is detected and handled
3538
        /// </summary>
3539
        [Test]
3540
        [Category("Zip")]
3541
        [Category("CreatesTempFile")]
3542
        public void Zip64Entries()
3543
        {
3544
            var tempFile = GetTempFilePath();
3545
            Assert.IsNotNull(tempFile, "No permission to execute this test?");
3546

    
3547
            const int target = 65537;
3548

    
3549
            using (var zipFile = ZipFile.Create(Path.GetTempFileName()))
3550
            {
3551
                zipFile.BeginUpdate();
3552

    
3553
                for (var i = 0; i < target; ++i)
3554
                {
3555
                    var ze = new ZipEntry(i.ToString());
3556
                    ze.CompressedSize = 0;
3557
                    ze.Size = 0;
3558
                    zipFile.Add(ze);
3559
                }
3560
                zipFile.CommitUpdate();
3561

    
3562
                Assert.IsTrue(zipFile.TestArchive(true));
3563
                Assert.AreEqual(target, zipFile.Count, "Incorrect number of entries stored");
3564
            }
3565
        }
3566

    
3567
        [Test]
3568
        [Category("Zip")]
3569
        [Explicit]
3570
        public void Zip64Offset()
3571
        {
3572
            // TODO: Test to check that a zip64 offset value is loaded correctly.
3573
            // Changes in ZipEntry to CentralHeaderRequiresZip64 and LocalHeaderRequiresZip64
3574
            // were not quite correct...
3575
        }
3576

    
3577
        [Test]
3578
        [Category("Zip")]
3579
        public void Zip64Useage()
3580
        {
3581
            var memStream = new MemoryStream();
3582
            using (var f = new ZipFile(memStream))
3583
            {
3584
                f.IsStreamOwner = false;
3585
                f.UseZip64 = UseZip64.On;
3586

    
3587
                var m = new StringMemoryDataSource("0000000");
3588
                f.BeginUpdate(new MemoryArchiveStorage());
3589
                f.Add(m, "a.dat");
3590
                f.Add(m, "b.dat");
3591
                f.CommitUpdate();
3592
                Assert.IsTrue(f.TestArchive(true));
3593
            }
3594

    
3595
            var rawArchive = memStream.ToArray();
3596

    
3597
            var pseudoSfx = new byte[1049 + rawArchive.Length];
3598
            Array.Copy(rawArchive, 0, pseudoSfx, 1049, rawArchive.Length);
3599

    
3600
            memStream = new MemoryStream(pseudoSfx);
3601
            using (var f = new ZipFile(memStream))
3602
            {
3603
                for (var index = 0; index < f.Count; ++index)
3604
                {
3605
                    var entryStream = f.GetInputStream(index);
3606
                    var data = new MemoryStream();
3607
                    StreamUtils.Copy(entryStream, data, new byte[128]);
3608

    
3609
                    var bytes = data.ToArray();
3610
                    string contents = Encoding.UTF8.GetString(bytes, 0, bytes.Length);
3611
                    Assert.AreEqual("0000000", contents);
3612
                }
3613
            }
3614
        }
3615
    }
3616

    
3617
    [TestFixture]
3618
    public class ZipEntryFactoryHandling : ZipBase
3619
    {
3620
        // TODO: Complete testing for ZipEntryFactory
3621

    
3622
        [Test]
3623
        [Category("Zip")]
3624
        public void CreateInMemoryValues()
3625
        {
3626
            var tempFile = "bingo:";
3627

    
3628
            // Note the seconds returned will be even!
3629
            var epochTime = new DateTime(1980, 1, 1);
3630
            var createTime = new DateTime(2100, 2, 27, 11, 07, 56);
3631
            var lastWriteTime = new DateTime(2050, 11, 3, 7, 23, 32);
3632
            var lastAccessTime = new DateTime(2050, 11, 3, 0, 42, 12);
3633

    
3634
            var factory = new ZipEntryFactory();
3635
            ZipEntry entry;
3636
            int combinedAttributes;
3637

    
3638
            var startTime = DateTime.Now;
3639

    
3640
            factory.Setting = ZipEntryFactory.TimeSetting.CreateTime;
3641
            factory.GetAttributes = ~((int) FileAttributes.ReadOnly);
3642
            factory.SetAttributes = (int) FileAttributes.ReadOnly;
3643
            combinedAttributes = (int) FileAttributes.ReadOnly;
3644

    
3645
            entry = factory.MakeFileEntry(tempFile, false);
3646
            Assert.IsTrue(TestHelper.CompareDosDateTimes(startTime, entry.DateTime) <= 0, "Create time failure");
3647
            Assert.AreEqual(entry.ExternalFileAttributes, combinedAttributes);
3648
            Assert.AreEqual(-1, entry.Size);
3649

    
3650
            factory.FixedDateTime = startTime;
3651
            factory.Setting = ZipEntryFactory.TimeSetting.Fixed;
3652
            entry = factory.MakeFileEntry(tempFile, false);
3653
            Assert.AreEqual(0, TestHelper.CompareDosDateTimes(startTime, entry.DateTime), "Access time failure");
3654
            Assert.AreEqual(-1, entry.Size);
3655

    
3656
            factory.Setting = ZipEntryFactory.TimeSetting.LastWriteTime;
3657
            entry = factory.MakeFileEntry(tempFile, false);
3658
            Assert.IsTrue(TestHelper.CompareDosDateTimes(startTime, entry.DateTime) <= 0, "Write time failure");
3659
            Assert.AreEqual(-1, entry.Size);
3660
        }
3661

    
3662
        [Test]
3663
        [Category("Zip")]
3664
        public void Defaults()
3665
        {
3666
            var testStart = DateTime.Now;
3667
            var f = new ZipEntryFactory();
3668
            Assert.IsNotNull(f.NameTransform);
3669
            Assert.AreEqual(-1, f.GetAttributes);
3670
            Assert.AreEqual(0, f.SetAttributes);
3671
            Assert.AreEqual(ZipEntryFactory.TimeSetting.LastWriteTime, f.Setting);
3672

    
3673
            Assert.LessOrEqual(testStart, f.FixedDateTime);
3674
            Assert.GreaterOrEqual(DateTime.Now, f.FixedDateTime);
3675

    
3676
            f = new ZipEntryFactory(ZipEntryFactory.TimeSetting.LastAccessTimeUtc);
3677
            Assert.IsNotNull(f.NameTransform);
3678
            Assert.AreEqual(-1, f.GetAttributes);
3679
            Assert.AreEqual(0, f.SetAttributes);
3680
            Assert.AreEqual(ZipEntryFactory.TimeSetting.LastAccessTimeUtc, f.Setting);
3681
            Assert.LessOrEqual(testStart, f.FixedDateTime);
3682
            Assert.GreaterOrEqual(DateTime.Now, f.FixedDateTime);
3683

    
3684
            var fixedDate = new DateTime(1999, 1, 2);
3685
            f = new ZipEntryFactory(fixedDate);
3686
            Assert.IsNotNull(f.NameTransform);
3687
            Assert.AreEqual(-1, f.GetAttributes);
3688
            Assert.AreEqual(0, f.SetAttributes);
3689
            Assert.AreEqual(ZipEntryFactory.TimeSetting.Fixed, f.Setting);
3690
            Assert.AreEqual(fixedDate, f.FixedDateTime);
3691
        }
3692
    }
3693
}