diff --git a/GameRes/ArchiveFormat.cs b/GameRes/ArchiveFormat.cs new file mode 100644 index 00000000..4117d495 --- /dev/null +++ b/GameRes/ArchiveFormat.cs @@ -0,0 +1,144 @@ +//! \file ArchiveFormat.cs +//! \date Sun Dec 04 15:19:21 2016 +//! \brief Abstract base class representing archive resource. +// +// Copyright (C) 2014-2016 by morkt +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +// + +using System; +using System.Collections.Generic; +using System.IO; + +namespace GameRes +{ + /// + /// Abstract base class for archive resource implementations. + /// + public abstract class ArchiveFormat : IResource + { + public override string Type { get { return "archive"; } } + + /// + /// Whether archive file system could contain subdirectories. + /// + public abstract bool IsHierarchic { get; } + + public abstract ArcFile TryOpen (ArcView view); + + /// + /// Extract file referenced by into current directory. + /// + public void Extract (ArcFile file, Entry entry) + { + using (var input = OpenEntry (file, entry)) + using (var output = CreateFile (entry.Name)) + input.CopyTo (output); + } + + /// + /// Open file referenced by as Stream. + /// + public virtual Stream OpenEntry (ArcFile arc, Entry entry) + { + return arc.File.CreateStream (entry.Offset, entry.Size, entry.Name); + } + + /// + /// Open as image. Throws InvalidFormatException if entry is not an image. + /// + public virtual IImageDecoder OpenImage (ArcFile arc, Entry entry) + { + var input = arc.OpenBinaryEntry (entry); + return new ImageFormatDecoder (input); + } + + /// + /// Create file corresponding to in current directory and open it + /// for writing. Overwrites existing file, if any. + /// + static public Stream CreateFile (string filename) + { + filename = CreatePath (filename); + if (File.Exists (filename)) + { + // query somehow whether to overwrite existing file or not. + } + return File.Create (filename); + } + + static public string CreatePath (string filename) + { + string dir = Path.GetDirectoryName (filename); + if (!string.IsNullOrEmpty (dir)) // check for malformed filenames + { + string root = Path.GetPathRoot (dir); + if (!string.IsNullOrEmpty (root)) + { + dir = dir.Substring (root.Length); // strip root + } + string cwd = Directory.GetCurrentDirectory() + Path.DirectorySeparatorChar; + dir = Path.GetFullPath (dir); + filename = Path.GetFileName (filename); + // check whether filename would reside within current directory + if (dir.StartsWith (cwd, StringComparison.OrdinalIgnoreCase)) + { + // path looks legit, create it + Directory.CreateDirectory (dir); + filename = Path.Combine (dir, filename); + } + } + return filename; + } + + /// + /// Create resource within stream containing entries from the + /// supplied and applying necessary . + /// + public virtual void Create (Stream file, IEnumerable list, ResourceOptions options = null, + EntryCallback callback = null) + { + throw new NotImplementedException ("ArchiveFormat.Create is not implemented"); + } + + /// + /// Whether represents legit number of files in archive. + /// + public static bool IsSaneCount (int count) + { + return count > 0 && count < 0x20000; + } + } + + public enum ArchiveOperation + { + Abort, + Skip, + Continue, + } + + public delegate ArchiveOperation EntryCallback (int num, Entry entry, string description); + + public class OverwriteEventArgs : EventArgs + { + public string Filename { get; set; } + public bool Overwrite { get; set; } + } +} diff --git a/GameRes/GameRes.cs b/GameRes/GameRes.cs index 82daf2e0..33923bb2 100644 --- a/GameRes/GameRes.cs +++ b/GameRes/GameRes.cs @@ -159,107 +159,6 @@ namespace GameRes { } - public enum ArchiveOperation - { - Abort, - Skip, - Continue, - } - - public delegate ArchiveOperation EntryCallback (int num, Entry entry, string description); - - public abstract class ArchiveFormat : IResource - { - public override string Type { get { return "archive"; } } - - /// - /// Whether archive file system could contain subdirectories. - /// - public abstract bool IsHierarchic { get; } - - public abstract ArcFile TryOpen (ArcView view); - - /// - /// Extract file referenced by into current directory. - /// - public void Extract (ArcFile file, Entry entry) - { - using (var input = OpenEntry (file, entry)) - using (var output = CreateFile (entry.Name)) - input.CopyTo (output); - } - - /// - /// Open file referenced by as Stream. - /// - public virtual Stream OpenEntry (ArcFile arc, Entry entry) - { - return arc.File.CreateStream (entry.Offset, entry.Size, entry.Name); - } - - /// - /// Open as image. Throws InvalidFormatException if entry is not an image. - /// - public virtual IImageDecoder OpenImage (ArcFile arc, Entry entry) - { - var input = arc.OpenBinaryEntry (entry); - return new ImageFormatDecoder (input); - } - - /// - /// Create file corresponding to in current directory and open it - /// for writing. Overwrites existing file, if any. - /// - static public Stream CreateFile (string filename) - { - filename = CreatePath (filename); - if (File.Exists (filename)) - { - // query somehow whether to overwrite existing file or not. - } - return File.Create (filename); - } - - static public string CreatePath (string filename) - { - string dir = Path.GetDirectoryName (filename); - if (!string.IsNullOrEmpty (dir)) // check for malformed filenames - { - string root = Path.GetPathRoot (dir); - if (!string.IsNullOrEmpty (root)) - { - dir = dir.Substring (root.Length); // strip root - } - string cwd = Directory.GetCurrentDirectory() + Path.DirectorySeparatorChar; - dir = Path.GetFullPath (dir); - filename = Path.GetFileName (filename); - // check whether filename would reside within current directory - if (dir.StartsWith (cwd, StringComparison.OrdinalIgnoreCase)) - { - // path looks legit, create it - Directory.CreateDirectory (dir); - filename = Path.Combine (dir, filename); - } - } - return filename; - } - - /// - /// Create resource within stream containing entries from the - /// supplied and applying necessary . - /// - public virtual void Create (Stream file, IEnumerable list, ResourceOptions options = null, - EntryCallback callback = null) - { - throw new NotImplementedException ("ArchiveFormat.Create is not implemented"); - } - - public static bool IsSaneCount (int count) - { - return count > 0 && count < 0x20000; - } - } - public delegate void ParametersRequestEventHandler (object sender, ParametersRequestEventArgs e); public class ParametersRequestEventArgs : EventArgs @@ -280,12 +179,6 @@ namespace GameRes public ResourceOptions Options { get; set; } } - public class OverwriteEventArgs : EventArgs - { - public string Filename { get; set; } - public bool Overwrite { get; set; } - } - public class InvalidFormatException : FileFormatException { public InvalidFormatException() : base(garStrings.MsgInvalidFormat) { } diff --git a/GameRes/GameRes.csproj b/GameRes/GameRes.csproj index 12640e57..20835433 100644 --- a/GameRes/GameRes.csproj +++ b/GameRes/GameRes.csproj @@ -63,6 +63,7 @@ +