// Copyright © 2016 The CefSharp Authors. All rights reserved.
//
// Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.
using System;
using System.IO;
using System.Net;
namespace CefSharp.SchemeHandler
{
///
/// FolderSchemeHandlerFactory is a very simple scheme handler that allows you
/// to map requests for urls to a folder on your file system. For example
/// creating a setting the rootFolder to c:\projects\CefSharp\CefSharp.Example\Resources
/// registering the scheme handler
///
public class FolderSchemeHandlerFactory : ISchemeHandlerFactory
{
private readonly string rootFolder;
private readonly string defaultPage;
private readonly string schemeName;
private readonly string hostName;
private readonly FileShare resourceFileShare;
///
/// is being deprecated in favour of using
/// Chromiums native mimeType lookup which is accessible using Cef.GetMimeType, this method is however
/// not directly avaliable as it exists in CefSharp.Core, to get around this we set
/// this static delegate with a reference to Cef.GetMimeType when Cef.Initialize is called.
///
public static Func GetMimeTypeDelegate = (s) => { return ResourceHandler.GetMimeType(s); };
///
/// Initialize a new instance of FolderSchemeHandlerFactory
///
/// Root Folder where all your files exist, requests cannot be made outside of this folder
/// if not null then schemeName checking will be implemented
/// if not null then hostName checking will be implemented
/// default page if no page specified, defaults to index.html
/// file share mode used to open resources, defaults to FileShare.Read
public FolderSchemeHandlerFactory(string rootFolder, string schemeName = null, string hostName = null, string defaultPage = "index.html", FileShare resourceFileShare = FileShare.Read)
{
this.rootFolder = Path.GetFullPath(rootFolder);
this.defaultPage = defaultPage;
this.schemeName = schemeName;
this.hostName = hostName;
this.resourceFileShare = resourceFileShare;
if (!Directory.Exists(this.rootFolder))
{
throw new DirectoryNotFoundException(this.rootFolder);
}
}
///
/// If the file requested is within the rootFolder then a IResourceHandler reference to the file requested will be returned
/// otherwise a 404 ResourceHandler will be returned.
///
/// the browser window that originated the
/// request or null if the request did not originate from a browser window
/// (for example, if the request came from CefURLRequest).
/// frame that originated the request
/// or null if the request did not originate from a browser window
/// (for example, if the request came from CefURLRequest).
/// the scheme name
/// The request. (will not contain cookie data)
///
/// A IResourceHandler
///
IResourceHandler ISchemeHandlerFactory.Create(IBrowser browser, IFrame frame, string schemeName, IRequest request)
{
return Create(browser, frame, schemeName, request);
}
///
/// If the file requested is within the rootFolder then a IResourceHandler reference to the file requested will be returned
/// otherwise a 404 ResourceHandler will be returned.
///
/// the browser window that originated the
/// request or null if the request did not originate from a browser window
/// (for example, if the request came from CefURLRequest).
/// frame that originated the request
/// or null if the request did not originate from a browser window
/// (for example, if the request came from CefURLRequest).
/// the scheme name
/// The request. (will not contain cookie data)
///
/// A IResourceHandler
///
protected virtual IResourceHandler Create(IBrowser browser, IFrame frame, string schemeName, IRequest request)
{
if (this.schemeName != null && !schemeName.Equals(this.schemeName, StringComparison.OrdinalIgnoreCase))
{
return ResourceHandler.ForErrorMessage(string.Format("SchemeName {0} does not match the expected SchemeName of {1}.", schemeName, this.schemeName), HttpStatusCode.NotFound);
}
var uri = new Uri(request.Url);
if (this.hostName != null && !uri.Host.Equals(this.hostName, StringComparison.OrdinalIgnoreCase))
{
return ResourceHandler.ForErrorMessage(string.Format("HostName {0} does not match the expected HostName of {1}.", uri.Host, this.hostName), HttpStatusCode.NotFound);
}
//Get the absolute path and remove the leading slash
var asbolutePath = uri.AbsolutePath.Substring(1);
if (string.IsNullOrEmpty(asbolutePath))
{
asbolutePath = defaultPage;
}
var filePath = WebUtility.UrlDecode(Path.GetFullPath(Path.Combine(rootFolder, asbolutePath)));
//Check the file requested is within the specified path and that the file exists
if (filePath.StartsWith(rootFolder, StringComparison.OrdinalIgnoreCase) && File.Exists(filePath))
{
var fileExtension = Path.GetExtension(filePath);
var mimeType = GetMimeTypeDelegate(fileExtension);
var stream = new FileStream(filePath, FileMode.Open, FileAccess.Read, resourceFileShare);
return ResourceHandler.FromStream(stream, mimeType);
}
return ResourceHandler.ForErrorMessage("File Not Found - " + filePath, HttpStatusCode.NotFound);
}
}
}