Exemplo n.º 1
0
            /// <summary>
            /// Creates an instance of <see cref="ICompressedArchiveAccess"/> that can be used to access a nested archive.
            /// </summary>
            /// <param name="parentArchiveAccess">The parent archive, which contains the nested archive indicated by <paramref name="entry"/>.</param>
            /// <param name="entry">The entry within <paramref name="parentArchiveAccess"/> that indicates a nested archive.</param>
            /// <returns>An instance of <see cref="NestedCompressedArchiveAccess"/>, which provides access to the nested archive.</returns>
            /// <remarks>This wrapper type takes care of cleaning up any temporary files that may be required to access the nested archive.
            /// For example, some data streams used to access an archive are not navigable from the parent stream (GZIP).</remarks>
            public static NestedCompressedArchiveAccess Create(ICompressedArchiveAccess parentArchiveAccess, ICompressedArchiveEntry entry)
            {
                NestedCompressedArchiveAccess nestedCompressedArchive = null;
                var entryName            = entry.Name;
                var nestedArchiveFormats = Path.GetExtension(entryName).GetCompressedArchiveFormatsFromFileExtension();
                var nestedArchiveFormat  = nestedArchiveFormats.FirstOrDefault();

                if (nestedArchiveFormat.IsCompressedArchiveFormatSupported())
                {
                    TemporaryDirectory temporaryLocation = null;
                    var entryData = parentArchiveAccess.OpenEntry(entry);
                    if (FormatMustBeExtracted(parentArchiveAccess.Format) || FormatMustBeExtracted(nestedArchiveFormat))
                    {
                        // We can't fully navigate the nested stream, so extract to disk, then proceed.
                        temporaryLocation = new TemporaryDirectory();
                        var temporaryEntryFilePath = Path.Combine(temporaryLocation.Path, entryName);
                        if (Directory.CreateDirectory(Path.GetDirectoryName(temporaryEntryFilePath)).Exists)
                        {
                            System.Diagnostics.Debug.WriteLine("Extracted entry " + entryName + " to " + temporaryLocation.Path);
                            var fileStream = new FileStream(temporaryEntryFilePath, FileMode.Create, FileAccess.ReadWrite);
                            entryData.CopyTo(fileStream);
                            fileStream.Seek(0, SeekOrigin.Begin);
                            entryData.Dispose();
                            entryData = fileStream;
                        }
                    }

                    var compressedArchive = CompressedArchiveAccess.Open(entryData, nestedArchiveFormat, CompressedArchiveAccessMode.Read);
                    nestedCompressedArchive = new NestedCompressedArchiveAccess(parentArchiveAccess, compressedArchive, temporaryLocation);
                    nestedCompressedArchive.NestedArchiveFormats = nestedArchiveFormats;
                }

                return(nestedCompressedArchive);
            }
