Example #1
0
        /// <summary>
        /// Encodes an HTTP response that will instruct the user agent to forward a message to
        /// some remote third party using a form POST method.
        /// </summary>
        /// <param name="message">The message to forward.</param>
        /// <param name="fields">The pre-serialized fields from the message.</param>
        /// <returns>The encoded HTTP response.</returns>
        protected virtual UserAgentResponse CreateFormPostResponse(IDirectedProtocolMessage message, IDictionary <string, string> fields)
        {
            ErrorUtilities.VerifyArgumentNotNull(message, "message");
            ErrorUtilities.VerifyArgumentNamed(message.Recipient != null, "message", MessagingStrings.DirectedMessageMissingRecipient);
            ErrorUtilities.VerifyArgumentNotNull(fields, "fields");

            WebHeaderCollection headers      = new WebHeaderCollection();
            StringWriter        bodyWriter   = new StringWriter(CultureInfo.InvariantCulture);
            StringBuilder       hiddenFields = new StringBuilder();

            foreach (var field in fields)
            {
                hiddenFields.AppendFormat(
                    "\t<input type=\"hidden\" name=\"{0}\" value=\"{1}\" />\r\n",
                    HttpUtility.HtmlEncode(field.Key),
                    HttpUtility.HtmlEncode(field.Value));
            }
            bodyWriter.WriteLine(
                indirectMessageFormPostFormat,
                HttpUtility.HtmlEncode(message.Recipient.AbsoluteUri),
                hiddenFields);
            bodyWriter.Flush();
            UserAgentResponse response = new UserAgentResponse {
                Status          = HttpStatusCode.OK,
                Headers         = headers,
                Body            = bodyWriter.ToString(),
                OriginalMessage = message
            };

            return(response);
        }
        /// <summary>
        /// Prepares an <see cref="HttpWebRequest"/> that contains an POST entity for sending the entity.
        /// </summary>
        /// <param name="request">The <see cref="HttpWebRequest"/> that should contain the entity.</param>
        /// <param name="options">The options to apply to this web request.</param>
        /// <returns>
        /// The writer the caller should write out the entity data to.
        /// </returns>
        /// <exception cref="ProtocolException">Thrown for any network error.</exception>
        /// <remarks>
        ///     <para>The caller should have set the <see cref="HttpWebRequest.ContentLength"/>
        /// and any other appropriate properties <i>before</i> calling this method.</para>
        ///     <para>Implementations should catch <see cref="WebException"/> and wrap it in a
        /// <see cref="ProtocolException"/> to abstract away the transport and provide
        /// a single exception type for hosts to catch.</para>
        /// </remarks>
        public Stream GetRequestStream(HttpWebRequest request, DirectWebRequestOptions options)
        {
            ErrorUtilities.VerifyArgumentNotNull(request, "request");
            ErrorUtilities.VerifySupported(this.CanSupport(options), MessagingStrings.DirectWebRequestOptionsNotSupported, options, this.GetType().Name);

            return(GetRequestStreamCore(request, options));
        }
