private bool FollowPath(string path, out ZipFileFolder folder, out string name)
            {
                string[] parts = path.ToLowerInvariant().Split(sSlashes);
                if (parts.Length < 1)
                {
                    throw new FileNotFoundException("Empty path: " + path);
                }
                if (parts[0].Length == 0)
                {
                    throw new FileNotFoundException("Absolute paths not supported: " + path);
                }

                ZipFileFolder f = this;

                for (int i = 0; i < parts.Length - 1; ++i)
                {
                    FileFolder next;
                    if (!f.mFolders.TryGetValue(parts[i], out next))
                    {
                        folder = null;
                        name   = null;
                        return(false);
                    }
                    f = (ZipFileFolder)next;
                }

                folder = f;
                name   = parts[parts.Length - 1];
                return(true);
            }
        public ZipFileTree(string zipFileName)
            : base("/", string.Empty)
        {
            mRoot = new ZipFileFolder(this, "/", string.Empty);

            try
            {
                mZip = ZipFile.OpenRead(zipFileName);

                // Enumerate all entries in the archive and fill in the tree
                foreach (ZipArchiveEntry entry in mZip.Entries)
                {
                    string[] parts = entry.FullName.Split(sSlashes);
                    if (parts[parts.Length - 1].Length == 0)
                    {
                        continue;                                      // Some archives contain folder names which have trailing slashes
                    }
                    ZipFileFolder folder = mRoot;
                    for (int i = 0; i < parts.Length - 1; ++i)
                    {
                        folder = folder.GetOrCreateSubFolder(parts[i]);
                    }
                    folder.AddFile(parts[parts.Length - 1], entry);
                }
            }
            catch (Exception err)
            {
                Dispose(true);
                throw new InvalidDataException($"Corrupted zip file '{zipFileName}': {err.Message}", err);
            }
        }
            public ZipFileFolder GetOrCreateSubFolder(string name)
            {
                string     lcName = name.ToLowerInvariant();
                FileFolder folder;

                if (!mFolders.TryGetValue(lcName, out folder))
                {
                    string subRootedName = (RootedName.Length <= 1) ? string.Concat("/", name) : string.Concat(RootedName, "/", name);
                    folder           = new ZipFileFolder(mTree, subRootedName, name);
                    mFolders[lcName] = folder;
                }
                return((ZipFileFolder)folder);
            }