[Mono-patches] mcs/class/System.Web/System.Web.Util ApacheVersionInfo.cs,NONE,1.1 ChangeLog,NONE,1.1 DataSourceHelper.cs,NONE,1.1 FileAction.cs,NONE,1.1 FileChangeEventHandler.cs,NONE,1.1 FileChangedEventArgs.cs,NONE,1.1 FileChangesMonitor.cs,NONE,1.1 FilePathParser.cs,NONE,1.1 IISVersionInfo.cs,NONE,1.1 NativeFileChangeEventHandler.cs,NONE,1.1 UrlUtils.cs,NONE,1.1 WebEqualComparer.cs,NONE,1.1 WebHashCodeProvider.cs,NONE,1.1

Gonzalo Paniagua gonzalo@mono-cvs.ximian.com
Sun, 25 Aug 2002 20:57:49 -0400


Update of /cvs/public/mcs/class/System.Web/System.Web.Util
In directory mono-cvs.ximian.com:/tmp/cvs-serv26387/System.Web.Util

Added Files:
	ApacheVersionInfo.cs ChangeLog DataSourceHelper.cs 
	FileAction.cs FileChangeEventHandler.cs 
	FileChangedEventArgs.cs FileChangesMonitor.cs 
	FilePathParser.cs IISVersionInfo.cs 
	NativeFileChangeEventHandler.cs UrlUtils.cs 
	WebEqualComparer.cs WebHashCodeProvider.cs 
Log Message:
Moved from System.Web.Utils to System.Web.Util

--- NEW FILE: ApacheVersionInfo.cs ---
/**
 * Namespace: System.Web.Util
 * Class:     ApacheVersionInfo
 * 
 * Author:  Gaurav Vaish
 * Maintainer: gvaish@iitk.ac.in
 * Contact: <my_scripts2001@yahoo.com>, <gvaish@iitk.ac.in>
 * Implementation: yes
 * Status:  ??%
 * 
 * (C) Gaurav Vaish (2001)
 */

namespace System.Web.Util
{
	/// <summary>
	/// Versions of the modules related to Apache
	/// </summary>
	/// <remarks>
	/// At present I don't know what modules are to be loaded and how
	/// </remarks>
	/// <see>
	/// System.Web.Util.IISVersionInfo
	/// </see>
	internal class ApacheVersionInfo
	{
		public ApacheVersionInfo()
		{
		}
	}
}

--- NEW FILE: ChangeLog ---
2002-01-03  Nick Drochak  <ndrochak@gol.com>

	* FileChangesMonitor.cs: remove redundant using statement; use int
	for MAXLEN; capitalize correctly 'WebHashCodeProvider';
	fix typo rsLock -> rwLock; Change IsRooted to IsPathRooted;
	set out parameter value where needed
	* FilePathParser.cs: qualify method GetPathRoot() with 'Path.'
	* IISVersionInfo.cs: initialize static member to avoid compile error.
	* WebEqualComparer.cs: static member defC shouldn't be readonly;
	the string comparer had some typos (fixed)
	* WebHashCodeProvider.cs: needed System.Globalization; static member
	defHcp shouldn't be readonly; remove double equal typo.

2002-01-02  Nick Drochak  <ndrochak@gol.com>

	* FileAction.cs: Use 0x7FFFFFFF as enum value for error.  0xFFFFFFFF
	is too big for Int32.
	* FileChangeEventHandler.cs: put missing 'void' return type on delegate
	FileChangeEventHandler()
	* FileChangedEventArgs.cs: ditto for FileChangedEvent()
	* NativeFileChangeEventHandler.cs: ditto for NativeFileChangeEventHandler()
	* FileChangesMonitor.cs: add needed namespaces and comment out imcomplete
	code.

2001-12-21      Gaurav Vaish <gvaish@iitk.ac.in>

	* ApacheVersionInfo.cs     - Dummy class, for later use.
        * FileAction.cs:
        * FileChangeEventHandler.cs:
        * FileChangeEventArgs.cs:
        * FileChangesMonitor.cs:
        * NativeFileChangeEventHandler.cs
	                           - To be used in System.Web/Http* classes.
	                             Initially needed for HttpRuntime
        * IISVersionInfo.cs        - Some useful methods


2001-12-17	Gaurav Vaish <gvaish@iitk.ac.in>

	* UrlUtils.cs              - Added functions Combine and Reduce

2001-12-16  Miguel de Icaza  <miguel@ximian.com>

	* DataSourceHelper.cs, UrlUtils.cs: Set the correct namespace. 

