SEBWIN-727: Implemented support for configuration data URIs.

This commit is contained in:
Damian Büchel 2023-09-05 17:47:05 +02:00
parent bbfa720b21
commit 3711555f70
5 changed files with 68 additions and 13 deletions

View file

@ -69,6 +69,7 @@ namespace SafeExamBrowser.Browser.UnitTests.Handlers
var quitUrl = "http://www.byebye.com";
var request = new Mock<IRequest>();
appConfig.ConfigurationFileMimeType = "application/seb";
request.SetupGet(r => r.Url).Returns(quitUrl);
settings.QuitUrl = quitUrl;
sut.QuitUrlVisited += (url) => eventFired = true;
@ -122,6 +123,7 @@ namespace SafeExamBrowser.Browser.UnitTests.Handlers
var request = new Mock<IRequest>();
var url = "https://www.test.org";
appConfig.ConfigurationFileMimeType = "application/seb";
filter.Setup(f => f.Process(It.Is<Request>(r => r.Url.Equals(url)))).Returns(FilterResult.Block);
request.SetupGet(r => r.ResourceType).Returns(ResourceType.MainFrame);
request.SetupGet(r => r.Url).Returns(url);
@ -155,6 +157,7 @@ namespace SafeExamBrowser.Browser.UnitTests.Handlers
var request = new Mock<IRequest>();
var url = "https://www.test.org";
appConfig.ConfigurationFileMimeType = "application/seb";
filter.Setup(f => f.Process(It.Is<Request>(r => r.Url.Equals(url)))).Returns(FilterResult.Block);
request.SetupGet(r => r.ResourceType).Returns(ResourceType.SubFrame);
request.SetupGet(r => r.Url).Returns(url);
@ -182,13 +185,34 @@ namespace SafeExamBrowser.Browser.UnitTests.Handlers
}
[TestMethod]
public void MustInitiateConfigurationFileDownload()
public void MustInitiateDataUriConfigurationFileDownload()
{
var browser = new Mock<IBrowser>();
var host = new Mock<IBrowserHost>();
var request = new Mock<IRequest>();
appConfig.ConfigurationFileExtension = ".xyz";
appConfig.ConfigurationFileMimeType = "application/seb";
appConfig.SebUriScheme = "abc";
appConfig.SebUriSchemeSecure = "abcd";
browser.Setup(b => b.GetHost()).Returns(host.Object);
request.SetupGet(r => r.Url).Returns($"{appConfig.SebUriSchemeSecure}://{appConfig.ConfigurationFileMimeType};base64,H4sIAAAAAAAAE41WbXPaRhD...");
var handled = sut.OnBeforeBrowse(Mock.Of<IWebBrowser>(), browser.Object, Mock.Of<IFrame>(), request.Object, false, false);
host.Verify(h => h.StartDownload(It.Is<string>(u => u == $"data:{appConfig.ConfigurationFileMimeType};base64,H4sIAAAAAAAAE41WbXPaRhD...")));
Assert.IsTrue(handled);
}
[TestMethod]
public void MustInitiateHttpConfigurationFileDownload()
{
var browser = new Mock<IBrowser>();
var host = new Mock<IBrowserHost>();
var request = new Mock<IRequest>();
appConfig.ConfigurationFileExtension = ".xyz";
appConfig.ConfigurationFileMimeType = "application/seb";
appConfig.SebUriScheme = "abc";
appConfig.SebUriSchemeSecure = "abcd";
browser.Setup(b => b.GetHost()).Returns(host.Object);
@ -198,13 +222,23 @@ namespace SafeExamBrowser.Browser.UnitTests.Handlers
host.Verify(h => h.StartDownload(It.Is<string>(u => u == $"{Uri.UriSchemeHttp}://host.com/path/file{appConfig.ConfigurationFileExtension}")));
Assert.IsTrue(handled);
}
handled = false;
host.Reset();
request.Reset();
[TestMethod]
public void MustInitiateHttpsConfigurationFileDownload()
{
var browser = new Mock<IBrowser>();
var host = new Mock<IBrowserHost>();
var request = new Mock<IRequest>();
appConfig.ConfigurationFileExtension = ".xyz";
appConfig.ConfigurationFileMimeType = "application/seb";
appConfig.SebUriScheme = "abc";
appConfig.SebUriSchemeSecure = "abcd";
browser.Setup(b => b.GetHost()).Returns(host.Object);
request.SetupGet(r => r.Url).Returns($"{appConfig.SebUriSchemeSecure}://host.com/path/file{appConfig.ConfigurationFileExtension}");
handled = sut.OnBeforeBrowse(Mock.Of<IWebBrowser>(), browser.Object, Mock.Of<IFrame>(), request.Object, false, false);
var handled = sut.OnBeforeBrowse(Mock.Of<IWebBrowser>(), browser.Object, Mock.Of<IFrame>(), request.Object, false, false);
host.Verify(h => h.StartDownload(It.Is<string>(u => u == $"{Uri.UriSchemeHttps}://host.com/path/file{appConfig.ConfigurationFileExtension}")));
Assert.IsTrue(handled);

View file

@ -121,19 +121,35 @@ namespace SafeExamBrowser.Browser.Handlers
private bool IsConfigurationFile(IRequest request, out string downloadUrl)
{
var isValidUri = Uri.TryCreate(request.Url, UriKind.RelativeOrAbsolute, out var uri);
var isConfigurationFile = isValidUri && string.Equals(appConfig.ConfigurationFileExtension, Path.GetExtension(uri.AbsolutePath), StringComparison.OrdinalIgnoreCase);
var hasFileExtension = string.Equals(appConfig.ConfigurationFileExtension, Path.GetExtension(uri.AbsolutePath), StringComparison.OrdinalIgnoreCase);
var isDataUri = request.Url.Contains(appConfig.ConfigurationFileMimeType);
var isConfigurationFile = isValidUri && (hasFileExtension || isDataUri);
downloadUrl = request.Url;
if (isConfigurationFile)
{
if (uri.Scheme == appConfig.SebUriScheme)
if (isDataUri)
{
downloadUrl = new UriBuilder(uri) { Scheme = Uri.UriSchemeHttp }.Uri.AbsoluteUri;
if (uri.Scheme == appConfig.SebUriScheme)
{
downloadUrl = request.Url.Replace($"{appConfig.SebUriScheme}{Uri.SchemeDelimiter}", "data:");
}
else if (uri.Scheme == appConfig.SebUriSchemeSecure)
{
downloadUrl = request.Url.Replace($"{appConfig.SebUriSchemeSecure}{Uri.SchemeDelimiter}", "data:");
}
}
else if (uri.Scheme == appConfig.SebUriSchemeSecure)
else
{
downloadUrl = new UriBuilder(uri) { Scheme = Uri.UriSchemeHttps }.Uri.AbsoluteUri;
if (uri.Scheme == appConfig.SebUriScheme)
{
downloadUrl = new UriBuilder(uri) { Scheme = Uri.UriSchemeHttp }.Uri.AbsoluteUri;
}
else if (uri.Scheme == appConfig.SebUriSchemeSecure)
{
downloadUrl = new UriBuilder(uri) { Scheme = Uri.UriSchemeHttps }.Uri.AbsoluteUri;
}
}
logger.Debug($"Detected configuration file {(windowSettings.UrlPolicy.CanLog() ? $"'{uri}'" : "")}.");

View file

@ -624,10 +624,10 @@ namespace SafeExamBrowser.Client
logger.Info($"Received server failure action request with id '{args.RequestId}'.");
var dialog = uiFactory.CreateServerFailureDialog(args.Message, args.ShowFallback);
var result = dialog.Show(splashScreen);
var result = dialog.Show();
runtime.SubmitServerFailureActionResult(args.RequestId, result.Abort, result.Fallback, result.Retry);
logger.Info($"Server failure action request with id '{args.RequestId}' is complete.");
logger.Info($"Server failure action request with id '{args.RequestId}' is complete, the user chose to {(result.Abort ? "abort" : (result.Fallback ? "fallback" : "retry"))}.");
}
private void ClientHost_Shutdown()

View file

@ -241,6 +241,11 @@ namespace SafeExamBrowser.Runtime.Operations
abort = args.Abort;
fallback = args.Fallback;
if (args.Retry)
{
logger.Debug("The user chose to retry the current server request.");
}
return args.Retry;
}

View file

@ -5,7 +5,7 @@
xmlns:fa="http://schemas.fontawesome.io/icons/"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:SafeExamBrowser.UserInterface.Desktop.Windows"
mc:Ignorable="d" Height="250" Width="450" ResizeMode="NoResize" Topmost="True">
mc:Ignorable="d" Height="250" Width="450" ResizeMode="NoResize" Topmost="True" WindowStartupLocation="CenterScreen">
<Window.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>