#17601: Avoiding exceptions by proactively handling the scenario where the path falls outside of the app directory.

--HG--
branch : 1.x
This commit is contained in:
Andre Rodrigues
2011-03-30 17:31:31 -07:00
parent 8c30a7d77e
commit e33f07ecc5
9 changed files with 79 additions and 20 deletions

View File

@@ -99,6 +99,10 @@ namespace Orchard.Tests.DisplayManagement.Descriptors {
public IEnumerable<string> ListDirectories(string path) {
throw new NotImplementedException();
}
public bool TryFileExists(string virtualPath) {
throw new NotImplementedException();
}
}
protected override void Resolve(ILifetimeScope container) {

View File

@@ -97,6 +97,10 @@ namespace Orchard.Tests.DisplayManagement.Descriptors {
public IEnumerable<string> ListDirectories(string path) {
throw new NotImplementedException();
}
public bool TryFileExists(string virtualPath) {
throw new NotImplementedException();
}
}
protected override void Resolve(ILifetimeScope container) {

View File

@@ -0,0 +1,26 @@
using Moq;
using NUnit.Framework;
using Orchard.FileSystems.VirtualPath;
namespace Orchard.Tests.FileSystems.VirtualPath {
[TestFixture]
public class DefaultVirtualPathProviderTests {
[Test]
public void TryFileExistsTest() {
StubDefaultVirtualPathProvider defaultVirtualPathProvider = new StubDefaultVirtualPathProvider();
Assert.That(defaultVirtualPathProvider.TryFileExists("~\\a.txt"), Is.True);
Assert.That(defaultVirtualPathProvider.TryFileExists("~\\..\\a.txt"), Is.False);
Assert.That(defaultVirtualPathProvider.TryFileExists("~\\a\\..\\a.txt"), Is.True);
Assert.That(defaultVirtualPathProvider.TryFileExists("~\\a\\b\\..\\a.txt"), Is.True);
Assert.That(defaultVirtualPathProvider.TryFileExists("~\\a\\b\\..\\..\\a.txt"), Is.True);
Assert.That(defaultVirtualPathProvider.TryFileExists("~\\a\\b\\..\\..\\..\\a.txt"), Is.False);
}
}
internal class StubDefaultVirtualPathProvider : DefaultVirtualPathProvider {
public override bool FileExists(string path) {
return true;
}
}
}

View File

@@ -253,6 +253,7 @@
<Compile Include="FileSystems\LockFile\LockFileManagerTests.cs" />
<Compile Include="FileSystems\Dependencies\AssemblyProbingFolderTests.cs" />
<Compile Include="FileSystems\Dependencies\DependenciesFolderTests.cs" />
<Compile Include="FileSystems\VirtualPath\DefaultVirtualPathProviderTests.cs" />
<Compile Include="Localization\CultureManagerTests.cs" />
<Compile Include="Messaging\MessagingChannelStub.cs" />
<Compile Include="Mvc\Html\HtmlHelperExtensionsTests.cs" />

View File

@@ -79,5 +79,14 @@ namespace Orchard.Tests.Stubs {
.Directories
.Select(f => Combine(path, f.Name));
}
public bool TryFileExists(string virtualPath) {
try {
return FileExists(virtualPath);
}
catch {
return false;
}
}
}
}

View File