2001-11-30
		Gaurav Vaish <gvaish@iitk.ac.in>
	* DataSourceHelper.cs      - Resolving DataSource objects

2001-11-09
		Gaurav Vaish <gvaish@iitk.ac.in>
	* UrlUtil.cs               - Some basic functions

2001-11-08
		Gaurav Vaish <gvaish@iitk.ac.in>
	* Namespace    - Created the namespace for commonly used,
	                   otherwise not available functions
--- NEW FILE: DataSourceHelper.cs ---
/**
 * Namespace: System.Web.UI.Util
 * Class:     DataSourceHelper
 *
 * Author:  Gaurav Vaish
 * Maintainer: gvaish@iitk.ac.in
 * Contact: <my_scripts2001@yahoo.com>, <gvaish@iitk.ac.in>
 * Status:  10%
 *
 * (C) Gaurav Vaish (2001)
 */

using System;
using System.Collections;
using System.ComponentModel;

namespace System.Web.Util
{
	internal class DataSourceHelper
	{
		public static IEnumerable GetResolvedDataSource(object source, string member)
		{
			if(source==null)
				return null;
			if(source is IListSource)
			{
				IListSource ils = (IListSource)source;
				IList       il  = ils.GetList();
				if(ils.ContainsListCollection)
				{
					return il;
				}
				if(il is ITypedList)
				{
					ITypedList itl = (ITypedList)il;
					PropertyDescriptorCollection pdc = itl.GetItemProperties(new PropertyDescriptor[0]);
					PropertyDescriptor pd = null;
					if(pdc != null)
					{
						if(pdc.Count > 0)
						{
							if(member != null)
							{
								if(member.Length > 0)
								{
									pd = pdc.Find(member, true);
								} else
								{
									pd = pdc[0];
								}
							}
						}
					}
					if(pd!=null)
					{
						object o = pd.GetValue(il[0]);
						if(o!=null)
						{
							if(o is IEnumerable)
								return (IEnumerable)o;
						}
						throw new HttpException("ListSource Empty"); // no data in ListSource object
					}
				}
			} else if(source is IEnumerable)
			{
				return (IEnumerable)source;
			}
			return null;
		}
	}
}

--- NEW FILE: FileAction.cs ---
/**
 * Namespace: System.Web.Util
 * Class:     FileAction
 *
 * Author:  Gaurav Vaish
 * Maintainer: gvaish@iitk.ac.in
 * Contact: <my_scripts2001@yahoo.com>, <gvaish@iitk.ac.in>
 * Implementation: yes
 * Status:  ??%
 *
 * (C) Gaurav Vaish (2001)
 */

namespace System.Web.Util
{
	public enum FileAction
	{
		Overwhleming,
		Added,
		Removed,
		Modifiled,
		RenamedOldName,
		RenamedNewName,
		Error = 0x7FFFFFFF
	}
}

--- NEW FILE: FileChangeEventHandler.cs ---
/**
 * Namespace: System.Web.Util
 * Class:     FileChangeEventHandler
 *
 * Author:  Gaurav Vaish
 * Maintainer: gvaish@iitk.ac.in
 * Contact: <my_scripts2001@yahoo.com>, <gvaish@iitk.ac.in>
 * Implementation: yes
 * Status:  100%
 *
 * (C) Gaurav Vaish (2001)
 */

namespace System.Web.Util
{
	public delegate void FileChangeEventHandler(object sender, int method);
}

--- NEW FILE: FileChangedEventArgs.cs ---
/**
 * Namespace: System.Web.Util
 * Class:     FileChangedEventArgs
 *
 * Author:  Gaurav Vaish
 * Maintainer: gvaish@iitk.ac.in
 * Contact: <my_scripts2001@yahoo.com>, <gvaish@iitk.ac.in>
 * Implementation: yes
 * Status:  ??%
 *
 * (C) Gaurav Vaish (2001)
 */

namespace System.Web.Util
{
	internal class FileChangedEventArgs : EventArgs
	{
		private string filename;
		private FileAction action;

		public void FileChangedEvent(FileAction action, string file)
		{
			this.action = action;
			this.filename = file;
		}

		public string FileName
		{
			get
			{
				return filename;
			}
		}

		public FileAction Action
		{
			get
			{
				return action;
			}
		}
	}
}

