SEBWIN-221: Implemented basic gzip decompression & binary format detection. The browser is now automatically started after client initialization.
This commit is contained in:
parent
1d58a84db8
commit
b29fd8c2d7
16 changed files with 346 additions and 92 deletions
|
@ -69,6 +69,11 @@ namespace SafeExamBrowser.Browser
|
||||||
this.button.Clicked += Button_OnClick;
|
this.button.Clicked += Button_OnClick;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Start()
|
||||||
|
{
|
||||||
|
CreateNewInstance();
|
||||||
|
}
|
||||||
|
|
||||||
public void Terminate()
|
public void Terminate()
|
||||||
{
|
{
|
||||||
foreach (var instance in instances)
|
foreach (var instance in instances)
|
||||||
|
|
|
@ -105,6 +105,7 @@ namespace SafeExamBrowser.Client
|
||||||
if (success)
|
if (success)
|
||||||
{
|
{
|
||||||
RegisterEvents();
|
RegisterEvents();
|
||||||
|
StartBrowser();
|
||||||
|
|
||||||
var communication = runtime.InformClientReady();
|
var communication = runtime.InformClientReady();
|
||||||
|
|
||||||
|
@ -182,6 +183,12 @@ namespace SafeExamBrowser.Client
|
||||||
windowMonitor.WindowChanged -= WindowMonitor_WindowChanged;
|
windowMonitor.WindowChanged -= WindowMonitor_WindowChanged;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void StartBrowser()
|
||||||
|
{
|
||||||
|
logger.Info("Starting browser application...");
|
||||||
|
Browser.Start();
|
||||||
|
}
|
||||||
|
|
||||||
private void DisplayMonitor_DisplaySettingsChanged()
|
private void DisplayMonitor_DisplaySettingsChanged()
|
||||||
{
|
{
|
||||||
logger.Info("Reinitializing working area...");
|
logger.Info("Reinitializing working area...");
|
||||||
|
|
116
SafeExamBrowser.Configuration/Compression/GZipCompressor.cs
Normal file
116
SafeExamBrowser.Configuration/Compression/GZipCompressor.cs
Normal file
|
@ -0,0 +1,116 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2018 ETH Zürich, Educational Development and Technology (LET)
|
||||||
|
*
|
||||||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.IO.Compression;
|
||||||
|
using SafeExamBrowser.Contracts.Configuration;
|
||||||
|
using SafeExamBrowser.Contracts.Logging;
|
||||||
|
|
||||||
|
namespace SafeExamBrowser.Configuration.Compression
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Data compression using the GNU-Zip format (see https://en.wikipedia.org/wiki/Gzip).
|
||||||
|
/// </summary>
|
||||||
|
public class GZipCompressor : IDataCompressor
|
||||||
|
{
|
||||||
|
private const int ID1 = 0x1F;
|
||||||
|
private const int ID2 = 0x8B;
|
||||||
|
private const int CM = 8;
|
||||||
|
private const int FOOTER_LENGTH = 8;
|
||||||
|
private const int HEADER_LENGTH = 10;
|
||||||
|
|
||||||
|
private ILogger logger;
|
||||||
|
|
||||||
|
public GZipCompressor(ILogger logger)
|
||||||
|
{
|
||||||
|
this.logger = logger;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Stream Compress(Stream data)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Stream Decompress(Stream data)
|
||||||
|
{
|
||||||
|
var decompressed = new MemoryStream();
|
||||||
|
|
||||||
|
logger.Debug($"Starting decompression of '{data}' with {data.Length / 1000.0} KB data...");
|
||||||
|
data.Seek(0, SeekOrigin.Begin);
|
||||||
|
|
||||||
|
using (var stream = new GZipStream(data, CompressionMode.Decompress))
|
||||||
|
{
|
||||||
|
var buffer = new byte[4096];
|
||||||
|
var bytesRead = 0;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
bytesRead = stream.Read(buffer, 0, buffer.Length);
|
||||||
|
decompressed.Write(buffer, 0, bytesRead);
|
||||||
|
} while (bytesRead > 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.Debug($"Successfully decompressed {decompressed.Length / 1000.0} KB data into '{decompressed}'.");
|
||||||
|
|
||||||
|
return decompressed;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <remarks>
|
||||||
|
/// All gzip-compressed data has a 10-byte header and 8-byte footer. The header starts with two magic numbers (ID1 and ID2) and
|
||||||
|
/// the used compression method (CM), which normally denotes the DEFLATE algorithm. See https://tools.ietf.org/html/rfc1952 for
|
||||||
|
/// the original data format specification.
|
||||||
|
/// </remarks>
|
||||||
|
public bool IsCompressed(Stream data)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var longEnough = data.Length > HEADER_LENGTH + FOOTER_LENGTH;
|
||||||
|
|
||||||
|
data.Seek(0, SeekOrigin.Begin);
|
||||||
|
|
||||||
|
if (longEnough)
|
||||||
|
{
|
||||||
|
var id1 = data.ReadByte();
|
||||||
|
var id2 = data.ReadByte();
|
||||||
|
var cm = data.ReadByte();
|
||||||
|
var compressed = id1 == ID1 && id2 == ID2 && cm == CM;
|
||||||
|
|
||||||
|
logger.Debug($"'{data}' is {(compressed ? string.Empty : "not ")}a gzip-compressed stream.");
|
||||||
|
|
||||||
|
return compressed;
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.Debug($"'{data}' is not long enough ({data.Length} bytes) to be a gzip-compressed stream.");
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
logger.Error($"Failed to check whether '{data}' with {data.Length / 1000.0} KB data is a gzip-compressed stream!", e);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] Peek(Stream data, int count)
|
||||||
|
{
|
||||||
|
logger.Debug($"Peeking {count} bytes from '{data}'...");
|
||||||
|
data.Seek(0, SeekOrigin.Begin);
|
||||||
|
|
||||||
|
using (var stream = new GZipStream(data, CompressionMode.Decompress))
|
||||||
|
using (var decompressed = new MemoryStream())
|
||||||
|
{
|
||||||
|
var buffer = new byte[count];
|
||||||
|
var bytesRead = stream.Read(buffer, 0, buffer.Length);
|
||||||
|
|
||||||
|
decompressed.Write(buffer, 0, bytesRead);
|
||||||
|
|
||||||
|
return decompressed.ToArray();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -9,7 +9,6 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.IO.Compression;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using SafeExamBrowser.Contracts.Configuration;
|
using SafeExamBrowser.Contracts.Configuration;
|
||||||
using SafeExamBrowser.Contracts.Configuration.Settings;
|
using SafeExamBrowser.Contracts.Configuration.Settings;
|
||||||
|
@ -133,12 +132,15 @@ namespace SafeExamBrowser.Configuration
|
||||||
{
|
{
|
||||||
var status = TryLoadData(resource, out Stream data);
|
var status = TryLoadData(resource, out Stream data);
|
||||||
|
|
||||||
switch (status)
|
using (data)
|
||||||
{
|
{
|
||||||
case LoadStatus.LoadWithBrowser:
|
switch (status)
|
||||||
return HandleBrowserResource(resource, out settings);
|
{
|
||||||
case LoadStatus.Success:
|
case LoadStatus.LoadWithBrowser:
|
||||||
return TryParseData(data, out settings, adminPassword, settingsPassword);
|
return HandleBrowserResource(resource, out settings);
|
||||||
|
case LoadStatus.Success:
|
||||||
|
return TryParseData(data, out settings, adminPassword, settingsPassword);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
|
@ -201,32 +203,6 @@ namespace SafeExamBrowser.Configuration
|
||||||
return LoadStatus.Success;
|
return LoadStatus.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
private byte[] Decompress(byte[] bytes)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var buffer = new byte[4096];
|
|
||||||
|
|
||||||
using (var stream = new GZipStream(new MemoryStream(bytes), CompressionMode.Decompress))
|
|
||||||
using (var decompressed = new MemoryStream())
|
|
||||||
{
|
|
||||||
var bytesRead = 0;
|
|
||||||
|
|
||||||
do
|
|
||||||
{
|
|
||||||
bytesRead = stream.Read(buffer, 0, buffer.Length);
|
|
||||||
decompressed.Write(buffer, 0, bytesRead);
|
|
||||||
} while (bytesRead > 0);
|
|
||||||
|
|
||||||
return decompressed.ToArray();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (InvalidDataException)
|
|
||||||
{
|
|
||||||
return bytes;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void UpdateAppConfig()
|
private void UpdateAppConfig()
|
||||||
{
|
{
|
||||||
appConfig.ClientId = Guid.NewGuid();
|
appConfig.ClientId = Guid.NewGuid();
|
||||||
|
|
119
SafeExamBrowser.Configuration/DataFormats/BinaryFormat.cs
Normal file
119
SafeExamBrowser.Configuration/DataFormats/BinaryFormat.cs
Normal file
|
@ -0,0 +1,119 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2018 ETH Zürich, Educational Development and Technology (LET)
|
||||||
|
*
|
||||||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Text;
|
||||||
|
using SafeExamBrowser.Contracts.Configuration;
|
||||||
|
using SafeExamBrowser.Contracts.Configuration.Settings;
|
||||||
|
using SafeExamBrowser.Contracts.Logging;
|
||||||
|
|
||||||
|
namespace SafeExamBrowser.Configuration.DataFormats
|
||||||
|
{
|
||||||
|
public class BinaryFormat : IDataFormat
|
||||||
|
{
|
||||||
|
private const int PREFIX_LENGTH = 4;
|
||||||
|
|
||||||
|
private IDataCompressor compressor;
|
||||||
|
private ILogger logger;
|
||||||
|
|
||||||
|
public BinaryFormat(IDataCompressor compressor, ILogger logger)
|
||||||
|
{
|
||||||
|
this.compressor = compressor;
|
||||||
|
this.logger = logger;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool CanParse(Stream data)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var longEnough = data.Length > PREFIX_LENGTH;
|
||||||
|
|
||||||
|
if (longEnough)
|
||||||
|
{
|
||||||
|
var prefix = ParsePrefix(data);
|
||||||
|
var success = TryDetermineFormat(prefix, out DataFormat format);
|
||||||
|
|
||||||
|
logger.Debug($"'{data}' starting with '{prefix}' does {(success ? string.Empty : "not ")}match the binary format.");
|
||||||
|
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.Debug($"'{data}' is not long enough ({data.Length} bytes) to match the binary format.");
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
logger.Error($"Failed to determine whether '{data}' with {data.Length / 1000.0} KB data matches the binary format!", e);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public LoadStatus TryParse(Stream data, out Settings settings, string adminPassword = null, string settingsPassword = null)
|
||||||
|
{
|
||||||
|
settings = new Settings();
|
||||||
|
settings.Browser.AllowAddressBar = true;
|
||||||
|
settings.Browser.StartUrl = "www.duckduckgo.com";
|
||||||
|
settings.Browser.AllowConfigurationDownloads = true;
|
||||||
|
|
||||||
|
return LoadStatus.Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
private string ParsePrefix(Stream data)
|
||||||
|
{
|
||||||
|
var prefixData = new byte[PREFIX_LENGTH];
|
||||||
|
|
||||||
|
if (compressor.IsCompressed(data))
|
||||||
|
{
|
||||||
|
prefixData = compressor.Peek(data, PREFIX_LENGTH);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
data.Seek(0, SeekOrigin.Begin);
|
||||||
|
data.Read(prefixData, 0, PREFIX_LENGTH);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Encoding.UTF8.GetString(prefixData);
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool TryDetermineFormat(string prefix, out DataFormat format)
|
||||||
|
{
|
||||||
|
format = default(DataFormat);
|
||||||
|
|
||||||
|
switch (prefix)
|
||||||
|
{
|
||||||
|
case "pswd":
|
||||||
|
format = DataFormat.Password;
|
||||||
|
return true;
|
||||||
|
case "pwcc":
|
||||||
|
format = DataFormat.PasswordForConfigureClient;
|
||||||
|
return true;
|
||||||
|
case "plnd":
|
||||||
|
format = DataFormat.PlainData;
|
||||||
|
return true;
|
||||||
|
case "pkhs":
|
||||||
|
format = DataFormat.PublicKeyHash;
|
||||||
|
return true;
|
||||||
|
case "phsk":
|
||||||
|
format = DataFormat.PublicKeyHashWithSymmetricKey;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private enum DataFormat
|
||||||
|
{
|
||||||
|
Password = 1,
|
||||||
|
PasswordForConfigureClient,
|
||||||
|
PlainData,
|
||||||
|
PublicKeyHash,
|
||||||
|
PublicKeyHashWithSymmetricKey
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,35 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2018 ETH Zürich, Educational Development and Technology (LET)
|
|
||||||
*
|
|
||||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
||||||
*/
|
|
||||||
|
|
||||||
using System.IO;
|
|
||||||
using SafeExamBrowser.Contracts.Configuration;
|
|
||||||
using SafeExamBrowser.Contracts.Configuration.Settings;
|
|
||||||
using SafeExamBrowser.Contracts.Logging;
|
|
||||||
|
|
||||||
namespace SafeExamBrowser.Configuration.DataFormats
|
|
||||||
{
|
|
||||||
public class DefaultFormat : IDataFormat
|
|
||||||
{
|
|
||||||
private ILogger logger;
|
|
||||||
|
|
||||||
public DefaultFormat(ILogger logger)
|
|
||||||
{
|
|
||||||
this.logger = logger;
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool CanParse(Stream data)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public LoadStatus TryParse(Stream data, out Settings settings, string adminPassword = null, string settingsPassword = null)
|
|
||||||
{
|
|
||||||
throw new System.NotImplementedException();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -24,7 +24,7 @@ namespace SafeExamBrowser.Configuration.ResourceLoaders
|
||||||
|
|
||||||
public bool CanLoad(Uri resource)
|
public bool CanLoad(Uri resource)
|
||||||
{
|
{
|
||||||
var exists = resource.IsFile && File.Exists(resource.AbsolutePath);
|
var exists = resource.IsFile && File.Exists(resource.LocalPath);
|
||||||
|
|
||||||
if (exists)
|
if (exists)
|
||||||
{
|
{
|
||||||
|
@ -41,8 +41,8 @@ namespace SafeExamBrowser.Configuration.ResourceLoaders
|
||||||
public LoadStatus TryLoad(Uri resource, out Stream data)
|
public LoadStatus TryLoad(Uri resource, out Stream data)
|
||||||
{
|
{
|
||||||
logger.Debug($"Loading data from '{resource}'...");
|
logger.Debug($"Loading data from '{resource}'...");
|
||||||
data = new FileStream(resource.AbsolutePath, FileMode.Open, FileAccess.Read);
|
data = new FileStream(resource.LocalPath, FileMode.Open, FileAccess.Read);
|
||||||
logger.Debug($"Created {data} for {data.Length / 1000.0} KB data in '{resource}'.");
|
logger.Debug($"Created '{data}' for {data.Length / 1000.0} KB data in '{resource}'.");
|
||||||
|
|
||||||
return LoadStatus.Success;
|
return LoadStatus.Success;
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,9 @@ namespace SafeExamBrowser.Configuration.ResourceLoaders
|
||||||
private AppConfig appConfig;
|
private AppConfig appConfig;
|
||||||
private ILogger logger;
|
private ILogger logger;
|
||||||
|
|
||||||
|
/// <remarks>
|
||||||
|
/// See https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types.
|
||||||
|
/// </remarks>
|
||||||
private string[] SupportedContentTypes => new[]
|
private string[] SupportedContentTypes => new[]
|
||||||
{
|
{
|
||||||
MediaTypeNames.Application.Octet,
|
MediaTypeNames.Application.Octet,
|
||||||
|
@ -77,7 +80,7 @@ namespace SafeExamBrowser.Configuration.ResourceLoaders
|
||||||
|
|
||||||
logger.Debug($"Trying to extract response data...");
|
logger.Debug($"Trying to extract response data...");
|
||||||
data = Extract(response.Content);
|
data = Extract(response.Content);
|
||||||
logger.Debug($"Created {data} for {data.Length / 1000.0} KB data of response body.");
|
logger.Debug($"Created '{data}' for {data.Length / 1000.0} KB data of response body.");
|
||||||
|
|
||||||
return LoadStatus.Success;
|
return LoadStatus.Success;
|
||||||
}
|
}
|
||||||
|
@ -137,6 +140,9 @@ namespace SafeExamBrowser.Configuration.ResourceLoaders
|
||||||
return LoadStatus.LoadWithBrowser;
|
return LoadStatus.LoadWithBrowser;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <remarks>
|
||||||
|
/// See https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Type.
|
||||||
|
/// </remarks>
|
||||||
private bool HasHtmlContent(HttpResponseMessage response)
|
private bool HasHtmlContent(HttpResponseMessage response)
|
||||||
{
|
{
|
||||||
return response.Content.Headers.ContentType.MediaType == MediaTypeNames.Text.Html;
|
return response.Content.Headers.ContentType.MediaType == MediaTypeNames.Text.Html;
|
||||||
|
|
|
@ -53,7 +53,8 @@
|
||||||
<Reference Include="Microsoft.CSharp" />
|
<Reference Include="Microsoft.CSharp" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Include="DataFormats\DefaultFormat.cs" />
|
<Compile Include="Compression\GZipCompressor.cs" />
|
||||||
|
<Compile Include="DataFormats\BinaryFormat.cs" />
|
||||||
<Compile Include="DataFormats\XmlFormat.cs" />
|
<Compile Include="DataFormats\XmlFormat.cs" />
|
||||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
<Compile Include="ConfigurationRepository.cs" />
|
<Compile Include="ConfigurationRepository.cs" />
|
||||||
|
|
38
SafeExamBrowser.Contracts/Configuration/IDataCompressor.cs
Normal file
38
SafeExamBrowser.Contracts/Configuration/IDataCompressor.cs
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2018 ETH Zürich, Educational Development and Technology (LET)
|
||||||
|
*
|
||||||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System.IO;
|
||||||
|
|
||||||
|
namespace SafeExamBrowser.Contracts.Configuration
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Defines the functionality for data compression and decompression.
|
||||||
|
/// </summary>
|
||||||
|
public interface IDataCompressor
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Compresses the data from the given stream.
|
||||||
|
/// </summary>
|
||||||
|
Stream Compress(Stream data);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Decompresses the data from the given stream.
|
||||||
|
/// </summary>
|
||||||
|
Stream Decompress(Stream data);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates whether the given stream holds compressed data.
|
||||||
|
/// </summary>
|
||||||
|
bool IsCompressed(Stream data);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Decompresses the specified number of bytes from the beginning of the given stream.
|
||||||
|
/// </summary>
|
||||||
|
byte[] Peek(Stream data, int count);
|
||||||
|
}
|
||||||
|
}
|
|
@ -57,6 +57,10 @@ namespace SafeExamBrowser.Contracts.Configuration.Settings
|
||||||
Keyboard = new KeyboardSettings();
|
Keyboard = new KeyboardSettings();
|
||||||
Mouse = new MouseSettings();
|
Mouse = new MouseSettings();
|
||||||
Taskbar = new TaskbarSettings();
|
Taskbar = new TaskbarSettings();
|
||||||
|
|
||||||
|
// TODO: For version 3.0 alpha only, remove for final release!
|
||||||
|
ServicePolicy = ServicePolicy.Optional;
|
||||||
|
Taskbar.AllowApplicationLog = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,6 +25,11 @@ namespace SafeExamBrowser.Contracts.Core
|
||||||
/// </summary>
|
/// </summary>
|
||||||
void RegisterApplicationButton(IApplicationButton button);
|
void RegisterApplicationButton(IApplicationButton button);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Starts the execution of the application.
|
||||||
|
/// </summary>
|
||||||
|
void Start();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Performs any termination work, e.g. releasing of used resources.
|
/// Performs any termination work, e.g. releasing of used resources.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
@ -53,6 +53,7 @@
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Include="Communication\Events\ClientConfigurationEventArgs.cs" />
|
<Compile Include="Communication\Events\ClientConfigurationEventArgs.cs" />
|
||||||
|
<Compile Include="Configuration\IDataCompressor.cs" />
|
||||||
<Compile Include="Configuration\IDataFormat.cs" />
|
<Compile Include="Configuration\IDataFormat.cs" />
|
||||||
<Compile Include="Core\Events\InstanceTerminatedEventHandler.cs" />
|
<Compile Include="Core\Events\InstanceTerminatedEventHandler.cs" />
|
||||||
<Compile Include="Core\Events\NameChangedEventHandler.cs" />
|
<Compile Include="Core\Events\NameChangedEventHandler.cs" />
|
||||||
|
|
|
@ -381,7 +381,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
|
||||||
var location = Path.GetDirectoryName(GetType().Assembly.Location);
|
var location = Path.GetDirectoryName(GetType().Assembly.Location);
|
||||||
var resource = new Uri(Path.Combine(location, nameof(Operations), "SettingsDummy.txt"));
|
var resource = new Uri(Path.Combine(location, nameof(Operations), "SettingsDummy.txt"));
|
||||||
|
|
||||||
sessionContext.ReconfigurationFilePath = resource.AbsolutePath;
|
sessionContext.ReconfigurationFilePath = resource.LocalPath;
|
||||||
repository.Setup(r => r.TryLoadSettings(It.Is<Uri>(u => u.Equals(resource)), out settings, null, null)).Returns(LoadStatus.Success);
|
repository.Setup(r => r.TryLoadSettings(It.Is<Uri>(u => u.Equals(resource)), out settings, null, null)).Returns(LoadStatus.Success);
|
||||||
|
|
||||||
sut = new ConfigurationOperation(null, repository.Object, logger.Object, sessionContext);
|
sut = new ConfigurationOperation(null, repository.Object, logger.Object, sessionContext);
|
||||||
|
@ -408,7 +408,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations
|
||||||
repository.Verify(r => r.TryLoadSettings(It.Is<Uri>(u => u.Equals(resource)), out settings, null, null), Times.Never);
|
repository.Verify(r => r.TryLoadSettings(It.Is<Uri>(u => u.Equals(resource)), out settings, null, null), Times.Never);
|
||||||
Assert.AreEqual(OperationResult.Failed, result);
|
Assert.AreEqual(OperationResult.Failed, result);
|
||||||
|
|
||||||
sessionContext.ReconfigurationFilePath = resource.AbsolutePath;
|
sessionContext.ReconfigurationFilePath = resource.LocalPath;
|
||||||
result = sut.Repeat();
|
result = sut.Repeat();
|
||||||
|
|
||||||
repository.Verify(r => r.TryLoadSettings(It.Is<Uri>(u => u.Equals(resource)), out settings, null, null), Times.Never);
|
repository.Verify(r => r.TryLoadSettings(It.Is<Uri>(u => u.Equals(resource)), out settings, null, null), Times.Never);
|
||||||
|
|
|
@ -13,6 +13,7 @@ using System.Reflection;
|
||||||
using SafeExamBrowser.Communication.Hosts;
|
using SafeExamBrowser.Communication.Hosts;
|
||||||
using SafeExamBrowser.Communication.Proxies;
|
using SafeExamBrowser.Communication.Proxies;
|
||||||
using SafeExamBrowser.Configuration;
|
using SafeExamBrowser.Configuration;
|
||||||
|
using SafeExamBrowser.Configuration.Compression;
|
||||||
using SafeExamBrowser.Configuration.DataFormats;
|
using SafeExamBrowser.Configuration.DataFormats;
|
||||||
using SafeExamBrowser.Configuration.ResourceLoaders;
|
using SafeExamBrowser.Configuration.ResourceLoaders;
|
||||||
using SafeExamBrowser.Contracts.Configuration;
|
using SafeExamBrowser.Contracts.Configuration;
|
||||||
|
@ -112,12 +113,13 @@ namespace SafeExamBrowser.Runtime
|
||||||
var programCopyright = executable.GetCustomAttribute<AssemblyCopyrightAttribute>().Copyright;
|
var programCopyright = executable.GetCustomAttribute<AssemblyCopyrightAttribute>().Copyright;
|
||||||
var programTitle = executable.GetCustomAttribute<AssemblyTitleAttribute>().Title;
|
var programTitle = executable.GetCustomAttribute<AssemblyTitleAttribute>().Title;
|
||||||
var programVersion = executable.GetCustomAttribute<AssemblyInformationalVersionAttribute>().InformationalVersion;
|
var programVersion = executable.GetCustomAttribute<AssemblyInformationalVersionAttribute>().InformationalVersion;
|
||||||
var moduleLogger = new ModuleLogger(logger, nameof(ConfigurationRepository));
|
var compressor = new GZipCompressor(new ModuleLogger(logger, nameof(GZipCompressor)));
|
||||||
|
var repositoryLogger = new ModuleLogger(logger, nameof(ConfigurationRepository));
|
||||||
|
|
||||||
configuration = new ConfigurationRepository(moduleLogger, executable.Location, programCopyright, programTitle, programVersion);
|
configuration = new ConfigurationRepository(repositoryLogger, executable.Location, programCopyright, programTitle, programVersion);
|
||||||
appConfig = configuration.InitializeAppConfig();
|
appConfig = configuration.InitializeAppConfig();
|
||||||
|
|
||||||
configuration.Register(new DefaultFormat(new ModuleLogger(logger, nameof(DefaultFormat))));
|
configuration.Register(new BinaryFormat(compressor, new ModuleLogger(logger, nameof(BinaryFormat))));
|
||||||
configuration.Register(new XmlFormat(new ModuleLogger(logger, nameof(XmlFormat))));
|
configuration.Register(new XmlFormat(new ModuleLogger(logger, nameof(XmlFormat))));
|
||||||
configuration.Register(new FileResourceLoader(new ModuleLogger(logger, nameof(FileResourceLoader))));
|
configuration.Register(new FileResourceLoader(new ModuleLogger(logger, nameof(FileResourceLoader))));
|
||||||
configuration.Register(new NetworkResourceLoader(appConfig, new ModuleLogger(logger, nameof(NetworkResourceLoader))));
|
configuration.Register(new NetworkResourceLoader(appConfig, new ModuleLogger(logger, nameof(NetworkResourceLoader))));
|
||||||
|
|
|
@ -44,22 +44,22 @@ namespace SafeExamBrowser.Runtime.Operations
|
||||||
logger.Info("Initializing application configuration...");
|
logger.Info("Initializing application configuration...");
|
||||||
StatusChanged?.Invoke(TextKey.OperationStatus_InitializeConfiguration);
|
StatusChanged?.Invoke(TextKey.OperationStatus_InitializeConfiguration);
|
||||||
|
|
||||||
|
var result = OperationResult.Failed;
|
||||||
var isValidUri = TryInitializeSettingsUri(out Uri uri);
|
var isValidUri = TryInitializeSettingsUri(out Uri uri);
|
||||||
|
|
||||||
if (isValidUri)
|
if (isValidUri)
|
||||||
{
|
{
|
||||||
var result = LoadSettings(uri);
|
result = LoadSettings(uri);
|
||||||
|
|
||||||
HandleClientConfiguration(ref result, uri);
|
HandleClientConfiguration(ref result, uri);
|
||||||
LogOperationResult(result);
|
}
|
||||||
|
else
|
||||||
return result;
|
{
|
||||||
|
result = LoadDefaultSettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.Info("No valid configuration resource specified nor found in PROGRAMDATA or APPDATA - loading default settings...");
|
LogOperationResult(result);
|
||||||
Context.Next.Settings = configuration.LoadDefaultSettings();
|
|
||||||
|
|
||||||
return OperationResult.Success;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override OperationResult Repeat()
|
public override OperationResult Repeat()
|
||||||
|
@ -67,20 +67,21 @@ namespace SafeExamBrowser.Runtime.Operations
|
||||||
logger.Info("Initializing new application configuration...");
|
logger.Info("Initializing new application configuration...");
|
||||||
StatusChanged?.Invoke(TextKey.OperationStatus_InitializeConfiguration);
|
StatusChanged?.Invoke(TextKey.OperationStatus_InitializeConfiguration);
|
||||||
|
|
||||||
|
var result = OperationResult.Failed;
|
||||||
var isValidUri = TryValidateSettingsUri(Context.ReconfigurationFilePath, out Uri uri);
|
var isValidUri = TryValidateSettingsUri(Context.ReconfigurationFilePath, out Uri uri);
|
||||||
|
|
||||||
if (isValidUri)
|
if (isValidUri)
|
||||||
{
|
{
|
||||||
var result = LoadSettings(uri);
|
result = LoadSettings(uri);
|
||||||
|
}
|
||||||
LogOperationResult(result);
|
else
|
||||||
|
{
|
||||||
return result;
|
logger.Warn($"The resource specified for reconfiguration does not exist or is not valid!");
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.Warn($"The resource specified for reconfiguration does not exist or is not valid!");
|
LogOperationResult(result);
|
||||||
|
|
||||||
return OperationResult.Failed;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override OperationResult Revert()
|
public override OperationResult Revert()
|
||||||
|
@ -88,6 +89,14 @@ namespace SafeExamBrowser.Runtime.Operations
|
||||||
return OperationResult.Success;
|
return OperationResult.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private OperationResult LoadDefaultSettings()
|
||||||
|
{
|
||||||
|
logger.Info("No valid configuration resource specified nor found in PROGRAMDATA or APPDATA - loading default settings...");
|
||||||
|
Context.Next.Settings = configuration.LoadDefaultSettings();
|
||||||
|
|
||||||
|
return OperationResult.Success;
|
||||||
|
}
|
||||||
|
|
||||||
private OperationResult LoadSettings(Uri uri)
|
private OperationResult LoadSettings(Uri uri)
|
||||||
{
|
{
|
||||||
var adminPassword = default(string);
|
var adminPassword = default(string);
|
||||||
|
|
Loading…
Reference in a new issue