/// <summary>
 /// Signs the request appropriately to make it an authenticated request.
 /// This method takes the URI components as decoding the URI components requires the knowledge
 /// of whether the URI is in path-style or host-style and a host-suffix if it's host-style.
 /// </summary>
 public void SignRequest(HttpWebRequest request, ResourceUriComponents uriComponents)
 {
     if (request == null)
         throw new ArgumentNullException("request");
     var message = MessageCanonicalizer.CanonicalizeHttpRequest(request, uriComponents);
     var computedBase64Signature = ComputeMacSha(message);
     request.Headers.Add(StorageHttpConstants.HeaderNames.Authorization,
                         string.Format(CultureInfo.InvariantCulture,
                                       "{0} {1}:{2}",
                                       StorageHttpConstants.AuthenticationSchemeNames.SharedKeyAuthSchemeName,
                                       accountName,
                                       computedBase64Signature));
 }
        public void SignRequestForSharedKeyLite(HttpWebRequest request, ResourceUriComponents uriComponents)
        {
            if (request == null)
            {
                throw new ArgumentNullException("request");
            }

            // add the date header to the request
            var dateString = MessageCanonicalizer.ConvertDateTimeToHttpString(DateTime.UtcNow);
            request.Headers.Add(StorageHttpConstants.HeaderNames.StorageDateTime, dateString);

            // compute the signature and add the authentication scheme
            var message = MessageCanonicalizer.CanonicalizeHttpRequestForSharedKeyLite(request, uriComponents, dateString);
            var computedBase64Signature = ComputeMacSha(message);
            request.Headers.Add(StorageHttpConstants.HeaderNames.Authorization,
                                string.Format(CultureInfo.InvariantCulture,
                                              "{0} {1}:{2}",
                                              StorageHttpConstants.AuthenticationSchemeNames.SharedKeyLiteAuthSchemeName,
                                              accountName,
                                              computedBase64Signature));
        }
        /// <summary>
        /// Constructs a path-style resource URI given all its constituents
        /// </summary>
        private static Uri ConstructPathStyleResourceUri(Uri endpoint, ResourceUriComponents uriComponents)
        {
            var path = new StringBuilder(string.Empty);
            if (uriComponents.AccountName != null)
            {
                path.Append(uriComponents.AccountName);

                if (uriComponents.ContainerName != null)
                {
                    path.Append(StorageHttpConstants.ConstChars.Slash);
                    path.Append(uriComponents.ContainerName);

                    if (uriComponents.RemainingPart != null)
                    {
                        path.Append(StorageHttpConstants.ConstChars.Slash);
                        path.Append(uriComponents.RemainingPart);
                    }
                }
            }

            return ConstructUriFromUriAndString(endpoint, path.ToString());
        }
        /// <summary>
        /// Constructs a host-style resource URI given all its constituents
        /// </summary>
        private static Uri ConstructHostStyleResourceUri(Uri hostSuffix, ResourceUriComponents uriComponents)
        {
            if (uriComponents.AccountName == null)
            {
                // When there is no account name, full URI is same as hostSuffix
                return hostSuffix;
            }
            // accountUri will be something like "http://accountname.hostSuffix/" and then we append
            // container name and remaining part if they are present.
            var accountUri = ConstructHostStyleAccountUri(hostSuffix, uriComponents.AccountName);
            var path = new StringBuilder(string.Empty);
            if (uriComponents.ContainerName != null)
            {
                path.Append(uriComponents.ContainerName);

                if (uriComponents.RemainingPart != null)
                {
                    path.Append(StorageHttpConstants.ConstChars.Slash);
                    path.Append(uriComponents.RemainingPart);
                }
            }

            return ConstructUriFromUriAndString(accountUri, path.ToString());
        }
        internal static string CanonicalizeHttpRequest(
            Uri address,
            ResourceUriComponents uriComponents,
            string method,
            string contentType,
            string date,
            NameValueCollection headers)
        {
            // The first element should be the Method of the request.
            // I.e. GET, POST, PUT, or HEAD.
            var canonicalizedString = new CanonicalizedString(method);

            // The second element should be the MD5 value.
            // This is optional and may be empty.
            var httpContentMD5Value = string.Empty;

            // First extract all the content MD5 values from the header.
            var httpContentMD5Values = HttpRequestAccessor.GetHeaderValues(headers, StorageHttpConstants.HeaderNames.ContentMD5);

            // If we only have one, then set it to the value we want to append to the canonicalized string.
            if (httpContentMD5Values.Count == 1)
            {
                httpContentMD5Value = (string)httpContentMD5Values[0];
            }

            canonicalizedString.AppendCanonicalizedElement(httpContentMD5Value);

            // The third element should be the content type.
            canonicalizedString.AppendCanonicalizedElement(contentType);

            // The fourth element should be the request date.
            // See if there's an storage date header.
            // If there's one, then don't use the date header.
            var httpStorageDateValues = HttpRequestAccessor.GetHeaderValues(headers, StorageHttpConstants.HeaderNames.StorageDateTime);
            if (httpStorageDateValues.Count > 0)
            {
                date = null;
            }

            canonicalizedString.AppendCanonicalizedElement(date);

            // Look for header names that start with StorageHttpConstants.HeaderNames.PrefixForStorageHeader
            // Then sort them in case-insensitive manner.
            var httpStorageHeaderNameArray = new ArrayList();
            foreach (string key in headers.Keys)
            {
                if (key.ToLowerInvariant().StartsWith(StorageHttpConstants.HeaderNames.PrefixForStorageHeader, StringComparison.Ordinal))
                {
                    httpStorageHeaderNameArray.Add(key.ToLowerInvariant());
                }
            }

            httpStorageHeaderNameArray.Sort();

            // Now go through each header's values in the sorted order and append them to the canonicalized string.
            foreach (string key in httpStorageHeaderNameArray)
            {
                var canonicalizedElement = new StringBuilder(key);
                var delimiter = ":";
                var values = HttpRequestAccessor.GetHeaderValues(headers, key);

                // Go through values, unfold them, and then append them to the canonicalized element string.
                foreach (string value in values)
                {
                    // Unfolding is simply removal of CRLF.
                    var unfoldedValue = value.Replace(StorageHttpConstants.ConstChars.CarriageReturnLinefeed, string.Empty);

                    // Append it to the canonicalized element string.
                    canonicalizedElement.Append(delimiter);
                    canonicalizedElement.Append(unfoldedValue);
                    delimiter = ",";
                }

                // Now, add this canonicalized element to the canonicalized header string.
                canonicalizedString.AppendCanonicalizedElement(canonicalizedElement.ToString());
            }

            // Now we append the canonicalized resource element.
            var canonicalizedResource = GetCanonicalizedResource(address, uriComponents);
            canonicalizedString.AppendCanonicalizedElement(canonicalizedResource);

            return canonicalizedString.Value;
        }
        internal static string CanonicalizeHttpRequestForSharedKeyLite(HttpWebRequest request, ResourceUriComponents uriComponents, string date)
        {
            var canonicalizedString = new StringBuilder(date);
            AppendStringToCanonicalizedString(canonicalizedString, GetCanonicalizedResource(request.Address, uriComponents));

            return canonicalizedString.ToString();
        }
 /// <summary>
 /// Canonicalize HTTP header contents.
 /// </summary>
 /// <param name="request">An HttpWebRequest object.</param>
 /// <param name="uriComponents">Components of the Uri extracted out of the request.</param>
 /// <returns>The canonicalized string of the given HTTP request's header.</returns>
 internal static string CanonicalizeHttpRequest(HttpWebRequest request, ResourceUriComponents uriComponents)
 {
     return CanonicalizeHttpRequest(
         request.Address, uriComponents, request.Method, request.ContentType, string.Empty, request.Headers);
 }
        internal static string GetCanonicalizedResource(Uri address, ResourceUriComponents uriComponents)
        {
            // Algorithm is as follows
            // 1. Start with the empty string ("")
            // 2. Append the account name owning the resource preceded by a /. This is not 
            //    the name of the account making the request but the account that owns the 
            //    resource being accessed.
            // 3. Append the path part of the un-decoded HTTP Request-URI, up-to but not 
            //    including the query string.
            // 4. If the request addresses a particular component of a resource, like?comp=
            //    metadata then append the sub-resource including question mark (like ?comp=
            //    metadata)

            //KCA FIX THIS, THIS IS  NOT ACCORDING TO  THE RULES ABOVE!!!!!!!!!!!!!!!
            var canonicalizedResource = new StringBuilder(StorageHttpConstants.ConstChars.Slash);
            canonicalizedResource.Append(uriComponents.AccountName);

            // AbsolutePath starts with a '/'.
            canonicalizedResource.Append(address.AbsolutePath);

            var queryVariables = HttpUtility.ParseQueryString(address.Query);
            var compQueryParameterValue = queryVariables[StorageHttpConstants.QueryParams.QueryParamComp];
            if (compQueryParameterValue != null)
            {
                canonicalizedResource.Append(StorageHttpConstants.ConstChars.QuestionMark);
                canonicalizedResource.Append(StorageHttpConstants.QueryParams.QueryParamComp);
                canonicalizedResource.Append(StorageHttpConstants.QueryParams.SeparatorForParameterAndValue);
                canonicalizedResource.Append(compQueryParameterValue);
            }

            return canonicalizedResource.ToString();
        }
 /// <summary>
 /// Constructs an URI given all its constituents
 /// </summary>
 /// <param name="endpoint">
 /// This is the service endpoint in case of path-style URIs and a host suffix in case of host-style URIs
 /// IMPORTANT: This does NOT include the service name or account name
 /// </param>
 /// <param name="uriComponents">Uri constituents</param>
 /// <param name="pathStyleUri">Indicates whether to construct a path-style Uri (true) or host-style URI (false)</param>
 /// <returns>Full uri</returns>
 public static Uri ConstructResourceUri(Uri endpoint, ResourceUriComponents uriComponents, bool pathStyleUri)
 {
     return pathStyleUri ?
             ConstructPathStyleResourceUri(endpoint, uriComponents) :
             ConstructHostStyleResourceUri(endpoint, uriComponents);
 }