--- NEW FILE: FileChangesMonitor.cs ---
/**
 * 
 * Namespace: System.Web.Util
 * Class:     FileChangesMonitor
 * 
 * Author:  Gaurav Vaish
 * Maintainer: gvaish@iitk.ac.in
 * Contact: <my_scripts2001@yahoo.com>, <gvaish@iitk.ac.in>
 * Implementation: yes
 * Status:  ??%
 *
 * 
 * (C) Gaurav Vaish (2001)
 */

using System;
using System.IO;
using System.Web;
using System.Runtime.InteropServices;
using System.Collections;
using System.Threading;

namespace System.Web.Util
{
	internal class FileChangesMonitor
	{
		private static string BIN    = "bin";
		private static string BINDIR = "bin/";
		private static int MAXLEN = 260;
		
		private FileChangeEventHandler       cbRename;
		private NativeFileChangeEventHandler cbSubDirs;
		
		private int       monitoredSubdirs;
		private string    rootDir;
		private Hashtable allDirs;
		private GCHandle  rootcbSubDirs;
		
		private ReaderWriterLock rwLock;
		
		public FileChangesMonitor()
		{
			allDirs = new Hashtable(WebHashCodeProvider.Default, WebEqualComparer.Default);
			rwLock  = new ReaderWriterLock();
		}
		
		/// <param name="file">Name of the file</param>
		/// <param name="mTime">Last modification date</param>
		/// <param name="length">Legnth of the file</param>
		[MonoTODO]
		public void GetFileAttributes(string file, out DateTime mTime, long length)
		{
			if(!Path.IsPathRooted(file))
			{
				throw new HttpException(HttpRuntime.FormatResourceString("Path_must_be_rooted"));
			}
			// TODO: finish this
			mTime = DateTime.Now;
			throw new NotImplementedException();
		}
	}
}

--- NEW FILE: FilePathParser.cs ---
/**
 * Namespace: System.Web.Util
 * Class:     FilePathParser
 *
 * Author:  Gaurav Vaish
 * Maintainer: gvaish@iitk.ac.in
 * Contact: <my_scripts2001@yahoo.com>, <gvaish@iitk.ac.in>
 * Implementation: yes
 * Status:  ??%
 *
 * (C) Gaurav Vaish (2001)
 */
using System.IO;

namespace System.Web.Util
{
	internal class FilePathParser
	{
		private static char[] pathSeparators = {
			Path.DirectorySeparatorChar,
			Path.AltDirectorySeparatorChar
		};
		
		private string dirName;
		private string fileName;
		private string shortDirName;
		private string shortFileName;
		
		private bool   exists;
		
		[MonoTODO]
		public FilePathParser(string path, bool isFile, bool getShortNames)
		{
			path = path.Trim();
			if(Path.GetPathRoot(path).Length < path.Length)
			{
				path = path.TrimEnd(pathSeparators);
			}
			if(!isFile)
			{
				dirName = GetBaseDirOrRoot(path);
			} else
			{
				dirName = path;
			}
			if(getShortNames)
			{
				if(!Directory.Exists(dirName))
				{
					dirName = null;
					return;
				}
				shortDirName = GetShortPathName(dirName);
				if(shortDirName==null)
				{
					dirName = null;
					return;
				}
				if(shortDirName == dirName)
				{
					shortDirName = null;
				} else
				{
					throw new NotImplementedException();
				}
			}
		}
		
		public static string GetBaseDirOrRoot(string file)
		{
			string bDir = Path.GetDirectoryName(file);
			return ( bDir!=null ? bDir : Path.GetPathRoot(file));
		}
		
		[MonoTODO("Native_Call_Required")]
		public static string GetShortPathName(string path)
		{
			//TODO: Native calls required, it's in kernel32.dll for windows
			throw new NotImplementedException();
		}
	}
}

--- NEW FILE: IISVersionInfo.cs ---
/**

 * Namespace: System.Web.Util
 * Class:     IISVersionInfo
 * 
 * Author:  Gaurav Vaish
 * Maintainer: gvaish@iitk.ac.in
 * Contact: <my_scripts2001@yahoo.com>, <gvaish@iitk.ac.in>
 * Implementation: yes
 * Status:  ??%

 *

 * (C) Gaurav Vaish (2001)

 */


using System;
using System.Diagnostics;
using System.Web;

namespace System.Web.Util
{
	//FIXME: This is highly Windows/IIS specific code. What about Apache related stuff?
	internal class IISVersionInfo
	{
		private static string isapiVersion;
		private static string mscoreeVersion;
		private static string systemWebVersion;

		private static readonly object lockObj = null;

