// This file is part of the BrowserHawk software and provided
// under the BrowserHawk End User License Agreement.
// Copyright (c) 2007-2008 cyScape, Inc.  www.cyscape.com

// *****************************
// USAGE INSTRUCTIONS: Search for all "TODO" strings contained in this file and make 
// the changes as instructed at each point.  Note that you must also set up the
// BrowserHawk Reports Web Service (BRWS) prior to using. See the BH docs for details.
// *****************************

// TODO: Include this JS file in the master page or main template of your web site.
// Example usage:
//   <script src="bhawk_errortracker.js" type="text/javascript">&nbsp;</script>
// The above example uses a relative path.  It's also possible to use
// an absolute path, helpful sometimes for use from ASP.NET master pages.
//   <script src="/js/bhawk_errortracker.js" type="text/javascript">&nbsp;</script>
// Note: The &nbsp; as shown in the lines above is a workaround for an IE issue; don't remove it.

// Set this to false if you want to temporarily stop logging.
// Note you can override its value in the main page as well.
var enableLogging = true;

// Dictate what happens when an error is caught.
// Note this overrides any previous setting.
onerror = $_event_onerror;

// TODO: Set this to the location of the BRWS server.  The address
// needs to be visible from the client's perspective.
// Do NOT include http or https on the URL.
//var recordServer = 'yourhost/brws/cyscapeBRWS.dll';
//var recordServer = 'yourhost:8080/reports/brws';

// TODO: When you have configured the above, comment out the following line:
alert("Before using BrowserHawk error logging you must edit the recordServer entry in the bhawk_errortracker.js file");

// Sets a cap on the max number of errors reported per page.
var maxErrorsPerPage = 3;

// Set to false to avoid sending the user-agent header
var enableUserAgentLogging = true;

// If "user" or "session" are set they'll be recorded with the entry.
// You can set them as the value of a cookie or something else.
var user = null;          // configure as you like, maybe read from a cookie
var session = null;       // configure as you like, maybe read from a cookie
// var session = bhawk_getcookie('ASP.NET_SessionId');  // .NET example
// var session = bhawk_getcookie('JSESSIONID');         // Servlet example

// It's often useful to store extra data with each entry.  If
// you want to do that, assign string, int, or double values to
// one or more of these variables.  To set values without altering
// this JavaScript file you may want to read text from a getElementById()
// call.
var extraString1 = null;
var extraString2 = null;
var extraString3 = null;
var extraString4 = null;
var extraString5 = null;
var extraInt1 = null;
var extraInt2 = null;
var extraInt3 = null;
var extraDouble1 = null;
var extraDouble2 = null;
var extraDouble3 = null;

// This data structure supports the suppress() function.  It
// holds error descriptions and error URLs which should be
// suppresed.  The data structure is an array of any length
// holding arrays of length two, first value an error
// description substring and second value a URL substring.
// One or both may be specified.  Each acts as a suppression
// rule.
var suppressItems = new Array(
  new Array("", "errorgen.js"),              // anything in errorgen.js
  new Array("is not defined", "mypage.html")  // specific error on specific page
)

// This function determines whether a certain hit should be
// suppressed.  For example, if it's a known issue that will
// be fixed later.  You can adjust the suppressItems array
// above or, for advanced users, reassign the suppress() function
// pointer on a specific page to alter this behavior in limitless
// ways.
function suppress(msg, url, line) {
  for (var i = 0; i < suppressItems.length; i++) {
    var item = suppressItems[i];
    var suppressMsg = item[0];
    var suppressUrl = item[1];
    if (msg != null && msg.indexOf(suppressMsg) >= 0 &&
        url != null && url.indexOf(suppressUrl) >= 0) {
      return true;
    }
  }
  return false;
}

// An internal bookkeeping variable.
errorLogCount = 0;

function $_event_log(strtolog) {
  var proto = document.location.protocol;
  if (proto != 'http:' && proto != 'https:') return;
  var pltImg = new Image(1, 1);
  pltImg.src = proto + '//' + recordServer + '?' + strtolog;
}

// Note: IE 6+ reports the url/line of the main page even if the error was included
function $_event_onerror(msg, url, line, errortype) {
  if (!enableLogging) {
    return true;
  }
  if (suppress(msg, url, line)) {
    return true;
  }
  if (++errorLogCount > maxErrorsPerPage) {
    return true;
  }
  if (!errortype) var errortype = "js";
  var user_part = (user == null) ? "" : "&u=" + encodeURIComponent(user);
  var session_part = (session == null) ? "" : "&s=" + encodeURIComponent(session);
  var ua_part = (!enableUserAgentLogging) ? "" : "&ua=" + encodeURIComponent(navigator.userAgent);
  var extraString1_part = (extraString1 == null) ? "" : "&uds1=" + encodeURIComponent(extraString1);
  var extraString2_part = (extraString2 == null) ? "" : "&uds2=" + encodeURIComponent(extraString2);
  var extraString3_part = (extraString3 == null) ? "" : "&uds3=" + encodeURIComponent(extraString3);
  var extraString4_part = (extraString4 == null) ? "" : "&uds4=" + encodeURIComponent(extraString4);
  var extraString5_part = (extraString5 == null) ? "" : "&uds5=" + encodeURIComponent(extraString5);
  var extraInt1_part = (extraInt1 == null) ? "" : "&udi1=" + encodeURIComponent(extraInt1);
  var extraInt2_part = (extraInt2 == null) ? "" : "&udi2=" + encodeURIComponent(extraInt2);
  var extraInt3_part = (extraInt3 == null) ? "" : "&udi3=" + encodeURIComponent(extraInt3);
  var extraDouble1_part = (extraDouble1 == null) ? "" : "&udd1=" + encodeURIComponent(extraDouble1);
  var extraDouble2_part = (extraDouble2 == null) ? "" : "&udd2=" + encodeURIComponent(extraDouble2);
  var extraDouble3_part = (extraDouble3 == null) ? "" : "&udd3=" + encodeURIComponent(extraDouble3);
  var errInfo = 'et='+errortype +
                '&es='+encodeURIComponent(msg) +
                '&ef='+encodeURIComponent(url) +
                '&el='+encodeURIComponent(line) +
                '&p='+encodeURIComponent(window.location)+
                user_part+
                session_part+
                ua_part+
                extraString1_part+extraString2_part+extraString3_part+extraString4_part+extraString5_part+
                extraInt1_part+extraInt2_part+extraInt3_part+
                extraDouble1_part+extraDouble2_part+extraDouble3_part+
                '&ev=2';
  $_event_log(errInfo);
}

// Helpful support function
function bhawk_getcookie(cname) {
   var cookie = new RegExp('\\b' + cname + '=([^;&]+)').exec(document.cookie);
   return cookie && cookie[1] ? decodeURIComponent(cookie[1]) : null;
}

// All uncaught JavaScript errors will be logged automatically. However you can also
// call this function manually to log any custom errors of your own as well!
function bhawk_logerror(errorstr, errorfile, errorline, errortype) {
  $_event_onerror(errorstr, errorfile, errorline, errortype);
}
