Esempio n. 1
0
        /// <summary>
        /// Function to returnthe files that are linked within the specified directory.
        /// </summary>
        /// <param name="directory">The directory to look up.</param>
        /// <returns>A list of files within the directory (or sub directories) that are linked to other files.</returns>
        public static IList <EditorFile> GetFileLinks(GorgonFileSystemDirectory directory)
        {
            var ownerFiles = new List <EditorFile>();

            if (directory.Directories.Count > 0)
            {
                foreach (IList <EditorFile> subFiles in
                         directory.Directories.Select(GetFileLinks).Where(subFiles => subFiles.Count > 0))
                {
                    ownerFiles.AddRange(subFiles);
                }
            }

            IEnumerable <EditorFile> editorFiles = from fileEntry in directory.Files
                                                   where Files.Contains(fileEntry.FullPath)
                                                   select Files[fileEntry.FullPath];


            foreach (IList <EditorFile> files in editorFiles.Select(GetFileLinks).Where(files => files.Count > 0))
            {
                ownerFiles.AddRange(files);
            }

            return(ownerFiles);
        }
Esempio n. 2
0
        /// <summary>
        /// Function to update the node with new directory information.
        /// </summary>
        /// <param name="newDir">New directory info.</param>
        public void UpdateNode(GorgonFileSystemDirectory newDir)
        {
            Name = newDir.FullPath;
            Text = newDir.Name;

            if ((Nodes.Count > 0) && (IsExpanded))
            {
                Collapse();
            }
        }
Esempio n. 3
0
        /// <summary>
        /// Function to add a directory to the tree.
        /// </summary>
        /// <param name="nodes">Source collection.</param>
        /// <param name="directory">Directory to add.</param>
        /// <param name="autoExpand">TRUE to expand the new node (if it has children) after it's been added, FALSE to leave collapsed.</param>
        /// <returns>The new node.</returns>
        public static TreeNodeDirectory AddDirectory(this TreeNodeCollection nodes, GorgonFileSystemDirectory directory, bool autoExpand)
        {
            if (directory == null)
            {
                throw new ArgumentNullException("directory");
            }

            // Find check to ensure the node is unique.
            TreeNodeDirectory result = (from node in nodes.Cast <TreeNode>()
                                        let dirNode = node as TreeNodeDirectory
                                                      where dirNode != null &&
                                                      string.Equals(node.Name, directory.FullPath, StringComparison.OrdinalIgnoreCase)
                                                      select dirNode).FirstOrDefault();

            if (result != null)
            {
                return(result);
            }

            result = new TreeNodeDirectory(directory)
            {
                ForeColor = Color.White,
                Text      = directory.Name
            };

            if ((directory.Directories.Count > 0) || (directory.Files.Count > 0))
            {
                // Add a dummy node to indicate that there are children.
                result.Nodes.Add("DummyNode");
            }

            nodes.Add(result);

            // Expand the parent.
            if ((result.Parent != null) &&
                (!result.Parent.IsExpanded))
            {
                TreeNode parent = result.Parent;
                parent.Expand();
                result = (TreeNodeDirectory)parent.Nodes[result.Name];
            }

            // Expand the node if necessary.
            if ((autoExpand) &&
                (result.Nodes.Count > 0))
            {
                result.Expand();
            }

            return(result);
        }
Esempio n. 4
0
        /// <summary>
        /// Function to determine if the directory or its sub-directories contain files that are linked.
        /// </summary>
        /// <param name="directory">Directory to evaluate.</param>
        /// <returns>TRUE if the directory or sub directory contains file links, FALSE if not.</returns>
        public static bool HasFileLinks(GorgonFileSystemDirectory directory)
        {
            if ((directory.Directories.Count > 0) && (directory.Directories.Any(HasFileLinks)))
            {
                return(true);
            }

            return(directory.Files.Any(item =>
            {
                EditorFile file;

                return Files.TryGetValue(item.FullPath, out file) && HasFileLinks(file);
            }));
        }
