示例#1
0
        /// <summary>
        /// Create file provider that re-opens archive.
        /// </summary>
        /// <param name="archiveOpener"></param>
        /// <param name="entryName">Entry name of the whole package</param>
        /// <param name="hintPath">(optional) archive name "folder/document.txt.gz", entry name is extracted by removing the folder (separator '/') and last extension.</param>
        /// <param name="dateTime">Date time for folder entries</param>
        /// <exception cref="IOException">On I/O error</exception>
        /// <exception cref="PackageException.LoadError">on file format error</exception>
        public GZipFileProvider(Func <GZipArchive> archiveOpener, string entryName, string hintPath = null, DateTimeOffset?dateTime = default) : base(hintPath, dateTime)
        {
            if (archiveOpener == null)
            {
                throw new ArgumentNullException(nameof(archiveOpener));
            }

            // Place holder for the uncompressed length value
            long[] length = new long[1];
            // Convert archiveOpener to streamOpener
            Stream streamOpener()
            {
                IArchive archive = archiveOpener();

                try
                {
                    // Search entry
                    IArchiveEntry entry = archive.Entries.First();
                    // Not found
                    if (entry == null)
                    {
                        archive.Dispose(); return(null);
                    }
                    // Open stream
                    Stream s = entry.OpenEntryStream();
                    // Attach the disposing of the archive to the stream.
                    return(new GZipStreamFix(s, archive, null, length[0]));
                }
                catch (Exception) when(CloseDisposable(archive))
                {
                    // Never goes here
                    return(null);
                }
            }

            // Create stream provider
            this.streamProvider = new StreamOpener(streamOpener, entryName, belatedDisposeList);
            // Open once to read entries.
            using (var archive = archiveOpener())
            {
                // Read first entry
                IArchiveEntry entry = archive.Entries.First();
                // Get length
                using (var s = entry.OpenEntryStream())
                    length[0] = CalculateLength(s);
                // File entry
                var fileEntry = new Lexical.FileProvider.Common.ArchiveFileEntry(streamProvider, entryName, entryName, length[0], dateTime ?? entry.LastModifiedTime ?? DateTime.MinValue);
                // Put it in directory
                this.root.files[entryName] = fileEntry;
            }
        }
示例#2
0
        /// <summary>
        /// Create file provider that reads one entry from <paramref name="archive"/>.
        /// </summary>
        /// <param name="archive"></param>
        /// <param name="entryName">Entry name of the whole package</param>
        /// <param name="hintPath">(optional) archive name "folder/document.txt.gz", entry name is extracted by removing the folder (separator '/') and last extension.</param>
        /// <param name="dateTime">(optional) Date time for folder entries</param>
        public GZipFileProvider(GZipArchive archive, string entryName, string hintPath = null, DateTimeOffset?dateTime = null) : base(hintPath, dateTime)
        {
            this.streamProvider = new Lexical.FileProvider.SharpCompress.Internal.ArchiveStreamProvider(archive ?? throw new ArgumentNullException(nameof(archive)), belatedDisposeList);
            IArchiveEntry entry = archive.Entries.First();

            long length;

            using (Stream s = entry.OpenEntryStream())
                length = CalculateLength(s);

            var fileEntry = new Lexical.FileProvider.Common.ArchiveFileEntry(streamProvider, entry.Key, entryName, length, dateTime ?? entry.LastModifiedTime ?? DateTime.MinValue);

            this.root.files[entryName] = fileEntry;
        }
示例#3
0
        /// <summary>
        /// Search file from the read-only archive index.
        /// </summary>
        /// <param name="path"></param>
        /// <returns></returns>
        public virtual IFileInfo GetFileInfo(string path)
        {
            if (IsDisposing)
            {
                throw new ObjectDisposedException(GetType().FullName);
            }
            if (path == null)
            {
                path = "";
            }
            string           canonizedPath = CanonizePath(path);
            ArchiveFileEntry zipFile       = root.GetFile(canonizedPath);

            return((IFileInfo)zipFile ?? new NotFoundFileInfo(path));
        }
        /// <summary>
        /// Add <paramref name="archiveEntries"/> into tree structure.
        /// </summary>
        /// <param name="root"></param>
        /// <param name="archiveEntries"></param>
        /// <param name="streamProvider">stream provider for files</param>
        /// <param name="convertBackslashesToSlashes">if true converts '\' to '/'</param>
        /// <returns>this</returns>
        protected virtual Lexical.FileProvider.Common.ArchiveDirectoryEntry AddArchiveEntries(Lexical.FileProvider.Common.ArchiveDirectoryEntry root, IEnumerable <IArchiveEntry> archiveEntries, Lexical.FileProvider.Common.IStreamProvider streamProvider, bool convertBackslashesToSlashes)
        {
            foreach (IArchiveEntry entry in archiveEntries)
            {
                string path = convertBackslashesToSlashes ? entry.Key.Replace('\\', '/') : entry.Key;

                // Is entry a file
                if (!entry.IsDirectory)
                {
                    // Split to filename and path
                    int    slashIx  = path.LastIndexOf('/');
                    string filename = path.Substring(slashIx + 1);
                    string dirPath  = slashIx < 0 ? "" : path.Substring(0, slashIx);

                    // Create file entry
                    Lexical.FileProvider.Common.ArchiveFileEntry fileEntry = new Lexical.FileProvider.Common.ArchiveFileEntry(streamProvider, entry.Key, filename, entry.Size, entry.LastModifiedTime ?? DateTime.MinValue);

                    // Create dir
                    Lexical.FileProvider.Common.ArchiveDirectoryEntry dir = root.GetOrCreateDirectory(dirPath);

                    // Add to dir
                    dir.files[filename] = fileEntry;
                }
                else
                {
                    // Create dir
                    var dir = root.GetOrCreateDirectory(path);
                    if (entry.LastModifiedTime != null)
                    {
                        dir.LastModified = (DateTime)entry.LastModifiedTime;
                    }
                }
            }

            // Return the whole tree
            return(root);
        }
示例#5
0
        /// <summary>
        /// Find file
        /// </summary>
        /// <param name="canonizedPath">file path</param>
        /// <returns>file or null</returns>
        public ArchiveFileEntry GetFile(string canonizedPath)
        {
            if (canonizedPath == null)
            {
                throw new ArgumentNullException(nameof(canonizedPath));
            }
            if (canonizedPath == "")
            {
                return(null);
            }

            // Find slash
            int slashIX = canonizedPath.IndexOf('/');

            // No slash, return direct file
            if (slashIX < 0)
            {
                ArchiveFileEntry result = null;
                files.TryGetValue(canonizedPath, out result);
                return(result);
            }

            // Got slash, find local dir
            string localDirectoryName            = canonizedPath.Substring(0, slashIX);
            ArchiveDirectoryEntry localDirectory = null;

            if (!directories.TryGetValue(localDirectoryName, out localDirectory))
            {
                return(null);
            }

            // Use recursion for the rest the path
            string restOfThePath = canonizedPath.Substring(slashIX + 1);

            return(localDirectory.GetFile(restOfThePath));
        }