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)) {
172 tbl = new Hashtable (StringComparer.InvariantCultureIgnoreCase);
174 tbl = new Hashtable (CaseInsensitiveHashCodeProvider.DefaultInvariant,
175 CaseInsensitiveComparer.DefaultInvariant);
178 return bd.GetProperties (tbl);
194 string filepath = "browscap.ini";
197 string dir = Path.GetDirectoryName (WebConfigurationManager.OpenMachineConfiguration().FilePath);
199 string dir = Path.GetDirectoryName (WebConfigurationSettings.MachineConfigPath);
201 string filepath = Path.Combine (dir, "browscap.ini");
202 if (!File.Exists (filepath)) {
203 // try removing the trailing version directory
204 dir = Path.GetDirectoryName (dir);
205 filepath = Path.Combine (dir, "browscap.ini");
210 } catch (Exception) { }
217 private static TextReader GetJavaTextReader(string filename)
222 java.lang.ClassLoader cl = (java.lang.ClassLoader)
223 AppDomain.CurrentDomain.GetData("GH_ContextClassLoader");
227 string custom = String.Concat("browscap/", filename);
229 java.io.InputStream inputStream = cl.getResourceAsStream(custom);
230 if (inputStream == null)
231 inputStream = cl.getResourceAsStream(filename);
233 s = (Stream)vmw.common.IOUtils.getStream(inputStream);
239 return new StreamReader (s);
243 static void LoadFile (string filename)
246 TextReader input = GetJavaTextReader(filename);
250 if (!File.Exists (filename))
253 TextReader input = new StreamReader (File.OpenRead (filename));
256 Hashtable allhash = new Hashtable ();
258 while ((str = input.ReadLine ()) != null) {
259 if (str.Length == 0 || str [0] == ';')
262 string userAgent = str.Substring (1, str.Length - 2);
263 BrowserData data = new BrowserData (userAgent);
264 ReadCapabilities (input, data);
266 /* Ignore default browser and file version information */
267 if (userAgent == "*" || userAgent == "GJK_Browscap_Version")
270 string key = data.GetBrowser ();
271 if (key == null || allhash.ContainsKey (key)) {
272 allhash.Add (aux++, data);
274 allhash.Add (key, data);
278 alldata = allhash.Values;
279 foreach (BrowserData data in alldata) {
280 if (data.Parent != null)
283 string pname = data.GetParentName ();
285 data.Parent = (BrowserData) allhash [pname];
289 static char [] eq = new char []{'='};
290 static void ReadCapabilities (TextReader input, BrowserData data)
293 while ((str = input.ReadLine ()) != null && str.Length != 0) {
294 string [] keyvalue = str.Split (eq, 2);
295 data.Add (keyvalue [0], keyvalue [1]);