Esempio n. 5
0
        /// <summary>
        /// Function to enumerate the files and directories for a mount point.
        /// </summary>
        /// <param name="physicalMountPoint">Mount point being enumerated.</param>
        /// <param name="mountPoint">Directory to hold the sub directories and files.</param>
        /// <param name="physicalDirectories">A list of directories in the physical file system (formatted to the virtual file system).</param>
        /// <param name="physicalFiles">A list of files in the physical file system (formatted to the virtual file system).</param>
        protected override void Enumerate(string physicalMountPoint, GorgonFileSystemDirectory mountPoint,
                                          out string[] physicalDirectories, out PhysicalFileInfo[] physicalFiles)
        {
            using (var reader = new GorgonBinaryReader(File.Open(physicalMountPoint, FileMode.Open, FileAccess.Read, FileShare.Read), false))
            {
                // Skip the header.
                reader.ReadString();

                int indexLength = reader.ReadInt32();

                byte[] indexData = Decompress(reader.ReadBytes(indexLength));
                string xmlData   = Encoding.UTF8.GetString(indexData);

                ParseIndexXML(physicalMountPoint, mountPoint, XDocument.Parse(xmlData, LoadOptions.None),
                              reader.BaseStream.Position, out physicalDirectories, out physicalFiles);
            }
        }
Esempio n. 6
0
        /// <summary>
        /// Function to enumerate the files and directories for a mount point.
        /// </summary>
        /// <param name="physicalMountPoint">Path on the physical file system to enumerate.</param>
        /// <param name="mountPoint">Directory to hold the sub directories and files.</param>
        /// <param name="physicalDirectories">The directories in the physical file system.</param>
        /// <param name="physicalFiles">The files in the physical file system.</param>
        protected override void Enumerate(string physicalMountPoint, GorgonFileSystemDirectory mountPoint, out string[] physicalDirectories, out PhysicalFileInfo[] physicalFiles)
        {
            var directories = new List <string>();
            var files       = new List <PhysicalFileInfo>();

            using (var zipStream = new ZipInputStream(File.Open(physicalMountPoint, FileMode.Open, FileAccess.Read, FileShare.Read)))
            {
                ZipEntry entry;

                while ((entry = zipStream.GetNextEntry()) != null)
                {
                    if (!entry.IsDirectory)
                    {
                        string directoryName = Path.GetDirectoryName(entry.Name).FormatDirectory('/');
                        string fileName      = Path.GetFileName(entry.Name).FormatFileName();

                        directoryName = mountPoint.FullPath + directoryName;

                        if (string.IsNullOrWhiteSpace(directoryName))
                        {
                            directoryName = "/";
                        }

                        directories.Add(directoryName);

                        files.Add(new PhysicalFileInfo(physicalMountPoint + "::/" + entry.Name, fileName, entry.DateTime,
                                                       entry.Offset, entry.Size, directoryName + fileName));
                    }
                    else
                    {
                        directories.Add(mountPoint.FullPath + entry.Name);
                    }
                }
            }

            physicalDirectories = directories.ToArray();
            physicalFiles       = files.ToArray();

            directories.Clear();
            files.Clear();
        }