		public IISVersionInfo()
		{
		}
		
		internal static string IsapiVersion
		{
			get
			{
				if(isapiVersion==null)
				{
					lock(lockObj)
					{
						// Recheck - another thread may have set the value
						// before entering lock / exiting previous lock
						if(isapiVersion==null)
						{
							//FIXME: What about Apache? What dll/shared-object to be loaded?
							isapiVersion = GetLoadedModuleVersion("aspnet_isapi.dll");
						}
					}
				}
				return isapiVersion;
			}
		}
		
		internal static string ClrVersion
		{
			get
			{
				if(mscoreeVersion==null)
				{
					lock(lockObj)
					{
						if(mscoreeVersion==null)
						{
							mscoreeVersion = GetLoadedModuleVersion("mscorlib.dll");
						}
					}
				}
				return mscoreeVersion;
			}
		}
		
		internal static string SystemWebVersion
		{
			get
			{
				if(systemWebVersion == null)
				{
					lock(lockObj)
					{
						if(systemWebVersion==null)
						{
							systemWebVersion = (FileVersionInfo.GetVersionInfo((typeof(HttpRuntime)).Module.FullyQualifiedName)).FileVersion;
						}
					}
				}
				return systemWebVersion;
			}
		}
				
		[MonoTODO]
		internal static string GetLoadedModuleVersion(string modulename)
		{
			//TODO: Load the version information from the module
			// Needs native calls - which ones, since the module will not be .Net aware
			throw new NotImplementedException();
		}
		
		[MonoTODO]
		internal static string GetLoadedModuleFilename(string modulename)
		{
			throw new NotImplementedException();
		}
	}
}

--- NEW FILE: NativeFileChangeEventHandler.cs ---
/**
 * Namespace: System.Web.Util
 * Class:     NativeFileChangeEventHandler
 *
 * Author:  Gaurav Vaish
 * Maintainer: gvaish@iitk.ac.in
 * Contact: <my_scripts2001@yahoo.com>, <gvaish@iitk.ac.in>
 * Implementation: yes
 * Status:  100%
 *
 * (C) Gaurav Vaish (2001)
 */

namespace System.Web.Util
{
	public delegate void NativeFileChangeEventHandler(object sender, int method);
}

--- NEW FILE: UrlUtils.cs ---
/**
 * Namespace: System.Web.UI.Util
 * Class:     UrlUtils
 * 
 * Author:  Gaurav Vaish
 * Maintainer: gvaish@iitk.ac.in
 * Status:  ??%
 * 
 * (C) Gaurav Vaish (2001)
 */

using System;
using System.Collections;
using System.Text;

namespace System.Web.Util
{
	internal class UrlUtils
	{
		/*
		 * I could not find these functions in the class System.Uri
		 * Besides, an instance of Uri will not be formed until and unless the address is of
		 * the form protocol://[user:pass]host[:port]/[fullpath]
		 * ie, a protocol, and that too without any blanks before,
		 * is a must which may not be the case here.
		 * Important: Escaped URL is assumed here. nothing like .aspx?path=/something
		 * It should be .aspx?path=%2Fsomething
		 */
		public static string GetProtocol(string url)
		{
			//Taking code from Java Class java.net.URL
			if(url!=null)
			{
				if(url.Length>0)
				{
					
					int i, start = 0, limit;
					limit = url.Length;
					char c;
					bool aRef = false;
					while( (limit > 0) && (url[limit-1] <= ' '))
					{
						limit --;
					}
					while( (start < limit) && (url[start] <= ' '))
					{
						start++;
					}
					if(RegionMatches(true, url, start, "url:", 0, 4))
					{
						start += 4;
					}
					if(start < url.Length && url[start]=='#')
					{
						aRef = true;
					}
					for(i = start; !aRef && (i < limit) && ((c=url[i]) != '/'); i++)
					{
						if(c==':')
						{
							return url.Substring(start, i - start);
						}
					}
				}
			}
			return String.Empty;
		}
		
		public static bool IsRelativeUrl(string url)
		{
			if(url.IndexOf(':') != -1)
				return !IsRootUrl(url);
			return true;
		}

		public static bool IsRootUrl(string url)
		{
			if(url!=null)
			{
				if(url.Length>0)
				{
					return IsValidProtocol(GetProtocol(url).ToLower());
				}
			}
			return true;
		}
		
		public static bool IsRooted(string path)
		{
			if(path!=null && path.Length > 0)
			{
				return (path[0]=='/' || path[0]=='\\');
			}
			return false;
		}
		
