145 lines
		
	
	
	
		
			3.6 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
			
		
		
	
	
			145 lines
		
	
	
	
		
			3.6 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
| /*
 | |
|  * 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 partial 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 FormatType 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 password = null)
 | |
| 		{
 | |
| 			var prefix = ParsePrefix(data);
 | |
| 			var success = TryDetermineFormat(prefix, out FormatType format);
 | |
| 
 | |
| 			settings = default(Settings);
 | |
| 
 | |
| 			if (success)
 | |
| 			{
 | |
| 				if (compressor.IsCompressed(data))
 | |
| 				{
 | |
| 					data = compressor.Decompress(data);
 | |
| 				}
 | |
| 
 | |
| 				data = new SubStream(data, PREFIX_LENGTH, data.Length - PREFIX_LENGTH);
 | |
| 
 | |
| 				// TODO: Try to abstract (Parser -> Binary, Xml, ...; DataBlock -> Password, PlainData, ...) once fully implemented!
 | |
| 				switch (format)
 | |
| 				{
 | |
| 					case FormatType.Password:
 | |
| 					case FormatType.PasswordConfigureClient:
 | |
| 						return ParsePassword(data, format, out settings, password);
 | |
| 					case FormatType.PlainData:
 | |
| 						return ParsePlainData(data, out settings);
 | |
| 					case FormatType.PublicKeyHash:
 | |
| 						return ParsePublicKeyHash(data, out settings, password);
 | |
| 					case FormatType.PublicKeyHashSymmetricKey:
 | |
| 						return ParsePublicKeyHashWithSymmetricKey(data, out settings, password);
 | |
| 				}
 | |
| 			}
 | |
| 
 | |
| 			logger.Error($"'{data}' starting with '{prefix}' does not match the binary format!");
 | |
| 
 | |
| 			return LoadStatus.InvalidData;
 | |
| 		}
 | |
| 
 | |
| 		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 FormatType format)
 | |
| 		{
 | |
| 			format = default(FormatType);
 | |
| 
 | |
| 			switch (prefix)
 | |
| 			{
 | |
| 				case "pswd":
 | |
| 					format = FormatType.Password;
 | |
| 					return true;
 | |
| 				case "pwcc":
 | |
| 					format = FormatType.PasswordConfigureClient;
 | |
| 					return true;
 | |
| 				case "plnd":
 | |
| 					format = FormatType.PlainData;
 | |
| 					return true;
 | |
| 				case "pkhs":
 | |
| 					format = FormatType.PublicKeyHash;
 | |
| 					return true;
 | |
| 				case "phsk":
 | |
| 					format = FormatType.PublicKeyHashSymmetricKey;
 | |
| 					return true;
 | |
| 			}
 | |
| 
 | |
| 			return false;
 | |
| 		}
 | |
| 
 | |
| 		private enum FormatType
 | |
| 		{
 | |
| 			Password = 1,
 | |
| 			PasswordConfigureClient,
 | |
| 			PlainData,
 | |
| 			PublicKeyHash,
 | |
| 			PublicKeyHashSymmetricKey
 | |
| 		}
 | |
| 	}
 | |
| }
 | 