Esempio n. 7
0
 /// <summary>
 /// Function to create a new path node.
 /// </summary>
 /// <param name="directory">Directory to retrieve information from.</param>
 /// <returns>A new node element with the directory information.</returns>
 private static XElement CreatePathNode(GorgonFileSystemDirectory directory)
 {
     return(new XElement("Path",
                         new XAttribute("Name", (directory.Name == "/") ? @"\" : directory.Name),
                         new XAttribute("FullPath", directory.FullPath.FormatDirectory(Path.DirectorySeparatorChar))));
 }
Esempio n. 8
0
        /// <summary>
        /// Function to compress the files in a given directory.
        /// </summary>
        /// <param name="output">The output data stream.</param>
        /// <param name="directory">Directory containing the files to compress.</param>
        /// <param name="rootNode">Root node for the file allocation table.</param>
        private void CompressFiles(Stream output, GorgonFileSystemDirectory directory, XElement rootNode)
        {
            // If we have sub directories, then create those entries.
            foreach (var subDir in directory.Directories)
            {
                var dirNode = CreatePathNode(subDir);

                if (_token.IsCancellationRequested)
                {
                    return;
                }

                CompressFiles(output, subDir, dirNode);

                if (_token.IsCancellationRequested)
                {
                    return;
                }

                // Attach to the root.
                rootNode.Add(dirNode);
            }

            // Compress the files.
            foreach (var fileEntry in directory.Files)
            {
                // Load the file into a buffer for compression.
                long fileStart = output.Position;
                long fileSize;
                long compressedSize = 0;


                UpdateStatus(string.Format(Resources.GORPKW_SAVING_MSG, fileEntry.FullPath.Ellipses(45, true)), 0);

                if (_token.IsCancellationRequested)
                {
                    return;
                }

                using (var sourceData = ScratchFileSystem.OpenStream(fileEntry, false))
                {
                    // Load the data into memory.
                    using (var fileData = new GorgonDataStream((int)sourceData.Length))
                    {
                        if (_token.IsCancellationRequested)
                        {
                            return;
                        }

                        sourceData.CopyTo(fileData);

                        if (_token.IsCancellationRequested)
                        {
                            return;
                        }

                        fileSize          = fileData.Length;
                        fileData.Position = 0;

                        using (var compressedData = new MemoryStream())
                        {
                            if (_token.IsCancellationRequested)
                            {
                                return;
                            }

                            CompressData(fileData, compressedData);

                            if (_token.IsCancellationRequested)
                            {
                                return;
                            }

                            compressedData.Position = 0;
                            fileData.Position       = 0;

                            // Write the compressed data out to our blob file.
                            if (compressedData.Length < fileSize)
                            {
                                if (_token.IsCancellationRequested)
                                {
                                    return;
                                }

                                compressedData.CopyTo(output);

                                if (_token.IsCancellationRequested)
                                {
                                    return;
                                }

                                compressedSize = compressedData.Length;
                            }
                            else
                            {
                                if (_token.IsCancellationRequested)
                                {
                                    return;
                                }

                                // We didn't compress anything, so just dump the file.
                                fileData.CopyTo(output);

                                if (_token.IsCancellationRequested)
                                {
                                    return;
                                }
                            }
                        }
                    }
                }

                // Add to our directory.
                rootNode.Add(CreateFileNode(fileEntry, fileStart, fileSize, compressedSize));
            }
        }
Esempio n. 9
0
 /// <summary>
 /// Initializes a new instance of the <see cref="TreeNodeDirectory"/> class.
 /// </summary>
 /// <param name="directory">The directory to associate with this node.</param>
 public TreeNodeDirectory(GorgonFileSystemDirectory directory)
 {
     Name           = directory.FullPath;
     ExpandedImage  = APIResources.folder_open_16x16;
     CollapsedImage = APIResources.folder_16x16;
 }
Esempio n. 10
0
        /// <summary>
        /// Function to parse the XML directory index.
        /// </summary>
        /// <param name="physicalPath">Path to the packed file.</param>
        /// <param name="mountPoint">Directory to hold the sub directories and files.</param>
        /// <param name="index">Index to parse.</param>
        /// <param name="physicalOffset">Offset in the file to add to the file offsets.</param>
        /// <param name="physicalDirectories">The list of directories in the physical file system.</param>
        /// <param name="physicalFiles">The list of files in the physical file system.</param>
        private void ParseIndexXML(string physicalPath, GorgonFileSystemDirectory mountPoint, XContainer index, long physicalOffset, out string[] physicalDirectories, out PhysicalFileInfo[] physicalFiles)
        {
            var dirNodeNames = new List <string>();
            var fileNodeInfo = new List <PhysicalFileInfo>();

            var directories = index.Descendants("Path");

            _compressedFiles = new Dictionary <string, CompressedFileEntry>();

            foreach (var directoryNode in directories)
            {
                var pathAttrib = directoryNode.Attribute("FullPath");

                if ((pathAttrib == null) ||
                    (string.IsNullOrWhiteSpace(pathAttrib.Value)))
                {
                    throw new FileLoadException(Resources.GORFS_FILEINDEX_CORRUPT);
                }

                string path  = (mountPoint.FullPath + pathAttrib.Value).FormatDirectory('/');
                var    files = directoryNode.Elements("File");

                // Add the directory.
                dirNodeNames.Add(path);

                foreach (var file in files)
                {
                    var fileNameNode           = file.Element("Filename");
                    var fileExtensionNode      = file.Element("Extension");
                    var fileOffsetNode         = file.Element("Offset");
                    var fileCompressedSizeNode = file.Element("CompressedSize");
                    var fileSizeNode           = file.Element("Size");
                    var fileDateNode           = file.Element("FileDate");

                    // We need these nodes.
                    if ((fileNameNode == null) || (fileOffsetNode == null) ||
                        (fileSizeNode == null) || (fileDateNode == null) ||
                        (string.IsNullOrWhiteSpace(fileNameNode.Value)) ||
                        (string.IsNullOrWhiteSpace(fileDateNode.Value)))
                    {
                        throw new FileLoadException(Resources.GORFS_FILEINDEX_CORRUPT);
                    }

                    string   fileName = fileNameNode.Value;
                    long     fileOffset;
                    long     fileSize;
                    DateTime fileDate;

                    // If we don't have a creation date, then don't allow the file to be processed.
                    if (!DateTime.TryParse(fileDateNode.Value, CultureInfo.InvariantCulture, DateTimeStyles.None, out fileDate))
                    {
                        throw new FileLoadException(Resources.GORFS_FILEINDEX_CORRUPT);
                    }

                    if (!Int64.TryParse(fileOffsetNode.Value, out fileOffset))
                    {
                        throw new FileLoadException(Resources.GORFS_FILEINDEX_CORRUPT);
                    }

                    fileOffset += physicalOffset;

                    if (!Int64.TryParse(fileSizeNode.Value, out fileSize))
                    {
                        throw new FileLoadException(Resources.GORFS_FILEINDEX_CORRUPT);
                    }

                    if (fileExtensionNode != null)
                    {
                        string fileExtension = fileExtensionNode.Value;

                        if ((!string.IsNullOrWhiteSpace(fileExtension)) && (!string.IsNullOrWhiteSpace(fileName)))
                        {
                            fileName += fileExtension;
                        }
                    }

                    // If the file is compressed, then add it to a special list.
                    if (fileCompressedSizeNode != null)
                    {
                        long compressedSize;

                        if (!Int64.TryParse(fileCompressedSizeNode.Value, out compressedSize))
                        {
                            throw new FileLoadException(Resources.GORFS_FILEINDEX_CORRUPT);
                        }

                        if (compressedSize > 0)
                        {
                            // Add to our list of compressed files for processing later.
                            _compressedFiles.Add(path + fileName,
                                                 new CompressedFileEntry(fileSize, compressedSize));
                        }
                    }

                    fileNodeInfo.Add(new PhysicalFileInfo(physicalPath + "::/" + path + fileName, fileName, fileDate, fileOffset, fileSize, path + fileName));
                }
            }

            physicalDirectories = dirNodeNames.ToArray();
            physicalFiles       = fileNodeInfo.ToArray();

            dirNodeNames.Clear();
            fileNodeInfo.Clear();
        }
Esempio n. 11
0
        /// <summary>
        /// Function to fill the file system tree view.
        /// </summary>
        /// <param name="directory">Parent directory to fill, or NULL (Nothing in VB.Net) to fill the root directory.</param>
        private void FillTree(GorgonFileSystemDirectory directory)
        {
            TreeNodeCollection nodes;
            TreeNode           parentNode;

            if (directory == null)
            {
                directory = _fileSystem.RootDirectory;
                nodes     = treeFileSystem.Nodes;

                // Set root node.
                parentNode = new TreeNode("/")
                {
                    Name = "/"
                };
                parentNode.SelectedImageIndex = parentNode.ImageIndex = 0;
            }
            else
            {
                // Find the node with the directory.
                var searchNodes = treeFileSystem.Nodes.Find(directory.FullPath, true);

                if (searchNodes.Length > 0)
                {
                    parentNode = searchNodes[0];
                    nodes      = parentNode.Nodes;
                }
                else
                {
                    GorgonDialogs.ErrorBox(this, "Could not find the virtual directory '" + directory.FullPath + "'");
                    return;
                }
            }

            parentNode.Tag = directory;

            // Turn off the expand event.
            treeFileSystem.BeforeExpand -= treeFileSystem_BeforeExpand;

            try
            {
                // Clean up the tree node.
                treeFileSystem.BeginUpdate();
                nodes.Clear();

                // Add the root node if necessary.
                if (parentNode.Tag == _fileSystem.RootDirectory)
                {
                    nodes.Add(parentNode);
                }

                // Enumerate the data.  For the purposed of this example, we will filter out known binary files from our file system.
                var directories = directory.Directories.OrderBy(item => item.Name);
                var files       = directory.Files.OrderBy(item => item.Name).Where(item => item.Extension != ".gorSprite" && item.Extension != ".gal");

                // Get directories.
                foreach (var subDirectory in directories)
                {
                    var directoryNode = new TreeNode(subDirectory.Name)
                    {
                        Name = subDirectory.FullPath,
                        Tag  = subDirectory
                    };

                    // Put a special icon on the zip file so we have a visual representation
                    // of where it is in our VFS.
                    // The VFS does not care if the data is in a zip file or folder, and Gorgon
                    // does very little to differentiate it.  After all, the whole point of
                    // have a unified file system is to abstract away the differences.
                    if (subDirectory.Name != "ZipFile")
                    {
                        directoryNode.SelectedImageIndex = directoryNode.ImageIndex = 0;
                    }
                    else
                    {
                        directoryNode.SelectedImageIndex = directoryNode.ImageIndex = 2;
                    }

                    // Add a dummy node if there are files or sub directories.
                    if ((subDirectory.Directories.Count > 0) || (subDirectory.Files.Count(item => item.Extension != ".gorSprite" && item.Extension != ".gal") > 0))
                    {
                        directoryNode.Nodes.Add(new TreeNode("This is a dummy node."));
                    }

                    parentNode.Nodes.Add(directoryNode);
                }

                // Get files.
                foreach (var file in files)
                {
                    if (file.Extension == ".gorSprite")
                    {
                        continue;
                    }

                    var fileNode = new TreeNode(file.Name)
                    {
                        Name = file.FullPath,
                        Tag  = file
                    };
                    fileNode.SelectedImageIndex = fileNode.ImageIndex = 1;
                    parentNode.Nodes.Add(fileNode);
                }

                parentNode.Expand();
            }
            finally
            {
                treeFileSystem.EndUpdate();
                treeFileSystem.BeforeExpand += treeFileSystem_BeforeExpand;
            }
        }
Esempio n. 12
0
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        static void Main()
        {
            try
            {
                Console.WindowHeight = 28;
                Console.BufferHeight = Console.WindowHeight;

                // Create a new file system.
                _fileSystem = new GorgonFileSystem();

                Console.ForegroundColor = ConsoleColor.White;
                Console.WriteLine("This example will mount a zip file as the root of a virtual file system.  The");
                Console.WriteLine("virtual file system is capable of mounting various types of data such as a zip,");
                Console.WriteLine("a file system folder, etc... as the root or a sub directory.  You can even");
                Console.WriteLine("mount a zip file as the root, and a physical file system directory as a virtual");
                Console.WriteLine("sub directory in the same virtual file system and access them as a single");
                Console.WriteLine("unified file system.");

                // Unlike the folder file system example, we need to load
                // a provider to handle zip files before trying to mount
                // one.
                if (!LoadZipProviderPlugIn())
                {
                    return;
                }

                // Set the following zip file as root on the virtual file system.
                //
                // If we wanted to, we could mount a zip file as a sub directory of
                // the root of the virtual file system.  For example, mounting the
                // directory D:\Dir\zipFile.zip with Mount(@"D:\Dir", "/VFSDir"); would mount
                // the contents of the D:\Dir\zipFile.zip directory under /VFSDir.
                //
                // It's also important to point out that the old Gorgon "file system"
                // would load files from the system into memory when mounting a
                // directory.  While this version only loads directory and file
                // information when mounting.  This is considerably more efficient.
                var physicalPath = GetResourcePath(@"FileSystem.zip");
                _fileSystem.Mount(physicalPath);

                Console.Write("\nMounted: ");
                Console.ForegroundColor = ConsoleColor.Cyan;
                Console.Write("'{0}'", physicalPath.Ellipses(Console.WindowWidth - 20, true));
                Console.ForegroundColor = ConsoleColor.White;
                Console.Write(" as ");
                Console.ForegroundColor = ConsoleColor.Cyan;
                Console.WriteLine("'/'\n");
                Console.ForegroundColor = ConsoleColor.White;

                // Get a count of all sub directories and files under the root directory.
                var directoryList = _fileSystem.FindDirectories("*", true).ToArray();

                // Display directories.
                Console.WriteLine("Virtual file system contents:");

                for (int i = -1; i < directoryList.Length; i++)
                {
                    GorgonFileSystemDirectory directory = _fileSystem.RootDirectory;

                    // Go into the sub directories under root.
                    if (i > -1)
                    {
                        directory = directoryList[i];
                    }

                    Console.ForegroundColor = ConsoleColor.Cyan;
                    Console.WriteLine("{0}", directory.FullPath);

                    Console.ForegroundColor = ConsoleColor.Yellow;

                    foreach (var file in directory.Files)
                    {
                        Console.Write("   {0}", file.Name);
                        // Align the size to the same place.
                        Console.CursorLeft = 65;
                        Console.WriteLine("{0}", file.Size.FormatMemory());
                    }
                }

                Console.ResetColor();
                Console.WriteLine("\nPress any key to close.");
                Console.ReadKey();
            }
            catch (Exception ex)
            {
                // Catch all exceptions here.  If we had logging for the application enabled, then this
                // would record the exception in the log.
                GorgonException.Catch(ex, () =>
                {
                    Console.Clear();
                    Console.ForegroundColor = ConsoleColor.Red;
                    Console.WriteLine("Exception:\n{0}\n\nStack Trace:{1}", ex.Message, ex.StackTrace);

                    Console.ResetColor();
#if DEBUG
                    Console.ReadKey();
#endif
                });
            }
        }