2019-08-07 10:10:37 +02:00
using System ;
using System.Collections ;
using System.Collections.Generic ;
using System.IO ;
using System.Runtime.InteropServices ;
using System.Text ;
using System.Windows.Forms ;
//
// SEBClientInfo.cs
// SafeExamBrowser
//
2020-01-06 15:24:46 +01:00
// Copyright (c) 2010-2020 Viktor Tomas, Dirk Bauer, Daniel R. Schneider, Pascal Wyss,
2019-08-07 10:10:37 +02:00
// ETH Zurich, Educational Development and Technology (LET),
// based on the original idea of Safe Exam Browser
// by Stefan Schneider, University of Giessen
// Project concept: Thomas Piendl, Daniel R. Schneider,
// Dirk Bauer, Kai Reuter, Tobias Halbherr, Karsten Burger, Marco Lehre,
// Brigitte Schmucki, Oliver Rahs. French localization: Nicolas Dunand
//
// ``The contents of this file are subject to the Mozilla Public License
// Version 1.1 (the "License"); you may not use this file except in
// compliance with the License. You may obtain a copy of the License at
// http://www.mozilla.org/MPL/
//
// Software distributed under the License is distributed on an "AS IS"
// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
// License for the specific language governing rights and limitations
// under the License.
//
// The Original Code is Safe Exam Browser for Windows.
//
// The Initial Developers of the Original Code are Viktor Tomas,
// Dirk Bauer, Daniel R. Schneider, Pascal Wyss.
// Portions created by Viktor Tomas, Dirk Bauer, Daniel R. Schneider, Pascal Wyss
2020-01-06 15:24:46 +01:00
// are Copyright (c) 2010-2020 Viktor Tomas, Dirk Bauer, Daniel R. Schneider,
2019-08-07 10:10:37 +02:00
// Pascal Wyss, ETH Zurich, Educational Development and Technology (LET),
// based on the original idea of Safe Exam Browser
// by Stefan Schneider, University of Giessen. All Rights Reserved.
//
// Contributor(s): ______________________________________.
//
namespace SebWindowsConfig.Utilities
{
public enum chooseFileToUploadPolicies
{
manuallyWithFileRequester = 0 ,
attemptUploadSameFileDownloadedBefore = 1 ,
onlyAllowUploadSameFileDownloadedBefore = 2
} ;
public enum newBrowserWindowPolicies
{
getGenerallyBlocked = 0 ,
openInSameWindow = 1 ,
openInNewWindow = 2
} ;
public enum sebServicePolicies
{
ignoreService = 0 ,
indicateMissingService = 1 ,
forceSebService = 2
} ;
public enum browserViewModes
{
browserViewModeWindow = 0 ,
browserViewModeFullscreen = 1
} ;
// MAC
public enum sebPurposePolicies
{
sebPurposePolicyStartingExam = 0 ,
sebPurposePolicyConfiguringClient = 1
} ;
public enum URLFilterRuleActions
{
block = 0 ,
allow = 1 ,
ignore = 2 ,
unknown = 3
} ;
public enum SEBMinMacOSVersion
{
SEBMinOSX10_7 = 0 ,
SEBMinOSX10_8 = 1 ,
SEBMinOSX10_9 = 2 ,
SEBMinOSX10_10 = 3 ,
SEBMinOSX10_11 = 4 ,
SEBMinMacOS10_12 = 5 ,
SEBMinMacOS10_13 = 6 ,
SEBMinMacOS10_14 = 7
} ;
public class SEBClientInfo
{
#region Imports
[DllImport("kernel32.Dll")]
public static extern short GetVersionEx ( ref OSVERSIONINFO o ) ;
#endregion
// Socket protocol
//static int ai_family = AF_INET;
//static int ai_socktype = SOCK_STREAM;
//static int ai_protocol = IPPROTO_TCP;
#region Constants
// Name and location of SEB configuration files and logfiles
public const string SEB_CLIENT_CONFIG = "SebClientSettings.seb" ;
public const string SEB_CLIENT_LOG = "SebClient.log" ;
private const string XUL_RUNNER_CONFIG = "config.json" ;
public const string SEB_SHORTNAME = "SEB" ;
public const string XUL_RUNNER = "firefox.exe" ;
private const string XUL_RUNNER_INI = "seb.ini" ;
// Application path contains [MANUFACTURER]\[PRODUCT_NAME]
// (see also "SebWindowsPackageSetup" Project in MS Visual Studio 10)
public const string MANUFACTURER_LOCAL = "SafeExamBrowser" ;
//private const string MANUFACTURER = "ETH Zuerich";
public const string PRODUCT_NAME = "SafeExamBrowser" ;
public const string SEB_SERVICE_DIRECTORY = "SebWindowsServiceWCF" ;
public const string SEB_BROWSER_DIRECTORY = "SebWindowsBrowser" ;
private const string XUL_RUNNER_DIRECTORY = "xulrunner" ;
private const string XUL_SEB_DIRECTORY = "xul_seb" ;
public const string FILENAME_SEB = "SafeExamBrowser.exe" ;
public const string FILENAME_SEBCONFIGTOOL = "SEBConfigTool.exe" ;
public const string FILENAME_SEBSERVICE = "SebWindowsServiceWCF.exe" ;
public const string FILENAME_DLL_FLECK = "Fleck.dll" ;
public const string FILENAME_DLL_ICONLIB = "IconLib.dll" ;
public const string FILENAME_DLL_IONICZIP = "Ionic.Zip.dll" ;
public const string FILENAME_DLL_METRO = "MetroFramework.dll" ;
public const string FILENAME_DLL_NAUDIO = "NAudio.dll" ;
public const string FILENAME_DLL_NEWTONSOFTJSON = "Newtonsoft.Json.dll" ;
public const string FILENAME_DLL_SERVICECONTRACTS = "SEBWindowsServiceContracts.dll" ;
public const string BROWSER_USERAGENT_DESKTOP = "Mozilla/5.0 (Windows NT 10.0; WOW64; rv:52.0) Gecko/20100101 Firefox/52.0" ;
public const string BROWSER_USERAGENT_TOUCH = "Mozilla/5.0 (Windows NT 10.0; WOW64; rv:52.0; Touch) Gecko/20100101 Firefox/52.0" ;
public const string BROWSER_USERAGENT_TOUCH_IPAD = "Mozilla/5.0 (iPad; CPU OS 11_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/11.3 Mobile/15E216 Safari/605.1.15" ;
public const string BROWSER_USERAGENT_SEB = "SEB" ;
public const string END_OF_STRING_KEYWORD = "---SEB---" ;
private const string DEFAULT_USERNAME = "" ;
private const string DEFAULT_HOSTNAME = "localhost" ;
private const string DEFAULT_HOST_IP_ADDRESS = "127.0.0.1" ;
private const int DEFAULT_PORTNUMBER = 57016 ;
public const string DEFAULT_KEY = "Di𝈭l𝈖 Ch𝈒 aht𝈁aHai1972" ;
private const int DEFAULT_SEND_INTERVAL = 100 ;
private const int DEFAULT_RECV_TIMEOUT = 100 ;
private const int DEFAULT_NUM_MESSAGES = 3 ;
public const string SEB_NEW_DESKTOP_NAME = "SEBDesktop" ;
public const string SEB_WINDOWS_SERVICE_NAME = "SebWindowsService" ;
#endregion
#region Public Properties
public static bool ExplorerShellWasKilled { get ; set ; }
public static bool IsNewOS { get ; set ; }
public static bool examMode = false ;
// SEB Client Socket properties
public static char [ ] UserNameRegistryFlags { get ; set ; }
public static char [ ] RegistryFlags { get ; set ; }
public static string HostName { get ; set ; }
public static string HostIpAddress { get ; set ; }
public static string UserName { get ; set ; }
public static char [ ] UserSid { get ; set ; }
public static int PortNumber { get ; set ; }
public static int SendInterval { get ; set ; }
public static int RecvTimeout { get ; set ; }
public static int NumMessages { get ; set ; }
public static int MessageNr { get ; set ; }
public static string DesktopName { get ; set ; }
// SEB Client Directories properties
public static string ApplicationExecutableDirectory { get ; set ; }
public static string ProgramFilesX86Directory { get ; set ; }
public static bool LogFileDesiredMsgHook { get ; set ; }
public static bool LogFileDesiredSebClient { get ; set ; }
public static string SebClientLogFileDirectory { get ; set ; }
public static string SebClientDirectory { get ; set ; }
public static string SebClientLogFile { get ; set ; }
public static string SebClientSettingsProgramDataDirectory { get ; set ; }
public static string SebClientSettingsAppDataDirectory { get ; set ; }
public static string XulRunnerAdditionalDictionariesDirectory { get ; set ; }
public static string XulRunnerDirectory { get ; set ; }
public static string XulSebDirectory { get ; set ; }
public static string SebClientSettingsProgramDataFile ;
public static string SebClientSettingsAppDataFile ;
public static string XulRunnerConfigFileDirectory { get ; set ; }
public static string XulRunnerConfigFile ;
public static string XulRunnerExePath ;
public static string XulRunnerSebIniPath ;
public static string XulRunnerParameter ;
//public static string XulRunnerFlashContainerState { get; set; }
public static string ExamUrl { get ; set ; }
public static string QuitPassword { get ; set ; }
public static string QuitHashcode { get ; set ; }
//public static Dictionary<string, object> sebSettings = new Dictionary<string, object>();
public static string LoadingSettingsFileName = "" ;
public static float scaleFactor = 1 ;
public static int appChooserHeight = 132 ;
#endregion
#region Structures
/// <summary>
/// Stores windows version info.
/// </summary>
[StructLayout(LayoutKind.Sequential)]
public struct OSVERSIONINFO
{
public int dwOSVersionInfoSize ;
public int dwMajorVersion ;
public int dwMinorVersion ;
public int dwBuildNumber ;
public int dwPlatformId ;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
public string szCSDVersion ;
}
#endregion
//public static SEBClientConfig sebClientConfig;
public static Dictionary < string , object > getSebSetting ( string key )
{
object sebSetting = null ;
try
{
sebSetting = SEBSettings . settingsCurrent [ key ] ;
}
catch
{
sebSetting = null ;
}
if ( sebSetting ! = null )
return SEBSettings . settingsCurrent ;
else
return SEBSettings . settingsDefault ;
}
/// <summary>
/// Sets user, host info, send-recv interval, recv timeout, Logger and read SebClient configuration.
/// </summary>
/// <returns></returns>
public static bool SetSebClientConfiguration ( )
{
bool setSebClientConfiguration = false ;
// Initialise socket properties
IsNewOS = false ;
ExplorerShellWasKilled = false ;
UserNameRegistryFlags = new char [ 100 ] ;
RegistryFlags = new char [ 50 ] ;
UserSid = new char [ 512 ] ;
UserName = DEFAULT_USERNAME ;
HostName = DEFAULT_HOSTNAME ;
HostIpAddress = DEFAULT_HOST_IP_ADDRESS ;
PortNumber = DEFAULT_PORTNUMBER ;
SendInterval = DEFAULT_SEND_INTERVAL ;
RecvTimeout = DEFAULT_RECV_TIMEOUT ;
NumMessages = DEFAULT_NUM_MESSAGES ;
//Sets paths to files SEB has to save or read from the file system
SetSebPaths ( ) ;
byte [ ] sebClientSettings = null ;
// Create a string builder for a temporary log (until we can write it with the Logger)
StringBuilder tempLogStringBuilder = new StringBuilder ( ) ;
// Try to read the SebClientSettigs.seb file from the program data directory
try
{
sebClientSettings = File . ReadAllBytes ( SebClientSettingsProgramDataFile ) ;
}
catch ( Exception streamReadException )
{
// Write error into string with temporary log string builder
tempLogStringBuilder . Append ( "Could not load SebClientSettigs.seb from the Program Data directory" ) . Append ( streamReadException = = null ? null : streamReadException . GetType ( ) . ToString ( ) ) . Append ( streamReadException . Message ) ;
}
if ( sebClientSettings = = null )
{
// Try to read the SebClientSettigs.seb file from the local application data directory
try
{
sebClientSettings = File . ReadAllBytes ( SebClientSettingsAppDataFile ) ;
}
catch ( Exception streamReadException )
{
// Write error into string with temporary log string builder
tempLogStringBuilder . Append ( "Could not load SebClientSettigs.seb from the Roaming Application Data directory. " ) . Append ( streamReadException = = null ? null : streamReadException . GetType ( ) . ToString ( ) ) . Append ( streamReadException . Message ) ;
}
}
// Store the decrypted configuration settings.
if ( ! SEBSettings . StoreDecryptedSebClientSettings ( sebClientSettings ) )
return false ;
// Initialise Logger, if enabled
InitializeLogger ( ) ;
// Save the temporary log string into the log
Logger . AddError ( tempLogStringBuilder . ToString ( ) , null , null ) ;
// Set username
UserName = Environment . UserName ;
setSebClientConfiguration = true ;
// Write settings into log
StringBuilder userInfo =
new StringBuilder ( "User Name: " ) . Append ( UserName )
. Append ( " Host Name: " ) . Append ( HostName )
. Append ( " Port Number: " ) . Append ( PortNumber )
. Append ( " Send Interval: " ) . Append ( SendInterval )
. Append ( " Recv Timeout: " ) . Append ( RecvTimeout )
. Append ( " Num Messages: " ) . Append ( NumMessages )
. Append ( " SebClientConfigFileDirectory: " ) . Append ( SebClientSettingsAppDataDirectory )
. Append ( " SebClientConfigFile: " ) . Append ( SebClientSettingsAppDataFile ) ;
Logger . AddInformation ( userInfo . ToString ( ) , null , null ) ;
return setSebClientConfiguration ;
}
/// <summary>
/// Initialise Logger if it's enabled.
/// </summary>
public static void InitializeLogger ( )
{
if ( ( Boolean ) getSebSetting ( SEBSettings . KeyEnableLogging ) [ SEBSettings . KeyEnableLogging ] )
{
string logDirectory = ( string ) SEBSettings . valueForDictionaryKey ( SEBSettings . settingsCurrent , SEBSettings . KeyLogDirectoryWin ) ;
if ( ! String . IsNullOrEmpty ( logDirectory ) )
{
// Expand environment variables in log file path
SebClientLogFileDirectory = Environment . ExpandEnvironmentVariables ( logDirectory ) ;
SebClientLogFile = String . Format ( @"{0}\{1}" , SebClientLogFileDirectory , SEB_CLIENT_LOG ) ;
}
else
{
SEBClientInfo . SetDefaultClientLogFile ( ) ;
}
Logger . InitLogger ( SEBClientInfo . SebClientLogFileDirectory , null ) ;
}
}
/// <summary>
/// Sets paths to files SEB has to save or read from the file system.
/// </summary>
public static void SetSebPaths ( )
{
// Get the path of the directory the application executable lies in
ApplicationExecutableDirectory = Path . GetDirectoryName ( Application . ExecutablePath ) ;
// Get the path of the "Program Files X86" directory.
ProgramFilesX86Directory = Environment . GetFolderPath ( Environment . SpecialFolder . ProgramFilesX86 ) ;
// Get the path of the "Program Data" and "Local Application Data" directory.
string programDataDirectory = Environment . GetFolderPath ( Environment . SpecialFolder . CommonApplicationData ) ; //GetEnvironmentVariable("PROGRAMMDATA");
string appDataDirectory = Environment . GetFolderPath ( Environment . SpecialFolder . ApplicationData ) ;
/// Get paths for the two possible locations of the SebClientSettings.seb file
///
// In the program data directory (for managed systems, only an administrator can write in this directory):
// If there is a SebClientSettigs.seb file, then this has priority and is used by the SEB client, another
// SebClientSettigs.seb file in the local app data folder is ignored then and the SEB client cannot be
// reconfigured by opening a .seb file saved for configuring a client
StringBuilder sebClientSettingsProgramDataDirectoryBuilder = new StringBuilder ( programDataDirectory ) . Append ( "\\" ) . Append ( MANUFACTURER_LOCAL ) . Append ( "\\" ) ; //.Append(PRODUCT_NAME).Append("\\");
SebClientSettingsProgramDataDirectory = sebClientSettingsProgramDataDirectoryBuilder . ToString ( ) ;
// In the local application data directory (for unmanaged systems like student computers, user can write in this directory):
// A SebClientSettigs.seb file in this directory can be created or replaced by opening a .seb file saved for configuring a client
StringBuilder sebClientSettingsAppDataDirectoryBuilder = new StringBuilder ( appDataDirectory ) . Append ( "\\" ) . Append ( MANUFACTURER_LOCAL ) . Append ( "\\" ) ; //.Append(PRODUCT_NAME).Append("\\");
SebClientSettingsAppDataDirectory = sebClientSettingsAppDataDirectoryBuilder . ToString ( ) ;
// Set the location of the SebWindowsClientDirectory
StringBuilder sebClientDirectoryBuilder = new StringBuilder ( ProgramFilesX86Directory ) . Append ( "\\" ) . Append ( PRODUCT_NAME ) . Append ( "\\" ) ;
SebClientDirectory = sebClientDirectoryBuilder . ToString ( ) ;
// The directory into which additional dictionaries are extracted.
XulRunnerAdditionalDictionariesDirectory = Path . Combine ( SebClientSettingsAppDataDirectory , "Dictionaries" ) ;
// Set the location of the XulRunnerDirectory
//StringBuilder xulRunnerDirectoryBuilder = new StringBuilder(SebClientDirectory).Append(XUL_RUNNER_DIRECTORY).Append("\\");
//XulRunnerDirectory = xulRunnerDirectoryBuilder.ToString();
StringBuilder xulRunnerDirectoryBuilder = new StringBuilder ( SEB_BROWSER_DIRECTORY ) . Append ( "\\" ) . Append ( XUL_RUNNER_DIRECTORY ) . Append ( "\\" ) ;
XulRunnerDirectory = xulRunnerDirectoryBuilder . ToString ( ) ;
// Set the location of the XulSebDirectory
//StringBuilder xulSebDirectoryBuilder = new StringBuilder(SebClientDirectory).Append(XUL_SEB_DIRECTORY).Append("\\");
//XulSebDirectory = xulSebDirectoryBuilder.ToString();
StringBuilder xulSebDirectoryBuilder = new StringBuilder ( SEB_BROWSER_DIRECTORY ) . Append ( "\\" ) . Append ( XUL_SEB_DIRECTORY ) . Append ( "\\" ) ;
XulSebDirectory = xulSebDirectoryBuilder . ToString ( ) ;
// Set the location of the XulRunnerExePath
//StringBuilder xulRunnerExePathBuilder = new StringBuilder("\"").Append(XulRunnerDirectory).Append(XUL_RUNNER).Append("\"");
//XulRunnerExePath = xulRunnerExePathBuilder.ToString();
StringBuilder xulRunnerExePathBuilder = new StringBuilder ( XulRunnerDirectory ) . Append ( XUL_RUNNER ) ; //.Append("\"");
XulRunnerExePath = xulRunnerExePathBuilder . ToString ( ) ;
// Set the location of the seb.ini
StringBuilder xulRunnerSebIniPathBuilder = new StringBuilder ( XulSebDirectory ) . Append ( XUL_RUNNER_INI ) ; //.Append("\"");
XulRunnerSebIniPath = xulRunnerSebIniPathBuilder . ToString ( ) ;
// Get the two possible paths of the SebClientSettings.seb file
StringBuilder sebClientSettingsProgramDataBuilder = new StringBuilder ( SebClientSettingsProgramDataDirectory ) . Append ( SEB_CLIENT_CONFIG ) ;
SebClientSettingsProgramDataFile = sebClientSettingsProgramDataBuilder . ToString ( ) ;
StringBuilder sebClientSettingsAppDataBuilder = new StringBuilder ( SebClientSettingsAppDataDirectory ) . Append ( SEB_CLIENT_CONFIG ) ;
SebClientSettingsAppDataFile = sebClientSettingsAppDataBuilder . ToString ( ) ;
// Set the default location of the SebClientLogFileDirectory
SetDefaultClientLogFile ( ) ;
}
/// <summary>
/// Set the default location of the SebClientLogFileDirectory.
/// </summary>
public static void SetDefaultClientLogFile ( )
{
StringBuilder SebClientLogFileDirectoryBuilder = new StringBuilder ( SebClientSettingsAppDataDirectory ) ; //.Append("\\").Append(MANUFACTURER_LOCAL).Append("\\");
SebClientLogFileDirectory = SebClientLogFileDirectoryBuilder . ToString ( ) ;
// Set the path of the SebClient.log file
StringBuilder sebClientLogFileBuilder = new StringBuilder ( SebClientLogFileDirectory ) . Append ( SEB_CLIENT_LOG ) ;
SebClientLogFile = sebClientLogFileBuilder . ToString ( ) ;
}
public static bool CreateNewDesktopOldValue { get ; set ; }
public static string ContractEnvironmentVariables ( string path )
{
path = Path . GetFullPath ( path ) ;
DictionaryEntry currentEntry = new DictionaryEntry ( "" , "" ) ;
foreach ( object key in Environment . GetEnvironmentVariables ( ) . Keys )
{
string value = ( string ) Environment . GetEnvironmentVariables ( ) [ key ] ;
if ( path . ToUpperInvariant ( ) . Contains ( value . ToUpperInvariant ( ) ) & & value . Length > ( ( string ) currentEntry . Value ) . Length )
{
currentEntry . Key = ( string ) key ;
currentEntry . Value = value ;
}
}
return path . Replace ( ( string ) currentEntry . Value , "%" + ( string ) currentEntry . Key + "%" ) ;
}
}
}