File: ZipFilePart.cs

package info (click to toggle)
mono-reference-assemblies 3.12.1%2Bdfsg-2
  • links: PTS, VCS
  • area: main
  • in suites: stretch
  • size: 604,240 kB
  • ctags: 625,505
  • sloc: cs: 3,967,741; xml: 2,793,081; ansic: 418,042; java: 60,435; sh: 14,833; makefile: 11,576; sql: 7,956; perl: 1,467; cpp: 1,446; yacc: 1,203; python: 598; asm: 422; sed: 16; php: 1
file content (184 lines) | stat: -rw-r--r-- 6,902 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
using System;
using System.IO;
using System.Linq;
using SharpCompress.Common.Zip.Headers;
using SharpCompress.Compressor;
#if BZIP2
using SharpCompress.Compressor.BZip2;
#endif
#if DEFLATE
using SharpCompress.Compressor.Deflate;
#endif
#if LZMA
using SharpCompress.Compressor.LZMA;
#endif
#if PPMd
using SharpCompress.Compressor.PPMd;
#endif
using SharpCompress.IO;

namespace SharpCompress.Common.Zip
{
    internal abstract class ZipFilePart : FilePart
    {
        internal ZipFilePart(ZipFileEntry header, Stream stream)
        {
            Header = header;
            header.Part = this;
            this.BaseStream = stream;
        }

        internal Stream BaseStream { get; private set; }
        internal ZipFileEntry Header { get; set; }


        internal override string FilePartName
        {
            get { return Header.Name; }
        }

        internal override Stream GetCompressedStream()
        {
            if (!Header.HasData)
            {
                return Stream.Null;
            }
            Stream decompressionStream = CreateDecompressionStream(GetCryptoStream(CreateBaseStream()));
            if (LeaveStreamOpen)
            {
                return new NonDisposingStream(decompressionStream);
            }
            return decompressionStream;
        }

        internal override Stream GetRawStream()
        {
            if (!Header.HasData)
            {
                return Stream.Null;
            }
            return CreateBaseStream();
        }

        protected abstract Stream CreateBaseStream();

        protected bool LeaveStreamOpen
        {
            get { return FlagUtility.HasFlag(Header.Flags, HeaderFlags.UsePostDataDescriptor); }
        }

        protected Stream CreateDecompressionStream(Stream stream)
        {
            switch (Header.CompressionMethod)
            {
                case ZipCompressionMethod.None:
                    {
                        return stream;
                    }
                case ZipCompressionMethod.Deflate:
                    {
                        return new System.IO.Compression.DeflateStream(stream,
                            System.IO.Compression.CompressionMode.Decompress);
                    }
#if BZIP2
                case ZipCompressionMethod.BZip2:
                    {
                        return new BZip2Stream(stream, CompressionMode.Decompress);
                    }
#endif
#if LZMA
                case ZipCompressionMethod.LZMA:
                    {
                        if (FlagUtility.HasFlag(Header.Flags, HeaderFlags.Encrypted))
                        {
                            throw new NotSupportedException("LZMA with pkware encryption.");
                        }
                        var reader = new BinaryReader(stream);
                        reader.ReadUInt16(); //LZMA version
                        var props = new byte[reader.ReadUInt16()];
                        reader.Read(props, 0, props.Length);
                        return new LzmaStream(props, stream,
                                              Header.CompressedSize > 0 ? Header.CompressedSize - 4 - props.Length : -1,
                                              FlagUtility.HasFlag(Header.Flags, HeaderFlags.Bit1)
                                                  ? -1
                                                  : (long)Header.UncompressedSize);
                    }
#endif
#if PPMd
                case ZipCompressionMethod.PPMd:
                    {
                        var props = new byte[2];
                        stream.Read(props, 0, props.Length);
                        return new PpmdStream(new PpmdProperties(props), stream, false);
                    }
#endif
                case ZipCompressionMethod.WinzipAes:
                    {
                        ExtraData data = Header.Extra.Where(x => x.Type == ExtraDataType.WinZipAes).SingleOrDefault();
                        if (data == null)
                        {
                            throw new InvalidFormatException("No Winzip AES extra data found.");
                        }
                        if (data.Length != 7)
                        {
                            throw new InvalidFormatException("Winzip data length is not 7.");
                        }
                        ushort method = BitConverter.ToUInt16(data.DataBytes, 0);

                        if (method != 0x01 && method != 0x02)
                        {
                            throw new InvalidFormatException("Unexpected vendor version number for WinZip AES metadata");
                        }

                        ushort vendorId = BitConverter.ToUInt16(data.DataBytes, 2);
                        if (vendorId != 0x4541)
                        {
                            throw new InvalidFormatException("Unexpected vendor ID for WinZip AES metadata");
                        }
                        Header.CompressionMethod = (ZipCompressionMethod)BitConverter.ToUInt16(data.DataBytes, 5);
                        return CreateDecompressionStream(stream);
                    }
                default:
                    {
                        throw new NotSupportedException("CompressionMethod: " + Header.CompressionMethod);
                    }
            }
        }

        protected Stream GetCryptoStream(Stream plainStream)
        {
            if ((Header.CompressedSize == 0)
#if !PORTABLE && !NETFX_CORE
 && ((Header.PkwareTraditionalEncryptionData != null)
                    || (Header.WinzipAesEncryptionData != null)))
#else 
                && (Header.PkwareTraditionalEncryptionData != null))
#endif
            {
                throw new NotSupportedException("Cannot encrypt file with unknown size at start.");
            }
            if ((Header.CompressedSize == 0)
                && FlagUtility.HasFlag(Header.Flags, HeaderFlags.UsePostDataDescriptor))
            {
                plainStream = new NonDisposingStream(plainStream); //make sure AES doesn't close    
            }
            else
            {
                plainStream = new ReadOnlySubStream(plainStream, Header.CompressedSize); //make sure AES doesn't close
            }
            if (Header.PkwareTraditionalEncryptionData != null)
            {
                return new PkwareTraditionalCryptoStream(plainStream, Header.PkwareTraditionalEncryptionData,
                                                         CryptoMode.Decrypt);
            }
#if !PORTABLE && !NETFX_CORE
            if (Header.WinzipAesEncryptionData != null)
            {
                //only read 10 less because the last ten are auth bytes
                return new WinzipAesCryptoStream(plainStream, Header.WinzipAesEncryptionData, Header.CompressedSize - 10);
            }
#endif
            return plainStream;
        }
    }
}