		public static void FailIfPhysicalPath(string path)
		{
			if(path!= null && path.Length > 0)
			{
				if(path[0]==':' || path.StartsWith(@"\\"))
					throw new HttpException(HttpRuntime.FormatResourceString("Physical_path_not_allowed", path));
			}
		}
		
		public static string Combine(string basePath, string relPath)
		{
			FailIfPhysicalPath(relPath);
			if(IsRootUrl(relPath))
			{
				if(relPath != null && relPath.Length > 0)
				{
					return Reduce(relPath);
				}
				return String.Empty;
			}
			if(relPath.Length < 3 || relPath[0]!='~' || (relPath[0]!='/' && relPath[0]!='\\'))
			{
				if(basePath==null || basePath.Length==1 || basePath[0]=='/')
					basePath = String.Empty;
				return Reduce(basePath + "/" + relPath);
			}
			string vPath = HttpRuntime.AppDomainAppVirtualPath;
			if(vPath.Length <= 1)
				vPath = String.Empty;
			return Reduce(vPath + "/" + relPath.Substring(2));
		}
		
		public static bool IsValidProtocol(string protocol)
		{
			if(protocol.Length < 1)
				return false;
			char c = protocol[0];
			if(!Char.IsLetter(c))
			{
				return false;
			}
			for(int i=1; i < protocol.Length; i++)
			{
				c = protocol[i];
				if(!Char.IsLetterOrDigit(c) && c!='.' && c!='+' && c!='-')
				{
					return false;
				}
			}
			return true;
		}
		
		/*
		 * MakeRelative("http://www.foo.com/bar1/bar2/file","http://www.foo.com/bar1")
		 * will return "bar2/file"
		 * while MakeRelative("http://www.foo.com/bar1/...","http://www.anotherfoo.com")
		 * return 'null' and so does the call
		 * MakeRelative("http://www.foo.com/bar1/bar2","http://www.foo.com/bar")
		 */
		public static string MakeRelative(string fullUrl, string relativeTo)
		{
			if(fullUrl==relativeTo)
			{
				return String.Empty;
			}
			if(fullUrl.IndexOf(relativeTo)!=0)
			{
				return null;
			}
			string leftOver = fullUrl.Substring(relativeTo.Length);
			if(!fullUrl.EndsWith("/") && !leftOver.StartsWith("/"))
			{
				return null;
			}
			if(leftOver.StartsWith("/"))
			{
				leftOver = leftOver.Substring(1);
			}
			return leftOver;
		}
		
		/*
		 * Check JavaDocs for java.lang.String#RegionMatches(bool, int, String, int, int)
		 * Could not find anything similar in the System.String class
		 */
		public static bool RegionMatches(bool ignoreCase, string source, int start, string match, int offset, int len)
		{
			if(source!=null || match!=null)
			{
				if(source.Length>0 && match.Length>0)
				{
					char[] ta = source.ToCharArray();
					char[] pa = match.ToCharArray();
					if((offset < 0) || (start < 0) || (start > (source.Length - len)) || (offset > (match.Length - len)))
					{
						return false;
					}
					while(len-- > 0)
					{
						char c1 = ta[start++];
						char c2 = pa[offset++];
						if(c1==c2)
							continue;
						if(ignoreCase)
						{
							if(Char.ToUpper(c1)==Char.ToUpper(c2))
								continue;
							// Check for Gregorian Calendar where the above may not hold good
							if(Char.ToLower(c1)==Char.ToLower(c2))
								continue;
						}
						return false;
					}
					return true;
				}
			}
			return false;
		}

		public static string Reduce(string path)
		{
			int len = path.Length;
			int dotIndex = -1;
			path = path.Replace('\\','/');
			while(true)
			{
				dotIndex++;
				dotIndex = path.IndexOf('.', dotIndex);
				if(dotIndex < 0)
				{
					return path;
				}
				if(dotIndex != 0 && path[dotIndex -1]=='/')
					continue;
				if(dotIndex+1 == len || path[dotIndex+1]=='/')
					break;
				if(path[dotIndex+1]=='.')
					continue;
				if(dotIndex+2 == len || path[dotIndex+2]=='/')
					break;
			}
			ArrayList list = new ArrayList();
			StringBuilder sb = new StringBuilder();
			dotIndex = 0;
			int temp;
			do
			{
				temp = dotIndex;
				dotIndex = path.IndexOf('/', temp + 1);
				if(dotIndex < 0)
					dotIndex = len;
				if( (dotIndex - temp) <= 3 && (dotIndex < 1 || path[dotIndex - 1]== '.') && ( (temp+1) >= len || path[temp+1]=='.') )
				{
					if(dotIndex - temp == 3)
						continue;
					if(list.Count == 0)
						throw new System.Web.HttpException(System.Web.HttpRuntime.FormatResourceString("Cannot_exit_up_top_directory"));
					sb.Length = (int) list[list.Count - 1];
					list.RemoveRange(list.Count - 1, 1);
					continue;
				}
				list.Add(sb.Length);
				sb.Append(path, temp, dotIndex - temp);
			} while(dotIndex != len);
			return sb.ToString();
		}
		
