From 566508ff2cee0f0010015a38af85d8a6a201050a Mon Sep 17 00:00:00 2001
From: Michael Graf <mgraf@igros.de>
Date: Sun, 23 Oct 2011 13:56:05 +0200
Subject: [PATCH] ISOResourceProvider now uses DiscUtils instead of ISOReader

---
 .../IsoResourceProvider/IsoResourceAccessor.cs     |  104 ++++++++++++++++----
 .../IsoResourceProvider/IsoResourceProvider.cs     |   33 +++++--
 .../IsoResourceProvider/IsoResourceProvider.csproj |   18 +---
 .../IsoResourceProvider/IsoResourceProxy.cs        |   55 ++++++----
 .../References/DiscUtils License.txt               |   20 ++++
 .../IsoResourceProvider/References/DiscUtils.dll   |  Bin 0 -> 812032 bytes
 6 files changed, 166 insertions(+), 64 deletions(-)
 create mode 100644 MediaPortal/Source/Extensions/ResourceProviders/IsoResourceProvider/References/DiscUtils License.txt
 create mode 100644 MediaPortal/Source/Extensions/ResourceProviders/IsoResourceProvider/References/DiscUtils.dll

diff --git a/MediaPortal/Source/Extensions/ResourceProviders/IsoResourceProvider/IsoResourceAccessor.cs b/MediaPortal/Source/Extensions/ResourceProviders/IsoResourceProvider/IsoResourceAccessor.cs
index 3c8dae6..b4ff76f 100644
--- a/MediaPortal/Source/Extensions/ResourceProviders/IsoResourceProvider/IsoResourceAccessor.cs
+++ b/MediaPortal/Source/Extensions/ResourceProviders/IsoResourceProvider/IsoResourceAccessor.cs
@@ -29,9 +29,11 @@ using System.Linq;
 using MediaPortal.Common;
 using MediaPortal.Common.Logging;
 using MediaPortal.Common.ResourceAccess;
-using ISOReader;
+using DiscUtils.Iso9660;
+using DiscUtils.Udf;
 using MediaPortal.Utilities;
 using MediaPortal.Utilities.FileSystem;
+using MediaPortal.Utilities.Exceptions;
 
 namespace MediaPortal.Extensions.ResourceProviders.IsoResourceProvider
 {
@@ -69,19 +71,41 @@ namespace MediaPortal.Extensions.ResourceProviders.IsoResourceProvider
       lock (_isoProxy.SyncObj)
       {
         string dosPath = ToDosPath(pathToDirOrFile);
-        RecordEntryInfo entry;
-        try
+        if (_isoProxy.IsoUdfReader != null)
         {
-          entry = _isoProxy.IsoReader.GetRecordEntryInfo(dosPath); // Path must start with /
+          if (_isoProxy.IsoUdfReader.FileExists(dosPath))
+          {
+            _isDirectory = false;
+            _size = _isoProxy.IsoUdfReader.GetFileLength(dosPath);
+            _lastChanged = _isoProxy.IsoUdfReader.GetLastWriteTime(dosPath);
+            return;
+          }
+          if (_isoProxy.IsoUdfReader.DirectoryExists(dosPath))
+          {
+            _isDirectory = true;
+            _size = (long) -1;
+            _lastChanged = _isoProxy.IsoUdfReader.GetLastWriteTime(dosPath);
+            return;
+          }
         }
-        catch
+        if (_isoProxy.Iso9660Reader != null)
         {
-          _isoProxy.DecUsage();
-          throw;
+          if (_isoProxy.Iso9660Reader.FileExists(dosPath))
+          {
+            _isDirectory = false;
+            _size = _isoProxy.Iso9660Reader.GetFileLength(dosPath);
+            _lastChanged = _isoProxy.Iso9660Reader.GetLastWriteTime(dosPath);
+            return;
+          }
+          if (_isoProxy.Iso9660Reader.DirectoryExists(dosPath))
+          {
+            _isDirectory = true;
+            _size = (long)-1;
+            _lastChanged = _isoProxy.Iso9660Reader.GetLastWriteTime(dosPath);
+            return;
+          }
         }
-        _isDirectory = entry.Directory;
-        _lastChanged = entry.Date;
-        _size = _isDirectory ? (long) (-1) : entry.Size;
+        throw new ArgumentException("IsoResourceAccessor cannot access path or file '{0}' in iso-file", dosPath);
       }
     }
 