Exemplo n.º 2
0
            /// <summary>
            /// Creates an instance of <see cref="CompressedArchiveFileAccess"/>, depending on <paramref name="mode"/>.
            /// </summary>
            /// <param name="filePath">The absolute path for the compressed archive.</param>
            /// <param name="mode">The access mode to use for operations on the compressed archive.</param>
            /// <param name="implementation">If not <c>null</c>, use a specific implementation if possible. Otherwise, use default, or any.</param>
            /// <returns>An instance of <see cref="CompressedArchiveFileAccess"/> that provides access to the compressed archive located at <paramref name="filePath"/>.</returns>
            /// <exception cref="System.ArgumentNullException">Thrown if <paramref name="filePath"/> is <c>null</c>.</exception>
            /// <exception cref="System.ArgumentOutOfRangeException">Thrown if the file is accessed incorrectly for the given <paramref name="mode"/>.</exception>
            /// <exception cref="System.ArgumentException">Thrown if <paramref name="filePath"/> is empty or white space, contains invalid characters, or is otherwise invalid</exception>
            /// <exception cref="System.NotSupportedException">Thrown if <paramref name="filePath"/> refers to a non-file device, e.g. a COM port, et. al.</exception>
            /// <exception cref="System.IO.FileNotFoundException">Thrown if <paramref name="filePath"/> cannot be found.</exception>
            /// <exception cref="System.IO.IOException">Thrown if an I/O error occurs.</exception>
            /// <exception cref="System.Security.SecurityException">Thrown if the requested action on <paramref name="filePath"/> cannot be performed, e.g. no read / create access is granted, et. al.</exception>
            /// <exception cref="System.IO.DirectoryNotFoundException">Thrown if the directory cannot be found, e.g. an unavailable network drive forms part of the file path.</exception>
            /// <exception cref="System.UnauthorizedAccessException">Thrown if access is denied, e.g. read/write access requested for a read-only file or directory.</exception>
            /// <exception cref="System.IO.PathTooLongException">Thrown if <paramref name="filePath"/> is too long.</exception>
            /// <exception cref="System.InvalidOperationException">Thrown if it is not possible to create an instance of <see cref="CompressedArchiveFileAccess"/> from the file at <paramref name="filePath"/>,
            /// despite the file appearing to be valid.</exception>
            public static CompressedArchiveFileAccess Create(string filePath, CompressedArchiveAccessMode mode, CompressedArchiveAccessImplementation?implementation)
            {
                var fileMode   = CompressedArchiveAccessModeToFileMode(mode);
                var fileAccess = CompressedArchiveAccessModeToFileAccess(mode);
                var fileName   = Path.GetFileName(filePath);

                var successfullyAccessedFormats = new List <CompressedArchiveFormat>();
                var fileStream = new FileStream(filePath, fileMode, fileAccess);
                var formats    = filePath.GetCompressedArchiveFormatsFromFileName();
                ICompressedArchiveAccess compressedArchiveAccess = null;

#if OPEN_NESTED_FORMAT_IMMEDIATELY
                Stream stream = fileStream;
                foreach (var format in formats)
                {
                    compressedArchiveAccess = Utility.CompressedArchiveAccess.Open(stream, format, mode);
                    if (compressedArchiveAccess != null)
                    {
                        successfullyAccessedFormats.Add(format);
                        if (!compressedArchiveAccess.IsArchive)
                        {
                            fileName = Path.GetFileNameWithoutExtension(fileName);
                            var entry = compressedArchiveAccess.FindEntry(fileName);
                            stream = entry == null ? null : compressedArchiveAccess.OpenEntry(entry);
                            if (stream == null)
                            {
                                compressedArchiveAccess = null;
                                break;
                            }
                        }
                    }
                    else
                    {
                        break;
                    }
                }
#else
                var format = formats.FirstOrDefault();
                if (format != CompressedArchiveFormat.None)
                {
                    compressedArchiveAccess = Utility.CompressedArchiveAccess.Open(fileStream, format, mode, implementation);
                }
#endif

                if (compressedArchiveAccess == null)
                {
                    var identifiedFormats          = string.Join(CultureInfo.CurrentCulture.TextInfo.ListSeparator, formats);
                    var successfullyCreatedFormats = string.Join(CultureInfo.CurrentCulture.TextInfo.ListSeparator, successfullyAccessedFormats);
                    var failedFormats = string.Join(CultureInfo.CurrentCulture.TextInfo.ListSeparator, formats.Except(successfullyAccessedFormats));
                    var errorMessage  = string.Format(CultureInfo.CurrentCulture, Resources.Strings.CompressedArchiveAccess_UnableToProcessError_Format, filePath, identifiedFormats, successfullyCreatedFormats, failedFormats);
                    throw new InvalidOperationException(errorMessage);
                }

                var compressedArchiveFileAccess = new CompressedArchiveFileAccess(filePath, compressedArchiveAccess)
                {
                    Stream = fileStream
                };
                return(compressedArchiveFileAccess);
            }