		public static string GetDirectory(string url)
		{
			if(url==null)
			{
				return null;
			}
			if(url.Length==0)
			{
				return String.Empty;
			}
			url.Replace('\\','/');
			string baseDir = url.Substring(0, url.LastIndexOf('/'));
			if(baseDir.Length==0)
			{
				baseDir = "/";
			}
			return baseDir;
		}
	}
}

--- NEW FILE: WebEqualComparer.cs ---
/**
 * Namespace: System.Web.Util
 * Class:     WebEqualComparer
 *
 * Author:  Gaurav Vaish
 * Maintainer: gvaish@iitk.ac.in
 * Contact: <my_scripts2001@yahoo.com>, <gvaish@iitk.ac.in>
 * Implementation: yes
 * Status:  ??%
 *
 * (C) Gaurav Vaish (2001)
 */

using System;
using System.Globalization;
using System.Collections;

namespace System.Web.Util
{
	public class WebEqualComparer : IComparer
	{
		private static IComparer defC;

		public WebEqualComparer()
		{
		}

		public static IComparer Default
		{
			get
			{
				if(defC == null)
				{
					defC = new WebEqualComparer();
				}
				return defC;
			}
		}

		/// <summary>
		/// To compare two strings
		/// </summary>
		/// <remarks>
		/// Cannot apply String.Compare(..) since I am at web
		/// </remarks>
		int IComparer.Compare(object left, object right)
		{
			string leftStr, rightStr;
			leftStr = null;
			rightStr = null;
			if(left is string)
			{
				leftStr = (string)left;
			}
			if(right is string)
			{
				rightStr = (string)right;
			}

			if(leftStr==null || rightStr==null)
			{
				throw new ArgumentException();
			}

			int ll = leftStr.Length;
			int lr = rightStr.Length;
			if(ll==0 && lr==0)
			{
				return 0;
			}

			if(ll==0 || lr==0)
			{
				return ( (ll > 0) ? 1 : -1);
			}

			char cl,cr;
			int i=0;
			for(i=0; i < leftStr.Length; i++)
			{
				if(i==lr)
				{
					return 1;
				}
				cl = leftStr[i];
				cr = leftStr[i];
				if(cl==cr)
				{
					continue;
				}
				UnicodeCategory ucl = Char.GetUnicodeCategory(cl);
				UnicodeCategory ucr = Char.GetUnicodeCategory(cr);
				if(ucl==ucr)
				{
					return ( (cl > cr) ? 1 : -1 );
				}
				cl = Char.ToLower(cl);
				cr = Char.ToLower(cr);
				if(cl!=cr)
				{
					return ( (cl > cr) ? 1 : -1);
				}
			}
			return ( (i==lr) ? 0 : -1 );
		}
	}
}

--- NEW FILE: WebHashCodeProvider.cs ---
/**

 * Namespace: System.Web.Util
 * Class:     WebHashCodeProvider
 *

 * Author:  Gaurav Vaish

 * Maintainer: gvaish@iitk.ac.in

 * Contact: <my_scripts2001@yahoo.com>, <gvaish@iitk.ac.in>

 * Implementation: yes

 * Status:  ??%

 *

 * (C) Gaurav Vaish (2001)

 */


using System.Collections;
using System.Globalization;

namespace System.Web.Util
{
	public class WebHashCodeProvider : IHashCodeProvider
	{
		private static IHashCodeProvider defHcp;

		public WebHashCodeProvider()
		{
		}
		
		int IHashCodeProvider.GetHashCode(object key)
		{
			return Default.GetHashCode(key);
		}

		public static IHashCodeProvider Default
		{
			get
			{
				if(defHcp==null)
				{
					 defHcp = new CaseInsensitiveHashCodeProvider(CultureInfo.InvariantCulture);
				}
				return defHcp;
			}
		}
	}
}