@@ -118,16 +142,21 @@ namespace MediaPortal.Extensions.ResourceProviders.IsoResourceProvider
       return StringUtils.CheckPrefix(path, "/");
     }
 
-    protected internal static bool IsResource(IsoReader isoReader, string providerPath)
+    protected internal static bool IsResource(UdfReader udfReader, CDReader iso9660Reader, string providerPath)
     {
       if (providerPath == "/")
         return true;
-      string isoPath = ToDosPath(providerPath);
-      string dirPath = "\\" + Path.GetDirectoryName(isoPath);
-      string isoResource = "\\" + isoPath;
+      string isoResource = "\\" + ToDosPath(providerPath);
 
-      string[] dirList = isoReader.GetFileSystemEntries(dirPath, SearchOption.TopDirectoryOnly);
-      return dirList.Any(entry => entry.Equals(isoResource, StringComparison.OrdinalIgnoreCase));
+      if (udfReader != null)
+        if(udfReader.Exists(isoResource))
+          return true;
+
+      if (iso9660Reader != null)
+        if (iso9660Reader.Exists(isoResource))
+          return true;
+
+      return false;
     }
 
     protected string ExpandPath(string relativeOrAbsoluteProviderPath)
@@ -198,7 +227,24 @@ namespace MediaPortal.Extensions.ResourceProviders.IsoResourceProvider
     public Stream OpenRead()
     {
       string dosPath = ToDosPath(_pathToDirOrFile);
-      return _isoProxy.IsoReader.GetFileStream(dosPath.StartsWith("\\") ? dosPath : "\\" + dosPath);
+      if (!dosPath.StartsWith("\\"))
+        dosPath = "\\" + dosPath;
+      if (_isoProxy.IsoUdfReader != null)
+      {
+        if (_isoProxy.IsoUdfReader.FileExists(dosPath))
+          return _isoProxy.IsoUdfReader.OpenFile(dosPath, FileMode.Open, FileAccess.Read);
+        if (_isoProxy.IsoUdfReader.DirectoryExists(dosPath))
+          throw new IllegalCallException ("IsoResourceAccessor.OpenRead() was called for directory '{0}'", dosPath);
+      }
+
+      if (_isoProxy.Iso9660Reader != null)
+      {
+        if (_isoProxy.Iso9660Reader.FileExists(dosPath))
+          return _isoProxy.Iso9660Reader.OpenFile(dosPath, FileMode.Open, FileAccess.Read);
+        if (_isoProxy.Iso9660Reader.DirectoryExists(dosPath))
+          throw new IllegalCallException ("IsoResourceAccessor.OpenRead() was called for directory '{0}'", dosPath);
+      }
+      return null;
     }
 
     public Stream OpenWrite()
@@ -222,7 +268,7 @@ namespace MediaPortal.Extensions.ResourceProviders.IsoResourceProvider
 
     public bool ResourceExists(string path)
     {
-      return path.Equals(_pathToDirOrFile, StringComparison.OrdinalIgnoreCase) || IsResource(_isoProxy.IsoReader, ExpandPath(path));
+      return path.Equals(_pathToDirOrFile, StringComparison.OrdinalIgnoreCase) || IsResource(_isoProxy.IsoUdfReader, _isoProxy.Iso9660Reader, ExpandPath(path));
     }
 
     public IFileSystemResourceAccessor GetResource(string path)
@@ -236,7 +282,15 @@ namespace MediaPortal.Extensions.ResourceProviders.IsoResourceProvider
       string dosPath = ToDosPath(_pathToDirOrFile);
       try
       {
-        string[] files = _isoProxy.IsoReader.GetFiles(dosPath.StartsWith("\\") ? dosPath : "\\" + dosPath, SearchOption.TopDirectoryOnly);
+        string[] udfFiles = { };
+        string[] iso9660Files = { };
+        string[] files = { };
+        if (_isoProxy.IsoUdfReader != null)
+          udfFiles = _isoProxy.IsoUdfReader.GetFiles(dosPath.StartsWith("\\") ? dosPath : "\\" + dosPath);
+        if (_isoProxy.Iso9660Reader != null)
+          iso9660Files = _isoProxy.Iso9660Reader.GetFiles(dosPath.StartsWith("\\") ? dosPath : "\\" + dosPath);
+        files = udfFiles.Union(iso9660Files).ToArray();
+
         return files.Select(path => new IsoResourceAccessor(_isoProvider, _isoProxy,
             ToProviderPath(path))).Cast<IFileSystemResourceAccessor>().ToList();
       }
