Helper.Windows.cs
using System; using System.Collections; using System.Reflection; using System.Windows; using System.Windows.Controls; using System.Windows.Navigation; namespace PSWebAuthBroker_ab8baa5cebae4693a6fc517d7b0f69c3 { public class BrokerWindow : IDisposable { Window window; WebBrowser browser; /// <summary> /// Initializes a new BrokerWindow object. /// </summary> public BrokerWindow() { window = new Window(); browser = new WebBrowser(); browser.Tag = this; browser.Navigating += browserNavigating; browser.Navigated += browserNavigated; window.Tag = this; window.Title = "Authnetication Broker"; window.MinWidth = 440; window.MinHeight = 330; window.Width = 550; window.Height = 450; window.Content = browser; window.Closing += windowClosing; } /// <summary> /// Displays the broker and authenticates the user. This method must not be called twice. /// </summary> public bool AuthenticateUser() { browser.Navigate(InitialUri); return window.ShowDialog() == true; } /// <summary> /// Gets/sets the title for the window. /// </summary> public string Title { get { return window.Title; } set { window.Title = value; } } /// <summary> /// Gets/sets the initial URI to navigate to. /// </summary> public string InitialUri { get; set; } /// <summary> /// Gets/sets whether the broker should use current URI as the title. /// </summary> public bool TitleIsUri { get; set; } /// <summary> /// Gets the extracted information object. /// </summary> public object Extracted { get; private set; } /// <summary> /// Gets/sets an extractor delegate that extracts authentication information from the URI. /// This delegate is called each time the broker has navigated. /// Returning null from this delegate continues the authentication procedure. /// Returning non-null from this delegate terminates the authentication procedure. /// </summary> public Func<string, object> CompletionExtractor { get; set; } /// <summary> /// Gets/sets a predicate whether a URI should be allowed to display within this broker. /// This delegate is called each time before the broker navigates. /// Returning true from this delegate allows navigation. /// Returning false from this delegate disallows navigation. /// An example usage is to only allow HTTPS pages. /// </summary> public Func<string, bool> UriPredicate { get; set; } private static void browserNavigating(object sender, NavigatingCancelEventArgs e) { var that = (BrokerWindow)((WebBrowser)sender).Tag; var uriUri = e.Uri; var uri = (uriUri != null ? uriUri.AbsoluteUri : null); var pred = that.UriPredicate ?? (_ => true); if (!pred(uri)) { MessageBox.Show(that.window, "The URI is disallowed in this authentication broker.\r\nThe URI is " + uri, "Navigation cancelled", MessageBoxButton.OK, MessageBoxImage.Warning); e.Cancel = true; } } const BindingFlags InstancePublicMethod = BindingFlags.Instance | BindingFlags.Public | BindingFlags.InvokeMethod; const BindingFlags InstancePublicSetProp = BindingFlags.Instance | BindingFlags.Public | BindingFlags.SetProperty; static readonly object[] CreateScriptElementParams = new object[] { "SCRIPT" }; static readonly object[] SetTypeJSParams = new object[] { "application/javascript" }; static readonly object[] SetInnerHtmlJSParams = new object[] { "window.onerror = function () { return true; };" }; static readonly object[] GetHeadParams = new object[] { "head" }; private static void SuppressJavaScriptErrors(WebBrowser browser) { try { var doc = browser.Document; var scriptElement = doc.GetType().InvokeMember("createElement", InstancePublicMethod, null, doc, CreateScriptElementParams); scriptElement.GetType().InvokeMember("type", InstancePublicSetProp, null, scriptElement, SetTypeJSParams); scriptElement.GetType().InvokeMember("innerHTML", InstancePublicSetProp, null, scriptElement, SetInnerHtmlJSParams); var heads = doc.GetType().InvokeMember("getElementsByTagName", InstancePublicMethod, null, doc, GetHeadParams); foreach (var head in (IEnumerable)heads) { head.GetType().InvokeMember("appendChild", InstancePublicMethod, null, head, new object[] { scriptElement }); break; } } catch { } } private static void browserNavigated(object sender, NavigationEventArgs e) { var that = (BrokerWindow)((WebBrowser)sender).Tag; SuppressJavaScriptErrors(that.browser); var srcUri = that.browser.Source; var newSource = (srcUri != null ? srcUri.AbsoluteUri : null); if (that.TitleIsUri) { that.window.Title = newSource ?? "Authentication Broker"; } var extractor = that.CompletionExtractor ?? (_ => null); var extracted = extractor(newSource ?? ""); if (!ReferenceEquals(extracted, null)) { that.Extracted = extracted; that.window.DialogResult = true; that.window.Close(); } } private static void windowClosing(object sender, System.ComponentModel.CancelEventArgs e) { var that = (BrokerWindow)((Window)sender).Tag; that.Dispose(); } /// <summary> /// Disposes the object. /// This method is automatically called when the UI is dismissed. /// </summary> public void Dispose() { window.Content = null; browser.Dispose(); } } } |