aboutsummaryrefslogtreecommitdiff
path: root/src/dtf/WixToolset.Dtf.Compression.Cab/CabEngine.cs
blob: ab135fd8ffdb4545a0d65b47f6a82c46c2af7b19 (plain)
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
// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.

namespace WixToolset.Dtf.Compression.Cab
{
    using System;
    using System.IO;
    using System.Collections.Generic;

    /// <summary>
    /// Engine capable of packing and unpacking archives in the cabinet format.
    /// </summary>
    public class CabEngine : CompressionEngine
    {
        private CabPacker packer;
        private CabUnpacker unpacker;

        /// <summary>
        /// Creates a new instance of the cabinet engine.
        /// </summary>
        public CabEngine()
            : base()
        {
        }

        /// <summary>
        /// Disposes of resources allocated by the cabinet engine.
        /// </summary>
        /// <param name="disposing">If true, the method has been called directly
        /// or indirectly by a user's code, so managed and unmanaged resources
        /// will be disposed. If false, the method has been called by the runtime
        /// from inside the finalizer, and only unmanaged resources will be
        /// disposed.</param>
        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                if (packer != null)
                {
                    packer.Dispose();
                    packer = null;
                }
                if (unpacker != null)
                {
                    unpacker.Dispose();
                    unpacker = null;
                }
            }

            base.Dispose(disposing);
        }

        private CabPacker Packer
        {
            get
            {
                if (this.packer == null)
                {
                    this.packer = new CabPacker(this);
                }

                return this.packer;
            }
        }

        private CabUnpacker Unpacker
        {
            get
            {
                if (this.unpacker == null)
                {
                    this.unpacker = new CabUnpacker(this);
                }

                return this.unpacker;
            }
        }

        /// <summary>
        /// Creates a cabinet or chain of cabinets.
        /// </summary>
        /// <param name="streamContext">A context interface to handle opening
        /// and closing of cabinet and file streams.</param>
        /// <param name="files">The paths of the files in the archive (not
        /// external file paths).</param>
        /// <param name="maxArchiveSize">The maximum number of bytes for one
        /// cabinet before the contents are chained to the next cabinet, or zero
        /// for unlimited cabinet size.</param>
        /// <exception cref="ArchiveException">The cabinet could not be
        /// created.</exception>
        /// <remarks>
        /// The stream context implementation may provide a mapping from the
        /// file paths within the cabinet to the external file paths.
        /// <para>Smaller folder sizes can make it more efficient to extract
        /// individual files out of large cabinet packages.</para>
        /// </remarks>
        public override void Pack(
            IPackStreamContext streamContext,
            IEnumerable<string> files,
            long maxArchiveSize)
        {
            this.Packer.CompressionLevel = this.CompressionLevel;
            this.Packer.UseTempFiles = this.UseTempFiles;
            this.Packer.Pack(streamContext, files, maxArchiveSize);
        }

        /// <summary>
        /// Checks whether a Stream begins with a header that indicates
        /// it is a valid cabinet file.
        /// </summary>
        /// <param name="stream">Stream for reading the cabinet file.</param>
        /// <returns>True if the stream is a valid cabinet file
        /// (with no offset); false otherwise.</returns>
        public override bool IsArchive(Stream stream)
        {
            return this.Unpacker.IsArchive(stream);
        }

        /// <summary>
        /// Gets information about files in a cabinet or cabinet chain.
        /// </summary>
        /// <param name="streamContext">A context interface to handle opening
        /// and closing of cabinet and file streams.</param>
        /// <param name="fileFilter">A predicate that can determine
        /// which files to process, optional.</param>
        /// <returns>Information about files in the cabinet stream.</returns>
        /// <exception cref="ArchiveException">The cabinet provided
        /// by the stream context is not valid.</exception>
        /// <remarks>
        /// The <paramref name="fileFilter"/> predicate takes an internal file
        /// path and returns true to include the file or false to exclude it.
        /// </remarks>
        public override IList<ArchiveFileInfo> GetFileInfo(
            IUnpackStreamContext streamContext,
            Predicate<string> fileFilter)
        {
            return this.Unpacker.GetFileInfo(streamContext, fileFilter);
        }

        /// <summary>
        /// Extracts files from a cabinet or cabinet chain.
        /// </summary>
        /// <param name="streamContext">A context interface to handle opening
        /// and closing of cabinet and file streams.</param>
        /// <param name="fileFilter">An optional predicate that can determine
        /// which files to process.</param>
        /// <exception cref="ArchiveException">The cabinet provided
        /// by the stream context is not valid.</exception>
        /// <remarks>
        /// The <paramref name="fileFilter"/> predicate takes an internal file
        /// path and returns true to include the file or false to exclude it.
        /// </remarks>
        public override void Unpack(
            IUnpackStreamContext streamContext,
            Predicate<string> fileFilter)
        {
            this.Unpacker.Unpack(streamContext, fileFilter);
        }

        internal void ReportProgress(ArchiveProgressEventArgs e)
        {
            base.OnProgress(e);
        }
    }
}