Exemple #1
0
        /// <summary>Builds a Content-Type header which includes media type and encoding information.</summary>
        /// <param name="mediaType">Media type to be used.</param>
        /// <param name="encoding">Encoding to be used in response, possibly null.</param>
        /// <returns>The value for the Content-Type header.</returns>
        internal static string BuildContentType(MediaType mediaType, Encoding encoding)
        {
            DebugUtils.CheckNoExternalCallers();
            Debug.Assert(mediaType != null, "mediaType != null");

            string mediaTypeAsText = mediaType.ToText();
            if (encoding == null)
            {
                return mediaTypeAsText;
            }
            else
            {
                return string.Concat(mediaTypeAsText, ";", HttpConstants.Charset, "=", encoding.WebName);
            }
        }
Exemple #2
0
        /// <summary>
        /// Gets a number of non-* matching type name parts and parameters; returns the number of matching type name parts or -1 if not matching at all.
        /// The <paramref name="matchingParameters"/> represent the number of matched parameters or -1 if there are no parameters to match and the candidate 
        /// type also has no parameters.
        /// </summary>
        /// <param name="candidate">Candidate media type to match.</param>
        /// <param name="matchingParameters">The number of matched parameters or -1 if there are no parameters to match and the <paramref name="candidate"/> does not have parameters either.</param>
        /// <param name="qualityValue">The quality value of the candidate (or -1 if none is specified).</param>
        /// <param name="parameterCount">The number of parameters of this type that are not accept-parameters (and thus ignored).</param>
        /// <returns>Returns the number of matching type name parts or -1 if not matching at all. The <paramref name="matchingParameters"/> 
        /// represent the number of matched parameters or -1 if there are no parameters to match and the candidate 
        /// type also has no parameters.
        /// </returns>
        internal int GetMatchingParts(MediaType candidate, out int matchingParameters, out int qualityValue, out int parameterCount)
        {
            DebugUtils.CheckNoExternalCallers();
            Debug.Assert(candidate != null, "candidate must not be null.");

            int matchedNameParts = -1;
            if (this.type == "*")
            {
                matchedNameParts = 0;
            }
            else
            {
                if (HttpUtils.CompareMediaTypeNames(this.type, candidate.type))
                {
                    if (this.subType == "*")
                    {
                        // only type matches
                        matchedNameParts = 1;
                    }
                    else if (HttpUtils.CompareMediaTypeNames(this.subType, candidate.subType))
                    {
                        // both type and subtype match
                        matchedNameParts = 2;
                    }
                }
            }

            qualityValue = DefaultQualityValue;
            parameterCount = 0;
            matchingParameters = 0;

            // NOTE: we know that the candidates don't have accept parameters so we can rely
            //       on the total parameter count.
            IList<KeyValuePair<string, string>> candidateParameters = candidate.Parameters;
            bool candidateHasParams = candidateParameters != null && candidateParameters.Count > 0;
            bool thisHasParams = this.parameters != null && this.parameters.Count > 0;
            if (thisHasParams)
            {
                for (int i = 0; i < this.parameters.Count; ++i)
                {
                    string parameterName = this.parameters[i].Key;
                    if (IsQualityValueParameter(parameterName))
                    {
                        // once we hit the q-value in the parameters we know that only accept-params will follow
                        // that don't contribute to the matching. Parse the quality value but don't continue processing
                        // parameters.
                        qualityValue = ParseQualityValue(this.parameters[i].Value.Trim());
                        break;
                    }

                    parameterCount = i + 1;

                    if (candidateHasParams)
                    {
                        // find the current parameter name in the set of parameters of the candidate and compare the value;
                        // if they match increase the result count
                        string parameterValue;
                        if (TryFindMediaTypeParameter(candidateParameters, parameterName, out parameterValue) &&
                            string.Compare(this.parameters[i].Value.Trim(), parameterValue.Trim(), StringComparison.OrdinalIgnoreCase) == 0)
                        {
                            matchingParameters++;
                        }
                    }
                }
            }

            // if we have no non-accept parameters special rules apply
            if (!thisHasParams || parameterCount == 0)
            {
                if (candidateHasParams)
                {
                    if (matchedNameParts == 0 || matchedNameParts == 1)
                    {
                        // this is a media range specification using the '*' wildcard.
                        // we assume that all parameters are matched for such ranges so the server
                        // will pick the most specific one
                        matchingParameters = candidateParameters.Count;
                    }
                    else
                    {
                        // the candidate type has parameters while this type has not;
                        // return 0 to indicate that none of the candidate's parameters match.
                        matchingParameters = 0;
                    }
                }
                else
                {
                    // neither this type nor the candidate have parameters; in this case we return -1 to indicate
                    // that the candidate parameters are a perfect.
                    matchingParameters = -1;
                }
            }

            return matchedNameParts;
        }