@@ -203,7 +203,7 @@ namespace Orchard.Environment.Extensions.Loaders {
: _virtualPathProvider.Combine(basePath, referenceDescriptor.Path);
// Attempt to reference the project / library file
if (!currentSet.Contains(path) && _virtualPathProvider.FileExists(path)) {
if (!string.IsNullOrEmpty(path) && !currentSet.Contains(path) && _virtualPathProvider.TryFileExists(path)) {
currentSet.Add(path);
// In case of project, also reference the source files
@@ -212,7 +212,7 @@ namespace Orchard.Environment.Extensions.Loaders {
// Try to also reference any pre-built DLL
DependencyDescriptor dependencyDescriptor = _dependenciesFolder.GetDescriptor(_virtualPathProvider.GetDirectoryName(referenceDescriptor.Path));
if (dependencyDescriptor != null && _virtualPathProvider.FileExists(dependencyDescriptor.VirtualPath)) {
if (dependencyDescriptor != null && _virtualPathProvider.TryFileExists(dependencyDescriptor.VirtualPath)) {
currentSet.Add(dependencyDescriptor.VirtualPath);
}
}

View File

@@ -7,11 +7,11 @@ using System.Web.Hosting;
namespace Orchard.FileSystems.VirtualPath {
public class DefaultVirtualPathProvider : IVirtualPathProvider {
public string GetDirectoryName(string virtualPath) {
public virtual string GetDirectoryName(string virtualPath) {
return Path.GetDirectoryName(virtualPath).Replace(Path.DirectorySeparatorChar, '/');
}
public IEnumerable<string> ListFiles(string path) {
public virtual IEnumerable<string> ListFiles(string path) {
return HostingEnvironment
.VirtualPathProvider
.GetDirectory(path)
@@ -20,7 +20,7 @@ namespace Orchard.FileSystems.VirtualPath {
.Select(f => ToAppRelative(f.VirtualPath));
}
public IEnumerable<string> ListDirectories(string path) {
public virtual IEnumerable<string> ListDirectories(string path) {
return HostingEnvironment
.VirtualPathProvider
.GetDirectory(path)
@@ -29,49 +29,63 @@ namespace Orchard.FileSystems.VirtualPath {
.Select(d => ToAppRelative(d.VirtualPath));
}
public string Combine(params string[] paths) {
public virtual string Combine(params string[] paths) {
return Path.Combine(paths).Replace(Path.DirectorySeparatorChar, '/');
}
public string ToAppRelative(string virtualPath) {
public virtual string ToAppRelative(string virtualPath) {
return VirtualPathUtility.ToAppRelative(virtualPath);
}
public Stream OpenFile(string virtualPath) {
public virtual Stream OpenFile(string virtualPath) {
return HostingEnvironment.VirtualPathProvider.GetFile(virtualPath).Open();
}
public StreamWriter CreateText(string virtualPath) {
public virtual StreamWriter CreateText(string virtualPath) {
return File.CreateText(MapPath(virtualPath));
}
public Stream CreateFile(string virtualPath) {
public virtual Stream CreateFile(string virtualPath) {
return File.Create(MapPath(virtualPath));
}
public DateTime GetFileLastWriteTimeUtc(string virtualPath) {
public virtual DateTime GetFileLastWriteTimeUtc(string virtualPath) {
return File.GetLastWriteTimeUtc(MapPath(virtualPath));
}
public string MapPath(string virtualPath) {
public virtual string MapPath(string virtualPath) {
return HostingEnvironment.MapPath(virtualPath);
}
public bool FileExists(string virtualPath) {
public virtual bool FileExists(string virtualPath) {
return HostingEnvironment.VirtualPathProvider.FileExists(virtualPath);
}
public virtual bool TryFileExists(string virtualPath) {
try {
return HostingEnvironment.VirtualPathProvider.FileExists(virtualPath);
} catch {
// Medium Trust or invalid mappings that fall outside the app folder
// Check if the path falls outside the root directory of the app
string directoryName = Path.GetDirectoryName(virtualPath);
if (CountOccurences(@"\", directoryName.Replace(@"\..", "")) < CountOccurences(@"..", directoryName)) {
return false;
}
return FileExists(virtualPath);
}
catch {
return false;
}
}
public bool DirectoryExists(string virtualPath) {
public virtual bool DirectoryExists(string virtualPath) {
return HostingEnvironment.VirtualPathProvider.DirectoryExists(virtualPath);
}
public void CreateDirectory(string virtualPath) {
public virtual void CreateDirectory(string virtualPath) {
Directory.CreateDirectory(MapPath(virtualPath));
}
private static int CountOccurences(string needle, string haystack) {
return (haystack.Length - haystack.Replace(needle, "").Length) / needle.Length;
}
}
}

View File

@@ -10,6 +10,7 @@ namespace Orchard.FileSystems.VirtualPath {
string MapPath(string virtualPath);
bool FileExists(string virtualPath);
bool TryFileExists(string virtualPath);
Stream OpenFile(string virtualPath);
StreamWriter CreateText(string virtualPath);
Stream CreateFile(string virtualPath);

View File

@@ -17,13 +17,13 @@ namespace Orchard.Utility.Extensions {
public static string GetReferenceVirtualPath(this IVirtualPathProvider virtualPathProvider, string basePath, string referenceName, string hintPath) {
// Check if hint path is valid
if (!string.IsNullOrEmpty(hintPath)) {
if (virtualPathProvider.FileExists(virtualPathProvider.Combine(basePath, hintPath)))
if (virtualPathProvider.TryFileExists(virtualPathProvider.Combine(basePath, hintPath)))
return hintPath;
}
// Fall back to bin directory
string relativePath = virtualPathProvider.Combine("bin", referenceName + ".dll");
if (virtualPathProvider.FileExists(virtualPathProvider.Combine(basePath, relativePath)))
if (virtualPathProvider.TryFileExists(virtualPathProvider.Combine(basePath, relativePath)))
return relativePath;
return null;