@@ -252,8 +306,16 @@ namespace MediaPortal.Extensions.ResourceProviders.IsoResourceProvider
       string dosPath = ToDosPath(_pathToDirOrFile);
       try
       {
-        string[] files = _isoProxy.IsoReader.GetDirectories(dosPath.StartsWith("\\") ? dosPath : "\\" + dosPath, SearchOption.TopDirectoryOnly);
-        return files.Select(path => new IsoResourceAccessor(_isoProvider, _isoProxy,
+        string[] udfDirectories = { };
+        string[] iso9660Directories = { };
+        string[] directories = { };
+        if (_isoProxy.IsoUdfReader != null)
+          udfDirectories = _isoProxy.IsoUdfReader.GetDirectories(dosPath.StartsWith("\\") ? dosPath : "\\" + dosPath);
+        if (_isoProxy.Iso9660Reader != null)
+          iso9660Directories = _isoProxy.Iso9660Reader.GetDirectories(dosPath.StartsWith("\\") ? dosPath : "\\" + dosPath);
+        directories = udfDirectories.Union(iso9660Directories).ToArray();
+
+        return directories.Select(path => new IsoResourceAccessor(_isoProvider, _isoProxy,
             ToProviderPath(path))).Cast<IFileSystemResourceAccessor>().ToList();
       }
       catch (Exception e)
diff --git a/MediaPortal/Source/Extensions/ResourceProviders/IsoResourceProvider/IsoResourceProvider.cs b/MediaPortal/Source/Extensions/ResourceProviders/IsoResourceProvider/IsoResourceProvider.cs
index f3b2bd7..c4a155f 100644
--- a/MediaPortal/Source/Extensions/ResourceProviders/IsoResourceProvider/IsoResourceProvider.cs
+++ b/MediaPortal/Source/Extensions/ResourceProviders/IsoResourceProvider/IsoResourceProvider.cs
@@ -28,7 +28,8 @@ using MediaPortal.Common;
 using MediaPortal.Common.Logging;
 using MediaPortal.Common.MediaManagement;
 using MediaPortal.Common.ResourceAccess;
-using ISOReader;
+using DiscUtils.Iso9660;
+using DiscUtils.Udf;
 using MediaPortal.Common.Services.ResourceAccess.StreamedResourceToLocalFsAccessBridge;
 
 namespace MediaPortal.Extensions.ResourceProviders.IsoResourceProvider
@@ -138,7 +139,7 @@ namespace MediaPortal.Extensions.ResourceProviders.IsoResourceProvider
         {
           IsoResourceProxy proxy;
           if (_isoUsages.TryGetValue(key, out proxy))
-            return IsoResourceAccessor.IsResource(proxy.IsoReader, path);
+            return IsoResourceAccessor.IsResource(proxy.IsoUdfReader, proxy.Iso9660Reader, path);
         }
         catch (Exception)
         {
@@ -147,21 +148,35 @@ namespace MediaPortal.Extensions.ResourceProviders.IsoResourceProvider
       }
 
       IResourceAccessor ra = baseResourceAccessor.Clone();
+      UdfReader udfReader;
+      CDReader iso9660Reader;
+
+      // Try udf-access first; if that doesn't work, try iso9660
       try
       {
-        using (ILocalFsResourceAccessor localFsResourceAccessor = StreamedResourceToLocalFsAccessBridge.GetLocalFsResourceAccessor(ra))
-        using (IsoReader isoReader = new IsoReader())
-        {
-          isoReader.Open(localFsResourceAccessor.LocalFileSystemPath);
-
-          return IsoResourceAccessor.IsResource(isoReader, path);
-        }
+        udfReader = new UdfReader(ra.OpenRead());
       }
       catch
       {
+        udfReader = null;
+      }
+      try
+      {
+        iso9660Reader = new CDReader(ra.OpenRead(), true, true);
+      }
+      catch
+      {
+        iso9660Reader = null;
+      }
+
+      if (udfReader == null && iso9660Reader == null)
+      {
         ra.Dispose();
         return false;
       }
+
+      return IsoResourceAccessor.IsResource(udfReader, iso9660Reader, path);
+
     }
 
     #endregion
diff --git a/MediaPortal/Source/Extensions/ResourceProviders/IsoResourceProvider/IsoResourceProvider.csproj b/MediaPortal/Source/Extensions/ResourceProviders/IsoResourceProvider/IsoResourceProvider.csproj
index f58365e..3a259ca 100644
--- a/MediaPortal/Source/Extensions/ResourceProviders/IsoResourceProvider/IsoResourceProvider.csproj
+++ b/MediaPortal/Source/Extensions/ResourceProviders/IsoResourceProvider/IsoResourceProvider.csproj
@@ -46,6 +46,10 @@
     <CodeAnalysisIgnoreBuiltInRules>false</CodeAnalysisIgnoreBuiltInRules>
   </PropertyGroup>
   <ItemGroup>
+    <Reference Include="DiscUtils, Version=0.9.0.0, Culture=neutral, processorArchitecture=MSIL">
+      <SpecificVersion>False</SpecificVersion>
+      <HintPath>References\DiscUtils.dll</HintPath>
+    </Reference>
     <Reference Include="System" />
     <Reference Include="System.Core" />
     <Reference Include="System.Data" />
@@ -54,17 +58,6 @@
   <ItemGroup>
     <Compile Include="IsoResourceProxy.cs" />
     <Compile Include="IsoResourceProvider.cs" />
-    <Compile Include="ISOReader\DirectoryRecord.cs" />
-    <Compile Include="ISOReader\FileFlags.cs" />
-    <Compile Include="ISOReader\IsoFileStream.cs" />
-    <Compile Include="ISOReader\IsoReader.cs" />
-    <Compile Include="ISOReader\IsoReaderBase.cs" />
-    <Compile Include="ISOReader\PathTableRecord.cs" />
-    <Compile Include="ISOReader\PathTableRecordPub.cs" />
-    <Compile Include="ISOReader\RecordEntryInfo.cs" />
-    <Compile Include="ISOReader\VolumeDescriptor.cs" />
-    <Compile Include="ISOReader\VolumeInfo.cs" />
-    <Compile Include="ISOReader\VolumeType.cs" />
     <Compile Include="IsoResourceAccessor.cs" />
     <Compile Include="Properties\AssemblyInfo.cs" />
   </ItemGroup>
@@ -88,7 +81,8 @@
     <PostBuildEvent>xcopy /Y "$(ProjectDir)plugin.xml" "$(SolutionDir)..\Bin\$(SolutionName)\$(OutDir)Plugins\$(ProjectName)\"
 mkdir "$(SolutionDir)..\Bin\$(SolutionName)\$(OutDir)Plugins\$(ProjectName)\Language"
 robocopy "$(ProjectDir)Language" "$(SolutionDir)..\Bin\$(SolutionName)\$(OutDir)Plugins\$(ProjectName)\Language" /MIR /NP /XD .svn
-xcopy /Y "$(TargetDir)$(ProjectName).dll"  "$(SolutionDir)..\Bin\$(SolutionName)\$(OutDir)Plugins\$(ProjectName)\"</PostBuildEvent>
+xcopy /Y "$(TargetDir)$(ProjectName).dll"  "$(SolutionDir)..\Bin\$(SolutionName)\$(OutDir)Plugins\$(ProjectName)\"
+xcopy /Y "$(ProjectDir)References\*"  "$(SolutionDir)..\Bin\$(SolutionName)\$(OutDir)Plugins\$(ProjectName)\"</PostBuildEvent>
   </PropertyGroup>
   <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
        Other similar extension points exist, see Microsoft.Common.targets.
diff --git a/MediaPortal/Source/Extensions/ResourceProviders/IsoResourceProvider/IsoResourceProxy.cs b/MediaPortal/Source/Extensions/ResourceProviders/IsoResourceProvider/IsoResourceProxy.cs
index 00c2617..008657d 100644
--- a/MediaPortal/Source/Extensions/ResourceProviders/IsoResourceProvider/IsoResourceProxy.cs
+++ b/MediaPortal/Source/Extensions/ResourceProviders/IsoResourceProvider/IsoResourceProxy.cs
@@ -24,7 +24,8 @@
 
 using System;
 using MediaPortal.Common.ResourceAccess;
-using ISOReader;
+using DiscUtils.Iso9660;
+using DiscUtils.Udf;
 using MediaPortal.Common.Services.ResourceAccess.StreamedResourceToLocalFsAccessBridge;
 
 namespace MediaPortal.Extensions.ResourceProviders.IsoResourceProvider
@@ -33,11 +34,11 @@ namespace MediaPortal.Extensions.ResourceProviders.IsoResourceProvider
   {
     #region Protected fields
 
-    protected IsoReader _isoReader;
+    protected UdfReader _udfReader;
+    protected CDReader _iso9660Reader;
     protected string _key;
     protected int _usageCount = 0;
     protected IResourceAccessor _isoFileResourceAccessor;
-    protected ILocalFsResourceAccessor _baseLocalFsIsoResourceAccessor;
     protected object _syncObj = new object();
 
     #endregion
@@ -48,19 +49,24 @@ namespace MediaPortal.Extensions.ResourceProviders.IsoResourceProvider
     {
       _key = key;
       _isoFileResourceAccessor = isoFileResourceAccessor;
-      _baseLocalFsIsoResourceAccessor = StreamedResourceToLocalFsAccessBridge.GetLocalFsResourceAccessor(isoFileResourceAccessor.Clone()); // The StreamedResourceToLocalFsAccessBridge might dispose the given RA
       try
       {
-        _isoReader = new IsoReader();
-        _isoReader.Open(_baseLocalFsIsoResourceAccessor.LocalFileSystemPath);
+        _udfReader = new UdfReader(_isoFileResourceAccessor.OpenRead());
+      }
+      catch
+      {
+        _udfReader = null;
+      }
 
+      try
+      {
+        _iso9660Reader = new CDReader(_isoFileResourceAccessor.OpenRead(), true, true);
       }
       catch
       {
-        _isoReader.Close();
-        _baseLocalFsIsoResourceAccessor.Dispose();
-        throw;
+        _iso9660Reader = null;
       }
+
     }
 
     #endregion
@@ -69,20 +75,20 @@ namespace MediaPortal.Extensions.ResourceProviders.IsoResourceProvider
 
     public void Dispose()
     {
-      if (_isoReader != null)
+      if (_isoFileResourceAccessor != null)
       {
-        _isoReader.Dispose();
-        _isoReader = null;
+        _isoFileResourceAccessor.Dispose();
+        _isoFileResourceAccessor = null;
       }
-      if (_baseLocalFsIsoResourceAccessor != null)
+      if (_udfReader != null)
       {
-        _baseLocalFsIsoResourceAccessor.Dispose();
-        _baseLocalFsIsoResourceAccessor = null;
+        _udfReader.Dispose();
+        _udfReader = null;
       }
-      if (_isoFileResourceAccessor != null)
+      if (_udfReader != null)
       {
-        _isoFileResourceAccessor.Dispose();
-        _isoFileResourceAccessor = null;
+        _iso9660Reader.Dispose();
+        _iso9660Reader = null;
       }
     }
 
@@ -110,9 +116,14 @@ namespace MediaPortal.Extensions.ResourceProviders.IsoResourceProvider
       get { return _isoFileResourceAccessor; }
     }
 
-    public IsoReader IsoReader
+    public UdfReader IsoUdfReader
     {
-      get { return _isoReader; }
+      get { return _udfReader; }
+    }
+
+    public CDReader Iso9660Reader
+    {
+      get { return _iso9660Reader; }
     }
 
     public int UsageCount
@@ -141,10 +152,10 @@ namespace MediaPortal.Extensions.ResourceProviders.IsoResourceProvider
       lock (_syncObj)
         _usageCount++;
     }
