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)
83 data = new ListDictionary ();
85 data.Add (key, value);
88 public Hashtable GetProperties (Hashtable tbl)
91 parent.GetProperties (tbl);
93 foreach (string key in data.Keys)
94 tbl [key] = data [key];
99 public string GetParentName ()
101 return (string) data ["parent"];
104 public string GetAlternateBrowser ()
106 return (pattern == null) ? text : null;
109 public string GetBrowser ()
114 return (string) data ["browser"];
117 public bool IsMatch (string expression)
119 if (expression == null || expression.Length == 0)
123 if (text [0] != expression [0] ||
124 String.Compare (text, 1, expression, 1,
125 text.Length - 1, false,
126 CultureInfo.InvariantCulture) != 0) {
129 expression = expression.Substring (text.Length);
133 return expression.Length == 0;
137 regex = new Regex (pattern);
140 return regex.Match (expression).Success;
144 class CapabilitiesLoader : MarshalByRefObject
146 static volatile bool loaded;
147 static ICollection alldata;
148 static Hashtable defaultCaps;
149 static readonly object lockobj = new object ();
150 private CapabilitiesLoader () {}
152 static CapabilitiesLoader ()
154 defaultCaps = new Hashtable ();
155 defaultCaps.Add ("frames", "True");
156 defaultCaps.Add ("tables", "True");
159 public static Hashtable GetCapabilities (string userAgent)
162 if (userAgent != null)
163 userAgent = userAgent.Trim ();
165 if (alldata == null || userAgent == null || userAgent == "")
168 foreach (BrowserData bd in alldata) {
169 if (bd.IsMatch (userAgent))
170 return bd.GetProperties (new Hashtable ());
185 string filepath = "browscap.ini";
188 string dir = Path.GetDirectoryName (WebConfigurationManager.OpenMachineConfiguration().FilePath);
190 string dir = Path.GetDirectoryName (WebConfigurationSettings.MachineConfigPath);
192 string filepath = Path.Combine (dir, "browscap.ini");
193 if (!File.Exists (filepath)) {
194 // try removing the trailing version directory
195 dir = Path.GetDirectoryName (dir);
196 filepath = Path.Combine (dir, "browscap.ini");
201 } catch (Exception) { }
208 private static TextReader GetJavaTextReader(string filename)
213 java.lang.ClassLoader cl = (java.lang.ClassLoader)
214 AppDomain.CurrentDomain.GetData("GH_ContextClassLoader");
218 string custom = String.Concat("browscap/", filename);
220 java.io.InputStream inputStream = cl.getResourceAsStream(custom);
221 if (inputStream == null)
222 inputStream = cl.getResourceAsStream(filename);
224 s = (Stream)vmw.common.IOUtils.getStream(inputStream);
230 return new StreamReader (s);
234 static void LoadFile (string filename)
237 TextReader input = GetJavaTextReader(filename);
241 if (!File.Exists (filename))
244 TextReader input = new StreamReader (File.OpenRead (filename));
247 Hashtable allhash = new Hashtable ();
249 while ((str = input.ReadLine ()) != null) {
250 if (str.Length == 0 || str [0] == ';')
253 string userAgent = str.Substring (1, str.Length - 2);
254 BrowserData data = new BrowserData (userAgent);
255 ReadCapabilities (input, data);
257 /* Ignore default browser and file version information */
258 if (userAgent == "*" || userAgent == "GJK_Browscap_Version")
261 string key = data.GetBrowser ();
262 if (key == null || allhash.ContainsKey (key)) {
263 allhash.Add (aux++, data);
265 allhash.Add (key, data);
269 alldata = allhash.Values;
270 foreach (BrowserData data in alldata) {
271 if (data.Parent != null)
274 string pname = data.GetParentName ();
276 data.Parent = (BrowserData) allhash [pname];
280 static char [] eq = new char []{'='};
281 static void ReadCapabilities (TextReader input, BrowserData data)
284 while ((str = input.ReadLine ()) != null && str.Length != 0) {
285 string [] keyvalue = str.Split (eq, 2);
286 data.Add (keyvalue [0], keyvalue [1]);