diff options
-rw-r--r-- | samples/OpenIdOfflineProvider/App.xaml.cs | 5 | ||||
-rw-r--r-- | samples/OpenIdOfflineProvider/HttpHost.cs | 54 | ||||
-rw-r--r-- | samples/OpenIdOfflineProvider/MainWindow.xaml | 18 | ||||
-rw-r--r-- | samples/OpenIdOfflineProvider/MainWindow.xaml.cs | 115 | ||||
-rw-r--r-- | samples/OpenIdOfflineProvider/OpenIdOfflineProvider.csproj | 22 |
5 files changed, 157 insertions, 57 deletions
diff --git a/samples/OpenIdOfflineProvider/App.xaml.cs b/samples/OpenIdOfflineProvider/App.xaml.cs index 1401d8c..ed0f25a 100644 --- a/samples/OpenIdOfflineProvider/App.xaml.cs +++ b/samples/OpenIdOfflineProvider/App.xaml.cs @@ -11,13 +11,16 @@ namespace DotNetOpenAuth.OpenIdOfflineProvider { using System.Data; using System.Linq; using System.Windows; - using log4net.Core; using log4net; + using log4net.Core; /// <summary> /// Interaction logic for App.xaml /// </summary> public partial class App : Application { + /// <summary> + /// Message logger. + /// </summary> internal static ILog Logger = log4net.LogManager.GetLogger(typeof(App)); /// <summary> diff --git a/samples/OpenIdOfflineProvider/HttpHost.cs b/samples/OpenIdOfflineProvider/HttpHost.cs index 0c810bf..390275a 100644 --- a/samples/OpenIdOfflineProvider/HttpHost.cs +++ b/samples/OpenIdOfflineProvider/HttpHost.cs @@ -6,23 +6,42 @@ namespace DotNetOpenAuth.OpenIdOfflineProvider { using System; + using System.Diagnostics.Contracts; using System.Globalization; using System.IO; using System.Net; using System.Threading; - using DotNetOpenAuth.OpenId.Provider; - using System.Diagnostics.Contracts; using DotNetOpenAuth.Messaging; + using DotNetOpenAuth.OpenId.Provider; + /// <summary> + /// An HTTP Listener that dispatches incoming requests for handling. + /// </summary> internal class HttpHost : IDisposable { + /// <summary> + /// The HttpListener that waits for incoming requests. + /// </summary> private readonly HttpListener listener; + + /// <summary> + /// The thread that listens for incoming HTTP requests and dispatches them + /// to the <see cref="handler"/>. + /// </summary> private Thread listenerThread; + + /// <summary> + /// The handler for incoming HTTP requests. + /// </summary> private RequestHandler handler; + /// <summary> + /// Initializes a new instance of the <see cref="HttpHost"/> class. + /// </summary> + /// <param name="handler">The handler for incoming HTTP requests.</param> private HttpHost(RequestHandler handler) { Contract.Requires(handler != null); - this.Port = 59687; + this.Port = 45235; this.handler = handler; Random r = new Random(); tryAgain: @@ -42,14 +61,29 @@ namespace DotNetOpenAuth.OpenIdOfflineProvider { this.listenerThread.Start(); } + /// <summary> + /// The request handler delegate. + /// </summary> + /// <param name="context">Information on the incoming HTTP request.</param> + internal delegate void RequestHandler(HttpListenerContext context); + + /// <summary> + /// Gets the port that HTTP requests are being listened for on. + /// </summary> public int Port { get; private set; } + /// <summary> + /// Gets the base URI for all incoming web requests that will be received. + /// </summary> public Uri BaseUri { get { return new Uri("http://localhost:" + this.Port.ToString() + "/"); } } - internal delegate void RequestHandler(HttpListenerContext context); - + /// <summary> + /// Creates the HTTP host. + /// </summary> + /// <param name="handler">The handler for incoming HTTP requests.</param> + /// <returns>The instantiated host.</returns> public static HttpHost CreateHost(RequestHandler handler) { Contract.Requires(handler != null); Contract.Ensures(Contract.Result<HttpHost>() != null); @@ -59,11 +93,18 @@ namespace DotNetOpenAuth.OpenIdOfflineProvider { #region IDisposable Members + /// <summary> + /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. + /// </summary> public void Dispose() { this.Dispose(true); GC.SuppressFinalize(this); } + /// <summary> + /// Releases unmanaged and - optionally - managed resources + /// </summary> + /// <param name="disposing"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param> protected virtual void Dispose(bool disposing) { if (disposing) { this.listener.Close(); @@ -74,6 +115,9 @@ namespace DotNetOpenAuth.OpenIdOfflineProvider { #endregion + /// <summary> + /// The HTTP listener thread body. + /// </summary> private void ProcessRequests() { Contract.Requires(this.listener != null); diff --git a/samples/OpenIdOfflineProvider/MainWindow.xaml b/samples/OpenIdOfflineProvider/MainWindow.xaml index e93cb7a..8100fb7 100644 --- a/samples/OpenIdOfflineProvider/MainWindow.xaml +++ b/samples/OpenIdOfflineProvider/MainWindow.xaml @@ -1,26 +1,32 @@ <Window x:Class="DotNetOpenAuth.OpenIdOfflineProvider.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" - Title="DotNetOpenAuth Offline OpenID Provider" Height="300" Width="300"> + Title="DotNetOpenAuth Offline OpenID Provider" Height="166" Width="329"> <StackPanel> <Grid> <Grid.RowDefinitions> <RowDefinition /> <RowDefinition /> <RowDefinition /> + <RowDefinition /> + <RowDefinition /> </Grid.RowDefinitions> <Grid.ColumnDefinitions> - <ColumnDefinition /> + <ColumnDefinition Width="auto" /> <ColumnDefinition /> </Grid.ColumnDefinitions> <Label >Port</Label> - <TextBox Name="portTextBox" Grid.Column="1" /> + <Label Name="portLabel" Grid.Column="1" /> <Label Grid.Row="1">OP Identifier</Label> - <Label Grid.Column="1" Grid.Row="1" Name="opIdentifierLabel" ></Label> + <Label Grid.Column="1" Grid.Row="1" Name="opIdentifierLabel"></Label> + <Label Grid.Row="2">Yes Identifier</Label> + <Label Grid.Column="1" Grid.Row="2" Name="yesIdentity" ></Label> + <Label Grid.Row="3">No Identifier</Label> + <Label Grid.Column="1" Grid.Row="3" Name="noIdentity" ></Label> </Grid> <StackPanel Orientation="Horizontal"> - <Button Name="startButton" Click="startButton_Click">Start</Button> - <Button Name="stopButton" Click="stopButton_Click">Stop</Button> + <Button Name="startButton" Click="startButton_Click" Padding="10,0,10,0">Start</Button> + <Button Name="stopButton" Click="stopButton_Click" Padding="10,0,10,0">Stop</Button> </StackPanel> </StackPanel> </Window> diff --git a/samples/OpenIdOfflineProvider/MainWindow.xaml.cs b/samples/OpenIdOfflineProvider/MainWindow.xaml.cs index 1975e91..8cfe157 100644 --- a/samples/OpenIdOfflineProvider/MainWindow.xaml.cs +++ b/samples/OpenIdOfflineProvider/MainWindow.xaml.cs @@ -7,7 +7,12 @@ namespace DotNetOpenAuth.OpenIdOfflineProvider { using System; using System.Collections.Generic; + using System.Diagnostics; + using System.Diagnostics.Contracts; + using System.Globalization; + using System.IO; using System.Linq; + using System.Net; using System.Text; using System.Windows; using System.Windows.Controls; @@ -18,18 +23,34 @@ namespace DotNetOpenAuth.OpenIdOfflineProvider { using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; - using DotNetOpenAuth.OpenId.Provider; - using System.Globalization; - using System.Net; using DotNetOpenAuth.Messaging; - using System.Diagnostics.Contracts; - using System.IO; + using DotNetOpenAuth.OpenId.Provider; /// <summary> /// Interaction logic for MainWindow.xaml /// </summary> public partial class MainWindow : Window, IDisposable { /// <summary> + /// The path to the Provider Endpoint. + /// </summary> + private const string ProviderPath = "/provider"; + + /// <summary> + /// The path to the OP Identifier. + /// </summary> + private const string OPIdentifier = "/"; + + /// <summary> + /// The path to the user identity page that always generates a positive assertion. + /// </summary> + private const string YesIdentity = "/user"; + + /// <summary> + /// The path to the user identity page that always generates a negative response. + /// </summary> + private const string NoIdentity = "/no"; + + /// <summary> /// The <see cref="OpenIdProvider"/> instance that processes incoming requests. /// </summary> private OpenIdProvider provider = new OpenIdProvider(new StandardProviderApplicationStore()); @@ -46,15 +67,6 @@ namespace DotNetOpenAuth.OpenIdOfflineProvider { this.InitializeComponent(); } - /// <summary> - /// Raises the <see cref="E:Closing"/> event. - /// </summary> - /// <param name="e">The <see cref="System.ComponentModel.CancelEventArgs"/> instance containing the event data.</param> - protected override void OnClosing(System.ComponentModel.CancelEventArgs e) { - this.StopProvider(); - base.OnClosing(e); - } - #region IDisposable Members /// <summary> @@ -82,6 +94,36 @@ namespace DotNetOpenAuth.OpenIdOfflineProvider { #endregion /// <summary> + /// Raises the <see cref="E:Closing"/> event. + /// </summary> + /// <param name="e">The <see cref="System.ComponentModel.CancelEventArgs"/> instance containing the event data.</param> + protected override void OnClosing(System.ComponentModel.CancelEventArgs e) { + this.StopProvider(); + base.OnClosing(e); + } + + private static string GenerateHtmlDiscoveryDocument(string providerEndpoint, string localId) { + Contract.Requires(providerEndpoint != null && providerEndpoint.Length > 0); + + const string DelegatedHtmlDiscoveryFormat = @"<html><head> + <link rel=""openid.server"" href=""{0}"" /> + <link rel=""openid.delegate"" href=""{1}"" /> + <link rel=""openid2.provider"" href=""{0}"" /> + <link rel=""openid2.local_id"" href=""{1}"" /> + </head><body></body></html>"; + + const string NonDelegatedHtmlDiscoveryFormat = @"<html><head> + <link rel=""openid.server"" href=""{0}"" /> + <link rel=""openid2.provider"" href=""{0}"" /> + </head><body></body></html>"; + + return string.Format( + localId != null ? DelegatedHtmlDiscoveryFormat : NonDelegatedHtmlDiscoveryFormat, + providerEndpoint, + localId); + } + + /// <summary> /// Handles the Click event of the startButton control. /// </summary> /// <param name="sender">The source of the event.</param> @@ -92,16 +134,18 @@ namespace DotNetOpenAuth.OpenIdOfflineProvider { private void StartProvider() { this.httpHost = HttpHost.CreateHost(this.RequestHandler); - this.portTextBox.Text = this.httpHost.Port.ToString(CultureInfo.InvariantCulture); - this.opIdentifierLabel.Content = string.Format("http://localhost:{0}/", this.httpHost.Port); + this.portLabel .Content = this.httpHost.Port.ToString(CultureInfo.InvariantCulture); + string url = "http://localhost:{0}{1}"; + this.opIdentifierLabel.Content = "not yet supported"; // string.Format(url, this.httpHost.Port, OPIdentifier); + this.noIdentity.Content = string.Format(url, this.httpHost.Port, NoIdentity); + this.yesIdentity.Content = string.Format(url, this.httpHost.Port, YesIdentity); } private void RequestHandler(HttpListenerContext context) { Contract.Requires(context != null); - - const string ProviderPath = "/provider"; - const string YesIdentity = "/user"; - const string NoIdentity = "/no"; + Contract.Requires(context.Response.OutputStream != null); + Stream outputStream = context.Response.OutputStream; + Contract.Assume(outputStream != null); // CC static verification shortcoming. if (context.Request.Url.AbsolutePath == ProviderPath) { HttpRequestInfo requestInfo = new HttpRequestInfo(context.Request); @@ -109,7 +153,7 @@ namespace DotNetOpenAuth.OpenIdOfflineProvider { if (providerRequest == null) { App.Logger.Error("A request came in that did not carry an OpenID message."); context.Response.StatusCode = (int)HttpStatusCode.BadRequest; - using (StreamWriter sw = new StreamWriter(context.Response.OutputStream)) { + using (StreamWriter sw = new StreamWriter(outputStream)) { sw.WriteLine("<html><body>This is an OpenID Provider endpoint.</body></html>"); } return; @@ -124,10 +168,9 @@ namespace DotNetOpenAuth.OpenIdOfflineProvider { authRequest.IsAuthenticated = new Uri(authRequest.ClaimedIdentifier).AbsolutePath == YesIdentity; } - Contract.Assert(providerRequest.IsResponseReady); this.provider.PrepareResponse(providerRequest).Send(context.Response); } else if (context.Request.Url.AbsolutePath == YesIdentity || context.Request.Url.AbsolutePath == NoIdentity) { - using (StreamWriter sw = new StreamWriter(context.Response.OutputStream)) { + using (StreamWriter sw = new StreamWriter(outputStream)) { string providerEndpoint = string.Format("http://localhost:{0}{1}", context.Request.Url.Port, ProviderPath); string localId = null; // string.Format("http://localhost:{0}/user", context.Request.Url.Port); string html = GenerateHtmlDiscoveryDocument(providerEndpoint, localId); @@ -142,30 +185,12 @@ namespace DotNetOpenAuth.OpenIdOfflineProvider { } } - private string GenerateHtmlDiscoveryDocument(string providerEndpoint, string localId) { - Contract.Requires(providerEndpoint != null && providerEndpoint.Length > 0); - - const string DelegatedHtmlDiscoveryFormat = @"<html><head> - <link rel=""openid.server"" href=""{0}"" /> - <link rel=""openid.delegate"" href=""{1}"" /> - <link rel=""openid2.provider"" href=""{0}"" /> - <link rel=""openid2.local_id"" href=""{1}"" /> - </head><body></body></html>"; - - const string NonDelegatedHtmlDiscoveryFormat = @"<html><head> - <link rel=""openid.server"" href=""{0}"" /> - <link rel=""openid2.provider"" href=""{0}"" /> - </head><body></body></html>"; - - return string.Format( - localId != null ? DelegatedHtmlDiscoveryFormat : NonDelegatedHtmlDiscoveryFormat, - providerEndpoint, - localId); - } - private void stopButton_Click(object sender, RoutedEventArgs e) { this.StopProvider(); - this.portTextBox.Text = string.Empty; + this.portLabel.Content = string.Empty; + this.noIdentity.Content = string.Empty; + this.yesIdentity.Content = string.Empty; + this.opIdentifierLabel.Content = string.Empty; } private void StopProvider() { diff --git a/samples/OpenIdOfflineProvider/OpenIdOfflineProvider.csproj b/samples/OpenIdOfflineProvider/OpenIdOfflineProvider.csproj index 26f523c..2e6db1b 100644 --- a/samples/OpenIdOfflineProvider/OpenIdOfflineProvider.csproj +++ b/samples/OpenIdOfflineProvider/OpenIdOfflineProvider.csproj @@ -24,6 +24,28 @@ <DefineConstants>DEBUG;TRACE</DefineConstants> <ErrorReport>prompt</ErrorReport> <WarningLevel>4</WarningLevel> + <CodeContractsEnableRuntimeChecking>True</CodeContractsEnableRuntimeChecking> + <CodeContractsCustomRewriterAssembly> + </CodeContractsCustomRewriterAssembly> + <CodeContractsCustomRewriterClass> + </CodeContractsCustomRewriterClass> + <CodeContractsRuntimeCheckingLevel>Full</CodeContractsRuntimeCheckingLevel> + <CodeContractsRunCodeAnalysis>True</CodeContractsRunCodeAnalysis> + <CodeContractsBuildReferenceAssembly>False</CodeContractsBuildReferenceAssembly> + <CodeContractsNonNullObligations>False</CodeContractsNonNullObligations> + <CodeContractsBoundsObligations>False</CodeContractsBoundsObligations> + <CodeContractsArithmeticObligations>False</CodeContractsArithmeticObligations> + <CodeContractsLibPaths> + </CodeContractsLibPaths> + <CodeContractsPlatformPath> + </CodeContractsPlatformPath> + <CodeContractsExtraAnalysisOptions> + </CodeContractsExtraAnalysisOptions> + <CodeContractsBaseLineFile> + </CodeContractsBaseLineFile> + <CodeContractsUseBaseLine>False</CodeContractsUseBaseLine> + <CodeContractsRunInBackground>True</CodeContractsRunInBackground> + <CodeContractsShowSquigglies>True</CodeContractsShowSquigglies> </PropertyGroup> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> <DebugType>pdbonly</DebugType> |