HttpChannelHelper.cs

  1. // ==++==
  2. // 
  3. //   
  4. //    Copyright (c) 2002 Microsoft Corporation.  All rights reserved.
  5. //   
  6. //    The use and distribution terms for this software are contained in the file
  7. //    named license.txt, which can be found in the root of this distribution.
  8. //    By using this software in any fashion, you are agreeing to be bound by the
  9. //    terms of this license.
  10. //   
  11. //    You must not remove this notice, or any other, from this software.
  12. //   
  13. // 
  14. // ==--==
  15. //==========================================================================
  16. //  File:       HttpChannelHelper.cs
  17. //
  18. //  Summary:    Implements helper methods for http client and server channels.
  19. //
  20. //==========================================================================
  21. using System;
  22. using System.Net;
  23. using System.Text;
  24. using System.Globalization;
  25. namespace System.Runtime.Remoting.Channels.Http
  26. {
  27.     
  28.     internal class HttpChannelHelper
  29.     {
  30.         private const String _http = "http://";
  31.         private static char[] s_semicolonSeparator = new char[]{';'};
  32.     
  33.         // Determine if the url starts with "http://"
  34.         internal static int StartsWithHttp(String url)
  35.         {
  36.             int urlLength = url.Length;
  37.             
  38.             if (StringHelper.StartsWithAsciiIgnoreCasePrefixLower(url, _http))
  39.                 return _http.Length;
  40.             else
  41.                 return -1;
  42.         } // StartsWithHttp
  43.         // Used by http channels to implement IChannel::Parse.
  44.         // It returns the channel uri and places object uri into out parameter.
  45.         internal static String ParseURL(String url, out String objectURI)
  46.         {            
  47.             // Set the out parameters
  48.             objectURI = null;
  49.             int separator = StartsWithHttp(url);
  50.             if (separator == -1)
  51.                 return null;
  52.             // find next slash (after end of scheme)
  53.             separator = url.IndexOf('/', separator);
  54.             if (-1 == separator)
  55.             {
  56.                 return url;  // means that the url is just "tcp://foo:90" or something like that
  57.             }
  58.             // Extract the channel URI which is the prefix
  59.             String channelURI = url.Substring(0, separator);
  60.             // Extract the object URI which is the suffix (leave the slash)
  61.             objectURI = url.Substring(separator);
  62.             InternalRemotingServices.RemotingTrace("HTTPChannel.Parse URI in: " + url);
  63.             InternalRemotingServices.RemotingTrace("HTTPChannel.Parse channelURI: " + channelURI);
  64.             InternalRemotingServices.RemotingTrace("HTTPChannel.Parse objectURI: " + objectURI);
  65.             return channelURI;
  66.         } // ParseURL
  67.         internal static String GetObjectUriFromRequestUri(String uri)
  68.         {
  69.             // We assume uri may be in one of the following forms
  70.             //   http://myhost.com/myobject.rem
  71.             //   /myobject.rem
  72.             //   /myobject
  73.             //   myobject.rem
  74.             // In all cases, myobject is considered to be the object URI (.rem might be absent)
  75.             int start, end; // range of characters to use
  76.             int index;
  77.             start = 0;
  78.             end = uri.Length;
  79.             // first see if uri starts with http://
  80.             // and remove up to next slash if it does
  81.             start = StartsWithHttp(uri);
  82.             if (start != -1)
  83.             {
  84.                 // remove domain name as well
  85.                 index = uri.IndexOf('/', start);
  86.                 if (index != -1)
  87.                     start = index + 1;
  88.                 else
  89.                     start = end; // uri will end up being ""
  90.             }
  91.             else
  92.             {
  93.                 // remove "/" if this is an absolute path
  94.                 start = 0; 
  95.                 if (uri[start] == '/')
  96.                    start++;
  97.             }
  98.             // remove query string if present ('?' and everything past it)
  99.             index = uri.IndexOf('?');
  100.             if (index != -1)
  101.                 end = index;
  102.             if (start < end)
  103.                 return CoreChannel.RemoveApplicationNameFromUri(uri.Substring(start, end - start));
  104.             else
  105.                 return "";
  106.         } // GetObjectURIFromRequestURI
  107.         
  108.         internal static void ParseContentType(String contentType,
  109.                                               out String value,
  110.                                               out String charset)
  111.         {
  112.             charset = null;
  113.         
  114.             if (contentType == null)
  115.             {
  116.                 value = null;
  117.                 return;
  118.             }
  119.         
  120.             String[] parts = contentType.Split(s_semicolonSeparator);
  121.             // the actual content-type value is always first
  122.             value = parts[0];
  123.             // examine name value pairs and look for charset
  124.             if (parts.Length > 0)
  125.             {
  126.                 foreach (String part in parts)
  127.                 {
  128.                     int index = part.IndexOf('=');
  129.                     if (index != -1)
  130.                     {
  131.                         String key = part.Substring(0, index).Trim();
  132.                         if (String.Compare(key, "charset"true, CultureInfo.InvariantCulture) == 0)
  133.                         {
  134.                             if ((index + 1) < part.Length)
  135.                             {
  136.                                 // we had to make sure there is something after the 
  137.                                 //   equals sign.
  138.                                 charset = part.Substring(index + 1);
  139.                             }
  140.                             else
  141.                             {
  142.                                 charset = null;
  143.                             }
  144.                             return;
  145.                         }
  146.                     }
  147.                 } // foreach
  148.             }
  149.         } // ParseContentType
  150.         // returns url with the machine name replaced with the ip address.
  151.         internal static String ReplaceMachineNameWithIpAddress(String url)
  152.         {
  153.             String objectUri;
  154.             String channelUri = ParseURL(url, out objectUri);    
  155.             // find bounds of machine name
  156.             int index = StartsWithHttp(url);
  157.             if (index == -1)
  158.                 return url;
  159.    
  160.             int colonIndex = channelUri.IndexOf(':', index);
  161.             if (colonIndex == -1)
  162.                 colonIndex = channelUri.Length;
  163.             // machine name is between index and up to but not including colonIndex, 
  164.             //   so we will replace those characters with the ip address.
  165.             String machineName = url.Substring(index, colonIndex - index);
  166.             // determine ip address (we'll resort to using the machine name
  167.             //   if resolving the ip address fails)
  168.             String ipAddress = machineName;
  169.             try
  170.             {
  171.                 IPHostEntry ipEntries = Dns.GetHostByName(machineName);
  172.                 if ((ipEntries != null) && (ipEntries.AddressList.Length > 0))
  173.                 {
  174.                     ipAddress = ipEntries.AddressList[0].ToString();
  175.                 }               
  176.             } 
  177.             catch
  178.             {
  179.             }
  180.             String newUrl = url.Substring(0, index) + ipAddress + url.Substring(colonIndex);
  181.             return newUrl;
  182.         } // ReplaceMachineNameWithIpAddress
  183.         internal static String ReplaceChannelUriWithThisString(String url, String channelUri) 
  184.         {
  185.             // NOTE: channelUri is assumed to be scheme://machinename:port
  186.             //   with NO trailing slash.
  187.             String oldChannelUri;
  188.             String objUri;
  189.             oldChannelUri = HttpChannelHelper.ParseURL(url, out objUri);
  190.             InternalRemotingServices.RemotingAssert(oldChannelUri != null"http url expected.");
  191.             InternalRemotingServices.RemotingAssert(objUri != null"non-null objUri expected.");
  192.             
  193.             return channelUri + objUri;
  194.         } // ReplaceChannelUriWithThisString
  195.         // returns url with the machine name replaced with the ip address.
  196.         internal static String ReplaceMachineNameWithThisString(String url, String newMachineName)
  197.         {
  198.             String objectUri;
  199.             String channelUri = ParseURL(url, out objectUri);    
  200.             // find bounds of machine name
  201.             int index = StartsWithHttp(url);
  202.             if (index == -1)
  203.                 return url;
  204.    
  205.             int colonIndex = channelUri.IndexOf(':', index);
  206.             if (colonIndex == -1)
  207.                 colonIndex = channelUri.Length;
  208.             // machine name is between index and up to but not including colonIndex, 
  209.             //   so we will replace those characters with the ip address.
  210.             String newUrl = url.Substring(0, index) + newMachineName + url.Substring(colonIndex);
  211.             return newUrl;
  212.         } // ReplaceMachineNameWithIpAddress
  213.         // Decodes a uri while it is in byte array form
  214.         internal static void DecodeUriInPlace(byte[] uriBytes, out int length)
  215.         {
  216.             int percentsFound = 0;
  217.             int count = uriBytes.Length;
  218.             length = count;
  219.             int co = 0;
  220.             while (co < count)
  221.             {
  222.                 if (uriBytes[co] == (byte)'%')
  223.                 {
  224.                     // determine location to write to (we skip 2 character for each percent)
  225.                     int writePos = co - (percentsFound * 2);
  226.                     // decode in place by collapsing bytes "%XY" (actual byte is 16*Dec(X) + Dec(Y))
  227.                     uriBytes[writePos] = (byte)
  228.                         (16 * CharacterHexDigitToDecimal(uriBytes[co + 1]) +
  229.                          CharacterHexDigitToDecimal(uriBytes[co + 2]));
  230.                     percentsFound++;      
  231.                     length -= 2; // we eliminated 2 characters from the length
  232.                     co += 3;
  233.                 }
  234.                 else
  235.                 {
  236.                     if (percentsFound != 0)
  237.                     {
  238.                         // we have to copy characters back into place since we will skip some characters
  239.                         // determine location to write to (we skip 2 character for each percent)
  240.                         int writePos = co - (percentsFound * 2);
  241.                         // copy character back into place
  242.                         uriBytes[writePos] = uriBytes[co];
  243.                     }
  244.                     co++;
  245.                 }
  246.             }
  247.             
  248.         } // DecodeUri
  249.         // reading helper functions
  250.         internal static int CharacterHexDigitToDecimal(byte b)
  251.         {
  252.             switch ((char)b)
  253.             {
  254.             case 'F'return 15;
  255.             case 'E'return 14;
  256.             case 'D'return 13;
  257.             case 'C'return 12;
  258.             case 'B'return 11;
  259.             case 'A'return 10;
  260.             defaultreturn b - (byte)'0';
  261.             }
  262.         } // CharacterHexDigitToDecimal
  263.         internal static char DecimalToCharacterHexDigit(int i)
  264.         {
  265.             switch (i)
  266.             {
  267.             case 15: return 'F';
  268.             case 14: return 'E';
  269.             case 13: return 'D';
  270.             case 12: return 'C';
  271.             case 11: return 'B';
  272.             case 10: return 'A';
  273.             defaultreturn (char)(i + (byte)'0');
  274.             }
  275.         } // DecimalToCharacterHexDigit
  276.                 
  277.     
  278.     } // class HttpChannelHelper
  279.     internal class HttpEncodingHelper
  280.     {
  281.         internal static String EncodeUriAsXLinkHref(String uri)
  282.         {
  283.             if (uri == null)
  284.                 return null;
  285.         
  286.             // uses modified encoding rules from xlink href spec for encoding uri's.
  287.             // http://www.w3.org/TR/2000/PR-xlink-20001220/#link-locators
  288.             byte[] uriBytes = Encoding.UTF8.GetBytes(uri);
  289.             StringBuilder sb = new StringBuilder(uri.Length);
  290.             // iterate over uri bytes and build up an encoded string.
  291.             foreach (byte b in uriBytes)
  292.             {
  293.                 if (!EscapeInXLinkHref(b))
  294.                 {
  295.                     sb.Append((char)b);
  296.                 }
  297.                 else
  298.                 {
  299.                     // the character needs to be encoded as %HH
  300.                     sb.Append('%');
  301.                     sb.Append(HttpChannelHelper.DecimalToCharacterHexDigit(b >> 4));
  302.                     sb.Append(HttpChannelHelper.DecimalToCharacterHexDigit(b & 0xF));
  303.                 }
  304.             }
  305.             return sb.ToString();            
  306.         } // EncodeUriAsXLinkHref
  307.         internal static bool EscapeInXLinkHref(byte ch)
  308.         {
  309.             if ((ch <= 32) || // control characters and space
  310.                 (ch >= 128) ||  // non-ascii characters
  311.                 (ch == (byte)'<') ||
  312.                 (ch == (byte)'>') ||
  313.                 (ch == (byte)'"'))        
  314.             {
  315.                 return true;
  316.             }
  317.                    
  318.             return false;
  319.         } // EscapeInXLinkHref
  320.         internal static String DecodeUri(String uri)
  321.         {
  322.             byte[] uriBytes = Encoding.UTF8.GetBytes(uri);
  323.             int length;
  324.             HttpChannelHelper.DecodeUriInPlace(uriBytes, out length);
  325.             String newUri = Encoding.UTF8.GetString(uriBytes, 0, length);
  326.             return newUri;
  327.         } // DecodeUri
  328.         
  329.     } // class HttpEncodingHelper
  330. // namespace System.Runtime.Remoting.Channels.Http
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值