Exemple #3
0
        /// <summary>Gets the best encoding available for the specified charset request.</summary>
        /// <param name="acceptableCharsets">
        /// The Accept-Charset header value (eg: "iso-8859-5, unicode-1-1;q=0.8").
        /// </param>
        /// <param name="mediaType">The media type used to compute the default encoding for the payload.</param>
        /// <param name="utf8Encoding">The encoding to use for UTF-8 charsets; we use the one without the BOM.</param>
        /// <param name="defaultEncoding">The encoding to use if no encoding could be computed from the <paramref name="acceptableCharsets"/> or <paramref name="mediaType"/>.</param>
        /// <returns>An Encoding object appropriate to the specifed charset request.</returns>
        internal static Encoding EncodingFromAcceptableCharsets(string acceptableCharsets, MediaType mediaType, Encoding utf8Encoding, Encoding defaultEncoding)
        {
            DebugUtils.CheckNoExternalCallers();
            Debug.Assert(mediaType != null, "mediaType != null");

            // Determines the appropriate encoding mapping according to
            // RFC 2616.14.2 (http://tools.ietf.org/html/rfc2616#section-14.2).
            Encoding result = null;
            if (!string.IsNullOrEmpty(acceptableCharsets))
            {
                // PERF: in the future if we find that computing the encoding from the accept charsets is
                //       too expensive we could introduce a cache of original strings to resolved encoding.
                List<CharsetPart> parts = new List<CharsetPart>(AcceptCharsetParts(acceptableCharsets));
                parts.Sort(delegate(CharsetPart x, CharsetPart y)
                {
                    return y.Quality - x.Quality;
                });

                foreach (CharsetPart part in parts)
                {
                    if (part.Quality > 0)
                    {
                        // When UTF-8 is specified, select the version that doesn't use the BOM.
                        if (String.Compare("utf-8", part.Charset, StringComparison.OrdinalIgnoreCase) == 0)
                        {
                            result = utf8Encoding;
                            break;
                        }
                        else
                        {
                            result = GetEncodingFromCharsetName(part.Charset);
                            if (result != null)
                            {
                                break;
                            }

                            // If the charset is not supported it is ignored so other possible charsets are evaluated.
                        }
                    }
                }
            }

            // No Charset was specifed, or if charsets were specified, no valid charset was found.
            // Returning a different charset is also valid. Get the default encoding for the media type.
            if (result == null)
            {
                result = mediaType.SelectEncoding();
                if (result == null)
                {
                    return defaultEncoding;
                }
            }

            return result;
        }
 /// <summary>
 /// Parses the accepted charsets and matches them against the supported encodings for the given <paramref name="payloadKind"/>.
 /// </summary>
 /// <param name="acceptCharsetHeader">The Accept-Charset header of the request.</param>
 /// <param name="payloadKind">The <see cref="ODataPayloadKind"/> for which to compute the encoding.</param>
 /// <param name="mediaType">The media type used to compute the default encoding for the payload.</param>
 /// <returns>The encoding to be used for the response.</returns>
 private static Encoding GetEncoding(string acceptCharsetHeader, ODataPayloadKind payloadKind, MediaType mediaType)
 {
     if (payloadKind == ODataPayloadKind.BinaryValue)
     {
         return null;
     }
     else
     {
         // TODO: we currently assume that the media type does not have a 'charset' parameter specified. This is true for 
         //       the current uses of this method. Consider making this general purpose and also include the 'charset'
         //       parameter on the media type into the resolution process. (Currently the media type is only used to
         //       compute the default encoding).
         return HttpUtils.EncodingFromAcceptableCharsets(acceptCharsetHeader, mediaType, encodingUtf8NoPreamble, encodingUtf8NoPreamble);
     }
 }
        /// <summary>
        /// Given the Accept and the Accept-Charset headers of the request message computes the media type, encoding and <see cref="ODataFormat"/>
        /// to be used for the response message.
        /// </summary>
        /// <param name="settings">The writer settings to use for serializing the response payload.</param>
        /// <param name="payloadKind">The kind of payload to be serialized as part of the response message.</param>
        /// <param name="mediaType">The media type to be used in the response message.</param>
        /// <param name="encoding">The encoding to be used in the response message.</param>
        /// <returns>The <see cref="ODataFormat"/> used when serializing the response.</returns>
        internal static ODataFormat GetContentTypeFromSettings(
            ODataWriterSettings settings,
            ODataPayloadKind payloadKind,
            out MediaType mediaType,
            out Encoding encoding)
        {
            DebugUtils.CheckNoExternalCallers();
            Debug.Assert(settings != null, "settings != null");

            // compute format, media type and encoding
            ODataFormat format;

            if (settings.AcceptableMediaTypes != null)
            {
                mediaType = GetMediaType(settings.AcceptableMediaTypes, payloadKind, out format);
                encoding = GetEncoding(settings.AcceptableCharsets, payloadKind, mediaType);
            }
            else
            {
                mediaType = GetDefaultMediaType(payloadKind, settings.Format, out format);
                encoding = mediaType.SelectEncoding();
            }

            return format;
        }
Exemple #6
0
 /// <summary>
 /// Parses the accepted charsets and matches them against the supported encodings for the given <paramref name="payloadKind"/>.
 /// </summary>
 /// <param name="acceptCharsetHeader">The Accept-Charset header of the request.</param>
 /// <param name="payloadKind">The <see cref="ODataPayloadKind"/> for which to compute the encoding.</param>
 /// <param name="mediaType">The media type used to compute the default encoding for the payload.</param>
 /// <returns>The encoding to be used for the response.</returns>
 private static Encoding GetEncoding(string acceptCharsetHeader, ODataPayloadKind payloadKind, MediaType mediaType)
 {
     if (payloadKind == ODataPayloadKind.BinaryValue)
     {
         return(null);
     }
     else
     {
         // TODO: we currently assume that the media type does not have a 'charset' parameter specified. This is true for
         //       the current uses of this method. Consider making this general purpose and also include the 'charset'
         //       parameter on the media type into the resolution process. (Currently the media type is only used to
         //       compute the default encoding).
         return(HttpUtils.EncodingFromAcceptableCharsets(acceptCharsetHeader, mediaType, encodingUtf8NoPreamble, encodingUtf8NoPreamble));
     }
 }