From 8c656e31378fc8ef939eed411a74a14b8f8b023e Mon Sep 17 00:00:00 2001 From: Vichingo455 Date: Sun, 1 Jun 2025 11:44:20 +0200 Subject: [PATCH] Restore SEBPatch --- .editorconfig | 135 + .gitattributes | 63 + .github/ISSUE_TEMPLATE/bug-report.md | 35 + .github/ISSUE_TEMPLATE/config.yml | 5 + .github/ISSUE_TEMPLATE/feature-request.md | 20 + .github/workflows/issues.yml | 25 + .gitignore | 261 + LICENSE.txt | 373 + README.md | 16 + SECURITY.md | 35 + .../Events/IconChangedEventHandler.cs | 17 + .../Events/TitleChangedEventHandler.cs | 15 + .../Events/WindowsChangedEventHandler.cs | 15 + .../FactoryResult.cs | 31 + .../IApplication.cs | 71 + .../IApplicationFactory.cs | 23 + .../IApplicationWindow.cs | 50 + .../Properties/AssemblyInfo.cs | 33 + ...eExamBrowser.Applications.Contracts.csproj | 78 + .../ApplicationFactoryTests.cs | 126 + .../ExternalApplicationInstanceTests.cs | 62 + .../ExternalApplicationTests.cs | 216 + .../ExternalApplicationWindowTests.cs | 64 + .../Properties/AssemblyInfo.cs | 16 + ...eExamBrowser.Applications.UnitTests.csproj | 199 + .../app.config | 35 + .../packages.config | 23 + .../ApplicationFactory.cs | 147 + .../Events/InstanceTerminatedEventHandler.cs | 12 + .../ExternalApplication.cs | 174 + .../ExternalApplicationInstance.cs | 174 + .../ExternalApplicationWindow.cs | 60 + .../Properties/AssemblyInfo.cs | 35 + .../SafeExamBrowser.Applications.csproj | 96 + .../Events/DownloadEventArgs.cs | 36 + .../Events/DownloadFinishedCallback.cs | 16 + .../Events/DownloadRequestedEventHandler.cs | 15 + .../Events/LoseFocusRequestedEventHandler.cs | 15 + .../Events/TabPressedEventHandler.cs | 15 + .../TerminationRequestedEventHandler.cs | 15 + .../UserIdentifierDetectedEventHandler.cs | 15 + .../Filters/IRequestFilter.cs | 33 + .../Filters/IRule.cs | 33 + .../Filters/IRuleFactory.cs | 23 + .../Filters/Request.cs | 21 + .../IBrowserApplication.cs | 45 + .../IBrowserWindow.cs | 28 + .../Properties/AssemblyInfo.cs | 33 + .../SafeExamBrowser.Browser.Contracts.csproj | 84 + .../Filters/LegacyFilter.cs | 553 ++ .../Filters/RequestFilterTests.cs | 114 + .../Filters/RuleFactoryTests.cs | 42 + .../Filters/Rules/RegexRuleTests.cs | 67 + .../Filters/Rules/SimplifiedRuleTests.cs | 962 +++ .../Handlers/ContextMenuHandlerTests.cs | 46 + .../Handlers/DialogHandlerTests.cs | 106 + .../Handlers/DisplayHandlerTests.cs | 72 + .../Handlers/DownloadHandlerTests.cs | 311 + .../Handlers/KeyboardHandlerTests.cs | 166 + .../Handlers/RequestHandlerTests.cs | 313 + .../Handlers/ResourceHandlerTests.cs | 363 + .../Properties/AssemblyInfo.cs | 17 + .../SafeExamBrowser.Browser.UnitTests.csproj | 220 + SafeExamBrowser.Browser.UnitTests/app.config | 51 + .../packages.config | 26 + SafeExamBrowser.Browser/BrowserApplication.cs | 501 ++ SafeExamBrowser.Browser/BrowserControl.cs | 195 + .../BrowserIconResource.cs | 21 + SafeExamBrowser.Browser/BrowserWindow.cs | 788 ++ SafeExamBrowser.Browser/Clipboard.cs | 57 + SafeExamBrowser.Browser/Content/Api.js | 16 + .../Content/BlockedContent.html | 3 + .../Content/BlockedPage.html | 13 + SafeExamBrowser.Browser/Content/Clipboard.js | 195 + .../Content/ContentLoader.cs | 119 + SafeExamBrowser.Browser/Content/PageZoom.js | 16 + .../Events/ClipboardChangedEventHandler.cs | 12 + .../Events/DialogRequestedEventArgs.cs | 22 + .../Events/DialogRequestedEventHandler.cs | 12 + .../Events/DownloadAbortedEventHandler.cs | 12 + .../Events/DownloadUpdatedEventHandler.cs | 14 + .../Events/FaviconChangedEventHandler.cs | 12 + .../Events/PopupRequestedEventArgs.cs | 15 + .../Events/PopupRequestedEventHandler.cs | 12 + .../Events/ProgressChangedEventHandler.cs | 12 + .../Events/ResetRequestedEventHandler.cs | 12 + .../Events/UrlEventHandler.cs | 12 + .../Events/WindowClosedEventHandler.cs | 12 + .../Filters/RequestFilter.cs | 66 + .../Filters/RuleFactory.cs | 31 + .../Filters/Rules/RegexRule.cs | 52 + .../Filters/Rules/SimplifiedRule.cs | 196 + .../Handlers/ContextMenuHandler.cs | 34 + .../Handlers/DialogHandler.cs | 51 + .../Handlers/DisplayHandler.cs | 73 + .../Handlers/DownloadHandler.cs | 210 + .../Handlers/KeyboardHandler.cs | 93 + .../Handlers/RenderProcessMessageHandler.cs | 80 + .../Handlers/RequestHandler.cs | 220 + .../Handlers/ResourceHandler.cs | 451 ++ .../Properties/AssemblyInfo.cs | 35 + .../SafeExamBrowser.Browser.csproj | 218 + .../Wrapper/CefSharpBrowserControl.cs | 134 + .../Wrapper/CefSharpPopupControl.cs | 128 + .../Events/AuthCredentialsEventHandler.cs | 14 + .../Events/BeforeBrowseEventHandler.cs | 14 + .../Events/BeforeDownloadEventHandler.cs | 14 + .../Wrapper/Events/CanDownloadEventHandler.cs | 14 + .../Events/ContextCreatedEventHandler.cs | 14 + .../Events/ContextReleasedEventHandler.cs | 14 + .../Events/DownloadUpdatedEventHandler.cs | 14 + .../Events/FaviconUrlChangedEventHandler.cs | 15 + .../Events/FileDialogRequestedEventHandler.cs | 15 + .../Events/FocusedNodeChangedEventHandler.cs | 14 + .../Wrapper/Events/GenericEventArgs.cs | 15 + .../Wrapper/Events/KeyEventHandler.cs | 14 + .../LoadingProgressChangedEventHandler.cs | 14 + .../Events/OpenUrlFromTabEventHandler.cs | 14 + .../Wrapper/Events/PreKeyEventHandler.cs | 14 + .../Events/ResourceRequestEventArgs.cs | 17 + .../Events/ResourceRequestEventHandler.cs | 14 + .../Events/UncaughtExceptionEventHandler.cs | 14 + SafeExamBrowser.Browser/Wrapper/Extensions.cs | 38 + .../Wrapper/Handlers/DialogHandlerSwitch.cs | 36 + .../Wrapper/Handlers/DisplayHandlerSwitch.cs | 55 + .../Wrapper/Handlers/DownloadHandlerSwitch.cs | 70 + .../Wrapper/Handlers/KeyboardHandlerSwitch.cs | 56 + .../RenderProcessMessageHandlerSwitch.cs | 81 + .../Wrapper/Handlers/RequestHandlerSwitch.cs | 99 + .../Wrapper/ICefSharpControl.cs | 57 + SafeExamBrowser.Browser/app.config | 11 + SafeExamBrowser.Browser/packages.config | 10 + .../ClientControllerTests.cs | 1367 ++++ .../Communication/ClientHostTests.cs | 371 + .../CoordinatorTests.cs | 118 + .../AboutNotificationControllerTests.cs | 79 + .../LogNotificationControllerTests.cs | 79 + .../Operations/ApplicationOperationTests.cs | 382 + .../Operations/BrowserOperationTests.cs | 116 + .../ClientHostDisconnectionOperationTests.cs | 112 + .../Operations/ClipboardOperationTests.cs | 53 + .../Operations/ConfigurationOperationTests.cs | 74 + .../DisplayMonitorOperationTests.cs | 101 + .../KeyboardInterceptorOperationTests.cs | 54 + .../MouseInterceptorOperationTests.cs | 54 + .../Operations/ProctoringOperationTests.cs | 118 + .../RuntimeConnectionOperationTests.cs | 112 + .../Operations/ServerOperationTests.cs | 88 + .../Operations/ShellOperationTests.cs | 437 ++ .../Properties/AssemblyInfo.cs | 17 + .../SafeExamBrowser.Client.UnitTests.csproj | 260 + SafeExamBrowser.Client.UnitTests/app.config | 51 + .../packages.config | 26 + SafeExamBrowser.Client/App.config | 18 + SafeExamBrowser.Client/App.cs | 101 + SafeExamBrowser.Client/ClientContext.cs | 84 + SafeExamBrowser.Client/ClientController.cs | 1192 +++ .../Communication/ClientHost.cs | 111 + SafeExamBrowser.Client/CompositionRoot.cs | 396 + .../Contracts/ICoordinator.cs | 46 + SafeExamBrowser.Client/Coordinator.cs | 78 + .../Notifications/AboutNotification.cs | 63 + .../Notifications/LogNotification.cs | 63 + .../Operations/ApplicationOperation.cs | 204 + .../Operations/BrowserOperation.cs | 90 + .../ClientHostDisconnectionOperation.cs | 77 + .../Operations/ClientOperation.cs | 32 + .../Operations/ClipboardOperation.cs | 59 + .../Operations/ConfigurationOperation.cs | 56 + .../Operations/DisplayMonitorOperation.cs | 56 + ...pplicationInitializationFailedEventArgs.cs | 27 + .../Events/ApplicationNotFoundEventArgs.cs | 26 + .../Events/ApplicationTerminationEventArgs.cs | 25 + .../ApplicationTerminationFailedEventArgs.cs | 24 + .../KeyboardInterceptorOperation.cs | 51 + .../Operations/MouseInterceptorOperation.cs | 51 + .../Operations/ProctoringOperation.cs | 93 + .../Operations/RuntimeConnectionOperation.cs | 77 + .../Operations/ServerOperation.cs | 64 + .../Operations/ShellOperation.cs | 371 + .../Properties/AssemblyInfo.cs | 56 + .../Properties/Resources.Designer.cs | 63 + .../Properties/Resources.resx | 117 + .../Properties/Settings.Designer.cs | 26 + .../Properties/Settings.settings | 7 + .../SafeExamBrowser.Client.csproj | 271 + SafeExamBrowser.Client/SafeExamBrowser.ico | Bin 0 -> 370070 bytes SafeExamBrowser.Client/app.manifest | 34 + .../Data/AuthenticationResponse.cs | 24 + .../Data/ConfigurationResponse.cs | 25 + .../Data/ConnectionResponse.cs | 29 + .../Data/DisconnectionMessage.cs | 24 + .../Data/DisconnectionResponse.cs | 24 + .../Data/ExamSelectionReplyMessage.cs | 41 + .../Data/ExamSelectionRequestMessage.cs | 36 + .../Data/Message.cs | 29 + .../Data/MessageBoxReplyMessage.cs | 35 + .../Data/MessageBoxRequestMessage.cs | 53 + .../Data/PasswordReplyMessage.cs | 41 + .../Data/PasswordRequestMessage.cs | 35 + .../Data/PasswordRequestPurpose.cs | 31 + .../Data/ReconfigurationDeniedMessage.cs | 29 + .../Data/ReconfigurationMessage.cs | 35 + .../Data/Response.cs | 24 + .../Data/ServerFailureActionReplyMessage.cs | 47 + .../Data/ServerFailureActionRequestMessage.cs | 41 + .../Data/SessionStartMessage.cs | 30 + .../Data/SessionStopMessage.cs | 26 + .../Data/SimpleMessage.cs | 34 + .../Data/SimpleMessagePurport.cs | 59 + .../Data/SimpleResponse.cs | 34 + .../Data/SimpleResponsePurport.cs | 34 + .../Events/ClientConfigurationEventArgs.cs | 23 + .../Events/CommunicationEventArgs.cs | 17 + .../Events/CommunicationEventHandler.cs | 41 + .../Events/ExamSelectionReplyEventArgs.cs | 33 + .../Events/ExamSelectionRequestEventArgs.cs | 29 + .../Events/MessageBoxReplyEventArgs.cs | 28 + .../Events/MessageBoxRequestEventArgs.cs | 43 + .../Events/PasswordReplyEventArgs.cs | 33 + .../Events/PasswordRequestEventArgs.cs | 29 + .../Events/ReconfigurationEventArgs.cs | 26 + .../ServerFailureActionReplyEventArgs.cs | 38 + .../ServerFailureActionRequestEventArgs.cs | 33 + .../Events/SessionStartEventArgs.cs | 23 + .../Events/SessionStopEventArgs.cs | 23 + .../Hosts/IClientHost.cs | 69 + .../Hosts/IHostObject.cs | 19 + .../Hosts/IHostObjectFactory.cs | 21 + .../Hosts/IRuntimeHost.cs | 74 + .../Hosts/IServiceHost.cs | 33 + .../ICommunication.cs | 60 + .../ICommunicationHost.cs | 34 + .../ICommunicationProxy.cs | 41 + .../Interlocutor.cs | 39 + .../Properties/AssemblyInfo.cs | 33 + .../Proxies/CommunicationResult.cs | 43 + .../Proxies/IClientProxy.cs | 60 + .../Proxies/IProxyFactory.cs | 21 + .../Proxies/IProxyObject.cs | 19 + .../Proxies/IProxyObjectFactory.cs | 21 + .../Proxies/IRuntimeProxy.cs | 61 + .../Proxies/IServiceProxy.cs | 34 + ...ExamBrowser.Communication.Contracts.csproj | 122 + .../Hosts/BaseHostStub.cs | 55 + .../Hosts/BaseHostTests.cs | 293 + .../Properties/AssemblyInfo.cs | 17 + .../Proxies/BaseProxyImpl.cs | 64 + .../Proxies/BaseProxyTests.cs | 388 + .../Proxies/ClientProxyTests.cs | 246 + .../Proxies/RuntimeProxyTests.cs | 268 + .../Proxies/ServiceProxyTests.cs | 134 + ...ExamBrowser.Communication.UnitTests.csproj | 192 + .../app.config | 43 + .../packages.config | 24 + .../Hosts/BaseHost.cs | 258 + .../Hosts/HostObjectFactory.cs | 37 + .../Properties/AssemblyInfo.cs | 33 + .../Proxies/BaseProxy.cs | 293 + .../Proxies/ClientProxy.cs | 235 + .../Proxies/ProxyFactory.cs | 34 + .../Proxies/ProxyObjectFactory.cs | 27 + .../Proxies/RuntimeProxy.cs | 234 + .../Proxies/ServiceProxy.cs | 105 + .../SafeExamBrowser.Communication.csproj | 84 + .../AppConfig.cs | 207 + .../ClientConfiguration.cs | 35 + .../Cryptography/EncryptionParameters.cs | 17 + .../Cryptography/ICertificateStore.cs | 30 + .../Cryptography/IHashAlgorithm.cs | 21 + .../Cryptography/IKeyGenerator.cs | 36 + .../Cryptography/IPasswordEncryption.cs | 30 + .../Cryptography/IPublicKeyEncryption.cs | 31 + .../Cryptography/PasswordParameters.cs | 26 + .../Cryptography/PublicKeyParameters.cs | 33 + .../DataCompression/IDataCompressor.cs | 38 + .../DataFormats/FormatType.cs | 19 + .../DataFormats/IDataParser.cs | 29 + .../DataFormats/IDataSerializer.cs | 29 + .../DataFormats/ParseResult.cs | 39 + .../DataFormats/SerializeResult.cs | 28 + .../DataResources/IResourceLoader.cs | 29 + .../DataResources/IResourceSaver.cs | 29 + .../IConfigurationRepository.cs | 67 + .../Integrity/IIntegrityModule.cs | 46 + .../LoadStatus.cs | 46 + .../Properties/AssemblyInfo.cs | 33 + ...ExamBrowser.Configuration.Contracts.csproj | 91 + .../SaveStatus.cs | 36 + .../ServiceConfiguration.cs | 45 + .../SessionConfiguration.cs | 44 + .../ConfigurationData/DataProcessorTests.cs | 101 + .../ConfigurationData/TestDictionary1.bin | Bin 0 -> 12067 bytes .../ConfigurationData/TestDictionary2.bin | Bin 0 -> 13543 bytes .../ConfigurationData/TestDictionary3.bin | Bin 0 -> 13664 bytes .../ConfigurationRepositoryTests.cs | 348 + .../Cryptography/HashAlgorithmTests.cs | 34 + .../Cryptography/KeyGeneratorTests.cs | 62 + .../Cryptography/PasswordEncryptionTests.cs | 72 + .../Cryptography/PublicKeyEncryptionTests.cs | 94 + .../PublicKeySymmetricEncryptionTests.cs | 96 + .../DataCompression/GZipCompressorTests.cs | 100 + .../DataFormats/BinaryParserTests.cs | 168 + .../DataFormats/BinarySerializerTests.cs | 153 + .../DataFormats/XmlParserTests.cs | 239 + .../DataFormats/XmlSerializerTests.cs | 287 + .../DataFormats/XmlTestData.xml | 45 + .../DataFormats/XmlTestSettings.xml | 795 ++ .../Properties/AssemblyInfo.cs | 17 + ...ExamBrowser.Configuration.UnitTests.csproj | 208 + .../SubStreamTests.cs | 187 + .../app.config | 43 + .../packages.config | 24 + .../ConfigurationData/DataMapper.cs | 50 + .../DataMapping/ApplicationDataMapper.cs | 176 + .../DataMapping/AudioDataMapper.cs | 58 + .../DataMapping/BaseDataMapper.cs | 19 + .../DataMapping/BrowserDataMapper.cs | 1036 +++ .../ConfigurationFileDataMapper.cs | 48 + .../DataMapping/DisplayDataMapper.cs | 75 + .../DataMapping/GeneralDataMapper.cs | 36 + .../DataMapping/InputDataMapper.cs | 316 + .../DataMapping/ProctoringDataMapper.cs | 225 + .../DataMapping/SecurityDataMapper.cs | 263 + .../DataMapping/ServerDataMapper.cs | 129 + .../DataMapping/ServiceDataMapper.cs | 249 + .../DataMapping/SystemDataMapper.cs | 33 + .../DataMapping/UserInterfaceDataMapper.cs | 148 + .../ConfigurationData/DataProcessor.cs | 101 + .../ConfigurationData/DataValues.cs | 311 + .../ConfigurationData/Json.cs | 107 + .../ConfigurationData/Keys.cs | 371 + .../ConfigurationRepository.cs | 259 + .../Cryptography/CertificateStore.cs | 122 + .../Cryptography/HashAlgorithm.cs | 31 + .../Cryptography/KeyGenerator.cs | 129 + .../Cryptography/PasswordEncryption.cs | 223 + .../Cryptography/PublicKeyEncryption.cs | 167 + .../PublicKeySymmetricEncryption.cs | 129 + .../DataCompression/GZipCompressor.cs | 120 + .../DataFormats/BinaryBlock.cs | 19 + .../DataFormats/BinaryParser.cs | 211 + .../DataFormats/BinarySerializer.cs | 162 + .../DataFormats/XmlElement.cs | 25 + .../DataFormats/XmlParser.cs | 301 + .../DataFormats/XmlSerializer.cs | 199 + .../DataResources/FileResourceLoader.cs | 51 + .../DataResources/FileResourceSaver.cs | 65 + .../DataResources/NetworkResourceLoader.cs | 216 + .../Integrity/IntegrityModule.cs | 253 + .../Properties/AssemblyInfo.cs | 35 + .../SafeExamBrowser.Configuration.csproj | 115 + SafeExamBrowser.Configuration/SubStream.cs | 140 + .../Events/NotificationChangedEventHandler.cs | 15 + .../Notifications/INotification.cs | 49 + .../Events/ActionRequiredEventArgs.cs | 17 + .../Events/ActionRequiredEventHandler.cs | 15 + .../Events/ProgressChangedEventArgs.cs | 41 + .../Events/ProgressChangedEventHandler.cs | 15 + .../Events/StatusChangedEventHandler.cs | 17 + .../OperationModel/IOperation.cs | 38 + .../OperationModel/IOperationSequence.cs | 52 + .../OperationModel/IRepeatableOperation.cs | 21 + .../IRepeatableOperationSequence.cs | 26 + .../OperationModel/OperationResult.cs | 31 + .../Properties/AssemblyInfo.cs | 33 + .../Resources/Icons/BitmapIconResource.cs | 23 + .../Resources/Icons/EmbeddedIconResource.cs | 21 + .../Resources/Icons/IconResource.cs | 17 + .../Resources/Icons/NativeIconResource.cs | 23 + .../Resources/Icons/XamlIconResource.cs | 23 + .../SafeExamBrowser.Core.Contracts.csproj | 84 + .../OperationModel/OperationSequenceTests.cs | 471 ++ .../OperationModel/QueueExtensionTests.cs | 36 + .../RepeatableOperationSequenceTests.cs | 179 + .../CommunicationHostOperationTests.cs | 111 + .../Operations/DelegateOperationTests.cs | 79 + .../Operations/I18nOperationTests.cs | 61 + .../LazyInitializationOperationTests.cs | 163 + .../Properties/AssemblyInfo.cs | 17 + .../SafeExamBrowser.Core.UnitTests.csproj | 197 + SafeExamBrowser.Core.UnitTests/app.config | 43 + .../packages.config | 24 + .../OperationModel/OperationSequence.cs | 163 + .../OperationModel/QueueExtensions.cs | 24 + .../RepeatableOperationSequence.cs | 72 + .../Operations/CommunicationHostOperation.cs | 69 + .../Operations/DelegateOperation.cs | 56 + .../Operations/I18nOperation.cs | 47 + .../Operations/LazyInitializationOperation.cs | 91 + .../Properties/AssemblyInfo.cs | 35 + .../SafeExamBrowser.Core.csproj | 88 + SafeExamBrowser.I18n.Contracts/IText.cs | 26 + .../ITextResource.cs | 23 + .../Properties/AssemblyInfo.cs | 33 + .../SafeExamBrowser.I18n.Contracts.csproj | 64 + SafeExamBrowser.I18n.Contracts/TextKey.cs | 277 + .../Properties/AssemblyInfo.cs | 17 + .../SafeExamBrowser.I18n.UnitTests.csproj | 193 + SafeExamBrowser.I18n.UnitTests/TextTests.cs | 46 + .../Text_Incompatible.xml | 6 + .../Text_Invalid.txt | 13 + SafeExamBrowser.I18n.UnitTests/Text_Valid.xml | 9 + .../XmlTextResourceTests.cs | 98 + SafeExamBrowser.I18n.UnitTests/app.config | 43 + .../packages.config | 24 + SafeExamBrowser.I18n/Data/de.xml | 780 ++ SafeExamBrowser.I18n/Data/en.xml | 780 ++ SafeExamBrowser.I18n/Data/es.xml | 780 ++ SafeExamBrowser.I18n/Data/et.xml | 780 ++ SafeExamBrowser.I18n/Data/fr.xml | 780 ++ SafeExamBrowser.I18n/Data/id.xml | 780 ++ SafeExamBrowser.I18n/Data/it.xml | 780 ++ SafeExamBrowser.I18n/Data/nl.xml | 780 ++ SafeExamBrowser.I18n/Data/ru.xml | 781 ++ SafeExamBrowser.I18n/Data/zh.xml | 780 ++ .../Properties/AssemblyInfo.cs | 33 + .../SafeExamBrowser.I18n.csproj | 109 + SafeExamBrowser.I18n/Text.cs | 77 + SafeExamBrowser.I18n/XmlTextResource.cs | 52 + .../FeatureConfigurationStatus.cs | 31 + .../IAutoRestoreMechanism.cs | 26 + .../IFeatureConfiguration.cs | 59 + .../IFeatureConfigurationBackup.cs | 39 + .../IFeatureConfigurationFactory.cs | 94 + .../IFeatureConfigurationMonitor.cs | 31 + .../ISystemConfigurationUpdate.cs | 26 + .../Properties/AssemblyInfo.cs | 33 + .../SafeExamBrowser.Lockdown.Contracts.csproj | 68 + .../AutoRestoreMechanismTests.cs | 158 + .../FeatureConfigurationBackupTests.cs | 198 + .../FeatureConfigurationMonitorTests.cs | 196 + .../FeatureConfigurationStub.cs | 55 + .../Properties/AssemblyInfo.cs | 17 + .../SafeExamBrowser.Lockdown.UnitTests.csproj | 179 + SafeExamBrowser.Lockdown.UnitTests/app.config | 39 + .../packages.config | 23 + .../AutoRestoreMechanism.cs | 164 + .../FeatureConfigurationBackup.cs | 140 + .../FeatureConfigurationFactory.cs | 119 + .../FeatureConfigurationMonitor.cs | 148 + .../FeatureConfiguration.cs | 50 + .../MachineHive/EaseOfAccessConfiguration.cs | 37 + .../MachineHive/MachineHiveConfiguration.cs | 29 + .../MachinePowerOptionsConfiguration.cs | 32 + .../NetworkOptionsConfiguration.cs | 32 + .../RemoteConnectionConfiguration.cs | 39 + .../MachineHive/SwitchUserConfiguration.cs | 32 + .../RegistryConfiguration.cs | 245 + .../RegistryConfigurationItem.cs | 26 + .../RegistryDataItem.cs | 25 + .../UserHive/ChangePasswordConfiguration.cs | 32 + .../ChromeNotificationConfiguration.cs | 40 + .../UserHive/FindPrinterConfiguration.cs | 32 + .../UserHive/LockWorkstationConfiguration.cs | 32 + .../UserHive/SignoutConfiguration.cs | 32 + .../UserHive/TaskManagerConfiguration.cs | 32 + .../UserHive/UserHiveConfiguration.cs | 50 + .../UserHive/UserPowerOptionsConfiguration.cs | 32 + .../UserHive/VmwareOverlayConfiguration.cs | 33 + .../ServiceConfiguration.cs | 319 + .../ServiceConfigurationItem.cs | 24 + .../ServiceConfigurations/ServiceDataItem.cs | 24 + .../ServiceConfigurations/ServiceStatus.cs | 17 + .../WindowsUpdateConfiguration.cs | 32 + .../Properties/AssemblyInfo.cs | 35 + .../SafeExamBrowser.Lockdown.csproj | 102 + .../SystemConfigurationUpdate.cs | 59 + .../ILogContent.cs | 19 + .../ILogContentFormatter.cs | 21 + .../ILogMessage.cs | 39 + .../ILogObserver.cs | 21 + SafeExamBrowser.Logging.Contracts/ILogText.cs | 21 + SafeExamBrowser.Logging.Contracts/ILogger.cs | 78 + .../IModuleLogger.cs | 21 + .../IThreadInfo.cs | 33 + .../Properties/AssemblyInfo.cs | 33 + .../SafeExamBrowser.Logging.Contracts.csproj | 75 + .../DefaultLogFormatterTests.cs | 51 + .../LoggerTests.cs | 242 + .../ModuleLoggerTests.cs | 70 + .../NewLogContentType.cs | 21 + .../Properties/AssemblyInfo.cs | 17 + .../SafeExamBrowser.Logging.UnitTests.csproj | 184 + SafeExamBrowser.Logging.UnitTests/app.config | 43 + .../packages.config | 24 + .../DefaultLogFormatter.cs | 45 + SafeExamBrowser.Logging/LogFileWriter.cs | 53 + SafeExamBrowser.Logging/LogMessage.cs | 38 + SafeExamBrowser.Logging/LogText.cs | 30 + SafeExamBrowser.Logging/Logger.cs | 190 + SafeExamBrowser.Logging/ModuleLogger.cs | 88 + .../Properties/AssemblyInfo.cs | 33 + .../SafeExamBrowser.Logging.csproj | 78 + SafeExamBrowser.Logging/ThreadInfo.cs | 38 + .../Applications/ActiveApplication.cs | 34 + .../Events/ExplorerStartedEventHandler.cs | 15 + .../Events/InstanceStartedEventHandler.cs | 18 + .../Events/TerminationFailedEventHandler.cs | 17 + .../Applications/IApplicationMonitor.cs | 60 + .../Applications/IWindow.cs | 28 + .../Applications/InitializationResult.cs | 34 + .../Applications/RunningApplication.cs | 35 + .../Events/DisplayChangedEventHandler.cs | 15 + .../Display/IDisplayMonitor.cs | 49 + .../Display/ValidationResult.cs | 31 + .../IClipboard.cs | 28 + .../IRemoteSessionDetector.cs | 21 + .../IVirtualMachineDetector.cs | 21 + .../Keyboard/IKeyboardInterceptor.cs | 26 + .../Mouse/IMouseInterceptor.cs | 26 + .../Properties/AssemblyInfo.cs | 33 + ...afeExamBrowser.Monitoring.Contracts.csproj | 91 + .../System/Events/SentinelEventArgs.cs | 21 + .../System/Events/SentinelEventHandler.cs | 15 + .../Events/SessionChangedEventHandler.cs | 15 + .../System/ISystemSentinel.cs | 88 + .../Applications/ApplicationMonitor.cs | 409 + .../Applications/Window.cs | 24 + SafeExamBrowser.Monitoring/Clipboard.cs | 74 + SafeExamBrowser.Monitoring/Display/Bounds.cs | 20 + SafeExamBrowser.Monitoring/Display/Display.cs | 18 + .../Display/DisplayMonitor.cs | 243 + .../Display/VideoOutputTechnology.cs | 41 + .../Keyboard/KeyboardInterceptor.cs | 62 + .../Mouse/MouseInterceptor.cs | 52 + .../Properties/AssemblyInfo.cs | 33 + .../RemoteSessionDetector.cs | 33 + .../SafeExamBrowser.Monitoring.csproj | 102 + .../System/Components/Cursors.cs | 102 + .../System/Components/EaseOfAccess.cs | 71 + .../System/Components/StickyKeys.cs | 124 + .../System/Components/SystemEvents.cs | 96 + .../System/SystemSentinel.cs | 95 + .../VirtualMachineDetector.cs | 64 + .../Events/ProctoringEventHandler.cs | 15 + .../Events/RemainingWorkUpdatedEventArgs.cs | 58 + .../RemainingWorkUpdatedEventHandler.cs | 15 + .../IProctoringController.cs | 76 + .../Properties/AssemblyInfo.cs | 32 + ...afeExamBrowser.Proctoring.Contracts.csproj | 75 + .../ProctoringController.cs | 211 + .../ProctoringFactory.cs | 70 + .../ProctoringImplementation.cs | 61 + .../Properties/AssemblyInfo.cs | 32 + .../SafeExamBrowser.Proctoring.csproj | 173 + .../ScreenProctoring/Buffer.cs | 92 + .../ScreenProctoring/Cache.cs | 241 + .../ScreenProctoring/Data/IntervalTrigger.cs | 15 + .../ScreenProctoring/Data/KeyboardTrigger.cs | 20 + .../Data/MetaDataAggregator.cs | 171 + .../ScreenProctoring/Data/Metadata.cs | 39 + .../ScreenProctoring/Data/MouseTrigger.cs | 19 + .../ScreenProctoring/DataCollector.cs | 177 + .../Events/DataCollectedEventHandler.cs | 15 + .../ScreenProctoring/Imaging/Extensions.cs | 93 + .../Imaging/ProcessingOrder.cs | 16 + .../ScreenProctoring/Imaging/ScreenShot.cs | 32 + .../Imaging/ScreenShotProcessor.cs | 160 + .../ScreenProctoringImplementation.cs | 212 + .../ScreenProctoring/Service/Api.cs | 28 + .../ScreenProctoring/Service/Parser.cs | 119 + .../Service/Requests/ContentType.cs | 17 + .../Service/Requests/CreateSessionRequest.cs | 36 + .../Service/Requests/Extensions.cs | 40 + .../Service/Requests/Header.cs | 31 + .../Service/Requests/HealthRequest.cs | 36 + .../Service/Requests/OAuth2TokenRequest.cs | 28 + .../Service/Requests/Request.cs | 181 + .../Service/Requests/ScreenShotRequest.cs | 61 + .../Requests/TerminateSessionRequest.cs | 30 + .../ScreenProctoring/Service/ServiceProxy.cs | 129 + .../Service/ServiceResponse.cs | 32 + .../ScreenProctoring/TransmissionSpooler.cs | 421 + SafeExamBrowser.Proctoring/packages.config | 7 + SafeExamBrowser.ResetUtility/App.config | 14 + .../CompositionRoot.cs | 93 + SafeExamBrowser.ResetUtility/NativeMethods.cs | 52 + .../Procedure/Initialization.cs | 96 + SafeExamBrowser.ResetUtility/Procedure/Log.cs | 143 + .../Procedure/MainMenu.cs | 32 + .../Procedure/MainMenuOption.cs | 16 + .../Procedure/MenuOption.cs | 21 + .../Procedure/ProcedureContext.cs | 26 + .../Procedure/ProcedureStep.cs | 207 + .../Procedure/ProcedureStepResult.cs | 16 + .../Procedure/Reset.cs | 156 + .../Procedure/Restore.cs | 163 + .../Procedure/Version.cs | 46 + SafeExamBrowser.ResetUtility/Program.cs | 41 + .../Properties/AssemblyInfo.cs | 33 + SafeExamBrowser.ResetUtility/ResetUtility.ico | Bin 0 -> 58686 bytes .../SafeExamBrowser.ResetUtility.csproj | 126 + SafeExamBrowser.ResetUtility/app.manifest | 11 + .../Communication/RuntimeHostTests.cs | 385 + .../Operations/ClientOperationTests.cs | 236 + .../ClientTerminationOperationTests.cs | 138 + .../Operations/ConfigurationOperationTests.cs | 647 ++ .../Operations/DisclaimerOperationTests.cs | 190 + .../DisplayMonitorOperationTests.cs | 124 + .../Operations/KioskModeOperationTests.cs | 487 ++ .../Operations/RemoteSessionOperationTests.cs | 205 + .../Operations/ServerOperationTests.cs | 660 ++ .../Operations/ServiceOperationTests.cs | 564 ++ .../SessionActivationOperationTests.cs | 97 + .../SessionInitializationOperationTests.cs | 101 + .../Operations/Testdata/SebClientSettings.seb | 1 + .../VirtualMachineOperationTests.cs | 141 + .../Properties/AssemblyInfo.cs | 17 + .../RuntimeControllerTests.cs | 773 ++ .../SafeExamBrowser.Runtime.UnitTests.csproj | 242 + SafeExamBrowser.Runtime.UnitTests/app.config | 51 + .../packages.config | 24 + SafeExamBrowser.Runtime/App.config | 18 + SafeExamBrowser.Runtime/App.cs | 91 + .../Communication/RuntimeHost.cs | 109 + SafeExamBrowser.Runtime/CompositionRoot.cs | 208 + .../ApplicationIntegrityOperation.cs | 60 + .../Operations/ClientOperation.cs | 270 + .../Operations/ClientTerminationOperation.cs | 44 + .../Operations/ConfigurationBaseOperation.cs | 91 + .../Operations/ConfigurationOperation.cs | 452 ++ .../Operations/DisclaimerOperation.cs | 86 + .../Operations/DisplayMonitorOperation.cs | 87 + .../ClientConfigurationErrorMessageArgs.cs | 23 + .../Events/ConfigurationCompletedEventArgs.cs | 17 + .../Events/ExamSelectionEventArgs.cs | 26 + .../Events/InvalidDataMessageArgs.cs | 24 + .../Events/InvalidPasswordMessageArgs.cs | 23 + .../Operations/Events/MessageEventArgs.cs | 33 + .../Events/NotSupportedMessageArgs.cs | 24 + .../Events/PasswordRequiredEventArgs.cs | 20 + .../Events/ServerFailureEventArgs.cs | 27 + .../Events/UnexpectedErrorMessageArgs.cs | 24 + .../Events/VersionRestrictionMessageArgs.cs | 25 + .../Operations/KioskModeOperation.cs | 183 + .../Operations/RemoteSessionOperation.cs | 71 + .../Operations/ServerOperation.cs | 292 + .../Operations/ServiceOperation.cs | 293 + .../Operations/SessionActivationOperation.cs | 77 + .../SessionInitializationOperation.cs | 83 + .../Operations/SessionIntegrityOperation.cs | 136 + .../Operations/SessionOperation.cs | 33 + .../Operations/VersionRestrictionOperation.cs | 164 + .../Operations/VirtualMachineOperation.cs | 72 + .../Properties/AssemblyInfo.cs | 53 + .../Properties/Resources.Designer.cs | 63 + .../Properties/Resources.resx | 117 + .../Properties/Settings.Designer.cs | 26 + .../Properties/Settings.settings | 7 + SafeExamBrowser.Runtime/RuntimeController.cs | 737 ++ .../SafeExamBrowser.Runtime.csproj | 282 + SafeExamBrowser.Runtime/SafeExamBrowser.ico | Bin 0 -> 370070 bytes SafeExamBrowser.Runtime/SessionContext.cs | 50 + SafeExamBrowser.Runtime/app.manifest | 26 + SafeExamBrowser.Runtime/packages.config | 4 + .../Data/ConnectionInfo.cs | 31 + SafeExamBrowser.Server.Contracts/Data/Exam.cs | 36 + .../Data/ServerResponse.cs | 49 + .../Events/LockScreenRequestedEventHandler.cs | 16 + .../Events/Proctoring/InstructionEventArgs.cs | 18 + .../Events/Proctoring/InstructionMethod.cs | 26 + .../Events/Proctoring/JitsiMeetInstruction.cs | 20 + ...toringConfigurationReceivedEventHandler.cs | 15 + ...octoringInstructionReceivedEventHandler.cs | 15 + .../Proctoring/ScreenProctoringInstruction.cs | 22 + .../Events/Proctoring/ZoomInstruction.cs | 23 + .../Events/ServerEventHandler.cs | 15 + .../TerminationRequestedEventHandler.cs | 15 + .../IServerProxy.cs | 128 + .../Properties/AssemblyInfo.cs | 33 + .../SafeExamBrowser.Server.Contracts.csproj | 82 + SafeExamBrowser.Server/Data/ApiVersion1.cs | 19 + SafeExamBrowser.Server/Data/AttributeType.cs | 17 + SafeExamBrowser.Server/Data/Attributes.cs | 23 + SafeExamBrowser.Server/Data/Instructions.cs | 19 + SafeExamBrowser.Server/Extensions.cs | 58 + SafeExamBrowser.Server/FileSystem.cs | 59 + SafeExamBrowser.Server/Parser.cs | 414 + .../Properties/AssemblyInfo.cs | 33 + SafeExamBrowser.Server/Requests/ApiRequest.cs | 42 + .../Requests/AppSignatureKeyRequest.cs | 37 + .../Requests/AvailableExamsRequest.cs | 63 + .../Requests/BaseRequest.cs | 213 + .../Requests/ConfirmLockScreenRequest.cs | 45 + .../Requests/ContentType.cs | 16 + .../Requests/DisconnectionRequest.cs | 37 + .../Requests/ExamConfigurationRequest.cs | 39 + SafeExamBrowser.Server/Requests/Header.cs | 19 + .../Requests/LockScreenRequest.cs | 46 + SafeExamBrowser.Server/Requests/LogRequest.cs | 42 + .../Requests/LowerHandRequest.cs | 45 + .../Requests/NetworkAdapterRequest.cs | 52 + .../Requests/OAuth2TokenRequest.cs | 32 + .../Requests/PingRequest.cs | 45 + .../Requests/PowerSupplyRequest.cs | 64 + .../Requests/RaiseHandRequest.cs | 46 + .../Requests/SelectExamRequest.cs | 41 + .../Requests/UserIdentifierRequest.cs | 38 + .../SafeExamBrowser.Server.csproj | 117 + SafeExamBrowser.Server/ServerProxy.cs | 536 ++ SafeExamBrowser.Server/packages.config | 4 + .../Communication/ServiceHostTests.cs | 167 + .../Operations/EventStub.cs | 26 + .../Operations/LockdownOperationTests.cs | 259 + .../Operations/RestoreOperationTests.cs | 58 + .../ServiceEventCleanupOperationTests.cs | 68 + .../SessionActivationOperationTests.cs | 62 + .../SessionInitializationOperationTests.cs | 139 + .../Properties/AssemblyInfo.cs | 17 + .../SafeExamBrowser.Service.UnitTests.csproj | 205 + .../ServiceControllerTests.cs | 264 + SafeExamBrowser.Service.UnitTests/app.config | 39 + .../packages.config | 23 + SafeExamBrowser.Service/App.config | 6 + .../Communication/ServiceHost.cs | 79 + SafeExamBrowser.Service/CompositionRoot.cs | 126 + SafeExamBrowser.Service/Installer.cs | 35 + .../Operations/LockdownOperation.cs | 166 + .../Operations/RestoreOperation.cs | 48 + .../ServiceEventCleanupOperation.cs | 46 + .../Operations/SessionActivationOperation.cs | 46 + .../SessionInitializationOperation.cs | 85 + .../Operations/SessionOperation.cs | 32 + .../Properties/AssemblyInfo.cs | 35 + .../SafeExamBrowser.Service.csproj | 134 + SafeExamBrowser.Service/SafeExamBrowser.ico | Bin 0 -> 370070 bytes SafeExamBrowser.Service/Service.cs | 49 + SafeExamBrowser.Service/ServiceController.cs | 227 + SafeExamBrowser.Service/SessionContext.cs | 40 + SafeExamBrowser.Settings/AppSettings.cs | 127 + .../Applications/ApplicationSettings.cs | 36 + .../Applications/BlacklistApplication.cs | 34 + .../Applications/WhitelistApplication.cs | 91 + .../Browser/BrowserSettings.cs | 239 + .../Browser/Filter/FilterResult.cs | 26 + .../Browser/Filter/FilterRuleSettings.cs | 34 + .../Browser/Filter/FilterRuleType.cs | 26 + .../Browser/FilterSettings.cs | 41 + .../Browser/PopupPolicy.cs | 41 + .../Browser/Proxy/ProxyConfiguration.cs | 49 + .../Browser/Proxy/ProxyPolicy.cs | 26 + .../Browser/Proxy/ProxyProtocol.cs | 21 + .../Browser/ProxySettings.cs | 57 + SafeExamBrowser.Settings/Browser/UrlPolicy.cs | 55 + .../Browser/WindowPosition.cs | 20 + .../Browser/WindowSettings.cs | 99 + SafeExamBrowser.Settings/ConfigurationMode.cs | 28 + SafeExamBrowser.Settings/Logging/LogLevel.cs | 36 + .../Monitoring/DisplaySettings.cs | 40 + .../Monitoring/KeyboardSettings.cs | 129 + .../Monitoring/MouseSettings.cs | 29 + .../Proctoring/ImageFormat.cs | 36 + .../Proctoring/ImageQuantization.cs | 51 + .../Proctoring/MetaDataSettings.cs | 34 + .../Proctoring/ProctoringSettings.cs | 49 + .../Proctoring/ScreenProctoringSettings.cs | 79 + .../Properties/AssemblyInfo.cs | 33 + .../SafeExamBrowser.Settings.csproj | 106 + .../Security/ClipboardPolicy.cs | 31 + .../Security/KioskMode.cs | 31 + .../Security/SecuritySettings.cs | 96 + .../Security/VersionRestriction.cs | 54 + .../Security/VirtualMachinePolicy.cs | 26 + .../Server/ServerSettings.cs | 79 + .../Service/ServicePolicy.cs | 31 + .../Service/ServiceSettings.cs | 96 + SafeExamBrowser.Settings/SessionMode.cs | 26 + .../System/SystemSettings.cs | 25 + .../SystemComponents/AudioSettings.cs | 34 + .../SystemComponents/PowerSupplySettings.cs | 29 + .../UserInterface/ActionCenterSettings.cs | 54 + .../UserInterface/LockScreenSettings.cs | 24 + .../UserInterface/TaskbarSettings.cs | 54 + .../UserInterface/UserInterfaceMode.cs | 26 + .../UserInterface/UserInterfaceSettings.cs | 46 + .../Audio/Events/VolumeChangedEventHandler.cs | 15 + .../Audio/IAudio.cs | 63 + .../IFileSystem.cs | 31 + .../ISystemComponent.cs | 26 + .../ISystemInfo.cs | 74 + .../IUserInfo.cs | 31 + .../Events/LayoutChangedEventHandler.cs | 15 + .../Keyboard/IKeyboard.cs | 35 + .../Keyboard/IKeyboardLayout.cs | 43 + .../Network/ConnectionStatus.cs | 36 + .../Network/ConnectionType.cs | 31 + .../Network/Events/ChangedEventHandler.cs | 15 + .../Events/CredentialsRequiredEventArgs.cs | 36 + .../Events/CredentialsRequiredEventHandler.cs | 15 + .../Network/INetworkAdapter.cs | 59 + .../Network/IWirelessNetwork.cs | 31 + .../OperatingSystem.cs | 23 + .../PowerSupply/BatteryChargeStatus.cs | 33 + .../Events/StatusChangedEventHandler.cs | 15 + .../PowerSupply/IPowerSupply.cs | 28 + .../PowerSupply/IPowerSupplyStatus.cs | 38 + .../Properties/AssemblyInfo.cs | 33 + .../RegistryValueChangedEventHandler.cs | 15 + .../Registry/IRegistry.cs | 54 + .../Registry/RegistryValue.cs | 56 + ...mBrowser.SystemComponents.Contracts.csproj | 86 + .../Audio/Audio.cs | 159 + .../FileSystem.cs | 39 + .../Keyboard/Keyboard.cs | 105 + .../Keyboard/KeyboardLayout.cs | 35 + .../Network/Extensions.cs | 46 + .../Network/NetworkAdapter.cs | 381 + .../Network/WirelessNetwork.cs | 22 + .../PowerSupply/PowerSupply.cs | 93 + .../PowerSupply/PowerSupplyStatus.cs | 21 + .../Properties/AssemblyInfo.cs | 33 + .../Registry/Registry.cs | 248 + .../SafeExamBrowser.SystemComponents.csproj | 109 + .../SystemInfo.cs | 291 + SafeExamBrowser.SystemComponents/UserInfo.cs | 112 + SafeExamBrowser.SystemComponents/app.config | 11 + .../Browser/Data/DownloadItemState.cs | 53 + .../Browser/Data/JavascriptResult.cs | 31 + .../Events/AddressChangedEventHandler.cs | 15 + .../Events/FindRequestedEventHandler.cs | 15 + .../Browser/Events/LoadFailedEventHandler.cs | 15 + .../Events/LoadingStateChangedEventHandler.cs | 15 + .../Events/TitleChangedEventHandler.cs | 15 + .../Browser/IBrowserControl.cs | 111 + .../Browser/IBrowserWindow.cs | 149 + .../Events/ActionRequestedEventHandler.cs | 15 + .../FileSystemDialogResult.cs | 26 + .../FileSystemDialog/FileSystemElement.cs | 26 + .../FileSystemDialog/FileSystemOperation.cs | 26 + .../FileSystemDialog/IFileSystemDialog.cs | 28 + .../IProgressIndicator.cs | 48 + .../IUserInterfaceFactory.cs | 152 + .../MessageBox/IMessageBox.cs | 29 + .../MessageBox/MessageBoxAction.cs | 20 + .../MessageBox/MessageBoxIcon.cs | 21 + .../MessageBox/MessageBoxResult.cs | 22 + .../Events/FullScreenChangedEventHandler.cs | 15 + .../Proctoring/IProctoringControl.cs | 24 + .../IProctoringFinalizationDialog.cs | 28 + .../Proctoring/IProctoringWindow.cs | 34 + .../Properties/AssemblyInfo.cs | 33 + ...ExamBrowser.UserInterface.Contracts.csproj | 158 + .../Shell/Events/ActivatorEventHandler.cs | 15 + .../Events/QuitButtonClickedEventHandler.cs | 17 + .../Shell/IActionCenter.cs | 84 + .../Shell/IActionCenterActivator.cs | 33 + .../Shell/IActivator.cs | 36 + .../Shell/IApplicationControl.cs | 17 + .../Shell/INotificationControl.cs | 17 + .../Shell/ISystemControl.cs | 21 + .../Shell/ITaskView.cs | 28 + .../Shell/ITaskViewActivator.cs | 33 + .../Shell/ITaskbar.cs | 90 + .../Shell/ITaskbarActivator.cs | 23 + .../Shell/ITerminationActivator.cs | 23 + .../Shell/Location.cs | 26 + .../Windows/Data/CredentialsDialogPurpose.cs | 26 + .../Windows/Data/CredentialsDialogResult.cs | 31 + .../Windows/Data/ExamSelectionDialogResult.cs | 28 + .../Windows/Data/LockScreenOption.cs | 33 + .../Windows/Data/LockScreenResult.cs | 33 + .../Windows/Data/PasswordDialogResult.cs | 26 + .../Windows/Data/ServerFailureDialogResult.cs | 36 + .../Events/WindowClosedEventHandler.cs | 15 + .../Events/WindowClosingEventHandler.cs | 15 + .../Windows/ICredentialsDialog.cs | 23 + .../Windows/IExamSelectionDialog.cs | 23 + .../Windows/ILockScreen.cs | 33 + .../Windows/IPasswordDialog.cs | 23 + .../Windows/IRuntimeWindow.cs | 34 + .../Windows/IServerFailureDialog.cs | 23 + .../Windows/ISplashScreen.cs | 23 + .../Windows/IWindow.cs | 48 + .../ActionCenter/ApplicationButton.xaml | 24 + .../ActionCenter/ApplicationButton.xaml.cs | 69 + .../ActionCenter/ApplicationControl.xaml | 27 + .../ActionCenter/ApplicationControl.xaml.cs | 70 + .../Controls/ActionCenter/AudioControl.xaml | 45 + .../ActionCenter/AudioControl.xaml.cs | 194 + .../Controls/ActionCenter/Clock.xaml | 36 + .../Controls/ActionCenter/Clock.xaml.cs | 32 + .../ActionCenter/KeyboardLayoutButton.xaml | 37 + .../ActionCenter/KeyboardLayoutButton.xaml.cs | 51 + .../ActionCenter/KeyboardLayoutControl.xaml | 37 + .../KeyboardLayoutControl.xaml.cs | 141 + .../Controls/ActionCenter/NetworkButton.xaml | 30 + .../ActionCenter/NetworkButton.xaml.cs | 43 + .../Controls/ActionCenter/NetworkControl.xaml | 43 + .../ActionCenter/NetworkControl.xaml.cs | 177 + .../ActionCenter/NotificationButton.xaml | 28 + .../ActionCenter/NotificationButton.xaml.cs | 51 + .../ActionCenter/PowerSupplyControl.xaml | 51 + .../ActionCenter/PowerSupplyControl.xaml.cs | 128 + .../Controls/ActionCenter/QuitButton.xaml | 28 + .../Controls/ActionCenter/QuitButton.xaml.cs | 37 + .../ActionCenter/RaiseHandControl.xaml | 42 + .../ActionCenter/RaiseHandControl.xaml.cs | 159 + .../Controls/Browser/DownloadItemControl.xaml | 22 + .../Browser/DownloadItemControl.xaml.cs | 56 + .../Controls/Taskbar/ApplicationControl.xaml | 31 + .../Taskbar/ApplicationControl.xaml.cs | 118 + .../Taskbar/ApplicationWindowButton.xaml | 24 + .../Taskbar/ApplicationWindowButton.xaml.cs | 58 + .../Controls/Taskbar/AudioControl.xaml | 39 + .../Controls/Taskbar/AudioControl.xaml.cs | 226 + .../Controls/Taskbar/Clock.xaml | 17 + .../Controls/Taskbar/Clock.xaml.cs | 32 + .../Taskbar/KeyboardLayoutButton.xaml | 35 + .../Taskbar/KeyboardLayoutButton.xaml.cs | 51 + .../Taskbar/KeyboardLayoutControl.xaml | 32 + .../Taskbar/KeyboardLayoutControl.xaml.cs | 162 + .../Controls/Taskbar/NetworkButton.xaml | 30 + .../Controls/Taskbar/NetworkButton.xaml.cs | 43 + .../Controls/Taskbar/NetworkControl.xaml | 37 + .../Controls/Taskbar/NetworkControl.xaml.cs | 188 + .../Controls/Taskbar/NotificationButton.xaml | 20 + .../Taskbar/NotificationButton.xaml.cs | 53 + .../Controls/Taskbar/PowerSupplyControl.xaml | 63 + .../Taskbar/PowerSupplyControl.xaml.cs | 155 + .../Controls/Taskbar/QuitButton.xaml | 22 + .../Controls/Taskbar/QuitButton.xaml.cs | 42 + .../Controls/Taskbar/RaiseHandControl.xaml | 36 + .../Controls/Taskbar/RaiseHandControl.xaml.cs | 160 + .../Controls/Taskview/WindowControl.xaml | 30 + .../Controls/Taskview/WindowControl.xaml.cs | 165 + .../FileSystemDialogFactory.cs | 49 + .../Images/AboutNotification.xaml | 14 + .../Images/Audio_100.xaml | 13 + .../Images/Audio_33.xaml | 13 + .../Images/Audio_66.xaml | 13 + .../Images/Audio_Light_100.xaml | 13 + .../Images/Audio_Light_33.xaml | 13 + .../Images/Audio_Light_66.xaml | 13 + .../Images/Audio_Light_NoDevice.xaml | 16 + .../Images/Audio_Muted.xaml | 12 + .../Images/Audio_NoDevice.xaml | 16 + .../Images/Battery.xaml | 11 + .../Images/Hand_Lowered.xaml | 9 + .../Images/Hand_Raised.xaml | 12 + .../Images/Home.xaml | 11 + .../Images/Keyboard.xaml | 34 + .../Images/LogNotification.ico | Bin 0 -> 93319 bytes .../Images/Menu.xaml | 7 + .../Images/NavigateBack.xaml | 12 + .../Images/NavigateForward.xaml | 12 + .../Images/Proctoring_Active.xaml | 9 + .../Images/Proctoring_Inactive.xaml | 9 + .../Images/Reload.xaml | 11 + .../Images/SafeExamBrowser.ico | Bin 0 -> 370070 bytes .../Images/ScreenProctoring_Active.xaml | 9 + .../Images/ScreenProctoring_Inactive.xaml | 7 + .../Images/ShutDown.xaml | 12 + .../Images/SplashScreen.png | Bin 0 -> 40053 bytes .../Images/WiFi_0.xaml | 16 + .../Images/WiFi_100.xaml | 16 + .../Images/WiFi_33.xaml | 16 + .../Images/WiFi_66.xaml | 16 + .../Images/WiFi_Light_0.xaml | 16 + .../Images/WiFi_Light_100.xaml | 16 + .../Images/WiFi_Light_33.xaml | 16 + .../Images/WiFi_Light_66.xaml | 16 + .../Images/ZoomPageIn.xaml | 12 + .../Images/ZoomPageOut.xaml | 12 + .../MessageBoxFactory.cs | 92 + .../Properties/AssemblyInfo.cs | 51 + ...feExamBrowser.UserInterface.Desktop.csproj | 589 ++ .../Templates/Buttons.xaml | 61 + .../Templates/Colors.xaml | 9 + .../Templates/ScrollViewers.xaml | 59 + .../UserInterfaceFactory.cs | 259 + .../ViewModels/DateTimeViewModel.cs | 48 + .../ViewModels/LogViewModel.cs | 109 + .../ViewModels/ProgressIndicatorViewModel.cs | 132 + .../ViewModels/RuntimeWindowViewModel.cs | 89 + .../Windows/AboutWindow.xaml | 82 + .../Windows/AboutWindow.xaml.cs | 68 + .../Windows/ActionCenter.xaml | 30 + .../Windows/ActionCenter.xaml.cs | 219 + .../Windows/BrowserWindow.xaml | 127 + .../Windows/BrowserWindow.xaml.cs | 663 ++ .../Windows/CredentialsDialog.xaml | 53 + .../Windows/CredentialsDialog.xaml.cs | 128 + .../Windows/ExamSelectionDialog.xaml | 58 + .../Windows/ExamSelectionDialog.xaml.cs | 88 + .../Windows/FileSystemDialog.xaml | 49 + .../Windows/FileSystemDialog.xaml.cs | 420 + .../Windows/LockScreen.xaml | 34 + .../Windows/LockScreen.xaml.cs | 214 + .../Windows/LogWindow.xaml | 30 + .../Windows/LogWindow.xaml.cs | 111 + .../Windows/PasswordDialog.xaml | 45 + .../Windows/PasswordDialog.xaml.cs | 112 + .../Windows/ProctoringFinalizationDialog.xaml | 53 + .../ProctoringFinalizationDialog.xaml.cs | 118 + .../Windows/ProctoringWindow.xaml | 8 + .../Windows/ProctoringWindow.xaml.cs | 140 + .../Windows/RuntimeWindow.xaml | 47 + .../Windows/RuntimeWindow.xaml.cs | 159 + .../Windows/ServerFailureDialog.xaml | 42 + .../Windows/ServerFailureDialog.xaml.cs | 96 + .../Windows/SplashScreen.xaml | 28 + .../Windows/SplashScreen.xaml.cs | 146 + .../Windows/Taskbar.xaml | 35 + .../Windows/Taskbar.xaml.cs | 265 + .../Windows/Taskview.xaml | 19 + .../Windows/Taskview.xaml.cs | 198 + .../app.config | 11 + .../packages.config | 4 + .../ActionCenter/ApplicationButton.xaml | 24 + .../ActionCenter/ApplicationButton.xaml.cs | 69 + .../ActionCenter/ApplicationControl.xaml | 27 + .../ActionCenter/ApplicationControl.xaml.cs | 70 + .../Controls/ActionCenter/AudioControl.xaml | 49 + .../ActionCenter/AudioControl.xaml.cs | 193 + .../Controls/ActionCenter/Clock.xaml | 36 + .../Controls/ActionCenter/Clock.xaml.cs | 32 + .../ActionCenter/KeyboardLayoutButton.xaml | 37 + .../ActionCenter/KeyboardLayoutButton.xaml.cs | 51 + .../ActionCenter/KeyboardLayoutControl.xaml | 37 + .../KeyboardLayoutControl.xaml.cs | 141 + .../Controls/ActionCenter/NetworkButton.xaml | 30 + .../ActionCenter/NetworkButton.xaml.cs | 43 + .../Controls/ActionCenter/NetworkControl.xaml | 43 + .../ActionCenter/NetworkControl.xaml.cs | 177 + .../ActionCenter/NotificationButton.xaml | 28 + .../ActionCenter/NotificationButton.xaml.cs | 51 + .../ActionCenter/PowerSupplyControl.xaml | 51 + .../ActionCenter/PowerSupplyControl.xaml.cs | 128 + .../Controls/ActionCenter/QuitButton.xaml | 28 + .../Controls/ActionCenter/QuitButton.xaml.cs | 37 + .../ActionCenter/RaiseHandControl.xaml | 42 + .../ActionCenter/RaiseHandControl.xaml.cs | 159 + .../Controls/Browser/DownloadItemControl.xaml | 22 + .../Browser/DownloadItemControl.xaml.cs | 56 + .../Controls/Taskbar/ApplicationControl.xaml | 31 + .../Taskbar/ApplicationControl.xaml.cs | 118 + .../Taskbar/ApplicationWindowButton.xaml | 24 + .../Taskbar/ApplicationWindowButton.xaml.cs | 58 + .../Controls/Taskbar/AudioControl.xaml | 43 + .../Controls/Taskbar/AudioControl.xaml.cs | 226 + .../Controls/Taskbar/Clock.xaml | 17 + .../Controls/Taskbar/Clock.xaml.cs | 32 + .../Taskbar/KeyboardLayoutButton.xaml | 35 + .../Taskbar/KeyboardLayoutButton.xaml.cs | 51 + .../Taskbar/KeyboardLayoutControl.xaml | 32 + .../Taskbar/KeyboardLayoutControl.xaml.cs | 162 + .../Controls/Taskbar/NetworkButton.xaml | 30 + .../Controls/Taskbar/NetworkButton.xaml.cs | 43 + .../Controls/Taskbar/NetworkControl.xaml | 37 + .../Controls/Taskbar/NetworkControl.xaml.cs | 188 + .../Controls/Taskbar/NotificationButton.xaml | 20 + .../Taskbar/NotificationButton.xaml.cs | 53 + .../Controls/Taskbar/PowerSupplyControl.xaml | 63 + .../Taskbar/PowerSupplyControl.xaml.cs | 155 + .../Controls/Taskbar/QuitButton.xaml | 22 + .../Controls/Taskbar/QuitButton.xaml.cs | 42 + .../Controls/Taskbar/RaiseHandControl.xaml | 35 + .../Controls/Taskbar/RaiseHandControl.xaml.cs | 161 + .../Controls/Taskview/WindowControl.xaml | 31 + .../Controls/Taskview/WindowControl.xaml.cs | 164 + .../FileSystemDialogFactory.cs | 49 + .../Images/AboutNotification.xaml | 14 + .../Images/Audio_100.xaml | 13 + .../Images/Audio_33.xaml | 13 + .../Images/Audio_66.xaml | 13 + .../Images/Audio_Light_100.xaml | 13 + .../Images/Audio_Light_33.xaml | 13 + .../Images/Audio_Light_66.xaml | 13 + .../Images/Audio_Light_NoDevice.xaml | 16 + .../Images/Audio_Muted.xaml | 12 + .../Images/Audio_NoDevice.xaml | 16 + .../Images/Battery.xaml | 11 + .../Images/Hand_Lowered.xaml | 9 + .../Images/Hand_Raised.xaml | 12 + .../Images/Home.xaml | 11 + .../Images/Keyboard.xaml | 34 + .../Images/LogNotification.ico | Bin 0 -> 93319 bytes .../Images/Menu.xaml | 7 + .../Images/NavigateBack.xaml | 12 + .../Images/NavigateForward.xaml | 12 + .../Images/Proctoring_Active.xaml | 9 + .../Images/Proctoring_Inactive.xaml | 9 + .../Images/Reload.xaml | 11 + .../Images/SafeExamBrowser.ico | Bin 0 -> 370070 bytes .../Images/ScreenProctoring_Active.xaml | 9 + .../Images/ScreenProctoring_Inactive.xaml | 7 + .../Images/ShutDown.xaml | 12 + .../Images/SplashScreen.png | Bin 0 -> 40053 bytes .../Images/WiFi_0.xaml | 16 + .../Images/WiFi_100.xaml | 16 + .../Images/WiFi_33.xaml | 16 + .../Images/WiFi_66.xaml | 16 + .../Images/WiFi_Light_0.xaml | 16 + .../Images/WiFi_Light_100.xaml | 16 + .../Images/WiFi_Light_33.xaml | 16 + .../Images/WiFi_Light_66.xaml | 16 + .../Images/ZoomPageIn.xaml | 12 + .../Images/ZoomPageOut.xaml | 12 + .../MessageBoxFactory.cs | 48 + .../Properties/AssemblyInfo.cs | 51 + ...afeExamBrowser.UserInterface.Mobile.csproj | 597 ++ .../Templates/Buttons.xaml | 61 + .../Templates/Colors.xaml | 9 + .../Templates/ScrollViewers.xaml | 59 + .../UserInterfaceFactory.cs | 259 + .../ViewModels/DateTimeViewModel.cs | 48 + .../ViewModels/LogViewModel.cs | 109 + .../ViewModels/ProgressIndicatorViewModel.cs | 132 + .../ViewModels/RuntimeWindowViewModel.cs | 89 + .../Windows/AboutWindow.xaml | 82 + .../Windows/AboutWindow.xaml.cs | 68 + .../Windows/ActionCenter.xaml | 30 + .../Windows/ActionCenter.xaml.cs | 219 + .../Windows/BrowserWindow.xaml | 128 + .../Windows/BrowserWindow.xaml.cs | 646 ++ .../Windows/CredentialsDialog.xaml | 56 + .../Windows/CredentialsDialog.xaml.cs | 148 + .../Windows/ExamSelectionDialog.xaml | 61 + .../Windows/ExamSelectionDialog.xaml.cs | 111 + .../Windows/FileSystemDialog.xaml | 49 + .../Windows/FileSystemDialog.xaml.cs | 420 + .../Windows/LockScreen.xaml | 34 + .../Windows/LockScreen.xaml.cs | 214 + .../Windows/LogWindow.xaml | 30 + .../Windows/LogWindow.xaml.cs | 111 + .../Windows/MessageBoxDialog.xaml | 43 + .../Windows/MessageBoxDialog.xaml.cs | 183 + .../Windows/PasswordDialog.xaml | 48 + .../Windows/PasswordDialog.xaml.cs | 132 + .../Windows/ProctoringFinalizationDialog.xaml | 56 + .../ProctoringFinalizationDialog.xaml.cs | 139 + .../Windows/ProctoringWindow.xaml | 8 + .../Windows/ProctoringWindow.xaml.cs | 140 + .../Windows/RuntimeWindow.xaml | 47 + .../Windows/RuntimeWindow.xaml.cs | 159 + .../Windows/ServerFailureDialog.xaml | 45 + .../Windows/ServerFailureDialog.xaml.cs | 119 + .../Windows/SplashScreen.xaml | 28 + .../Windows/SplashScreen.xaml.cs | 146 + .../Windows/Taskbar.xaml | 35 + .../Windows/Taskbar.xaml.cs | 262 + .../Windows/Taskview.xaml | 19 + .../Windows/Taskview.xaml.cs | 197 + .../packages.config | 4 + .../ActionCenterKeyboardActivator.cs | 64 + .../Activators/ActionCenterTouchActivator.cs | 90 + .../Activators/KeyboardActivator.cs | 72 + .../Activators/TaskViewKeyboardActivator.cs | 122 + .../Activators/TaskbarKeyboardActivator.cs | 51 + .../Activators/TerminationActivator.cs | 69 + .../Activators/TouchActivator.cs | 63 + .../Properties/AssemblyInfo.cs | 51 + ...afeExamBrowser.UserInterface.Shared.csproj | 103 + .../Utilities/IconLoader.cs | 86 + .../Utilities/IconResourceLoader.cs | 105 + .../Utilities/Parser.cs | 30 + .../Utilities/Thumbnail.cs | 63 + .../Utilities/VisualExtensions.cs | 63 + .../Utilities/WindowExtensions.cs | 84 + .../Events/KeyModifier.cs | 23 + .../Events/KeyState.cs | 20 + .../Events/KeyboardHookCallback.cs | 15 + .../Events/MouseButton.cs | 22 + .../Events/MouseButtonState.cs | 20 + .../Events/MouseHookCallback.cs | 15 + .../Events/MouseInformation.cs | 31 + .../Events/ProcessTerminatedEventHandler.cs | 15 + .../Events/SystemEventCallback.cs | 17 + .../TerminationActivatorEventHandler.cs | 15 + .../IBounds.cs | 21 + .../IDesktop.cs | 40 + .../IDesktopFactory.cs | 34 + .../IDesktopMonitor.cs | 26 + .../IExplorerShell.cs | 36 + .../INativeMethods.cs | 228 + .../IProcess.cs | 71 + .../IProcessFactory.cs | 40 + .../IStickyKeysState.cs | 31 + .../Properties/AssemblyInfo.cs | 33 + ...afeExamBrowser.WindowsApi.Contracts.csproj | 80 + .../Constants/AccessMask.cs | 34 + .../Constants/Constant.cs | 244 + .../Constants/HookType.cs | 100 + SafeExamBrowser.WindowsApi/Constants/SPI.cs | 59 + SafeExamBrowser.WindowsApi/Constants/SPIF.cs | 36 + .../Constants/ShowWindowCommand.cs | 97 + .../Constants/StickyKeysFlags.cs | 64 + .../Constants/SystemCommand.cs | 21 + .../Constants/ThreadAccess.cs | 29 + .../Constants/VirtualKeyCode.cs | 25 + .../Delegates/EnumDesktopDelegate.cs | 17 + .../Delegates/EnumWindowsDelegate.cs | 17 + .../Delegates/EventDelegate.cs | 17 + .../Delegates/HookDelegate.cs | 17 + .../Desktops/Desktop.cs | 42 + .../Desktops/DesktopFactory.cs | 123 + .../Desktops/DesktopMonitor.cs | 55 + .../Desktops/ObfuscatedDesktop.cs | 29 + SafeExamBrowser.WindowsApi/ExplorerShell.cs | 74 + .../Hooks/KeyboardHook.cs | 128 + SafeExamBrowser.WindowsApi/Hooks/MouseHook.cs | 126 + .../Hooks/SystemHook.cs | 66 + SafeExamBrowser.WindowsApi/Kernel32.cs | 55 + SafeExamBrowser.WindowsApi/NativeMethods.cs | 541 ++ .../Processes/Process.cs | 171 + .../Processes/ProcessFactory.cs | 243 + .../Properties/AssemblyInfo.cs | 33 + .../SafeExamBrowser.WindowsApi.csproj | 112 + SafeExamBrowser.WindowsApi/Types/Bounds.cs | 20 + .../Types/EXECUTION_STATE.cs | 25 + .../Types/KBDLLHOOKSTRUCT.cs | 48 + .../Types/KBDLLHOOKSTRUCTFlags.cs | 36 + .../Types/MSLLHOOKSTRUCT.cs | 23 + SafeExamBrowser.WindowsApi/Types/POINT.cs | 19 + .../Types/PROCESS_INFORMATION.cs | 26 + SafeExamBrowser.WindowsApi/Types/RECT.cs | 36 + .../Types/STARTUPINFO.cs | 39 + .../Types/STICKYKEYS.cs | 23 + .../Types/StickyKeysState.cs | 22 + .../Types/WINDOWPLACEMENT.cs | 22 + SafeExamBrowser.WindowsApi/Types/Window.cs | 18 + SafeExamBrowser.WindowsApi/User32.cs | 122 + SafeExamBrowser.WindowsApi/WinInet.cs | 21 + SafeExamBrowser.sln | 485 ++ SebWindowsConfig/ConfigurationTool.ico | Bin 0 -> 53120 bytes .../Controls/AdditionalResources.Designer.cs | 661 ++ .../Controls/AdditionalResources.cs | 811 ++ .../Controls/AdditionalResources.resx | 138 + .../Controls/FilterRuleControl.Designer.cs | 174 + .../Controls/FilterRuleControl.cs | 165 + .../Controls/FilterRuleControl.resx | 138 + SebWindowsConfig/Entities/FilterAction.cs | 8 + SebWindowsConfig/Entities/FilterRule.cs | 35 + .../PermittedApplicationInformation.cs | 11 + SebWindowsConfig/Properties/AssemblyInfo.cs | 33 + .../Properties/Resources.Designer.cs | 63 + SebWindowsConfig/Properties/Resources.resx | 117 + .../Properties/Settings.Designer.cs | 26 + SebWindowsConfig/Properties/Settings.settings | 7 + SebWindowsConfig/SEBSettings.cs | 1945 +++++ SebWindowsConfig/SEBUIStrings.Designer.cs | 1143 +++ SebWindowsConfig/SEBUIStrings.de.Designer.cs | 0 SebWindowsConfig/SEBUIStrings.de.resx | 453 ++ SebWindowsConfig/SEBUIStrings.resx | 480 ++ .../SebPasswordDialogForm.Designer.cs | 94 + SebWindowsConfig/SebPasswordDialogForm.cs | 141 + .../SebPasswordDialogForm.de.resx | 126 + SebWindowsConfig/SebPasswordDialogForm.resx | 243 + SebWindowsConfig/SebWindowsConfig.csproj | 220 + .../SebWindowsConfigForm.Designer.cs | 6909 +++++++++++++++++ SebWindowsConfig/SebWindowsConfigForm.cs | 4845 ++++++++++++ SebWindowsConfig/SebWindowsConfigForm.resx | 4663 +++++++++++ .../SebWindowsConfigGUIManagement.cs | 579 ++ SebWindowsConfig/SebWindowsConfigProgram.cs | 56 + SebWindowsConfig/TabIcons/32x32/IconHelp.png | Bin 0 -> 2492 bytes .../TabIcons/32x32/Icon_01_General.png | Bin 0 -> 3900 bytes .../TabIcons/32x32/Icon_02_ConfigFile.png | Bin 0 -> 1557 bytes .../TabIcons/32x32/Icon_03_Appearance.png | Bin 0 -> 5006 bytes .../TabIcons/32x32/Icon_04_Browser.png | Bin 0 -> 2427 bytes .../TabIcons/32x32/Icon_05_DownUploads.png | Bin 0 -> 1675 bytes .../TabIcons/32x32/Icon_06_Exam.png | Bin 0 -> 1596 bytes .../TabIcons/32x32/Icon_07_Applications.png | Bin 0 -> 2282 bytes .../TabIcons/32x32/Icon_07b_Resources.png | Bin 0 -> 1503 bytes .../TabIcons/32x32/Icon_08_Network.png | Bin 0 -> 5027 bytes .../TabIcons/32x32/Icon_09_Security.png | Bin 0 -> 1941 bytes .../TabIcons/32x32/Icon_10_Registry.png | Bin 0 -> 1125 bytes .../TabIcons/32x32/Icon_11_HookedKeys.png | Bin 0 -> 1241 bytes SebWindowsConfig/Utilities/FileCompressor.cs | 207 + SebWindowsConfig/Utilities/IFileCompressor.cs | 21 + SebWindowsConfig/Utilities/LogCollector.cs | 118 + SebWindowsConfig/Utilities/Logger.cs | 113 + SebWindowsConfig/Utilities/Plist.cs | 964 +++ SebWindowsConfig/Utilities/SEBClientInfo.cs | 461 ++ .../Utilities/SEBConfigFileManager.cs | 908 +++ .../Utilities/SEBProtectionController.cs | 1123 +++ SebWindowsConfig/Utilities/SEBURLFilter.cs | 344 + .../Utilities/SEBURLFilterExpression.cs | 169 + .../Utilities/SEBURLFilterRegexExpression.cs | 298 + SebWindowsConfig/app.config | 3 + SebWindowsConfig/packages.config | 4 + appveyor-release.yml | 43 + appveyor-test.yml | 27 + codecov.yml | 6 + patch-seb/App.config | 6 + patch-seb/Form1.Designer.cs | 110 + patch-seb/Form1.cs | 200 + patch-seb/Form1.resx | 6293 +++++++++++++++ patch-seb/Program.cs | 22 + patch-seb/Properties/AssemblyInfo.cs | 33 + patch-seb/Properties/Resources.Designer.cs | 203 + patch-seb/Properties/Resources.resx | 163 + patch-seb/Properties/Settings.Designer.cs | 30 + patch-seb/Properties/Settings.settings | 7 + patch-seb/SafeExamBrowser.ico | Bin 0 -> 370070 bytes patch-seb/app.manifest | 33 + patch-seb/patch-seb.csproj | 109 + 1297 files changed, 142172 insertions(+) create mode 100644 .editorconfig create mode 100644 .gitattributes create mode 100644 .github/ISSUE_TEMPLATE/bug-report.md create mode 100644 .github/ISSUE_TEMPLATE/config.yml create mode 100644 .github/ISSUE_TEMPLATE/feature-request.md create mode 100644 .github/workflows/issues.yml create mode 100644 .gitignore create mode 100644 LICENSE.txt create mode 100644 README.md create mode 100644 SECURITY.md create mode 100644 SafeExamBrowser.Applications.Contracts/Events/IconChangedEventHandler.cs create mode 100644 SafeExamBrowser.Applications.Contracts/Events/TitleChangedEventHandler.cs create mode 100644 SafeExamBrowser.Applications.Contracts/Events/WindowsChangedEventHandler.cs create mode 100644 SafeExamBrowser.Applications.Contracts/FactoryResult.cs create mode 100644 SafeExamBrowser.Applications.Contracts/IApplication.cs create mode 100644 SafeExamBrowser.Applications.Contracts/IApplicationFactory.cs create mode 100644 SafeExamBrowser.Applications.Contracts/IApplicationWindow.cs create mode 100644 SafeExamBrowser.Applications.Contracts/Properties/AssemblyInfo.cs create mode 100644 SafeExamBrowser.Applications.Contracts/SafeExamBrowser.Applications.Contracts.csproj create mode 100644 SafeExamBrowser.Applications.UnitTests/ApplicationFactoryTests.cs create mode 100644 SafeExamBrowser.Applications.UnitTests/ExternalApplicationInstanceTests.cs create mode 100644 SafeExamBrowser.Applications.UnitTests/ExternalApplicationTests.cs create mode 100644 SafeExamBrowser.Applications.UnitTests/ExternalApplicationWindowTests.cs create mode 100644 SafeExamBrowser.Applications.UnitTests/Properties/AssemblyInfo.cs create mode 100644 SafeExamBrowser.Applications.UnitTests/SafeExamBrowser.Applications.UnitTests.csproj create mode 100644 SafeExamBrowser.Applications.UnitTests/app.config create mode 100644 SafeExamBrowser.Applications.UnitTests/packages.config create mode 100644 SafeExamBrowser.Applications/ApplicationFactory.cs create mode 100644 SafeExamBrowser.Applications/Events/InstanceTerminatedEventHandler.cs create mode 100644 SafeExamBrowser.Applications/ExternalApplication.cs create mode 100644 SafeExamBrowser.Applications/ExternalApplicationInstance.cs create mode 100644 SafeExamBrowser.Applications/ExternalApplicationWindow.cs create mode 100644 SafeExamBrowser.Applications/Properties/AssemblyInfo.cs create mode 100644 SafeExamBrowser.Applications/SafeExamBrowser.Applications.csproj create mode 100644 SafeExamBrowser.Browser.Contracts/Events/DownloadEventArgs.cs create mode 100644 SafeExamBrowser.Browser.Contracts/Events/DownloadFinishedCallback.cs create mode 100644 SafeExamBrowser.Browser.Contracts/Events/DownloadRequestedEventHandler.cs create mode 100644 SafeExamBrowser.Browser.Contracts/Events/LoseFocusRequestedEventHandler.cs create mode 100644 SafeExamBrowser.Browser.Contracts/Events/TabPressedEventHandler.cs create mode 100644 SafeExamBrowser.Browser.Contracts/Events/TerminationRequestedEventHandler.cs create mode 100644 SafeExamBrowser.Browser.Contracts/Events/UserIdentifierDetectedEventHandler.cs create mode 100644 SafeExamBrowser.Browser.Contracts/Filters/IRequestFilter.cs create mode 100644 SafeExamBrowser.Browser.Contracts/Filters/IRule.cs create mode 100644 SafeExamBrowser.Browser.Contracts/Filters/IRuleFactory.cs create mode 100644 SafeExamBrowser.Browser.Contracts/Filters/Request.cs create mode 100644 SafeExamBrowser.Browser.Contracts/IBrowserApplication.cs create mode 100644 SafeExamBrowser.Browser.Contracts/IBrowserWindow.cs create mode 100644 SafeExamBrowser.Browser.Contracts/Properties/AssemblyInfo.cs create mode 100644 SafeExamBrowser.Browser.Contracts/SafeExamBrowser.Browser.Contracts.csproj create mode 100644 SafeExamBrowser.Browser.UnitTests/Filters/LegacyFilter.cs create mode 100644 SafeExamBrowser.Browser.UnitTests/Filters/RequestFilterTests.cs create mode 100644 SafeExamBrowser.Browser.UnitTests/Filters/RuleFactoryTests.cs create mode 100644 SafeExamBrowser.Browser.UnitTests/Filters/Rules/RegexRuleTests.cs create mode 100644 SafeExamBrowser.Browser.UnitTests/Filters/Rules/SimplifiedRuleTests.cs create mode 100644 SafeExamBrowser.Browser.UnitTests/Handlers/ContextMenuHandlerTests.cs create mode 100644 SafeExamBrowser.Browser.UnitTests/Handlers/DialogHandlerTests.cs create mode 100644 SafeExamBrowser.Browser.UnitTests/Handlers/DisplayHandlerTests.cs create mode 100644 SafeExamBrowser.Browser.UnitTests/Handlers/DownloadHandlerTests.cs create mode 100644 SafeExamBrowser.Browser.UnitTests/Handlers/KeyboardHandlerTests.cs create mode 100644 SafeExamBrowser.Browser.UnitTests/Handlers/RequestHandlerTests.cs create mode 100644 SafeExamBrowser.Browser.UnitTests/Handlers/ResourceHandlerTests.cs create mode 100644 SafeExamBrowser.Browser.UnitTests/Properties/AssemblyInfo.cs create mode 100644 SafeExamBrowser.Browser.UnitTests/SafeExamBrowser.Browser.UnitTests.csproj create mode 100644 SafeExamBrowser.Browser.UnitTests/app.config create mode 100644 SafeExamBrowser.Browser.UnitTests/packages.config create mode 100644 SafeExamBrowser.Browser/BrowserApplication.cs create mode 100644 SafeExamBrowser.Browser/BrowserControl.cs create mode 100644 SafeExamBrowser.Browser/BrowserIconResource.cs create mode 100644 SafeExamBrowser.Browser/BrowserWindow.cs create mode 100644 SafeExamBrowser.Browser/Clipboard.cs create mode 100644 SafeExamBrowser.Browser/Content/Api.js create mode 100644 SafeExamBrowser.Browser/Content/BlockedContent.html create mode 100644 SafeExamBrowser.Browser/Content/BlockedPage.html create mode 100644 SafeExamBrowser.Browser/Content/Clipboard.js create mode 100644 SafeExamBrowser.Browser/Content/ContentLoader.cs create mode 100644 SafeExamBrowser.Browser/Content/PageZoom.js create mode 100644 SafeExamBrowser.Browser/Events/ClipboardChangedEventHandler.cs create mode 100644 SafeExamBrowser.Browser/Events/DialogRequestedEventArgs.cs create mode 100644 SafeExamBrowser.Browser/Events/DialogRequestedEventHandler.cs create mode 100644 SafeExamBrowser.Browser/Events/DownloadAbortedEventHandler.cs create mode 100644 SafeExamBrowser.Browser/Events/DownloadUpdatedEventHandler.cs create mode 100644 SafeExamBrowser.Browser/Events/FaviconChangedEventHandler.cs create mode 100644 SafeExamBrowser.Browser/Events/PopupRequestedEventArgs.cs create mode 100644 SafeExamBrowser.Browser/Events/PopupRequestedEventHandler.cs create mode 100644 SafeExamBrowser.Browser/Events/ProgressChangedEventHandler.cs create mode 100644 SafeExamBrowser.Browser/Events/ResetRequestedEventHandler.cs create mode 100644 SafeExamBrowser.Browser/Events/UrlEventHandler.cs create mode 100644 SafeExamBrowser.Browser/Events/WindowClosedEventHandler.cs create mode 100644 SafeExamBrowser.Browser/Filters/RequestFilter.cs create mode 100644 SafeExamBrowser.Browser/Filters/RuleFactory.cs create mode 100644 SafeExamBrowser.Browser/Filters/Rules/RegexRule.cs create mode 100644 SafeExamBrowser.Browser/Filters/Rules/SimplifiedRule.cs create mode 100644 SafeExamBrowser.Browser/Handlers/ContextMenuHandler.cs create mode 100644 SafeExamBrowser.Browser/Handlers/DialogHandler.cs create mode 100644 SafeExamBrowser.Browser/Handlers/DisplayHandler.cs create mode 100644 SafeExamBrowser.Browser/Handlers/DownloadHandler.cs create mode 100644 SafeExamBrowser.Browser/Handlers/KeyboardHandler.cs create mode 100644 SafeExamBrowser.Browser/Handlers/RenderProcessMessageHandler.cs create mode 100644 SafeExamBrowser.Browser/Handlers/RequestHandler.cs create mode 100644 SafeExamBrowser.Browser/Handlers/ResourceHandler.cs create mode 100644 SafeExamBrowser.Browser/Properties/AssemblyInfo.cs create mode 100644 SafeExamBrowser.Browser/SafeExamBrowser.Browser.csproj create mode 100644 SafeExamBrowser.Browser/Wrapper/CefSharpBrowserControl.cs create mode 100644 SafeExamBrowser.Browser/Wrapper/CefSharpPopupControl.cs create mode 100644 SafeExamBrowser.Browser/Wrapper/Events/AuthCredentialsEventHandler.cs create mode 100644 SafeExamBrowser.Browser/Wrapper/Events/BeforeBrowseEventHandler.cs create mode 100644 SafeExamBrowser.Browser/Wrapper/Events/BeforeDownloadEventHandler.cs create mode 100644 SafeExamBrowser.Browser/Wrapper/Events/CanDownloadEventHandler.cs create mode 100644 SafeExamBrowser.Browser/Wrapper/Events/ContextCreatedEventHandler.cs create mode 100644 SafeExamBrowser.Browser/Wrapper/Events/ContextReleasedEventHandler.cs create mode 100644 SafeExamBrowser.Browser/Wrapper/Events/DownloadUpdatedEventHandler.cs create mode 100644 SafeExamBrowser.Browser/Wrapper/Events/FaviconUrlChangedEventHandler.cs create mode 100644 SafeExamBrowser.Browser/Wrapper/Events/FileDialogRequestedEventHandler.cs create mode 100644 SafeExamBrowser.Browser/Wrapper/Events/FocusedNodeChangedEventHandler.cs create mode 100644 SafeExamBrowser.Browser/Wrapper/Events/GenericEventArgs.cs create mode 100644 SafeExamBrowser.Browser/Wrapper/Events/KeyEventHandler.cs create mode 100644 SafeExamBrowser.Browser/Wrapper/Events/LoadingProgressChangedEventHandler.cs create mode 100644 SafeExamBrowser.Browser/Wrapper/Events/OpenUrlFromTabEventHandler.cs create mode 100644 SafeExamBrowser.Browser/Wrapper/Events/PreKeyEventHandler.cs create mode 100644 SafeExamBrowser.Browser/Wrapper/Events/ResourceRequestEventArgs.cs create mode 100644 SafeExamBrowser.Browser/Wrapper/Events/ResourceRequestEventHandler.cs create mode 100644 SafeExamBrowser.Browser/Wrapper/Events/UncaughtExceptionEventHandler.cs create mode 100644 SafeExamBrowser.Browser/Wrapper/Extensions.cs create mode 100644 SafeExamBrowser.Browser/Wrapper/Handlers/DialogHandlerSwitch.cs create mode 100644 SafeExamBrowser.Browser/Wrapper/Handlers/DisplayHandlerSwitch.cs create mode 100644 SafeExamBrowser.Browser/Wrapper/Handlers/DownloadHandlerSwitch.cs create mode 100644 SafeExamBrowser.Browser/Wrapper/Handlers/KeyboardHandlerSwitch.cs create mode 100644 SafeExamBrowser.Browser/Wrapper/Handlers/RenderProcessMessageHandlerSwitch.cs create mode 100644 SafeExamBrowser.Browser/Wrapper/Handlers/RequestHandlerSwitch.cs create mode 100644 SafeExamBrowser.Browser/Wrapper/ICefSharpControl.cs create mode 100644 SafeExamBrowser.Browser/app.config create mode 100644 SafeExamBrowser.Browser/packages.config create mode 100644 SafeExamBrowser.Client.UnitTests/ClientControllerTests.cs create mode 100644 SafeExamBrowser.Client.UnitTests/Communication/ClientHostTests.cs create mode 100644 SafeExamBrowser.Client.UnitTests/CoordinatorTests.cs create mode 100644 SafeExamBrowser.Client.UnitTests/Notifications/AboutNotificationControllerTests.cs create mode 100644 SafeExamBrowser.Client.UnitTests/Notifications/LogNotificationControllerTests.cs create mode 100644 SafeExamBrowser.Client.UnitTests/Operations/ApplicationOperationTests.cs create mode 100644 SafeExamBrowser.Client.UnitTests/Operations/BrowserOperationTests.cs create mode 100644 SafeExamBrowser.Client.UnitTests/Operations/ClientHostDisconnectionOperationTests.cs create mode 100644 SafeExamBrowser.Client.UnitTests/Operations/ClipboardOperationTests.cs create mode 100644 SafeExamBrowser.Client.UnitTests/Operations/ConfigurationOperationTests.cs create mode 100644 SafeExamBrowser.Client.UnitTests/Operations/DisplayMonitorOperationTests.cs create mode 100644 SafeExamBrowser.Client.UnitTests/Operations/KeyboardInterceptorOperationTests.cs create mode 100644 SafeExamBrowser.Client.UnitTests/Operations/MouseInterceptorOperationTests.cs create mode 100644 SafeExamBrowser.Client.UnitTests/Operations/ProctoringOperationTests.cs create mode 100644 SafeExamBrowser.Client.UnitTests/Operations/RuntimeConnectionOperationTests.cs create mode 100644 SafeExamBrowser.Client.UnitTests/Operations/ServerOperationTests.cs create mode 100644 SafeExamBrowser.Client.UnitTests/Operations/ShellOperationTests.cs create mode 100644 SafeExamBrowser.Client.UnitTests/Properties/AssemblyInfo.cs create mode 100644 SafeExamBrowser.Client.UnitTests/SafeExamBrowser.Client.UnitTests.csproj create mode 100644 SafeExamBrowser.Client.UnitTests/app.config create mode 100644 SafeExamBrowser.Client.UnitTests/packages.config create mode 100644 SafeExamBrowser.Client/App.config create mode 100644 SafeExamBrowser.Client/App.cs create mode 100644 SafeExamBrowser.Client/ClientContext.cs create mode 100644 SafeExamBrowser.Client/ClientController.cs create mode 100644 SafeExamBrowser.Client/Communication/ClientHost.cs create mode 100644 SafeExamBrowser.Client/CompositionRoot.cs create mode 100644 SafeExamBrowser.Client/Contracts/ICoordinator.cs create mode 100644 SafeExamBrowser.Client/Coordinator.cs create mode 100644 SafeExamBrowser.Client/Notifications/AboutNotification.cs create mode 100644 SafeExamBrowser.Client/Notifications/LogNotification.cs create mode 100644 SafeExamBrowser.Client/Operations/ApplicationOperation.cs create mode 100644 SafeExamBrowser.Client/Operations/BrowserOperation.cs create mode 100644 SafeExamBrowser.Client/Operations/ClientHostDisconnectionOperation.cs create mode 100644 SafeExamBrowser.Client/Operations/ClientOperation.cs create mode 100644 SafeExamBrowser.Client/Operations/ClipboardOperation.cs create mode 100644 SafeExamBrowser.Client/Operations/ConfigurationOperation.cs create mode 100644 SafeExamBrowser.Client/Operations/DisplayMonitorOperation.cs create mode 100644 SafeExamBrowser.Client/Operations/Events/ApplicationInitializationFailedEventArgs.cs create mode 100644 SafeExamBrowser.Client/Operations/Events/ApplicationNotFoundEventArgs.cs create mode 100644 SafeExamBrowser.Client/Operations/Events/ApplicationTerminationEventArgs.cs create mode 100644 SafeExamBrowser.Client/Operations/Events/ApplicationTerminationFailedEventArgs.cs create mode 100644 SafeExamBrowser.Client/Operations/KeyboardInterceptorOperation.cs create mode 100644 SafeExamBrowser.Client/Operations/MouseInterceptorOperation.cs create mode 100644 SafeExamBrowser.Client/Operations/ProctoringOperation.cs create mode 100644 SafeExamBrowser.Client/Operations/RuntimeConnectionOperation.cs create mode 100644 SafeExamBrowser.Client/Operations/ServerOperation.cs create mode 100644 SafeExamBrowser.Client/Operations/ShellOperation.cs create mode 100644 SafeExamBrowser.Client/Properties/AssemblyInfo.cs create mode 100644 SafeExamBrowser.Client/Properties/Resources.Designer.cs create mode 100644 SafeExamBrowser.Client/Properties/Resources.resx create mode 100644 SafeExamBrowser.Client/Properties/Settings.Designer.cs create mode 100644 SafeExamBrowser.Client/Properties/Settings.settings create mode 100644 SafeExamBrowser.Client/SafeExamBrowser.Client.csproj create mode 100644 SafeExamBrowser.Client/SafeExamBrowser.ico create mode 100644 SafeExamBrowser.Client/app.manifest create mode 100644 SafeExamBrowser.Communication.Contracts/Data/AuthenticationResponse.cs create mode 100644 SafeExamBrowser.Communication.Contracts/Data/ConfigurationResponse.cs create mode 100644 SafeExamBrowser.Communication.Contracts/Data/ConnectionResponse.cs create mode 100644 SafeExamBrowser.Communication.Contracts/Data/DisconnectionMessage.cs create mode 100644 SafeExamBrowser.Communication.Contracts/Data/DisconnectionResponse.cs create mode 100644 SafeExamBrowser.Communication.Contracts/Data/ExamSelectionReplyMessage.cs create mode 100644 SafeExamBrowser.Communication.Contracts/Data/ExamSelectionRequestMessage.cs create mode 100644 SafeExamBrowser.Communication.Contracts/Data/Message.cs create mode 100644 SafeExamBrowser.Communication.Contracts/Data/MessageBoxReplyMessage.cs create mode 100644 SafeExamBrowser.Communication.Contracts/Data/MessageBoxRequestMessage.cs create mode 100644 SafeExamBrowser.Communication.Contracts/Data/PasswordReplyMessage.cs create mode 100644 SafeExamBrowser.Communication.Contracts/Data/PasswordRequestMessage.cs create mode 100644 SafeExamBrowser.Communication.Contracts/Data/PasswordRequestPurpose.cs create mode 100644 SafeExamBrowser.Communication.Contracts/Data/ReconfigurationDeniedMessage.cs create mode 100644 SafeExamBrowser.Communication.Contracts/Data/ReconfigurationMessage.cs create mode 100644 SafeExamBrowser.Communication.Contracts/Data/Response.cs create mode 100644 SafeExamBrowser.Communication.Contracts/Data/ServerFailureActionReplyMessage.cs create mode 100644 SafeExamBrowser.Communication.Contracts/Data/ServerFailureActionRequestMessage.cs create mode 100644 SafeExamBrowser.Communication.Contracts/Data/SessionStartMessage.cs create mode 100644 SafeExamBrowser.Communication.Contracts/Data/SessionStopMessage.cs create mode 100644 SafeExamBrowser.Communication.Contracts/Data/SimpleMessage.cs create mode 100644 SafeExamBrowser.Communication.Contracts/Data/SimpleMessagePurport.cs create mode 100644 SafeExamBrowser.Communication.Contracts/Data/SimpleResponse.cs create mode 100644 SafeExamBrowser.Communication.Contracts/Data/SimpleResponsePurport.cs create mode 100644 SafeExamBrowser.Communication.Contracts/Events/ClientConfigurationEventArgs.cs create mode 100644 SafeExamBrowser.Communication.Contracts/Events/CommunicationEventArgs.cs create mode 100644 SafeExamBrowser.Communication.Contracts/Events/CommunicationEventHandler.cs create mode 100644 SafeExamBrowser.Communication.Contracts/Events/ExamSelectionReplyEventArgs.cs create mode 100644 SafeExamBrowser.Communication.Contracts/Events/ExamSelectionRequestEventArgs.cs create mode 100644 SafeExamBrowser.Communication.Contracts/Events/MessageBoxReplyEventArgs.cs create mode 100644 SafeExamBrowser.Communication.Contracts/Events/MessageBoxRequestEventArgs.cs create mode 100644 SafeExamBrowser.Communication.Contracts/Events/PasswordReplyEventArgs.cs create mode 100644 SafeExamBrowser.Communication.Contracts/Events/PasswordRequestEventArgs.cs create mode 100644 SafeExamBrowser.Communication.Contracts/Events/ReconfigurationEventArgs.cs create mode 100644 SafeExamBrowser.Communication.Contracts/Events/ServerFailureActionReplyEventArgs.cs create mode 100644 SafeExamBrowser.Communication.Contracts/Events/ServerFailureActionRequestEventArgs.cs create mode 100644 SafeExamBrowser.Communication.Contracts/Events/SessionStartEventArgs.cs create mode 100644 SafeExamBrowser.Communication.Contracts/Events/SessionStopEventArgs.cs create mode 100644 SafeExamBrowser.Communication.Contracts/Hosts/IClientHost.cs create mode 100644 SafeExamBrowser.Communication.Contracts/Hosts/IHostObject.cs create mode 100644 SafeExamBrowser.Communication.Contracts/Hosts/IHostObjectFactory.cs create mode 100644 SafeExamBrowser.Communication.Contracts/Hosts/IRuntimeHost.cs create mode 100644 SafeExamBrowser.Communication.Contracts/Hosts/IServiceHost.cs create mode 100644 SafeExamBrowser.Communication.Contracts/ICommunication.cs create mode 100644 SafeExamBrowser.Communication.Contracts/ICommunicationHost.cs create mode 100644 SafeExamBrowser.Communication.Contracts/ICommunicationProxy.cs create mode 100644 SafeExamBrowser.Communication.Contracts/Interlocutor.cs create mode 100644 SafeExamBrowser.Communication.Contracts/Properties/AssemblyInfo.cs create mode 100644 SafeExamBrowser.Communication.Contracts/Proxies/CommunicationResult.cs create mode 100644 SafeExamBrowser.Communication.Contracts/Proxies/IClientProxy.cs create mode 100644 SafeExamBrowser.Communication.Contracts/Proxies/IProxyFactory.cs create mode 100644 SafeExamBrowser.Communication.Contracts/Proxies/IProxyObject.cs create mode 100644 SafeExamBrowser.Communication.Contracts/Proxies/IProxyObjectFactory.cs create mode 100644 SafeExamBrowser.Communication.Contracts/Proxies/IRuntimeProxy.cs create mode 100644 SafeExamBrowser.Communication.Contracts/Proxies/IServiceProxy.cs create mode 100644 SafeExamBrowser.Communication.Contracts/SafeExamBrowser.Communication.Contracts.csproj create mode 100644 SafeExamBrowser.Communication.UnitTests/Hosts/BaseHostStub.cs create mode 100644 SafeExamBrowser.Communication.UnitTests/Hosts/BaseHostTests.cs create mode 100644 SafeExamBrowser.Communication.UnitTests/Properties/AssemblyInfo.cs create mode 100644 SafeExamBrowser.Communication.UnitTests/Proxies/BaseProxyImpl.cs create mode 100644 SafeExamBrowser.Communication.UnitTests/Proxies/BaseProxyTests.cs create mode 100644 SafeExamBrowser.Communication.UnitTests/Proxies/ClientProxyTests.cs create mode 100644 SafeExamBrowser.Communication.UnitTests/Proxies/RuntimeProxyTests.cs create mode 100644 SafeExamBrowser.Communication.UnitTests/Proxies/ServiceProxyTests.cs create mode 100644 SafeExamBrowser.Communication.UnitTests/SafeExamBrowser.Communication.UnitTests.csproj create mode 100644 SafeExamBrowser.Communication.UnitTests/app.config create mode 100644 SafeExamBrowser.Communication.UnitTests/packages.config create mode 100644 SafeExamBrowser.Communication/Hosts/BaseHost.cs create mode 100644 SafeExamBrowser.Communication/Hosts/HostObjectFactory.cs create mode 100644 SafeExamBrowser.Communication/Properties/AssemblyInfo.cs create mode 100644 SafeExamBrowser.Communication/Proxies/BaseProxy.cs create mode 100644 SafeExamBrowser.Communication/Proxies/ClientProxy.cs create mode 100644 SafeExamBrowser.Communication/Proxies/ProxyFactory.cs create mode 100644 SafeExamBrowser.Communication/Proxies/ProxyObjectFactory.cs create mode 100644 SafeExamBrowser.Communication/Proxies/RuntimeProxy.cs create mode 100644 SafeExamBrowser.Communication/Proxies/ServiceProxy.cs create mode 100644 SafeExamBrowser.Communication/SafeExamBrowser.Communication.csproj create mode 100644 SafeExamBrowser.Configuration.Contracts/AppConfig.cs create mode 100644 SafeExamBrowser.Configuration.Contracts/ClientConfiguration.cs create mode 100644 SafeExamBrowser.Configuration.Contracts/Cryptography/EncryptionParameters.cs create mode 100644 SafeExamBrowser.Configuration.Contracts/Cryptography/ICertificateStore.cs create mode 100644 SafeExamBrowser.Configuration.Contracts/Cryptography/IHashAlgorithm.cs create mode 100644 SafeExamBrowser.Configuration.Contracts/Cryptography/IKeyGenerator.cs create mode 100644 SafeExamBrowser.Configuration.Contracts/Cryptography/IPasswordEncryption.cs create mode 100644 SafeExamBrowser.Configuration.Contracts/Cryptography/IPublicKeyEncryption.cs create mode 100644 SafeExamBrowser.Configuration.Contracts/Cryptography/PasswordParameters.cs create mode 100644 SafeExamBrowser.Configuration.Contracts/Cryptography/PublicKeyParameters.cs create mode 100644 SafeExamBrowser.Configuration.Contracts/DataCompression/IDataCompressor.cs create mode 100644 SafeExamBrowser.Configuration.Contracts/DataFormats/FormatType.cs create mode 100644 SafeExamBrowser.Configuration.Contracts/DataFormats/IDataParser.cs create mode 100644 SafeExamBrowser.Configuration.Contracts/DataFormats/IDataSerializer.cs create mode 100644 SafeExamBrowser.Configuration.Contracts/DataFormats/ParseResult.cs create mode 100644 SafeExamBrowser.Configuration.Contracts/DataFormats/SerializeResult.cs create mode 100644 SafeExamBrowser.Configuration.Contracts/DataResources/IResourceLoader.cs create mode 100644 SafeExamBrowser.Configuration.Contracts/DataResources/IResourceSaver.cs create mode 100644 SafeExamBrowser.Configuration.Contracts/IConfigurationRepository.cs create mode 100644 SafeExamBrowser.Configuration.Contracts/Integrity/IIntegrityModule.cs create mode 100644 SafeExamBrowser.Configuration.Contracts/LoadStatus.cs create mode 100644 SafeExamBrowser.Configuration.Contracts/Properties/AssemblyInfo.cs create mode 100644 SafeExamBrowser.Configuration.Contracts/SafeExamBrowser.Configuration.Contracts.csproj create mode 100644 SafeExamBrowser.Configuration.Contracts/SaveStatus.cs create mode 100644 SafeExamBrowser.Configuration.Contracts/ServiceConfiguration.cs create mode 100644 SafeExamBrowser.Configuration.Contracts/SessionConfiguration.cs create mode 100644 SafeExamBrowser.Configuration.UnitTests/ConfigurationData/DataProcessorTests.cs create mode 100644 SafeExamBrowser.Configuration.UnitTests/ConfigurationData/TestDictionary1.bin create mode 100644 SafeExamBrowser.Configuration.UnitTests/ConfigurationData/TestDictionary2.bin create mode 100644 SafeExamBrowser.Configuration.UnitTests/ConfigurationData/TestDictionary3.bin create mode 100644 SafeExamBrowser.Configuration.UnitTests/ConfigurationRepositoryTests.cs create mode 100644 SafeExamBrowser.Configuration.UnitTests/Cryptography/HashAlgorithmTests.cs create mode 100644 SafeExamBrowser.Configuration.UnitTests/Cryptography/KeyGeneratorTests.cs create mode 100644 SafeExamBrowser.Configuration.UnitTests/Cryptography/PasswordEncryptionTests.cs create mode 100644 SafeExamBrowser.Configuration.UnitTests/Cryptography/PublicKeyEncryptionTests.cs create mode 100644 SafeExamBrowser.Configuration.UnitTests/Cryptography/PublicKeySymmetricEncryptionTests.cs create mode 100644 SafeExamBrowser.Configuration.UnitTests/DataCompression/GZipCompressorTests.cs create mode 100644 SafeExamBrowser.Configuration.UnitTests/DataFormats/BinaryParserTests.cs create mode 100644 SafeExamBrowser.Configuration.UnitTests/DataFormats/BinarySerializerTests.cs create mode 100644 SafeExamBrowser.Configuration.UnitTests/DataFormats/XmlParserTests.cs create mode 100644 SafeExamBrowser.Configuration.UnitTests/DataFormats/XmlSerializerTests.cs create mode 100644 SafeExamBrowser.Configuration.UnitTests/DataFormats/XmlTestData.xml create mode 100644 SafeExamBrowser.Configuration.UnitTests/DataFormats/XmlTestSettings.xml create mode 100644 SafeExamBrowser.Configuration.UnitTests/Properties/AssemblyInfo.cs create mode 100644 SafeExamBrowser.Configuration.UnitTests/SafeExamBrowser.Configuration.UnitTests.csproj create mode 100644 SafeExamBrowser.Configuration.UnitTests/SubStreamTests.cs create mode 100644 SafeExamBrowser.Configuration.UnitTests/app.config create mode 100644 SafeExamBrowser.Configuration.UnitTests/packages.config create mode 100644 SafeExamBrowser.Configuration/ConfigurationData/DataMapper.cs create mode 100644 SafeExamBrowser.Configuration/ConfigurationData/DataMapping/ApplicationDataMapper.cs create mode 100644 SafeExamBrowser.Configuration/ConfigurationData/DataMapping/AudioDataMapper.cs create mode 100644 SafeExamBrowser.Configuration/ConfigurationData/DataMapping/BaseDataMapper.cs create mode 100644 SafeExamBrowser.Configuration/ConfigurationData/DataMapping/BrowserDataMapper.cs create mode 100644 SafeExamBrowser.Configuration/ConfigurationData/DataMapping/ConfigurationFileDataMapper.cs create mode 100644 SafeExamBrowser.Configuration/ConfigurationData/DataMapping/DisplayDataMapper.cs create mode 100644 SafeExamBrowser.Configuration/ConfigurationData/DataMapping/GeneralDataMapper.cs create mode 100644 SafeExamBrowser.Configuration/ConfigurationData/DataMapping/InputDataMapper.cs create mode 100644 SafeExamBrowser.Configuration/ConfigurationData/DataMapping/ProctoringDataMapper.cs create mode 100644 SafeExamBrowser.Configuration/ConfigurationData/DataMapping/SecurityDataMapper.cs create mode 100644 SafeExamBrowser.Configuration/ConfigurationData/DataMapping/ServerDataMapper.cs create mode 100644 SafeExamBrowser.Configuration/ConfigurationData/DataMapping/ServiceDataMapper.cs create mode 100644 SafeExamBrowser.Configuration/ConfigurationData/DataMapping/SystemDataMapper.cs create mode 100644 SafeExamBrowser.Configuration/ConfigurationData/DataMapping/UserInterfaceDataMapper.cs create mode 100644 SafeExamBrowser.Configuration/ConfigurationData/DataProcessor.cs create mode 100644 SafeExamBrowser.Configuration/ConfigurationData/DataValues.cs create mode 100644 SafeExamBrowser.Configuration/ConfigurationData/Json.cs create mode 100644 SafeExamBrowser.Configuration/ConfigurationData/Keys.cs create mode 100644 SafeExamBrowser.Configuration/ConfigurationRepository.cs create mode 100644 SafeExamBrowser.Configuration/Cryptography/CertificateStore.cs create mode 100644 SafeExamBrowser.Configuration/Cryptography/HashAlgorithm.cs create mode 100644 SafeExamBrowser.Configuration/Cryptography/KeyGenerator.cs create mode 100644 SafeExamBrowser.Configuration/Cryptography/PasswordEncryption.cs create mode 100644 SafeExamBrowser.Configuration/Cryptography/PublicKeyEncryption.cs create mode 100644 SafeExamBrowser.Configuration/Cryptography/PublicKeySymmetricEncryption.cs create mode 100644 SafeExamBrowser.Configuration/DataCompression/GZipCompressor.cs create mode 100644 SafeExamBrowser.Configuration/DataFormats/BinaryBlock.cs create mode 100644 SafeExamBrowser.Configuration/DataFormats/BinaryParser.cs create mode 100644 SafeExamBrowser.Configuration/DataFormats/BinarySerializer.cs create mode 100644 SafeExamBrowser.Configuration/DataFormats/XmlElement.cs create mode 100644 SafeExamBrowser.Configuration/DataFormats/XmlParser.cs create mode 100644 SafeExamBrowser.Configuration/DataFormats/XmlSerializer.cs create mode 100644 SafeExamBrowser.Configuration/DataResources/FileResourceLoader.cs create mode 100644 SafeExamBrowser.Configuration/DataResources/FileResourceSaver.cs create mode 100644 SafeExamBrowser.Configuration/DataResources/NetworkResourceLoader.cs create mode 100644 SafeExamBrowser.Configuration/Integrity/IntegrityModule.cs create mode 100644 SafeExamBrowser.Configuration/Properties/AssemblyInfo.cs create mode 100644 SafeExamBrowser.Configuration/SafeExamBrowser.Configuration.csproj create mode 100644 SafeExamBrowser.Configuration/SubStream.cs create mode 100644 SafeExamBrowser.Core.Contracts/Notifications/Events/NotificationChangedEventHandler.cs create mode 100644 SafeExamBrowser.Core.Contracts/Notifications/INotification.cs create mode 100644 SafeExamBrowser.Core.Contracts/OperationModel/Events/ActionRequiredEventArgs.cs create mode 100644 SafeExamBrowser.Core.Contracts/OperationModel/Events/ActionRequiredEventHandler.cs create mode 100644 SafeExamBrowser.Core.Contracts/OperationModel/Events/ProgressChangedEventArgs.cs create mode 100644 SafeExamBrowser.Core.Contracts/OperationModel/Events/ProgressChangedEventHandler.cs create mode 100644 SafeExamBrowser.Core.Contracts/OperationModel/Events/StatusChangedEventHandler.cs create mode 100644 SafeExamBrowser.Core.Contracts/OperationModel/IOperation.cs create mode 100644 SafeExamBrowser.Core.Contracts/OperationModel/IOperationSequence.cs create mode 100644 SafeExamBrowser.Core.Contracts/OperationModel/IRepeatableOperation.cs create mode 100644 SafeExamBrowser.Core.Contracts/OperationModel/IRepeatableOperationSequence.cs create mode 100644 SafeExamBrowser.Core.Contracts/OperationModel/OperationResult.cs create mode 100644 SafeExamBrowser.Core.Contracts/Properties/AssemblyInfo.cs create mode 100644 SafeExamBrowser.Core.Contracts/Resources/Icons/BitmapIconResource.cs create mode 100644 SafeExamBrowser.Core.Contracts/Resources/Icons/EmbeddedIconResource.cs create mode 100644 SafeExamBrowser.Core.Contracts/Resources/Icons/IconResource.cs create mode 100644 SafeExamBrowser.Core.Contracts/Resources/Icons/NativeIconResource.cs create mode 100644 SafeExamBrowser.Core.Contracts/Resources/Icons/XamlIconResource.cs create mode 100644 SafeExamBrowser.Core.Contracts/SafeExamBrowser.Core.Contracts.csproj create mode 100644 SafeExamBrowser.Core.UnitTests/OperationModel/OperationSequenceTests.cs create mode 100644 SafeExamBrowser.Core.UnitTests/OperationModel/QueueExtensionTests.cs create mode 100644 SafeExamBrowser.Core.UnitTests/OperationModel/RepeatableOperationSequenceTests.cs create mode 100644 SafeExamBrowser.Core.UnitTests/Operations/CommunicationHostOperationTests.cs create mode 100644 SafeExamBrowser.Core.UnitTests/Operations/DelegateOperationTests.cs create mode 100644 SafeExamBrowser.Core.UnitTests/Operations/I18nOperationTests.cs create mode 100644 SafeExamBrowser.Core.UnitTests/Operations/LazyInitializationOperationTests.cs create mode 100644 SafeExamBrowser.Core.UnitTests/Properties/AssemblyInfo.cs create mode 100644 SafeExamBrowser.Core.UnitTests/SafeExamBrowser.Core.UnitTests.csproj create mode 100644 SafeExamBrowser.Core.UnitTests/app.config create mode 100644 SafeExamBrowser.Core.UnitTests/packages.config create mode 100644 SafeExamBrowser.Core/OperationModel/OperationSequence.cs create mode 100644 SafeExamBrowser.Core/OperationModel/QueueExtensions.cs create mode 100644 SafeExamBrowser.Core/OperationModel/RepeatableOperationSequence.cs create mode 100644 SafeExamBrowser.Core/Operations/CommunicationHostOperation.cs create mode 100644 SafeExamBrowser.Core/Operations/DelegateOperation.cs create mode 100644 SafeExamBrowser.Core/Operations/I18nOperation.cs create mode 100644 SafeExamBrowser.Core/Operations/LazyInitializationOperation.cs create mode 100644 SafeExamBrowser.Core/Properties/AssemblyInfo.cs create mode 100644 SafeExamBrowser.Core/SafeExamBrowser.Core.csproj create mode 100644 SafeExamBrowser.I18n.Contracts/IText.cs create mode 100644 SafeExamBrowser.I18n.Contracts/ITextResource.cs create mode 100644 SafeExamBrowser.I18n.Contracts/Properties/AssemblyInfo.cs create mode 100644 SafeExamBrowser.I18n.Contracts/SafeExamBrowser.I18n.Contracts.csproj create mode 100644 SafeExamBrowser.I18n.Contracts/TextKey.cs create mode 100644 SafeExamBrowser.I18n.UnitTests/Properties/AssemblyInfo.cs create mode 100644 SafeExamBrowser.I18n.UnitTests/SafeExamBrowser.I18n.UnitTests.csproj create mode 100644 SafeExamBrowser.I18n.UnitTests/TextTests.cs create mode 100644 SafeExamBrowser.I18n.UnitTests/Text_Incompatible.xml create mode 100644 SafeExamBrowser.I18n.UnitTests/Text_Invalid.txt create mode 100644 SafeExamBrowser.I18n.UnitTests/Text_Valid.xml create mode 100644 SafeExamBrowser.I18n.UnitTests/XmlTextResourceTests.cs create mode 100644 SafeExamBrowser.I18n.UnitTests/app.config create mode 100644 SafeExamBrowser.I18n.UnitTests/packages.config create mode 100644 SafeExamBrowser.I18n/Data/de.xml create mode 100644 SafeExamBrowser.I18n/Data/en.xml create mode 100644 SafeExamBrowser.I18n/Data/es.xml create mode 100644 SafeExamBrowser.I18n/Data/et.xml create mode 100644 SafeExamBrowser.I18n/Data/fr.xml create mode 100644 SafeExamBrowser.I18n/Data/id.xml create mode 100644 SafeExamBrowser.I18n/Data/it.xml create mode 100644 SafeExamBrowser.I18n/Data/nl.xml create mode 100644 SafeExamBrowser.I18n/Data/ru.xml create mode 100644 SafeExamBrowser.I18n/Data/zh.xml create mode 100644 SafeExamBrowser.I18n/Properties/AssemblyInfo.cs create mode 100644 SafeExamBrowser.I18n/SafeExamBrowser.I18n.csproj create mode 100644 SafeExamBrowser.I18n/Text.cs create mode 100644 SafeExamBrowser.I18n/XmlTextResource.cs create mode 100644 SafeExamBrowser.Lockdown.Contracts/FeatureConfigurationStatus.cs create mode 100644 SafeExamBrowser.Lockdown.Contracts/IAutoRestoreMechanism.cs create mode 100644 SafeExamBrowser.Lockdown.Contracts/IFeatureConfiguration.cs create mode 100644 SafeExamBrowser.Lockdown.Contracts/IFeatureConfigurationBackup.cs create mode 100644 SafeExamBrowser.Lockdown.Contracts/IFeatureConfigurationFactory.cs create mode 100644 SafeExamBrowser.Lockdown.Contracts/IFeatureConfigurationMonitor.cs create mode 100644 SafeExamBrowser.Lockdown.Contracts/ISystemConfigurationUpdate.cs create mode 100644 SafeExamBrowser.Lockdown.Contracts/Properties/AssemblyInfo.cs create mode 100644 SafeExamBrowser.Lockdown.Contracts/SafeExamBrowser.Lockdown.Contracts.csproj create mode 100644 SafeExamBrowser.Lockdown.UnitTests/AutoRestoreMechanismTests.cs create mode 100644 SafeExamBrowser.Lockdown.UnitTests/FeatureConfigurationBackupTests.cs create mode 100644 SafeExamBrowser.Lockdown.UnitTests/FeatureConfigurationMonitorTests.cs create mode 100644 SafeExamBrowser.Lockdown.UnitTests/FeatureConfigurationStub.cs create mode 100644 SafeExamBrowser.Lockdown.UnitTests/Properties/AssemblyInfo.cs create mode 100644 SafeExamBrowser.Lockdown.UnitTests/SafeExamBrowser.Lockdown.UnitTests.csproj create mode 100644 SafeExamBrowser.Lockdown.UnitTests/app.config create mode 100644 SafeExamBrowser.Lockdown.UnitTests/packages.config create mode 100644 SafeExamBrowser.Lockdown/AutoRestoreMechanism.cs create mode 100644 SafeExamBrowser.Lockdown/FeatureConfigurationBackup.cs create mode 100644 SafeExamBrowser.Lockdown/FeatureConfigurationFactory.cs create mode 100644 SafeExamBrowser.Lockdown/FeatureConfigurationMonitor.cs create mode 100644 SafeExamBrowser.Lockdown/FeatureConfigurations/FeatureConfiguration.cs create mode 100644 SafeExamBrowser.Lockdown/FeatureConfigurations/RegistryConfigurations/MachineHive/EaseOfAccessConfiguration.cs create mode 100644 SafeExamBrowser.Lockdown/FeatureConfigurations/RegistryConfigurations/MachineHive/MachineHiveConfiguration.cs create mode 100644 SafeExamBrowser.Lockdown/FeatureConfigurations/RegistryConfigurations/MachineHive/MachinePowerOptionsConfiguration.cs create mode 100644 SafeExamBrowser.Lockdown/FeatureConfigurations/RegistryConfigurations/MachineHive/NetworkOptionsConfiguration.cs create mode 100644 SafeExamBrowser.Lockdown/FeatureConfigurations/RegistryConfigurations/MachineHive/RemoteConnectionConfiguration.cs create mode 100644 SafeExamBrowser.Lockdown/FeatureConfigurations/RegistryConfigurations/MachineHive/SwitchUserConfiguration.cs create mode 100644 SafeExamBrowser.Lockdown/FeatureConfigurations/RegistryConfigurations/RegistryConfiguration.cs create mode 100644 SafeExamBrowser.Lockdown/FeatureConfigurations/RegistryConfigurations/RegistryConfigurationItem.cs create mode 100644 SafeExamBrowser.Lockdown/FeatureConfigurations/RegistryConfigurations/RegistryDataItem.cs create mode 100644 SafeExamBrowser.Lockdown/FeatureConfigurations/RegistryConfigurations/UserHive/ChangePasswordConfiguration.cs create mode 100644 SafeExamBrowser.Lockdown/FeatureConfigurations/RegistryConfigurations/UserHive/ChromeNotificationConfiguration.cs create mode 100644 SafeExamBrowser.Lockdown/FeatureConfigurations/RegistryConfigurations/UserHive/FindPrinterConfiguration.cs create mode 100644 SafeExamBrowser.Lockdown/FeatureConfigurations/RegistryConfigurations/UserHive/LockWorkstationConfiguration.cs create mode 100644 SafeExamBrowser.Lockdown/FeatureConfigurations/RegistryConfigurations/UserHive/SignoutConfiguration.cs create mode 100644 SafeExamBrowser.Lockdown/FeatureConfigurations/RegistryConfigurations/UserHive/TaskManagerConfiguration.cs create mode 100644 SafeExamBrowser.Lockdown/FeatureConfigurations/RegistryConfigurations/UserHive/UserHiveConfiguration.cs create mode 100644 SafeExamBrowser.Lockdown/FeatureConfigurations/RegistryConfigurations/UserHive/UserPowerOptionsConfiguration.cs create mode 100644 SafeExamBrowser.Lockdown/FeatureConfigurations/RegistryConfigurations/UserHive/VmwareOverlayConfiguration.cs create mode 100644 SafeExamBrowser.Lockdown/FeatureConfigurations/ServiceConfigurations/ServiceConfiguration.cs create mode 100644 SafeExamBrowser.Lockdown/FeatureConfigurations/ServiceConfigurations/ServiceConfigurationItem.cs create mode 100644 SafeExamBrowser.Lockdown/FeatureConfigurations/ServiceConfigurations/ServiceDataItem.cs create mode 100644 SafeExamBrowser.Lockdown/FeatureConfigurations/ServiceConfigurations/ServiceStatus.cs create mode 100644 SafeExamBrowser.Lockdown/FeatureConfigurations/ServiceConfigurations/WindowsUpdateConfiguration.cs create mode 100644 SafeExamBrowser.Lockdown/Properties/AssemblyInfo.cs create mode 100644 SafeExamBrowser.Lockdown/SafeExamBrowser.Lockdown.csproj create mode 100644 SafeExamBrowser.Lockdown/SystemConfigurationUpdate.cs create mode 100644 SafeExamBrowser.Logging.Contracts/ILogContent.cs create mode 100644 SafeExamBrowser.Logging.Contracts/ILogContentFormatter.cs create mode 100644 SafeExamBrowser.Logging.Contracts/ILogMessage.cs create mode 100644 SafeExamBrowser.Logging.Contracts/ILogObserver.cs create mode 100644 SafeExamBrowser.Logging.Contracts/ILogText.cs create mode 100644 SafeExamBrowser.Logging.Contracts/ILogger.cs create mode 100644 SafeExamBrowser.Logging.Contracts/IModuleLogger.cs create mode 100644 SafeExamBrowser.Logging.Contracts/IThreadInfo.cs create mode 100644 SafeExamBrowser.Logging.Contracts/Properties/AssemblyInfo.cs create mode 100644 SafeExamBrowser.Logging.Contracts/SafeExamBrowser.Logging.Contracts.csproj create mode 100644 SafeExamBrowser.Logging.UnitTests/DefaultLogFormatterTests.cs create mode 100644 SafeExamBrowser.Logging.UnitTests/LoggerTests.cs create mode 100644 SafeExamBrowser.Logging.UnitTests/ModuleLoggerTests.cs create mode 100644 SafeExamBrowser.Logging.UnitTests/NewLogContentType.cs create mode 100644 SafeExamBrowser.Logging.UnitTests/Properties/AssemblyInfo.cs create mode 100644 SafeExamBrowser.Logging.UnitTests/SafeExamBrowser.Logging.UnitTests.csproj create mode 100644 SafeExamBrowser.Logging.UnitTests/app.config create mode 100644 SafeExamBrowser.Logging.UnitTests/packages.config create mode 100644 SafeExamBrowser.Logging/DefaultLogFormatter.cs create mode 100644 SafeExamBrowser.Logging/LogFileWriter.cs create mode 100644 SafeExamBrowser.Logging/LogMessage.cs create mode 100644 SafeExamBrowser.Logging/LogText.cs create mode 100644 SafeExamBrowser.Logging/Logger.cs create mode 100644 SafeExamBrowser.Logging/ModuleLogger.cs create mode 100644 SafeExamBrowser.Logging/Properties/AssemblyInfo.cs create mode 100644 SafeExamBrowser.Logging/SafeExamBrowser.Logging.csproj create mode 100644 SafeExamBrowser.Logging/ThreadInfo.cs create mode 100644 SafeExamBrowser.Monitoring.Contracts/Applications/ActiveApplication.cs create mode 100644 SafeExamBrowser.Monitoring.Contracts/Applications/Events/ExplorerStartedEventHandler.cs create mode 100644 SafeExamBrowser.Monitoring.Contracts/Applications/Events/InstanceStartedEventHandler.cs create mode 100644 SafeExamBrowser.Monitoring.Contracts/Applications/Events/TerminationFailedEventHandler.cs create mode 100644 SafeExamBrowser.Monitoring.Contracts/Applications/IApplicationMonitor.cs create mode 100644 SafeExamBrowser.Monitoring.Contracts/Applications/IWindow.cs create mode 100644 SafeExamBrowser.Monitoring.Contracts/Applications/InitializationResult.cs create mode 100644 SafeExamBrowser.Monitoring.Contracts/Applications/RunningApplication.cs create mode 100644 SafeExamBrowser.Monitoring.Contracts/Display/Events/DisplayChangedEventHandler.cs create mode 100644 SafeExamBrowser.Monitoring.Contracts/Display/IDisplayMonitor.cs create mode 100644 SafeExamBrowser.Monitoring.Contracts/Display/ValidationResult.cs create mode 100644 SafeExamBrowser.Monitoring.Contracts/IClipboard.cs create mode 100644 SafeExamBrowser.Monitoring.Contracts/IRemoteSessionDetector.cs create mode 100644 SafeExamBrowser.Monitoring.Contracts/IVirtualMachineDetector.cs create mode 100644 SafeExamBrowser.Monitoring.Contracts/Keyboard/IKeyboardInterceptor.cs create mode 100644 SafeExamBrowser.Monitoring.Contracts/Mouse/IMouseInterceptor.cs create mode 100644 SafeExamBrowser.Monitoring.Contracts/Properties/AssemblyInfo.cs create mode 100644 SafeExamBrowser.Monitoring.Contracts/SafeExamBrowser.Monitoring.Contracts.csproj create mode 100644 SafeExamBrowser.Monitoring.Contracts/System/Events/SentinelEventArgs.cs create mode 100644 SafeExamBrowser.Monitoring.Contracts/System/Events/SentinelEventHandler.cs create mode 100644 SafeExamBrowser.Monitoring.Contracts/System/Events/SessionChangedEventHandler.cs create mode 100644 SafeExamBrowser.Monitoring.Contracts/System/ISystemSentinel.cs create mode 100644 SafeExamBrowser.Monitoring/Applications/ApplicationMonitor.cs create mode 100644 SafeExamBrowser.Monitoring/Applications/Window.cs create mode 100644 SafeExamBrowser.Monitoring/Clipboard.cs create mode 100644 SafeExamBrowser.Monitoring/Display/Bounds.cs create mode 100644 SafeExamBrowser.Monitoring/Display/Display.cs create mode 100644 SafeExamBrowser.Monitoring/Display/DisplayMonitor.cs create mode 100644 SafeExamBrowser.Monitoring/Display/VideoOutputTechnology.cs create mode 100644 SafeExamBrowser.Monitoring/Keyboard/KeyboardInterceptor.cs create mode 100644 SafeExamBrowser.Monitoring/Mouse/MouseInterceptor.cs create mode 100644 SafeExamBrowser.Monitoring/Properties/AssemblyInfo.cs create mode 100644 SafeExamBrowser.Monitoring/RemoteSessionDetector.cs create mode 100644 SafeExamBrowser.Monitoring/SafeExamBrowser.Monitoring.csproj create mode 100644 SafeExamBrowser.Monitoring/System/Components/Cursors.cs create mode 100644 SafeExamBrowser.Monitoring/System/Components/EaseOfAccess.cs create mode 100644 SafeExamBrowser.Monitoring/System/Components/StickyKeys.cs create mode 100644 SafeExamBrowser.Monitoring/System/Components/SystemEvents.cs create mode 100644 SafeExamBrowser.Monitoring/System/SystemSentinel.cs create mode 100644 SafeExamBrowser.Monitoring/VirtualMachineDetector.cs create mode 100644 SafeExamBrowser.Proctoring.Contracts/Events/ProctoringEventHandler.cs create mode 100644 SafeExamBrowser.Proctoring.Contracts/Events/RemainingWorkUpdatedEventArgs.cs create mode 100644 SafeExamBrowser.Proctoring.Contracts/Events/RemainingWorkUpdatedEventHandler.cs create mode 100644 SafeExamBrowser.Proctoring.Contracts/IProctoringController.cs create mode 100644 SafeExamBrowser.Proctoring.Contracts/Properties/AssemblyInfo.cs create mode 100644 SafeExamBrowser.Proctoring.Contracts/SafeExamBrowser.Proctoring.Contracts.csproj create mode 100644 SafeExamBrowser.Proctoring/ProctoringController.cs create mode 100644 SafeExamBrowser.Proctoring/ProctoringFactory.cs create mode 100644 SafeExamBrowser.Proctoring/ProctoringImplementation.cs create mode 100644 SafeExamBrowser.Proctoring/Properties/AssemblyInfo.cs create mode 100644 SafeExamBrowser.Proctoring/SafeExamBrowser.Proctoring.csproj create mode 100644 SafeExamBrowser.Proctoring/ScreenProctoring/Buffer.cs create mode 100644 SafeExamBrowser.Proctoring/ScreenProctoring/Cache.cs create mode 100644 SafeExamBrowser.Proctoring/ScreenProctoring/Data/IntervalTrigger.cs create mode 100644 SafeExamBrowser.Proctoring/ScreenProctoring/Data/KeyboardTrigger.cs create mode 100644 SafeExamBrowser.Proctoring/ScreenProctoring/Data/MetaDataAggregator.cs create mode 100644 SafeExamBrowser.Proctoring/ScreenProctoring/Data/Metadata.cs create mode 100644 SafeExamBrowser.Proctoring/ScreenProctoring/Data/MouseTrigger.cs create mode 100644 SafeExamBrowser.Proctoring/ScreenProctoring/DataCollector.cs create mode 100644 SafeExamBrowser.Proctoring/ScreenProctoring/Events/DataCollectedEventHandler.cs create mode 100644 SafeExamBrowser.Proctoring/ScreenProctoring/Imaging/Extensions.cs create mode 100644 SafeExamBrowser.Proctoring/ScreenProctoring/Imaging/ProcessingOrder.cs create mode 100644 SafeExamBrowser.Proctoring/ScreenProctoring/Imaging/ScreenShot.cs create mode 100644 SafeExamBrowser.Proctoring/ScreenProctoring/Imaging/ScreenShotProcessor.cs create mode 100644 SafeExamBrowser.Proctoring/ScreenProctoring/ScreenProctoringImplementation.cs create mode 100644 SafeExamBrowser.Proctoring/ScreenProctoring/Service/Api.cs create mode 100644 SafeExamBrowser.Proctoring/ScreenProctoring/Service/Parser.cs create mode 100644 SafeExamBrowser.Proctoring/ScreenProctoring/Service/Requests/ContentType.cs create mode 100644 SafeExamBrowser.Proctoring/ScreenProctoring/Service/Requests/CreateSessionRequest.cs create mode 100644 SafeExamBrowser.Proctoring/ScreenProctoring/Service/Requests/Extensions.cs create mode 100644 SafeExamBrowser.Proctoring/ScreenProctoring/Service/Requests/Header.cs create mode 100644 SafeExamBrowser.Proctoring/ScreenProctoring/Service/Requests/HealthRequest.cs create mode 100644 SafeExamBrowser.Proctoring/ScreenProctoring/Service/Requests/OAuth2TokenRequest.cs create mode 100644 SafeExamBrowser.Proctoring/ScreenProctoring/Service/Requests/Request.cs create mode 100644 SafeExamBrowser.Proctoring/ScreenProctoring/Service/Requests/ScreenShotRequest.cs create mode 100644 SafeExamBrowser.Proctoring/ScreenProctoring/Service/Requests/TerminateSessionRequest.cs create mode 100644 SafeExamBrowser.Proctoring/ScreenProctoring/Service/ServiceProxy.cs create mode 100644 SafeExamBrowser.Proctoring/ScreenProctoring/Service/ServiceResponse.cs create mode 100644 SafeExamBrowser.Proctoring/ScreenProctoring/TransmissionSpooler.cs create mode 100644 SafeExamBrowser.Proctoring/packages.config create mode 100644 SafeExamBrowser.ResetUtility/App.config create mode 100644 SafeExamBrowser.ResetUtility/CompositionRoot.cs create mode 100644 SafeExamBrowser.ResetUtility/NativeMethods.cs create mode 100644 SafeExamBrowser.ResetUtility/Procedure/Initialization.cs create mode 100644 SafeExamBrowser.ResetUtility/Procedure/Log.cs create mode 100644 SafeExamBrowser.ResetUtility/Procedure/MainMenu.cs create mode 100644 SafeExamBrowser.ResetUtility/Procedure/MainMenuOption.cs create mode 100644 SafeExamBrowser.ResetUtility/Procedure/MenuOption.cs create mode 100644 SafeExamBrowser.ResetUtility/Procedure/ProcedureContext.cs create mode 100644 SafeExamBrowser.ResetUtility/Procedure/ProcedureStep.cs create mode 100644 SafeExamBrowser.ResetUtility/Procedure/ProcedureStepResult.cs create mode 100644 SafeExamBrowser.ResetUtility/Procedure/Reset.cs create mode 100644 SafeExamBrowser.ResetUtility/Procedure/Restore.cs create mode 100644 SafeExamBrowser.ResetUtility/Procedure/Version.cs create mode 100644 SafeExamBrowser.ResetUtility/Program.cs create mode 100644 SafeExamBrowser.ResetUtility/Properties/AssemblyInfo.cs create mode 100644 SafeExamBrowser.ResetUtility/ResetUtility.ico create mode 100644 SafeExamBrowser.ResetUtility/SafeExamBrowser.ResetUtility.csproj create mode 100644 SafeExamBrowser.ResetUtility/app.manifest create mode 100644 SafeExamBrowser.Runtime.UnitTests/Communication/RuntimeHostTests.cs create mode 100644 SafeExamBrowser.Runtime.UnitTests/Operations/ClientOperationTests.cs create mode 100644 SafeExamBrowser.Runtime.UnitTests/Operations/ClientTerminationOperationTests.cs create mode 100644 SafeExamBrowser.Runtime.UnitTests/Operations/ConfigurationOperationTests.cs create mode 100644 SafeExamBrowser.Runtime.UnitTests/Operations/DisclaimerOperationTests.cs create mode 100644 SafeExamBrowser.Runtime.UnitTests/Operations/DisplayMonitorOperationTests.cs create mode 100644 SafeExamBrowser.Runtime.UnitTests/Operations/KioskModeOperationTests.cs create mode 100644 SafeExamBrowser.Runtime.UnitTests/Operations/RemoteSessionOperationTests.cs create mode 100644 SafeExamBrowser.Runtime.UnitTests/Operations/ServerOperationTests.cs create mode 100644 SafeExamBrowser.Runtime.UnitTests/Operations/ServiceOperationTests.cs create mode 100644 SafeExamBrowser.Runtime.UnitTests/Operations/SessionActivationOperationTests.cs create mode 100644 SafeExamBrowser.Runtime.UnitTests/Operations/SessionInitializationOperationTests.cs create mode 100644 SafeExamBrowser.Runtime.UnitTests/Operations/Testdata/SebClientSettings.seb create mode 100644 SafeExamBrowser.Runtime.UnitTests/Operations/VirtualMachineOperationTests.cs create mode 100644 SafeExamBrowser.Runtime.UnitTests/Properties/AssemblyInfo.cs create mode 100644 SafeExamBrowser.Runtime.UnitTests/RuntimeControllerTests.cs create mode 100644 SafeExamBrowser.Runtime.UnitTests/SafeExamBrowser.Runtime.UnitTests.csproj create mode 100644 SafeExamBrowser.Runtime.UnitTests/app.config create mode 100644 SafeExamBrowser.Runtime.UnitTests/packages.config create mode 100644 SafeExamBrowser.Runtime/App.config create mode 100644 SafeExamBrowser.Runtime/App.cs create mode 100644 SafeExamBrowser.Runtime/Communication/RuntimeHost.cs create mode 100644 SafeExamBrowser.Runtime/CompositionRoot.cs create mode 100644 SafeExamBrowser.Runtime/Operations/ApplicationIntegrityOperation.cs create mode 100644 SafeExamBrowser.Runtime/Operations/ClientOperation.cs create mode 100644 SafeExamBrowser.Runtime/Operations/ClientTerminationOperation.cs create mode 100644 SafeExamBrowser.Runtime/Operations/ConfigurationBaseOperation.cs create mode 100644 SafeExamBrowser.Runtime/Operations/ConfigurationOperation.cs create mode 100644 SafeExamBrowser.Runtime/Operations/DisclaimerOperation.cs create mode 100644 SafeExamBrowser.Runtime/Operations/DisplayMonitorOperation.cs create mode 100644 SafeExamBrowser.Runtime/Operations/Events/ClientConfigurationErrorMessageArgs.cs create mode 100644 SafeExamBrowser.Runtime/Operations/Events/ConfigurationCompletedEventArgs.cs create mode 100644 SafeExamBrowser.Runtime/Operations/Events/ExamSelectionEventArgs.cs create mode 100644 SafeExamBrowser.Runtime/Operations/Events/InvalidDataMessageArgs.cs create mode 100644 SafeExamBrowser.Runtime/Operations/Events/InvalidPasswordMessageArgs.cs create mode 100644 SafeExamBrowser.Runtime/Operations/Events/MessageEventArgs.cs create mode 100644 SafeExamBrowser.Runtime/Operations/Events/NotSupportedMessageArgs.cs create mode 100644 SafeExamBrowser.Runtime/Operations/Events/PasswordRequiredEventArgs.cs create mode 100644 SafeExamBrowser.Runtime/Operations/Events/ServerFailureEventArgs.cs create mode 100644 SafeExamBrowser.Runtime/Operations/Events/UnexpectedErrorMessageArgs.cs create mode 100644 SafeExamBrowser.Runtime/Operations/Events/VersionRestrictionMessageArgs.cs create mode 100644 SafeExamBrowser.Runtime/Operations/KioskModeOperation.cs create mode 100644 SafeExamBrowser.Runtime/Operations/RemoteSessionOperation.cs create mode 100644 SafeExamBrowser.Runtime/Operations/ServerOperation.cs create mode 100644 SafeExamBrowser.Runtime/Operations/ServiceOperation.cs create mode 100644 SafeExamBrowser.Runtime/Operations/SessionActivationOperation.cs create mode 100644 SafeExamBrowser.Runtime/Operations/SessionInitializationOperation.cs create mode 100644 SafeExamBrowser.Runtime/Operations/SessionIntegrityOperation.cs create mode 100644 SafeExamBrowser.Runtime/Operations/SessionOperation.cs create mode 100644 SafeExamBrowser.Runtime/Operations/VersionRestrictionOperation.cs create mode 100644 SafeExamBrowser.Runtime/Operations/VirtualMachineOperation.cs create mode 100644 SafeExamBrowser.Runtime/Properties/AssemblyInfo.cs create mode 100644 SafeExamBrowser.Runtime/Properties/Resources.Designer.cs create mode 100644 SafeExamBrowser.Runtime/Properties/Resources.resx create mode 100644 SafeExamBrowser.Runtime/Properties/Settings.Designer.cs create mode 100644 SafeExamBrowser.Runtime/Properties/Settings.settings create mode 100644 SafeExamBrowser.Runtime/RuntimeController.cs create mode 100644 SafeExamBrowser.Runtime/SafeExamBrowser.Runtime.csproj create mode 100644 SafeExamBrowser.Runtime/SafeExamBrowser.ico create mode 100644 SafeExamBrowser.Runtime/SessionContext.cs create mode 100644 SafeExamBrowser.Runtime/app.manifest create mode 100644 SafeExamBrowser.Runtime/packages.config create mode 100644 SafeExamBrowser.Server.Contracts/Data/ConnectionInfo.cs create mode 100644 SafeExamBrowser.Server.Contracts/Data/Exam.cs create mode 100644 SafeExamBrowser.Server.Contracts/Data/ServerResponse.cs create mode 100644 SafeExamBrowser.Server.Contracts/Events/LockScreenRequestedEventHandler.cs create mode 100644 SafeExamBrowser.Server.Contracts/Events/Proctoring/InstructionEventArgs.cs create mode 100644 SafeExamBrowser.Server.Contracts/Events/Proctoring/InstructionMethod.cs create mode 100644 SafeExamBrowser.Server.Contracts/Events/Proctoring/JitsiMeetInstruction.cs create mode 100644 SafeExamBrowser.Server.Contracts/Events/Proctoring/ProctoringConfigurationReceivedEventHandler.cs create mode 100644 SafeExamBrowser.Server.Contracts/Events/Proctoring/ProctoringInstructionReceivedEventHandler.cs create mode 100644 SafeExamBrowser.Server.Contracts/Events/Proctoring/ScreenProctoringInstruction.cs create mode 100644 SafeExamBrowser.Server.Contracts/Events/Proctoring/ZoomInstruction.cs create mode 100644 SafeExamBrowser.Server.Contracts/Events/ServerEventHandler.cs create mode 100644 SafeExamBrowser.Server.Contracts/Events/TerminationRequestedEventHandler.cs create mode 100644 SafeExamBrowser.Server.Contracts/IServerProxy.cs create mode 100644 SafeExamBrowser.Server.Contracts/Properties/AssemblyInfo.cs create mode 100644 SafeExamBrowser.Server.Contracts/SafeExamBrowser.Server.Contracts.csproj create mode 100644 SafeExamBrowser.Server/Data/ApiVersion1.cs create mode 100644 SafeExamBrowser.Server/Data/AttributeType.cs create mode 100644 SafeExamBrowser.Server/Data/Attributes.cs create mode 100644 SafeExamBrowser.Server/Data/Instructions.cs create mode 100644 SafeExamBrowser.Server/Extensions.cs create mode 100644 SafeExamBrowser.Server/FileSystem.cs create mode 100644 SafeExamBrowser.Server/Parser.cs create mode 100644 SafeExamBrowser.Server/Properties/AssemblyInfo.cs create mode 100644 SafeExamBrowser.Server/Requests/ApiRequest.cs create mode 100644 SafeExamBrowser.Server/Requests/AppSignatureKeyRequest.cs create mode 100644 SafeExamBrowser.Server/Requests/AvailableExamsRequest.cs create mode 100644 SafeExamBrowser.Server/Requests/BaseRequest.cs create mode 100644 SafeExamBrowser.Server/Requests/ConfirmLockScreenRequest.cs create mode 100644 SafeExamBrowser.Server/Requests/ContentType.cs create mode 100644 SafeExamBrowser.Server/Requests/DisconnectionRequest.cs create mode 100644 SafeExamBrowser.Server/Requests/ExamConfigurationRequest.cs create mode 100644 SafeExamBrowser.Server/Requests/Header.cs create mode 100644 SafeExamBrowser.Server/Requests/LockScreenRequest.cs create mode 100644 SafeExamBrowser.Server/Requests/LogRequest.cs create mode 100644 SafeExamBrowser.Server/Requests/LowerHandRequest.cs create mode 100644 SafeExamBrowser.Server/Requests/NetworkAdapterRequest.cs create mode 100644 SafeExamBrowser.Server/Requests/OAuth2TokenRequest.cs create mode 100644 SafeExamBrowser.Server/Requests/PingRequest.cs create mode 100644 SafeExamBrowser.Server/Requests/PowerSupplyRequest.cs create mode 100644 SafeExamBrowser.Server/Requests/RaiseHandRequest.cs create mode 100644 SafeExamBrowser.Server/Requests/SelectExamRequest.cs create mode 100644 SafeExamBrowser.Server/Requests/UserIdentifierRequest.cs create mode 100644 SafeExamBrowser.Server/SafeExamBrowser.Server.csproj create mode 100644 SafeExamBrowser.Server/ServerProxy.cs create mode 100644 SafeExamBrowser.Server/packages.config create mode 100644 SafeExamBrowser.Service.UnitTests/Communication/ServiceHostTests.cs create mode 100644 SafeExamBrowser.Service.UnitTests/Operations/EventStub.cs create mode 100644 SafeExamBrowser.Service.UnitTests/Operations/LockdownOperationTests.cs create mode 100644 SafeExamBrowser.Service.UnitTests/Operations/RestoreOperationTests.cs create mode 100644 SafeExamBrowser.Service.UnitTests/Operations/ServiceEventCleanupOperationTests.cs create mode 100644 SafeExamBrowser.Service.UnitTests/Operations/SessionActivationOperationTests.cs create mode 100644 SafeExamBrowser.Service.UnitTests/Operations/SessionInitializationOperationTests.cs create mode 100644 SafeExamBrowser.Service.UnitTests/Properties/AssemblyInfo.cs create mode 100644 SafeExamBrowser.Service.UnitTests/SafeExamBrowser.Service.UnitTests.csproj create mode 100644 SafeExamBrowser.Service.UnitTests/ServiceControllerTests.cs create mode 100644 SafeExamBrowser.Service.UnitTests/app.config create mode 100644 SafeExamBrowser.Service.UnitTests/packages.config create mode 100644 SafeExamBrowser.Service/App.config create mode 100644 SafeExamBrowser.Service/Communication/ServiceHost.cs create mode 100644 SafeExamBrowser.Service/CompositionRoot.cs create mode 100644 SafeExamBrowser.Service/Installer.cs create mode 100644 SafeExamBrowser.Service/Operations/LockdownOperation.cs create mode 100644 SafeExamBrowser.Service/Operations/RestoreOperation.cs create mode 100644 SafeExamBrowser.Service/Operations/ServiceEventCleanupOperation.cs create mode 100644 SafeExamBrowser.Service/Operations/SessionActivationOperation.cs create mode 100644 SafeExamBrowser.Service/Operations/SessionInitializationOperation.cs create mode 100644 SafeExamBrowser.Service/Operations/SessionOperation.cs create mode 100644 SafeExamBrowser.Service/Properties/AssemblyInfo.cs create mode 100644 SafeExamBrowser.Service/SafeExamBrowser.Service.csproj create mode 100644 SafeExamBrowser.Service/SafeExamBrowser.ico create mode 100644 SafeExamBrowser.Service/Service.cs create mode 100644 SafeExamBrowser.Service/ServiceController.cs create mode 100644 SafeExamBrowser.Service/SessionContext.cs create mode 100644 SafeExamBrowser.Settings/AppSettings.cs create mode 100644 SafeExamBrowser.Settings/Applications/ApplicationSettings.cs create mode 100644 SafeExamBrowser.Settings/Applications/BlacklistApplication.cs create mode 100644 SafeExamBrowser.Settings/Applications/WhitelistApplication.cs create mode 100644 SafeExamBrowser.Settings/Browser/BrowserSettings.cs create mode 100644 SafeExamBrowser.Settings/Browser/Filter/FilterResult.cs create mode 100644 SafeExamBrowser.Settings/Browser/Filter/FilterRuleSettings.cs create mode 100644 SafeExamBrowser.Settings/Browser/Filter/FilterRuleType.cs create mode 100644 SafeExamBrowser.Settings/Browser/FilterSettings.cs create mode 100644 SafeExamBrowser.Settings/Browser/PopupPolicy.cs create mode 100644 SafeExamBrowser.Settings/Browser/Proxy/ProxyConfiguration.cs create mode 100644 SafeExamBrowser.Settings/Browser/Proxy/ProxyPolicy.cs create mode 100644 SafeExamBrowser.Settings/Browser/Proxy/ProxyProtocol.cs create mode 100644 SafeExamBrowser.Settings/Browser/ProxySettings.cs create mode 100644 SafeExamBrowser.Settings/Browser/UrlPolicy.cs create mode 100644 SafeExamBrowser.Settings/Browser/WindowPosition.cs create mode 100644 SafeExamBrowser.Settings/Browser/WindowSettings.cs create mode 100644 SafeExamBrowser.Settings/ConfigurationMode.cs create mode 100644 SafeExamBrowser.Settings/Logging/LogLevel.cs create mode 100644 SafeExamBrowser.Settings/Monitoring/DisplaySettings.cs create mode 100644 SafeExamBrowser.Settings/Monitoring/KeyboardSettings.cs create mode 100644 SafeExamBrowser.Settings/Monitoring/MouseSettings.cs create mode 100644 SafeExamBrowser.Settings/Proctoring/ImageFormat.cs create mode 100644 SafeExamBrowser.Settings/Proctoring/ImageQuantization.cs create mode 100644 SafeExamBrowser.Settings/Proctoring/MetaDataSettings.cs create mode 100644 SafeExamBrowser.Settings/Proctoring/ProctoringSettings.cs create mode 100644 SafeExamBrowser.Settings/Proctoring/ScreenProctoringSettings.cs create mode 100644 SafeExamBrowser.Settings/Properties/AssemblyInfo.cs create mode 100644 SafeExamBrowser.Settings/SafeExamBrowser.Settings.csproj create mode 100644 SafeExamBrowser.Settings/Security/ClipboardPolicy.cs create mode 100644 SafeExamBrowser.Settings/Security/KioskMode.cs create mode 100644 SafeExamBrowser.Settings/Security/SecuritySettings.cs create mode 100644 SafeExamBrowser.Settings/Security/VersionRestriction.cs create mode 100644 SafeExamBrowser.Settings/Security/VirtualMachinePolicy.cs create mode 100644 SafeExamBrowser.Settings/Server/ServerSettings.cs create mode 100644 SafeExamBrowser.Settings/Service/ServicePolicy.cs create mode 100644 SafeExamBrowser.Settings/Service/ServiceSettings.cs create mode 100644 SafeExamBrowser.Settings/SessionMode.cs create mode 100644 SafeExamBrowser.Settings/System/SystemSettings.cs create mode 100644 SafeExamBrowser.Settings/SystemComponents/AudioSettings.cs create mode 100644 SafeExamBrowser.Settings/SystemComponents/PowerSupplySettings.cs create mode 100644 SafeExamBrowser.Settings/UserInterface/ActionCenterSettings.cs create mode 100644 SafeExamBrowser.Settings/UserInterface/LockScreenSettings.cs create mode 100644 SafeExamBrowser.Settings/UserInterface/TaskbarSettings.cs create mode 100644 SafeExamBrowser.Settings/UserInterface/UserInterfaceMode.cs create mode 100644 SafeExamBrowser.Settings/UserInterface/UserInterfaceSettings.cs create mode 100644 SafeExamBrowser.SystemComponents.Contracts/Audio/Events/VolumeChangedEventHandler.cs create mode 100644 SafeExamBrowser.SystemComponents.Contracts/Audio/IAudio.cs create mode 100644 SafeExamBrowser.SystemComponents.Contracts/IFileSystem.cs create mode 100644 SafeExamBrowser.SystemComponents.Contracts/ISystemComponent.cs create mode 100644 SafeExamBrowser.SystemComponents.Contracts/ISystemInfo.cs create mode 100644 SafeExamBrowser.SystemComponents.Contracts/IUserInfo.cs create mode 100644 SafeExamBrowser.SystemComponents.Contracts/Keyboard/Events/LayoutChangedEventHandler.cs create mode 100644 SafeExamBrowser.SystemComponents.Contracts/Keyboard/IKeyboard.cs create mode 100644 SafeExamBrowser.SystemComponents.Contracts/Keyboard/IKeyboardLayout.cs create mode 100644 SafeExamBrowser.SystemComponents.Contracts/Network/ConnectionStatus.cs create mode 100644 SafeExamBrowser.SystemComponents.Contracts/Network/ConnectionType.cs create mode 100644 SafeExamBrowser.SystemComponents.Contracts/Network/Events/ChangedEventHandler.cs create mode 100644 SafeExamBrowser.SystemComponents.Contracts/Network/Events/CredentialsRequiredEventArgs.cs create mode 100644 SafeExamBrowser.SystemComponents.Contracts/Network/Events/CredentialsRequiredEventHandler.cs create mode 100644 SafeExamBrowser.SystemComponents.Contracts/Network/INetworkAdapter.cs create mode 100644 SafeExamBrowser.SystemComponents.Contracts/Network/IWirelessNetwork.cs create mode 100644 SafeExamBrowser.SystemComponents.Contracts/OperatingSystem.cs create mode 100644 SafeExamBrowser.SystemComponents.Contracts/PowerSupply/BatteryChargeStatus.cs create mode 100644 SafeExamBrowser.SystemComponents.Contracts/PowerSupply/Events/StatusChangedEventHandler.cs create mode 100644 SafeExamBrowser.SystemComponents.Contracts/PowerSupply/IPowerSupply.cs create mode 100644 SafeExamBrowser.SystemComponents.Contracts/PowerSupply/IPowerSupplyStatus.cs create mode 100644 SafeExamBrowser.SystemComponents.Contracts/Properties/AssemblyInfo.cs create mode 100644 SafeExamBrowser.SystemComponents.Contracts/Registry/Events/RegistryValueChangedEventHandler.cs create mode 100644 SafeExamBrowser.SystemComponents.Contracts/Registry/IRegistry.cs create mode 100644 SafeExamBrowser.SystemComponents.Contracts/Registry/RegistryValue.cs create mode 100644 SafeExamBrowser.SystemComponents.Contracts/SafeExamBrowser.SystemComponents.Contracts.csproj create mode 100644 SafeExamBrowser.SystemComponents/Audio/Audio.cs create mode 100644 SafeExamBrowser.SystemComponents/FileSystem.cs create mode 100644 SafeExamBrowser.SystemComponents/Keyboard/Keyboard.cs create mode 100644 SafeExamBrowser.SystemComponents/Keyboard/KeyboardLayout.cs create mode 100644 SafeExamBrowser.SystemComponents/Network/Extensions.cs create mode 100644 SafeExamBrowser.SystemComponents/Network/NetworkAdapter.cs create mode 100644 SafeExamBrowser.SystemComponents/Network/WirelessNetwork.cs create mode 100644 SafeExamBrowser.SystemComponents/PowerSupply/PowerSupply.cs create mode 100644 SafeExamBrowser.SystemComponents/PowerSupply/PowerSupplyStatus.cs create mode 100644 SafeExamBrowser.SystemComponents/Properties/AssemblyInfo.cs create mode 100644 SafeExamBrowser.SystemComponents/Registry/Registry.cs create mode 100644 SafeExamBrowser.SystemComponents/SafeExamBrowser.SystemComponents.csproj create mode 100644 SafeExamBrowser.SystemComponents/SystemInfo.cs create mode 100644 SafeExamBrowser.SystemComponents/UserInfo.cs create mode 100644 SafeExamBrowser.SystemComponents/app.config create mode 100644 SafeExamBrowser.UserInterface.Contracts/Browser/Data/DownloadItemState.cs create mode 100644 SafeExamBrowser.UserInterface.Contracts/Browser/Data/JavascriptResult.cs create mode 100644 SafeExamBrowser.UserInterface.Contracts/Browser/Events/AddressChangedEventHandler.cs create mode 100644 SafeExamBrowser.UserInterface.Contracts/Browser/Events/FindRequestedEventHandler.cs create mode 100644 SafeExamBrowser.UserInterface.Contracts/Browser/Events/LoadFailedEventHandler.cs create mode 100644 SafeExamBrowser.UserInterface.Contracts/Browser/Events/LoadingStateChangedEventHandler.cs create mode 100644 SafeExamBrowser.UserInterface.Contracts/Browser/Events/TitleChangedEventHandler.cs create mode 100644 SafeExamBrowser.UserInterface.Contracts/Browser/IBrowserControl.cs create mode 100644 SafeExamBrowser.UserInterface.Contracts/Browser/IBrowserWindow.cs create mode 100644 SafeExamBrowser.UserInterface.Contracts/Events/ActionRequestedEventHandler.cs create mode 100644 SafeExamBrowser.UserInterface.Contracts/FileSystemDialog/FileSystemDialogResult.cs create mode 100644 SafeExamBrowser.UserInterface.Contracts/FileSystemDialog/FileSystemElement.cs create mode 100644 SafeExamBrowser.UserInterface.Contracts/FileSystemDialog/FileSystemOperation.cs create mode 100644 SafeExamBrowser.UserInterface.Contracts/FileSystemDialog/IFileSystemDialog.cs create mode 100644 SafeExamBrowser.UserInterface.Contracts/IProgressIndicator.cs create mode 100644 SafeExamBrowser.UserInterface.Contracts/IUserInterfaceFactory.cs create mode 100644 SafeExamBrowser.UserInterface.Contracts/MessageBox/IMessageBox.cs create mode 100644 SafeExamBrowser.UserInterface.Contracts/MessageBox/MessageBoxAction.cs create mode 100644 SafeExamBrowser.UserInterface.Contracts/MessageBox/MessageBoxIcon.cs create mode 100644 SafeExamBrowser.UserInterface.Contracts/MessageBox/MessageBoxResult.cs create mode 100644 SafeExamBrowser.UserInterface.Contracts/Proctoring/Events/FullScreenChangedEventHandler.cs create mode 100644 SafeExamBrowser.UserInterface.Contracts/Proctoring/IProctoringControl.cs create mode 100644 SafeExamBrowser.UserInterface.Contracts/Proctoring/IProctoringFinalizationDialog.cs create mode 100644 SafeExamBrowser.UserInterface.Contracts/Proctoring/IProctoringWindow.cs create mode 100644 SafeExamBrowser.UserInterface.Contracts/Properties/AssemblyInfo.cs create mode 100644 SafeExamBrowser.UserInterface.Contracts/SafeExamBrowser.UserInterface.Contracts.csproj create mode 100644 SafeExamBrowser.UserInterface.Contracts/Shell/Events/ActivatorEventHandler.cs create mode 100644 SafeExamBrowser.UserInterface.Contracts/Shell/Events/QuitButtonClickedEventHandler.cs create mode 100644 SafeExamBrowser.UserInterface.Contracts/Shell/IActionCenter.cs create mode 100644 SafeExamBrowser.UserInterface.Contracts/Shell/IActionCenterActivator.cs create mode 100644 SafeExamBrowser.UserInterface.Contracts/Shell/IActivator.cs create mode 100644 SafeExamBrowser.UserInterface.Contracts/Shell/IApplicationControl.cs create mode 100644 SafeExamBrowser.UserInterface.Contracts/Shell/INotificationControl.cs create mode 100644 SafeExamBrowser.UserInterface.Contracts/Shell/ISystemControl.cs create mode 100644 SafeExamBrowser.UserInterface.Contracts/Shell/ITaskView.cs create mode 100644 SafeExamBrowser.UserInterface.Contracts/Shell/ITaskViewActivator.cs create mode 100644 SafeExamBrowser.UserInterface.Contracts/Shell/ITaskbar.cs create mode 100644 SafeExamBrowser.UserInterface.Contracts/Shell/ITaskbarActivator.cs create mode 100644 SafeExamBrowser.UserInterface.Contracts/Shell/ITerminationActivator.cs create mode 100644 SafeExamBrowser.UserInterface.Contracts/Shell/Location.cs create mode 100644 SafeExamBrowser.UserInterface.Contracts/Windows/Data/CredentialsDialogPurpose.cs create mode 100644 SafeExamBrowser.UserInterface.Contracts/Windows/Data/CredentialsDialogResult.cs create mode 100644 SafeExamBrowser.UserInterface.Contracts/Windows/Data/ExamSelectionDialogResult.cs create mode 100644 SafeExamBrowser.UserInterface.Contracts/Windows/Data/LockScreenOption.cs create mode 100644 SafeExamBrowser.UserInterface.Contracts/Windows/Data/LockScreenResult.cs create mode 100644 SafeExamBrowser.UserInterface.Contracts/Windows/Data/PasswordDialogResult.cs create mode 100644 SafeExamBrowser.UserInterface.Contracts/Windows/Data/ServerFailureDialogResult.cs create mode 100644 SafeExamBrowser.UserInterface.Contracts/Windows/Events/WindowClosedEventHandler.cs create mode 100644 SafeExamBrowser.UserInterface.Contracts/Windows/Events/WindowClosingEventHandler.cs create mode 100644 SafeExamBrowser.UserInterface.Contracts/Windows/ICredentialsDialog.cs create mode 100644 SafeExamBrowser.UserInterface.Contracts/Windows/IExamSelectionDialog.cs create mode 100644 SafeExamBrowser.UserInterface.Contracts/Windows/ILockScreen.cs create mode 100644 SafeExamBrowser.UserInterface.Contracts/Windows/IPasswordDialog.cs create mode 100644 SafeExamBrowser.UserInterface.Contracts/Windows/IRuntimeWindow.cs create mode 100644 SafeExamBrowser.UserInterface.Contracts/Windows/IServerFailureDialog.cs create mode 100644 SafeExamBrowser.UserInterface.Contracts/Windows/ISplashScreen.cs create mode 100644 SafeExamBrowser.UserInterface.Contracts/Windows/IWindow.cs create mode 100644 SafeExamBrowser.UserInterface.Desktop/Controls/ActionCenter/ApplicationButton.xaml create mode 100644 SafeExamBrowser.UserInterface.Desktop/Controls/ActionCenter/ApplicationButton.xaml.cs create mode 100644 SafeExamBrowser.UserInterface.Desktop/Controls/ActionCenter/ApplicationControl.xaml create mode 100644 SafeExamBrowser.UserInterface.Desktop/Controls/ActionCenter/ApplicationControl.xaml.cs create mode 100644 SafeExamBrowser.UserInterface.Desktop/Controls/ActionCenter/AudioControl.xaml create mode 100644 SafeExamBrowser.UserInterface.Desktop/Controls/ActionCenter/AudioControl.xaml.cs create mode 100644 SafeExamBrowser.UserInterface.Desktop/Controls/ActionCenter/Clock.xaml create mode 100644 SafeExamBrowser.UserInterface.Desktop/Controls/ActionCenter/Clock.xaml.cs create mode 100644 SafeExamBrowser.UserInterface.Desktop/Controls/ActionCenter/KeyboardLayoutButton.xaml create mode 100644 SafeExamBrowser.UserInterface.Desktop/Controls/ActionCenter/KeyboardLayoutButton.xaml.cs create mode 100644 SafeExamBrowser.UserInterface.Desktop/Controls/ActionCenter/KeyboardLayoutControl.xaml create mode 100644 SafeExamBrowser.UserInterface.Desktop/Controls/ActionCenter/KeyboardLayoutControl.xaml.cs create mode 100644 SafeExamBrowser.UserInterface.Desktop/Controls/ActionCenter/NetworkButton.xaml create mode 100644 SafeExamBrowser.UserInterface.Desktop/Controls/ActionCenter/NetworkButton.xaml.cs create mode 100644 SafeExamBrowser.UserInterface.Desktop/Controls/ActionCenter/NetworkControl.xaml create mode 100644 SafeExamBrowser.UserInterface.Desktop/Controls/ActionCenter/NetworkControl.xaml.cs create mode 100644 SafeExamBrowser.UserInterface.Desktop/Controls/ActionCenter/NotificationButton.xaml create mode 100644 SafeExamBrowser.UserInterface.Desktop/Controls/ActionCenter/NotificationButton.xaml.cs create mode 100644 SafeExamBrowser.UserInterface.Desktop/Controls/ActionCenter/PowerSupplyControl.xaml create mode 100644 SafeExamBrowser.UserInterface.Desktop/Controls/ActionCenter/PowerSupplyControl.xaml.cs create mode 100644 SafeExamBrowser.UserInterface.Desktop/Controls/ActionCenter/QuitButton.xaml create mode 100644 SafeExamBrowser.UserInterface.Desktop/Controls/ActionCenter/QuitButton.xaml.cs create mode 100644 SafeExamBrowser.UserInterface.Desktop/Controls/ActionCenter/RaiseHandControl.xaml create mode 100644 SafeExamBrowser.UserInterface.Desktop/Controls/ActionCenter/RaiseHandControl.xaml.cs create mode 100644 SafeExamBrowser.UserInterface.Desktop/Controls/Browser/DownloadItemControl.xaml create mode 100644 SafeExamBrowser.UserInterface.Desktop/Controls/Browser/DownloadItemControl.xaml.cs create mode 100644 SafeExamBrowser.UserInterface.Desktop/Controls/Taskbar/ApplicationControl.xaml create mode 100644 SafeExamBrowser.UserInterface.Desktop/Controls/Taskbar/ApplicationControl.xaml.cs create mode 100644 SafeExamBrowser.UserInterface.Desktop/Controls/Taskbar/ApplicationWindowButton.xaml create mode 100644 SafeExamBrowser.UserInterface.Desktop/Controls/Taskbar/ApplicationWindowButton.xaml.cs create mode 100644 SafeExamBrowser.UserInterface.Desktop/Controls/Taskbar/AudioControl.xaml create mode 100644 SafeExamBrowser.UserInterface.Desktop/Controls/Taskbar/AudioControl.xaml.cs create mode 100644 SafeExamBrowser.UserInterface.Desktop/Controls/Taskbar/Clock.xaml create mode 100644 SafeExamBrowser.UserInterface.Desktop/Controls/Taskbar/Clock.xaml.cs create mode 100644 SafeExamBrowser.UserInterface.Desktop/Controls/Taskbar/KeyboardLayoutButton.xaml create mode 100644 SafeExamBrowser.UserInterface.Desktop/Controls/Taskbar/KeyboardLayoutButton.xaml.cs create mode 100644 SafeExamBrowser.UserInterface.Desktop/Controls/Taskbar/KeyboardLayoutControl.xaml create mode 100644 SafeExamBrowser.UserInterface.Desktop/Controls/Taskbar/KeyboardLayoutControl.xaml.cs create mode 100644 SafeExamBrowser.UserInterface.Desktop/Controls/Taskbar/NetworkButton.xaml create mode 100644 SafeExamBrowser.UserInterface.Desktop/Controls/Taskbar/NetworkButton.xaml.cs create mode 100644 SafeExamBrowser.UserInterface.Desktop/Controls/Taskbar/NetworkControl.xaml create mode 100644 SafeExamBrowser.UserInterface.Desktop/Controls/Taskbar/NetworkControl.xaml.cs create mode 100644 SafeExamBrowser.UserInterface.Desktop/Controls/Taskbar/NotificationButton.xaml create mode 100644 SafeExamBrowser.UserInterface.Desktop/Controls/Taskbar/NotificationButton.xaml.cs create mode 100644 SafeExamBrowser.UserInterface.Desktop/Controls/Taskbar/PowerSupplyControl.xaml create mode 100644 SafeExamBrowser.UserInterface.Desktop/Controls/Taskbar/PowerSupplyControl.xaml.cs create mode 100644 SafeExamBrowser.UserInterface.Desktop/Controls/Taskbar/QuitButton.xaml create mode 100644 SafeExamBrowser.UserInterface.Desktop/Controls/Taskbar/QuitButton.xaml.cs create mode 100644 SafeExamBrowser.UserInterface.Desktop/Controls/Taskbar/RaiseHandControl.xaml create mode 100644 SafeExamBrowser.UserInterface.Desktop/Controls/Taskbar/RaiseHandControl.xaml.cs create mode 100644 SafeExamBrowser.UserInterface.Desktop/Controls/Taskview/WindowControl.xaml create mode 100644 SafeExamBrowser.UserInterface.Desktop/Controls/Taskview/WindowControl.xaml.cs create mode 100644 SafeExamBrowser.UserInterface.Desktop/FileSystemDialogFactory.cs create mode 100644 SafeExamBrowser.UserInterface.Desktop/Images/AboutNotification.xaml create mode 100644 SafeExamBrowser.UserInterface.Desktop/Images/Audio_100.xaml create mode 100644 SafeExamBrowser.UserInterface.Desktop/Images/Audio_33.xaml create mode 100644 SafeExamBrowser.UserInterface.Desktop/Images/Audio_66.xaml create mode 100644 SafeExamBrowser.UserInterface.Desktop/Images/Audio_Light_100.xaml create mode 100644 SafeExamBrowser.UserInterface.Desktop/Images/Audio_Light_33.xaml create mode 100644 SafeExamBrowser.UserInterface.Desktop/Images/Audio_Light_66.xaml create mode 100644 SafeExamBrowser.UserInterface.Desktop/Images/Audio_Light_NoDevice.xaml create mode 100644 SafeExamBrowser.UserInterface.Desktop/Images/Audio_Muted.xaml create mode 100644 SafeExamBrowser.UserInterface.Desktop/Images/Audio_NoDevice.xaml create mode 100644 SafeExamBrowser.UserInterface.Desktop/Images/Battery.xaml create mode 100644 SafeExamBrowser.UserInterface.Desktop/Images/Hand_Lowered.xaml create mode 100644 SafeExamBrowser.UserInterface.Desktop/Images/Hand_Raised.xaml create mode 100644 SafeExamBrowser.UserInterface.Desktop/Images/Home.xaml create mode 100644 SafeExamBrowser.UserInterface.Desktop/Images/Keyboard.xaml create mode 100644 SafeExamBrowser.UserInterface.Desktop/Images/LogNotification.ico create mode 100644 SafeExamBrowser.UserInterface.Desktop/Images/Menu.xaml create mode 100644 SafeExamBrowser.UserInterface.Desktop/Images/NavigateBack.xaml create mode 100644 SafeExamBrowser.UserInterface.Desktop/Images/NavigateForward.xaml create mode 100644 SafeExamBrowser.UserInterface.Desktop/Images/Proctoring_Active.xaml create mode 100644 SafeExamBrowser.UserInterface.Desktop/Images/Proctoring_Inactive.xaml create mode 100644 SafeExamBrowser.UserInterface.Desktop/Images/Reload.xaml create mode 100644 SafeExamBrowser.UserInterface.Desktop/Images/SafeExamBrowser.ico create mode 100644 SafeExamBrowser.UserInterface.Desktop/Images/ScreenProctoring_Active.xaml create mode 100644 SafeExamBrowser.UserInterface.Desktop/Images/ScreenProctoring_Inactive.xaml create mode 100644 SafeExamBrowser.UserInterface.Desktop/Images/ShutDown.xaml create mode 100644 SafeExamBrowser.UserInterface.Desktop/Images/SplashScreen.png create mode 100644 SafeExamBrowser.UserInterface.Desktop/Images/WiFi_0.xaml create mode 100644 SafeExamBrowser.UserInterface.Desktop/Images/WiFi_100.xaml create mode 100644 SafeExamBrowser.UserInterface.Desktop/Images/WiFi_33.xaml create mode 100644 SafeExamBrowser.UserInterface.Desktop/Images/WiFi_66.xaml create mode 100644 SafeExamBrowser.UserInterface.Desktop/Images/WiFi_Light_0.xaml create mode 100644 SafeExamBrowser.UserInterface.Desktop/Images/WiFi_Light_100.xaml create mode 100644 SafeExamBrowser.UserInterface.Desktop/Images/WiFi_Light_33.xaml create mode 100644 SafeExamBrowser.UserInterface.Desktop/Images/WiFi_Light_66.xaml create mode 100644 SafeExamBrowser.UserInterface.Desktop/Images/ZoomPageIn.xaml create mode 100644 SafeExamBrowser.UserInterface.Desktop/Images/ZoomPageOut.xaml create mode 100644 SafeExamBrowser.UserInterface.Desktop/MessageBoxFactory.cs create mode 100644 SafeExamBrowser.UserInterface.Desktop/Properties/AssemblyInfo.cs create mode 100644 SafeExamBrowser.UserInterface.Desktop/SafeExamBrowser.UserInterface.Desktop.csproj create mode 100644 SafeExamBrowser.UserInterface.Desktop/Templates/Buttons.xaml create mode 100644 SafeExamBrowser.UserInterface.Desktop/Templates/Colors.xaml create mode 100644 SafeExamBrowser.UserInterface.Desktop/Templates/ScrollViewers.xaml create mode 100644 SafeExamBrowser.UserInterface.Desktop/UserInterfaceFactory.cs create mode 100644 SafeExamBrowser.UserInterface.Desktop/ViewModels/DateTimeViewModel.cs create mode 100644 SafeExamBrowser.UserInterface.Desktop/ViewModels/LogViewModel.cs create mode 100644 SafeExamBrowser.UserInterface.Desktop/ViewModels/ProgressIndicatorViewModel.cs create mode 100644 SafeExamBrowser.UserInterface.Desktop/ViewModels/RuntimeWindowViewModel.cs create mode 100644 SafeExamBrowser.UserInterface.Desktop/Windows/AboutWindow.xaml create mode 100644 SafeExamBrowser.UserInterface.Desktop/Windows/AboutWindow.xaml.cs create mode 100644 SafeExamBrowser.UserInterface.Desktop/Windows/ActionCenter.xaml create mode 100644 SafeExamBrowser.UserInterface.Desktop/Windows/ActionCenter.xaml.cs create mode 100644 SafeExamBrowser.UserInterface.Desktop/Windows/BrowserWindow.xaml create mode 100644 SafeExamBrowser.UserInterface.Desktop/Windows/BrowserWindow.xaml.cs create mode 100644 SafeExamBrowser.UserInterface.Desktop/Windows/CredentialsDialog.xaml create mode 100644 SafeExamBrowser.UserInterface.Desktop/Windows/CredentialsDialog.xaml.cs create mode 100644 SafeExamBrowser.UserInterface.Desktop/Windows/ExamSelectionDialog.xaml create mode 100644 SafeExamBrowser.UserInterface.Desktop/Windows/ExamSelectionDialog.xaml.cs create mode 100644 SafeExamBrowser.UserInterface.Desktop/Windows/FileSystemDialog.xaml create mode 100644 SafeExamBrowser.UserInterface.Desktop/Windows/FileSystemDialog.xaml.cs create mode 100644 SafeExamBrowser.UserInterface.Desktop/Windows/LockScreen.xaml create mode 100644 SafeExamBrowser.UserInterface.Desktop/Windows/LockScreen.xaml.cs create mode 100644 SafeExamBrowser.UserInterface.Desktop/Windows/LogWindow.xaml create mode 100644 SafeExamBrowser.UserInterface.Desktop/Windows/LogWindow.xaml.cs create mode 100644 SafeExamBrowser.UserInterface.Desktop/Windows/PasswordDialog.xaml create mode 100644 SafeExamBrowser.UserInterface.Desktop/Windows/PasswordDialog.xaml.cs create mode 100644 SafeExamBrowser.UserInterface.Desktop/Windows/ProctoringFinalizationDialog.xaml create mode 100644 SafeExamBrowser.UserInterface.Desktop/Windows/ProctoringFinalizationDialog.xaml.cs create mode 100644 SafeExamBrowser.UserInterface.Desktop/Windows/ProctoringWindow.xaml create mode 100644 SafeExamBrowser.UserInterface.Desktop/Windows/ProctoringWindow.xaml.cs create mode 100644 SafeExamBrowser.UserInterface.Desktop/Windows/RuntimeWindow.xaml create mode 100644 SafeExamBrowser.UserInterface.Desktop/Windows/RuntimeWindow.xaml.cs create mode 100644 SafeExamBrowser.UserInterface.Desktop/Windows/ServerFailureDialog.xaml create mode 100644 SafeExamBrowser.UserInterface.Desktop/Windows/ServerFailureDialog.xaml.cs create mode 100644 SafeExamBrowser.UserInterface.Desktop/Windows/SplashScreen.xaml create mode 100644 SafeExamBrowser.UserInterface.Desktop/Windows/SplashScreen.xaml.cs create mode 100644 SafeExamBrowser.UserInterface.Desktop/Windows/Taskbar.xaml create mode 100644 SafeExamBrowser.UserInterface.Desktop/Windows/Taskbar.xaml.cs create mode 100644 SafeExamBrowser.UserInterface.Desktop/Windows/Taskview.xaml create mode 100644 SafeExamBrowser.UserInterface.Desktop/Windows/Taskview.xaml.cs create mode 100644 SafeExamBrowser.UserInterface.Desktop/app.config create mode 100644 SafeExamBrowser.UserInterface.Desktop/packages.config create mode 100644 SafeExamBrowser.UserInterface.Mobile/Controls/ActionCenter/ApplicationButton.xaml create mode 100644 SafeExamBrowser.UserInterface.Mobile/Controls/ActionCenter/ApplicationButton.xaml.cs create mode 100644 SafeExamBrowser.UserInterface.Mobile/Controls/ActionCenter/ApplicationControl.xaml create mode 100644 SafeExamBrowser.UserInterface.Mobile/Controls/ActionCenter/ApplicationControl.xaml.cs create mode 100644 SafeExamBrowser.UserInterface.Mobile/Controls/ActionCenter/AudioControl.xaml create mode 100644 SafeExamBrowser.UserInterface.Mobile/Controls/ActionCenter/AudioControl.xaml.cs create mode 100644 SafeExamBrowser.UserInterface.Mobile/Controls/ActionCenter/Clock.xaml create mode 100644 SafeExamBrowser.UserInterface.Mobile/Controls/ActionCenter/Clock.xaml.cs create mode 100644 SafeExamBrowser.UserInterface.Mobile/Controls/ActionCenter/KeyboardLayoutButton.xaml create mode 100644 SafeExamBrowser.UserInterface.Mobile/Controls/ActionCenter/KeyboardLayoutButton.xaml.cs create mode 100644 SafeExamBrowser.UserInterface.Mobile/Controls/ActionCenter/KeyboardLayoutControl.xaml create mode 100644 SafeExamBrowser.UserInterface.Mobile/Controls/ActionCenter/KeyboardLayoutControl.xaml.cs create mode 100644 SafeExamBrowser.UserInterface.Mobile/Controls/ActionCenter/NetworkButton.xaml create mode 100644 SafeExamBrowser.UserInterface.Mobile/Controls/ActionCenter/NetworkButton.xaml.cs create mode 100644 SafeExamBrowser.UserInterface.Mobile/Controls/ActionCenter/NetworkControl.xaml create mode 100644 SafeExamBrowser.UserInterface.Mobile/Controls/ActionCenter/NetworkControl.xaml.cs create mode 100644 SafeExamBrowser.UserInterface.Mobile/Controls/ActionCenter/NotificationButton.xaml create mode 100644 SafeExamBrowser.UserInterface.Mobile/Controls/ActionCenter/NotificationButton.xaml.cs create mode 100644 SafeExamBrowser.UserInterface.Mobile/Controls/ActionCenter/PowerSupplyControl.xaml create mode 100644 SafeExamBrowser.UserInterface.Mobile/Controls/ActionCenter/PowerSupplyControl.xaml.cs create mode 100644 SafeExamBrowser.UserInterface.Mobile/Controls/ActionCenter/QuitButton.xaml create mode 100644 SafeExamBrowser.UserInterface.Mobile/Controls/ActionCenter/QuitButton.xaml.cs create mode 100644 SafeExamBrowser.UserInterface.Mobile/Controls/ActionCenter/RaiseHandControl.xaml create mode 100644 SafeExamBrowser.UserInterface.Mobile/Controls/ActionCenter/RaiseHandControl.xaml.cs create mode 100644 SafeExamBrowser.UserInterface.Mobile/Controls/Browser/DownloadItemControl.xaml create mode 100644 SafeExamBrowser.UserInterface.Mobile/Controls/Browser/DownloadItemControl.xaml.cs create mode 100644 SafeExamBrowser.UserInterface.Mobile/Controls/Taskbar/ApplicationControl.xaml create mode 100644 SafeExamBrowser.UserInterface.Mobile/Controls/Taskbar/ApplicationControl.xaml.cs create mode 100644 SafeExamBrowser.UserInterface.Mobile/Controls/Taskbar/ApplicationWindowButton.xaml create mode 100644 SafeExamBrowser.UserInterface.Mobile/Controls/Taskbar/ApplicationWindowButton.xaml.cs create mode 100644 SafeExamBrowser.UserInterface.Mobile/Controls/Taskbar/AudioControl.xaml create mode 100644 SafeExamBrowser.UserInterface.Mobile/Controls/Taskbar/AudioControl.xaml.cs create mode 100644 SafeExamBrowser.UserInterface.Mobile/Controls/Taskbar/Clock.xaml create mode 100644 SafeExamBrowser.UserInterface.Mobile/Controls/Taskbar/Clock.xaml.cs create mode 100644 SafeExamBrowser.UserInterface.Mobile/Controls/Taskbar/KeyboardLayoutButton.xaml create mode 100644 SafeExamBrowser.UserInterface.Mobile/Controls/Taskbar/KeyboardLayoutButton.xaml.cs create mode 100644 SafeExamBrowser.UserInterface.Mobile/Controls/Taskbar/KeyboardLayoutControl.xaml create mode 100644 SafeExamBrowser.UserInterface.Mobile/Controls/Taskbar/KeyboardLayoutControl.xaml.cs create mode 100644 SafeExamBrowser.UserInterface.Mobile/Controls/Taskbar/NetworkButton.xaml create mode 100644 SafeExamBrowser.UserInterface.Mobile/Controls/Taskbar/NetworkButton.xaml.cs create mode 100644 SafeExamBrowser.UserInterface.Mobile/Controls/Taskbar/NetworkControl.xaml create mode 100644 SafeExamBrowser.UserInterface.Mobile/Controls/Taskbar/NetworkControl.xaml.cs create mode 100644 SafeExamBrowser.UserInterface.Mobile/Controls/Taskbar/NotificationButton.xaml create mode 100644 SafeExamBrowser.UserInterface.Mobile/Controls/Taskbar/NotificationButton.xaml.cs create mode 100644 SafeExamBrowser.UserInterface.Mobile/Controls/Taskbar/PowerSupplyControl.xaml create mode 100644 SafeExamBrowser.UserInterface.Mobile/Controls/Taskbar/PowerSupplyControl.xaml.cs create mode 100644 SafeExamBrowser.UserInterface.Mobile/Controls/Taskbar/QuitButton.xaml create mode 100644 SafeExamBrowser.UserInterface.Mobile/Controls/Taskbar/QuitButton.xaml.cs create mode 100644 SafeExamBrowser.UserInterface.Mobile/Controls/Taskbar/RaiseHandControl.xaml create mode 100644 SafeExamBrowser.UserInterface.Mobile/Controls/Taskbar/RaiseHandControl.xaml.cs create mode 100644 SafeExamBrowser.UserInterface.Mobile/Controls/Taskview/WindowControl.xaml create mode 100644 SafeExamBrowser.UserInterface.Mobile/Controls/Taskview/WindowControl.xaml.cs create mode 100644 SafeExamBrowser.UserInterface.Mobile/FileSystemDialogFactory.cs create mode 100644 SafeExamBrowser.UserInterface.Mobile/Images/AboutNotification.xaml create mode 100644 SafeExamBrowser.UserInterface.Mobile/Images/Audio_100.xaml create mode 100644 SafeExamBrowser.UserInterface.Mobile/Images/Audio_33.xaml create mode 100644 SafeExamBrowser.UserInterface.Mobile/Images/Audio_66.xaml create mode 100644 SafeExamBrowser.UserInterface.Mobile/Images/Audio_Light_100.xaml create mode 100644 SafeExamBrowser.UserInterface.Mobile/Images/Audio_Light_33.xaml create mode 100644 SafeExamBrowser.UserInterface.Mobile/Images/Audio_Light_66.xaml create mode 100644 SafeExamBrowser.UserInterface.Mobile/Images/Audio_Light_NoDevice.xaml create mode 100644 SafeExamBrowser.UserInterface.Mobile/Images/Audio_Muted.xaml create mode 100644 SafeExamBrowser.UserInterface.Mobile/Images/Audio_NoDevice.xaml create mode 100644 SafeExamBrowser.UserInterface.Mobile/Images/Battery.xaml create mode 100644 SafeExamBrowser.UserInterface.Mobile/Images/Hand_Lowered.xaml create mode 100644 SafeExamBrowser.UserInterface.Mobile/Images/Hand_Raised.xaml create mode 100644 SafeExamBrowser.UserInterface.Mobile/Images/Home.xaml create mode 100644 SafeExamBrowser.UserInterface.Mobile/Images/Keyboard.xaml create mode 100644 SafeExamBrowser.UserInterface.Mobile/Images/LogNotification.ico create mode 100644 SafeExamBrowser.UserInterface.Mobile/Images/Menu.xaml create mode 100644 SafeExamBrowser.UserInterface.Mobile/Images/NavigateBack.xaml create mode 100644 SafeExamBrowser.UserInterface.Mobile/Images/NavigateForward.xaml create mode 100644 SafeExamBrowser.UserInterface.Mobile/Images/Proctoring_Active.xaml create mode 100644 SafeExamBrowser.UserInterface.Mobile/Images/Proctoring_Inactive.xaml create mode 100644 SafeExamBrowser.UserInterface.Mobile/Images/Reload.xaml create mode 100644 SafeExamBrowser.UserInterface.Mobile/Images/SafeExamBrowser.ico create mode 100644 SafeExamBrowser.UserInterface.Mobile/Images/ScreenProctoring_Active.xaml create mode 100644 SafeExamBrowser.UserInterface.Mobile/Images/ScreenProctoring_Inactive.xaml create mode 100644 SafeExamBrowser.UserInterface.Mobile/Images/ShutDown.xaml create mode 100644 SafeExamBrowser.UserInterface.Mobile/Images/SplashScreen.png create mode 100644 SafeExamBrowser.UserInterface.Mobile/Images/WiFi_0.xaml create mode 100644 SafeExamBrowser.UserInterface.Mobile/Images/WiFi_100.xaml create mode 100644 SafeExamBrowser.UserInterface.Mobile/Images/WiFi_33.xaml create mode 100644 SafeExamBrowser.UserInterface.Mobile/Images/WiFi_66.xaml create mode 100644 SafeExamBrowser.UserInterface.Mobile/Images/WiFi_Light_0.xaml create mode 100644 SafeExamBrowser.UserInterface.Mobile/Images/WiFi_Light_100.xaml create mode 100644 SafeExamBrowser.UserInterface.Mobile/Images/WiFi_Light_33.xaml create mode 100644 SafeExamBrowser.UserInterface.Mobile/Images/WiFi_Light_66.xaml create mode 100644 SafeExamBrowser.UserInterface.Mobile/Images/ZoomPageIn.xaml create mode 100644 SafeExamBrowser.UserInterface.Mobile/Images/ZoomPageOut.xaml create mode 100644 SafeExamBrowser.UserInterface.Mobile/MessageBoxFactory.cs create mode 100644 SafeExamBrowser.UserInterface.Mobile/Properties/AssemblyInfo.cs create mode 100644 SafeExamBrowser.UserInterface.Mobile/SafeExamBrowser.UserInterface.Mobile.csproj create mode 100644 SafeExamBrowser.UserInterface.Mobile/Templates/Buttons.xaml create mode 100644 SafeExamBrowser.UserInterface.Mobile/Templates/Colors.xaml create mode 100644 SafeExamBrowser.UserInterface.Mobile/Templates/ScrollViewers.xaml create mode 100644 SafeExamBrowser.UserInterface.Mobile/UserInterfaceFactory.cs create mode 100644 SafeExamBrowser.UserInterface.Mobile/ViewModels/DateTimeViewModel.cs create mode 100644 SafeExamBrowser.UserInterface.Mobile/ViewModels/LogViewModel.cs create mode 100644 SafeExamBrowser.UserInterface.Mobile/ViewModels/ProgressIndicatorViewModel.cs create mode 100644 SafeExamBrowser.UserInterface.Mobile/ViewModels/RuntimeWindowViewModel.cs create mode 100644 SafeExamBrowser.UserInterface.Mobile/Windows/AboutWindow.xaml create mode 100644 SafeExamBrowser.UserInterface.Mobile/Windows/AboutWindow.xaml.cs create mode 100644 SafeExamBrowser.UserInterface.Mobile/Windows/ActionCenter.xaml create mode 100644 SafeExamBrowser.UserInterface.Mobile/Windows/ActionCenter.xaml.cs create mode 100644 SafeExamBrowser.UserInterface.Mobile/Windows/BrowserWindow.xaml create mode 100644 SafeExamBrowser.UserInterface.Mobile/Windows/BrowserWindow.xaml.cs create mode 100644 SafeExamBrowser.UserInterface.Mobile/Windows/CredentialsDialog.xaml create mode 100644 SafeExamBrowser.UserInterface.Mobile/Windows/CredentialsDialog.xaml.cs create mode 100644 SafeExamBrowser.UserInterface.Mobile/Windows/ExamSelectionDialog.xaml create mode 100644 SafeExamBrowser.UserInterface.Mobile/Windows/ExamSelectionDialog.xaml.cs create mode 100644 SafeExamBrowser.UserInterface.Mobile/Windows/FileSystemDialog.xaml create mode 100644 SafeExamBrowser.UserInterface.Mobile/Windows/FileSystemDialog.xaml.cs create mode 100644 SafeExamBrowser.UserInterface.Mobile/Windows/LockScreen.xaml create mode 100644 SafeExamBrowser.UserInterface.Mobile/Windows/LockScreen.xaml.cs create mode 100644 SafeExamBrowser.UserInterface.Mobile/Windows/LogWindow.xaml create mode 100644 SafeExamBrowser.UserInterface.Mobile/Windows/LogWindow.xaml.cs create mode 100644 SafeExamBrowser.UserInterface.Mobile/Windows/MessageBoxDialog.xaml create mode 100644 SafeExamBrowser.UserInterface.Mobile/Windows/MessageBoxDialog.xaml.cs create mode 100644 SafeExamBrowser.UserInterface.Mobile/Windows/PasswordDialog.xaml create mode 100644 SafeExamBrowser.UserInterface.Mobile/Windows/PasswordDialog.xaml.cs create mode 100644 SafeExamBrowser.UserInterface.Mobile/Windows/ProctoringFinalizationDialog.xaml create mode 100644 SafeExamBrowser.UserInterface.Mobile/Windows/ProctoringFinalizationDialog.xaml.cs create mode 100644 SafeExamBrowser.UserInterface.Mobile/Windows/ProctoringWindow.xaml create mode 100644 SafeExamBrowser.UserInterface.Mobile/Windows/ProctoringWindow.xaml.cs create mode 100644 SafeExamBrowser.UserInterface.Mobile/Windows/RuntimeWindow.xaml create mode 100644 SafeExamBrowser.UserInterface.Mobile/Windows/RuntimeWindow.xaml.cs create mode 100644 SafeExamBrowser.UserInterface.Mobile/Windows/ServerFailureDialog.xaml create mode 100644 SafeExamBrowser.UserInterface.Mobile/Windows/ServerFailureDialog.xaml.cs create mode 100644 SafeExamBrowser.UserInterface.Mobile/Windows/SplashScreen.xaml create mode 100644 SafeExamBrowser.UserInterface.Mobile/Windows/SplashScreen.xaml.cs create mode 100644 SafeExamBrowser.UserInterface.Mobile/Windows/Taskbar.xaml create mode 100644 SafeExamBrowser.UserInterface.Mobile/Windows/Taskbar.xaml.cs create mode 100644 SafeExamBrowser.UserInterface.Mobile/Windows/Taskview.xaml create mode 100644 SafeExamBrowser.UserInterface.Mobile/Windows/Taskview.xaml.cs create mode 100644 SafeExamBrowser.UserInterface.Mobile/packages.config create mode 100644 SafeExamBrowser.UserInterface.Shared/Activators/ActionCenterKeyboardActivator.cs create mode 100644 SafeExamBrowser.UserInterface.Shared/Activators/ActionCenterTouchActivator.cs create mode 100644 SafeExamBrowser.UserInterface.Shared/Activators/KeyboardActivator.cs create mode 100644 SafeExamBrowser.UserInterface.Shared/Activators/TaskViewKeyboardActivator.cs create mode 100644 SafeExamBrowser.UserInterface.Shared/Activators/TaskbarKeyboardActivator.cs create mode 100644 SafeExamBrowser.UserInterface.Shared/Activators/TerminationActivator.cs create mode 100644 SafeExamBrowser.UserInterface.Shared/Activators/TouchActivator.cs create mode 100644 SafeExamBrowser.UserInterface.Shared/Properties/AssemblyInfo.cs create mode 100644 SafeExamBrowser.UserInterface.Shared/SafeExamBrowser.UserInterface.Shared.csproj create mode 100644 SafeExamBrowser.UserInterface.Shared/Utilities/IconLoader.cs create mode 100644 SafeExamBrowser.UserInterface.Shared/Utilities/IconResourceLoader.cs create mode 100644 SafeExamBrowser.UserInterface.Shared/Utilities/Parser.cs create mode 100644 SafeExamBrowser.UserInterface.Shared/Utilities/Thumbnail.cs create mode 100644 SafeExamBrowser.UserInterface.Shared/Utilities/VisualExtensions.cs create mode 100644 SafeExamBrowser.UserInterface.Shared/Utilities/WindowExtensions.cs create mode 100644 SafeExamBrowser.WindowsApi.Contracts/Events/KeyModifier.cs create mode 100644 SafeExamBrowser.WindowsApi.Contracts/Events/KeyState.cs create mode 100644 SafeExamBrowser.WindowsApi.Contracts/Events/KeyboardHookCallback.cs create mode 100644 SafeExamBrowser.WindowsApi.Contracts/Events/MouseButton.cs create mode 100644 SafeExamBrowser.WindowsApi.Contracts/Events/MouseButtonState.cs create mode 100644 SafeExamBrowser.WindowsApi.Contracts/Events/MouseHookCallback.cs create mode 100644 SafeExamBrowser.WindowsApi.Contracts/Events/MouseInformation.cs create mode 100644 SafeExamBrowser.WindowsApi.Contracts/Events/ProcessTerminatedEventHandler.cs create mode 100644 SafeExamBrowser.WindowsApi.Contracts/Events/SystemEventCallback.cs create mode 100644 SafeExamBrowser.WindowsApi.Contracts/Events/TerminationActivatorEventHandler.cs create mode 100644 SafeExamBrowser.WindowsApi.Contracts/IBounds.cs create mode 100644 SafeExamBrowser.WindowsApi.Contracts/IDesktop.cs create mode 100644 SafeExamBrowser.WindowsApi.Contracts/IDesktopFactory.cs create mode 100644 SafeExamBrowser.WindowsApi.Contracts/IDesktopMonitor.cs create mode 100644 SafeExamBrowser.WindowsApi.Contracts/IExplorerShell.cs create mode 100644 SafeExamBrowser.WindowsApi.Contracts/INativeMethods.cs create mode 100644 SafeExamBrowser.WindowsApi.Contracts/IProcess.cs create mode 100644 SafeExamBrowser.WindowsApi.Contracts/IProcessFactory.cs create mode 100644 SafeExamBrowser.WindowsApi.Contracts/IStickyKeysState.cs create mode 100644 SafeExamBrowser.WindowsApi.Contracts/Properties/AssemblyInfo.cs create mode 100644 SafeExamBrowser.WindowsApi.Contracts/SafeExamBrowser.WindowsApi.Contracts.csproj create mode 100644 SafeExamBrowser.WindowsApi/Constants/AccessMask.cs create mode 100644 SafeExamBrowser.WindowsApi/Constants/Constant.cs create mode 100644 SafeExamBrowser.WindowsApi/Constants/HookType.cs create mode 100644 SafeExamBrowser.WindowsApi/Constants/SPI.cs create mode 100644 SafeExamBrowser.WindowsApi/Constants/SPIF.cs create mode 100644 SafeExamBrowser.WindowsApi/Constants/ShowWindowCommand.cs create mode 100644 SafeExamBrowser.WindowsApi/Constants/StickyKeysFlags.cs create mode 100644 SafeExamBrowser.WindowsApi/Constants/SystemCommand.cs create mode 100644 SafeExamBrowser.WindowsApi/Constants/ThreadAccess.cs create mode 100644 SafeExamBrowser.WindowsApi/Constants/VirtualKeyCode.cs create mode 100644 SafeExamBrowser.WindowsApi/Delegates/EnumDesktopDelegate.cs create mode 100644 SafeExamBrowser.WindowsApi/Delegates/EnumWindowsDelegate.cs create mode 100644 SafeExamBrowser.WindowsApi/Delegates/EventDelegate.cs create mode 100644 SafeExamBrowser.WindowsApi/Delegates/HookDelegate.cs create mode 100644 SafeExamBrowser.WindowsApi/Desktops/Desktop.cs create mode 100644 SafeExamBrowser.WindowsApi/Desktops/DesktopFactory.cs create mode 100644 SafeExamBrowser.WindowsApi/Desktops/DesktopMonitor.cs create mode 100644 SafeExamBrowser.WindowsApi/Desktops/ObfuscatedDesktop.cs create mode 100644 SafeExamBrowser.WindowsApi/ExplorerShell.cs create mode 100644 SafeExamBrowser.WindowsApi/Hooks/KeyboardHook.cs create mode 100644 SafeExamBrowser.WindowsApi/Hooks/MouseHook.cs create mode 100644 SafeExamBrowser.WindowsApi/Hooks/SystemHook.cs create mode 100644 SafeExamBrowser.WindowsApi/Kernel32.cs create mode 100644 SafeExamBrowser.WindowsApi/NativeMethods.cs create mode 100644 SafeExamBrowser.WindowsApi/Processes/Process.cs create mode 100644 SafeExamBrowser.WindowsApi/Processes/ProcessFactory.cs create mode 100644 SafeExamBrowser.WindowsApi/Properties/AssemblyInfo.cs create mode 100644 SafeExamBrowser.WindowsApi/SafeExamBrowser.WindowsApi.csproj create mode 100644 SafeExamBrowser.WindowsApi/Types/Bounds.cs create mode 100644 SafeExamBrowser.WindowsApi/Types/EXECUTION_STATE.cs create mode 100644 SafeExamBrowser.WindowsApi/Types/KBDLLHOOKSTRUCT.cs create mode 100644 SafeExamBrowser.WindowsApi/Types/KBDLLHOOKSTRUCTFlags.cs create mode 100644 SafeExamBrowser.WindowsApi/Types/MSLLHOOKSTRUCT.cs create mode 100644 SafeExamBrowser.WindowsApi/Types/POINT.cs create mode 100644 SafeExamBrowser.WindowsApi/Types/PROCESS_INFORMATION.cs create mode 100644 SafeExamBrowser.WindowsApi/Types/RECT.cs create mode 100644 SafeExamBrowser.WindowsApi/Types/STARTUPINFO.cs create mode 100644 SafeExamBrowser.WindowsApi/Types/STICKYKEYS.cs create mode 100644 SafeExamBrowser.WindowsApi/Types/StickyKeysState.cs create mode 100644 SafeExamBrowser.WindowsApi/Types/WINDOWPLACEMENT.cs create mode 100644 SafeExamBrowser.WindowsApi/Types/Window.cs create mode 100644 SafeExamBrowser.WindowsApi/User32.cs create mode 100644 SafeExamBrowser.WindowsApi/WinInet.cs create mode 100644 SafeExamBrowser.sln create mode 100644 SebWindowsConfig/ConfigurationTool.ico create mode 100644 SebWindowsConfig/Controls/AdditionalResources.Designer.cs create mode 100644 SebWindowsConfig/Controls/AdditionalResources.cs create mode 100644 SebWindowsConfig/Controls/AdditionalResources.resx create mode 100644 SebWindowsConfig/Controls/FilterRuleControl.Designer.cs create mode 100644 SebWindowsConfig/Controls/FilterRuleControl.cs create mode 100644 SebWindowsConfig/Controls/FilterRuleControl.resx create mode 100644 SebWindowsConfig/Entities/FilterAction.cs create mode 100644 SebWindowsConfig/Entities/FilterRule.cs create mode 100644 SebWindowsConfig/Entities/PermittedApplicationInformation.cs create mode 100644 SebWindowsConfig/Properties/AssemblyInfo.cs create mode 100644 SebWindowsConfig/Properties/Resources.Designer.cs create mode 100644 SebWindowsConfig/Properties/Resources.resx create mode 100644 SebWindowsConfig/Properties/Settings.Designer.cs create mode 100644 SebWindowsConfig/Properties/Settings.settings create mode 100644 SebWindowsConfig/SEBSettings.cs create mode 100644 SebWindowsConfig/SEBUIStrings.Designer.cs create mode 100644 SebWindowsConfig/SEBUIStrings.de.Designer.cs create mode 100644 SebWindowsConfig/SEBUIStrings.de.resx create mode 100644 SebWindowsConfig/SEBUIStrings.resx create mode 100644 SebWindowsConfig/SebPasswordDialogForm.Designer.cs create mode 100644 SebWindowsConfig/SebPasswordDialogForm.cs create mode 100644 SebWindowsConfig/SebPasswordDialogForm.de.resx create mode 100644 SebWindowsConfig/SebPasswordDialogForm.resx create mode 100644 SebWindowsConfig/SebWindowsConfig.csproj create mode 100644 SebWindowsConfig/SebWindowsConfigForm.Designer.cs create mode 100644 SebWindowsConfig/SebWindowsConfigForm.cs create mode 100644 SebWindowsConfig/SebWindowsConfigForm.resx create mode 100644 SebWindowsConfig/SebWindowsConfigGUIManagement.cs create mode 100644 SebWindowsConfig/SebWindowsConfigProgram.cs create mode 100644 SebWindowsConfig/TabIcons/32x32/IconHelp.png create mode 100644 SebWindowsConfig/TabIcons/32x32/Icon_01_General.png create mode 100644 SebWindowsConfig/TabIcons/32x32/Icon_02_ConfigFile.png create mode 100644 SebWindowsConfig/TabIcons/32x32/Icon_03_Appearance.png create mode 100644 SebWindowsConfig/TabIcons/32x32/Icon_04_Browser.png create mode 100644 SebWindowsConfig/TabIcons/32x32/Icon_05_DownUploads.png create mode 100644 SebWindowsConfig/TabIcons/32x32/Icon_06_Exam.png create mode 100644 SebWindowsConfig/TabIcons/32x32/Icon_07_Applications.png create mode 100644 SebWindowsConfig/TabIcons/32x32/Icon_07b_Resources.png create mode 100644 SebWindowsConfig/TabIcons/32x32/Icon_08_Network.png create mode 100644 SebWindowsConfig/TabIcons/32x32/Icon_09_Security.png create mode 100644 SebWindowsConfig/TabIcons/32x32/Icon_10_Registry.png create mode 100644 SebWindowsConfig/TabIcons/32x32/Icon_11_HookedKeys.png create mode 100644 SebWindowsConfig/Utilities/FileCompressor.cs create mode 100644 SebWindowsConfig/Utilities/IFileCompressor.cs create mode 100644 SebWindowsConfig/Utilities/LogCollector.cs create mode 100644 SebWindowsConfig/Utilities/Logger.cs create mode 100644 SebWindowsConfig/Utilities/Plist.cs create mode 100644 SebWindowsConfig/Utilities/SEBClientInfo.cs create mode 100644 SebWindowsConfig/Utilities/SEBConfigFileManager.cs create mode 100644 SebWindowsConfig/Utilities/SEBProtectionController.cs create mode 100644 SebWindowsConfig/Utilities/SEBURLFilter.cs create mode 100644 SebWindowsConfig/Utilities/SEBURLFilterExpression.cs create mode 100644 SebWindowsConfig/Utilities/SEBURLFilterRegexExpression.cs create mode 100644 SebWindowsConfig/app.config create mode 100644 SebWindowsConfig/packages.config create mode 100644 appveyor-release.yml create mode 100644 appveyor-test.yml create mode 100644 codecov.yml create mode 100644 patch-seb/App.config create mode 100644 patch-seb/Form1.Designer.cs create mode 100644 patch-seb/Form1.cs create mode 100644 patch-seb/Form1.resx create mode 100644 patch-seb/Program.cs create mode 100644 patch-seb/Properties/AssemblyInfo.cs create mode 100644 patch-seb/Properties/Resources.Designer.cs create mode 100644 patch-seb/Properties/Resources.resx create mode 100644 patch-seb/Properties/Settings.Designer.cs create mode 100644 patch-seb/Properties/Settings.settings create mode 100644 patch-seb/SafeExamBrowser.ico create mode 100644 patch-seb/app.manifest create mode 100644 patch-seb/patch-seb.csproj diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..013bd17 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,135 @@ +# Defines coding style deviations from the Microsoft Minimum Recommended Rules ruleset, which is active per default in Visual Studio 2017 +# For more info, see https://editorconfig.org/ and https://docs.microsoft.com/en-us/visualstudio/ide/create-portable-custom-editor-options + +root = true + +[*] +end_of_line = crlf +dotnet_style_operator_placement_when_wrapping = beginning_of_line +tab_width = 4 +indent_size = 4 +dotnet_style_coalesce_expression = true:suggestion +dotnet_style_null_propagation = true:suggestion +dotnet_style_prefer_is_null_check_over_reference_equality_method = true:suggestion +dotnet_style_prefer_auto_properties = true:silent +dotnet_style_object_initializer = false:none +dotnet_style_collection_initializer = true:suggestion +dotnet_style_prefer_simplified_boolean_expressions = true:suggestion +dotnet_style_prefer_conditional_expression_over_assignment = true:silent +dotnet_style_prefer_conditional_expression_over_return = true:silent +dotnet_style_explicit_tuple_names = true:suggestion +dotnet_style_prefer_inferred_tuple_names = true:suggestion +dotnet_style_prefer_inferred_anonymous_type_member_names = true:suggestion +dotnet_style_prefer_compound_assignment = true:suggestion +dotnet_style_prefer_simplified_interpolation = true:suggestion +dotnet_style_namespace_match_folder = true:suggestion + +[*.cs] +dotnet_style_object_initializer = false:none +indent_style = tab +csharp_indent_labels = one_less_than_current +csharp_using_directive_placement = outside_namespace:silent +csharp_prefer_simple_using_statement = true:suggestion +csharp_prefer_braces = true:silent +csharp_style_namespace_declarations = block_scoped:silent +csharp_style_expression_bodied_methods = false:silent +csharp_style_expression_bodied_constructors = false:silent +csharp_style_expression_bodied_operators = false:silent +csharp_style_expression_bodied_properties = true:silent +csharp_style_expression_bodied_indexers = true:silent +csharp_style_expression_bodied_accessors = true:silent +csharp_style_expression_bodied_lambdas = true:silent +csharp_style_expression_bodied_local_functions = false:silent +csharp_style_throw_expression = true:suggestion +csharp_style_prefer_null_check_over_type_check = true:suggestion +csharp_prefer_simple_default_expression = true:suggestion +csharp_style_prefer_local_over_anonymous_function = true:suggestion +csharp_style_prefer_index_operator = true:suggestion +csharp_style_prefer_range_operator = true:suggestion +csharp_style_prefer_tuple_swap = true:suggestion +csharp_style_implicit_object_creation_when_type_is_apparent = true:suggestion +csharp_style_deconstructed_variable_declaration = true:suggestion +csharp_style_inlined_variable_declaration = true:suggestion +csharp_style_unused_value_expression_statement_preference = discard_variable:silent +csharp_style_unused_value_assignment_preference = discard_variable:silent +csharp_prefer_static_local_function = true:suggestion +csharp_style_allow_embedded_statements_on_same_line_experimental = true:silent +csharp_style_allow_blank_lines_between_consecutive_braces_experimental = true:silent +csharp_style_allow_blank_line_after_colon_in_constructor_initializer_experimental = true:silent +csharp_style_conditional_delegate_call = true:suggestion +csharp_style_prefer_switch_expression = true:suggestion +csharp_style_prefer_pattern_matching = true:silent +csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion +csharp_style_pattern_matching_over_as_with_null_check = true:suggestion +csharp_style_prefer_not_pattern = true:suggestion +csharp_style_prefer_extended_property_pattern = true:suggestion +csharp_style_var_for_built_in_types = true:suggestion +csharp_style_var_when_type_is_apparent = true:suggestion +csharp_style_var_elsewhere = true:suggestion +csharp_space_after_cast = true +csharp_space_around_binary_operators = before_and_after + +[*.xml] +indent_style = space +[*.{cs,vb}] +#### Naming styles #### + +# Naming rules + +dotnet_naming_rule.interface_should_be_begins_with_i.severity = suggestion +dotnet_naming_rule.interface_should_be_begins_with_i.symbols = interface +dotnet_naming_rule.interface_should_be_begins_with_i.style = begins_with_i + +dotnet_naming_rule.types_should_be_pascal_case.severity = suggestion +dotnet_naming_rule.types_should_be_pascal_case.symbols = types +dotnet_naming_rule.types_should_be_pascal_case.style = pascal_case + +dotnet_naming_rule.non_field_members_should_be_pascal_case.severity = suggestion +dotnet_naming_rule.non_field_members_should_be_pascal_case.symbols = non_field_members +dotnet_naming_rule.non_field_members_should_be_pascal_case.style = pascal_case + +# Symbol specifications + +dotnet_naming_symbols.interface.applicable_kinds = interface +dotnet_naming_symbols.interface.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected +dotnet_naming_symbols.interface.required_modifiers = + +dotnet_naming_symbols.types.applicable_kinds = class, struct, interface, enum +dotnet_naming_symbols.types.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected +dotnet_naming_symbols.types.required_modifiers = + +dotnet_naming_symbols.non_field_members.applicable_kinds = property, event, method +dotnet_naming_symbols.non_field_members.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected +dotnet_naming_symbols.non_field_members.required_modifiers = + +# Naming styles + +dotnet_naming_style.begins_with_i.required_prefix = I +dotnet_naming_style.begins_with_i.required_suffix = +dotnet_naming_style.begins_with_i.word_separator = +dotnet_naming_style.begins_with_i.capitalization = pascal_case + +dotnet_naming_style.pascal_case.required_prefix = +dotnet_naming_style.pascal_case.required_suffix = +dotnet_naming_style.pascal_case.word_separator = +dotnet_naming_style.pascal_case.capitalization = pascal_case + +dotnet_naming_style.pascal_case.required_prefix = +dotnet_naming_style.pascal_case.required_suffix = +dotnet_naming_style.pascal_case.word_separator = +dotnet_naming_style.pascal_case.capitalization = pascal_case +dotnet_style_readonly_field = true:suggestion +dotnet_style_predefined_type_for_locals_parameters_members = true:silent +dotnet_style_predefined_type_for_member_access = true:silent +dotnet_style_require_accessibility_modifiers = for_non_interface_members:silent +dotnet_style_allow_multiple_blank_lines_experimental = true:silent +dotnet_style_allow_statement_immediately_after_block_experimental = true:silent +dotnet_code_quality_unused_parameters = all:suggestion +dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity:silent +dotnet_style_parentheses_in_other_binary_operators = always_for_clarity:silent +dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity:silent +dotnet_style_parentheses_in_other_operators = never_if_unnecessary:silent +dotnet_style_qualification_for_field = false:silent +dotnet_style_qualification_for_property = false:silent +dotnet_style_qualification_for_method = false:silent +dotnet_style_qualification_for_event = false:silent diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..1ff0c42 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,63 @@ +############################################################################### +# Set default behavior to automatically normalize line endings. +############################################################################### +* text=auto + +############################################################################### +# Set default behavior for command prompt diff. +# +# This is need for earlier builds of msysgit that does not have it on by +# default for csharp files. +# Note: This is only used by command line +############################################################################### +#*.cs diff=csharp + +############################################################################### +# Set the merge driver for project and solution files +# +# Merging from the command prompt will add diff markers to the files if there +# are conflicts (Merging from VS is not affected by the settings below, in VS +# the diff markers are never inserted). Diff markers may cause the following +# file extensions to fail to load in VS. An alternative would be to treat +# these files as binary and thus will always conflict and require user +# intervention with every merge. To do so, just uncomment the entries below +############################################################################### +#*.sln merge=binary +#*.csproj merge=binary +#*.vbproj merge=binary +#*.vcxproj merge=binary +#*.vcproj merge=binary +#*.dbproj merge=binary +#*.fsproj merge=binary +#*.lsproj merge=binary +#*.wixproj merge=binary +#*.modelproj merge=binary +#*.sqlproj merge=binary +#*.wwaproj merge=binary + +############################################################################### +# behavior for image files +# +# image files are treated as binary by default. +############################################################################### +#*.jpg binary +#*.png binary +#*.gif binary + +############################################################################### +# diff behavior for common document formats +# +# Convert binary document formats to text before diffing them. This feature +# is only available from the command line. Turn it on by uncommenting the +# entries below. +############################################################################### +#*.doc diff=astextplain +#*.DOC diff=astextplain +#*.docx diff=astextplain +#*.DOCX diff=astextplain +#*.dot diff=astextplain +#*.DOT diff=astextplain +#*.pdf diff=astextplain +#*.PDF diff=astextplain +#*.rtf diff=astextplain +#*.RTF diff=astextplain diff --git a/.github/ISSUE_TEMPLATE/bug-report.md b/.github/ISSUE_TEMPLATE/bug-report.md new file mode 100644 index 0000000..78d4791 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug-report.md @@ -0,0 +1,35 @@ +--- +name: Bug Report +about: Create a bug report to help us improve Safe Exam Browser. +title: '' +labels: '' +assignees: dbuechel + +--- + +> [!IMPORTANT] +> - Please _always_ consult the documentation first before creating a bug report: https://safeexambrowser.org/windows/win_usermanual_en.html. +> - Please _always_ attach the log file(s) of the affected session(s)! They can be found under `%LocalAppData%\SafeExamBrowser\Logs`. + +**Describe the Bug** +A clear and concise description of what the bug is. + +**Steps to Reproduce** +Steps to reproduce the behavior: +1. Go to '...' +2. Click on '....' +3. Scroll down to '....' +4. See error + +**Expected Behavior** +A clear and concise description of what you expected to happen. + +**Screenshots** +If applicable, add screenshots to help explain your problem. + +**Version Information** + - OS: [e.g. Windows 10 Professional, Version 1803] + - SEB-Version [e.g. SEB 3.0.1] + +**Additional Context** +Add any other context about the problem here. diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 0000000..722ea42 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,5 @@ +blank_issues_enabled: false +contact_links: + - name: Wiki + url: https://github.com/school-cheating/SEBPatch/wiki + about: Before opening an issue, check out the wiki to see if your issue is listed there. diff --git a/.github/ISSUE_TEMPLATE/feature-request.md b/.github/ISSUE_TEMPLATE/feature-request.md new file mode 100644 index 0000000..325de6b --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature-request.md @@ -0,0 +1,20 @@ +--- +name: Feature Request +about: Suggest an idea or new feature for Safe Exam Browser. +title: '' +labels: '' +assignees: dbuechel + +--- + +**Is your feature request related to a problem? Please describe.** +A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] + +**Describe the solution you'd like** +A clear and concise description of what you want to happen. + +**Describe alternatives you've considered** +A clear and concise description of any alternative solutions or features you've considered. + +**Additional context** +Add any other context or screenshots about the feature request here. diff --git a/.github/workflows/issues.yml b/.github/workflows/issues.yml new file mode 100644 index 0000000..02438a1 --- /dev/null +++ b/.github/workflows/issues.yml @@ -0,0 +1,25 @@ +name: Issue Maintenance +on: + workflow_dispatch: + schedule: + - cron: "0 0 * * *" + +jobs: + close-issues: + runs-on: ubuntu-latest + permissions: + issues: write + pull-requests: write + steps: + - uses: actions/stale@v8 + with: + # https://github.com/marketplace/actions/close-stale-issues + days-before-issue-stale: 28 + days-before-issue-close: 14 + stale-issue-label: "stale" + stale-issue-message: "This issue is stale because it has been open for 28 days with no activity. It will soon be closed automatically if there are no updates." + close-issue-message: "This issue was closed because it has been inactive for 14 days since being marked as stale." + days-before-pr-stale: -1 + days-before-pr-close: -1 + exempt-issue-labels: "bug,enhancement,feature request,known issue" + repo-token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3c4efe2 --- /dev/null +++ b/.gitignore @@ -0,0 +1,261 @@ +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. + +# User-specific files +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +bld/ +[Bb]in/ +[Oo]bj/ +[Ll]og/ + +# Visual Studio 2015 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUNIT +*.VisualState.xml +TestResult.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# DNX +project.lock.json +project.fragment.lock.json +artifacts/ + +*_i.c +*_p.c +*_i.h +*.ilk +*.meta +*.obj +*.pch +*.pdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db +*.VC.VC.opendb + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# JustCode is a .NET coding add-in +.JustCode + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# TODO: Comment the next line if you want to checkin your web deploy settings +# but database connection strings (with potential passwords) will be unencrypted +#*.pubxml +*.publishproj + +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ + +# NuGet Packages +*.nupkg +# The packages folder can be ignored because of Package Restore +**/packages/* +# except build/, which is used as an MSBuild target. +!**/packages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/packages/repositories.config +# NuGet v3's project.json files produces more ignoreable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.jfm +*.pfx +*.publishsettings +node_modules/ +orleans.codegen.cs + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm + +# SQL Server files +*.mdf +*.ldf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe +paket-files/ + +# FAKE - F# Make +.fake/ + +# JetBrains Rider +.idea/ +*.sln.iml + +# CodeRush +.cr/ + +# Python Tools for Visual Studio (PTVS) +__pycache__/ +*.pyc \ No newline at end of file diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100644 index 0000000..14e2f77 --- /dev/null +++ b/LICENSE.txt @@ -0,0 +1,373 @@ +Mozilla Public License Version 2.0 +================================== + +1. Definitions +-------------- + +1.1. "Contributor" + means each individual or legal entity that creates, contributes to + the creation of, or owns Covered Software. + +1.2. "Contributor Version" + means the combination of the Contributions of others (if any) used + by a Contributor and that particular Contributor's Contribution. + +1.3. "Contribution" + means Covered Software of a particular Contributor. + +1.4. "Covered Software" + means Source Code Form to which the initial Contributor has attached + the notice in Exhibit A, the Executable Form of such Source Code + Form, and Modifications of such Source Code Form, in each case + including portions thereof. + +1.5. "Incompatible With Secondary Licenses" + means + + (a) that the initial Contributor has attached the notice described + in Exhibit B to the Covered Software; or + + (b) that the Covered Software was made available under the terms of + version 1.1 or earlier of the License, but not also under the + terms of a Secondary License. + +1.6. "Executable Form" + means any form of the work other than Source Code Form. + +1.7. "Larger Work" + means a work that combines Covered Software with other material, in + a separate file or files, that is not Covered Software. + +1.8. "License" + means this document. + +1.9. "Licensable" + means having the right to grant, to the maximum extent possible, + whether at the time of the initial grant or subsequently, any and + all of the rights conveyed by this License. + +1.10. "Modifications" + means any of the following: + + (a) any file in Source Code Form that results from an addition to, + deletion from, or modification of the contents of Covered + Software; or + + (b) any new file in Source Code Form that contains any Covered + Software. + +1.11. "Patent Claims" of a Contributor + means any patent claim(s), including without limitation, method, + process, and apparatus claims, in any patent Licensable by such + Contributor that would be infringed, but for the grant of the + License, by the making, using, selling, offering for sale, having + made, import, or transfer of either its Contributions or its + Contributor Version. + +1.12. "Secondary License" + means either the GNU General Public License, Version 2.0, the GNU + Lesser General Public License, Version 2.1, the GNU Affero General + Public License, Version 3.0, or any later versions of those + licenses. + +1.13. "Source Code Form" + means the form of the work preferred for making modifications. + +1.14. "You" (or "Your") + means an individual or a legal entity exercising rights under this + License. For legal entities, "You" includes any entity that + controls, is controlled by, or is under common control with You. For + purposes of this definition, "control" means (a) the power, direct + or indirect, to cause the direction or management of such entity, + whether by contract or otherwise, or (b) ownership of more than + fifty percent (50%) of the outstanding shares or beneficial + ownership of such entity. + +2. License Grants and Conditions +-------------------------------- + +2.1. Grants + +Each Contributor hereby grants You a world-wide, royalty-free, +non-exclusive license: + +(a) under intellectual property rights (other than patent or trademark) + Licensable by such Contributor to use, reproduce, make available, + modify, display, perform, distribute, and otherwise exploit its + Contributions, either on an unmodified basis, with Modifications, or + as part of a Larger Work; and + +(b) under Patent Claims of such Contributor to make, use, sell, offer + for sale, have made, import, and otherwise transfer either its + Contributions or its Contributor Version. + +2.2. Effective Date + +The licenses granted in Section 2.1 with respect to any Contribution +become effective for each Contribution on the date the Contributor first +distributes such Contribution. + +2.3. Limitations on Grant Scope + +The licenses granted in this Section 2 are the only rights granted under +this License. No additional rights or licenses will be implied from the +distribution or licensing of Covered Software under this License. +Notwithstanding Section 2.1(b) above, no patent license is granted by a +Contributor: + +(a) for any code that a Contributor has removed from Covered Software; + or + +(b) for infringements caused by: (i) Your and any other third party's + modifications of Covered Software, or (ii) the combination of its + Contributions with other software (except as part of its Contributor + Version); or + +(c) under Patent Claims infringed by Covered Software in the absence of + its Contributions. + +This License does not grant any rights in the trademarks, service marks, +or logos of any Contributor (except as may be necessary to comply with +the notice requirements in Section 3.4). + +2.4. Subsequent Licenses + +No Contributor makes additional grants as a result of Your choice to +distribute the Covered Software under a subsequent version of this +License (see Section 10.2) or under the terms of a Secondary License (if +permitted under the terms of Section 3.3). + +2.5. Representation + +Each Contributor represents that the Contributor believes its +Contributions are its original creation(s) or it has sufficient rights +to grant the rights to its Contributions conveyed by this License. + +2.6. Fair Use + +This License is not intended to limit any rights You have under +applicable copyright doctrines of fair use, fair dealing, or other +equivalents. + +2.7. Conditions + +Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted +in Section 2.1. + +3. Responsibilities +------------------- + +3.1. Distribution of Source Form + +All distribution of Covered Software in Source Code Form, including any +Modifications that You create or to which You contribute, must be under +the terms of this License. You must inform recipients that the Source +Code Form of the Covered Software is governed by the terms of this +License, and how they can obtain a copy of this License. You may not +attempt to alter or restrict the recipients' rights in the Source Code +Form. + +3.2. Distribution of Executable Form + +If You distribute Covered Software in Executable Form then: + +(a) such Covered Software must also be made available in Source Code + Form, as described in Section 3.1, and You must inform recipients of + the Executable Form how they can obtain a copy of such Source Code + Form by reasonable means in a timely manner, at a charge no more + than the cost of distribution to the recipient; and + +(b) You may distribute such Executable Form under the terms of this + License, or sublicense it under different terms, provided that the + license for the Executable Form does not attempt to limit or alter + the recipients' rights in the Source Code Form under this License. + +3.3. Distribution of a Larger Work + +You may create and distribute a Larger Work under terms of Your choice, +provided that You also comply with the requirements of this License for +the Covered Software. If the Larger Work is a combination of Covered +Software with a work governed by one or more Secondary Licenses, and the +Covered Software is not Incompatible With Secondary Licenses, this +License permits You to additionally distribute such Covered Software +under the terms of such Secondary License(s), so that the recipient of +the Larger Work may, at their option, further distribute the Covered +Software under the terms of either this License or such Secondary +License(s). + +3.4. Notices + +You may not remove or alter the substance of any license notices +(including copyright notices, patent notices, disclaimers of warranty, +or limitations of liability) contained within the Source Code Form of +the Covered Software, except that You may alter any license notices to +the extent required to remedy known factual inaccuracies. + +3.5. Application of Additional Terms + +You may choose to offer, and to charge a fee for, warranty, support, +indemnity or liability obligations to one or more recipients of Covered +Software. However, You may do so only on Your own behalf, and not on +behalf of any Contributor. You must make it absolutely clear that any +such warranty, support, indemnity, or liability obligation is offered by +You alone, and You hereby agree to indemnify every Contributor for any +liability incurred by such Contributor as a result of warranty, support, +indemnity or liability terms You offer. You may include additional +disclaimers of warranty and limitations of liability specific to any +jurisdiction. + +4. Inability to Comply Due to Statute or Regulation +--------------------------------------------------- + +If it is impossible for You to comply with any of the terms of this +License with respect to some or all of the Covered Software due to +statute, judicial order, or regulation then You must: (a) comply with +the terms of this License to the maximum extent possible; and (b) +describe the limitations and the code they affect. Such description must +be placed in a text file included with all distributions of the Covered +Software under this License. Except to the extent prohibited by statute +or regulation, such description must be sufficiently detailed for a +recipient of ordinary skill to be able to understand it. + +5. Termination +-------------- + +5.1. The rights granted under this License will terminate automatically +if You fail to comply with any of its terms. However, if You become +compliant, then the rights granted under this License from a particular +Contributor are reinstated (a) provisionally, unless and until such +Contributor explicitly and finally terminates Your grants, and (b) on an +ongoing basis, if such Contributor fails to notify You of the +non-compliance by some reasonable means prior to 60 days after You have +come back into compliance. Moreover, Your grants from a particular +Contributor are reinstated on an ongoing basis if such Contributor +notifies You of the non-compliance by some reasonable means, this is the +first time You have received notice of non-compliance with this License +from such Contributor, and You become compliant prior to 30 days after +Your receipt of the notice. + +5.2. If You initiate litigation against any entity by asserting a patent +infringement claim (excluding declaratory judgment actions, +counter-claims, and cross-claims) alleging that a Contributor Version +directly or indirectly infringes any patent, then the rights granted to +You by any and all Contributors for the Covered Software under Section +2.1 of this License shall terminate. + +5.3. In the event of termination under Sections 5.1 or 5.2 above, all +end user license agreements (excluding distributors and resellers) which +have been validly granted by You or Your distributors under this License +prior to termination shall survive termination. + +************************************************************************ +* * +* 6. Disclaimer of Warranty * +* ------------------------- * +* * +* Covered Software is provided under this License on an "as is" * +* basis, without warranty of any kind, either expressed, implied, or * +* statutory, including, without limitation, warranties that the * +* Covered Software is free of defects, merchantable, fit for a * +* particular purpose or non-infringing. The entire risk as to the * +* quality and performance of the Covered Software is with You. * +* Should any Covered Software prove defective in any respect, You * +* (not any Contributor) assume the cost of any necessary servicing, * +* repair, or correction. This disclaimer of warranty constitutes an * +* essential part of this License. No use of any Covered Software is * +* authorized under this License except under this disclaimer. * +* * +************************************************************************ + +************************************************************************ +* * +* 7. Limitation of Liability * +* -------------------------- * +* * +* Under no circumstances and under no legal theory, whether tort * +* (including negligence), contract, or otherwise, shall any * +* Contributor, or anyone who distributes Covered Software as * +* permitted above, be liable to You for any direct, indirect, * +* special, incidental, or consequential damages of any character * +* including, without limitation, damages for lost profits, loss of * +* goodwill, work stoppage, computer failure or malfunction, or any * +* and all other commercial damages or losses, even if such party * +* shall have been informed of the possibility of such damages. This * +* limitation of liability shall not apply to liability for death or * +* personal injury resulting from such party's negligence to the * +* extent applicable law prohibits such limitation. Some * +* jurisdictions do not allow the exclusion or limitation of * +* incidental or consequential damages, so this exclusion and * +* limitation may not apply to You. * +* * +************************************************************************ + +8. Litigation +------------- + +Any litigation relating to this License may be brought only in the +courts of a jurisdiction where the defendant maintains its principal +place of business and such litigation shall be governed by laws of that +jurisdiction, without reference to its conflict-of-law provisions. +Nothing in this Section shall prevent a party's ability to bring +cross-claims or counter-claims. + +9. Miscellaneous +---------------- + +This License represents the complete agreement concerning the subject +matter hereof. If any provision of this License is held to be +unenforceable, such provision shall be reformed only to the extent +necessary to make it enforceable. Any law or regulation which provides +that the language of a contract shall be construed against the drafter +shall not be used to construe this License against a Contributor. + +10. Versions of the License +--------------------------- + +10.1. New Versions + +Mozilla Foundation is the license steward. Except as provided in Section +10.3, no one other than the license steward has the right to modify or +publish new versions of this License. Each version will be given a +distinguishing version number. + +10.2. Effect of New Versions + +You may distribute the Covered Software under the terms of the version +of the License under which You originally received the Covered Software, +or under the terms of any subsequent version published by the license +steward. + +10.3. Modified Versions + +If you create software not governed by this License, and you want to +create a new license for such software, you may create and use a +modified version of this License if you rename the license and remove +any references to the name of the license steward (except to note that +such modified license differs from this License). + +10.4. Distributing Source Code Form that is Incompatible With Secondary +Licenses + +If You choose to distribute Source Code Form that is Incompatible With +Secondary Licenses under the terms of this version of the License, the +notice described in Exhibit B of this License must be attached. + +Exhibit A - Source Code Form License Notice +------------------------------------------- + + 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/. + +If it is not possible or desirable to put the notice in a particular +file, then You may include the notice in a location (such as a LICENSE +file in a relevant directory) where a recipient would be likely to look +for such a notice. + +You may add additional accurate notices of copyright ownership. + +Exhibit B - "Incompatible With Secondary Licenses" Notice +--------------------------------------------------------- + + This Source Code Form is "Incompatible With Secondary Licenses", as + defined by the Mozilla Public License, v. 2.0. diff --git a/README.md b/README.md new file mode 100644 index 0000000..34892dd --- /dev/null +++ b/README.md @@ -0,0 +1,16 @@ +# Safe Exam Browser Patch +A patch to bypass Safe Exam Browser restrictions. + +- Patch for version 3.8.0.742 has been deprecated and will not receive updates in the future, please upgrade to Safe Exam Browser 3.9.0.787. + +## How to use +Check out the [Wiki](https://github.com/school-cheating/SEBPatch/wiki) + +## Mirrors +In case you can't download from the latest release, here is a list of mirrors (will be updated eventually): +* [Vichingo455's Software Repository](https://software-repository-website.vercel.app/Random%20Files/Projects/SEBPatch/) + +## Credits +This project uses the same license as Safe Exam Browser, so it's completely legal. +However, it should be used with caution. I don't recommend cheating in exams as it could lead to educational consequences. +Safe Exam Browser is a product copyrighted by ETH Zurich and is modified here under the MPL License. diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 0000000..e0edba7 --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,35 @@ +# Security Policy + +We only support the latest official relese version with respect to security vulnerabilities. Thus, only the latest or then the upcoming next release version +will receive vulnerability fixes and security updates. A vulnerability may however be reported for any version, unless it already has been fixed with a later +release version. + +## Reporting a Vulnerability + +> [!IMPORTANT] +> - Please _always_ verify that no later release version exists which fixes the vulnerability. +> - Please _always_ consult the documentation first before creating a vulnerability report: https://safeexambrowser.org/windows/win_usermanual_en.html. +> - Please _always_ attach the log file(s) of the affected session(s)! They can be found under `%LocalAppData%\SafeExamBrowser\Logs`. + +**Describe the Vulnerability** +A clear and concise description of what the vulnerability is. + +**Steps to Reproduce** +Steps to reproduce the behavior: +1. Go to '...' +2. Click on '....' +3. Scroll down to '....' +4. See ... + +**Expected Behavior** +A clear and concise description of what you expected to happen. + +**Screenshots** +If applicable, add screenshots to help explain your problem. + +**Version Information** + - OS: [e.g. Windows 10 Professional, Version 1803] + - SEB-Version [e.g. SEB 3.0.1] + +**Additional Context** +Add any other context about the vulnerability here. diff --git a/SafeExamBrowser.Applications.Contracts/Events/IconChangedEventHandler.cs b/SafeExamBrowser.Applications.Contracts/Events/IconChangedEventHandler.cs new file mode 100644 index 0000000..a68529e --- /dev/null +++ b/SafeExamBrowser.Applications.Contracts/Events/IconChangedEventHandler.cs @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2024 ETH Zürich, IT Services + * + * 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 SafeExamBrowser.Core.Contracts.Resources.Icons; + +namespace SafeExamBrowser.Applications.Contracts.Events +{ + /// + /// Event handler used to indicate that an icon has changed. + /// + public delegate void IconChangedEventHandler(IconResource icon); +} diff --git a/SafeExamBrowser.Applications.Contracts/Events/TitleChangedEventHandler.cs b/SafeExamBrowser.Applications.Contracts/Events/TitleChangedEventHandler.cs new file mode 100644 index 0000000..080133c --- /dev/null +++ b/SafeExamBrowser.Applications.Contracts/Events/TitleChangedEventHandler.cs @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2024 ETH Zürich, IT Services + * + * 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/. + */ + +namespace SafeExamBrowser.Applications.Contracts.Events +{ + /// + /// Event handler used to indicate that a title has changed to a new value. + /// + public delegate void TitleChangedEventHandler(string title); +} diff --git a/SafeExamBrowser.Applications.Contracts/Events/WindowsChangedEventHandler.cs b/SafeExamBrowser.Applications.Contracts/Events/WindowsChangedEventHandler.cs new file mode 100644 index 0000000..b399c7e --- /dev/null +++ b/SafeExamBrowser.Applications.Contracts/Events/WindowsChangedEventHandler.cs @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2024 ETH Zürich, IT Services + * + * 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/. + */ + +namespace SafeExamBrowser.Applications.Contracts.Events +{ + /// + /// Event handler used to indicate that the windows of an application have changed. + /// + public delegate void WindowsChangedEventHandler(); +} diff --git a/SafeExamBrowser.Applications.Contracts/FactoryResult.cs b/SafeExamBrowser.Applications.Contracts/FactoryResult.cs new file mode 100644 index 0000000..cb0a7bd --- /dev/null +++ b/SafeExamBrowser.Applications.Contracts/FactoryResult.cs @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2024 ETH Zürich, IT Services + * + * 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/. + */ + +namespace SafeExamBrowser.Applications.Contracts +{ + /// + /// Defines all possible results of an attempt to create an application. + /// + public enum FactoryResult + { + /// + /// An error occurred while trying to create the application. + /// + Error, + + /// + /// The application could not be found on the system. + /// + NotFound, + + /// + /// The application has been created successfully. + /// + Success + } +} diff --git a/SafeExamBrowser.Applications.Contracts/IApplication.cs b/SafeExamBrowser.Applications.Contracts/IApplication.cs new file mode 100644 index 0000000..249b878 --- /dev/null +++ b/SafeExamBrowser.Applications.Contracts/IApplication.cs @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2024 ETH Zürich, IT Services + * + * 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.Collections.Generic; +using SafeExamBrowser.Applications.Contracts.Events; +using SafeExamBrowser.Core.Contracts.Resources.Icons; + +namespace SafeExamBrowser.Applications.Contracts +{ + /// + /// Controls the lifetime and functionality of an application. + /// + public interface IApplication where TWindow : IApplicationWindow + { + /// + /// Indicates whether the application should be automatically started. + /// + bool AutoStart { get; } + + /// + /// The resource providing the application icon. + /// + IconResource Icon { get; } + + /// + /// The unique identifier of the application. + /// + Guid Id { get; } + + /// + /// The name of the application. + /// + string Name { get; } + + /// + /// The tooltip for the application. + /// + string Tooltip { get; } + + /// + /// Event fired when the windows of the application have changed. + /// + event WindowsChangedEventHandler WindowsChanged; + + /// + /// Returns all windows of the application. + /// + IEnumerable GetWindows(); + + /// + /// Performs any initialization work, if necessary. + /// + void Initialize(); + + /// + /// Starts the execution of the application. + /// + void Start(); + + /// + /// Performs any termination work, e.g. releasing of used resources. + /// + void Terminate(); + } +} diff --git a/SafeExamBrowser.Applications.Contracts/IApplicationFactory.cs b/SafeExamBrowser.Applications.Contracts/IApplicationFactory.cs new file mode 100644 index 0000000..8b30fb5 --- /dev/null +++ b/SafeExamBrowser.Applications.Contracts/IApplicationFactory.cs @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2024 ETH Zürich, IT Services + * + * 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 SafeExamBrowser.Settings.Applications; + +namespace SafeExamBrowser.Applications.Contracts +{ + /// + /// Provides functionality to create external applications. + /// + public interface IApplicationFactory + { + /// + /// Attempts to create an application according to the given settings. + /// + FactoryResult TryCreate(WhitelistApplication settings, out IApplication application); + } +} diff --git a/SafeExamBrowser.Applications.Contracts/IApplicationWindow.cs b/SafeExamBrowser.Applications.Contracts/IApplicationWindow.cs new file mode 100644 index 0000000..7981578 --- /dev/null +++ b/SafeExamBrowser.Applications.Contracts/IApplicationWindow.cs @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2024 ETH Zürich, IT Services + * + * 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 SafeExamBrowser.Applications.Contracts.Events; +using SafeExamBrowser.Core.Contracts.Resources.Icons; + +namespace SafeExamBrowser.Applications.Contracts +{ + /// + /// Defines a window of an . + /// + public interface IApplicationWindow + { + /// + /// The native handle of the window. + /// + IntPtr Handle { get; } + + /// + /// The icon of the window. + /// + IconResource Icon { get; } + + /// + /// The title of the window. + /// + string Title { get; } + + /// + /// Event fired when the icon of the window has changed. + /// + event IconChangedEventHandler IconChanged; + + /// + /// Event fired when the title of the window has changed. + /// + event TitleChangedEventHandler TitleChanged; + + /// + /// Brings the window to the foreground and activates it. + /// + void Activate(); + } +} diff --git a/SafeExamBrowser.Applications.Contracts/Properties/AssemblyInfo.cs b/SafeExamBrowser.Applications.Contracts/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..48034c2 --- /dev/null +++ b/SafeExamBrowser.Applications.Contracts/Properties/AssemblyInfo.cs @@ -0,0 +1,33 @@ +using System.Reflection; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("SafeExamBrowser.Applications.Contracts")] +[assembly: AssemblyDescription("Safe Exam Browser")] +[assembly: AssemblyCompany("ETH Zürich")] +[assembly: AssemblyProduct("SafeExamBrowser.Applications.Contracts")] +[assembly: AssemblyCopyright("Copyright © 2024 ETH Zürich, IT Services")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("ac77745d-3b41-43e2-8e84-d40e5a4ee77f")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] +[assembly: AssemblyInformationalVersion("1.0.0.0")] diff --git a/SafeExamBrowser.Applications.Contracts/SafeExamBrowser.Applications.Contracts.csproj b/SafeExamBrowser.Applications.Contracts/SafeExamBrowser.Applications.Contracts.csproj new file mode 100644 index 0000000..e4e239b --- /dev/null +++ b/SafeExamBrowser.Applications.Contracts/SafeExamBrowser.Applications.Contracts.csproj @@ -0,0 +1,78 @@ + + + + + Debug + AnyCPU + {AC77745D-3B41-43E2-8E84-D40E5A4EE77F} + Library + Properties + SafeExamBrowser.Applications.Contracts + SafeExamBrowser.Applications.Contracts + v4.8 + 512 + true + + + + true + bin\x86\Debug\ + DEBUG;TRACE + full + x86 + prompt + MinimumRecommendedRules.ruleset + + + bin\x86\Release\ + TRACE + true + pdbonly + x86 + prompt + MinimumRecommendedRules.ruleset + + + true + bin\x64\Debug\ + DEBUG;TRACE + full + x64 + prompt + MinimumRecommendedRules.ruleset + + + bin\x64\Release\ + TRACE + true + pdbonly + x64 + prompt + MinimumRecommendedRules.ruleset + + + + + + + + + + + + + + + + + + {fe0e1224-b447-4b14-81e7-ed7d84822aa0} + SafeExamBrowser.Core.Contracts + + + {30b2d907-5861-4f39-abad-c4abf1b3470e} + SafeExamBrowser.Settings + + + + \ No newline at end of file diff --git a/SafeExamBrowser.Applications.UnitTests/ApplicationFactoryTests.cs b/SafeExamBrowser.Applications.UnitTests/ApplicationFactoryTests.cs new file mode 100644 index 0000000..074e1cb --- /dev/null +++ b/SafeExamBrowser.Applications.UnitTests/ApplicationFactoryTests.cs @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2024 ETH Zürich, IT Services + * + * 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 Microsoft.VisualStudio.TestTools.UnitTesting; +using Moq; +using SafeExamBrowser.Applications.Contracts; +using SafeExamBrowser.Logging.Contracts; +using SafeExamBrowser.Monitoring.Contracts.Applications; +using SafeExamBrowser.Settings.Applications; +using SafeExamBrowser.SystemComponents.Contracts.Registry; +using SafeExamBrowser.WindowsApi.Contracts; + +namespace SafeExamBrowser.Applications.UnitTests +{ + [TestClass] + public class ApplicationFactoryTests + { + private Mock applicationMonitor; + private Mock logger; + private Mock nativeMethods; + private Mock processFactory; + private Mock registry; + + private ApplicationFactory sut; + + [TestInitialize] + public void Initialize() + { + applicationMonitor = new Mock(); + logger = new Mock(); + nativeMethods = new Mock(); + processFactory = new Mock(); + registry = new Mock(); + + sut = new ApplicationFactory(applicationMonitor.Object, logger.Object, nativeMethods.Object, processFactory.Object, registry.Object); + } + + [TestMethod] + public void MustCorrectlyCreateApplication() + { + var settings = new WhitelistApplication + { + DisplayName = "Windows Command Prompt", + ExecutableName = "cmd.exe", + }; + + var result = sut.TryCreate(settings, out var application); + + Assert.AreEqual(FactoryResult.Success, result); + Assert.IsNotNull(application); + Assert.IsInstanceOfType(application); + } + + [TestMethod] + public void MustCorrectlyReadPathFromRegistry() + { + object o = @"C:\Some\Registry\Path"; + var settings = new WhitelistApplication + { + DisplayName = "Windows Command Prompt", + ExecutableName = "cmd.exe", + ExecutablePath = @"C:\Some\Path" + }; + + registry.Setup(r => r.TryRead(It.Is(s => s.Contains(RegistryValue.MachineHive.AppPaths_Key)), It.Is(s => s == "Path"), out o)).Returns(true); + + var result = sut.TryCreate(settings, out var application); + + registry.Verify(r => r.TryRead(It.Is(s => s.Contains(RegistryValue.MachineHive.AppPaths_Key)), It.Is(s => s == "Path"), out o), Times.Once); + + Assert.AreEqual(FactoryResult.Success, result); + Assert.IsNotNull(application); + Assert.IsInstanceOfType(application); + } + + [TestMethod] + public void MustIndicateIfApplicationNotFound() + { + var settings = new WhitelistApplication + { + ExecutableName = "some_random_application_which_does_not_exist_on_a_normal_system.exe", + ExecutablePath = "Some/Path/Which/Does/Not/Exist" + }; + + var result = sut.TryCreate(settings, out var application); + + Assert.AreEqual(FactoryResult.NotFound, result); + Assert.IsNull(application); + } + + [TestMethod] + public void MustFailGracefullyWhenPathIsInvalid() + { + var settings = new WhitelistApplication + { + ExecutableName = "asdfg(/ç)&=%\"fsdg..exe..", + ExecutablePath = "[]#°§¬#°¢@tu03450'w89tz!$£äöüèé:" + }; + + var result = sut.TryCreate(settings, out _); + + logger.Verify(l => l.Error(It.IsAny(), It.IsAny()), Times.AtLeastOnce); + + Assert.AreEqual(FactoryResult.NotFound, result); + } + + [TestMethod] + public void MustFailGracefullyAndIndicateThatErrorOccurred() + { + var o = default(object); + var settings = new WhitelistApplication(); + + registry.Setup(r => r.TryRead(It.IsAny(), It.IsAny(), out o)).Throws(); + + var result = sut.TryCreate(settings, out var application); + + Assert.AreEqual(FactoryResult.Error, result); + } + } +} diff --git a/SafeExamBrowser.Applications.UnitTests/ExternalApplicationInstanceTests.cs b/SafeExamBrowser.Applications.UnitTests/ExternalApplicationInstanceTests.cs new file mode 100644 index 0000000..61b13c3 --- /dev/null +++ b/SafeExamBrowser.Applications.UnitTests/ExternalApplicationInstanceTests.cs @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2024 ETH Zürich, IT Services + * + * 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 Microsoft.VisualStudio.TestTools.UnitTesting; +using Moq; +using SafeExamBrowser.Core.Contracts.Resources.Icons; +using SafeExamBrowser.Logging.Contracts; +using SafeExamBrowser.WindowsApi.Contracts; + +namespace SafeExamBrowser.Applications.UnitTests +{ + [TestClass] + public class ExternalApplicationInstanceTests + { + private NativeIconResource icon; + private Mock logger; + private Mock nativeMethods; + private Mock process; + private ExternalApplicationInstance sut; + + [TestInitialize] + public void Initialize() + { + icon = new NativeIconResource(); + logger = new Mock(); + nativeMethods = new Mock(); + process = new Mock(); + + sut = new ExternalApplicationInstance(icon, logger.Object, nativeMethods.Object, process.Object, 1); + } + + [TestMethod] + public void Terminate_MustDoNothingIfAlreadyTerminated() + { + process.SetupGet(p => p.HasTerminated).Returns(true); + + sut.Terminate(); + + process.Verify(p => p.TryClose(It.IsAny()), Times.Never()); + process.Verify(p => p.TryKill(It.IsAny()), Times.Never()); + } + + [TestMethod] + public void Terminate_MustLogIfTerminationFailed() + { + process.Setup(p => p.TryClose(It.IsAny())).Returns(false); + process.Setup(p => p.TryKill(It.IsAny())).Returns(false); + process.SetupGet(p => p.HasTerminated).Returns(false); + + sut.Terminate(); + + logger.Verify(l => l.Warn(It.IsAny()), Times.AtLeastOnce); + process.Verify(p => p.TryClose(It.IsAny()), Times.AtLeastOnce()); + process.Verify(p => p.TryKill(It.IsAny()), Times.AtLeastOnce()); + } + } +} diff --git a/SafeExamBrowser.Applications.UnitTests/ExternalApplicationTests.cs b/SafeExamBrowser.Applications.UnitTests/ExternalApplicationTests.cs new file mode 100644 index 0000000..f5c9935 --- /dev/null +++ b/SafeExamBrowser.Applications.UnitTests/ExternalApplicationTests.cs @@ -0,0 +1,216 @@ +/* + * Copyright (c) 2024 ETH Zürich, IT Services + * + * 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.Collections.Generic; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Moq; +using SafeExamBrowser.Core.Contracts.Resources.Icons; +using SafeExamBrowser.Logging.Contracts; +using SafeExamBrowser.Monitoring.Contracts.Applications; +using SafeExamBrowser.Monitoring.Contracts.Applications.Events; +using SafeExamBrowser.Settings.Applications; +using SafeExamBrowser.WindowsApi.Contracts; + +namespace SafeExamBrowser.Applications.UnitTests +{ + [TestClass] + public class ExternalApplicationTests + { + private Mock applicationMonitor; + private string executablePath; + private Mock logger; + private Mock nativeMethods; + private Mock processFactory; + private WhitelistApplication settings; + + private ExternalApplication sut; + + [TestInitialize] + public void Initialize() + { + applicationMonitor = new Mock(); + executablePath = @"C:\Some\Random\Path\Application.exe"; + logger = new Mock(); + nativeMethods = new Mock(); + processFactory = new Mock(); + settings = new WhitelistApplication(); + + logger.Setup(l => l.CloneFor(It.IsAny())).Returns(new Mock().Object); + + sut = new ExternalApplication(applicationMonitor.Object, executablePath, logger.Object, nativeMethods.Object, processFactory.Object, settings, 1); + } + + [TestMethod] + public void GetWindows_MustCorrectlyReturnOpenWindows() + { + var openWindows = new List { new IntPtr(123), new IntPtr(234), new IntPtr(456), new IntPtr(345), new IntPtr(567), new IntPtr(789) }; + var process1 = new Mock(); + var process2 = new Mock(); + var sync = new AutoResetEvent(false); + + nativeMethods.Setup(n => n.GetOpenWindows()).Returns(openWindows); + nativeMethods.Setup(n => n.GetProcessIdFor(It.Is(p => p == new IntPtr(234)))).Returns(1234); + nativeMethods.Setup(n => n.GetProcessIdFor(It.Is(p => p == new IntPtr(345)))).Returns(1234); + nativeMethods.Setup(n => n.GetProcessIdFor(It.Is(p => p == new IntPtr(567)))).Returns(5678); + process1.Setup(p => p.TryClose(It.IsAny())).Returns(false); + process1.Setup(p => p.TryKill(It.IsAny())).Returns(true); + process1.SetupGet(p => p.Id).Returns(1234); + process2.Setup(p => p.TryClose(It.IsAny())).Returns(true); + process2.SetupGet(p => p.Id).Returns(5678); + processFactory.Setup(f => f.StartNew(It.IsAny(), It.IsAny())).Returns(process1.Object); + + sut.WindowsChanged += () => sync.Set(); + sut.Initialize(); + sut.Start(); + + applicationMonitor.Raise(m => m.InstanceStarted += null, sut.Id, process2.Object); + + sync.WaitOne(); + sync.WaitOne(); + + var windows = sut.GetWindows(); + + Assert.AreEqual(3, windows.Count()); + Assert.IsTrue(windows.Any(w => w.Handle == new IntPtr(234))); + Assert.IsTrue(windows.Any(w => w.Handle == new IntPtr(345))); + Assert.IsTrue(windows.Any(w => w.Handle == new IntPtr(567))); + + nativeMethods.Setup(n => n.GetOpenWindows()).Returns(openWindows.Skip(2)); + Task.Run(() => process2.Raise(p => p.Terminated += null, default(int))); + + sync.WaitOne(); + sync.WaitOne(); + + windows = sut.GetWindows(); + + Assert.AreEqual(1, windows.Count()); + Assert.IsTrue(windows.Any(w => w.Handle != new IntPtr(234))); + Assert.IsTrue(windows.Any(w => w.Handle == new IntPtr(345))); + Assert.IsTrue(windows.All(w => w.Handle != new IntPtr(567))); + } + + [TestMethod] + public void Initialize_MustInitializeCorrectly() + { + settings.AutoStart = new Random().Next(2) == 1; + settings.Description = "Some Description"; + + sut.Initialize(); + + applicationMonitor.VerifyAdd(a => a.InstanceStarted += It.IsAny(), Times.Once); + + Assert.AreEqual(settings.AutoStart, sut.AutoStart); + Assert.AreEqual(executablePath, (sut.Icon as EmbeddedIconResource).FilePath); + Assert.AreEqual(settings.Id, settings.Id); + Assert.AreEqual(settings.DisplayName, sut.Name); + Assert.AreEqual(settings.Description ?? settings.DisplayName, sut.Tooltip); + } + + [TestMethod] + public void Start_MustCreateInstanceCorrectly() + { + settings.Arguments.Add("some_parameter"); + settings.Arguments.Add("another_parameter"); + settings.Arguments.Add("yet another parameter"); + + sut.Start(); + + processFactory.Verify(f => f.StartNew(executablePath, It.Is(args => args.All(a => settings.Arguments.Contains(a)))), Times.Once); + } + + [TestMethod] + public void Start_MustHandleFailureGracefully() + { + processFactory.Setup(f => f.StartNew(It.IsAny(), It.IsAny())).Throws(); + + sut.Start(); + + logger.Verify(l => l.Error(It.IsAny(), It.IsAny()), Times.AtLeastOnce); + processFactory.Verify(f => f.StartNew(It.IsAny(), It.IsAny()), Times.Once); + } + + [TestMethod] + public void Start_MustRemoveInstanceCorrectlyWhenTerminated() + { + var eventCount = 0; + var openWindows = new List { new IntPtr(123), new IntPtr(234), new IntPtr(456), new IntPtr(345), new IntPtr(567), new IntPtr(789), }; + var process = new Mock(); + var sync = new AutoResetEvent(false); + + nativeMethods.Setup(n => n.GetOpenWindows()).Returns(openWindows); + nativeMethods.Setup(n => n.GetProcessIdFor(It.Is(p => p == new IntPtr(234)))).Returns(1234); + process.Setup(p => p.TryClose(It.IsAny())).Returns(false); + process.Setup(p => p.TryKill(It.IsAny())).Returns(true); + process.SetupGet(p => p.Id).Returns(1234); + processFactory.Setup(f => f.StartNew(It.IsAny(), It.IsAny())).Returns(process.Object); + + sut.WindowsChanged += () => + { + eventCount++; + sync.Set(); + }; + + sut.Initialize(); + sut.Start(); + + sync.WaitOne(); + + Assert.AreEqual(1, sut.GetWindows().Count()); + + process.Raise(p => p.Terminated += null, default(int)); + + Assert.AreEqual(2, eventCount); + Assert.AreEqual(0, sut.GetWindows().Count()); + } + + [TestMethod] + public void Terminate_MustStopAllInstancesCorrectly() + { + var process1 = new Mock(); + var process2 = new Mock(); + + process1.Setup(p => p.TryClose(It.IsAny())).Returns(false); + process1.Setup(p => p.TryKill(It.IsAny())).Returns(true); + process1.SetupGet(p => p.Id).Returns(1234); + process2.Setup(p => p.TryClose(It.IsAny())).Returns(true); + process2.SetupGet(p => p.Id).Returns(5678); + processFactory.Setup(f => f.StartNew(It.IsAny(), It.IsAny())).Returns(process1.Object); + + sut.Initialize(); + sut.Start(); + + applicationMonitor.Raise(m => m.InstanceStarted += null, sut.Id, process2.Object); + sut.Terminate(); + + process1.Verify(p => p.TryClose(It.IsAny()), Times.AtLeastOnce); + process1.Verify(p => p.TryKill(It.IsAny()), Times.Once); + process2.Verify(p => p.TryClose(It.IsAny()), Times.Once); + process2.Verify(p => p.TryKill(It.IsAny()), Times.Never); + } + + [TestMethod] + public void Terminate_MustHandleFailureGracefully() + { + var process = new Mock(); + + process.Setup(p => p.TryClose(It.IsAny())).Throws(); + processFactory.Setup(f => f.StartNew(It.IsAny(), It.IsAny())).Returns(process.Object); + + sut.Initialize(); + sut.Start(); + sut.Terminate(); + + process.Verify(p => p.TryClose(It.IsAny()), Times.AtLeastOnce); + process.Verify(p => p.TryKill(It.IsAny()), Times.Never); + } + } +} diff --git a/SafeExamBrowser.Applications.UnitTests/ExternalApplicationWindowTests.cs b/SafeExamBrowser.Applications.UnitTests/ExternalApplicationWindowTests.cs new file mode 100644 index 0000000..cf06347 --- /dev/null +++ b/SafeExamBrowser.Applications.UnitTests/ExternalApplicationWindowTests.cs @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2024 ETH Zürich, IT Services + * + * 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 Microsoft.VisualStudio.TestTools.UnitTesting; +using Moq; +using SafeExamBrowser.Core.Contracts.Resources.Icons; +using SafeExamBrowser.WindowsApi.Contracts; + +namespace SafeExamBrowser.Applications.UnitTests +{ + [TestClass] + public class ExternalApplicationWindowTests + { + private IntPtr handle; + private NativeIconResource icon; + private Mock nativeMethods; + + private ExternalApplicationWindow sut; + + [TestInitialize] + public void Initialize() + { + handle = new IntPtr(123); + icon = new NativeIconResource(); + nativeMethods = new Mock(); + + sut = new ExternalApplicationWindow(icon, nativeMethods.Object, handle); + } + + [TestMethod] + public void Activate_MustCorrectlyActivateWindow() + { + sut.Activate(); + nativeMethods.Verify(n => n.ActivateWindow(It.Is(h => h == handle))); + } + + [TestMethod] + public void Update_MustCorrectlyUpdateWindow() + { + var iconChanged = false; + var titleChanged = false; + + nativeMethods.Setup(m => m.GetWindowIcon(It.IsAny())).Returns(new IntPtr(456)); + nativeMethods.Setup(m => m.GetWindowTitle((It.IsAny()))).Returns("Some New Window Title"); + + sut.IconChanged += (_) => iconChanged = true; + sut.TitleChanged += (_) => titleChanged = true; + + sut.Update(); + + nativeMethods.Verify(m => m.GetWindowIcon(handle), Times.Once); + nativeMethods.Verify(m => m.GetWindowTitle(handle), Times.Once); + + Assert.IsTrue(iconChanged); + Assert.IsTrue(titleChanged); + } + } +} diff --git a/SafeExamBrowser.Applications.UnitTests/Properties/AssemblyInfo.cs b/SafeExamBrowser.Applications.UnitTests/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..5a24166 --- /dev/null +++ b/SafeExamBrowser.Applications.UnitTests/Properties/AssemblyInfo.cs @@ -0,0 +1,16 @@ +using System.Reflection; +using System.Runtime.InteropServices; + +[assembly: AssemblyTitle("SafeExamBrowser.Applications.UnitTests")] +[assembly: AssemblyDescription("Safe Exam Browser")] +[assembly: AssemblyCompany("ETH Zürich")] +[assembly: AssemblyProduct("SafeExamBrowser.Applications.UnitTests")] +[assembly: AssemblyCopyright("Copyright © 2024 ETH Zürich, IT Services")] + +[assembly: ComVisible(false)] + +[assembly: Guid("fc6d80ec-8611-4287-87e2-17c028a10858")] + +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] +[assembly: AssemblyInformationalVersion("1.0.0.0")] diff --git a/SafeExamBrowser.Applications.UnitTests/SafeExamBrowser.Applications.UnitTests.csproj b/SafeExamBrowser.Applications.UnitTests/SafeExamBrowser.Applications.UnitTests.csproj new file mode 100644 index 0000000..a6b7500 --- /dev/null +++ b/SafeExamBrowser.Applications.UnitTests/SafeExamBrowser.Applications.UnitTests.csproj @@ -0,0 +1,199 @@ + + + + + + + + Debug + AnyCPU + {FC6D80EC-8611-4287-87E2-17C028A10858} + Library + Properties + SafeExamBrowser.Applications.UnitTests + SafeExamBrowser.Applications.UnitTests + v4.8 + 512 + {3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + 15.0 + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) + $(ProgramFiles)\Common Files\microsoft shared\VSTT\$(VisualStudioVersion)\UITestExtensionPackages + False + UnitTest + + + + + + true + bin\x64\Debug\ + DEBUG;TRACE + full + x64 + 7.3 + prompt + + + bin\x64\Release\ + TRACE + true + pdbonly + x64 + 7.3 + prompt + + + true + bin\x86\Debug\ + DEBUG;TRACE + full + x86 + 7.3 + prompt + + + bin\x86\Release\ + TRACE + true + pdbonly + x86 + 7.3 + prompt + + + + ..\packages\Castle.Core.5.1.1\lib\net462\Castle.Core.dll + + + ..\packages\Microsoft.ApplicationInsights.2.22.0\lib\net46\Microsoft.ApplicationInsights.dll + + + + ..\packages\Microsoft.Testing.Extensions.Telemetry.1.0.2\lib\netstandard2.0\Microsoft.Testing.Extensions.Telemetry.dll + + + ..\packages\Microsoft.Testing.Extensions.TrxReport.Abstractions.1.0.2\lib\netstandard2.0\Microsoft.Testing.Extensions.TrxReport.Abstractions.dll + + + ..\packages\Microsoft.Testing.Extensions.VSTestBridge.1.0.2\lib\netstandard2.0\Microsoft.Testing.Extensions.VSTestBridge.dll + + + ..\packages\Microsoft.Testing.Platform.MSBuild.1.0.2\lib\netstandard2.0\Microsoft.Testing.Platform.dll + + + ..\packages\Microsoft.Testing.Platform.MSBuild.1.0.2\lib\netstandard2.0\Microsoft.Testing.Platform.MSBuild.dll + + + ..\packages\Microsoft.TestPlatform.ObjectModel.17.9.0\lib\net462\Microsoft.TestPlatform.CoreUtilities.dll + + + ..\packages\Microsoft.TestPlatform.ObjectModel.17.9.0\lib\net462\Microsoft.TestPlatform.PlatformAbstractions.dll + + + ..\packages\Microsoft.TestPlatform.ObjectModel.17.9.0\lib\net462\Microsoft.VisualStudio.TestPlatform.ObjectModel.dll + + + ..\packages\MSTest.TestFramework.3.2.2\lib\net462\Microsoft.VisualStudio.TestPlatform.TestFramework.dll + + + ..\packages\MSTest.TestFramework.3.2.2\lib\net462\Microsoft.VisualStudio.TestPlatform.TestFramework.Extensions.dll + + + ..\packages\Moq.4.20.70\lib\net462\Moq.dll + + + ..\packages\NuGet.Frameworks.6.9.1\lib\net472\NuGet.Frameworks.dll + + + + ..\packages\System.Buffers.4.5.1\lib\net461\System.Buffers.dll + + + ..\packages\System.Collections.Immutable.8.0.0\lib\net462\System.Collections.Immutable.dll + + + + + ..\packages\System.Diagnostics.DiagnosticSource.8.0.0\lib\net462\System.Diagnostics.DiagnosticSource.dll + + + ..\packages\System.Memory.4.5.5\lib\net461\System.Memory.dll + + + + + ..\packages\System.Numerics.Vectors.4.5.0\lib\net46\System.Numerics.Vectors.dll + + + ..\packages\System.Reflection.Metadata.8.0.0\lib\net462\System.Reflection.Metadata.dll + + + + ..\packages\System.Runtime.CompilerServices.Unsafe.6.0.0\lib\net461\System.Runtime.CompilerServices.Unsafe.dll + + + + ..\packages\System.Threading.Tasks.Extensions.4.5.4\lib\net461\System.Threading.Tasks.Extensions.dll + + + + + + + + + + + + + + + + + {ac77745d-3b41-43e2-8e84-d40e5a4ee77f} + SafeExamBrowser.Applications.Contracts + + + {a113e68f-1209-4689-981a-15c554b2df4e} + SafeExamBrowser.Applications + + + {fe0e1224-b447-4b14-81e7-ed7d84822aa0} + SafeExamBrowser.Core.Contracts + + + {64ea30fb-11d4-436a-9c2b-88566285363e} + SafeExamBrowser.Logging.Contracts + + + {6d563a30-366d-4c35-815b-2c9e6872278b} + SafeExamBrowser.Monitoring.Contracts + + + {30b2d907-5861-4f39-abad-c4abf1b3470e} + SafeExamBrowser.Settings + + + {903129c6-e236-493b-9ad6-c6a57f647a3a} + SafeExamBrowser.SystemComponents.Contracts + + + {7016f080-9aa5-41b2-a225-385ad877c171} + SafeExamBrowser.WindowsApi.Contracts + + + + + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + + + + + + + \ No newline at end of file diff --git a/SafeExamBrowser.Applications.UnitTests/app.config b/SafeExamBrowser.Applications.UnitTests/app.config new file mode 100644 index 0000000..9821a52 --- /dev/null +++ b/SafeExamBrowser.Applications.UnitTests/app.config @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/SafeExamBrowser.Applications.UnitTests/packages.config b/SafeExamBrowser.Applications.UnitTests/packages.config new file mode 100644 index 0000000..f170b50 --- /dev/null +++ b/SafeExamBrowser.Applications.UnitTests/packages.config @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/SafeExamBrowser.Applications/ApplicationFactory.cs b/SafeExamBrowser.Applications/ApplicationFactory.cs new file mode 100644 index 0000000..44be9f7 --- /dev/null +++ b/SafeExamBrowser.Applications/ApplicationFactory.cs @@ -0,0 +1,147 @@ +/* + * Copyright (c) 2024 ETH Zürich, IT Services + * + * 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.Collections.Generic; +using System.IO; +using SafeExamBrowser.Applications.Contracts; +using SafeExamBrowser.Logging.Contracts; +using SafeExamBrowser.Monitoring.Contracts.Applications; +using SafeExamBrowser.Settings.Applications; +using SafeExamBrowser.SystemComponents.Contracts.Registry; +using SafeExamBrowser.WindowsApi.Contracts; + +namespace SafeExamBrowser.Applications +{ + public class ApplicationFactory : IApplicationFactory + { + private readonly IApplicationMonitor applicationMonitor; + private readonly IModuleLogger logger; + private readonly INativeMethods nativeMethods; + private readonly IProcessFactory processFactory; + private readonly IRegistry registry; + + public ApplicationFactory( + IApplicationMonitor applicationMonitor, + IModuleLogger logger, + INativeMethods nativeMethods, + IProcessFactory processFactory, + IRegistry registry) + { + this.applicationMonitor = applicationMonitor; + this.logger = logger; + this.nativeMethods = nativeMethods; + this.processFactory = processFactory; + this.registry = registry; + } + + public FactoryResult TryCreate(WhitelistApplication settings, out IApplication application) + { + var name = $"'{settings.DisplayName}' ({settings.ExecutableName})"; + + application = default; + + try + { + var success = TryFindApplication(settings, out var executablePath); + + if (success) + { + application = BuildApplication(executablePath, settings); + application.Initialize(); + + logger.Debug($"Successfully initialized application {name}."); + + return FactoryResult.Success; + } + + logger.Error($"Could not find application {name}!"); + + return FactoryResult.NotFound; + } + catch (Exception e) + { + logger.Error($"Unexpected error while trying to initialize application {name}!", e); + } + + return FactoryResult.Error; + } + + private IApplication BuildApplication(string executablePath, WhitelistApplication settings) + { + const int ONE_SECOND = 1000; + + var applicationLogger = logger.CloneFor(settings.DisplayName); + var application = new ExternalApplication(applicationMonitor, executablePath, applicationLogger, nativeMethods, processFactory, settings, ONE_SECOND); + + return application; + } + + private bool TryFindApplication(WhitelistApplication settings, out string mainExecutable) + { + var paths = new List(); + var registryPath = QueryPathFromRegistry(settings); + + mainExecutable = default; + + paths.Add(new[] { Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), settings.ExecutableName }); + paths.Add(new[] { Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86), settings.ExecutableName }); + paths.Add(new[] { Environment.GetFolderPath(Environment.SpecialFolder.System), settings.ExecutableName }); + paths.Add(new[] { Environment.GetFolderPath(Environment.SpecialFolder.SystemX86), settings.ExecutableName }); + + if (settings.ExecutablePath != default) + { + paths.Add(new[] { settings.ExecutablePath, settings.ExecutableName }); + paths.Add(new[] { Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), settings.ExecutablePath, settings.ExecutableName }); + paths.Add(new[] { Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86), settings.ExecutablePath, settings.ExecutableName }); + paths.Add(new[] { Environment.GetFolderPath(Environment.SpecialFolder.System), settings.ExecutablePath, settings.ExecutableName }); + paths.Add(new[] { Environment.GetFolderPath(Environment.SpecialFolder.SystemX86), settings.ExecutablePath, settings.ExecutableName }); + } + + if (registryPath != default) + { + paths.Add(new[] { registryPath, settings.ExecutableName }); + + if (settings.ExecutablePath != default) + { + paths.Add(new[] { registryPath, settings.ExecutablePath, settings.ExecutableName }); + } + } + + foreach (var path in paths) + { + try + { + mainExecutable = Path.Combine(path); + mainExecutable = Environment.ExpandEnvironmentVariables(mainExecutable); + + if (File.Exists(mainExecutable)) + { + return true; + } + } + catch (Exception e) + { + logger.Error($"Failed to test path {string.Join(@"\", path)}!", e); + } + } + + return false; + } + + private string QueryPathFromRegistry(WhitelistApplication settings) + { + if (registry.TryRead($@"{RegistryValue.MachineHive.AppPaths_Key}\{settings.ExecutableName}", "Path", out var value)) + { + return value as string; + } + + return default; + } + } +} diff --git a/SafeExamBrowser.Applications/Events/InstanceTerminatedEventHandler.cs b/SafeExamBrowser.Applications/Events/InstanceTerminatedEventHandler.cs new file mode 100644 index 0000000..564a038 --- /dev/null +++ b/SafeExamBrowser.Applications/Events/InstanceTerminatedEventHandler.cs @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2024 ETH Zürich, IT Services + * + * 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/. + */ + +namespace SafeExamBrowser.Applications.Events +{ + internal delegate void InstanceTerminatedEventHandler(int id); +} diff --git a/SafeExamBrowser.Applications/ExternalApplication.cs b/SafeExamBrowser.Applications/ExternalApplication.cs new file mode 100644 index 0000000..1767dc1 --- /dev/null +++ b/SafeExamBrowser.Applications/ExternalApplication.cs @@ -0,0 +1,174 @@ +/* + * Copyright (c) 2024 ETH Zürich, IT Services + * + * 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.Collections.Generic; +using System.Linq; +using SafeExamBrowser.Applications.Contracts; +using SafeExamBrowser.Applications.Contracts.Events; +using SafeExamBrowser.Core.Contracts.Resources.Icons; +using SafeExamBrowser.Logging.Contracts; +using SafeExamBrowser.Monitoring.Contracts.Applications; +using SafeExamBrowser.Settings.Applications; +using SafeExamBrowser.WindowsApi.Contracts; + +namespace SafeExamBrowser.Applications +{ + internal class ExternalApplication : IApplication + { + private readonly object @lock = new object(); + + private readonly IApplicationMonitor applicationMonitor; + private readonly string executablePath; + private readonly IList instances; + private readonly IModuleLogger logger; + private readonly INativeMethods nativeMethods; + private readonly IProcessFactory processFactory; + private readonly WhitelistApplication settings; + private readonly int windowMonitoringInterval; + + public bool AutoStart { get; private set; } + public IconResource Icon { get; private set; } + public Guid Id { get; private set; } + public string Name { get; private set; } + public string Tooltip { get; private set; } + + public event WindowsChangedEventHandler WindowsChanged; + + internal ExternalApplication( + IApplicationMonitor applicationMonitor, + string executablePath, + IModuleLogger logger, + INativeMethods nativeMethods, + IProcessFactory processFactory, + WhitelistApplication settings, + int windowMonitoringInterval_ms) + { + this.applicationMonitor = applicationMonitor; + this.executablePath = executablePath; + this.logger = logger; + this.nativeMethods = nativeMethods; + this.instances = new List(); + this.processFactory = processFactory; + this.settings = settings; + this.windowMonitoringInterval = windowMonitoringInterval_ms; + } + + public IEnumerable GetWindows() + { + lock (@lock) + { + return instances.SelectMany(i => i.GetWindows()); + } + } + + public void Initialize() + { + AutoStart = settings.AutoStart; + Icon = new EmbeddedIconResource { FilePath = executablePath }; + Id = settings.Id; + Name = settings.DisplayName; + Tooltip = settings.Description ?? settings.DisplayName; + + applicationMonitor.InstanceStarted += ApplicationMonitor_InstanceStarted; + } + + public void Start() + { + try + { + logger.Info("Starting application..."); + InitializeInstance(processFactory.StartNew(executablePath, BuildArguments())); + logger.Info("Successfully started application."); + } + catch (Exception e) + { + logger.Error("Failed to start application!", e); + } + } + + public void Terminate() + { + applicationMonitor.InstanceStarted -= ApplicationMonitor_InstanceStarted; + + try + { + lock (@lock) + { + if (instances.Any() && !settings.AllowRunning) + { + logger.Info($"Terminating application with {instances.Count} instance(s)..."); + + foreach (var instance in instances) + { + instance.Terminated -= Instance_Terminated; + instance.Terminate(); + } + + logger.Info("Successfully terminated application."); + } + } + } + catch (Exception e) + { + logger.Error($"Failed to terminate application!", e); + } + } + + private void ApplicationMonitor_InstanceStarted(Guid applicationId, IProcess process) + { + lock (@lock) + { + var isNewInstance = instances.All(i => i.Id != process.Id); + + if (applicationId == Id && isNewInstance) + { + logger.Info("New application instance was started."); + InitializeInstance(process); + } + } + } + + private void Instance_Terminated(int id) + { + lock (@lock) + { + instances.Remove(instances.First(i => i.Id == id)); + } + + WindowsChanged?.Invoke(); + } + + private string[] BuildArguments() + { + var arguments = new List(); + + foreach (var argument in settings.Arguments) + { + arguments.Add(Environment.ExpandEnvironmentVariables(argument)); + } + + return arguments.ToArray(); + } + + private void InitializeInstance(IProcess process) + { + lock (@lock) + { + var instanceLogger = logger.CloneFor($"{Name} ({process.Id})"); + var instance = new ExternalApplicationInstance(Icon, instanceLogger, nativeMethods, process, windowMonitoringInterval); + + instance.Terminated += Instance_Terminated; + instance.WindowsChanged += () => WindowsChanged?.Invoke(); + instance.Initialize(); + + instances.Add(instance); + } + } + } +} diff --git a/SafeExamBrowser.Applications/ExternalApplicationInstance.cs b/SafeExamBrowser.Applications/ExternalApplicationInstance.cs new file mode 100644 index 0000000..36e8f6c --- /dev/null +++ b/SafeExamBrowser.Applications/ExternalApplicationInstance.cs @@ -0,0 +1,174 @@ +/* + * Copyright (c) 2024 ETH Zürich, IT Services + * + * 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.Collections.Generic; +using System.Linq; +using System.Timers; +using SafeExamBrowser.Applications.Contracts; +using SafeExamBrowser.Applications.Contracts.Events; +using SafeExamBrowser.Applications.Events; +using SafeExamBrowser.Core.Contracts.Resources.Icons; +using SafeExamBrowser.Logging.Contracts; +using SafeExamBrowser.WindowsApi.Contracts; + +namespace SafeExamBrowser.Applications +{ + internal class ExternalApplicationInstance + { + private readonly object @lock = new object(); + + private readonly IconResource icon; + private readonly ILogger logger; + private readonly INativeMethods nativeMethods; + private readonly IProcess process; + private readonly int windowMonitoringInterval; + private readonly IList windows; + + private Timer timer; + + internal int Id { get; private set; } + + internal event InstanceTerminatedEventHandler Terminated; + internal event WindowsChangedEventHandler WindowsChanged; + + internal ExternalApplicationInstance( + IconResource icon, + ILogger logger, + INativeMethods nativeMethods, + IProcess process, + int windowMonitoringInterval_ms) + { + this.icon = icon; + this.logger = logger; + this.nativeMethods = nativeMethods; + this.process = process; + this.windowMonitoringInterval = windowMonitoringInterval_ms; + this.windows = new List(); + } + + internal IEnumerable GetWindows() + { + lock (@lock) + { + return new List(windows); + } + } + + internal void Initialize() + { + Id = process.Id; + InitializeEvents(); + logger.Info("Initialized application instance."); + } + + internal void Terminate() + { + const int MAX_ATTEMPTS = 5; + const int TIMEOUT_MS = 500; + + var terminated = process.HasTerminated; + + if (terminated) + { + logger.Info("Application instance is already terminated."); + } + else + { + FinalizeEvents(); + + for (var attempt = 0; attempt < MAX_ATTEMPTS && !terminated; attempt++) + { + terminated = process.TryClose(TIMEOUT_MS); + } + + for (var attempt = 0; attempt < MAX_ATTEMPTS && !terminated; attempt++) + { + terminated = process.TryKill(TIMEOUT_MS); + } + + if (terminated) + { + logger.Info("Successfully terminated application instance."); + } + else + { + logger.Warn("Failed to terminate application instance!"); + } + } + } + + private void Process_Terminated(int exitCode) + { + logger.Info($"Application instance has terminated with exit code {exitCode}."); + FinalizeEvents(); + Terminated?.Invoke(Id); + } + + private void Timer_Elapsed(object sender, ElapsedEventArgs e) + { + var changed = false; + var openWindows = nativeMethods.GetOpenWindows(); + + lock (@lock) + { + var closedWindows = windows.Where(w => openWindows.All(ow => ow != w.Handle)).ToList(); + var openedWindows = openWindows.Where(ow => windows.All(w => w.Handle != ow) && BelongsToInstance(ow)).ToList(); + + foreach (var window in closedWindows) + { + changed = true; + windows.Remove(window); + } + + foreach (var window in openedWindows) + { + changed = true; + windows.Add(new ExternalApplicationWindow(icon, nativeMethods, window)); + } + + foreach (var window in windows) + { + window.Update(); + } + } + + if (changed) + { + WindowsChanged?.Invoke(); + } + + timer.Start(); + } + + private bool BelongsToInstance(IntPtr window) + { + return nativeMethods.GetProcessIdFor(window) == process.Id; + } + + private void InitializeEvents() + { + process.Terminated += Process_Terminated; + + timer = new Timer(windowMonitoringInterval); + timer.Elapsed += Timer_Elapsed; + timer.Start(); + } + + private void FinalizeEvents() + { + if (timer != default) + { + timer.Elapsed -= Timer_Elapsed; + timer.Stop(); + } + + process.Terminated -= Process_Terminated; + } + } +} diff --git a/SafeExamBrowser.Applications/ExternalApplicationWindow.cs b/SafeExamBrowser.Applications/ExternalApplicationWindow.cs new file mode 100644 index 0000000..fd07e07 --- /dev/null +++ b/SafeExamBrowser.Applications/ExternalApplicationWindow.cs @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2024 ETH Zürich, IT Services + * + * 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 SafeExamBrowser.Applications.Contracts; +using SafeExamBrowser.Applications.Contracts.Events; +using SafeExamBrowser.Core.Contracts.Resources.Icons; +using SafeExamBrowser.WindowsApi.Contracts; + +namespace SafeExamBrowser.Applications +{ + internal class ExternalApplicationWindow : IApplicationWindow + { + private readonly INativeMethods nativeMethods; + + public IntPtr Handle { get; } + public IconResource Icon { get; private set; } + public string Title { get; private set; } + + public event IconChangedEventHandler IconChanged; + public event TitleChangedEventHandler TitleChanged; + + internal ExternalApplicationWindow(IconResource icon, INativeMethods nativeMethods, IntPtr handle) + { + this.Handle = handle; + this.Icon = icon; + this.nativeMethods = nativeMethods; + } + + public void Activate() + { + nativeMethods.ActivateWindow(Handle); + } + + internal void Update() + { + var icon = nativeMethods.GetWindowIcon(Handle); + var iconChanged = icon != IntPtr.Zero && (!(Icon is NativeIconResource) || Icon is NativeIconResource r && r.Handle != icon); + var title = nativeMethods.GetWindowTitle(Handle); + var titleChanged = Title?.Equals(title, StringComparison.Ordinal) != true; + + if (iconChanged) + { + Icon = new NativeIconResource { Handle = icon }; + IconChanged?.Invoke(Icon); + } + + if (titleChanged) + { + Title = title; + TitleChanged?.Invoke(title); + } + } + } +} diff --git a/SafeExamBrowser.Applications/Properties/AssemblyInfo.cs b/SafeExamBrowser.Applications/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..615967b --- /dev/null +++ b/SafeExamBrowser.Applications/Properties/AssemblyInfo.cs @@ -0,0 +1,35 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("SafeExamBrowser.Applications")] +[assembly: AssemblyDescription("Safe Exam Browser")] +[assembly: AssemblyCompany("ETH Zürich")] +[assembly: AssemblyProduct("SafeExamBrowser.Applications")] +[assembly: AssemblyCopyright("Copyright © 2024 ETH Zürich, IT Services")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] +[assembly: InternalsVisibleTo("SafeExamBrowser.Applications.UnitTests")] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("a113e68f-1209-4689-981a-15c554b2df4e")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] +[assembly: AssemblyInformationalVersion("1.0.0.0")] diff --git a/SafeExamBrowser.Applications/SafeExamBrowser.Applications.csproj b/SafeExamBrowser.Applications/SafeExamBrowser.Applications.csproj new file mode 100644 index 0000000..0713836 --- /dev/null +++ b/SafeExamBrowser.Applications/SafeExamBrowser.Applications.csproj @@ -0,0 +1,96 @@ + + + + + Debug + AnyCPU + {A113E68F-1209-4689-981A-15C554B2DF4E} + Library + Properties + SafeExamBrowser.Applications + SafeExamBrowser.Applications + v4.8 + 512 + true + + + + true + bin\x86\Debug\ + DEBUG;TRACE + full + x86 + prompt + MinimumRecommendedRules.ruleset + + + bin\x86\Release\ + TRACE + true + pdbonly + x86 + prompt + MinimumRecommendedRules.ruleset + + + true + bin\x64\Debug\ + DEBUG;TRACE + full + x64 + prompt + MinimumRecommendedRules.ruleset + + + bin\x64\Release\ + TRACE + true + pdbonly + x64 + prompt + MinimumRecommendedRules.ruleset + + + + + + + + + + + + + + + + {ac77745d-3b41-43e2-8e84-d40e5a4ee77f} + SafeExamBrowser.Applications.Contracts + + + {fe0e1224-b447-4b14-81e7-ed7d84822aa0} + SafeExamBrowser.Core.Contracts + + + {64ea30fb-11d4-436a-9c2b-88566285363e} + SafeExamBrowser.Logging.Contracts + + + {6d563a30-366d-4c35-815b-2c9e6872278b} + SafeExamBrowser.Monitoring.Contracts + + + {30b2d907-5861-4f39-abad-c4abf1b3470e} + SafeExamBrowser.Settings + + + {903129c6-e236-493b-9ad6-c6a57f647a3a} + SafeExamBrowser.SystemComponents.Contracts + + + {7016f080-9aa5-41b2-a225-385ad877c171} + SafeExamBrowser.WindowsApi.Contracts + + + + \ No newline at end of file diff --git a/SafeExamBrowser.Browser.Contracts/Events/DownloadEventArgs.cs b/SafeExamBrowser.Browser.Contracts/Events/DownloadEventArgs.cs new file mode 100644 index 0000000..86c5a22 --- /dev/null +++ b/SafeExamBrowser.Browser.Contracts/Events/DownloadEventArgs.cs @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2024 ETH Zürich, IT Services + * + * 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/. + */ + +namespace SafeExamBrowser.Browser.Contracts.Events +{ + /// + /// The event arguments used for all download events. + /// + public class DownloadEventArgs + { + /// + /// Determines whether the specified download is allowed. + /// + public bool AllowDownload { get; set; } + + /// + /// Callback executed once a download has been finished. + /// + public DownloadFinishedCallback Callback { get; set; } + + /// + /// The full path under which the specified file should be saved. + /// + public string DownloadPath { get; set; } + + /// + /// The URL of the resource to be downloaded. + /// + public string Url { get; set; } + } +} diff --git a/SafeExamBrowser.Browser.Contracts/Events/DownloadFinishedCallback.cs b/SafeExamBrowser.Browser.Contracts/Events/DownloadFinishedCallback.cs new file mode 100644 index 0000000..6bc0fc8 --- /dev/null +++ b/SafeExamBrowser.Browser.Contracts/Events/DownloadFinishedCallback.cs @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2024 ETH Zürich, IT Services + * + * 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/. + */ + +namespace SafeExamBrowser.Browser.Contracts.Events +{ + /// + /// Defines the method signature for callbacks to be executed once a download has been finished. Indicates the URL of the resource, + /// whether the download was successful, and if so, where it was saved. + /// + public delegate void DownloadFinishedCallback(bool success, string url, string filePath = null); +} diff --git a/SafeExamBrowser.Browser.Contracts/Events/DownloadRequestedEventHandler.cs b/SafeExamBrowser.Browser.Contracts/Events/DownloadRequestedEventHandler.cs new file mode 100644 index 0000000..73b80cb --- /dev/null +++ b/SafeExamBrowser.Browser.Contracts/Events/DownloadRequestedEventHandler.cs @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2024 ETH Zürich, IT Services + * + * 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/. + */ + +namespace SafeExamBrowser.Browser.Contracts.Events +{ + /// + /// Event handler used to control (e.g. allow or prohibit) download requests. + /// + public delegate void DownloadRequestedEventHandler(string fileName, DownloadEventArgs args); +} diff --git a/SafeExamBrowser.Browser.Contracts/Events/LoseFocusRequestedEventHandler.cs b/SafeExamBrowser.Browser.Contracts/Events/LoseFocusRequestedEventHandler.cs new file mode 100644 index 0000000..c3ab885 --- /dev/null +++ b/SafeExamBrowser.Browser.Contracts/Events/LoseFocusRequestedEventHandler.cs @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2024 ETH Zürich, IT Services + * + * 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/. + */ + +namespace SafeExamBrowser.Browser.Contracts.Events +{ + /// + /// Event handler used to indicate that the user wants to move the focus away from the item. + /// + public delegate void LoseFocusRequestedEventHandler(bool forward); +} diff --git a/SafeExamBrowser.Browser.Contracts/Events/TabPressedEventHandler.cs b/SafeExamBrowser.Browser.Contracts/Events/TabPressedEventHandler.cs new file mode 100644 index 0000000..4e9a13a --- /dev/null +++ b/SafeExamBrowser.Browser.Contracts/Events/TabPressedEventHandler.cs @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2024 ETH Zürich, IT Services + * + * 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/. + */ + +namespace SafeExamBrowser.Browser.Contracts.Events +{ + /// + /// Event handler used to indicate that the user pressed the tab key to move the focus forward or backward. + /// + public delegate void TabPressedEventHandler(bool forward); +} diff --git a/SafeExamBrowser.Browser.Contracts/Events/TerminationRequestedEventHandler.cs b/SafeExamBrowser.Browser.Contracts/Events/TerminationRequestedEventHandler.cs new file mode 100644 index 0000000..b31dce0 --- /dev/null +++ b/SafeExamBrowser.Browser.Contracts/Events/TerminationRequestedEventHandler.cs @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2024 ETH Zürich, IT Services + * + * 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/. + */ + +namespace SafeExamBrowser.Browser.Contracts.Events +{ + /// + /// Event handler used to indicate that a termination request has been detected. + /// + public delegate void TerminationRequestedEventHandler(); +} diff --git a/SafeExamBrowser.Browser.Contracts/Events/UserIdentifierDetectedEventHandler.cs b/SafeExamBrowser.Browser.Contracts/Events/UserIdentifierDetectedEventHandler.cs new file mode 100644 index 0000000..b256954 --- /dev/null +++ b/SafeExamBrowser.Browser.Contracts/Events/UserIdentifierDetectedEventHandler.cs @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2024 ETH Zürich, IT Services + * + * 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/. + */ + +namespace SafeExamBrowser.Browser.Contracts.Events +{ + /// + /// Event handler used to indicate that the browser has detected a user identifier of an LMS. + /// + public delegate void UserIdentifierDetectedEventHandler(string identifier); +} diff --git a/SafeExamBrowser.Browser.Contracts/Filters/IRequestFilter.cs b/SafeExamBrowser.Browser.Contracts/Filters/IRequestFilter.cs new file mode 100644 index 0000000..963e38a --- /dev/null +++ b/SafeExamBrowser.Browser.Contracts/Filters/IRequestFilter.cs @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2024 ETH Zürich, IT Services + * + * 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 SafeExamBrowser.Settings.Browser.Filter; + +namespace SafeExamBrowser.Browser.Contracts.Filters +{ + /// + /// Defines the filter for browser requests. + /// + public interface IRequestFilter + { + /// + /// The default result to be returned by if no rule matches. + /// + FilterResult Default { get; set; } + + /// + /// Loads the given filter rule to be used when processing requests. + /// + void Load(IRule rule); + + /// + /// Filters the given request according to the loaded rules. + /// + FilterResult Process(Request request); + } +} diff --git a/SafeExamBrowser.Browser.Contracts/Filters/IRule.cs b/SafeExamBrowser.Browser.Contracts/Filters/IRule.cs new file mode 100644 index 0000000..b0f571f --- /dev/null +++ b/SafeExamBrowser.Browser.Contracts/Filters/IRule.cs @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2024 ETH Zürich, IT Services + * + * 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 SafeExamBrowser.Settings.Browser.Filter; + +namespace SafeExamBrowser.Browser.Contracts.Filters +{ + /// + /// Defines a request filter rule. + /// + public interface IRule + { + /// + /// The filter result to be used if the rule matches a request. + /// + FilterResult Result { get; } + + /// + /// Initializes the rule for processing requests. + /// + void Initialize(FilterRuleSettings settings); + + /// + /// Indicates whether the rule applies for the given request. + /// + bool IsMatch(Request request); + } +} diff --git a/SafeExamBrowser.Browser.Contracts/Filters/IRuleFactory.cs b/SafeExamBrowser.Browser.Contracts/Filters/IRuleFactory.cs new file mode 100644 index 0000000..97ff254 --- /dev/null +++ b/SafeExamBrowser.Browser.Contracts/Filters/IRuleFactory.cs @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2024 ETH Zürich, IT Services + * + * 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 SafeExamBrowser.Settings.Browser.Filter; + +namespace SafeExamBrowser.Browser.Contracts.Filters +{ + /// + /// Builds request filter rules. + /// + public interface IRuleFactory + { + /// + /// Creates a filter rule for the given type. + /// + IRule CreateRule(FilterRuleType type); + } +} diff --git a/SafeExamBrowser.Browser.Contracts/Filters/Request.cs b/SafeExamBrowser.Browser.Contracts/Filters/Request.cs new file mode 100644 index 0000000..81a39fe --- /dev/null +++ b/SafeExamBrowser.Browser.Contracts/Filters/Request.cs @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2024 ETH Zürich, IT Services + * + * 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/. + */ + +namespace SafeExamBrowser.Browser.Contracts.Filters +{ + /// + /// Holds data relevant for filtering requests. + /// + public class Request + { + /// + /// The full URL of the request. + /// + public string Url { get; set; } + } +} diff --git a/SafeExamBrowser.Browser.Contracts/IBrowserApplication.cs b/SafeExamBrowser.Browser.Contracts/IBrowserApplication.cs new file mode 100644 index 0000000..7d0bba7 --- /dev/null +++ b/SafeExamBrowser.Browser.Contracts/IBrowserApplication.cs @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2024 ETH Zürich, IT Services + * + * 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 SafeExamBrowser.Applications.Contracts; +using SafeExamBrowser.Browser.Contracts.Events; + +namespace SafeExamBrowser.Browser.Contracts +{ + /// + /// Controls the lifetime and functionality of the browser application. + /// + public interface IBrowserApplication : IApplication + { + /// + /// Event fired when the browser application detects a download request for an application configuration file. + /// + event DownloadRequestedEventHandler ConfigurationDownloadRequested; + + /// + /// Event fired when the user tries to focus the taskbar. + /// + event LoseFocusRequestedEventHandler LoseFocusRequested; + + /// + /// Event fired when the browser application detects a request to terminate SEB. + /// + event TerminationRequestedEventHandler TerminationRequested; + + /// + /// Event fired when the browser application detects a user identifier of an LMS. + /// + event UserIdentifierDetectedEventHandler UserIdentifierDetected; + + /// + /// Transfers the focus to the browser application. If the parameter is true, the first focusable element in the browser window + /// receives focus (passing forward of focus). Otherwise, the last element receives focus. + /// + void Focus(bool forward); + } +} diff --git a/SafeExamBrowser.Browser.Contracts/IBrowserWindow.cs b/SafeExamBrowser.Browser.Contracts/IBrowserWindow.cs new file mode 100644 index 0000000..6cc3af1 --- /dev/null +++ b/SafeExamBrowser.Browser.Contracts/IBrowserWindow.cs @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2024 ETH Zürich, IT Services + * + * 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 SafeExamBrowser.Applications.Contracts; + +namespace SafeExamBrowser.Browser.Contracts +{ + /// + /// Defines a window of the . + /// + public interface IBrowserWindow : IApplicationWindow + { + /// + /// Indicates whether the window is the main browser window. + /// + bool IsMainWindow { get; } + + /// + /// The currently loaded URL, or default(string) in case no navigation has happened yet. + /// + string Url { get; } + } +} diff --git a/SafeExamBrowser.Browser.Contracts/Properties/AssemblyInfo.cs b/SafeExamBrowser.Browser.Contracts/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..0dfc261 --- /dev/null +++ b/SafeExamBrowser.Browser.Contracts/Properties/AssemblyInfo.cs @@ -0,0 +1,33 @@ +using System.Reflection; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("SafeExamBrowser.Browser.Contracts")] +[assembly: AssemblyDescription("Safe Exam Browser")] +[assembly: AssemblyCompany("ETH Zürich")] +[assembly: AssemblyProduct("SafeExamBrowser.Browser.Contracts")] +[assembly: AssemblyCopyright("Copyright © 2024 ETH Zürich, IT Services")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("5fb5273d-277c-41dd-8593-a25ce1aff2e9")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] +[assembly: AssemblyInformationalVersion("1.0.0.0")] diff --git a/SafeExamBrowser.Browser.Contracts/SafeExamBrowser.Browser.Contracts.csproj b/SafeExamBrowser.Browser.Contracts/SafeExamBrowser.Browser.Contracts.csproj new file mode 100644 index 0000000..35f2d64 --- /dev/null +++ b/SafeExamBrowser.Browser.Contracts/SafeExamBrowser.Browser.Contracts.csproj @@ -0,0 +1,84 @@ + + + + + Debug + AnyCPU + {5FB5273D-277C-41DD-8593-A25CE1AFF2E9} + Library + Properties + SafeExamBrowser.Browser.Contracts + SafeExamBrowser.Browser.Contracts + v4.8 + 512 + true + + + + true + bin\x86\Debug\ + DEBUG;TRACE + full + x86 + prompt + MinimumRecommendedRules.ruleset + + + bin\x86\Release\ + TRACE + true + pdbonly + x86 + prompt + MinimumRecommendedRules.ruleset + + + true + bin\x64\Debug\ + DEBUG;TRACE + full + x64 + prompt + MinimumRecommendedRules.ruleset + + + bin\x64\Release\ + TRACE + true + pdbonly + x64 + prompt + MinimumRecommendedRules.ruleset + + + + + + + + + + + + + + + + + + + + + + + + {ac77745d-3b41-43e2-8e84-d40e5a4ee77f} + SafeExamBrowser.Applications.Contracts + + + {30b2d907-5861-4f39-abad-c4abf1b3470e} + SafeExamBrowser.Settings + + + + \ No newline at end of file diff --git a/SafeExamBrowser.Browser.UnitTests/Filters/LegacyFilter.cs b/SafeExamBrowser.Browser.UnitTests/Filters/LegacyFilter.cs new file mode 100644 index 0000000..1bd2604 --- /dev/null +++ b/SafeExamBrowser.Browser.UnitTests/Filters/LegacyFilter.cs @@ -0,0 +1,553 @@ +/* + * Copyright (c) 2024 ETH Zürich, IT Services + * + * This Source Code Form is subject to the terms of the Mozilla internal + * 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.Text; +using System.Text.RegularExpressions; + +namespace SafeExamBrowser.Browser.UnitTests.Filters +{ + internal class LegacyFilter + { + internal Regex scheme; + internal Regex user; + internal Regex password; + internal Regex host; + internal int? port; + internal Regex path; + internal Regex query; + internal Regex fragment; + + internal LegacyFilter(string filterExpressionString) + { + SEBURLFilterExpression URLFromString = new SEBURLFilterExpression(filterExpressionString); + try + { + this.scheme = RegexForFilterString(URLFromString.scheme); + this.user = RegexForFilterString(URLFromString.user); + this.password = RegexForFilterString(URLFromString.password); + this.host = RegexForHostFilterString(URLFromString.host); + this.port = URLFromString.port; + this.path = RegexForPathFilterString(URLFromString.path); + this.query = RegexForQueryFilterString(URLFromString.query); + this.fragment = RegexForFilterString(URLFromString.fragment); + } + catch (Exception) + { + throw; + } + } + + // Method comparing all components of a passed URL with the filter expression + // and returning YES (= allow or block) if it matches + internal bool IsMatch(Uri URLToFilter) + { + Regex filterComponent; + + // If a scheme is indicated in the filter expression, it has to match + filterComponent = scheme; + UriBuilder urlToFilterParts = new UriBuilder(URLToFilter); + + if (filterComponent != null && + !Regex.IsMatch(URLToFilter.Scheme, filterComponent.ToString(), RegexOptions.IgnoreCase)) + { + // Scheme of the URL to filter doesn't match the one from the filter expression: Exit with matching = NO + return false; + } + + string userInfo = URLToFilter.UserInfo; + filterComponent = user; + if (filterComponent != null && + !Regex.IsMatch(urlToFilterParts.UserName, filterComponent.ToString(), RegexOptions.IgnoreCase)) + { + return false; + } + + filterComponent = password; + if (filterComponent != null && + !Regex.IsMatch(urlToFilterParts.Password, filterComponent.ToString(), RegexOptions.IgnoreCase)) + { + return false; + } + + filterComponent = host; + if (filterComponent != null && + !Regex.IsMatch(URLToFilter.Host, filterComponent.ToString(), RegexOptions.IgnoreCase)) + { + return false; + } + + if (port != null && URLToFilter.Port != port) + { + return false; + } + + filterComponent = path; + if (filterComponent != null && + !Regex.IsMatch(URLToFilter.AbsolutePath.TrimEnd(new char[] { '/' }), filterComponent.ToString(), RegexOptions.IgnoreCase)) + { + return false; + } + + string urlQuery = URLToFilter.GetComponents(UriComponents.Query, UriFormat.Unescaped); + filterComponent = query; + if (filterComponent != null) + { + // If there's a query filter component, then we need to even filter empty URL query strings + // as the filter might either allow some specific queries or no query at all ("?." query filter) + if (urlQuery == null) + { + urlQuery = ""; + } + if (!Regex.IsMatch(urlQuery, filterComponent.ToString(), RegexOptions.IgnoreCase)) + { + return false; + } + } + + string urlFragment = URLToFilter.GetComponents(UriComponents.Fragment, UriFormat.Unescaped); + filterComponent = fragment; + if (filterComponent != null && + !Regex.IsMatch(urlFragment, filterComponent.ToString(), RegexOptions.IgnoreCase)) + { + return false; + } + + // URL matches the filter expression + return true; + } + + internal static Regex RegexForFilterString(string filterString) + { + if (string.IsNullOrEmpty(filterString)) + { + return null; + } + else + { + string regexString = Regex.Escape(filterString); + regexString = regexString.Replace("\\*", ".*?"); + // Add regex command characters for matching at start and end of a line (part) + regexString = string.Format("^{0}$", regexString); + + try + { + Regex regex = new Regex(regexString, RegexOptions.IgnoreCase); + return regex; + } + catch (Exception) + { + throw; + } + } + } + + internal static Regex RegexForHostFilterString(string filterString) + { + if (string.IsNullOrEmpty(filterString)) + { + return null; + } + else + { + try + { + // Check if host string has a dot "." prefix to disable subdomain matching + if (filterString.Length > 1 && filterString.StartsWith(".")) + { + // Get host string without the "." prefix + filterString = filterString.Substring(1); + // Get regex for host <*://example.com> (without possible subdomains) + return RegexForFilterString(filterString); + } + // Allow subdomain matching: Create combined regex for and <*.example.com> + string regexString = Regex.Escape(filterString); + regexString = regexString.Replace("\\*", ".*?"); + // Add regex command characters for matching at start and end of a line (part) + regexString = string.Format("^(({0})|(.*?\\.{0}))$", regexString); + Regex regex = new Regex(regexString, RegexOptions.IgnoreCase); + return regex; + } + catch (Exception) + { + throw; + } + } + } + + internal static Regex RegexForPathFilterString(string filterString) + { + // Trim a possible trailing slash "/", we will instead add a rule to also match paths to directories without trailing slash + filterString = filterString.TrimEnd(new char[] { '/' }); + ; + + if (string.IsNullOrEmpty(filterString)) + { + return null; + } + else + { + try + { + // Check if path string ends with a "/*" for matching contents of a directory + if (filterString.EndsWith("/*")) + { + // As the path filter string matches for a directory, we need to add a string to match directories without trailing slash + + // Get path string without the "/*" suffix + string filterStringDirectory = filterString.Substring(0, filterString.Length - 2); + + string regexString = Regex.Escape(filterString); + regexString = regexString.Replace("\\*", ".*?"); + + string regexStringDir = Regex.Escape(filterString); + regexStringDir = regexStringDir.Replace("\\*", ".*?"); + + // Add regex command characters for matching at start and end of a line (part) + regexString = string.Format("^(({0})|({1}))$", regexString, regexStringDir); + + Regex regex = new Regex(regexString, RegexOptions.IgnoreCase); + return regex; + } + else + { + return RegexForFilterString(filterString); + } + } + catch (Exception) + { + throw; + } + } + } + + internal static Regex RegexForQueryFilterString(string filterString) + { + if (string.IsNullOrEmpty(filterString)) + { + return null; + } + else + { + if (filterString.Equals(".")) + { + // Add regex command characters for matching at start and end of a line (part) + // and regex for no string allowed + string regexString = @"^$"; + try + { + Regex regex = new Regex(regexString, RegexOptions.IgnoreCase); + return regex; + } + catch (Exception) + { + throw; + } + } + else + { + return RegexForFilterString(filterString); + } + } + } + + public override string ToString() + { + StringBuilder expressionString = new StringBuilder(); + string part; + expressionString.Append("^"); + + /// Scheme + if (this.scheme != null) + { + // If there is a regex filter for scheme + // get stripped regex pattern + part = StringForRegexFilter(this.scheme); + } + else + { + // otherwise use the regex wildcard pattern for scheme + part = @".*?"; + } + + expressionString.AppendFormat("{0}:\\/\\/", part); + + /// User/Password + if (this.user != null) + { + part = StringForRegexFilter(this.user); + + expressionString.Append(part); + + if (this.password != null) + { + expressionString.AppendFormat(":{0}@", StringForRegexFilter(this.password)); + } + else + { + expressionString.Append("@"); + } + } + + /// Host + string hostPort = ""; + if (this.host != null) + { + hostPort = StringForRegexFilter(this.host); + } + else + { + hostPort = ".*?"; + } + + /// Port + if (this.port != null && this.port > 0 && this.port <= 65535) + { + hostPort = string.Format("{0}:{1}", hostPort, this.port); + } + + // When there is a host, but no path + if (this.host != null && this.path == null) + { + hostPort = string.Format("(({0})|({0}\\/.*?))", hostPort); + } + + expressionString.Append(hostPort); + + /// Path + if (this.path != null) + { + string path = StringForRegexFilter(this.path); + if (path.StartsWith("\\/")) + { + expressionString.Append(path); + } + else + { + expressionString.AppendFormat("\\/{0}", path); + } + } + + /// Query + if (this.query != null) + { + // Check for special case Query = "?." which means no query string is allowed + if (StringForRegexFilter(this.query).Equals(".")) + { + expressionString.AppendFormat("[^\\?]"); + } + else + { + expressionString.AppendFormat("\\?{0}", StringForRegexFilter(this.query)); + } + } + else + { + expressionString.AppendFormat("(()|(\\?.*?))"); + } + + /// Fragment + if (this.fragment != null) + { + expressionString.AppendFormat("#{0}", StringForRegexFilter(this.fragment)); + } + + expressionString.Append("$"); + + return expressionString.ToString(); + } + + internal string StringForRegexFilter(Regex regexFilter) + { + // Get pattern string from regular expression + string regexPattern = regexFilter.ToString(); + if (regexPattern.Length <= 2) + { + return ""; + } + // Remove the regex command characters for matching at start and end of a line + regexPattern = regexPattern.Substring(1, regexPattern.Length - 2); + return regexPattern; + } + + private class SEBURLFilterExpression + { + internal string scheme; + internal string user; + internal string password; + internal string host; + internal int? port; + internal string path; + internal string query; + internal string fragment; + + internal SEBURLFilterExpression(string filterExpressionString) + { + if (!string.IsNullOrEmpty(filterExpressionString)) + { + /// Convert Uri to a SEBURLFilterExpression + string splitURLRegexPattern = @"(?:([^\:]*)\:\/\/)?(?:([^\:\@]*)(?:\:([^\@]*))?\@)?(?:([^\/‌​\:]*))?(?:\:([0-9\*]*))?([^\?#]*)?(?:\?([^#]*))?(?:#(.*))?"; + Regex splitURLRegex = new Regex(splitURLRegexPattern); + Match regexMatch = splitURLRegex.Match(filterExpressionString); + if (regexMatch.Success == false) + { + return; + } + + this.scheme = regexMatch.Groups[1].Value; + this.user = regexMatch.Groups[2].Value; + this.password = regexMatch.Groups[3].Value; + this.host = regexMatch.Groups[4].Value; + + // Treat a special case when a query or fragment is interpreted as part of the host address + if (this.host.Contains("?") || this.host.Contains("#")) + { + string splitURLRegexPattern2 = @"([^\?#]*)?(?:\?([^#]*))?(?:#(.*))?"; + Regex splitURLRegex2 = new Regex(splitURLRegexPattern2); + Match regexMatch2 = splitURLRegex2.Match(this.host); + if (regexMatch.Success == false) + { + return; + } + this.host = regexMatch2.Groups[1].Value; + this.port = null; + this.path = ""; + this.query = regexMatch2.Groups[2].Value; + this.fragment = regexMatch2.Groups[3].Value; + } + else + { + string portNumber = regexMatch.Groups[5].Value; + + // We only want a port if the filter expression string explicitely defines one! + if (portNumber.Length == 0 || portNumber == "*") + { + this.port = null; + } + else + { + this.port = UInt16.Parse(portNumber); + } + + this.path = regexMatch.Groups[6].Value.TrimEnd(new char[] { '/' }); + this.query = regexMatch.Groups[7].Value; + this.fragment = regexMatch.Groups[8].Value; + } + } + } + + internal static string User(string userInfo) + { + string user = ""; + if (!string.IsNullOrEmpty(userInfo)) + { + int userPasswordSeparator = userInfo.IndexOf(":"); + if (userPasswordSeparator == -1) + { + user = userInfo; + } + else + { + if (userPasswordSeparator != 0) + { + user = userInfo.Substring(0, userPasswordSeparator); + } + } + } + return user; + } + + internal static string Password(string userInfo) + { + string password = ""; + if (!string.IsNullOrEmpty(userInfo)) + { + int userPasswordSeparator = userInfo.IndexOf(":"); + if (userPasswordSeparator != -1) + { + if (userPasswordSeparator < userInfo.Length - 1) + { + password = userInfo.Substring(userPasswordSeparator + 1, userInfo.Length - 1 - userPasswordSeparator); + } + } + } + return password; + } + + internal SEBURLFilterExpression(string scheme, string user, string password, string host, int port, string path, string query, string fragment) + { + this.scheme = scheme; + this.user = user; + this.password = password; + this.host = host; + this.port = port; + this.path = path; + this.query = query; + this.fragment = fragment; + } + + public override string ToString() + { + StringBuilder expressionString = new StringBuilder(); + if (!string.IsNullOrEmpty(this.scheme)) + { + if (!string.IsNullOrEmpty(this.host)) + { + expressionString.AppendFormat("{0}://", this.scheme); + } + else + { + expressionString.AppendFormat("{0}:", this.scheme); + } + } + if (!string.IsNullOrEmpty(this.user)) + { + expressionString.Append(this.user); + + if (!string.IsNullOrEmpty(this.password)) + { + expressionString.AppendFormat(":{0}@", this.password); + } + else + { + expressionString.Append("@"); + } + } + if (!string.IsNullOrEmpty(this.host)) + { + expressionString.Append(this.host); + } + if (this.port != null && this.port > 0 && this.port <= 65535) + { + expressionString.AppendFormat(":{0}", this.port); + } + if (!string.IsNullOrEmpty(this.path)) + { + if (this.path.StartsWith("/")) + { + expressionString.Append(this.path); + } + else + { + expressionString.AppendFormat("/{0}", this.path); + } + } + if (!string.IsNullOrEmpty(this.query)) + { + expressionString.AppendFormat("?{0}", this.query); + } + if (!string.IsNullOrEmpty(this.fragment)) + { + expressionString.AppendFormat("#{0}", this.fragment); + } + + return expressionString.ToString(); + } + } + } +} diff --git a/SafeExamBrowser.Browser.UnitTests/Filters/RequestFilterTests.cs b/SafeExamBrowser.Browser.UnitTests/Filters/RequestFilterTests.cs new file mode 100644 index 0000000..195b64f --- /dev/null +++ b/SafeExamBrowser.Browser.UnitTests/Filters/RequestFilterTests.cs @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2024 ETH Zürich, IT Services + * + * 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 Microsoft.VisualStudio.TestTools.UnitTesting; +using Moq; +using SafeExamBrowser.Browser.Contracts.Filters; +using SafeExamBrowser.Browser.Filters; +using SafeExamBrowser.Settings.Browser.Filter; + +namespace SafeExamBrowser.Browser.UnitTests.Filters +{ + [TestClass] + public class RequestFilterTests + { + private RequestFilter sut; + + [TestInitialize] + public void Initialize() + { + sut = new RequestFilter(); + } + + [TestMethod] + public void MustProcessBlockRulesFirst() + { + var allow = new Mock(); + var block = new Mock(); + + allow.SetupGet(r => r.Result).Returns(FilterResult.Allow); + block.SetupGet(r => r.Result).Returns(FilterResult.Block); + block.Setup(r => r.IsMatch(It.IsAny())).Returns(true); + + sut.Load(allow.Object); + sut.Load(block.Object); + + var result = sut.Process(new Request()); + + allow.Verify(r => r.IsMatch(It.IsAny()), Times.Never); + block.Verify(r => r.IsMatch(It.IsAny()), Times.Once); + + Assert.AreEqual(FilterResult.Block, result); + } + + [TestMethod] + public void MustProcessAllowRulesSecond() + { + var allow = new Mock(); + var block = new Mock(); + + allow.SetupGet(r => r.Result).Returns(FilterResult.Allow); + allow.Setup(r => r.IsMatch(It.IsAny())).Returns(true); + block.SetupGet(r => r.Result).Returns(FilterResult.Block); + + sut.Load(allow.Object); + sut.Load(block.Object); + + var result = sut.Process(new Request()); + + allow.Verify(r => r.IsMatch(It.IsAny()), Times.Once); + block.Verify(r => r.IsMatch(It.IsAny()), Times.Once); + + Assert.AreEqual(FilterResult.Allow, result); + } + + [TestMethod] + public void MustReturnDefaultWithoutMatch() + { + var allow = new Mock(); + var block = new Mock(); + + allow.SetupGet(r => r.Result).Returns(FilterResult.Allow); + block.SetupGet(r => r.Result).Returns(FilterResult.Block); + + sut.Default = (FilterResult) (-1); + sut.Load(allow.Object); + sut.Load(block.Object); + + var result = sut.Process(new Request()); + + allow.Verify(r => r.IsMatch(It.IsAny()), Times.Once); + block.Verify(r => r.IsMatch(It.IsAny()), Times.Once); + + Assert.AreEqual((FilterResult) (-1), result); + } + + [TestMethod] + public void MustReturnDefaultWithoutRules() + { + sut.Default = FilterResult.Allow; + var result = sut.Process(new Request()); + Assert.AreEqual(FilterResult.Allow, result); + + sut.Default = FilterResult.Block; + result = sut.Process(new Request()); + Assert.AreEqual(FilterResult.Block, result); + } + + [TestMethod] + [ExpectedException(typeof(NotImplementedException))] + public void MustNotAllowUnsupportedResult() + { + var rule = new Mock(); + + rule.SetupGet(r => r.Result).Returns((FilterResult) (-1)); + sut.Load(rule.Object); + } + } +} diff --git a/SafeExamBrowser.Browser.UnitTests/Filters/RuleFactoryTests.cs b/SafeExamBrowser.Browser.UnitTests/Filters/RuleFactoryTests.cs new file mode 100644 index 0000000..f1ec7b0 --- /dev/null +++ b/SafeExamBrowser.Browser.UnitTests/Filters/RuleFactoryTests.cs @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2024 ETH Zürich, IT Services + * + * 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 Microsoft.VisualStudio.TestTools.UnitTesting; +using SafeExamBrowser.Browser.Filters; +using SafeExamBrowser.Browser.Filters.Rules; +using SafeExamBrowser.Settings.Browser.Filter; + +namespace SafeExamBrowser.Browser.UnitTests.Filters +{ + [TestClass] + public class RuleFactoryTests + { + private RuleFactory sut; + + [TestInitialize] + public void Initialize() + { + sut = new RuleFactory(); + } + + [TestMethod] + public void MustCreateCorrectRules() + { + Assert.IsInstanceOfType(sut.CreateRule(FilterRuleType.Regex), typeof(RegexRule)); + Assert.IsInstanceOfType(sut.CreateRule(FilterRuleType.Simplified), typeof(SimplifiedRule)); + } + + [TestMethod] + [ExpectedException(typeof(NotImplementedException))] + public void MustNotAllowUnsupportedFilterType() + { + sut.CreateRule((FilterRuleType) (-1)); + } + } +} diff --git a/SafeExamBrowser.Browser.UnitTests/Filters/Rules/RegexRuleTests.cs b/SafeExamBrowser.Browser.UnitTests/Filters/Rules/RegexRuleTests.cs new file mode 100644 index 0000000..6ba74bd --- /dev/null +++ b/SafeExamBrowser.Browser.UnitTests/Filters/Rules/RegexRuleTests.cs @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2024 ETH Zürich, IT Services + * + * 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.Text.RegularExpressions; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using SafeExamBrowser.Browser.Contracts.Filters; +using SafeExamBrowser.Browser.Filters.Rules; +using SafeExamBrowser.Settings.Browser.Filter; + +namespace SafeExamBrowser.Browser.UnitTests.Filters.Rules +{ + [TestClass] + public class RegexRuleTests + { + private RegexRule sut; + + [TestInitialize] + public void Initialize() + { + sut = new RegexRule(); + } + + [TestMethod] + public void MustIgnoreCase() + { + sut.Initialize(new FilterRuleSettings { Expression = Regex.Escape("http://www.test.org/path/file.txt?param=123") }); + + Assert.IsTrue(sut.IsMatch(new Request { Url = "hTtP://wWw.TeSt.OrG/pAtH/fIlE.tXt?PaRaM=123" })); + Assert.IsTrue(sut.IsMatch(new Request { Url = "HtTp://WwW.tEst.oRg/PaTh/FiLe.TxT?pArAm=123" })); + + sut.Initialize(new FilterRuleSettings { Expression = Regex.Escape("HTTP://WWW.TEST.ORG/PATH/FILE.TXT?PARAM=123") }); + + Assert.IsTrue(sut.IsMatch(new Request { Url = "hTtP://wWw.TeSt.OrG/pAtH/fIlE.tXt?PaRaM=123" })); + Assert.IsTrue(sut.IsMatch(new Request { Url = "HtTp://WwW.tEst.oRg/PaTh/FiLe.TxT?pArAm=123" })); + } + + [TestMethod] + public void MustInitializeResult() + { + foreach (var result in Enum.GetValues(typeof(FilterResult))) + { + sut.Initialize(new FilterRuleSettings { Expression = "", Result = (FilterResult) result }); + Assert.AreEqual(result, sut.Result); + } + } + + [TestMethod] + [ExpectedException(typeof(ArgumentNullException))] + public void MustNotAllowUndefinedExpression() + { + sut.Initialize(new FilterRuleSettings()); + } + + [TestMethod] + [ExpectedException(typeof(ArgumentException))] + public void MustValidateExpression() + { + sut.Initialize(new FilterRuleSettings { Expression = "ç+\"}%&*/(+)=?{=*+¦]@#°§]`?´^¨'°[¬|¢" }); + } + } +} diff --git a/SafeExamBrowser.Browser.UnitTests/Filters/Rules/SimplifiedRuleTests.cs b/SafeExamBrowser.Browser.UnitTests/Filters/Rules/SimplifiedRuleTests.cs new file mode 100644 index 0000000..6ee35eb --- /dev/null +++ b/SafeExamBrowser.Browser.UnitTests/Filters/Rules/SimplifiedRuleTests.cs @@ -0,0 +1,962 @@ +/* + * Copyright (c) 2024 ETH Zürich, IT Services + * + * 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.Collections.Generic; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using SafeExamBrowser.Browser.Contracts.Filters; +using SafeExamBrowser.Browser.Filters.Rules; +using SafeExamBrowser.Settings.Browser.Filter; + +namespace SafeExamBrowser.Browser.UnitTests.Filters.Rules +{ + [TestClass] + public class SimplifiedRuleTests + { + private SimplifiedRule sut; + + [TestInitialize] + public void Initialize() + { + sut = new SimplifiedRule(); + } + + [TestMethod] + public void MustIgnoreCase() + { + sut.Initialize(new FilterRuleSettings { Expression = "http://www.test.org/path/file.txt?param=123" }); + + Assert.IsTrue(sut.IsMatch(new Request { Url = "hTtP://wWw.TeSt.OrG/pAtH/fIlE.tXt?PaRaM=123" })); + Assert.IsTrue(sut.IsMatch(new Request { Url = "HtTp://WwW.tEst.oRg/PaTh/FiLe.TxT?pArAm=123" })); + + sut.Initialize(new FilterRuleSettings { Expression = "HTTP://WWW.TEST.ORG/PATH/FILE.TXT?PARAM=123" }); + + Assert.IsTrue(sut.IsMatch(new Request { Url = "hTtP://wWw.TeSt.OrG/pAtH/fIlE.tXt?PaRaM=123" })); + Assert.IsTrue(sut.IsMatch(new Request { Url = "HtTp://WwW.tEst.oRg/PaTh/FiLe.TxT?pArAm=123" })); + } + + [TestMethod] + public void MustInitializeResult() + { + foreach (var result in Enum.GetValues(typeof(FilterResult))) + { + sut.Initialize(new FilterRuleSettings { Expression = "*", Result = (FilterResult) result }); + Assert.AreEqual(result, sut.Result); + } + } + + [TestMethod] + [ExpectedException(typeof(ArgumentNullException))] + public void MustNotAllowUndefinedExpression() + { + sut.Initialize(new FilterRuleSettings()); + } + + [TestMethod] + public void MustValidateExpression() + { + var invalid = new[] + { + ".", "+", "\"", "ç", "%", "&", "/", "(", ")", "=", "?", "^", "!", "[", "]", "{", "}", "¦", "@", "#", "°", "§", "¬", "|", "¢", "´", "'", "`", "~", "<", ">", "\\" + }; + + sut.Initialize(new FilterRuleSettings { Expression = "*" }); + sut.Initialize(new FilterRuleSettings { Expression = "a" }); + sut.Initialize(new FilterRuleSettings { Expression = "A" }); + sut.Initialize(new FilterRuleSettings { Expression = "0" }); + sut.Initialize(new FilterRuleSettings { Expression = "abcdeFGHIJK-12345" }); + + foreach (var expression in invalid) + { + Assert.ThrowsException(() => sut.Initialize(new FilterRuleSettings { Expression = expression })); + } + } + + [TestMethod] + public void TestAlphanumericExpression() + { + var expression = "hostname123"; + var positive = new[] + { + $"scheme://{expression}" + }; + var negative = new[] + { + $"scheme://hostname", + $"scheme://hostname1", + $"scheme://hostname12", + $"scheme://hostname1234", + $"scheme://{expression}.org", + $"scheme://www.{expression}.org", + $"scheme://subdomain.{expression}.com", + $"scheme://www.realhost.{expression}", + $"scheme://subdomain-1.subdomain-2.{expression}.org", + $"scheme://user:password@www.{expression}.org/path/file.txt?param=123#fragment", + $"scheme://{expression}4", + $"scheme://hostname.org", + $"scheme://hostname12.org", + $"scheme://{expression}4.org", + $"scheme://{expression}.realhost.org", + $"scheme://subdomain.{expression}.realhost.org", + $"{expression}://www.host.org", + $"scheme://www.host.org/{expression}/path", + $"scheme://www.host.org/path?param={expression}", + $"scheme://{expression}:password@www.host.org", + $"scheme://user:{expression}@www.host.org", + $"scheme://user:password@www.host.org/path?param=123#{expression}" + }; + + Test(expression, positive, negative, false); + } + + [TestMethod] + public void TestAlphanumericExpressionWithWildcard() + { + var expression = "hostname*"; + var positive = new[] + { + "scheme://hostname.org", + "scheme://hostnameabc.org", + "scheme://hostname-12.org", + "scheme://hostname-abc-def-123-456.org", + "scheme://www.hostname-abc.org", + "scheme://www.realhost.hostname", + "scheme://subdomain.hostname-xyz.com", + "scheme://hostname.realhost.org", + "scheme://subdomain.hostname.realhost.org", + "scheme://subdomain-1.subdomain-2.hostname-abc-123.org", + "scheme://user:password@www.hostname-abc.org/path/file.txt?param=123#fragment" + }; + var negative = new[] + { + "scheme://hostnam.org", + "hostname://www.host.org", + "scheme://www.host.org/hostname/path", + "scheme://www.host.org/path?param=hostname", + "scheme://hostname:password@www.host.org", + "scheme://user:hostname@www.host.org", + "scheme://user:password@www.host.org/path?param=123#hostname" + }; + + Test(expression, positive, negative, false); + } + + [TestMethod] + public void TestHostWithDomain() + { + var expression = "123-hostname.org"; + var positive = new[] + { + $"scheme://{expression}", + $"scheme://www.{expression}", + $"scheme://subdomain.{expression}", + $"scheme://subdomain-1.subdomain-2.{expression}", + $"scheme://user:password@www.{expression}/path/file.txt?param=123#fragment" + }; + var negative = new[] + { + $"scheme://123.org", + $"scheme://123-host.org", + $"scheme://{expression}.com", + $"scheme://{expression}s.org", + $"scheme://{expression}.realhost.org", + $"scheme://subdomain.{expression}.realhost.org", + $"scheme{expression}://www.host.org", + $"scheme://www.host.org/{expression}/path", + $"scheme://www.host.org/path?param={expression}", + $"scheme://{expression}:password@www.host.org", + $"scheme://user:{expression}@www.host.org", + $"scheme://user:password@www.host.org/path?param=123#{expression}" + }; + + Test(expression, positive, negative); + } + + [TestMethod] + public void TestHostWithWildcard() + { + var expression = "test.*.org"; + var positive = new[] + { + "scheme://test.host.org", + "scheme://test.host.domain.org", + "scheme://subdomain.test.host.org", + "scheme://user:password@test.domain.org/path/file.txt?param=123#fragment" + }; + var negative = new[] + { + "scheme://test.org", + "scheme://host.com/test.host.org", + "scheme://www.host.org/test.host.org/path", + "scheme://www.host.org/path?param=test.host.org", + "scheme://test.host.org:password@www.host.org", + "scheme://user:test.host.org@www.host.org", + "scheme://user:password@www.host.org/path?param=123#test.host.org" + }; + + Test(expression, positive, negative); + } + + [TestMethod] + public void TestHostWithWildcardAsSuffix() + { + var expression = "test.host.*"; + var positive = new[] + { + "scheme://test.host.org", + "scheme://test.host.domain.org", + "scheme://subdomain.test.host.org", + "scheme://user:password@test.host.org/path/file.txt?param=123#fragment" + }; + var negative = new[] + { + "scheme://host.com", + "scheme://test.host", + "scheme://host.com/test.host.txt" + }; + + Test(expression, positive, negative); + } + + [TestMethod] + public void TestHostWithWildcardAsPrefix() + { + var expression = "*.org"; + var positive = new[] + { + "scheme://domain.org", + "scheme://test.host.org", + "scheme://test.host.domain.org", + "scheme://user:password@www.host.org/path/file.txt?param=123#fragment" + }; + var negative = new[] + { + "scheme://org", + "scheme://host.com", + "scheme://test.net", + "scheme://test.ch", + "scheme://host.com/test.org" + }; + + Test(expression, positive, negative); + } + + [TestMethod] + public void TestHostWithExactSubdomain() + { + var expression = ".www.host.org"; + var positive = new[] + { + "scheme://www.host.org", + "scheme://user:password@www.host.org/path/file.txt?param=123#fragment" + }; + var negative = new[] + { + "scheme://host.org", + "scheme://test.www.host.org", + "scheme://www.host.org.com" + }; + + Test(expression, positive, negative); + } + + [TestMethod] + public void TestHostWithTrailingSlash() + { + var expression = "host.org/"; + var positive = new[] + { + "scheme://host.org", + "scheme://host.org/", + "scheme://host.org/url", + "scheme://host.org/url/", + "scheme://host.org/url/path", + "scheme://host.org/url/path/", + "scheme://user:password@www.host.org/url/path?param=123#fragment", + "scheme://user:password@www.host.org/url/path/?param=123#fragment" + }; + + Test(expression, positive, Array.Empty()); + } + + [TestMethod] + public void TestHostWithoutTrailingSlash() + { + var expression = "host.org"; + var positive = new[] + { + "scheme://host.org", + "scheme://host.org/", + "scheme://host.org/url", + "scheme://host.org/url/", + "scheme://host.org/url/path", + "scheme://host.org/url/path/", + "scheme://user:password@www.host.org/url/path?param=123#fragment", + "scheme://user:password@www.host.org/url/path/?param=123#fragment" + }; + + Test(expression, positive, Array.Empty()); + } + + [TestMethod] + public void TestPortNumber() + { + var expression = "host.org:2020"; + var positive = new[] + { + "scheme://host.org:2020", + "scheme://www.host.org:2020", + "scheme://user:password@www.host.org:2020/path/file.txt?param=123#fragment" + }; + var negative = new[] + { + "scheme://host.org", + "scheme://www.host.org", + "scheme://www.host.org:2", + "scheme://www.host.org:20", + "scheme://www.host.org:202", + "scheme://www.host.org:20202" + }; + + Test(expression, positive, negative); + } + + [TestMethod] + public void TestPortWildcard() + { + var expression = "host.org:*"; + var positive = new[] + { + "scheme://host.org", + "scheme://host.org:0", + "scheme://host.org:1", + "scheme://host.org:2020", + "scheme://host.org:65535", + "scheme://www.host.org", + "scheme://www.host.org:2", + "scheme://www.host.org:20", + "scheme://www.host.org:202", + "scheme://www.host.org:2020", + "scheme://www.host.org:20202", + "scheme://user:password@www.host.org:2020/path/file.txt?param=123#fragment" + }; + + Test(expression, positive, Array.Empty()); + } + + [TestMethod] + public void TestPortNumberWithHostWildcard() + { + var expression = "*:2020"; + var positive = new[] + { + "scheme://host.org:2020", + "scheme://domain.com:2020", + "scheme://user:password@www.server.net:2020/path/file.txt?param=123#fragment" + }; + var negative = new List + { + "scheme://host.org" + }; + + for (var port = 0; port < 65536; port++) + { + if (port != 2020) + { + negative.Add($"{negative[0]}:{port}"); + } + } + + Test(expression, positive, negative.ToArray()); + } + + [TestMethod] + public void TestPath() + { + var expression = "host.org/url/path"; + var positive = new[] + { + "scheme://host.org/url/path", + "scheme://user:password@www.host.org/url/path?param=123#fragment" + }; + var negative = new[] + { + "scheme://host.org", + "scheme://host.org//", + "scheme://host.org///", + "scheme://host.org/url", + "scheme://host.org/path", + "scheme://host.org/url/path.txt", + "scheme://host.org/another/url/path" + }; + + Test(expression, positive, negative); + } + + [TestMethod] + public void TestPathWithFile() + { + var expression = "host.org/url/path/to/file.txt"; + var positive = new[] + { + "scheme://host.org/url/path/to/file.txt", + "scheme://subdomain.host.org/url/path/to/file.txt", + "scheme://user:password@www.host.org/url/path/to/file.txt?param=123#fragment" + }; + var negative = new[] + { + "scheme://host.org", + "scheme://host.org/url", + "scheme://host.org/path", + "scheme://host.org/file.txt", + "scheme://host.org/url/path.txt", + "scheme://host.org/url/path/to.txt", + "scheme://host.org/url/path/to/file", + "scheme://host.org/url/path/to/file.", + "scheme://host.org/url/path/to/file.t", + "scheme://host.org/url/path/to/file.tx", + "scheme://host.org/url/path/to/file.txt/segment", + "scheme://host.org/url/path/to/file.txtt", + "scheme://host.org/another/url/path/to/file.txt" + }; + + Test(expression, positive, negative); + } + + [TestMethod] + public void TestPathWithWildcard() + { + var expression = "host.org/*/path"; + var positive = new[] + { + "scheme://host.org//path", + "scheme://host.org/url/path", + "scheme://host.org/another/url/path", + "scheme://user:password@www.host.org/yet/another/url/path?param=123#fragment" + }; + var negative = new[] + { + "scheme://host.org", + "scheme://host.org/url", + "scheme://host.org/path", + "scheme://host.org/url/path.txt", + "scheme://host.org/url/path/2" + }; + + Test(expression, positive, negative); + } + + [TestMethod] + public void TestPathWithHostWildcard() + { + var expression = "*/url/path"; + var positive = new[] + { + "scheme://local/url/path", + "scheme://host.org/url/path", + "scheme://www.host.org/url/path", + "scheme://another.server.org/url/path", + "scheme://user:password@www.host.org/url/path?param=123#fragment" + }; + var negative = new[] + { + "scheme://host.org", + "scheme://host.org/url", + "scheme://host.org/path", + "scheme://host.org/url/path.txt", + "scheme://host.org/url/path/2" + }; + + Test(expression, positive, negative); + } + + [TestMethod] + public void TestPathWithTrailingSlash() + { + var expression = "host.org/url/path/"; + var positive = new[] + { + "scheme://host.org/url/path", + "scheme://host.org/url/path/", + "scheme://user:password@www.host.org/url/path?param=123#fragment", + "scheme://user:password@www.host.org/url/path/?param=123#fragment" + }; + + Test(expression, positive, Array.Empty()); + } + + [TestMethod] + public void TestPathWithoutTrailingSlash() + { + var expression = "host.org/url/path"; + var positive = new[] + { + "scheme://host.org/url/path", + "scheme://host.org/url/path/", + "scheme://user:password@www.host.org/url/path?param=123#fragment", + "scheme://user:password@www.host.org/url/path/?param=123#fragment" + }; + + Test(expression, positive, Array.Empty()); + } + + [TestMethod] + public void TestScheme() + { + var expression = "scheme://host.org"; + var positive = new[] + { + "scheme://host.org", + "scheme://www.host.org", + "scheme://user:password@www.host.org/url/path?param=123#fragment" + }; + var negative = new[] + { + "//host.org", + "https://host.org", + "ftp://host.org", + "ftps://host.org", + "schemes://host.org" + }; + + Test(expression, positive, negative); + } + + [TestMethod] + public void TestSchemeWithWildcard() + { + var expression = "*tp://host.org"; + var positive = new[] + { + "tp://host.org", + "ftp://www.host.org", + "http://user:password@www.host.org/url/path?param=123#fragment" + }; + var negative = new[] + { + "//host.org", + "p://host.org", + "https://host.org", + "ftps://host.org" + }; + + Test(expression, positive, negative); + } + + [TestMethod] + public void TestSchemeWithHostWildcard() + { + var expression = "scheme://*"; + var positive = new[] + { + "scheme://host", + "scheme://www.server.org", + "scheme://subdomain.domain.org", + "scheme://user:password@www.host.org/url/path?param=123#fragment" + }; + var negative = new[] + { + "//host.org", + "http://host.org", + "https://host.org", + "ftp://host.org", + "ftps://host.org", + }; + + Test(expression, positive, negative); + } + + [TestMethod] + public void TestUserInfoWithName() + { + var expression = "user@host.org"; + var positive = new[] + { + "scheme://user@host.org", + "scheme://user@www.host.org", + "scheme://user:password@host.org", + "scheme://user:password-123@host.org", + "scheme://user:password@www.host.org/url/path?param=123#fragment" + }; + var negative = new[] + { + "scheme://u@host.org", + "scheme://us@host.org", + "scheme://use@host.org", + "scheme://usera@host.org", + "scheme://user@server.net", + "scheme://usertwo@www.host.org" + }; + + Test(expression, positive, negative); + } + + [TestMethod] + public void TestUserInfoWithNameWildcard() + { + var expression = "user*@host.org"; + var positive = new[] + { + "scheme://user@host.org", + "scheme://userabc@host.org", + "scheme://user:abc@host.org", + "scheme://user-123@www.host.org", + "scheme://user-123:password@host.org", + "scheme://user-123:password-123@host.org", + "scheme://user-abc-123:password@www.host.org/url/path?param=123#fragment" + }; + var negative = new[] + { + "scheme://u@host.org", + "scheme://us@host.org", + "scheme://use@host.org", + "scheme://user@server.net", + "scheme://usertwo@server.org" + }; + + Test(expression, positive, negative); + } + + [TestMethod] + public void TestUserInfoWithPassword() + { + var expression = "user:password@host.org"; + var positive = new[] + { + "scheme://user:password@host.org", + "scheme://user:password@www.host.org", + "scheme://user:password@www.host.org/url/path?param=123#fragment" + }; + var negative = new[] + { + "scheme://u@host.org", + "scheme://us@host.org", + "scheme://use@host.org", + "scheme://user@server.net", + "scheme://usertwo@server.org", + "scheme://user@host.org", + "scheme://userabc@host.org", + "scheme://user:abc@host.org", + "scheme://user-123@www.host.org", + "scheme://user-123:password@host.org", + "scheme://user-123:password@www.host.org/url/path?param=123#fragment", + "scheme://user:password-123@host.org", + "scheme://user:password-123@www.host.org/url/path?param=123#fragment" + }; + + Test(expression, positive, negative); + } + + [TestMethod] + public void TestUserInfoWithWildcard() + { + var expression = "*@host.org"; + var positive = new[] + { + "scheme://host.org", + "scheme://user@host.org", + "scheme://user:password@host.org", + "scheme://www.host.org/url/path?param=123#fragment", + "scheme://user@www.host.org/url/path?param=123#fragment", + "scheme://user:password@www.host.org/url/path?param=123#fragment" + }; + var negative = new[] + { + "scheme://server.org", + "scheme://user@server.org", + "scheme://www.server.org/url/path?param=123#fragment", + "scheme://user:password@www.server.org/url/path?param=123#fragment" + }; + + Test(expression, positive, negative); + } + + [TestMethod] + public void TestUserInfoWithHostWildcard() + { + var expression = "user:password@*"; + var positive = new[] + { + "scheme://user:password@host.org", + "scheme://user:password@server.net", + "scheme://user:password@www.host.org/url/path?param=123#fragment" + }; + var negative = new[] + { + "scheme://host.org", + "scheme://server.org", + "scheme://user@host.org", + "scheme://user@server.org", + "scheme://password@host.org", + "scheme://www.host.org/url/path?param=123#fragment", + "scheme://www.server.org/url/path?param=123#fragment", + "scheme://user@www.host.org/url/path?param=123#fragment", + "scheme://user@www.server.org/url/path?param=123#fragment", + "scheme://password@www.server.org/url/path?param=123#fragment" + }; + + Test(expression, positive, negative); + } + + [TestMethod] + public void TestQuery() + { + var expression = "host.org?param=123"; + var positive = new[] + { + "scheme://host.org?param=123", + "scheme://www.host.org/?param=123", + "scheme://www.host.org/path/?param=123", + "scheme://www.host.org/some/other/random/path?param=123", + "scheme://user:password@www.host.org/url/path?param=123#fragment" + }; + var negative = new[] + { + "scheme://host.org?", + "scheme://host.org?=", + "scheme://host.org?=123", + "scheme://host.org?param=", + "scheme://host.org?param=1", + "scheme://host.org?param=12", + "scheme://host.org?param=1234" + }; + + Test(expression, positive, negative); + } + + [TestMethod] + public void TestQueryWithWildcardAsPrefix() + { + var expression = "host.org?*param=123"; + var positive = new[] + { + "scheme://host.org?param=123", + "scheme://www.host.org?param=123", + "scheme://www.host.org/path/?param=123", + "scheme://www.host.org/some/other/random/path?param=123", + "scheme://user:password@www.host.org/url/path?param=123#fragment", + "scheme://host.org?other_param=456¶m=123", + "scheme://host.org?param=123&another_param=123", + "scheme://www.host.org?other_param=456¶m=123", + "scheme://www.host.org/path/?other_param=456¶m=123", + "scheme://www.host.org/some/other/random/path?other_param=456¶m=123", + "scheme://user:password@www.host.org/url/path?other_param=456¶m=123#fragment", + "scheme://host.org?some_param=123469yvuiopwo&another_param=some%20whitespaces%26special%20characters%2B%22%2A%25%C3%A7%2F%28¶m=123" + }; + var negative = new[] + { + "scheme://host.org?", + "scheme://host.org?=", + "scheme://host.org?=123", + "scheme://host.org?aram=123", + "scheme://host.org?param=", + "scheme://host.org?param=1", + "scheme://host.org?param=12", + "scheme://host.org?param=1234", + "scheme://host.org?param=123&another_param=456" + }; + + Test(expression, positive, negative); + } + + [TestMethod] + public void TestQueryWithWildcardAsSuffix() + { + var expression = "host.org?param=123*"; + var positive = new[] + { + "scheme://host.org?param=123", + "scheme://host.org?param=1234", + "scheme://www.host.org?param=123", + "scheme://www.host.org/path/?param=123", + "scheme://host.org?param=123&another_param=456", + "scheme://www.host.org/some/other/random/path?param=123", + "scheme://user:password@www.host.org/url/path?param=123#fragment", + "scheme://host.org?param=123&other_param=456", + "scheme://www.host.org/path/?param=123&other_param=456", + "scheme://www.host.org/some/other/random/path?param=123&other_param=456", + "scheme://user:password@www.host.org/url/path?param=123&other_param=456#fragment", + "scheme://host.org?param=123&some_param=123469yvuiopwo&another_param=some%20whitespaces%26special%20characters%2B%22%2A%25%C3%A7%2F%28" + }; + var negative = new[] + { + "scheme://host.org?", + "scheme://host.org?=", + "scheme://host.org?=123", + "scheme://host.org?aram=123", + "scheme://host.org?param=", + "scheme://host.org?param=1", + "scheme://host.org?param=12", + "scheme://host.org?aparam=123", + "scheme://www.host.org?param=456¶m=123", + "scheme://host.org?some_param=123469yvuiopwo&another_param=some%20whitespaces%26special%20characters%2B%22%2A%25%C3%A7%2F%28¶m=123" + }; + + Test(expression, positive, negative); + } + + [TestMethod] + public void TestQueryNotAllowed() + { + var expression = "host.org?."; + var positive = new[] + { + "scheme://host.org", + "scheme://host.org?", + "scheme://user:password@www.host.org/url/path#fragment", + "scheme://user:password@www.host.org/url/path?#fragment" + }; + var negative = new[] + { + "scheme://host.org?a", + "scheme://host.org?%20", + "scheme://host.org?=", + }; + + Test(expression, positive, negative); + } + + [TestMethod] + public void TestQueryWithHostWildcard() + { + var expression = "*?param=123"; + var positive = new[] + { + "scheme://host.org?param=123", + "scheme://server.net?param=123", + "scheme://user:password@www.host.org/url/path?param=123#fragment", + "scheme://user:password@www.server.net/url/path?param=123#fragment" + }; + var negative = new[] + { + "scheme://host.org?param=1234", + "scheme://host.org?param=12", + "scheme://host.org?", + "scheme://host.org?param", + "scheme://host.org?123", + "scheme://host.org?=" + }; + + Test(expression, positive, negative); + } + + [TestMethod] + public void TestFragment() + { + var expression = "host.org#fragment"; + var positive = new[] + { + "scheme://host.org#fragment", + "scheme://www.host.org#fragment", + "scheme://user:password@www.host.org/url/path/file.txt?param=123#fragment" + }; + var negative = new[] + { + "scheme://host.org", + "scheme://host.org#", + "scheme://host.org#fragmen", + "scheme://host.org#fragment123", + "scheme://host.org#otherfragment" + }; + + Test(expression, positive, negative); + } + + [TestMethod] + public void TestFragmentWithWildcardAsPrefix() + { + var expression = "host.org#*fragment"; + var positive = new[] + { + "scheme://host.org#fragment", + "scheme://host.org#somefragment", + "scheme://www.host.org#another_fragment", + "scheme://user:password@www.host.org/url/path/file.txt?param=123#fragment" + }; + var negative = new[] + { + "scheme://host.org", + "scheme://host.org#", + "scheme://host.org#fragmen", + "scheme://host.org#fragment123" + }; + + Test(expression, positive, negative); + } + + [TestMethod] + public void TestFragmentWithWildcardAsSuffix() + { + var expression = "host.org#fragment*"; + var positive = new[] + { + "scheme://host.org#fragment", + "scheme://host.org#fragment-123", + "scheme://user:password@www.host.org/url/path/file.txt?param=123#fragment_abc" + }; + var negative = new[] + { + "scheme://host.org", + "scheme://host.org#", + "scheme://host.org#fragmen", + "scheme://www.host.org#another_fragment" + }; + + Test(expression, positive, negative); + } + + [TestMethod] + public void TestFragmentWithHostWildcard() + { + var expression = "*#fragment"; + var positive = new[] + { + "scheme://host.org#fragment", + "scheme://server.net#fragment", + "scheme://user:password@www.host.org/url/path?param=123#fragment", + "scheme://user:password@www.server.net/url/path?param=123#fragment" + }; + var negative = new[] + { + "scheme://host.org", + "scheme://host.org#", + "scheme://host.org#fragmen", + "scheme://host.org#fragment123" + }; + + Test(expression, positive, negative); + } + + private void Test(string expression, string[] positive, string[] negative, bool testLegacy = true) + { + var legacy = new LegacyFilter(expression); + + sut.Initialize(new FilterRuleSettings { Expression = expression }); + + foreach (var url in positive) + { + Assert.IsTrue(sut.IsMatch(new Request { Url = url }), url); + + if (testLegacy) + { + Assert.IsTrue(legacy.IsMatch(new Uri(url)), url); + } + } + + foreach (var url in negative) + { + Assert.IsFalse(sut.IsMatch(new Request { Url = url }), url); + + if (testLegacy) + { + Assert.IsFalse(legacy.IsMatch(new Uri(url)), url); + } + } + } + } +} diff --git a/SafeExamBrowser.Browser.UnitTests/Handlers/ContextMenuHandlerTests.cs b/SafeExamBrowser.Browser.UnitTests/Handlers/ContextMenuHandlerTests.cs new file mode 100644 index 0000000..153677a --- /dev/null +++ b/SafeExamBrowser.Browser.UnitTests/Handlers/ContextMenuHandlerTests.cs @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2024 ETH Zürich, IT Services + * + * 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 CefSharp; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Moq; +using SafeExamBrowser.Browser.Handlers; + +namespace SafeExamBrowser.Browser.UnitTests.Handlers +{ + [TestClass] + public class ContextMenuHandlerTests + { + private ContextMenuHandler sut; + + [TestInitialize] + public void Initialize() + { + sut = new ContextMenuHandler(); + } + + [TestMethod] + public void MustClearContextMenu() + { + var menu = new Mock(); + + sut.OnBeforeContextMenu(default(IWebBrowser), default(IBrowser), default(IFrame), default(IContextMenuParams), menu.Object); + menu.Verify(m => m.Clear(), Times.Once); + } + + [TestMethod] + public void MustBlockContextMenu() + { + var command = sut.OnContextMenuCommand(default(IWebBrowser), default(IBrowser), default(IFrame), default(IContextMenuParams), default(CefMenuCommand), default(CefEventFlags)); + var run = sut.RunContextMenu(default(IWebBrowser), default(IBrowser), default(IFrame), default(IContextMenuParams), default(IMenuModel), default(IRunContextMenuCallback)); + + Assert.IsFalse(command); + Assert.IsFalse(run); + } + } +} diff --git a/SafeExamBrowser.Browser.UnitTests/Handlers/DialogHandlerTests.cs b/SafeExamBrowser.Browser.UnitTests/Handlers/DialogHandlerTests.cs new file mode 100644 index 0000000..887bc4f --- /dev/null +++ b/SafeExamBrowser.Browser.UnitTests/Handlers/DialogHandlerTests.cs @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2024 ETH Zürich, IT Services + * + * 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.Collections.Generic; +using System.Threading; +using CefSharp; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Moq; +using SafeExamBrowser.Browser.Events; +using SafeExamBrowser.Browser.Handlers; +using SafeExamBrowser.UserInterface.Contracts.FileSystemDialog; + +namespace SafeExamBrowser.Browser.UnitTests.Handlers +{ + [TestClass] + public class DialogHandlerTests + { + private DialogHandler sut; + + [TestInitialize] + public void Initialize() + { + sut = new DialogHandler(); + } + + [TestMethod] + public void MustCorrectlyCancelDialog() + { + RequestDialog(default, false); + } + + [TestMethod] + public void MustCorrectlyRequestOpenFileDialog() + { + var args = RequestDialog(CefFileDialogMode.Open); + + Assert.AreEqual(FileSystemElement.File, args.Element); + Assert.AreEqual(FileSystemOperation.Open, args.Operation); + } + + [TestMethod] + public void MustCorrectlyRequestOpenFolderDialog() + { + var args = RequestDialog(CefFileDialogMode.OpenFolder); + + Assert.AreEqual(FileSystemElement.Folder, args.Element); + Assert.AreEqual(FileSystemOperation.Open, args.Operation); + } + + [TestMethod] + public void MustCorrectlyRequestSaveFileDialog() + { + var args = RequestDialog(CefFileDialogMode.Save); + + Assert.AreEqual(FileSystemElement.File, args.Element); + Assert.AreEqual(FileSystemOperation.Save, args.Operation); + } + + private DialogRequestedEventArgs RequestDialog(CefFileDialogMode mode, bool confirm = true) + { + var args = default(DialogRequestedEventArgs); + var callback = new Mock(); + var title = "Some random dialog title"; + var initialPath = @"C:\Some\Random\Path"; + var sync = new AutoResetEvent(false); + var threadId = default(int); + + callback.Setup(c => c.Cancel()).Callback(() => sync.Set()); + callback.Setup(c => c.Continue(It.IsAny>())).Callback(() => sync.Set()); + sut.DialogRequested += (a) => + { + args = a; + args.Success = confirm; + args.FullPath = @"D:\Some\Other\File\Path.txt"; + threadId = Thread.CurrentThread.ManagedThreadId; + }; + + var status = sut.OnFileDialog(default, default, mode, title, initialPath, default, callback.Object); + + sync.WaitOne(); + + if (confirm) + { + callback.Verify(c => c.Continue(It.IsAny>()), Times.Once); + callback.Verify(c => c.Cancel(), Times.Never); + } + else + { + callback.Verify(c => c.Continue(It.IsAny>()), Times.Never); + callback.Verify(c => c.Cancel(), Times.Once); + } + + Assert.IsTrue(status); + Assert.AreEqual(initialPath, args.InitialPath); + Assert.AreEqual(title, args.Title); + Assert.AreNotEqual(threadId, Thread.CurrentThread.ManagedThreadId); + + return args; + } + } +} diff --git a/SafeExamBrowser.Browser.UnitTests/Handlers/DisplayHandlerTests.cs b/SafeExamBrowser.Browser.UnitTests/Handlers/DisplayHandlerTests.cs new file mode 100644 index 0000000..1ae483f --- /dev/null +++ b/SafeExamBrowser.Browser.UnitTests/Handlers/DisplayHandlerTests.cs @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2024 ETH Zürich, IT Services + * + * 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.Collections.Generic; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using SafeExamBrowser.Browser.Handlers; + +namespace SafeExamBrowser.Browser.UnitTests.Handlers +{ + [TestClass] + public class DisplayHandlerTests + { + private DisplayHandler sut; + + [TestInitialize] + public void Initialize() + { + sut = new DisplayHandler(); + } + + [TestMethod] + public void MustUseDefaultHandling() + { + var text = default(string); + + Assert.IsFalse(sut.OnAutoResize(default, default, default)); + Assert.IsFalse(sut.OnConsoleMessage(default, default)); + Assert.IsFalse(sut.OnCursorChange(default, default, default, default, default)); + Assert.IsFalse(sut.OnTooltipChanged(default, ref text)); + } + + [TestMethod] + public void MustHandleFaviconChange() + { + var newUrl = "www.someurl.org/favicon.ico"; + var url = default(string); + var called = false; + + sut.FaviconChanged += (u) => + { + called = true; + url = u; + }; + sut.OnFaviconUrlChange(default, default, new List()); + + Assert.AreEqual(default, url); + Assert.IsFalse(called); + + sut.OnFaviconUrlChange(default, default, new List { newUrl }); + + Assert.AreEqual(newUrl, url); + Assert.IsTrue(called); + } + + [TestMethod] + public void MustHandleProgressChange() + { + var expected = 0.123456; + var actual = default(double); + + sut.ProgressChanged += (p) => actual = p; + sut.OnLoadingProgressChange(default, default, expected); + + Assert.AreEqual(expected, actual); + } + } +} diff --git a/SafeExamBrowser.Browser.UnitTests/Handlers/DownloadHandlerTests.cs b/SafeExamBrowser.Browser.UnitTests/Handlers/DownloadHandlerTests.cs new file mode 100644 index 0000000..7fe625a --- /dev/null +++ b/SafeExamBrowser.Browser.UnitTests/Handlers/DownloadHandlerTests.cs @@ -0,0 +1,311 @@ +/* + * Copyright (c) 2024 ETH Zürich, IT Services + * + * 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.Threading; +using CefSharp; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Moq; +using SafeExamBrowser.Browser.Contracts.Events; +using SafeExamBrowser.Browser.Handlers; +using SafeExamBrowser.Configuration.Contracts; +using SafeExamBrowser.Logging.Contracts; +using SafeExamBrowser.Settings.Browser; +using SafeExamBrowser.UserInterface.Contracts.Browser.Data; +using BrowserSettings = SafeExamBrowser.Settings.Browser.BrowserSettings; + +namespace SafeExamBrowser.Browser.UnitTests.Handlers +{ + [TestClass] + public class DownloadHandlerTests + { + private AppConfig appConfig; + private Mock logger; + private BrowserSettings settings; + private WindowSettings windowSettings; + private DownloadHandler sut; + + [TestInitialize] + public void Initialize() + { + appConfig = new AppConfig(); + logger = new Mock(); + settings = new BrowserSettings(); + windowSettings = new WindowSettings(); + + sut = new DownloadHandler(appConfig, logger.Object, settings, windowSettings); + } + + [TestMethod] + public void MustCorrectlyHandleConfigurationByFileExtension() + { + var item = new DownloadItem + { + SuggestedFileName = "File.seb", + Url = "https://somehost.org/some-path" + }; + + RequestConfigurationDownload(item); + } + + [TestMethod] + public void MustCorrectlyHandleConfigurationByUrlExtension() + { + var item = new DownloadItem + { + SuggestedFileName = "Abc.xyz", + Url = "https://somehost.org/some-path-to/file.seb" + }; + + RequestConfigurationDownload(item); + } + + [TestMethod] + public void MustCorrectlyHandleConfigurationByMimeType() + { + appConfig.ConfigurationFileMimeType = "some/mime-type"; + + var item = new DownloadItem + { + MimeType = appConfig.ConfigurationFileMimeType, + SuggestedFileName = "Abc.xyz", + Url = "https://somehost.org/some-path" + }; + + RequestConfigurationDownload(item); + } + + [TestMethod] + public void MustCorrectlyHandleDeniedConfigurationFileDownload() + { + var args = default(DownloadEventArgs); + var callback = new Mock(); + var failed = false; + var fileName = default(string); + var item = new DownloadItem + { + SuggestedFileName = "File.seb", + Url = "https://somehost.org/some-path" + }; + var sync = new AutoResetEvent(false); + var threadId = default(int); + + settings.AllowDownloads = false; + settings.AllowConfigurationDownloads = true; + sut.ConfigurationDownloadRequested += (f, a) => + { + args = a; + args.AllowDownload = false; + fileName = f; + threadId = Thread.CurrentThread.ManagedThreadId; + sync.Set(); + }; + sut.DownloadUpdated += (state) => failed = true; + + sut.OnBeforeDownload(default(IWebBrowser), default(IBrowser), item, callback.Object); + sync.WaitOne(); + + callback.VerifyNoOtherCalls(); + + Assert.IsFalse(failed); + Assert.IsFalse(args.AllowDownload); + Assert.AreEqual(item.SuggestedFileName, fileName); + Assert.AreNotEqual(Thread.CurrentThread.ManagedThreadId, threadId); + } + + [TestMethod] + public void MustCorrectlyHandleFileDownload() + { + var callback = new Mock(); + var downloadPath = default(string); + var failed = false; + var item = new DownloadItem + { + MimeType = "application/something", + SuggestedFileName = "File.txt", + Url = "https://somehost.org/somefile.abc" + }; + var sync = new AutoResetEvent(false); + var threadId = default(int); + + callback.Setup(c => c.Continue(It.IsAny(), It.IsAny())).Callback((f, s) => + { + downloadPath = f; + threadId = Thread.CurrentThread.ManagedThreadId; + sync.Set(); + }); + settings.AllowDownloads = true; + settings.AllowConfigurationDownloads = false; + sut.ConfigurationDownloadRequested += (f, a) => failed = true; + sut.DownloadUpdated += (state) => failed = true; + + sut.OnBeforeDownload(default(IWebBrowser), default(IBrowser), item, callback.Object); + sync.WaitOne(); + + callback.Verify(c => c.Continue(It.Is(p => p.Equals(downloadPath)), false), Times.Once); + + Assert.IsFalse(failed); + Assert.AreNotEqual(Thread.CurrentThread.ManagedThreadId, threadId); + } + + [TestMethod] + public void MustCorrectlyHandleFileDownloadWithCustomDirectory() + { + var callback = new Mock(); + var failed = false; + var item = new DownloadItem + { + MimeType = "application/something", + SuggestedFileName = "File.txt", + Url = "https://somehost.org/somefile.abc" + }; + var sync = new AutoResetEvent(false); + var threadId = default(int); + + callback.Setup(c => c.Continue(It.IsAny(), It.IsAny())).Callback(() => + { + threadId = Thread.CurrentThread.ManagedThreadId; + sync.Set(); + }); + settings.AllowDownloads = true; + settings.AllowConfigurationDownloads = false; + settings.AllowCustomDownAndUploadLocation = true; + settings.DownAndUploadDirectory = @"%APPDATA%\Downloads"; + sut.ConfigurationDownloadRequested += (f, a) => failed = true; + sut.DownloadUpdated += (state) => failed = true; + + sut.OnBeforeDownload(default(IWebBrowser), default(IBrowser), item, callback.Object); + sync.WaitOne(); + + var downloadPath = Path.Combine(Environment.ExpandEnvironmentVariables(settings.DownAndUploadDirectory), item.SuggestedFileName); + + callback.Verify(c => c.Continue(It.Is(p => p.Equals(downloadPath)), true), Times.Once); + + Assert.IsFalse(failed); + Assert.AreNotEqual(Thread.CurrentThread.ManagedThreadId, threadId); + } + + [TestMethod] + public void MustDoNothingIfDownloadsNotAllowed() + { + var callback = new Mock(); + var fail = false; + var item = new DownloadItem + { + SuggestedFileName = "File.txt", + Url = "https://somehost.org/somefile.abc" + }; + + settings.AllowDownloads = false; + settings.AllowConfigurationDownloads = false; + sut.ConfigurationDownloadRequested += (file, args) => fail = true; + sut.DownloadUpdated += (state) => fail = true; + + sut.OnBeforeDownload(default(IWebBrowser), default(IBrowser), item, callback.Object); + + callback.VerifyNoOtherCalls(); + Assert.IsFalse(fail); + } + + [TestMethod] + public void MustUpdateDownloadProgress() + { + var callback = new Mock(); + var failed = false; + var item = new DownloadItem + { + MimeType = "application/something", + SuggestedFileName = "File.txt", + Url = "https://somehost.org/somefile.abc" + }; + var state = default(DownloadItemState); + var sync = new AutoResetEvent(false); + var threadId = default(int); + + callback.Setup(c => c.Continue(It.IsAny(), It.IsAny())).Callback(() => sync.Set()); + settings.AllowDownloads = true; + settings.AllowConfigurationDownloads = false; + sut.ConfigurationDownloadRequested += (f, a) => failed = true; + + sut.OnBeforeDownload(default(IWebBrowser), default(IBrowser), item, callback.Object); + sync.WaitOne(); + + Assert.IsFalse(failed); + + sut.DownloadUpdated += (s) => + { + state = s; + threadId = Thread.CurrentThread.ManagedThreadId; + sync.Set(); + }; + + item.PercentComplete = 10; + sut.OnDownloadUpdated(default(IWebBrowser), default(IBrowser), item, default(IDownloadItemCallback)); + sync.WaitOne(); + + Assert.IsFalse(state.IsCancelled); + Assert.IsFalse(state.IsComplete); + Assert.AreEqual(0.1, state.Completion); + Assert.AreNotEqual(Thread.CurrentThread.ManagedThreadId, threadId); + + item.PercentComplete = 20; + sut.OnDownloadUpdated(default(IWebBrowser), default(IBrowser), item, default(IDownloadItemCallback)); + sync.WaitOne(); + + Assert.IsFalse(state.IsCancelled); + Assert.IsFalse(state.IsComplete); + Assert.AreEqual(0.2, state.Completion); + Assert.AreNotEqual(Thread.CurrentThread.ManagedThreadId, threadId); + + item.PercentComplete = 50; + item.IsCancelled = true; + sut.OnDownloadUpdated(default(IWebBrowser), default(IBrowser), item, default(IDownloadItemCallback)); + sync.WaitOne(); + + Assert.IsFalse(failed); + Assert.IsTrue(state.IsCancelled); + Assert.IsFalse(state.IsComplete); + Assert.AreEqual(0.5, state.Completion); + Assert.AreNotEqual(Thread.CurrentThread.ManagedThreadId, threadId); + } + + private void RequestConfigurationDownload(DownloadItem item) + { + var args = default(DownloadEventArgs); + var callback = new Mock(); + var failed = false; + var fileName = default(string); + var sync = new AutoResetEvent(false); + var threadId = default(int); + + callback.Setup(c => c.Continue(It.IsAny(), It.IsAny())).Callback(() => sync.Set()); + settings.AllowDownloads = false; + settings.AllowConfigurationDownloads = true; + sut.ConfigurationDownloadRequested += (f, a) => + { + args = a; + args.AllowDownload = true; + args.DownloadPath = @"C:\Downloads\File.seb"; + fileName = f; + threadId = Thread.CurrentThread.ManagedThreadId; + }; + sut.DownloadUpdated += (state) => failed = true; + + sut.OnBeforeDownload(default(IWebBrowser), default(IBrowser), item, callback.Object); + sync.WaitOne(); + + callback.Verify(c => c.Continue(It.Is(p => p.Equals(args.DownloadPath)), false), Times.Once); + + Assert.IsFalse(failed); + Assert.IsTrue(args.AllowDownload); + Assert.AreEqual(item.SuggestedFileName, fileName); + Assert.AreNotEqual(Thread.CurrentThread.ManagedThreadId, threadId); + } + } +} diff --git a/SafeExamBrowser.Browser.UnitTests/Handlers/KeyboardHandlerTests.cs b/SafeExamBrowser.Browser.UnitTests/Handlers/KeyboardHandlerTests.cs new file mode 100644 index 0000000..355bc4b --- /dev/null +++ b/SafeExamBrowser.Browser.UnitTests/Handlers/KeyboardHandlerTests.cs @@ -0,0 +1,166 @@ +/* + * Copyright (c) 2024 ETH Zürich, IT Services + * + * 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.Windows.Forms; +using CefSharp; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using SafeExamBrowser.Browser.Handlers; + +namespace SafeExamBrowser.Browser.UnitTests.Handlers +{ + [TestClass] + public class KeyboardHandlerTests + { + private KeyboardHandler sut; + + [TestInitialize] + public void Initialize() + { + sut = new KeyboardHandler(); + } + + [TestMethod] + public void MustDetectFindCommand() + { + var findRequested = false; + + sut.FindRequested += () => findRequested = true; + + var handled = sut.OnKeyEvent(default(IWebBrowser), default(IBrowser), KeyType.KeyUp, (int) Keys.F, default(int), CefEventFlags.ControlDown, default(bool)); + + Assert.IsTrue(findRequested); + Assert.IsFalse(handled); + + findRequested = false; + handled = sut.OnKeyEvent(default(IWebBrowser), default(IBrowser), default(KeyType), default(int), default(int), CefEventFlags.ControlDown, default(bool)); + + Assert.IsFalse(findRequested); + Assert.IsFalse(handled); + } + + [TestMethod] + public void MustDetectHomeNavigationCommand() + { + var homeRequested = false; + + sut.HomeNavigationRequested += () => homeRequested = true; + + var handled = sut.OnKeyEvent(default(IWebBrowser), default(IBrowser), KeyType.KeyUp, (int) Keys.Home, default(int), default(CefEventFlags), default(bool)); + + Assert.IsTrue(homeRequested); + Assert.IsFalse(handled); + + homeRequested = false; + handled = sut.OnKeyEvent(default(IWebBrowser), default(IBrowser), default(KeyType), default(int), default(int), default(CefEventFlags), default(bool)); + + Assert.IsFalse(homeRequested); + Assert.IsFalse(handled); + } + + [TestMethod] + public void MustDetectReloadCommand() + { + var isShortcut = default(bool); + var reloadRequested = false; + + sut.ReloadRequested += () => reloadRequested = true; + + var handled = sut.OnPreKeyEvent(default(IWebBrowser), default(IBrowser), KeyType.KeyUp, (int) Keys.F5, default(int), default(CefEventFlags), default(bool), ref isShortcut); + + Assert.IsTrue(reloadRequested); + Assert.IsTrue(handled); + + reloadRequested = false; + handled = sut.OnPreKeyEvent(default(IWebBrowser), default(IBrowser), default(KeyType), default(int), default(int), default(CefEventFlags), default(bool), ref isShortcut); + + Assert.IsFalse(reloadRequested); + Assert.IsFalse(handled); + } + + [TestMethod] + public void MustDetectZoomInCommand() + { + var zoomIn = false; + var zoomOut = false; + var zoomReset = false; + + sut.ZoomInRequested += () => zoomIn = true; + sut.ZoomOutRequested += () => zoomOut = true; + sut.ZoomResetRequested += () => zoomReset = true; + + var handled = sut.OnKeyEvent(default(IWebBrowser), default(IBrowser), KeyType.KeyUp, (int) Keys.Add, default(int), CefEventFlags.ControlDown, false); + + Assert.IsFalse(handled); + Assert.IsTrue(zoomIn); + Assert.IsFalse(zoomOut); + Assert.IsFalse(zoomReset); + + zoomIn = false; + handled = sut.OnKeyEvent(default(IWebBrowser), default(IBrowser), KeyType.KeyUp, (int) Keys.D1, default(int), CefEventFlags.ControlDown | CefEventFlags.ShiftDown, false); + + Assert.IsFalse(handled); + Assert.IsTrue(zoomIn); + Assert.IsFalse(zoomOut); + Assert.IsFalse(zoomReset); + } + + [TestMethod] + public void MustDetectZoomOutCommand() + { + var zoomIn = false; + var zoomOut = false; + var zoomReset = false; + + sut.ZoomInRequested += () => zoomIn = true; + sut.ZoomOutRequested += () => zoomOut = true; + sut.ZoomResetRequested += () => zoomReset = true; + + var handled = sut.OnKeyEvent(default(IWebBrowser), default(IBrowser), KeyType.KeyUp, (int) Keys.Subtract, default(int), CefEventFlags.ControlDown, false); + + Assert.IsFalse(handled); + Assert.IsFalse(zoomIn); + Assert.IsTrue(zoomOut); + Assert.IsFalse(zoomReset); + + zoomOut = false; + handled = sut.OnKeyEvent(default(IWebBrowser), default(IBrowser), KeyType.KeyUp, (int) Keys.OemMinus, default(int), CefEventFlags.ControlDown, false); + + Assert.IsFalse(handled); + Assert.IsFalse(zoomIn); + Assert.IsTrue(zoomOut); + Assert.IsFalse(zoomReset); + } + + [TestMethod] + public void MustDetectZoomResetCommand() + { + var zoomIn = false; + var zoomOut = false; + var zoomReset = false; + + sut.ZoomInRequested += () => zoomIn = true; + sut.ZoomOutRequested += () => zoomOut = true; + sut.ZoomResetRequested += () => zoomReset = true; + + var handled = sut.OnKeyEvent(default(IWebBrowser), default(IBrowser), KeyType.KeyUp, (int) Keys.D0, default(int), CefEventFlags.ControlDown, false); + + Assert.IsFalse(handled); + Assert.IsFalse(zoomIn); + Assert.IsFalse(zoomOut); + Assert.IsTrue(zoomReset); + + zoomReset = false; + handled = sut.OnKeyEvent(default(IWebBrowser), default(IBrowser), KeyType.KeyUp, (int) Keys.NumPad0, default(int), CefEventFlags.ControlDown, false); + + Assert.IsFalse(handled); + Assert.IsFalse(zoomIn); + Assert.IsFalse(zoomOut); + Assert.IsTrue(zoomReset); + } + } +} diff --git a/SafeExamBrowser.Browser.UnitTests/Handlers/RequestHandlerTests.cs b/SafeExamBrowser.Browser.UnitTests/Handlers/RequestHandlerTests.cs new file mode 100644 index 0000000..db7954a --- /dev/null +++ b/SafeExamBrowser.Browser.UnitTests/Handlers/RequestHandlerTests.cs @@ -0,0 +1,313 @@ +/* + * Copyright (c) 2024 ETH Zürich, IT Services + * + * 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 CefSharp; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Moq; +using SafeExamBrowser.Browser.Contracts.Filters; +using SafeExamBrowser.Browser.Handlers; +using SafeExamBrowser.Configuration.Contracts; +using SafeExamBrowser.Configuration.Contracts.Cryptography; +using SafeExamBrowser.I18n.Contracts; +using SafeExamBrowser.Logging.Contracts; +using SafeExamBrowser.Settings.Browser; +using SafeExamBrowser.Settings.Browser.Filter; +using SafeExamBrowser.Settings.Browser.Proxy; +using BrowserSettings = SafeExamBrowser.Settings.Browser.BrowserSettings; +using Request = SafeExamBrowser.Browser.Contracts.Filters.Request; +using ResourceHandler = SafeExamBrowser.Browser.Handlers.ResourceHandler; + +namespace SafeExamBrowser.Browser.UnitTests.Handlers +{ + [TestClass] + public class RequestHandlerTests + { + private AppConfig appConfig; + private Mock filter; + private Mock keyGenerator; + private Mock logger; + private BrowserSettings settings; + private WindowSettings windowSettings; + private ResourceHandler resourceHandler; + private Mock text; + private TestableRequestHandler sut; + + [TestInitialize] + public void Initialize() + { + appConfig = new AppConfig(); + filter = new Mock(); + keyGenerator = new Mock(); + logger = new Mock(); + settings = new BrowserSettings(); + windowSettings = new WindowSettings(); + text = new Mock(); + resourceHandler = new ResourceHandler(appConfig, filter.Object, keyGenerator.Object, logger.Object, default, settings, windowSettings, text.Object); + + sut = new TestableRequestHandler(appConfig, filter.Object, logger.Object, resourceHandler, settings, windowSettings); + } + + [TestMethod] + public void MustBlockSpecialWindowDispositions() + { + Assert.IsTrue(sut.OnOpenUrlFromTab(default, default, default, default, WindowOpenDisposition.NewBackgroundTab, default)); + Assert.IsTrue(sut.OnOpenUrlFromTab(default, default, default, default, WindowOpenDisposition.NewPopup, default)); + Assert.IsTrue(sut.OnOpenUrlFromTab(default, default, default, default, WindowOpenDisposition.NewWindow, default)); + Assert.IsTrue(sut.OnOpenUrlFromTab(default, default, default, default, WindowOpenDisposition.SaveToDisk, default)); + } + + [TestMethod] + public void MustDetectQuitUrl() + { + var eventFired = false; + var quitUrl = "http://www.byebye.com"; + var request = new Mock(); + + appConfig.ConfigurationFileMimeType = "application/seb"; + request.SetupGet(r => r.Url).Returns(quitUrl); + settings.QuitUrl = quitUrl; + sut.QuitUrlVisited += (url) => eventFired = true; + + var blocked = sut.OnBeforeBrowse(Mock.Of(), Mock.Of(), Mock.Of