Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why am I getting these strange results when looking at browser capabilities?

I am currently looking into browser capabilities and am trying to test the browser definition files that come with .NET 4.0. To do this I am using an add-on for Firefox to change the user agent and I have a simple page which reports on the following:

Request.UserAgent
Request.Browser.Id
Request.Browser.Browser
Request.Browser.MajorVersion
Request.Browser.MinorVersion
Request.Browser.Platform
Request.Browser.IsMobileDevice
Request.Browser.MobileDeviceManufacturer
Request.Browser.MobileDeviceModel

Generally this gives the correct information based on the examples provided in the comments in the default browser definition files. However I am seeing strange results from time to time that I cannot quite explain.

Take the example iPhone user agent in the iphone.browser definition file which is as follows:

Mozilla/5.0 (iPhone; U; CPU like Mac OS X; en) AppleWebKit/420+ (KHTML, like Gecko) Version/3.0 Mobile/1A543a Safari/419.3

This should return the browser as Safari, which it does. This is down to the IPhone gateway having Safari as a parent, which matches on the term Safari.

Altering the user agent slightly so it emulates the user agent of the mail client on an iPhone means removing the end part of the user agent as follows:

Mozilla/5.0 (iPhone; U; CPU like Mac OS X; en) AppleWebKit/420+ (KHTML, like Gecko)

This now should return Mozilla as the browser, as it will be unable to match on the term Safari. However, analysing this immediately after the first reports back incorrect information, and still indicates the browser to be Safari.

Adding a custom .browser file with the App_Browsers folder and then modifying that seems to force it to be correct temporarily, almost like the definitions or rules are being cached and not fully run on each request.

This works the other way too, if you start with the second example user agent then upon analysing the first it will report as being Mozilla instead of Safari.

Can anyone explain this behaviour or a way to work around it? Is it trying to do some sort of (not so) clever caching where it makes assumptions based on similar user agents?

Thanks.

like image 489
rrrr-o Avatar asked Nov 13 '22 14:11

rrrr-o


1 Answers

There is more to the match than just looking for the string "Safari". If you look at the user agent database used by Mono's ASP.Net implementation, you'll see that your first more specific user agent string will match one of the more specific rules, and the browser version will be set. But even the trimmed user agent string still hits a rule that identifies it as some variant of "iPhone", which is later presented as "Safari".

Microsoft's ASP.Net most likely uses a very similar database, I just used Mono as an example since the code is readily available on the web.


So, I revisited my answer, and realized I completely misinterpreted the question! You are right: caching is in action here. The .NET Framework tries to save time parsing the user-agent strings. Once a UA string is parsed, the result is saved in a hash table. The key is the UA string, truncated.

By default this key length is 64 characters, which is why when you change the end of a long UA string you observe no changes. This setting is controlled by the property UserAgentCacheKeyLength of HttpCapabilitiesDefaultProvider. To verify, I added

<browserCaps userAgentCacheKeyLength="512" />

to the <system.web> element in Web.config in my test project. With this quick fix the problem goes away.

like image 68
Greg Inozemtsev Avatar answered Dec 07 '22 23:12

Greg Inozemtsev