2 // System.Web.CapabilitiesLoader
4 // Loads data from browscap.ini file provided by Gary J. Keith from
5 // http://www.GaryKeith.com/browsers. Please don't abuse the
6 // site when updating browscap.ini file. Use the update-browscap.exe tool.
9 // Gonzalo Paniagua Javier (gonzalo@ximian.com)
11 // (c) 2003 Novell, Inc. (http://www.novell.com)
15 // Permission is hereby granted, free of charge, to any person obtaining
16 // a copy of this software and associated documentation files (the
17 // "Software"), to deal in the Software without restriction, including
18 // without limitation the rights to use, copy, modify, merge, publish,
19 // distribute, sublicense, and/or sell copies of the Software, and to
20 // permit persons to whom the Software is furnished to do so, subject to
21 // the following conditions:
23 // The above copyright notice and this permission notice shall be
24 // included in all copies or substantial portions of the Software.
26 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
27 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
28 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
29 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
30 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
31 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
32 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
36 using System.Collections;
37 using System.Collections.Specialized;
38 using System.Globalization;
40 using System.Text.RegularExpressions;
41 using System.Web.Configuration;
47 static char [] wildchars = new char [] {'*', '?'};
54 public BrowserData (string pattern)
56 int norx = pattern.IndexOfAny (wildchars);
60 this.pattern = pattern.Substring (norx);
61 text = pattern.Substring (0, norx);
65 this.pattern = this.pattern.Replace (".", "\\.");
66 this.pattern = this.pattern.Replace ("(", "\\(");
67 this.pattern = this.pattern.Replace (")", "\\)");
68 this.pattern = this.pattern.Replace ("[", "\\[");
69 this.pattern = this.pattern.Replace ("]", "\\]");
70 this.pattern = this.pattern.Replace ("?", ".");
71 this.pattern = this.pattern.Replace ("*", ".*");
75 public BrowserData Parent {
76 get { return parent; }
77 set { parent = value; }
80 public void Add (string key, string value)
84 data = new ListDictionary ();
86 data.Add (key, value);
90 public Hashtable GetProperties (Hashtable tbl)
93 parent.GetProperties (tbl);
95 foreach (string key in data.Keys)
96 tbl [key] = data [key];
101 public string GetParentName ()
103 return (string) data ["parent"];
106 public string GetAlternateBrowser ()
108 return (pattern == null) ? text : null;
111 public string GetBrowser ()
116 return (string) data ["browser"];
119 public bool IsMatch (string expression)
121 if (expression == null || expression.Length == 0)
125 if (text [0] != expression [0] ||
126 String.Compare (text, 1, expression, 1,
127 text.Length - 1, false,
128 CultureInfo.InvariantCulture) != 0) {
131 expression = expression.Substring (text.Length);
136 return expression.Length == 0;
139 regex = new Regex (pattern);
142 return regex.Match (expression).Success;
146 class CapabilitiesLoader : MarshalByRefObject
149 static ICollection alldata;
150 static Hashtable defaultCaps;
151 private CapabilitiesLoader () {}
153 public static Hashtable GetCapabilities (string userAgent)
156 if (userAgent != null)
157 userAgent = userAgent.Trim ();
159 if (alldata == null || userAgent == null || userAgent == "")
160 return DefaultCapabilities;
162 foreach (BrowserData bd in alldata) {
163 if (bd.IsMatch (userAgent)) {
164 return bd.GetProperties (new Hashtable ());
168 return DefaultCapabilities;
173 lock (typeof (CapabilitiesLoader)) {
177 string path = Path.GetDirectoryName (WebConfigurationSettings.MachineConfigPath);
178 path = Path.Combine (path, "browscap.ini");
181 } catch (Exception) { }
187 static void LoadFile (string filename)
189 if (!File.Exists (filename))
192 TextReader input = new StreamReader (File.OpenRead (filename));
194 Hashtable allhash = new Hashtable ();
196 while ((str = input.ReadLine ()) != null) {
197 if (str.Length == 0 || str [0] == ';')
200 string userAgent = str.Substring (1, str.Length - 2);
201 BrowserData data = new BrowserData (userAgent);
202 ReadCapabilities (input, data);
204 /* Ignore default browser and file version information */
205 if (userAgent == "*" || userAgent == "GJK_Browscap_Version")
208 string key = data.GetBrowser ();
209 if (key == null || allhash.ContainsKey (key)) {
210 allhash.Add (aux++, data);
212 allhash.Add (key, data);
216 alldata = allhash.Values;
217 foreach (BrowserData data in alldata) {
218 if (data.Parent != null)
221 string pname = data.GetParentName ();
223 data.Parent = (BrowserData) allhash [pname];
227 static char [] eq = new char []{'='};
228 static void ReadCapabilities (TextReader input, BrowserData data)
231 while ((str = input.ReadLine ()) != null && str.Length != 0) {
232 string [] keyvalue = str.Split (eq, 2);
233 data.Add (keyvalue [0], keyvalue [1]);
237 static Hashtable DefaultCapabilities {
239 lock (typeof (CapabilitiesLoader)) {
240 if (defaultCaps != null)
243 defaultCaps = new Hashtable ();
244 defaultCaps.Add ("frames", "True");
245 defaultCaps.Add ("tables", "True");