Example #3
0
        /// <summary>
        /// Prepares to send a request to the Service Provider as the payload of a POST request.
        /// </summary>
        /// <param name="requestMessage">The message to be transmitted to the ServiceProvider.</param>
        /// <returns>The web request ready to send.</returns>
        /// <remarks>
        /// This method is simply a standard HTTP POST request with the message parts serialized to the POST entity
        /// with the application/x-www-form-urlencoded content type
        /// This method satisfies OAuth 1.0 section 5.2, item #2 and OpenID 2.0 section 4.1.2.
        /// </remarks>
        protected virtual HttpWebRequest InitializeRequestAsPost(IDirectedProtocolMessage requestMessage)
        {
            ErrorUtilities.VerifyArgumentNotNull(requestMessage, "requestMessage");

            var serializer = MessageSerializer.Get(requestMessage.GetType());
            var fields     = serializer.Serialize(requestMessage);

            HttpWebRequest httpRequest = (HttpWebRequest)WebRequest.Create(requestMessage.Recipient);

            httpRequest.CachePolicy = this.CachePolicy;
            httpRequest.Method      = "POST";
            httpRequest.ContentType = "application/x-www-form-urlencoded";
            httpRequest.Headers[HttpRequestHeader.ContentEncoding] = PostEntityEncoding.WebName;
            string requestBody = MessagingUtilities.CreateQueryString(fields);

            byte[] requestBytes = PostEntityEncoding.GetBytes(requestBody);
            httpRequest.ContentLength = requestBytes.Length;
            Stream requestStream = this.WebRequestHandler.GetRequestStream(httpRequest);

            try {
                requestStream.Write(requestBytes, 0, requestBytes.Length);
            } finally {
                // We need to be sure to close the request stream...
                // unless it is a MemoryStream, which is a clue that we're in
                // a mock stream situation and closing it would preclude reading it later.
                if (!(requestStream is MemoryStream))
                {
                    requestStream.Dispose();
                }
            }

            return(httpRequest);
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="CachedDirectWebResponse"/> class.
        /// </summary>
        /// <param name="requestUri">The request URI.</param>
        /// <param name="responseUri">The final URI to respond to the request.</param>
        /// <param name="headers">The headers.</param>
        /// <param name="statusCode">The status code.</param>
        /// <param name="contentType">Type of the content.</param>
        /// <param name="contentEncoding">The content encoding.</param>
        /// <param name="responseStream">The response stream.</param>
        internal CachedDirectWebResponse(Uri requestUri, Uri responseUri, WebHeaderCollection headers, HttpStatusCode statusCode, string contentType, string contentEncoding, MemoryStream responseStream)
            : base(requestUri, responseUri, headers, statusCode, contentType, contentEncoding)
        {
            ErrorUtilities.VerifyArgumentNotNull(responseStream, "responseStream");

            this.responseStream = responseStream;
        }
        internal IDictionary <string, string> Serialize(IMessage message)
        {
            ErrorUtilities.VerifyArgumentNotNull(message, "message");

            var messageDescription = MessageDescription.Get(this.messageType, message.Version);
            var messageDictionary  = new MessageDictionary(message);

            // Rather than hand back the whole message dictionary (which
            // includes keys with blank values), create a new dictionary
            // that only has required keys, and optional keys whose
            // values are not empty.
            var result = new Dictionary <string, string>();

            foreach (var pair in messageDictionary)
            {
                MessagePart partDescription;
                if (messageDescription.Mapping.TryGetValue(pair.Key, out partDescription))
                {
                    if (partDescription.IsRequired || partDescription.IsNondefaultValueSet(message))
                    {
                        result.Add(pair.Key, pair.Value);
                    }
                }
                else
                {
                    // This is extra data.  We always write it out.
                    result.Add(pair.Key, pair.Value);
                }
            }

            return(result);
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="MessageReceivingEndpoint"/> class.
        /// </summary>
        /// <param name="location">The URL of this endpoint.</param>
        /// <param name="method">The HTTP method(s) allowed.</param>
        public MessageReceivingEndpoint(Uri location, HttpDeliveryMethods method)
        {
            ErrorUtilities.VerifyArgumentNotNull(location, "location");
            ErrorUtilities.VerifyArgumentInRange(method != HttpDeliveryMethods.None, "method");
            ErrorUtilities.VerifyArgumentInRange((method & (HttpDeliveryMethods.PostRequest | HttpDeliveryMethods.GetRequest)) != 0, "method", MessagingStrings.GetOrPostFlagsRequired);

            this.Location       = location;
            this.AllowedMethods = method;
        }
Example #7
0
        /// <summary>
        /// Prepares an <see cref="HttpWebRequest"/> that contains an POST entity for sending the entity.
        /// </summary>
        /// <param name="request">The <see cref="HttpWebRequest"/> that should contain the entity.</param>
        /// <param name="options">The options to apply to this web request.</param>
        /// <returns>
        /// The writer the caller should write out the entity data to.
        /// </returns>
        /// <exception cref="ProtocolException">Thrown for any network error.</exception>
        /// <remarks>
        ///     <para>The caller should have set the <see cref="HttpWebRequest.ContentLength"/>
        /// and any other appropriate properties <i>before</i> calling this method.</para>
        ///     <para>Implementations should catch <see cref="WebException"/> and wrap it in a
        /// <see cref="ProtocolException"/> to abstract away the transport and provide
        /// a single exception type for hosts to catch.</para>
        /// </remarks>
        public Stream GetRequestStream(HttpWebRequest request, DirectWebRequestOptions options)
        {
            ErrorUtilities.VerifyArgumentNotNull(request, "request");
            this.EnsureAllowableRequestUri(request.RequestUri, (options & DirectWebRequestOptions.RequireSsl) != 0);

            this.PrepareRequest(request, true);

            // Submit the request and get the request stream back.
            return(this.chainedWebRequestHandler.GetRequestStream(request, options & ~DirectWebRequestOptions.RequireSsl));
        }
        /// <summary>
        /// Creates a snapshot of some stream so it is seekable, and the original can be closed.
        /// </summary>
        /// <param name="copyFrom">The stream to copy bytes from.</param>
        /// <returns>A seekable stream with the same contents as the original.</returns>
        internal static Stream CreateSnapshot(this Stream copyFrom)
        {
            ErrorUtilities.VerifyArgumentNotNull(copyFrom, "copyFrom");

            MemoryStream copyTo = new MemoryStream(copyFrom.CanSeek ? (int)copyFrom.Length : 4 * 1024);

            copyFrom.CopyTo(copyTo);
            copyTo.Position = 0;
            return(copyTo);
        }
Example #9
0
        /// <summary>
        /// Fires the <see cref="Sending"/> event.
        /// </summary>
        /// <param name="message">The message about to be encoded and sent.</param>
        protected virtual void OnSending(IProtocolMessage message)
        {
            ErrorUtilities.VerifyArgumentNotNull(message, "message");

            var sending = this.Sending;

            if (sending != null)
            {
                sending(this, new ChannelEventArgs(message));
            }
        }
Example #10
0
        /// <summary>
        /// Prepares a message for transmit by applying signatures, nonces, etc.
        /// </summary>
        /// <param name="message">The message to prepare for sending.</param>
        /// <remarks>
        /// This method should NOT be called by derived types
        /// except when sending ONE WAY request messages.
        /// </remarks>
        protected void PrepareMessageForSending(IProtocolMessage message)
        {
            ErrorUtilities.VerifyArgumentNotNull(message, "message");

            Logger.DebugFormat("Preparing to send {0} ({1}) message.", message.GetType().Name, message.Version);
            this.OnSending(message);

            // Give the message a chance to do custom serialization.
            IMessageWithEvents eventedMessage = message as IMessageWithEvents;

            if (eventedMessage != null)
            {
                eventedMessage.OnSending();
            }

            MessageProtections appliedProtection = MessageProtections.None;

            foreach (IChannelBindingElement bindingElement in this.outgoingBindingElements)
            {
                if (bindingElement.PrepareMessageForSending(message))
                {
                    Logger.DebugFormat("Binding element {0} applied to message.", bindingElement.GetType().FullName);

                    // Ensure that only one protection binding element applies to this message
                    // for each protection type.
                    ErrorUtilities.VerifyProtocol((appliedProtection & bindingElement.Protection) == 0, MessagingStrings.TooManyBindingsOfferingSameProtection, bindingElement.Protection);
                    appliedProtection |= bindingElement.Protection;
                }
                else
                {
                    Logger.DebugFormat("Binding element {0} did not apply to message.", bindingElement.GetType().FullName);
                }
            }

            // Ensure that the message's protection requirements have been satisfied.
            if ((message.RequiredProtection & appliedProtection) != message.RequiredProtection)
            {
                throw new UnprotectedMessageException(message, appliedProtection);
            }

            EnsureValidMessageParts(message);
            message.EnsureValidMessage();

            if (Logger.IsDebugEnabled)
            {
                Logger.DebugFormat(
                    "Sending {0} ({1}) message: {2}{3}",
                    message.GetType().Name,
                    message.Version,
                    Environment.NewLine,
                    new MessageDictionary(message).ToStringDeferred());
            }
        }
        /// <summary>
        /// Copies some extra parameters into a message.
        /// </summary>
        /// <param name="message">The message to copy the extra data into.</param>
        /// <param name="extraParameters">The extra data to copy into the message.  May be null to do nothing.</param>
        internal static void AddExtraParameters(this IMessage message, IDictionary <string, string> extraParameters)
        {
            ErrorUtilities.VerifyArgumentNotNull(message, "message");

            if (extraParameters != null)
            {
                MessageDictionary messageDictionary = new MessageDictionary(message);
                foreach (var pair in extraParameters)
                {
                    messageDictionary.Add(pair);
                }
            }
        }
Example #12
0
        /// <summary>
        /// Initializes a new instance of the <see cref="UserAgentResponse"/> class
        /// based on the contents of an <see cref="HttpWebResponse"/>.
        /// </summary>
        /// <param name="response">The <see cref="HttpWebResponse"/> to clone.</param>
        /// <param name="maximumBytesToRead">The maximum bytes to read from the response stream.</param>
        protected internal UserAgentResponse(HttpWebResponse response, int maximumBytesToRead)
        {
            ErrorUtilities.VerifyArgumentNotNull(response, "response");

            this.Status         = response.StatusCode;
            this.Headers        = response.Headers;
            this.ResponseStream = new MemoryStream(response.ContentLength < 0 ? 4 * 1024 : (int)response.ContentLength);
            using (Stream responseStream = response.GetResponseStream()) {
                // BUGBUG: strictly speaking, is the response were exactly the limit, we'd report it as truncated here.
                this.IsResponseTruncated = responseStream.CopyTo(this.ResponseStream, maximumBytesToRead) == maximumBytesToRead;
                this.ResponseStream.Seek(0, SeekOrigin.Begin);
            }
        }
Example #13
0
        /// <summary>
        /// Customizes the binding element order for outgoing and incoming messages.
        /// </summary>
        /// <param name="outgoingOrder">The outgoing order.</param>
        /// <param name="incomingOrder">The incoming order.</param>
        /// <remarks>
        /// No binding elements can be added or removed from the channel using this method.
        /// Only a customized order is allowed.
        /// </remarks>
        /// <exception cref="ArgumentException">Thrown if a binding element is new or missing in one of the ordered lists.</exception>
        protected void CustomizeBindingElementOrder(IEnumerable <IChannelBindingElement> outgoingOrder, IEnumerable <IChannelBindingElement> incomingOrder)
        {
            ErrorUtilities.VerifyArgumentNotNull(outgoingOrder, "outgoingOrder");
            ErrorUtilities.VerifyArgumentNotNull(incomingOrder, "incomingOrder");

            ErrorUtilities.VerifyArgument(this.IsBindingElementOrderValid(outgoingOrder), MessagingStrings.InvalidCustomBindingElementOrder);
            ErrorUtilities.VerifyArgument(this.IsBindingElementOrderValid(incomingOrder), MessagingStrings.InvalidCustomBindingElementOrder);

            this.outgoingBindingElements.Clear();
            this.outgoingBindingElements.AddRange(outgoingOrder);
            this.incomingBindingElements.Clear();
            this.incomingBindingElements.AddRange(incomingOrder);
        }
 /// <summary>
 /// Initializes a new instance of the <see cref="DirectWebResponse"/> class.
 /// </summary>
 /// <param name="requestUri">The request URI.</param>
 /// <param name="responseUri">The final URI to respond to the request.</param>
 /// <param name="headers">The headers.</param>
 /// <param name="statusCode">The status code.</param>
 /// <param name="contentType">Type of the content.</param>
 /// <param name="contentEncoding">The content encoding.</param>
 protected DirectWebResponse(Uri requestUri, Uri responseUri, WebHeaderCollection headers, HttpStatusCode statusCode, string contentType, string contentEncoding)
 {
     ErrorUtilities.VerifyArgumentNotNull(requestUri, "requestUri");
     this.RequestUri = requestUri;
     this.Status     = statusCode;
     if (!string.IsNullOrEmpty(contentType))
     {
         this.ContentType = new ContentType(contentType);
     }
     this.ContentEncoding = string.IsNullOrEmpty(contentEncoding) ? DefaultContentEncoding : contentEncoding;
     this.Headers         = headers;
     this.FinalUri        = responseUri;
 }
Example #15
0
        /// <summary>
        /// Prepares to send a request to the Service Provider as the query string in a GET request.
        /// </summary>
        /// <param name="requestMessage">The message to be transmitted to the ServiceProvider.</param>
        /// <returns>The web request ready to send.</returns>
        /// <remarks>
        /// This method is simply a standard HTTP Get request with the message parts serialized to the query string.
        /// This method satisfies OAuth 1.0 section 5.2, item #3.
        /// </remarks>
        protected virtual HttpWebRequest InitializeRequestAsGet(IDirectedProtocolMessage requestMessage)
        {
            ErrorUtilities.VerifyArgumentNotNull(requestMessage, "requestMessage");

            var serializer = MessageSerializer.Get(requestMessage.GetType());
            var fields     = serializer.Serialize(requestMessage);

            UriBuilder builder = new UriBuilder(requestMessage.Recipient);

            MessagingUtilities.AppendQueryArgs(builder, fields);
            HttpWebRequest httpRequest = (HttpWebRequest)WebRequest.Create(builder.Uri);

            return(httpRequest);
        }
        /// <summary>
        /// Prepares an HTTP request.
        /// </summary>
        /// <param name="request">The request.</param>
        /// <param name="preparingPost"><c>true</c> if this is a POST request whose headers have not yet been sent out; <c>false</c> otherwise.</param>
        private static void PrepareRequest(HttpWebRequest request, bool preparingPost)
        {
            ErrorUtilities.VerifyArgumentNotNull(request, "request");

            // Be careful to not try to change the HTTP headers that have already gone out.
            if (preparingPost || request.Method == "GET")
            {
                // Some sites, such as Technorati, return 403 Forbidden on identity
                // pages unless a User-Agent header is included.
                if (string.IsNullOrEmpty(request.UserAgent))
                {
                    request.UserAgent = userAgentValue;
                }
            }
        }
Example #17
0
        /// <summary>
        /// Initializes a new instance of the <see cref="Channel"/> class.
        /// </summary>
        /// <param name="messageTypeProvider">
        /// A class prepared to analyze incoming messages and indicate what concrete
        /// message types can deserialize from it.
        /// </param>
        /// <param name="bindingElements">The binding elements to use in sending and receiving messages.</param>
        protected Channel(IMessageFactory messageTypeProvider, params IChannelBindingElement[] bindingElements)
        {
            ErrorUtilities.VerifyArgumentNotNull(messageTypeProvider, "messageTypeProvider");

            this.messageTypeProvider     = messageTypeProvider;
            this.WebRequestHandler       = new StandardWebRequestHandler();
            this.outgoingBindingElements = new List <IChannelBindingElement>(ValidateAndPrepareBindingElements(bindingElements));
            this.incomingBindingElements = new List <IChannelBindingElement>(this.outgoingBindingElements);
            this.incomingBindingElements.Reverse();

            foreach (var element in this.outgoingBindingElements)
            {
                element.Channel = this;
            }
        }
        /// <summary>
        /// Adds parameters to a query string, replacing parameters that
        /// match ones that already exist in the query string.
        /// </summary>
        /// <param name="builder">The UriBuilder to add arguments to.</param>
        /// <param name="args">
        /// The arguments to add to the query.
        /// If null, <paramref name="builder"/> is not changed.
        /// </param>
        internal static void AppendAndReplaceQueryArgs(this UriBuilder builder, IEnumerable <KeyValuePair <string, string> > args)
        {
            ErrorUtilities.VerifyArgumentNotNull(builder, "builder");

            if (args != null && args.Count() > 0)
            {
                NameValueCollection aggregatedArgs = HttpUtility.ParseQueryString(builder.Query);
                foreach (var pair in args)
                {
                    aggregatedArgs[pair.Key] = pair.Value;
                }

                builder.Query = CreateQueryString(aggregatedArgs.ToDictionary());
            }
        }
Example #19
0
        /// <summary>
        /// Sends a direct message to a remote party and waits for the response.
        /// </summary>
        /// <param name="requestMessage">The message to send.</param>
        /// <returns>The remote party's response.  Guaranteed to never be null.</returns>
        /// <exception cref="ProtocolException">Thrown if the response does not include a protocol message.</exception>
        public IProtocolMessage Request(IDirectedProtocolMessage requestMessage)
        {
            ErrorUtilities.VerifyArgumentNotNull(requestMessage, "requestMessage");

            this.PrepareMessageForSending(requestMessage);
            Logger.DebugFormat("Sending request: {0}", requestMessage);
            var responseMessage = this.RequestInternal(requestMessage);

            ErrorUtilities.VerifyProtocol(responseMessage != null, MessagingStrings.ExpectedMessageNotReceived, typeof(IProtocolMessage).Name);

            Logger.DebugFormat("Received message response: {0}", responseMessage);
            this.VerifyMessageAfterReceiving(responseMessage);

            return(responseMessage);
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="DirectWebResponse"/> class.
        /// </summary>
        /// <param name="requestUri">The original request URI.</param>
        /// <param name="response">The response to initialize from.  The network stream is used by this class directly.</param>
        protected DirectWebResponse(Uri requestUri, HttpWebResponse response)
        {
            ErrorUtilities.VerifyArgumentNotNull(requestUri, "requestUri");
            ErrorUtilities.VerifyArgumentNotNull(response, "response");

            this.RequestUri = requestUri;
            if (!string.IsNullOrEmpty(response.ContentType))
            {
                this.ContentType = new ContentType(response.ContentType);
            }
            this.ContentEncoding = string.IsNullOrEmpty(response.ContentEncoding) ? DefaultContentEncoding : response.ContentEncoding;
            this.FinalUri        = response.ResponseUri;
            this.Status          = response.StatusCode;
            this.Headers         = response.Headers;
        }
Example #21
0
        /// <summary>
        /// Gets the protocol message that may be embedded in the given HTTP request.
        /// </summary>
        /// <param name="request">The request to search for an embedded message.</param>
        /// <returns>The deserialized message, if one is found.  Null otherwise.</returns>
        protected virtual IDirectedProtocolMessage ReadFromRequestInternal(HttpRequestInfo request)
        {
            ErrorUtilities.VerifyArgumentNotNull(request, "request");

            Logger.DebugFormat("Incoming HTTP request: {0}", request.Url.AbsoluteUri);

            // Search Form data first, and if nothing is there search the QueryString
            var fields = request.Form.ToDictionary();

            if (fields.Count == 0)
            {
                fields = request.QueryString.ToDictionary();
            }

            return((IDirectedProtocolMessage)this.Receive(fields, request.GetRecipient()));
        }
        /// <summary>
        /// Caches the network stream and closes it if it is open.
        /// </summary>
        /// <param name="response">The response whose stream is to be cloned.</param>
        /// <param name="maximumBytesToRead">The maximum bytes to cache.</param>
        /// <returns>The seekable Stream instance that contains a copy of what was returned in the HTTP response.</returns>
        private static MemoryStream CacheNetworkStreamAndClose(HttpWebResponse response, int maximumBytesToRead)
        {
            ErrorUtilities.VerifyArgumentNotNull(response, "response");

            // Now read and cache the network stream
            Stream       networkStream = response.GetResponseStream();
            MemoryStream cachedStream  = new MemoryStream(response.ContentLength < 0 ? 4 * 1024 : Math.Min((int)response.ContentLength, maximumBytesToRead));

            networkStream.CopyTo(cachedStream);
            cachedStream.Seek(0, SeekOrigin.Begin);

            networkStream.Dispose();
            response.Close();

            return(cachedStream);
        }
Example #23
0
 /// <summary>
 /// Determines whether an IP address is the IPv6 equivalent of "localhost/127.0.0.1".
 /// </summary>
 /// <param name="ip">The ip address to check.</param>
 /// <returns>
 ///     <c>true</c> if this is a loopback IP address; <c>false</c> otherwise.
 /// </returns>
 private static bool IsIPv6Loopback(IPAddress ip)
 {
     ErrorUtilities.VerifyArgumentNotNull(ip, "ip");
     byte[] addressBytes = ip.GetAddressBytes();
     for (int i = 0; i < addressBytes.Length - 1; i++)
     {
         if (addressBytes[i] != 0)
         {
             return(false);
         }
     }
     if (addressBytes[addressBytes.Length - 1] != 1)
     {
         return(false);
     }
     return(true);
 }
        /// <summary>
        /// Adds a set of name-value pairs to the end of a given URL
        /// as part of the querystring piece.  Prefixes a ? or &amp; before
        /// first element as necessary.
        /// </summary>
        /// <param name="builder">The UriBuilder to add arguments to.</param>
        /// <param name="args">
        /// The arguments to add to the query.
        /// If null, <paramref name="builder"/> is not changed.
        /// </param>
        /// <remarks>
        /// If the parameters to add match names of parameters that already are defined
        /// in the query string, the existing ones are <i>not</i> replaced.
        /// </remarks>
        internal static void AppendQueryArgs(this UriBuilder builder, IEnumerable <KeyValuePair <string, string> > args)
        {
            ErrorUtilities.VerifyArgumentNotNull(builder, "builder");

            if (args != null && args.Count() > 0)
            {
                StringBuilder sb = new StringBuilder(50 + (args.Count() * 10));
                if (!string.IsNullOrEmpty(builder.Query))
                {
                    sb.Append(builder.Query.Substring(1));
                    sb.Append('&');
                }
                sb.Append(CreateQueryString(args));

                builder.Query = sb.ToString();
            }
        }
 /// <summary>
 /// Tests whether two arrays are equal in contents and ordering.
 /// </summary>
 /// <typeparam name="T">The type of elements in the arrays.</typeparam>
 /// <param name="first">The first array in the comparison.  May not be null.</param>
 /// <param name="second">The second array in the comparison. May not be null.</param>
 /// <returns>True if the arrays equal; false otherwise.</returns>
 internal static bool AreEquivalent <T>(T[] first, T[] second)
 {
     ErrorUtilities.VerifyArgumentNotNull(first, "first");
     ErrorUtilities.VerifyArgumentNotNull(second, "second");
     if (first.Length != second.Length)
     {
         return(false);
     }
     for (int i = 0; i < first.Length; i++)
     {
         if (!first[i].Equals(second[i]))
         {
             return(false);
         }
     }
     return(true);
 }
Example #26
0
        /// <summary>
        /// Determines whether a given ordered list of binding elements includes every
        /// binding element in this channel exactly once.
        /// </summary>
        /// <param name="order">The list of binding elements to test.</param>
        /// <returns>
        ///     <c>true</c> if the given list is a valid description of a binding element ordering; otherwise, <c>false</c>.
        /// </returns>
        private bool IsBindingElementOrderValid(IEnumerable <IChannelBindingElement> order)
        {
            ErrorUtilities.VerifyArgumentNotNull(order, "order");

            // Check that the same number of binding elements are defined.
            if (order.Count() != this.OutgoingBindingElements.Count)
            {
                return(false);
            }

            // Check that every binding element appears exactly once.
            if (order.Any(el => !this.OutgoingBindingElements.Contains(el)))
            {
                return(false);
            }

            return(true);
        }
Example #27
0
        /// <summary>
        /// Prepares the request by setting timeout and redirect policies.
        /// </summary>
        /// <param name="request">The request to prepare.</param>
        /// <param name="preparingPost"><c>true</c> if this is a POST request whose headers have not yet been sent out; <c>false</c> otherwise.</param>
        private void PrepareRequest(HttpWebRequest request, bool preparingPost)
        {
            ErrorUtilities.VerifyArgumentNotNull(request, "request");

            // Be careful to not try to change the HTTP headers that have already gone out.
            if (preparingPost || request.Method == "GET")
            {
                // Set/override a few properties of the request to apply our policies for untrusted requests.
                request.ReadWriteTimeout = (int)this.ReadWriteTimeout.TotalMilliseconds;
                request.Timeout          = (int)this.Timeout.TotalMilliseconds;
                request.KeepAlive        = false;

                // If SSL is required throughout, we cannot allow auto redirects because
                // it may include a pass through an unprotected HTTP request.
                // We have to follow redirects manually.
                request.AllowAutoRedirect = false;
            }
        }
Example #28
0
        /// <summary>
        /// Queues an indirect message for transmittal via the user agent.
        /// </summary>
        /// <param name="message">The message to send.</param>
        /// <returns>The pending user agent redirect based message to be sent as an HttpResponse.</returns>
        protected virtual UserAgentResponse SendIndirectMessage(IDirectedProtocolMessage message)
        {
            ErrorUtilities.VerifyArgumentNotNull(message, "message");

            var serializer = MessageSerializer.Get(message.GetType());
            var fields     = serializer.Serialize(message);

            // First try creating a 301 redirect, and fallback to a form POST
            // if the message is too big.
            UserAgentResponse response = this.Create301RedirectResponse(message, fields);

            if (response.Headers[HttpResponseHeader.Location].Length > indirectMessageGetToPostThreshold)
            {
                response = this.CreateFormPostResponse(message, fields);
            }

            return(response);
        }
Example #29
0
        /// <summary>
        /// Initializes a new instance of the <see cref="UntrustedWebRequestHandler"/> class.
        /// </summary>
        /// <param name="chainedWebRequestHandler">The chained web request handler.</param>
        public UntrustedWebRequestHandler(IDirectWebRequestHandler chainedWebRequestHandler)
        {
            ErrorUtilities.VerifyArgumentNotNull(chainedWebRequestHandler, "chainedWebRequestHandler");

            this.chainedWebRequestHandler = chainedWebRequestHandler;
            if (Debugger.IsAttached)
            {
                // Since a debugger is attached, requests may be MUCH slower,
                // so give ourselves huge timeouts.
                this.ReadWriteTimeout = TimeSpan.FromHours(1);
                this.Timeout          = TimeSpan.FromHours(1);
            }
            else
            {
                this.ReadWriteTimeout = Configuration.ReadWriteTimeout;
                this.Timeout          = Configuration.Timeout;
            }
        }
        /// <summary>
        /// Reads name=value pairs into an OAuth message.
        /// </summary>
        /// <param name="fields">The name=value pairs that were read in from the transport.</param>
        /// <param name="message">The message to deserialize into.</param>
        /// <exception cref="ProtocolException">Thrown when protocol rules are broken by the incoming message.</exception>
        internal void Deserialize(IDictionary <string, string> fields, IMessage message)
        {
            ErrorUtilities.VerifyArgumentNotNull(fields, "fields");
            ErrorUtilities.VerifyArgumentNotNull(message, "message");

            // Before we deserialize the message, make sure all the required parts are present.
            MessageDescription.Get(this.messageType, message.Version).EnsureMessagePartsPassBasicValidation(fields);

            try {
                foreach (var pair in fields)
                {
                    IDictionary <string, string> dictionary = new MessageDictionary(message);
                    dictionary[pair.Key] = pair.Value;
                }
            } catch (ArgumentException ex) {
                throw ErrorUtilities.Wrap(ex, MessagingStrings.ErrorDeserializingMessage, this.messageType.Name);
            }
            message.EnsureValidMessage();
        }