//----------------------------------------------------------------------- // // Copyright (c) Andrew Arnott. All rights reserved. // //----------------------------------------------------------------------- namespace DotNetOAuth.ChannelElements { using System; using System.Collections.Generic; using System.Linq; using System.Text; using DotNetOAuth.Messaging; /// /// A tamper protection applying binding element that can use any of several given /// binding elements to apply the protection. /// internal class SigningBindingElementChain : ITamperProtectionChannelBindingElement { /// /// The various signing binding elements that may be applicable to a message in preferred use order. /// private ITamperProtectionChannelBindingElement[] signers; /// /// Initializes a new instance of the class. /// /// /// The signing binding elements that may be used for some outgoing message, /// in preferred use order. /// internal SigningBindingElementChain(ITamperProtectionChannelBindingElement[] signers) { if (signers == null) { throw new ArgumentNullException("signers"); } if (signers.Length == 0) { throw new ArgumentException(MessagingStrings.SequenceContainsNoElements, "signers"); } if (signers.Contains(null)) { throw new ArgumentException(MessagingStrings.SequenceContainsNullElement, "signers"); } MessageProtection protection = signers[0].Protection; if (signers.Any(element => element.Protection != protection)) { throw new ArgumentException(Strings.SigningElementsMustShareSameProtection, "signers"); } this.signers = signers; } #region ITamperProtectionChannelBindingElement Members /// /// Gets or sets the delegate that will initialize the non-serialized properties necessary on a signed /// message so that its signature can be correctly calculated for verification. /// May be null for Consumers (who never have to verify signatures). /// public Action SignatureVerificationCallback { get { return this.signers[0].SignatureVerificationCallback; } set { foreach (ITamperProtectionChannelBindingElement signer in this.signers) { signer.SignatureVerificationCallback = value; } } } #endregion #region IChannelBindingElement Members /// /// Gets the protection offered (if any) by this binding element. /// public MessageProtection Protection { get { return this.signers[0].Protection; } } /// /// Prepares a message for sending based on the rules of this channel binding element. /// /// The message to prepare for sending. /// /// True if the applied to this binding element /// and the operation was successful. False otherwise. /// public bool PrepareMessageForSending(IProtocolMessage message) { foreach (IChannelBindingElement signer in this.signers) { if (signer.PrepareMessageForSending(message)) { return true; } } return false; } /// /// Performs any transformation on an incoming message that may be necessary and/or /// validates an incoming message based on the rules of this channel binding element. /// /// The incoming message to process. /// /// True if the applied to this binding element /// and the operation was successful. False if the operation did not apply to this message. /// public bool PrepareMessageForReceiving(IProtocolMessage message) { foreach (IChannelBindingElement signer in this.signers) { if (signer.PrepareMessageForReceiving(message)) { return true; } } return false; } #endregion } }