Handling Other Browsers
If the user agent string contains the word compatible followed by a
semi-colon, the next word is usually the manufacturer or browser name.
Following the same style as we did with the other two browsers, but not knowing
the manufacturer's web address, we can use this approach to make it easy for
visitors to search for their browser manufacturer on the Web if they need an
upgrade.
This code runs when we know that it's not a Microsoft
browser, and that it's probably not a Netscape browser either. It pulls the
manufacturer's name or browser name out of the user agent string, and puts it
in a hyperlink to the AltaVista
search engine:
...
If
InStr(strUA, "compatible;") = 0 _
And
InStr(strUA, "Opera") = 0 Then
'its probably a Netscape browser
'...
'code for Netscape browser
'...
Else 'not Netscape, so we'll allow the user to search on the Web for it
If InStr(strUA, "Opera") Then
'Opera 3.60 doesn't include 'compatible'
in UA string
strProduct = Trim(Mid(strUA, InStr(strUA, ")") + 1))
Else
'use the part after the compatible
keyword
strProduct = Mid(strUA, Instr(strUA, "compatible;") + 11)
strProduct = Trim(Left(strProduct, Instr(strProduct, ";") -
1))
End If
strSearchURL
= "http://www.altavista.digital.com/cgi-bin/query?q=" _
& Server.URLEncode(strProduct & " web
browser")
Response.Write "Your browser is Navigator-compatible. You can
" _
& "search for the manufacturer using a search engine, such as
" _
& "<A HREF=" & QUOT & strSearchURL & QUOT
& ">" & strSearchURL _
& "</A></P>"
...
Notice how we have to perform a separate operation for Opera
3.60 because of the missing compatible
keyword.
Here's how this works in that browser – you can see the URL
and query string displayed in the Web page. Each '+' sign
represents a space in the query string value, and the encoding of the other
characters such as the decimal point in the version number and the square brackets
is also visible as their URL equivalents:

Clicking the link in the page opens the AltaVista search results page with
the results of a search on the browser name and version:

Using The Browser Capabilities Component
We've spent some time on the contents of the user agent
string, because it's useful to know how to interpret it. However, there are
components we can use to make identifying browsers easier and more accurate.
The downside is that they are likely to impose a heavier load on the server
than the few simple lines of script we've used so far.
ASP comes complete with a component called the Browser
Capabilities component. We met this in Chapter 2, when we used it
to figure out if the browser we were serving to supported frames:
...
Set objBCap =
Server.CreateObject("MSWC.BrowserType")
If Not(objBCap.frames) Then 'no frames support
Response.Clear
Response.Redirect
"mainpage.asp"
End If
...
The Browser Capabilities component uses the user agent
string sent from the browser to identify it as accurately as possible. In most
cases, for all the common browsers, it will identify it absolutely. This means
that it can accurately report the various abilities of that browser in detail.
In Windows 2000, there is a new version of the Browser
Capabilities component that adds a useful extra feature. It can use client-side
code to collect values from a specific user, as long as their browser supports
scripting. We'll come back to look at this topic once we've examined how the
component works.
The Browser Capabilities Information File
The information about all the browser types is stored in a
text file named browscap.ini, located in the same folder as the component
on the server. The default is Winnt\System32\inetsrv\
(or whatever the path to the %system32% folder actually is on your
machine). In this file are sections for each browser user agent string, for
example:
[Mozilla/4.0 (compatible; MSIE 5.0; Windows
95)*]
parent=IE 5.0
platform=Win95
The third line shows that the parent
for this entry is the entry for IE 5.0, and that only the platform
entry differs from those of the parent. The parent entry (elsewhere in the file)
looks like this:
[IE 5.0]
browser=IE
Version=5.0
majorver=#5
minorver=#0
frames=TRUE
tables=TRUE
cookies=TRUE
backgroundsounds=TRUE
vbscript=TRUE
javascript=TRUE
javaapplets=TRUE
ActiveXControls=TRUE
Win16=False
beta=False
AK=False
SK=False
AOL=False
crawler=False
CDF=True
Each of the entries in the file is available as a property
of the component, so we can do things like this:
...
<%
Set objBCap =
Server.CreateObject("MSWC.BrowserType")
'see
if this browser supports ActiveX Controls
If objBCap.ActiveXControls Then
%>
HTML here to define the ActiveX Control for
presenting some information
<% Else %>
HTML here to use a different way of
presenting the information
<% End If %>
...
Note how the component exposes the browser make and version,
which saves us having to use script to get at it like we did earlier:
...
strBrowserName = objBCap.browser 'a string defining the manufacturer
sngBrowserVersion =
CSng(objBCap.Version) 'a number for use in comparison tests
...
You can edit the file yourself, and add other browsers. You
can also add extra properties, because the component automatically exposes all
the entries it finds as properties. So, you could add the Web Home page URL for
each browser to the file if you wanted, making it easy to display it as a link
(like we did with ASP in our previous example). The file also accepts
wildcards, so you can – to some extent – future-proof for new browser versions.
For instance, an asterisk (*) matches any combination of
characters; so that [Mozilla/4.0 (compatible; MSIE 5.*) *] means any MSIE
version 5 browser on any platform. If the component cannot find an entry for a
browser, it sets all the properties to the string "UNKNOWN".
The IIS documentation (http://localhost/iishelp/)
contains more details about the Browser Capabilities component. Look up Browser
Capabilities in the Index. You can also download the latest
version of the browscap.ini
file from http://www.cyscape.com/browscap/.
Getting Client-Side Information With The Browser Capabilities Component
The new version of the Browser Capabilities component that
comes with ASP 3.0 in Windows 2000 has a neat feature that allows us to collect
information about each specific user's browser, rather than just relying on the
values that are generic to each browser. Obviously, the browscap.ini
file that the Browser Capabilities component uses to identify the browser from
its USER-AGENT
string can only contain general information that applies to that browser. In
other words, it can tell you if it supports frames or ActiveX controls, but it
can't tell you what screen resolution (for example) the user is running in.
To be able to create pages that are tailored to individual users,
rather than individual browsers, we have to be able to collect
information that is specific to each user. This is done by instructing the
browser to return the information in a cookie named BrowsCap,
which the ASP interpreter sends and receives when the page is first executed.
The instruction that tells ASP to do this is a special version of the METADATA
element:
<!--METADATA TYPE="Cookie"
NAME="BrowsCap"
SRC="url_of_page_that_creates_the_cookie"-->
ASP sees this element when loading the page, and does all
the work of sending and receiving the cookie. Then it takes the values stored
in the cookie and automatically adds them to the values that are available from
the browscap.ini
file for that browser. These values are only available for the duration of the
current page, so if you want to use them again you either have to re-send the
cookie (using the METADATA element again) or store them somewhere on the
server. The second option is obviously the best, and a useful trick is to store
them in the user's Session object.
The Client-Side 'Create Cookie' Page
We've provided a page that creates a cookie (make_cookie.htm)
containing client-side information, and which works in IE4+ and Navigator 4+
(although performance in Navigator is variable due to the caching of the pages
and cookie). The first part of the page defines an IE5-specific ClientCaps behavior, and attaches
it to an XML element in the page. This allows us to access features and
settings of the browser directly. The ClientCaps
behavior is built into IE5, and provides a whole range of information about the
browser.
In the opening <BODY> tag, we also specify the
function createCookie,
which will run when the page has loaded. Then comes the start of the <SCRIPT>
section where this function is defined:
<HTML XMLNS:IE>
<HEAD>
<STYLE>
IE\:clientcaps {behavior:url(#default#clientcaps)}
</STYLE>
</HEAD>
<BODY
ONLOAD="createCookie();">
<IE:clientcaps ID="objCCaps"
/>
<SCRIPT
LANGUAGE="JavaScript">
<!--
function createCookie() {
var strCookie = new String();
...
Now we have to decide which browser we are running under,
and create the cookie to return to the server. If it's Navigator 4, we can get
values from the screen and navigator objects:
...
if
(navigator.appName.indexOf('Netscape') != -1) {
if (navigator.appVersion.substr(0, 1) > 3) {
// Navigator 4 or higher
strCookie = 'width=' + window.screen.width
+ '&height=' + window.screen.height
+ '&availWidth=' +
window.screen.availWidth
+ '&availHeight=' + window.screen.availHeight
+ '&bufferDepth=' + window.screen.pixelDepth
+ '&colorDepth=' + window.screen.colorDepth
+ '&javaEnabled=' +
window.navigator.javaEnabled()
+ '&platform=' + window.navigator.platform
+ '&userLanguage=' +
window.navigator.language;
}
}
...
If it's IE4, we can also use the screen
and navigator
objects, though there are fewer properties available:
...
if
(navigator.appName.indexOf('Microsoft') != -1) {
window.onerror = stopAllErrors;
intPos = navigator.appVersion.indexOf('MSIE') + 5;
strVersion = navigator.appVersion.substr(intPos, 1);
if (strVersion == 4) {
// Internet Explorer 4
strCookie = 'width=' + window.screen.width
+ '&height=' + window.screen.height
+ '&bufferDepth=' + window.screen.bufferDepth
+ '&colorDepth=' + window.screen.colorDepth
+ '&javaEnabled=' +
window.navigator.javaEnabled()
+ '&cookieEnabled=' +
window.navigator.cookieEnabled;
}
...
Notice that we can prevent any errors from causing a dialog
to be displayed by setting the onerror property of the window
object to a function that simply returns the value true:
function stopAllErrors() {
return true; // prevent display
of any errors
}
If the browser is IE5, we can use the ClientCaps behavior object that we
created earlier in the page. This provides many more properties that we can
query:
...
if (strVersion > 4) {
// Internet Explorer 5 or higher
strCookie = 'width=' + objCCaps.width
+ '&height=' + objCCaps.height
+ '&availWidth=' + objCCaps.availWidth
+ '&availHeight=' + objCCaps.availHeight
+ '&bufferDepth=' + objCCaps.bufferDepth
+ '&colorDepth=' + objCCaps.colorDepth
+ '&javaEnabled=' + objCCaps.javaEnabled
+ '&cookieEnabled=' + objCCaps.cookieEnabled
+ '&connectionType=' + objCCaps.connectionType
+ '&platform=' + objCCaps.platform
+ '&cpuClass=' + objCCaps.cpuClass
+ '&systemLanguage=' + objCCaps.systemLanguage
+ '&userLanguage=' + objCCaps.userLanguage;
}
}
...
Once we've collected the values we need into our string, we
can assign it to the document's cookie property with the name 'BrowsCap' (note that you must always use this name for
the Browser Capabilities component to be able to recognize the cookie:
...
document.cookie = 'BrowsCap=' + strCookie;
}
By temporarily adding the line:
to the page, we can see the cookie that is created. Here it
is when the browser is IE5:

The Server-Side ASP Page
Having created our client-side page, we can now examine how
we use it with the Browser Capabilities component. The first step is to create
an instance of the component, and then provide the METADATA
element that instructs the component to send the make_cookie.htm
page to the client. On return, the values in the cookie are decoded and added
to the list of properties that are exposed by the Browser Capabilities
component:
<%@LANGUAGE="VBScript"%>
<%
'create
an instance of the component
Set objBCap =
Server.CreateObject("MSWC.BrowserType")
%>
<!--METADATA TYPE="Cookie"
NAME="BrowsCap" SRC="make_cookie.htm"-->
...
Now we can create a two-column table and place the values
from the Browser Capabilities component into it. We put the values that come
directly from the browscap.ini file in the left-hand column:
...
<HTML>
<HEAD><TITLE>The Browser
Capabilities Component</TITLE></HEAD>
<BODY BGCOLOR="#FFFFFF">
<SPAN CLASS="heading">The
Browser Capabilities Component</SPAN><HR>
<!--------------------------------------------------------------------------->
<TABLE WIDTH="100%">
<TR><TD VALIGN="TOP">
<DIV CLASS="subhead">Values
from the<BR>browscap.ini file:</DIV>
browser: <B><% = objBCap.browser
%></B><BR>
version: <B><% = objBCap.version
%></B><BR>
majorver: <B><% = objBCap.majorver
%></B><BR>
minorver: <B><% = objBCap.minorver
%></B><BR>
frames: <B><% = objBCap.frames
%></B><BR>
tables: <B><% = objBCap.tables
%></B><BR>
cookies: <B><% = objBCap.cookies
%></B><BR>
backgroundsounds: <B><% =
objBCap.backgroundsounds %></B><BR>
vbscript: <B><% = objBCap.vbscript
%></B><BR>
javascript: <B><% =
objBCap.javascript %></B><BR>
javaapplets: <B><% =
objBCap.javaapplets %></B><BR>
activexcontrols: <B><% =
objBCap.activexcontrols %></B><BR>
AK: <B><% = objBCap.AK
%></B><BR>
SK: <B><% = objBCap.SK
%></B><BR>
AOL: <B><% = objBCap.AOL
%></B><BR>
beta: <B><% = objBCap.beta
%></B><BR>
Win16: <B><% = objBCap.Win16
%></B><BR>
Crawler: <B><% = objBCap.Crawler
%></B><BR>
CDF: <B><% = objBCap.CDF
%></B><BR>
</TD>
...
Then, in the right-hand column, we place the values that
have been collected from the client and added to the list of properties exposed
by the Browser Capabilities component:
...
<TD VALIGN="TOP">
<DIV CLASS="subhead">Values
from the<BR>browser cookie:</DIV>
width: <B><% = objBCap.width
%></B><BR>
height: <B><% = objBCap.height
%></B><BR>
availWidth: <B><% =
objBCap.availWidth %></B><BR>
availHeight: <B><% =
objBCap.availHeight %></B><BR>
buffer/pixelDepth: <B><% =
objBCap.bufferDepth %></B><BR>
colorDepth: <B><% =
objBCap.colorDepth %></B><BR>
javaEnabled: <B><% =
objBCap.javaEnabled %></B><BR>
cookieEnabled: <B><% = objBCap.cookieEnabled
%></B><BR>
connectionType: <B><% =
objBCap.connectionType %></B><BR>
platform: <B><% = objBCap.platform
%></B><BR>
cpuClass: <B><% = objBCap.cpuClass
%></B><BR>
systemLanguage: <B><% =
objBCap.systemLanguage %></B><BR>
userLanguage: <B><% = objBCap.userLanguage
%></B><BR>
</TD></TR></TABLE>
</BODY>
</HTML>
And here's the result for IE5. You can see how the extra
client-specific properties provide useful information that you can use to
tailor your pages to that client, not only by sizing it appropriately, but by
changing the images to ones with a suitable color depth, which will give
optimal performance depending on the connection type (which can be over a LAN
or via a modem):

The CyScape 'BrowserHawk' Component
While the Browser Capabilities component is a great deal
quicker, easier and more accurate than our attempts at browser detection with
script, it's still not perfect. Another approach is taken by CyScape Inc, who not only provide
updated versions of browscap.ini, but also manufacture a component called BrowserHawk.
This recognizes many more different types of browsers, and provides a lot more
information about each one. There is also a version available as a JavaBean.
You'll find CyScape at http://www.cyscape.com/

BrowserHawk can tell you if the browser supports Style
Sheets and CSS, File Uploads, and SSL encrypted communication, as well as many
other features. In fact there is a whole section of the site devoted to the
advantages of BrowserHawk over the Browser Capabilities component, starting at http://www.cyscape.com/browserhawk/intro.asp.

The latest version of BrowserHawk (BrowserHawk 2000) also supports two
new features. It can use a cookie to obtain specific information from each
client, in much that same way as the Browser Capabilities component does.
However, his feature works in all IE, Netscape, Opera 3.x and upward browsers,
not just in IE5 as the method we described earlier with the Browser
Capabilities component. The user details that are available include:
q
Automatic detection of disabled JavaScript and disabled
Java applets
q
Users screen size resolution and available browser
window height/width
q
Detection of Macromedia Flash and Directory plugins
q
Detection of user's connection speed in kilobits per
second!
q
Detection of disabled cookies
BrowserHawk also offers a 'live update' feature, where the
server can query and automatically download and install new versions of the configuration
file direct from the CyScape
Web site at specific intervals.
To change over from the Microsoft Browser Capabilities
component to BrowserHawk is easy. You just download and install BrowserHawk,
then change the class string in the Server.CreateObject statement that
creates the component instance to "cyScape.browserObj".
The remainder of your code (according to CyScape)
will continue to work as normal, though there is a section of their Web site
devoted to issues that may arise. For more information, or to download an
evaluation copy of BrowserHawk, go to http://www.cyscape.com/.