sources/Google.Solutions.IapDesktop.Application/Windows/Options/NetworkOptionsViewModel.cs (273 lines of code) (raw):

// // Copyright 2020 Google LLC // // Licensed to the Apache Software Foundation (ASF) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information // regarding copyright ownership. The ASF licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. // using Google.Solutions.IapDesktop.Application.Client; using Google.Solutions.IapDesktop.Application.Profile.Settings; using Google.Solutions.Settings; using Google.Solutions.Settings.Collection; using System; using System.Diagnostics; #pragma warning disable CA1822 // Mark members as static namespace Google.Solutions.IapDesktop.Application.Windows.Options { internal class NetworkOptionsViewModel : OptionsViewModelBase<IApplicationSettings> { private readonly IHttpProxyAdapter proxyAdapter; private string? proxyPacAddress = null; private string? proxyServer = null; private string? proxyPort = null; private string? proxyUsername = null; private string? proxyPassword = null; public NetworkOptionsViewModel( IRepository<IApplicationSettings> settingsRepository, IHttpProxyAdapter proxyAdapter) : base("Network", settingsRepository) { this.proxyAdapter = proxyAdapter; var settings = settingsRepository.GetSettings(); this.IsProxyEditable = !settings.ProxyUrl.IsReadOnly && !settings.ProxyPacUrl.IsReadOnly; if (!string.IsNullOrEmpty(settings.ProxyUrl.Value) && Uri.TryCreate(settings.ProxyUrl.Value, UriKind.Absolute, out var proxyUrl)) { this.proxyServer = proxyUrl.Host; this.proxyPort = proxyUrl.Port.ToString(); } if (settings.ProxyPacUrl.Value != null && !string.IsNullOrEmpty(settings.ProxyPacUrl.Value) && IsValidProxyAutoConfigurationAddress(settings.ProxyPacUrl.Value)) { this.proxyPacAddress = settings.ProxyPacUrl.Value; } if (this.proxyServer != null || this.proxyPacAddress != null) { this.proxyUsername = settings.ProxyUsername.Value; this.proxyPassword = settings.ProxyPassword.GetClearTextValue(); } base.OnInitializationCompleted(); } //--------------------------------------------------------------------- // Overrides. //--------------------------------------------------------------------- protected override void Save(IApplicationSettings settings) { Debug.Assert(this.IsDirty.Value); switch (this.Proxy) { case ProxyType.Custom: if (!IsValidProxyHost(this.proxyServer?.Trim())) { throw new ArgumentException( $"'{this.proxyServer}' is not a valid host name"); } if (!IsValidProxyPort(this.proxyPort?.Trim())) { throw new ArgumentException( $"'{this.proxyPort}' is not a valid port number"); } settings.ProxyUrl.Value = $"http://{this.proxyServer?.Trim()}:{this.proxyPort?.Trim()}"; settings.ProxyPacUrl.Reset(); break; case ProxyType.Autoconfig: if (!IsValidProxyAutoConfigurationAddress(this.proxyPacAddress?.Trim())) { throw new ArgumentException( $"'{this.proxyPacAddress?.Trim()}' is not a valid proxy autoconfiguration URL"); } settings.ProxyUrl.Reset(); settings.ProxyPacUrl.Value = this.proxyPacAddress?.Trim(); break; case ProxyType.System: settings.ProxyUrl.Reset(); settings.ProxyPacUrl.Reset(); break; } if (string.IsNullOrEmpty(this.proxyUsername) != string.IsNullOrEmpty(this.proxyPassword)) { throw new ArgumentException("Proxy credentials are incomplete"); } settings.ProxyUsername.Value = this.proxyUsername; if (this.proxyPassword != null) { settings.ProxyPassword.SetClearTextValue(this.proxyPassword); } else { settings.ProxyPassword.Value = null; } // // Activate changed proxy settings so that the app // does not need to be restarted. // this.proxyAdapter.ActivateSettings(settings); } //--------------------------------------------------------------------- // Observable properties. //--------------------------------------------------------------------- public bool IsProxyEditable { get; private set; } public enum ProxyType { System, Custom, Autoconfig } public ProxyType Proxy { set { switch (value) { case ProxyType.System: // Reset everything. this.ProxyAutoconfigurationAddress = null; this.ProxyServer = null; this.ProxyPort = null; this.ProxyUsername = null; this.ProxyPassword = null; break; case ProxyType.Custom: // Initialize to a sane default. this.ProxyAutoconfigurationAddress = null; this.ProxyServer = this.ProxyServer ?? "proxy"; this.ProxyPort = this.ProxyPort ?? "3128"; break; case ProxyType.Autoconfig: // Initialize to a sane default. this.ProxyAutoconfigurationAddress = "http://proxy/proxy.pac"; this.ProxyServer = null; this.ProxyPort = null; break; } RaisePropertyChange((NetworkOptionsViewModel m) => m.IsSystemProxyServerEnabled); RaisePropertyChange((NetworkOptionsViewModel m) => m.IsCustomProxyServerEnabled); RaisePropertyChange((NetworkOptionsViewModel m) => m.IsProxyAutoConfigurationEnabled); RaisePropertyChange((NetworkOptionsViewModel m) => m.IsCustomProxyServerOrProxyAutoConfigurationEnabled); RaisePropertyChange((NetworkOptionsViewModel m) => m.IsProxyAuthenticationEnabled); } get { if (this.proxyPacAddress != null) { return ProxyType.Autoconfig; } else if (this.proxyServer != null) { return ProxyType.Custom; } else { return ProxyType.System; } } } public bool IsCustomProxyServerEnabled { get => this.Proxy == ProxyType.Custom; set { if (value) { this.Proxy = ProxyType.Custom; } } } public bool IsProxyAutoConfigurationEnabled { get => this.Proxy == ProxyType.Autoconfig; set { if (value) { this.Proxy = ProxyType.Autoconfig; } } } public bool IsSystemProxyServerEnabled { get => this.Proxy == ProxyType.System; set { if (value) { this.Proxy = ProxyType.System; } } } public bool IsCustomProxyServerOrProxyAutoConfigurationEnabled => this.IsCustomProxyServerEnabled || this.IsProxyAutoConfigurationEnabled; public string? ProxyAutoconfigurationAddress { get => this.proxyPacAddress; set { this.proxyPacAddress = value; this.IsDirty.Value = true; RaisePropertyChange(); } } public string? ProxyServer { get => this.proxyServer; set { this.proxyServer = value; this.IsDirty.Value = true; RaisePropertyChange(); } } public string? ProxyPort { get => this.proxyPort; set { this.proxyPort = value; this.IsDirty.Value = true; RaisePropertyChange(); } } public bool IsProxyAuthenticationEnabled { get => !this.IsSystemProxyServerEnabled && !string.IsNullOrEmpty(this.proxyUsername); set { if (value) { // Initialize to a sane default. this.ProxyUsername = Environment.UserName; } else { this.ProxyUsername = null; this.ProxyPassword = null; } RaisePropertyChange(); } } public string? ProxyUsername { get => this.proxyUsername; set { this.proxyUsername = value; this.IsDirty.Value = true; RaisePropertyChange(); } } public string? ProxyPassword { get => this.proxyPassword; set { this.proxyPassword = value; this.IsDirty.Value = true; RaisePropertyChange(); } } //--------------------------------------------------------------------- // Actions. //--------------------------------------------------------------------- public bool IsValidProxyPort(string? port) => int.TryParse(port, out var portNumber) && portNumber > 0 && portNumber <= ushort.MaxValue; public bool IsValidProxyHost(string? host) => Uri.TryCreate($"http://{host}", UriKind.Absolute, out var _); public bool IsValidProxyAutoConfigurationAddress(string? pacAddress) => Uri.TryCreate(pacAddress, UriKind.Absolute, out var uri) && (uri.Scheme == "http" || uri.Scheme == "https"); public void OpenProxyControlPanelApplet() { using (Process.Start(new ProcessStartInfo() { UseShellExecute = false, Verb = "open", FileName = "rundll32.exe", Arguments = "shell32.dll,Control_RunDLL inetcpl.cpl,,4" })) { }; } } }