-
+    
     public override string ToString()
     {
-      return string.Format("ISO file proxy object for file '{0}'", _baseLocalFsIsoResourceAccessor.LocalFileSystemPath);
+      return string.Format("ISO file proxy object for file '{0}'", _isoFileResourceAccessor.CanonicalLocalResourcePath);
     }
   }
 }
diff --git a/MediaPortal/Source/Extensions/ResourceProviders/IsoResourceProvider/References/DiscUtils License.txt b/MediaPortal/Source/Extensions/ResourceProviders/IsoResourceProvider/References/DiscUtils License.txt
new file mode 100644
index 0000000..481db28
--- /dev/null
+++ b/MediaPortal/Source/Extensions/ResourceProviders/IsoResourceProvider/References/DiscUtils License.txt	
@@ -0,0 +1,20 @@
+Copyright (c) 2008, Kenneth Bell
+
+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.
+
diff --git a/MediaPortal/Source/Extensions/ResourceProviders/IsoResourceProvider/References/DiscUtils.dll b/MediaPortal/Source/Extensions/ResourceProviders/IsoResourceProvider/References/DiscUtils.dll
new file mode 100644
index 0000000000000000000000000000000000000000..4766377ad46855c7604ee95ecc101f31dd037572
GIT binary patch
-- 
1.7.6.msysgit.0

