diff options
Diffstat (limited to 'src')
26 files changed, 197 insertions, 69 deletions
diff --git a/src/DotNetOpenAuth.Test/DotNetOpenAuth.Test.csproj b/src/DotNetOpenAuth.Test/DotNetOpenAuth.Test.csproj index 4e32069..4779214 100644 --- a/src/DotNetOpenAuth.Test/DotNetOpenAuth.Test.csproj +++ b/src/DotNetOpenAuth.Test/DotNetOpenAuth.Test.csproj @@ -315,7 +315,6 @@ <ProjectReference Include="..\DotNetOpenAuth\DotNetOpenAuth.csproj"> <Project>{3191B653-F76D-4C1A-9A5A-347BC3AAAAB7}</Project> <Name>DotNetOpenAuth</Name> - <Shadow>true</Shadow> </ProjectReference> </ItemGroup> <ItemGroup> diff --git a/src/DotNetOpenAuth.Test/Messaging/ChannelTests.cs b/src/DotNetOpenAuth.Test/Messaging/ChannelTests.cs index d22c2f7..5d31d40 100644 --- a/src/DotNetOpenAuth.Test/Messaging/ChannelTests.cs +++ b/src/DotNetOpenAuth.Test/Messaging/ChannelTests.cs @@ -254,8 +254,7 @@ namespace DotNetOpenAuth.Test.Messaging { new TestMessageFactory(), new MockSigningBindingElement(), new MockSigningBindingElement()); - Channel_Accessor accessor = Channel_Accessor.AttachShadow(channel); - accessor.ProcessOutgoingMessage(new TestSignedDirectedMessage()); + channel.ProcessOutgoingMessageTestHook(new TestSignedDirectedMessage()); } [TestCase] diff --git a/src/DotNetOpenAuth.Test/Mocks/CoordinatingChannel.cs b/src/DotNetOpenAuth.Test/Mocks/CoordinatingChannel.cs index 0bb35bc..99520a2 100644 --- a/src/DotNetOpenAuth.Test/Mocks/CoordinatingChannel.cs +++ b/src/DotNetOpenAuth.Test/Mocks/CoordinatingChannel.cs @@ -200,13 +200,11 @@ namespace DotNetOpenAuth.Test.Mocks { } protected override IDictionary<string, string> ReadFromResponseCore(IncomingWebResponse response) { - Channel_Accessor accessor = Channel_Accessor.AttachShadow(this.wrappedChannel); - return accessor.ReadFromResponseCore(response); + return this.wrappedChannel.ReadFromResponseCoreTestHook(response); } protected override void ProcessIncomingMessage(IProtocolMessage message) { - Channel_Accessor accessor = Channel_Accessor.AttachShadow(this.wrappedChannel); - accessor.ProcessIncomingMessage(message); + this.wrappedChannel.ProcessIncomingMessageTestHook(message); } /// <summary> @@ -254,8 +252,7 @@ namespace DotNetOpenAuth.Test.Mocks { private static IMessageFactory GetMessageFactory(Channel channel) { Contract.Requires<ArgumentNullException>(channel != null); - Channel_Accessor accessor = Channel_Accessor.AttachShadow(channel); - return accessor.MessageFactory; + return channel.MessageFactoryTestHook; } private IDictionary<string, string> AwaitIncomingMessage(out MessageReceivingEndpoint recipient) { diff --git a/src/DotNetOpenAuth.Test/OAuth/ChannelElements/HmacSha1SigningBindingElementTests.cs b/src/DotNetOpenAuth.Test/OAuth/ChannelElements/HmacSha1SigningBindingElementTests.cs index a11c67d..036f8ec 100644 --- a/src/DotNetOpenAuth.Test/OAuth/ChannelElements/HmacSha1SigningBindingElementTests.cs +++ b/src/DotNetOpenAuth.Test/OAuth/ChannelElements/HmacSha1SigningBindingElementTests.cs @@ -16,9 +16,9 @@ namespace DotNetOpenAuth.Test.ChannelElements { public void SignatureTest() { UnauthorizedTokenRequest message = SigningBindingElementBaseTests.CreateTestRequestTokenMessage(this.MessageDescriptions, null); - HmacSha1SigningBindingElement_Accessor hmac = new HmacSha1SigningBindingElement_Accessor(); + var hmac = new HmacSha1SigningBindingElement(); hmac.Channel = new TestChannel(this.MessageDescriptions); - Assert.AreEqual("kR0LhH8UqylaLfR/esXVVlP4sQI=", hmac.GetSignature(message)); + Assert.AreEqual("kR0LhH8UqylaLfR/esXVVlP4sQI=", hmac.GetSignatureTestHook(message)); } } } diff --git a/src/DotNetOpenAuth.Test/OAuth/ChannelElements/OAuthChannelTests.cs b/src/DotNetOpenAuth.Test/OAuth/ChannelElements/OAuthChannelTests.cs index c7b9f89..f78f4e1 100644 --- a/src/DotNetOpenAuth.Test/OAuth/ChannelElements/OAuthChannelTests.cs +++ b/src/DotNetOpenAuth.Test/OAuth/ChannelElements/OAuthChannelTests.cs @@ -24,7 +24,6 @@ namespace DotNetOpenAuth.Test.ChannelElements { [TestFixture] public class OAuthChannelTests : TestBase { private OAuthChannel channel; - private OAuthChannel_Accessor accessor; private TestWebRequestHandler webRequestHandler; private SigningBindingElementBase signingElement; private INonceStore nonceStore; @@ -37,7 +36,6 @@ namespace DotNetOpenAuth.Test.ChannelElements { this.signingElement = new RsaSha1SigningBindingElement(new InMemoryTokenManager()); this.nonceStore = new NonceMemoryStore(StandardExpirationBindingElement.MaximumMessageAge); this.channel = new OAuthChannel(this.signingElement, this.nonceStore, new InMemoryTokenManager(), new TestMessageFactory()); - this.accessor = OAuthChannel_Accessor.AttachShadow(this.channel); this.channel.WebRequestHandler = this.webRequestHandler; } @@ -149,8 +147,7 @@ namespace DotNetOpenAuth.Test.ChannelElements { writer.Write(MessagingUtilities.CreateQueryString(fields)); writer.Flush(); ms.Seek(0, SeekOrigin.Begin); - Channel_Accessor channelAccessor = Channel_Accessor.AttachShadow(this.channel); - IDictionary<string, string> deserializedFields = channelAccessor.ReadFromResponseCore(new CachedDirectWebResponse { CachedResponseStream = ms }); + IDictionary<string, string> deserializedFields = this.channel.ReadFromResponseCoreTestHook(new CachedDirectWebResponse { CachedResponseStream = ms }); Assert.AreEqual(fields.Count, deserializedFields.Count); foreach (string key in fields.Keys) { Assert.AreEqual(fields[key], deserializedFields[key]); @@ -238,13 +235,13 @@ namespace DotNetOpenAuth.Test.ChannelElements { [TestCase] public void SendDirectMessageResponseHonorsHttpStatusCodes() { IProtocolMessage message = MessagingTestBase.GetStandardTestMessage(MessagingTestBase.FieldFill.AllRequired); - OutgoingWebResponse directResponse = this.accessor.PrepareDirectResponse(message); + OutgoingWebResponse directResponse = this.channel.PrepareDirectResponseTestHook(message); Assert.AreEqual(HttpStatusCode.OK, directResponse.Status); var httpMessage = new TestDirectResponseMessageWithHttpStatus(); MessagingTestBase.GetStandardTestMessage(MessagingTestBase.FieldFill.AllRequired, httpMessage); httpMessage.HttpStatusCode = HttpStatusCode.NotAcceptable; - directResponse = this.accessor.PrepareDirectResponse(httpMessage); + directResponse = this.channel.PrepareDirectResponseTestHook(httpMessage); Assert.AreEqual(HttpStatusCode.NotAcceptable, directResponse.Status); } diff --git a/src/DotNetOpenAuth.Test/OAuth/ChannelElements/SigningBindingElementBaseTests.cs b/src/DotNetOpenAuth.Test/OAuth/ChannelElements/SigningBindingElementBaseTests.cs index c2ae65e..86add22 100644 --- a/src/DotNetOpenAuth.Test/OAuth/ChannelElements/SigningBindingElementBaseTests.cs +++ b/src/DotNetOpenAuth.Test/OAuth/ChannelElements/SigningBindingElementBaseTests.cs @@ -22,7 +22,7 @@ namespace DotNetOpenAuth.Test.ChannelElements { new MessageReceivingEndpoint("https://www.google.com/accounts/OAuthGetRequestToken", HttpDeliveryMethods.AuthorizationHeaderRequest | HttpDeliveryMethods.GetRequest)); Assert.AreEqual( "GET&https%3A%2F%2Fwww.google.com%2Faccounts%2FOAuthGetRequestToken&oauth_consumer_key%3Dnerdbank.org%26oauth_nonce%3Dfe4045a3f0efdd1e019fa8f8ae3f5c38%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D1222665749%26oauth_version%3D1.0%26scope%3Dhttp%253A%252F%252Fwww.google.com%252Fm8%252Ffeeds%252F", - SigningBindingElementBase_Accessor.ConstructSignatureBaseString(message, MessageDictionary_Accessor.AttachShadow(this.MessageDescriptions.GetAccessor(message)))); + SigningBindingElementBase.ConstructSignatureBaseString(message, this.MessageDescriptions.GetAccessor(message))); // Test HTTP GET with an attached query string. We're elevating the scope parameter to the query string // and removing it from the extradata dictionary. This should NOT affect the base signature string. @@ -32,7 +32,7 @@ namespace DotNetOpenAuth.Test.ChannelElements { message.ExtraData.Remove("scope"); // remove it from ExtraData since we put it in the URL Assert.AreEqual( "GET&https%3A%2F%2Fwww.google.com%2Faccounts%2FOAuthGetRequestToken&oauth_consumer_key%3Dnerdbank.org%26oauth_nonce%3Dfe4045a3f0efdd1e019fa8f8ae3f5c38%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D1222665749%26oauth_version%3D1.0%26scope%3Dhttp%253A%252F%252Fwww.google.com%252Fm8%252Ffeeds%252F", - SigningBindingElementBase_Accessor.ConstructSignatureBaseString(message, MessageDictionary_Accessor.AttachShadow(this.MessageDescriptions.GetAccessor(message)))); + SigningBindingElementBase.ConstructSignatureBaseString(message, this.MessageDescriptions.GetAccessor(message))); // Test HTTP POST, with query string as well message = CreateTestRequestTokenMessage( @@ -41,7 +41,7 @@ namespace DotNetOpenAuth.Test.ChannelElements { message.ExtraData.Remove("scope"); // remove it from ExtraData since we put it in the URL Assert.AreEqual( "GET&https%3A%2F%2Fwww.google.com%2Faccounts%2FOAuthGetRequestToken&oauth_consumer_key%3Dnerdbank.org%26oauth_nonce%3Dfe4045a3f0efdd1e019fa8f8ae3f5c38%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D1222665749%26oauth_version%3D1.0%26scope%3Dhttp%253A%252F%252Fwww.google.com%252Fm8%252Ffeeds%252F", - SigningBindingElementBase_Accessor.ConstructSignatureBaseString(message, MessageDictionary_Accessor.AttachShadow(this.MessageDescriptions.GetAccessor(message)))); + SigningBindingElementBase.ConstructSignatureBaseString(message, this.MessageDescriptions.GetAccessor(message))); // Test HTTP POST, with query string, but not using the Authorization header message = CreateTestRequestTokenMessage( @@ -50,7 +50,7 @@ namespace DotNetOpenAuth.Test.ChannelElements { message.ExtraData.Remove("scope"); // remove it from ExtraData since we put it in the URL Assert.AreEqual( "GET&https%3A%2F%2Fwww.google.com%2Faccounts%2FOAuthGetRequestToken&oauth_consumer_key%3Dnerdbank.org%26oauth_nonce%3Dfe4045a3f0efdd1e019fa8f8ae3f5c38%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D1222665749%26oauth_version%3D1.0%26scope%3Dhttp%253A%252F%252Fwww.google.com%252Fm8%252Ffeeds%252F", - SigningBindingElementBase_Accessor.ConstructSignatureBaseString(message, MessageDictionary_Accessor.AttachShadow(this.MessageDescriptions.GetAccessor(message)))); + SigningBindingElementBase.ConstructSignatureBaseString(message, this.MessageDescriptions.GetAccessor(message))); // This is a simulation of receiving the message, where the query string is still in the URL, // but has been read into ExtraData, so parameters in the query string appear twice. @@ -59,7 +59,7 @@ namespace DotNetOpenAuth.Test.ChannelElements { new MessageReceivingEndpoint("https://www.google.com/accounts/OAuthGetRequestToken?scope=http://www.google.com/m8/feeds/", HttpDeliveryMethods.AuthorizationHeaderRequest | HttpDeliveryMethods.PostRequest)); Assert.AreEqual( "GET&https%3A%2F%2Fwww.google.com%2Faccounts%2FOAuthGetRequestToken&oauth_consumer_key%3Dnerdbank.org%26oauth_nonce%3Dfe4045a3f0efdd1e019fa8f8ae3f5c38%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D1222665749%26oauth_version%3D1.0%26scope%3Dhttp%253A%252F%252Fwww.google.com%252Fm8%252Ffeeds%252F", - SigningBindingElementBase_Accessor.ConstructSignatureBaseString(message, MessageDictionary_Accessor.AttachShadow(this.MessageDescriptions.GetAccessor(message)))); + SigningBindingElementBase.ConstructSignatureBaseString(message, this.MessageDescriptions.GetAccessor(message))); } internal static UnauthorizedTokenRequest CreateTestRequestTokenMessage(MessageDescriptionCollection messageDescriptions, MessageReceivingEndpoint endpoint) { diff --git a/src/DotNetOpenAuth.Test/OpenId/AssociationHandshakeTests.cs b/src/DotNetOpenAuth.Test/OpenId/AssociationHandshakeTests.cs index 8c2b5bd..390a5f1 100644 --- a/src/DotNetOpenAuth.Test/OpenId/AssociationHandshakeTests.cs +++ b/src/DotNetOpenAuth.Test/OpenId/AssociationHandshakeTests.cs @@ -81,23 +81,21 @@ namespace DotNetOpenAuth.Test.OpenId { // Receive initial request for an HMAC-SHA256 association. AutoResponsiveRequest req = (AutoResponsiveRequest)op.GetRequest(); - AutoResponsiveRequest_Accessor reqAccessor = AutoResponsiveRequest_Accessor.AttachShadow(req); - AssociateRequest associateRequest = (AssociateRequest)reqAccessor.RequestMessage; + AssociateRequest associateRequest = (AssociateRequest)req.RequestMessage; Assert.AreEqual(protocol.Args.SignatureAlgorithm.HMAC_SHA256, associateRequest.AssociationType); // Ensure that the response is a suggestion that the RP try again with HMAC-SHA1 - AssociateUnsuccessfulResponse renegotiateResponse = (AssociateUnsuccessfulResponse)reqAccessor.ResponseMessage; + AssociateUnsuccessfulResponse renegotiateResponse = (AssociateUnsuccessfulResponse)req.ResponseMessageTestHook; Assert.AreEqual(protocol.Args.SignatureAlgorithm.HMAC_SHA1, renegotiateResponse.AssociationType); op.SendResponse(req); // Receive second attempt request for an HMAC-SHA1 association. req = (AutoResponsiveRequest)op.GetRequest(); - reqAccessor = AutoResponsiveRequest_Accessor.AttachShadow(req); - associateRequest = (AssociateRequest)reqAccessor.RequestMessage; + associateRequest = (AssociateRequest)req.RequestMessage; Assert.AreEqual(protocol.Args.SignatureAlgorithm.HMAC_SHA1, associateRequest.AssociationType); // Ensure that the response is a success response. - AssociateSuccessfulResponse successResponse = (AssociateSuccessfulResponse)reqAccessor.ResponseMessage; + AssociateSuccessfulResponse successResponse = (AssociateSuccessfulResponse)req.ResponseMessageTestHook; Assert.AreEqual(protocol.Args.SignatureAlgorithm.HMAC_SHA1, successResponse.AssociationType); op.SendResponse(req); }); @@ -352,11 +350,9 @@ namespace DotNetOpenAuth.Test.OpenId { }; coordinator.Run(); - var associationManagerAccessor = AssociationManager_Accessor.AttachShadow(coordinator.RelyingParty.AssociationManager); - if (expectSuccess) { Assert.IsNotNull(rpAssociation); - Assert.AreSame(rpAssociation, associationManagerAccessor.associationStore.GetAssociation(opDescription.Uri, rpAssociation.Handle)); + Assert.AreSame(rpAssociation, coordinator.RelyingParty.AssociationManager.AssociationStoreTestHook.GetAssociation(opDescription.Uri, rpAssociation.Handle)); opAssociation = coordinator.Provider.AssociationStore.GetAssociation(AssociationRelyingPartyType.Smart, rpAssociation.Handle); Assert.IsNotNull(opAssociation, "The Provider should have stored the association."); @@ -375,7 +371,7 @@ namespace DotNetOpenAuth.Test.OpenId { var unencryptedResponse = (AssociateUnencryptedResponse)associateSuccessfulResponse; } } else { - Assert.IsNull(associationManagerAccessor.associationStore.GetAssociation(opDescription.Uri, new RelyingPartySecuritySettings())); + Assert.IsNull(coordinator.RelyingParty.AssociationManager.AssociationStoreTestHook.GetAssociation(opDescription.Uri, new RelyingPartySecuritySettings())); Assert.IsNull(coordinator.Provider.AssociationStore.GetAssociation(AssociationRelyingPartyType.Smart, new ProviderSecuritySettings())); } } diff --git a/src/DotNetOpenAuth.Test/OpenId/ChannelElements/OpenIdChannelTests.cs b/src/DotNetOpenAuth.Test/OpenId/ChannelElements/OpenIdChannelTests.cs index 97a40e8..eaaef34 100644 --- a/src/DotNetOpenAuth.Test/OpenId/ChannelElements/OpenIdChannelTests.cs +++ b/src/DotNetOpenAuth.Test/OpenId/ChannelElements/OpenIdChannelTests.cs @@ -24,14 +24,12 @@ namespace DotNetOpenAuth.Test.OpenId.ChannelElements { public class OpenIdChannelTests : TestBase { private static readonly TimeSpan maximumMessageAge = TimeSpan.FromHours(3); // good for tests, too long for production private OpenIdChannel channel; - private OpenIdChannel_Accessor accessor; private Mocks.TestWebRequestHandler webHandler; [SetUp] public void Setup() { this.webHandler = new Mocks.TestWebRequestHandler(); this.channel = new OpenIdChannel(new AssociationMemoryStore<Uri>(), new NonceMemoryStore(maximumMessageAge), new RelyingPartySecuritySettings()); - this.accessor = OpenIdChannel_Accessor.AttachShadow(this.channel); this.channel.WebRequestHandler = this.webHandler; } @@ -59,7 +57,7 @@ namespace DotNetOpenAuth.Test.OpenId.ChannelElements { Recipient = new Uri("http://host"), Name = "Andrew", }; - HttpWebRequest httpRequest = this.accessor.CreateHttpRequest(requestMessage); + HttpWebRequest httpRequest = this.channel.CreateHttpRequestTestHook(requestMessage); Assert.AreEqual("POST", httpRequest.Method); StringAssert.Contains("Name=Andrew", this.webHandler.RequestEntityAsString); } @@ -78,9 +76,9 @@ namespace DotNetOpenAuth.Test.OpenId.ChannelElements { IProtocolMessage message = MessagingTestBase.GetStandardTestMessage(MessagingTestBase.FieldFill.AllRequired); MessageDictionary messageFields = this.MessageDescriptions.GetAccessor(message); byte[] expectedBytes = KeyValueFormEncoding.GetBytes(messageFields); - string expectedContentType = OpenIdChannel_Accessor.KeyValueFormContentType; + string expectedContentType = OpenIdChannel.KeyValueFormContentType; - OutgoingWebResponse directResponse = this.accessor.PrepareDirectResponse(message); + OutgoingWebResponse directResponse = this.channel.PrepareDirectResponseTestHook(message); Assert.AreEqual(expectedContentType, directResponse.Headers[HttpResponseHeader.ContentType]); byte[] actualBytes = new byte[directResponse.ResponseStream.Length]; directResponse.ResponseStream.Read(actualBytes, 0, actualBytes.Length); @@ -99,7 +97,7 @@ namespace DotNetOpenAuth.Test.OpenId.ChannelElements { var response = new CachedDirectWebResponse { CachedResponseStream = new MemoryStream(KeyValueFormEncoding.GetBytes(fields)), }; - Assert.IsTrue(MessagingUtilities.AreEquivalent(fields, this.accessor.ReadFromResponseCore(response))); + Assert.IsTrue(MessagingUtilities.AreEquivalent(fields, this.channel.ReadFromResponseCoreTestHook(response))); } /// <summary> @@ -108,13 +106,13 @@ namespace DotNetOpenAuth.Test.OpenId.ChannelElements { [TestCase] public void SendDirectMessageResponseHonorsHttpStatusCodes() { IProtocolMessage message = MessagingTestBase.GetStandardTestMessage(MessagingTestBase.FieldFill.AllRequired); - OutgoingWebResponse directResponse = this.accessor.PrepareDirectResponse(message); + OutgoingWebResponse directResponse = this.channel.PrepareDirectResponseTestHook(message); Assert.AreEqual(HttpStatusCode.OK, directResponse.Status); var httpMessage = new TestDirectResponseMessageWithHttpStatus(); MessagingTestBase.GetStandardTestMessage(MessagingTestBase.FieldFill.AllRequired, httpMessage); httpMessage.HttpStatusCode = HttpStatusCode.NotAcceptable; - directResponse = this.accessor.PrepareDirectResponse(httpMessage); + directResponse = this.channel.PrepareDirectResponseTestHook(httpMessage); Assert.AreEqual(HttpStatusCode.NotAcceptable, directResponse.Status); } } diff --git a/src/DotNetOpenAuth.Test/OpenId/Extensions/ExtensionsInteropHelperOPTests.cs b/src/DotNetOpenAuth.Test/OpenId/Extensions/ExtensionsInteropHelperOPTests.cs index 1b1dd49..bcafc41 100644 --- a/src/DotNetOpenAuth.Test/OpenId/Extensions/ExtensionsInteropHelperOPTests.cs +++ b/src/DotNetOpenAuth.Test/OpenId/Extensions/ExtensionsInteropHelperOPTests.cs @@ -132,8 +132,8 @@ namespace DotNetOpenAuth.Test.OpenId.Extensions { private void ParameterizedAXTest(AXAttributeFormats format) { var axInjected = new FetchRequest(); - axInjected.Attributes.AddOptional(ExtensionsInteropHelper_Accessor.TransformAXFormat(WellKnownAttributes.Name.Alias, format)); - axInjected.Attributes.AddRequired(ExtensionsInteropHelper_Accessor.TransformAXFormat(WellKnownAttributes.Name.FullName, format)); + axInjected.Attributes.AddOptional(ExtensionsInteropHelper.TransformAXFormatTestHook(WellKnownAttributes.Name.Alias, format)); + axInjected.Attributes.AddRequired(ExtensionsInteropHelper.TransformAXFormatTestHook(WellKnownAttributes.Name.FullName, format)); this.extensions.Add(axInjected); var sreg = ExtensionsInteropHelper.UnifyExtensionsAsSreg(this.request); Assert.AreSame(sreg, this.request.GetExtension<ClaimsRequest>()); @@ -147,7 +147,7 @@ namespace DotNetOpenAuth.Test.OpenId.Extensions { ExtensionsInteropHelper.ConvertSregToMatchRequest(this.request); var extensions = this.GetResponseExtensions(); var axResponse = extensions.OfType<FetchResponse>().Single(); - Assert.AreEqual("andy", axResponse.GetAttributeValue(ExtensionsInteropHelper_Accessor.TransformAXFormat(WellKnownAttributes.Name.Alias, format))); + Assert.AreEqual("andy", axResponse.GetAttributeValue(ExtensionsInteropHelper.TransformAXFormatTestHook(WellKnownAttributes.Name.Alias, format))); } } } diff --git a/src/DotNetOpenAuth.Test/OpenId/Extensions/ExtensionsInteropHelperRPRequestTests.cs b/src/DotNetOpenAuth.Test/OpenId/Extensions/ExtensionsInteropHelperRPRequestTests.cs index 44a629a..d477e9b 100644 --- a/src/DotNetOpenAuth.Test/OpenId/Extensions/ExtensionsInteropHelperRPRequestTests.cs +++ b/src/DotNetOpenAuth.Test/OpenId/Extensions/ExtensionsInteropHelperRPRequestTests.cs @@ -76,8 +76,8 @@ namespace DotNetOpenAuth.Test.OpenId.Extensions { ExtensionsInteropHelper.SpreadSregToAX(this.authReq, AXAttributeFormats.AXSchemaOrg | AXAttributeFormats.SchemaOpenIdNet); var ax = this.authReq.AppliedExtensions.OfType<FetchRequest>().Single(); Assert.IsTrue(ax.Attributes.Contains(WellKnownAttributes.Name.Alias)); - Assert.IsTrue(ax.Attributes.Contains(ExtensionsInteropHelper_Accessor.TransformAXFormat(WellKnownAttributes.Name.Alias, AXAttributeFormats.SchemaOpenIdNet))); - Assert.IsFalse(ax.Attributes.Contains(ExtensionsInteropHelper_Accessor.TransformAXFormat(WellKnownAttributes.Name.Alias, AXAttributeFormats.OpenIdNetSchema))); + Assert.IsTrue(ax.Attributes.Contains(ExtensionsInteropHelper.TransformAXFormatTestHook(WellKnownAttributes.Name.Alias, AXAttributeFormats.SchemaOpenIdNet))); + Assert.IsFalse(ax.Attributes.Contains(ExtensionsInteropHelper.TransformAXFormatTestHook(WellKnownAttributes.Name.Alias, AXAttributeFormats.OpenIdNetSchema))); } /// <summary> @@ -100,7 +100,7 @@ namespace DotNetOpenAuth.Test.OpenId.Extensions { this.InjectAdvertisedTypeUri(WellKnownAttributes.Name.FullName); ExtensionsInteropHelper.SpreadSregToAX(this.authReq, AXAttributeFormats.OpenIdNetSchema); var ax = this.authReq.AppliedExtensions.OfType<FetchRequest>().Single(); - Assert.IsFalse(ax.Attributes.Contains(ExtensionsInteropHelper_Accessor.TransformAXFormat(WellKnownAttributes.Contact.Email, AXAttributeFormats.OpenIdNetSchema))); + Assert.IsFalse(ax.Attributes.Contains(ExtensionsInteropHelper.TransformAXFormatTestHook(WellKnownAttributes.Contact.Email, AXAttributeFormats.OpenIdNetSchema))); Assert.IsTrue(ax.Attributes.Contains(WellKnownAttributes.Contact.Email)); } @@ -109,9 +109,9 @@ namespace DotNetOpenAuth.Test.OpenId.Extensions { /// </summary> [TestCase] public void TransformAXFormatTest() { - Assert.AreEqual(WellKnownAttributes.Name.Alias, ExtensionsInteropHelper_Accessor.TransformAXFormat(WellKnownAttributes.Name.Alias, AXAttributeFormats.AXSchemaOrg)); - Assert.AreEqual("http://schema.openid.net/namePerson/friendly", ExtensionsInteropHelper_Accessor.TransformAXFormat(WellKnownAttributes.Name.Alias, AXAttributeFormats.SchemaOpenIdNet)); - Assert.AreEqual("http://openid.net/schema/namePerson/friendly", ExtensionsInteropHelper_Accessor.TransformAXFormat(WellKnownAttributes.Name.Alias, AXAttributeFormats.OpenIdNetSchema)); + Assert.AreEqual(WellKnownAttributes.Name.Alias, ExtensionsInteropHelper.TransformAXFormatTestHook(WellKnownAttributes.Name.Alias, AXAttributeFormats.AXSchemaOrg)); + Assert.AreEqual("http://schema.openid.net/namePerson/friendly", ExtensionsInteropHelper.TransformAXFormatTestHook(WellKnownAttributes.Name.Alias, AXAttributeFormats.SchemaOpenIdNet)); + Assert.AreEqual("http://openid.net/schema/namePerson/friendly", ExtensionsInteropHelper.TransformAXFormatTestHook(WellKnownAttributes.Name.Alias, AXAttributeFormats.OpenIdNetSchema)); } /// <summary> diff --git a/src/DotNetOpenAuth.Test/OpenId/Extensions/ExtensionsInteropHelperRPResponseTests.cs b/src/DotNetOpenAuth.Test/OpenId/Extensions/ExtensionsInteropHelperRPResponseTests.cs index 7b528d0..e7db6e6 100644 --- a/src/DotNetOpenAuth.Test/OpenId/Extensions/ExtensionsInteropHelperRPResponseTests.cs +++ b/src/DotNetOpenAuth.Test/OpenId/Extensions/ExtensionsInteropHelperRPResponseTests.cs @@ -74,7 +74,7 @@ namespace DotNetOpenAuth.Test.OpenId.Extensions { [TestCase] public void UnifyExtensionsasSregFromSchemaOpenIdNet() { var axInjected = new FetchResponse(); - axInjected.Attributes.Add(ExtensionsInteropHelper_Accessor.TransformAXFormat(WellKnownAttributes.Name.Alias, AXAttributeFormats.SchemaOpenIdNet), "nate"); + axInjected.Attributes.Add(ExtensionsInteropHelper.TransformAXFormatTestHook(WellKnownAttributes.Name.Alias, AXAttributeFormats.SchemaOpenIdNet), "nate"); this.extensions.Add(axInjected); var sreg = ExtensionsInteropHelper.UnifyExtensionsAsSreg(this.response, true); Assert.AreEqual("nate", sreg.Nickname); diff --git a/src/DotNetOpenAuth.Test/OpenId/Messages/IndirectSignedResponseTests.cs b/src/DotNetOpenAuth.Test/OpenId/Messages/IndirectSignedResponseTests.cs index ad6b15d..406a48b 100644 --- a/src/DotNetOpenAuth.Test/OpenId/Messages/IndirectSignedResponseTests.cs +++ b/src/DotNetOpenAuth.Test/OpenId/Messages/IndirectSignedResponseTests.cs @@ -63,25 +63,23 @@ namespace DotNetOpenAuth.Test.OpenId.Messages { [TestCase] public void ResponseNonceSetter() { const string HybridValue = CreationDateString + "UNIQUE"; - var responseAccessor = IndirectSignedResponse_Accessor.AttachShadow(this.response); IReplayProtectedProtocolMessage responseReplay = this.response; - responseAccessor.ResponseNonce = HybridValue; - Assert.AreEqual(HybridValue, responseAccessor.ResponseNonce); + this.response.ResponseNonceTestHook = HybridValue; + Assert.AreEqual(HybridValue, this.response.ResponseNonceTestHook); Assert.AreEqual(this.creationDate, responseReplay.UtcCreationDate); Assert.AreEqual("UNIQUE", responseReplay.Nonce); - responseAccessor.ResponseNonce = null; + this.response.ResponseNonceTestHook = null; Assert.IsNull(responseReplay.Nonce); } [TestCase] public void ResponseNonceGetter() { - var responseAccessor = IndirectSignedResponse_Accessor.AttachShadow(this.response); IReplayProtectedProtocolMessage responseReplay = this.response; responseReplay.Nonce = "UnIqUe"; responseReplay.UtcCreationDate = this.creationDate; - Assert.AreEqual(CreationDateString + "UnIqUe", responseAccessor.ResponseNonce); + Assert.AreEqual(CreationDateString + "UnIqUe", this.response.ResponseNonceTestHook); Assert.AreEqual("UnIqUe", responseReplay.Nonce); Assert.AreEqual(this.creationDate, responseReplay.UtcCreationDate); } diff --git a/src/DotNetOpenAuth.Test/OpenId/OpenIdTestBase.cs b/src/DotNetOpenAuth.Test/OpenId/OpenIdTestBase.cs index c7df99a..414585f 100644 --- a/src/DotNetOpenAuth.Test/OpenId/OpenIdTestBase.cs +++ b/src/DotNetOpenAuth.Test/OpenId/OpenIdTestBase.cs @@ -89,11 +89,9 @@ namespace DotNetOpenAuth.Test.OpenId { /// <param name="providerEndpoint">The provider endpoint.</param> /// <param name="association">The association.</param> internal static void StoreAssociation(OpenIdRelyingParty relyingParty, Uri providerEndpoint, Association association) { - var associationManagerAccessor = AssociationManager_Accessor.AttachShadow(relyingParty.AssociationManager); - // Only store the association if the RP is not in stateless mode. - if (associationManagerAccessor.associationStore != null) { - associationManagerAccessor.associationStore.StoreAssociation(providerEndpoint, association); + if (relyingParty.AssociationManager.AssociationStoreTestHook != null) { + relyingParty.AssociationManager.AssociationStoreTestHook.StoreAssociation(providerEndpoint, association); } } diff --git a/src/DotNetOpenAuth.Test/OpenId/Provider/AuthenticationRequestTest.cs b/src/DotNetOpenAuth.Test/OpenId/Provider/AuthenticationRequestTest.cs index dc5b3e3..39b4355 100644 --- a/src/DotNetOpenAuth.Test/OpenId/Provider/AuthenticationRequestTest.cs +++ b/src/DotNetOpenAuth.Test/OpenId/Provider/AuthenticationRequestTest.cs @@ -35,8 +35,8 @@ namespace DotNetOpenAuth.Test.OpenId.Provider { // Now construct a new request as if it had just come in. HttpRequestInfo httpRequest = new HttpRequestInfo { UrlBeforeRewriting = userSetupUrl }; - var setupRequest = AuthenticationRequest_Accessor.AttachShadow(provider.GetRequest(httpRequest)); - CheckIdRequest_Accessor setupRequestMessage = setupRequest.RequestMessage; + var setupRequest = (AuthenticationRequest)provider.GetRequest(httpRequest); + var setupRequestMessage = (CheckIdRequest)setupRequest.RequestMessage; // And make sure all the right properties are set. Assert.IsFalse(setupRequestMessage.Immediate); diff --git a/src/DotNetOpenAuth.Test/OpenId/RelyingParty/AuthenticationRequestTests.cs b/src/DotNetOpenAuth.Test/OpenId/RelyingParty/AuthenticationRequestTests.cs index 001f3fa..793669a 100644 --- a/src/DotNetOpenAuth.Test/OpenId/RelyingParty/AuthenticationRequestTests.cs +++ b/src/DotNetOpenAuth.Test/OpenId/RelyingParty/AuthenticationRequestTests.cs @@ -86,8 +86,8 @@ namespace DotNetOpenAuth.Test.OpenId.RelyingParty { authRequest.AddExtension(sregRequest); // Construct the actual authentication request message. - var authRequestAccessor = AuthenticationRequest_Accessor.AttachShadow(authRequest); - var req = authRequestAccessor.CreateRequestMessage(); + var authRequestAccessor = (AuthenticationRequest)authRequest; + var req = authRequestAccessor.CreateRequestMessageTestHook(); Assert.IsNotNull(req); // Verify that callback arguments were included. diff --git a/src/DotNetOpenAuth.Test/OpenId/RelyingParty/PositiveAuthenticationResponseTests.cs b/src/DotNetOpenAuth.Test/OpenId/RelyingParty/PositiveAuthenticationResponseTests.cs index 25b0607..fc7ed0f 100644 --- a/src/DotNetOpenAuth.Test/OpenId/RelyingParty/PositiveAuthenticationResponseTests.cs +++ b/src/DotNetOpenAuth.Test/OpenId/RelyingParty/PositiveAuthenticationResponseTests.cs @@ -35,7 +35,6 @@ namespace DotNetOpenAuth.Test.OpenId.RelyingParty { assertion.Extensions.Add(extension); var rp = CreateRelyingParty(); var authResponse = new PositiveAuthenticationResponse(assertion, rp); - var authResponseAccessor = PositiveAuthenticationResponse_Accessor.AttachShadow(authResponse); Assert.AreEqual(AuthenticationStatus.Authenticated, authResponse.Status); Assert.IsNull(authResponse.Exception); Assert.AreEqual((string)assertion.ClaimedIdentifier, (string)authResponse.ClaimedIdentifier); diff --git a/src/DotNetOpenAuth.Test/OpenId/UriIdentifierTests.cs b/src/DotNetOpenAuth.Test/OpenId/UriIdentifierTests.cs index eeb579c..e6bed2f 100644 --- a/src/DotNetOpenAuth.Test/OpenId/UriIdentifierTests.cs +++ b/src/DotNetOpenAuth.Test/OpenId/UriIdentifierTests.cs @@ -301,14 +301,14 @@ namespace DotNetOpenAuth.Test.OpenId { private static void TestAsFullAndPartialTrust(Action<bool> action) { // Test a bunch of interesting URLs both with scheme substitution on and off. - Assert.IsTrue(UriIdentifier_Accessor.schemeSubstitution, "Expected scheme substitution to be working."); + Assert.IsTrue(UriIdentifier.SchemeSubstitutionTestHook, "Expected scheme substitution to be working."); action(true); - UriIdentifier_Accessor.schemeSubstitution = false; + UriIdentifier.SchemeSubstitutionTestHook = false; try { action(false); } finally { - UriIdentifier_Accessor.schemeSubstitution = true; + UriIdentifier.SchemeSubstitutionTestHook = true; } } } diff --git a/src/DotNetOpenAuth/Messaging/Channel.cs b/src/DotNetOpenAuth/Messaging/Channel.cs index cc411c8..3d56f02 100644 --- a/src/DotNetOpenAuth/Messaging/Channel.cs +++ b/src/DotNetOpenAuth/Messaging/Channel.cs @@ -163,6 +163,14 @@ namespace DotNetOpenAuth.Messaging { } /// <summary> + /// Gets a tool that can figure out what kind of message is being received + /// so it can be deserialized. + /// </summary> + internal IMessageFactory MessageFactoryTestHook { + get { return this.MessageFactory; } + } + + /// <summary> /// Gets the binding elements used by this channel, in no particular guaranteed order. /// </summary> protected internal ReadOnlyCollection<IChannelBindingElement> BindingElements { @@ -444,6 +452,66 @@ namespace DotNetOpenAuth.Messaging { #endregion /// <summary> + /// Verifies the integrity and applicability of an incoming message. + /// </summary> + /// <param name="message">The message just received.</param> + /// <exception cref="ProtocolException"> + /// Thrown when the message is somehow invalid. + /// This can be due to tampering, replay attack or expiration, among other things. + /// </exception> + internal void ProcessIncomingMessageTestHook(IProtocolMessage message) { + this.ProcessIncomingMessage(message); + } + + /// <summary> + /// Prepares an HTTP request that carries a given message. + /// </summary> + /// <param name="request">The message to send.</param> + /// <returns>The <see cref="HttpWebRequest"/> prepared to send the request.</returns> + /// <remarks> + /// This method must be overridden by a derived class, unless the <see cref="RequestCore"/> method + /// is overridden and does not require this method. + /// </remarks> + internal HttpWebRequest CreateHttpRequestTestHook(IDirectedProtocolMessage request) { + return this.CreateHttpRequest(request); + } + + /// <summary> + /// Queues a message for sending in the response stream where the fields + /// are sent in the response stream in querystring style. + /// </summary> + /// <param name="response">The message to send as a response.</param> + /// <returns>The pending user agent redirect based message to be sent as an HttpResponse.</returns> + /// <remarks> + /// This method implements spec OAuth V1.0 section 5.3. + /// </remarks> + internal OutgoingWebResponse PrepareDirectResponseTestHook(IProtocolMessage response) { + return this.PrepareDirectResponse(response); + } + + /// <summary> + /// Gets the protocol message that may be in the given HTTP response. + /// </summary> + /// <param name="response">The response that is anticipated to contain an protocol message.</param> + /// <returns>The deserialized message parts, if found. Null otherwise.</returns> + /// <exception cref="ProtocolException">Thrown when the response is not valid.</exception> + internal IDictionary<string, string> ReadFromResponseCoreTestHook(IncomingWebResponse response) { + return this.ReadFromResponseCore(response); + } + + /// <remarks> + /// This method should NOT be called by derived types + /// except when sending ONE WAY request messages. + /// </remarks> + /// <summary> + /// Prepares a message for transmit by applying signatures, nonces, etc. + /// </summary> + /// <param name="message">The message to prepare for sending.</param> + internal void ProcessOutgoingMessageTestHook(IProtocolMessage message) { + this.ProcessOutgoingMessage(message); + } + + /// <summary> /// Gets the current HTTP request being processed. /// </summary> /// <returns>The HttpRequestInfo for the current request.</returns> diff --git a/src/DotNetOpenAuth/OAuth/ChannelElements/SigningBindingElementBase.cs b/src/DotNetOpenAuth/OAuth/ChannelElements/SigningBindingElementBase.cs index cf09036..fdf6e08 100644 --- a/src/DotNetOpenAuth/OAuth/ChannelElements/SigningBindingElementBase.cs +++ b/src/DotNetOpenAuth/OAuth/ChannelElements/SigningBindingElementBase.cs @@ -234,6 +234,18 @@ namespace DotNetOpenAuth.OAuth.ChannelElements { } /// <summary> + /// Calculates a signature for a given message. + /// </summary> + /// <param name="message">The message to sign.</param> + /// <returns>The signature for the message.</returns> + /// <remarks> + /// This method signs the message per OAuth 1.0 section 9.2. + /// </remarks> + internal string GetSignatureTestHook(ITamperResistantOAuthMessage message) { + return this.GetSignature(message); + } + + /// <summary> /// Gets the "ConsumerSecret&TokenSecret" string, allowing either property to be empty or null. /// </summary> /// <param name="message">The message to extract the secrets from.</param> diff --git a/src/DotNetOpenAuth/OpenId/ChannelElements/OpenIdChannel.cs b/src/DotNetOpenAuth/OpenId/ChannelElements/OpenIdChannel.cs index b25e819..bc613ed 100644 --- a/src/DotNetOpenAuth/OpenId/ChannelElements/OpenIdChannel.cs +++ b/src/DotNetOpenAuth/OpenId/ChannelElements/OpenIdChannel.cs @@ -35,7 +35,7 @@ namespace DotNetOpenAuth.OpenId.ChannelElements { /// to the end of the direct response, corrupting the data. So we deviate /// from the spec a bit here to improve the story for free Providers. /// </remarks> - private const string KeyValueFormContentType = "application/x-openid-kvf"; + internal const string KeyValueFormContentType = "application/x-openid-kvf"; /// <summary> /// The encoder that understands how to read and write Key-Value Form. diff --git a/src/DotNetOpenAuth/OpenId/Extensions/ExtensionsInteropHelper.cs b/src/DotNetOpenAuth/OpenId/Extensions/ExtensionsInteropHelper.cs index 1b58c2f..5e1003a 100644 --- a/src/DotNetOpenAuth/OpenId/Extensions/ExtensionsInteropHelper.cs +++ b/src/DotNetOpenAuth/OpenId/Extensions/ExtensionsInteropHelper.cs @@ -234,6 +234,16 @@ namespace DotNetOpenAuth.OpenId.Extensions { } /// <summary> + /// Transforms an AX attribute type URI from the axschema.org format into a given format. + /// </summary> + /// <param name="axSchemaOrgFormatTypeUri">The ax schema org format type URI.</param> + /// <param name="targetFormat">The target format. Only one flag should be set.</param> + /// <returns>The AX attribute type URI in the target format.</returns> + internal static string TransformAXFormatTestHook(string axSchemaOrgFormatTypeUri, AXAttributeFormats targetFormat) { + return TransformAXFormat(axSchemaOrgFormatTypeUri, targetFormat); + } + + /// <summary> /// Adds the AX attribute value to the response if it is non-empty. /// </summary> /// <param name="ax">The AX Fetch response to add the attribute value to.</param> diff --git a/src/DotNetOpenAuth/OpenId/Messages/IndirectSignedResponse.cs b/src/DotNetOpenAuth/OpenId/Messages/IndirectSignedResponse.cs index fff4cf6..776b28b 100644 --- a/src/DotNetOpenAuth/OpenId/Messages/IndirectSignedResponse.cs +++ b/src/DotNetOpenAuth/OpenId/Messages/IndirectSignedResponse.cs @@ -272,6 +272,29 @@ namespace DotNetOpenAuth.OpenId.Messages { /// </list> /// </value> /// <example>2005-05-15T17:11:51ZUNIQUE</example> + internal string ResponseNonceTestHook { + get { return this.ResponseNonce; } + set { this.ResponseNonce = value; } + } + + /// <summary> + /// Gets or sets the nonce that will protect the message from replay attacks. + /// </summary> + /// <value> + /// <para>A string 255 characters or less in length, that MUST be unique to + /// this particular successful authentication response. The nonce MUST start + /// with the current time on the server, and MAY contain additional ASCII + /// characters in the range 33-126 inclusive (printable non-whitespace characters), + /// as necessary to make each response unique. The date and time MUST be + /// formatted as specified in section 5.6 of [RFC3339] + /// (Klyne, G. and C. Newman, “Date and Time on the Internet: Timestamps,” .), + /// with the following restrictions:</para> + /// <list type="bullet"> + /// <item>All times must be in the UTC timezone, indicated with a "Z".</item> + /// <item>No fractional seconds are allowed</item> + /// </list> + /// </value> + /// <example>2005-05-15T17:11:51ZUNIQUE</example> [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Justification = "Called by messaging framework via reflection.")] [MessagePart("openid.response_nonce", IsRequired = true, AllowEmpty = false, RequiredProtection = ProtectionLevel.Sign, MinVersion = "2.0")] [MessagePart("openid.response_nonce", IsRequired = false, AllowEmpty = false, RequiredProtection = ProtectionLevel.None, MaxVersion = "1.1")] diff --git a/src/DotNetOpenAuth/OpenId/Provider/AutoResponsiveRequest.cs b/src/DotNetOpenAuth/OpenId/Provider/AutoResponsiveRequest.cs index e5988dd..41e082b 100644 --- a/src/DotNetOpenAuth/OpenId/Provider/AutoResponsiveRequest.cs +++ b/src/DotNetOpenAuth/OpenId/Provider/AutoResponsiveRequest.cs @@ -64,6 +64,13 @@ namespace DotNetOpenAuth.OpenId.Provider { /// <summary> /// Gets the response message, once <see cref="IsResponseReady"/> is <c>true</c>. /// </summary> + internal IProtocolMessage ResponseMessageTestHook { + get { return this.ResponseMessage; } + } + + /// <summary> + /// Gets the response message, once <see cref="IsResponseReady"/> is <c>true</c>. + /// </summary> protected override IProtocolMessage ResponseMessage { get { return this.response; } } diff --git a/src/DotNetOpenAuth/OpenId/RelyingParty/AssociationManager.cs b/src/DotNetOpenAuth/OpenId/RelyingParty/AssociationManager.cs index ac70387..1ae2726 100644 --- a/src/DotNetOpenAuth/OpenId/RelyingParty/AssociationManager.cs +++ b/src/DotNetOpenAuth/OpenId/RelyingParty/AssociationManager.cs @@ -91,6 +91,13 @@ namespace DotNetOpenAuth.OpenId.RelyingParty { } /// <summary> + /// Gets the storage to use for saving and retrieving associations. May be null. + /// </summary> + internal IAssociationStore<Uri> AssociationStoreTestHook { + get { return this.associationStore; } + } + + /// <summary> /// Gets an association between this Relying Party and a given Provider /// if it already exists in the association store. /// </summary> diff --git a/src/DotNetOpenAuth/OpenId/RelyingParty/AuthenticationRequest.cs b/src/DotNetOpenAuth/OpenId/RelyingParty/AuthenticationRequest.cs index 09383bb..c2472e0 100644 --- a/src/DotNetOpenAuth/OpenId/RelyingParty/AuthenticationRequest.cs +++ b/src/DotNetOpenAuth/OpenId/RelyingParty/AuthenticationRequest.cs @@ -398,6 +398,16 @@ namespace DotNetOpenAuth.OpenId.RelyingParty { } /// <summary> + /// Creates the request message to send to the Provider, + /// based on the properties in this instance. + /// </summary> + /// <returns>The message to send to the Provider.</returns> + internal SignedResponseRequest CreateRequestMessageTestHook() + { + return this.CreateRequestMessage(); + } + + /// <summary> /// Performs deferred request generation for the <see cref="Create"/> method. /// </summary> /// <param name="userSuppliedIdentifier">The user supplied identifier.</param> diff --git a/src/DotNetOpenAuth/OpenId/UriIdentifier.cs b/src/DotNetOpenAuth/OpenId/UriIdentifier.cs index f5ecd4f..48ed7f2 100644 --- a/src/DotNetOpenAuth/OpenId/UriIdentifier.cs +++ b/src/DotNetOpenAuth/OpenId/UriIdentifier.cs @@ -156,6 +156,16 @@ namespace DotNetOpenAuth.OpenId { } /// <summary> + /// Gets or sets a value indicating whether scheme substitution is being used to workaround + /// .NET path compression that invalidates some OpenIDs that have trailing periods + /// in one of their path segments. + /// </summary> + internal static bool SchemeSubstitutionTestHook { + get { return schemeSubstitution; } + set { schemeSubstitution = value; } + } + + /// <summary> /// Gets the URI this instance represents. /// </summary> internal Uri Uri { get; private set; } |