I'm so glad you asked this question! It has been bothering me forever. Basically what you have to do is get and parse one of the browscap files. I used the XML file. From there, you have to check each regex pattern against your user agent string. In the XML file, that is the "name" attribute of each browscapitem.
However, the patterns in the file have to be converted to real regex so C# will understand them. This is the main method required for your problem. Everything else is just a matter of parsing the different file types.
(I used this code to see what others did to make it work in PHP.)
public static Boolean BrowserPatternMatches(string pattern, string input)
{
string patternConverted = "^" + pattern
.Replace("\\", "\\\\")
.Replace(".", "\\.")
.Replace("?", ".")
.Replace("*", ".*")
.Replace("$", "\\$")
.Replace("[", "\\[")
.Replace("]", "\\]")
.Replace("|", "\\|")
.Replace("(", "\\(")
.Replace(")", "\\)")
.Replace("+", "\\+")
.Replace("{", "\\{")
.Replace("}", "\\}")
.Replace("%", "\\%")
+ "$";
Regex regex = new Regex(patternConverted);
return regex.IsMatch(input);
}
This is the meat of your problem. The rest is a matter of parsing the XML and getting those values. This is NOT my area of expertise, so I just did enough to get it functional. In my class I have:
private Dictionary<string, Dictionary<string, string>> dic = new Dictionary<string, Dictionary<string, string>>();
private void FillDictionary()
{
if (this.dic.Count == 0)
{
XmlTextReader reader = new XmlTextReader("browscap.xml");
while (reader.Read())
{
if (reader.Name == "browscapitem")
{
string pattern = reader.GetAttribute("name");
if (pattern != null)
{
if (!this.dic.ContainsKey(pattern))
{
Dictionary<string, string> properties = new Dictionary<string, string>();
while (reader.Read())
{
if (reader.Name == "browscapitem")
{
break;
}
if (reader.GetAttribute("name") != null)
{
properties.Add(reader.GetAttribute("name").ToLower(), reader.GetAttribute("value"));
}
}
this.dic.Add(pattern, properties);
}
}
}
}
}
}
The rest is just some trickery to fill in the "parent" properties. So once you find your match, you have to go back and find its parent, and its parent's parent, etc.
private Dictionary<string, string> GetBrowserProps(string parentId)
{
return this.dic[parentId];
}
public Dictionary<string, string> GetBrowserObject(string uaString)
{
this.FillDictionary();
bool found = false;
string foundKey = "";
foreach (string pattern in this.dic.Keys)
{
if (!found)
{
found = RecordBrowsers.BrowserPatternMatches(pattern, uaString);
if (found) { foundKey = pattern; break; }
}
}
Dictionary<string, string> browserProps = new Dictionary<string, string>();
if (foundKey != "")
{
browserProps = this.GetBrowserProps(foundKey);
Dictionary<string, string> current = this.GetBrowserProps(foundKey);
bool cont = current.ContainsKey("parent");
while (cont)
{
Dictionary<string, string> parent = this.GetBrowserProps(current["parent"]);
foreach (string s in parent.Keys)
{
if (!browserProps.ContainsKey(s))
{
browserProps.Add(s, parent[s]);
}
}
current = parent;
cont = current.ContainsKey("parent");
}
}
return browserProps;
}
Here are my tests for good measure:
Console.WriteLine("RecordBrowser started");
string[] strs = { "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/40.0.2214.94 Safari/537.36",
"Mozilla/5.0 (Windows NT 6.1; WOW64; rv:35.0) Gecko/20100101 Firefox/35.0",
"Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/40.0.2214.94 Safari/537.36 OPR/27.0.1689.66",
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/40.0.2214.94 Safari/537.36",
"Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US; rv:1.8.1.8pre) Gecko/20070928 Firefox/2.0.0.7 Navigator/9.0RC1",
"Mozilla/5.0 (X11; Linux x86_64; rv:17.0) Gecko/20121202 Firefox/17.0 Iceweasel/17.0.1"};
string[] expectedResults = { "Chrome 40.0", "Firefox 35.0", "Opera 27.0", "Chrome 40.0", "Netscape 9.0", "Iceweasel 17.0" };
for(int i=0; i<strs.Length; i++)
{
Dictionary<string, string> browserProps = this.GetBrowserObject(strs[i]);
if (browserProps["comment"] == expectedResults[i])
{
Console.WriteLine("test " + i + " passed");
}
else
{
Console.WriteLine("test " + i + " failed");
}
Console.WriteLine("**********************************************************");
}
Console.WriteLine("DONE");