Note: This is not the complete source code--just the main source file.
You can download the full source (with include files) from our
sample code archive by clicking on the diskette icons.
<%
'// Browser Mirror engine
'// version 2002-02-16
'//
'// Displays information that your browser reveals to servers.
'//
'// Inputs (form variables):
'// none
'//
'// HexGadgets (components) required:
'// none
'//
'// Other dependencies:
'// - VBScript 5.0 or later
'// Get the latest at http://msdn.microsoft.com/scripting/
'//
'// History:
'// 2002-02-16 Created
'//
'// Copyright 2002 Hexillion Technologies. All rights reserved.
'//
'// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY
'// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT
'// LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND/OR
'// FITNESS FOR A PARTICULAR PURPOSE.
const sBrowserMirrorSession = "BrowserMirrorSession"
const sBrowserMirrorPersistent = "BrowserMirrorPersistent"
const sHexUtilityVars = "HexUtilityVars"
const sAspSession = "ASPSESSIONID"
class BrowserMirror
private m_dtCookie
property Get Name()
Name = "Browser Mirror"
end property
property Get Desc()
Desc = "See what your browser reveals"
end property
property Get ViewSourceURL()
ViewSourceURL = "http://www.hexillion.com/samples/view_src.asp?name=BrowserMirror.inc.vbs.asp"
end property
property Get DownloadSourceURL()
DownloadSourceURL = "http://www.hexillion.com/samples/#BrowserMirror"
end property
Private Sub Class_Initialize()
'// Get date for designating current cookies
m_dtCookie = now()
end sub
Private Sub Class_Terminate()
end sub
public function GetHead()
'// Returns a string to put between the <head></head> tags
'// Build cookie strings
dim sSession, sPersist
sPersist = "BrowserMirrorPersistent=" & _
server.URLEncode( m_dtCookie ) & _
"; expires=" & FormatGMT( DateAdd( "yyyy", 1, m_dtCookie ) ) & _
"; path=/"
sSession = "BrowserMirrorSession=" & _
server.URLEncode( m_dtCookie ) & _
"; path=/"
'// Set cookies with meta tags and JavaScript to try to circumvent HTTP header filtering
GetHead = "<meta http-equiv=""Set-Cookie"" content=""" & sPersist & """>" & vbcrlf & _
"<meta http-equiv=""Set-Cookie"" content=""" & sSession & """>" & vbcrlf & _
"<SCRIPT LANGUAGE=""JavaScript"" TYPE=""text/javascript""><!--" & vbcrlf & _
" // Intentional obfuscation to evade JavaScript ""sanitizers""" & vbcrlf & _
" var d1 = document;" & vbcrlf & _
" var c1 = 'c' + 'o' + 'o' + 'k' + 'i' + 'e';" & vbcrlf & _
" d1[c1] = '" & sPersist & "';" & vbcrlf & _
" d1[c1] = '" & sSession & "';" & vbcrlf & _
"//--></SCRIPT>"
end function
private function FormatGMT( dt )
'// Put date into string format appropriate for cookie expiration dates
FormatGMT = WeekdayName( Weekday( dt ), true ) & ", " & _
Format00( Day( dt ) ) & "-" & _
MonthName( Month( dt ), true ) & "-" & _
cstr( Year( dt ) ) & " " & _
Format00( Hour( dt ) ) & ":" & _
Format00( Minute( dt ) ) & ":" & _
Format00( Second( dt ) ) & " GMT"
end function
private function Format00( i )
if i < 10 then
Format00 = "0" + cstr( i )
else
Format00 = cstr( i )
end if
end function
Sub WriteForm()
'// No input form needed
end sub
sub WriteOutput()
'// Grab incoming test cookies first because setting them in
'// the response will change them in the request. (ASP bug?)
dim sCookieSession, sCookiePersistent
sCookieSession = Request.Cookies( sBrowserMirrorSession )
sCookiePersistent = Request.Cookies( sBrowserMirrorPersistent )
'// Set test cookies before flushing output
Response.Cookies( sBrowserMirrorSession ) = m_dtCookie
Response.Cookies( sBrowserMirrorSession ).Path = "/"
Response.Cookies( sBrowserMirrorPersistent ) = m_dtCookie
Response.Cookies( sBrowserMirrorPersistent ).Expires = DateAdd( "yyyy", 1, m_dtCookie )
Response.Cookies( sBrowserMirrorPersistent ).Path = "/"
'// Display any output so far
Response.Flush
ShowConnectionInfo
ShowHeaders
ShowCookies m_dtCookie, sCookieSession, sCookiePersistent
ShowScripting
end sub
private sub ShowConnectionInfo
'// Write heading
WriteLn "<h3>Connection</h3>"
dim sRequest
sRequest = request( "REQUEST_METHOD" ) & " " & request( "URL" )
if "" <> request( "QUERY_STRING" ) then sRequest = sRequest & "?" & request( "QUERY_STRING" )
sRequest = sRequest & " " & request( "SERVER_PROTOCOL" )
dim sCrypto
if "on" = request( "HTTPS" ) then
sCrypto = request( "HTTPS_KEYSIZE" ) & "-bit session key"
else
sCrypto = "none"
end if
dim sDomDoss
sDomDoss = "DomainDossier.vbs.asp?dom_whois=1&net_whois=1&dom_dns=1&addr=" & request( "REMOTE_ADDR" )
'// Write connection info
WriteLn "<table border=""0"" cellpadding=""5"" cellspacing=""0"">"
WriteLn " <tr>"
WriteLn " <td valign=""baseline"" align=""right"">client IP address:</td>"
WriteLn " <td valign=""baseline"">"
WriteLn " <span class=""ipaddr"">" & request( "REMOTE_ADDR" ) & "</span> "
WriteLn " <a href=""" & sDomDoss & """>[see what this reveals]</a>"
WriteLn " </td>"
WriteLn " </tr>"
WriteLn " <tr>"
WriteLn " <td valign=""baseline"" align=""right"">server port:</td>"
WriteLn " <td valign=""baseline""><b>" & request( "SERVER_PORT" ) & "</b></td>"
WriteLn " </tr>"
WriteLn " <tr>"
WriteLn " <td valign=""baseline"" align=""right"">request:</td>"
WriteLn " <td valign=""baseline""><b>" & sRequest & "</b></td>"
WriteLn " </tr>"
WriteLn " <tr>"
WriteLn " <td valign=""baseline"" align=""right"">encryption:</td>"
WriteLn " <td valign=""baseline""><b>" & sCrypto & "</b></td>"
WriteLn " </tr>"
if "" <> request( "AUTH_TYPE" ) then
WriteLn " <tr>"
WriteLn " <td valign=""baseline"" align=""right"">authentication:</td>"
WriteLn " <td valign=""baseline""><b>" & request( "AUTH_TYPE" ) & "</b></td>"
WriteLn " </tr>"
WriteLn " <tr>"
WriteLn " <td valign=""baseline"" align=""right"">username:</td>"
WriteLn " <td valign=""baseline""><b>" & request( "AUTH_USER" ) & "</b></td>"
WriteLn " </tr>"
if "basic" = lcase( request( "AUTH_TYPE" ) ) then
WriteLn " <tr>"
WriteLn " <td valign=""baseline"" align=""right"">password:</td>"
WriteLn " <td valign=""baseline""><b>" & request( "AUTH_PASSWORD" ) & "</b></td>"
WriteLn " </tr>"
end if
else
WriteLn " <tr>"
WriteLn " <td valign=""baseline"" align=""right"">authentication:</td>"
WriteLn " <td valign=""baseline""><b>none</b></td>"
WriteLn " </tr>"
end if
WriteLn "</table>"
Response.Flush
end sub
private sub ShowHeaders
'// Write heading
WriteLn "<h3>HTTP headers</h3>"
'// Write HTTP headers
WriteLn "<pre>" & server.HTMLEncode( Request.ServerVariables( "ALL_RAW" ) ) & "</pre>"
Response.Flush
end sub
private sub ShowCookies( dtNew, sCookieSession, sCookiePersistent )
'// Write heading
WriteLn "<h3>Cookies</h3>"
dim sAcceptSession, sAcceptPersist, sSendSession, sSendPersist, sAspSession
dim sButton
sAcceptSession = "?"
sAcceptPersist = "?"
sSendSession = "?"
sSendPersist = "?"
sButton = "complete test"
'// If this is a postback...
if "" <> Request.Form( "key" ) then
dim sDate
sDate = Request.Form( "key" )
'// If we got the session cookie we just set...
if sDate = sCookieSession then
sAcceptSession = "yes"
sSendSession = "yes"
'// Else if we at least got an old session cookie...
elseif 0 <> len( sCookieSession ) then
sAcceptSession = "no"
sSendSession = "yes"
else
'// Cookie was neither received nor sent
sAcceptSession = "no"
sSendSession = "no"
end if
'// If we got the persistent cookie we just set...
if sDate = sCookiePersistent then
sAcceptPersist = "yes"
sSendPersist = "yes"
'// Else if we at least got an old persistent cookie...
elseif 0 <> len( sCookiePersistent ) then
sAcceptPersist = "no"
sSendPersist = "yes"
else
'// Cookie was neither received nor sent
sAcceptPersist = "no"
sSendPersist = "no"
end if
sButton = "test again"
end if
'// Search for known cookies
dim s, aCookies
'// Use HTTP_Cookie because we've already set the Response
'// cookies and ASP has put them in the Request.Cookies
aCookies = split( request( "HTTP_Cookie" ), " " )
for each s in aCookies
if left( s, len( sBrowserMirrorSession ) ) = sBrowserMirrorSession then
sSendSession = "yes"
elseif left( s, len( sBrowserMirrorPersistent ) ) = sBrowserMirrorPersistent then
sSendPersist = "yes"
elseif left( s, len( sHexUtilityVars ) ) = sHexUtilityVars then
sSendSession = "yes"
elseif left( s, len( sAspSession ) ) = sAspSession then
sSendSession = "yes"
end if
next
WriteLn "<table border=""0"" cellpadding=""5"" cellspacing=""0"">"
WriteLn " <tr>"
WriteLn " <td valign=""baseline"" align=""right""> </td>"
WriteLn " <td valign=""baseline"" align=""center"">accepting</td>"
WriteLn " <td valign=""baseline"" align=""center"">sending</td>"
WriteLn " </tr>"
WriteLn " <tr>"
WriteLn " <td valign=""baseline"" align=""right"">session</td>"
WriteLn " <td valign=""baseline"" align=""center""><b>" & sAcceptSession & "</b></td>"
WriteLn " <td valign=""baseline"" align=""center""><b>" & sSendSession & "</b></td>"
WriteLn " </tr>"
WriteLn " <tr>"
WriteLn " <td valign=""baseline"" align=""right"">persistent</td>"
WriteLn " <td valign=""baseline"" align=""center""><b>" & sAcceptPersist & "</b></td>"
WriteLn " <td valign=""baseline"" align=""center""><b>" & sSendPersist & "</b></td>"
WriteLn " </tr>"
WriteLn "</table>"
WriteLn "<form name=""cookieform"" method=""POST"" action=""" & request( "SCRIPT_NAME" ) & """>"
WriteLn " <input type=""hidden"" name=""key"" value=""" & dtNew & """>"
WriteLn " <input id=""cookietest"" type=""submit"" value=""" & sButton & """>"
WriteLn "</form>"
Response.Flush
end sub
private sub ShowScripting
'// This isn't meant to be an exhaustive list of all that can
'// be obtained via client-side scripting. It just samples some
'// of the more interesting items.
'// Notice the obfuscation. The SafeWeb.com anonymizing service
'// (which PrivaSec.com licenses) tries to "sanitize" JavaScript
'// instead of stripping it out entirely. It breaks blocks of JS
'// that it finds suspicious. The obfuscation tries to circumvent
'// the sanitizing, though in some cases it's overkill--the sanitizing
'// just doesn't work very well. It's also quite erratic, breaking
'// innocent code while letting evil stuff slip right by.
'// Observations about the SafeWeb sanitizing:
'//
'// - Suspicious assignments are flagged with extra semicolons on the end:
'// var suspect = 'suspicious';;
'//
'// - In the vicinity of suspicious code, any function calls get broken
'// with extra parentheses:
'// document.writeln()('My innocent text');
'//
'// - Javascript comments are stripped out everywhere *except* suspicious blocks.
'//
'// - For all the effort that the SafeWeb people apparently put into the
'// sanitizer, they missed a number of obvious security holes. For example,
'// Netscape browsers can still reveal the user's true IP address via
'// java.net.InetAddress.getLocalHost().getHostAddress();
'// Duh.
'//
'// - SafeWeb's "paranoid" mode does little more than modify all document.write
'// and document.writeln calls to write blanks. This will break a lot of
'// innocent code but is easily circumvented. And Netscape will still display
'// the true IP address. So much for paranoia.
'//
'// More about SafeWeb:
'// http://www.safeweb.com/
'// http://www.privasec.com/
'// http://www.wired.com/news/politics/0,1283,50371,00.html
'// http://www.cs.bu.edu/techreports/pdf/2002-003-deanonymizing-safeweb.pdf
%>
<h3>Client-side scripting</h3>
<script language="JavaScript"><!--
var version = '1.0';
var d = document;
var n = navigator;
var w = 'w' + 'r' + 'i' + 't' + 'e' + 'l' + 'n';
// SafeWeb's paranoid mode makes *any* VBScript
// method called write or writeln shoot blanks, so
// we've made this handy little function that
// VBScript can call to display its output.
function jsdw( s )
{
d[w]( s );
}
//--></script>
<script language="JavaScript1.1"><!--
var version = '1.1';
// Turn off error reporting
window.onerror = null;
//--></SCRIPT>
<script language="JavaScript1.2"><!--
var version = '1.2';
//--></script>
<script language="JavaScript1.3"><!--
var version = '1.3';
//--></script>
<script language="JavaScript1.4"><!--
var version = '1.4';
//--></script>
<script language="JavaScript1.5"><!--
var version = '1.5';
//--></script>
<script language="JavaScript1.6"><!--
var version = '1.6';
//--></script>
<script language="JavaScript2.0"><!--
var version = '2.0';
//--></script>
<table border="0" cellpadding="5" cellspacing="0">
<tr>
<td valign="baseline" align="right">JavaScript:</td>
<td valign="baseline">
<b>
<SCRIPT LANGUAGE="JavaScript" TYPE="text/javascript"><!--
d[w]( 'version ' + version );
//--></SCRIPT>
<noscript>disabled/not supported</noscript>
</b>
</td>
</tr>
<tr>
<td valign="baseline" align="right">VBScript:</td>
<td valign="baseline"><b ID="vbs">disabled/not supported</b></td>
<SCRIPT LANGUAGE="VBScript" TYPE="text/vbscript"><!--
'// This technique won't work for IE 3.
document.all( "vbs" ).firstChild.nodeValue = "version " & ScriptEngineMajorVersion & "." & ScriptEngineMinorVersion & "." & ScriptEngineBuildVersion
'--></SCRIPT>
</tr>
<tr>
<td valign="baseline" align="right">Java:</td>
<td valign="baseline">
<b>
<SCRIPT LANGUAGE="JavaScript" TYPE="text/javascript"><!--
// SafeWeb/PrivaSec is suspicious of this block and breaks it.
// By leaving this block in, however, the next block escapes breakage.
document.writeln( '' );
//--></SCRIPT>
<SCRIPT LANGUAGE="JavaScript" TYPE="text/javascript"><!--
var je = 'j' + 'a' + 'v' + 'a' + 'E' + 'n' + 'a' + 'b' + 'l' + 'e' + 'd';
if( n[je]() )
{
d[w]( 'enabled' );
}
//--></SCRIPT>
<applet height="0" width="0">disabled/not supported</applet>
</b>
</td>
</tr>
<SCRIPT LANGUAGE="JavaScript" TYPE="text/javascript"><!--
// Personal profile
/*
var n = navigator;
if( "undefined" != typeof( n['userProfile'] ) )
{
var profile = n['userProfile'];
profile.clearRequest();
profile.addReadRequest("Vcard.FirstName");
profile.addReadRequest("Vcard.LastName");
profile.addReadRequest("Vcard.Email");
profile.addReadRequest("Vcard.Home.Phone");
profile.doReadRequest(1,"Browser Mirror");
var name = profile.getAttribute("Vcard.FirstName") + ' ' + profile.getAttribute("Vcard.LastName" );
var email = profile.getAttribute("Vcard.Email");
var phone = profile.getAttribute("Vcard.Home.Phone");
if( ' ' != name )
{
d[w]( '<tr>' );
d[w]( '<td valign="baseline" align="right">name:</td>' );
d[w]( '<td valign="baseline"><b>' + name + '</b></td>' );
d[w]( '</tr>' );
}
if( '' != email )
{
d[w]( '<tr>' );
d[w]( '<td valign="baseline" align="right">email:</td>' );
d[w]( '<td valign="baseline"><b>' + email + '</b></td>' );
d[w]( '</tr>' );
}
if( '' != phone )
{
d[w]( '<tr>' );
d[w]( '<td valign="baseline" align="right">home phone:</td>' );
d[w]( '<td valign="baseline"><b>' + phone + '</b></td>' );
d[w]( '</tr>' );
}
}
*/
//--></SCRIPT>
<SCRIPT LANGUAGE="JavaScript" TYPE="text/javascript"><!--
// Try to get IP address
if( "undefined" != typeof( java ) )
{
var j = java;
var IPAddress = j.net.InetAddress.getLocalHost().getHostAddress();
}
// Close and reopen script block--a Java exception could kill this block
//--></SCRIPT>
<SCRIPT LANGUAGE="JavaScript" TYPE="text/javascript"><!--
// IP Address
if( IPAddress )
{
d[w]( '<tr>' );
d[w]( '<td valign="baseline" align="right">IP address:</td>' );
d[w]( '<td valign="baseline"><span class="ipaddr">' + IPAddress + '</span>' );
d[w]( '<a href="DomainDossier.vbs.asp?dom_whois=1&net_whois=1&dom_dns=1&addr=' + IPAddress + '"> [see what this reveals]</a></td>' );
d[w]( '</tr>' );
}
//--></SCRIPT>
<SCRIPT LANGUAGE="JavaScript" TYPE="text/javascript"><!--
// Cookies
// SafeWeb/PrivaSec and other services aggregate cookies from *all* sites
// you visit into one master cookie, which the following will reveal.
var c = 'c' + 'o' + 'o' + 'k' + 'i' + 'e';
var gotcha = d[c];
if( gotcha )
{
d[w]( '<tr>' );
d[w]( '<td valign="baseline" align="right">cookies:</td>' );
d[w]( '<td valign="baseline"><b>' + gotcha + '</b></td>' );
d[w]( '</tr>' );
}
//--></SCRIPT>
<SCRIPT LANGUAGE="JavaScript" TYPE="text/javascript"><!--
// Referrer
if( d['referrer'] )
{
d[w]( '<tr>' );
d[w]( '<td valign="baseline" align="right">referrer:</td>' );
d[w]( '<td valign="baseline"><b>' + d['referrer'] + '</b></td>' );
d[w]( '</tr>' );
}
//--></SCRIPT>
<SCRIPT LANGUAGE="JavaScript" TYPE="text/javascript"><!--
// Browser
var n = navigator;
var ua = 'u' + 's' + 'e' + 'r' + 'A' + 'g' + 'e' + 'n' + 't';
var browser = n[ua];
d[w]( '<tr>' );
d[w]( '<td valign="baseline" align="right">browser:</td>' );
d[w]( '<td valign="baseline"><b>' + browser + '</b></td>' );
d[w]( '</tr>' );
//--></SCRIPT>
<SCRIPT LANGUAGE="JavaScript" TYPE="text/javascript"><!--
// Plugins - Netscape
var pi = 'p' + 'l' + 'u' + 'g' + 'i' + 'n' + 's';
if( "undefined" != typeof( n[pi] ) )
{
var ps = n[pi];
if( ps.length > 0 )
{
d[w]( '<tr>' );
d[w]( '<td valign="top" align="right">plugins:</td>' );
d[w]( '<td valign="top">' );
d[w]( '<table border="0" cellpadding="5" cellspacing="0">' );
for( var i=0; i<ps.length; i++ )
{
d[w]( '<tr>' );
d[w]( '<td valign="baseline"><b>' + ps[i].name + '</b></td>' );
d[w]( '<td valign="baseline"><b>' + ps[i].description + '</b></td>' );
d[w]( '<td valign="baseline"><b>' );
for( var i2=0; i2<ps[i].length; i2++ )
{
d[w]( ps[i][i2].type + '<br>' );
}
d[w]( '</b></td>' );
d[w]( '<td valign="baseline"><b>' + ps[i].filename + '</b></td>' );
d[w]( '</tr>' );
}
d[w]( '</table>' );
d[w]( '</td></tr>' );
}
}
//--></SCRIPT>
<SCRIPT LANGUAGE="VBScript" TYPE="text/vbscript"><!--
'// ActiveX plugins - IE
sub Detect( ProgID, Description )
On Error resume next
dim o
if ScriptEngineMajorVersion() >= 2 then
set o = CreateObject( ProgID )
if Err = 0 then jsdw Description & "<br>"
end if
end sub
jsdw "<tr>"
jsdw "<td valign=""baseline"" align=""right"">ActiveX:</td>"
jsdw "<td valign=""baseline""><b>"
Detect "ShockwaveFlash.ShockwaveFlash", "Macromedia Flash Player"
Detect "SWCtl.SWCtl", "Macromedia Shockwave Player"
Detect "Macromedia.ActiveShockwave.1", "Active Shockwave"
Detect "RealPlayer.RealPlayer(tm) ActiveX Control (32-bit)", "RealPlayer"
Detect "rmocx.RealPlayer G2 Control", "RealPlayer G2"
Detect "IERJCtl.IERJCtl.1", "RealJukebox"
Detect "MediaPlayer.MediaPlayer.1", "MediaPlayer"
Detect "PDF.PdfCtrl.1", "Adobe Acrobat 1.0 Reader"
Detect "PDF.PdfCtrl.2", "Adobe Acrobat 2.0 Reader"
Detect "PDF.PdfCtrl.3", "Adobe Acrobat 3.0 Reader"
Detect "PDF.PdfCtrl.4", "Adobe Acrobat 4.0 Reader"
Detect "PDF.PdfCtrl.5", "Adobe Acrobat 5.0 Reader"
Detect "Agent.Control.1", "MS Agent 1.5"
Detect "Agent.Control.2", "MS Agent 2.0"
Detect "MSComCtl2.Animation", "MS Animation"
Detect "DirectAnimation.DirectAnimationIntegratedMediaControl.1", "MS DirectAnimation"
Detect "MSVRML2C.VRMLBrowserCtl.1", "MS VRML 2.0 Viewer"
jsdw "</b></td>"
jsdw "</tr>"
'--></SCRIPT>
<SCRIPT LANGUAGE="JavaScript" TYPE="text/javascript"><!--
// SafeWeb/PrivaSec is suspicious of this block and breaks it.
// By leaving this block in, however, the next block escapes breakage.
document.writeln( '' );
//--></SCRIPT>
<SCRIPT LANGUAGE="JavaScript" TYPE="text/javascript"><!--
// Clipboard
var ec = 'e' + 'x' + 'e' + 'c' + 'C' + 'o' + 'm' + 'm' + 'a' + 'n' + 'd';
var pste = 'p' + 'a' + 's' + 't' + 'e';
var ctr = 'c' + 'r' + 'e' + 'a' + 't' + 'e' + 'T' + 'e' + 'x' + 't' + 'R' + 'a' + 'n' + 'g' + 'e';
if( "undefined" != typeof( d[ec] ) )
{
d[w]( '<tr>' );
d[w]( '<td valign="top" align="right">clipboard:</td>' );
d[w]( '<td><form name="clipform">' );
d[w]( '<textarea id="cliptext" rows="5" cols="50"></textarea>' );
d[w]( '</form></td>' );
d[w]( '</tr>' );
d['clipform']['cliptext']['focus']();
d['clipform']['cliptext'][ctr]()[ec]( pste );
window['scroll']( 0, 0 );
}
//--></SCRIPT>
<SCRIPT LANGUAGE="JavaScript" TYPE="text/javascript"><!--
// Local time
d[w]( '<tr>' );
d[w]( '<td valign="baseline" align="right">local time:</td>' );
d[w]( '<td valign="baseline"><b>' + (new Date()) + '</b></td>' );
d[w]( '</tr>' );
//--></SCRIPT>
<SCRIPT LANGUAGE="JavaScript" TYPE="text/javascript"><!--
// Screen dimensions
if( "undefined" != typeof( screen ) )
{
d[w]( '<tr>' );
d[w]( '<td valign="baseline" align="right">screen:</td>' );
d[w]( '<td valign="baseline"><b>' + screen.width + 'x' + screen.height + ' ' + screen.colorDepth + ' bits/pixel</b></td>' );
d[w]( '</tr>' );
}
//--></SCRIPT>
<SCRIPT LANGUAGE="JavaScript" TYPE="text/javascript"><!--
// Browser window dimensions
if( "undefined" != typeof( window.screenX ) &&
"undefined" != typeof( window.screenY ) &&
"undefined" != typeof( window.outerWidth ) &&
"undefined" != typeof( window.outerHeight ) )
{
d[w]( '<tr>' );
d[w]( '<td valign="baseline" align="right">window:</td>' );
d[w]( '<td valign="baseline"><b>' + window.outerWidth + 'x' + window.outerHeight + ' (' + window.screenX + ',' + window.screenY + ')</b></td>' );
d[w]( '</tr>' );
}
//--></SCRIPT>
<SCRIPT LANGUAGE="JavaScript" TYPE="text/javascript"><!--
// Web page dimensions
if( "undefined" != typeof( window.innerWidth ) &&
"undefined" != typeof( window.innerHeight ) )
{
d[w]( '<tr>' );
d[w]( '<td valign="baseline" align="right">page:</td>' );
d[w]( '<td valign="baseline"><b>' + window.innerWidth + 'x' + window.innerHeight + '</b></td>' );
d[w]( '</tr>' );
}
else if( "undefined" != typeof( document.body ) )
{
if( "undefined" != typeof( document.body.clientWidth ) &&
"undefined" != typeof( document.body.clientHeight ) )
{
d[w]( '<tr>' );
d[w]( '<td valign="baseline" align="right">page:</td>' );
d[w]( '<td valign="baseline"><b>' + document.body.clientWidth + 'x' + document.body.clientHeight + '</b></td>' );
d[w]( '</tr>' );
}
}
//--></SCRIPT>
</table>
<%
end sub
private sub WriteLn( s )
Response.Write s & vbcrlf
end sub
end class
%>