JScript ASP Library
Audience Level
Beginner and above.
Introduction
A bumper collection of Classic ASP (JScript) functions for use by web programmers. Functions are grouped together by functionality where convenient and are copy-pastable or downloadable from links under the source displays.
The Library
Six years of JScript ASP programming means that I have naturally collected functions that have saved not only programming time and effort but code around common gotchas. The scripts vary from very simple to more involved, but they're listed below because they are so useful to me time and time again when programming JScript ASP. This is only a partial list, there are at least as many again that could be here but they're much more involved and need more careful documentation so they're not listed here for the timebeing.
Table of Content
- Request.Form(), Request.QueryString() & Request.ServerVariables() Shortcuts
- Server.HTMLEncode() & Server.URLEncode() Shortcuts
- appendToQuerystring()
- isNumber() & isBoolean()
- objectEnumerate()
- trim(), capitalise() & prefixPad()
- ADO Enumerations
- Database Connections
- Debugging
- enumerateCollection()
- sendEmail() & emailReport()
- propError()
Request.Form(), Request.QueryString() & Request.ServerVariables() Shortcuts
This first set falls into the “simple” category and provide shortcuts to the Form, QueryString and
ServerVariables collections. However, they do make for nicer ways to dereference these collections because they return consistent
results and always de-reference the first “Item(1)” for the requested
“Key”.
The “RQ” and “RF” functions always return strings, including
null strings “""” when there's either no data or no such querystring
“Key”. The “RQI” and “RFI” functions
always either return a trimmed and parsed Integer number or null — the latter being returned instead of
“NaN” because “NaN” is too much hassle to work with reliably.
These two also protect against acquiring “QNaN” error values from attempting to convert
nulls to Integer numbers. “RS” works the same way as “RQ” but using the “ServerVariables”
collection.
Function: RF()
History:
20050131 1549GMT v1 Andrew Urquhart Comment added
*/
function RF(strKey) {
var objKey = Request.Form(strKey);
return (objKey.Count ? objKey.Item(1) : "");
}
/*
Function: RQ()
History:
20050131 1551GMT v1 Andrew Urquhart Comment added
*/
function RQ(strKey) {
var objKey = Request.QueryString(strKey);
return (objKey.Count ? objKey.Item(1) : "");
}
/*
Function: RFI()
Description: Like RF() but returns integers. Note that NaN => null;
History:
20060608 0920BST v1 Andrew Urquhart Created
*/
function RFI(strKey) {
var objKey = Request.Form(strKey);
var intVal = objKey.Count ? parseInt(objKey.Item(1).trim(), 10) : NaN;
return (isNaN(intVal) ? null : intVal);
}
/*
Function: RQI()
Description: Like RQ() but returns integers. Note that NaN => null;
History:
20060608 0920BST v1 Andrew Urquhart Created
*/
function RQI(strKey) {
var objKey = Request.QueryString(strKey);
var intVal = objKey.Count ? parseInt(objKey.Item(1).trim(), 10) : NaN;
return (isNaN(intVal) ? null : intVal);
}
/*
Function: RS()
History:
20060321 1446GMT v1 Andrew Urquhart Created
*/
function RS(strKey) {
var objKey = Request.ServerVariables(strKey);
return (objKey.Count ? objKey.Item(1) : "");
}
Download the JScript ASP source directly.
Server.HTMLEncode() & Server.URLEncode() Shortcuts
More shortcuts to built-in functions, this time shortcuts to the two functions that are the last step in protecting
against XSS exploits. The shortcuts perform the useful workaround for
the errors that occur when attempting to encode “null” or “undefined” values.
Normally these two data values will cause the built-in functions to throw exceptions, but these shortcuts encode these values
to harmless null strings, which is usually what you intended to do and just makes for one less thing to worry about.
Function: hEnc()
Description: Sugar wrapper for Server.HTMLEncode to cope with nulls and undefined values
Returns: String
History:
20060330 1447BST v1 Andrew Urquhart Created
*/
function hEnc(strRawHTML) {
return (strRawHTML === null || strRawHTML === undefined ? "" : Server.HTMLEncode(strRawHTML));
}
/*
Function: uEnc()
Description: Sugar wrapper for Server.URLEncode to cope with nulls and undefined values
Returns: String
History:
20060413 1053BST v1 Andrew Urquhart Created
*/
function uEnc(strData) {
return (strData === null || strData === undefined || (typeof strData == "number" && isNaN(strData)) ? "" : Server.URLEncode(strData));
}
Download the JScript ASP source directly.
appendToQuerystring()
When building up a URI with a querystring you often have to append a new key-value pairs to the querystring. However,
you don't always know if the URI already contains a querystring and so don't know whether you need to prepend with
a question mark or an ampersand before you add your new key-value pair or pairs. This function works that out for you
and returns the correctly formated URI by inserting a question mark or ampersand before your fragment. You just give it
the current URI and then the key-value pair(s) you want to add to it as part of the querystring,
e.g. “key=value&key=value”.
Function: appendToQuerystring()
Description: Adds a combination of querystring 'key=value&key=value' to a URI and correctly inserts linking '?' or '&' as required
Returns: String (URI)
History:
20060815 1542BST v1 Andrew Urquhart Created
*/
function appendToQuerystring(strUri, strQSFragment) {
if (!strUri) {
throw new Error(1, "Required parameter \"strUri\" was not defined");
}
if (!strQSFragment) {
throw new Error(2, "Required parameter \"strQSFragment\" was not defined");
}
if (strUri.indexOf("?") > 0) {
if (strUri.charAt(strUri.length - 1) != "?") {
strUri += "&";
}
}
else {
strUri += "?"
}
return strUri + strQSFragment;
}
Download the JScript ASP source directly.
isNumber() & isBoolean()
“isNumber()” I find incredibly useful because “NaN” is such
a slippery thing to deal with since it gets past “typeof” checking, so this function
is a simple wrapper to test both the “typeof” and the “NaN”
state of a number — whilst simple it almost entirely removes those “NaN” hassles.
“isBoolean()” is similar but is a straight “typeof” check. Of course
there could be others such as “isString()”, “isNull()”,
“isObject()” and “isFunction()” etc. but on the whole I don't
tend to need them so they are omitted here and left as an exercise for the reader!
Function: isNumber()
Description:
Returns:
History:
20060608 0928BST v1 Andrew Urquhart Created
*/
function isNumber(varData) {
if (typeof varData !== "number" || isNaN(varData)) {
return false;
}
return true;
}
/*
Function: isBoolean()
Description:
Returns:
History:
20060608 0928BST v1 Andrew Urquhart Created
*/
function isBoolean(varData) {
if (typeof varData === "boolean") {
return true;
}
return false;
}
Download the JScript ASP source directly.
objectEnumerate()
“objectenumerate” is simple but extremely useful function that overrides the default
“toString()” method of all Objects and their derivations (so that's pretty much everything in
javascript). It's so useful because when you want to debug an object the built-in “toString()”
method that is invoked by implicitly casting to a String will return the following: “[object Object]”,
which is not much use to anyone. However, by defining “objectEnumerate()” as described then
any objects implicitly (or explicitly) cast to strings will enumerate the properties of the object and return a CSV string of
them, which can allow you to determine what the object is and what its state is.
/*
Function: objectEnumerate()
Description: Overrides the default implicit cast to string function for Objects in order to enumerate their contents in CSV format
Returns: CSV String
History:
20060203 1256GMT v1 Andrew Urquhart Created
*/
function objectEnumerate() {
var a = [];
for (var e in this) {
var strType = typeof this[e];
if (strType != "function") {
a.push(e + ":" + (strType == "string" ? "\"" : "") + ("" + this[e]).replace(/"/g,"\\\"") + (strType == "string" ? "\"" : ""))
}
}
return "{" + a.join(", ") + "}";
}
Download the JScript ASP source directly.
trim(), capitalise() & prefixPad()
The next three functions are attached as methods to the “String” object and prefixPad() is also attached as
a method to the “Number” object. trim is commonly defined so you should have seen it already to remove
white-space before and after a string, although not always seen as a “String” method, e.g.
“var myCompactVar = myPaddedVar.trim()”. “capitalise()” sets the first letter
of a “String” to be a capital letter and leaves the remaining characters in whatever
case they were in. The same function invoked as “capitalise(true)” does the same but forces
all other characters to become lowercase.
“prefixPad()” acts on strings and numbers (converting the latter to a “String”).
Without any input parameters the function pads out a string or number to at least two characters long and pads with a "0" character.
This is intended mainly for presenting hours, days and seconds in a familiar 2-digit format. Optionally you can specify the
character to pad with and how much minimum padding is required. For example you could use it for white-space padding.
String.prototype.capitalise = capitalise;
String.prototype.prefixPad = prefixPad;
Number.prototype.prefixPad = prefixPad;
/*
Function: trim()
Description:
Returns:
History:
20050202 2215GMT v1 Andrew Urquhart Comment added
*/
function trim() {
var strInput = String(this);
if (typeof strInput == "undefined" || strInput == null) {
return this;
}
return strInput.replace(/^\s+|\s+$/g, "");
}
/*
Function: capitalise()
Description:
Returns:
History:
20050131 1552GMT v1 Andrew Urquhart Comment added and updated readability
*/
function capitalise(blnForceLowercase) {
var strInput = String(this);
if (typeof strInput == "undefined" || strInput == null) {
return this;
}
var objWords = ("" + strInput).split(/\s+/);
for (var i in objWords) {
var strWord = objWords[i];
objWords[i] = strWord.charAt(0).toUpperCase() + (blnForceLowercase ? strWord.substring(1).toLowerCase() : strWord.substring(1));
}
return objWords.join(" ");
}
/*
Function: prefixPad()
Description:
Returns:
History:
20050202 2234GMT v1 Andrew Urquhart Comment added
*/
function prefixPad(strPadChar, intLength) {
try {
if (!strPadChar) {
var strPadChar = "0";
}
if (!intLength) {
var intLength = 2;
}
var strInput = String(this);
if (typeof strInput == "undefined" || strInput == null) {
return this;
}
for (var i=strInput.length; i<intLength; ++i) {
strInput = strPadChar + strInput;
}
return strInput;
}
catch (err) {
propError(err, arguments);
}
}
Download the JScript ASP source directly.
ADO Enumerations
“enumerateADOErrors()” takes an ADO connection object and returns a formatted report on
what, if any, errors were found in the ADO Error collection. “enumerateCommandParameters()”
takes an ADO Command object as its argument and returns a formatted report on the parameters being passed across to
a stored procedure, including return code and input/output parameter names and values. Both are intended for
debugging and automated error reports.
Function: enumerateADOErrors()
Description: Enumerate the ADO connection errors collection
Returns: String
History:
20060209 1011GMT v1 Andrew Urquhart Created
*/
function enumerateADOErrors(objAdoConn) {
try {
if (!objAdoConn) {
throw new Error(1, "Required parameter \"objAdoConn\" was not defined");
}
var intErrCount = objAdoConn.Errors.Count;
var arrErrs = [];
arrErrs.push("ADO CONNECTION ERROR REPORT (" + intErrCount + " ERRORS)");
if (intErrCount > 0) {
// Enumerate over all errors in error collection
for (var objAdoErrorsEnum=new Enumerator(objAdoConn.Errors); !objAdoErrorsEnum.atEnd();objAdoErrorsEnum.moveNext()) {
var objAdoError = objAdoErrorsEnum.item();
arrErrs.push("Number: " + objAdoError.Number);
arrErrs.push("\tSource: " + objAdoError.Source);
arrErrs.push("\tDescription: " + objAdoError.Description);
arrErrs.push("\tHelpFile: " + objAdoError.HelpFile);
arrErrs.push("\tHelpContext: " + objAdoError.HelpContext);
arrErrs.push("\tSQLState: " + objAdoError.SQLState);
arrErrs.push("\tNativeError: " + objAdoError.NativeError);
}
}
else {
arrErrs.push("[No errors found!]");
}
return arrErrs.join("\r\n");
}
catch (err) {
propError(err, arguments);
}
}
/*
Function: enumerateCommandParameters()
Description: Like enumerateADOErrors() but for an ADO Command object
Returns:
History:
20060703 1347BST v1 Andrew Urquhart Created
*/
function enumerateCommandParameters(objCmd) {
try {
var objO = [];
var intMaxKeyLen = 0;
objO.push("DEFINED COMMAND OBJECT PARAMETERS\r\n=================================\r\n");
if (!objCmd) {
objO.push("[ Invalid Command object ]");
}
else if (!objCmd.Parameters) {
objO.push("[ Command object has no parameters ]");
}
else {
var objParams = new Enumerator(objCmd.Parameters);
// Determine width of longest key name
for (; !objParams.atEnd(); objParams.moveNext()) {
var intKeyLen = objParams.item().Name.length;
if (intKeyLen > intMaxKeyLen) {
intMaxKeyLen = intKeyLen;
}
}
// Write key: value pairs out
for (objParams.moveFirst(); !objParams.atEnd(); objParams.moveNext()) {
var objItem = objParams.item();
var strKeyName = objItem.Name.suffixPad("\u00a0", intMaxKeyLen);
var strKeyValue = ("" + objItem.Value).replace(/\n/g, "\\n").replace(/\r/g, "\\r").replace(/\t/g, "\\t");
objO.push(strKeyName + " : " + strKeyValue);
}
}
return objO.join("\r\n");
}
catch (err) {
propError(err, arguments);
}
}
Download the JScript ASP source directly.
Database Connections
Simple functions for getting and destroying database connections. “getDbConnection()”
returns a valid connection object given an ADO read/write mode (“adModeRead”,
“adModeWrite”, “adModeReadWrite”) and a connection string.
“getConn()” is a wrapper for “getDbConnection()” using a
connection string stored in “Application” space. “killConn()”
is a safe way to kill a connection object, especially when it's not known if the connection is active. An
additional function “doRollback()” is included for initiating ADO transaction rollbacks
whilst silently consuming the native exception that occurs if the transaction has already been rolled back.
Function: getDbConnection()
Description: Gets a database connection object
Returns: ADO Database connection object
History:
20051219 12:13GMT v1 Andrew Urquhart Created
*/
function getDbConnection(mode, strConnection) {
try {
if (typeof mode != "number") {
throw new Error(1, "Expected parameter \"mode\" was not a number");
}
if (!strConnection) {
throw new Error(2, "Expected parameter \"strConnection\" was not defined");
}
if (mode != adModeRead && mode != adModeWrite && mode != adModeReadWrite) {
throw new Error(3, "Unknown connection mode \"" + mode + "\" specified");
}
var objAdoConn = new ActiveXObject("ADODB.Connection");
objAdoConn.Mode = mode;
objAdoConn.Open(strConnection);
if (objAdoConn && objAdoConn.State != adStateOpen) {
throw new Error(4, "Failed to open requested database connection");
}
if (objAdoConn.Errors.Count > 0) {
throw new Error(5, enumerateADOErrors(objAdoConn));
}
return objAdoConn;
}
catch (err) {
propError(err, arguments);
}
}
/*
Function: getConn()
Description: Syntactic sugar for getDbConnection() with the MASTER_ADOCONN_STRING
Returns:
History:
20060413 0950BST v1 Andrew Urquhart Created
*/
function getConn(intAdoMode) {
try {
return getDbConnection(intAdoMode, Application("MASTER_ADOCONN_STRING"));
}
catch (err) {
propError(err, arguments);
}
}
/*
Function: killConn()
Description: Terminate an open database connection
Returns: Boolean true or null
History:
20060413 0957BST v1 Andrew Urquhart Created
*/
function killConn(adoConn) {
if (adoConn && adoConn.State != adStateClosed) {
adoConn.Close();
return true;
}
return null;
}
/*
Function: doRollback()
Description: Transaction rollback on a database connection that doesn't fail if their is no active transaction
Returns:
History:
20060913 1457BST v1 Andrew Urquhart Created
*/
function doRollback(objAdoConn) {
try {
if (objAdoConn && objAdoConn.State != adStateClosed) {
objAdoConn.RollbackTrans();
return true;
}
return null;
}
catch (err) {
if (err.number == -2147168242) {
return false; // No open transactions - i.e. probably already rolled back from further down the chain
}
else {
propError(err, arguments);
}
}
}
Download the JScript ASP source directly.
Debugging
“saveDebug()” utilises two functions that exist elsewhere: “saveFile()”
and “createDirectoryPath()” to write
whatever the input argument is to a file whose path is defined by application variable “SAVEDEBUG_FILEPATH”, e.g.:
“C:\savedebug\” and is useful for debugging routines where you can't easily dump to the default
output. “debug()” just dumps the argument to the browser with a little styling and kills further
processing.
Function: saveDebug()
Description: Writes a debugging file to a standard location - useful for processes where it is inconvenient to display debugging information
Returns:
History:
20060324 0908GMT v1 Andrew Urquhart Created
*/
function saveDebug(strData) {
try {
if (typeof arguments.callee.count != "number") {
arguments.callee.count = 1;
}
else {
++arguments.callee.count;
}
var strData = "" + strData; // Force to string
var strAbsoluteFilePath = Application("SAVEDEBUG_FILEPATH");
// If save path is a folder and not a specific file, add a dynamic filename based on the date
if ((/\\|\/$/).test(strAbsoluteFilePath)) {
var objNow = new Date();
strAbsoluteFilePath += objNow.getUTCFullYear() + (objNow.getUTCMonth()+1).prefixPad() + objNow.getUTCDate().prefixPad() + "_" + objNow.getUTCHours().prefixPad() + objNow.getUTCMinutes().prefixPad() + objNow.getUTCSeconds().prefixPad() + "." + objNow.getUTCMilliseconds().prefixPad("0", 3) + "_UTC_" + arguments.callee.count + ".txt";
}
createDirectoryPath(strAbsoluteFilePath)
var blnSaved = saveFile(strAbsoluteFilePath, "utf-8", strData, true);
if (!blnSaved) {
throw new Error(2, "saveFile(" + strAbsoluteFilePath + ") failed");
}
}
catch (err) {
propError(err, arguments);
}
}
/*
Function: debug()
Description:
Returns:
History:
20050131 1554GMT v1 Andrew Urquhart Comment added
*/
function debug(txt) {
Response.Write("<div style=\"color: #ff3333; background-color: #ffffff; font-weight: bold; font-family: monospace;\">Value: "" + hEnc(txt).replace(/\r\n|\r|\n/g, "<br />") + ""</div>");
Response.End();
}
Download the JScript ASP source directly.
enumerateCollection()
“enumerateCollection()” generates a <pre>-like formatted list of the many keys and their
many values in a collection. Parameter “blnSupportsMultipleKeys” is “true”
for “Request.QueryString”, “Request.Form” and “Request.ServerVariables”
collections and “false” for the “Application” collection. Particularly
useful for debugging and error notification.
Function: enumerateCollection()
Description:
Returns:
History:
20060503 0124BST v1 Andrew Urquhart Created
*/
function enumerateCollection(objCollection, blnSupportsMultipleKeys) {
try {
var objO = [];
var intMaxKeyLen = 0;
if (blnSupportsMultipleKeys == null) {
var blnSupportsMultipleKeys = true; // default behaviour
}
var objColl = new Enumerator(objCollection);
// Determine width of longest key name
for (; !objColl.atEnd(); objColl.moveNext()) {
var intKeyLen = objColl.item().length;
if (intKeyLen > intMaxKeyLen) {
intMaxKeyLen = intKeyLen;
}
}
// Write key: value pairs out
for (objColl.moveFirst(); !objColl.atEnd(); objColl.moveNext()) {
var strKeyName = objColl.item();
var strKeyNameNrm = ("" + strKeyName).suffixPad("\u00a0", intMaxKeyLen);
if (blnSupportsMultipleKeys) {
var intValCount = objCollection(strKeyName).Count;
for (var i=1; i<=intValCount; ++i) {
var strKeyValue = objCollection(strKeyName).Item(i).replace(/\n/g, "\\n").replace(/\r/g, "\\r").replace(/\t/g, "\\t");
objO.push(strKeyNameNrm + " : " + strKeyValue);
}
}
else {
var strKeyValue = ("" + objCollection(strKeyName)).replace(/\n/g, "\\n").replace(/\r/g, "\\r").replace(/\t/g, "\\t");
objO.push(strKeyNameNrm + " : " + strKeyValue);
}
}
return objO.join("\r\n");
}
catch (err) {
propError(err, arguments);
}
}
Download the JScript ASP source directly.
sendEmail() & emailReport()
“sendEmail()” is a wrapper for invoking “CDO.Message”
using mail-server settings held in “Application” space. “emailReport()”
is a wrapper for “sendEmail()” for sending formatted application reports including
application state — again most useful for debugging and production-level behind-the-scenes error handling.
“wrapText()” is defined elsewhere.
Function: sendEmail()
Description: Sends an email
Returns: Exception if critical error occurs, true if no errors
History:
20030928 1459BST v1 Andrew Urquhart Created
20041212 0123GMT v1.1 " Massaged to work with CDO.Message
*/
function sendEmail(strToAddresses, strFromAddresses, strSubject, strMessageBody, strReplyToAddresses) {
try {
// CACHE DATA
strToAddresses = strToAddresses.trim();
strFromAddresses = strFromAddresses.trim();
strSubject = strSubject.trim();
strMessageBody = strMessageBody.trim();
strReplyToAddresses = strReplyToAddresses ? strReplyToAddresses.trim() : "";
// CHECK PARAMETERS
if (!strToAddresses) {
throw new Error(1, "Expected parameter \"strToAddresses\" was not defined");
}
if (!strFromAddresses) {
throw new Error(2, "Expected parameter \"strFromAddresses\" was not defined");
}
if (!strSubject) {
throw new Error(3, "Expected parameter \"strSubject\" was not defined");
}
if (!strMessageBody) {
throw new Error(4, "Expected parameter \"strMessageBody\" was not defined");
}
// PREPARE DATA
strMessageBody = wrapText(strMessageBody, 72);
var strCDOSchemaConfig = "http://schemas.microsoft.com/cdo/configuration/";
var objCDOConfig = Server.CreateObject("CDO.Configuration");
objCDOConfig.Fields.Item(strCDOSchemaConfig + "sendusing") = Application("SMTP_SENDUSING");
objCDOConfig.Fields.Item(strCDOSchemaConfig + "smtpserverport") = Application("SMTP_SERVERPORT");
objCDOConfig.Fields.Item(strCDOSchemaConfig + "smtpconnectiontimeout") = 30; // seconds
objCDOConfig.Fields.Item(strCDOSchemaConfig + "smtpauthenticate") = Application("SMTP_AUTHENTICATE");
objCDOConfig.Fields.Item(strCDOSchemaConfig + "smtpserver") = Application("SMTP_SERVERNAME");
if (Application("SMTP_USERNAME").length > 0) {
objCDOConfig.Fields.Item(strCDOSchemaConfig + "sendusername") = Application("SMTP_USERNAME");
}
if (Application("SMTP_USERPASS").length > 0) {
objCDOConfig.Fields.Item(strCDOSchemaConfig + "sendpassword") = Application("SMTP_USERPASS");
}
objCDOConfig.Fields.Update();
var objCDOMsg = Server.CreateObject("CDO.Message");
objCDOMsg.Configuration = objCDOConfig;
objCDOMsg.To = strToAddresses;
objCDOMsg.From = strFromAddresses;
objCDOMsg.Subject = strSubject;
if (strReplyToAddresses) {
objCDOMsg.ReplyTo = strReplyToAddresses;
}
objCDOMsg.BodyPart.CharSet = "UTF-8";
objCDOMsg.TextBody = strMessageBody;
objCDOMsg.TextBodyPart.CharSet = "UTF-8";
objCDOMsg.Send();
// DIDN'T FAIL, ASSUME SENT!
return true;
}
catch (err) {
propError(err, arguments);
}
}
var EMAIL_TYPE_INFO = 1;
var EMAIL_TYPE_WARNING = 2;
var EMAIL_TYPE_ERROR = 3;
/*
Function: emailReport()
Description: Send an error report email
Returns: n/a
History:
20060111 1108GMT v1 Andrew Urquhart Created
*/
function emailReport(message, intMessageType) {
try {
if (!message) {
throw new Error(1, "Required parameter \"message\" was not defined");
}
var strMessageType = "";
switch (intMessageType) {
case EMAIL_TYPE_INFO : strMessageType = "INFORMATION"; break;
case EMAIL_TYPE_WARNING : strMessageType = "WARNING"; break;
case EMAIL_TYPE_ERROR : strMessageType = "ERROR"; break;
default : strMessageType = "UNKNOWN";
}
var arrMsg = [];
arrMsg.push("$APPLICATION REPORT$");
arrMsg.push("====================");
arrMsg.push("REPORT TYPE: " + strMessageType);
arrMsg.push("CURRENT DATE: " + (new Date()).toUTCString());
arrMsg.push("============================");
arrMsg.push(message);
arrMsg.push("===============================");
arrMsg.push("$APPLICATION STATE INFORMATION$");
arrMsg.push("===============================");
try {
arrMsg.push(enumerateCollection(Application.Contents, false));
arrMsg.push(enumerateCollection(Request.QueryString, true));
if (RQ("REQUEST_METHOD").toUpperCase() == "POST") {
arrMsg.push(enumerateCollection(Request.Form, true));
}
arrMsg.push(enumerateCollection(Request.ServerVariables, true));
}
catch (err) {
arrMsg.push("[emailReport() failed to list all state information: " + err.description + "]");
}
var strSubject = "$" + strMessageType + ": Report";
sendEmail(Application("ADMIN_RECIPIENTEMAIL"), Application("SMTP_USERNAME"), strSubject, arrMsg.join("\r\n"), null);
}
catch (err) {
propError(err, arguments);
}
}
Download the JScript ASP source directly.
propError()
“propError()” is a function that you have seen in some of the above functions.
It is designed to be invoked from within the “catch” block of a
“try”-“catch(err)”-“finally”
statement. Invoking “propError(err, arguments)” in this way examines the error object and records
the parent functions name and parameter arguments as a new error description and then throws on up the error with the originating error number.
If the parent function doesn't handle (consume) the exception that is thrown and also has its own “propError()”
invocation from its “catch” block then a cascade can occur that builds up a complete or
partial call-tree and its run-time state. If you catch this exception chain before it is passed out of the script engine and on up
to generate an ASP HTTP 500 error message, then it is really useful for error reporting in production systems. It tells
you what the failure was, where it occurred and how it occurred in lots of gory detail, but it's like having your
own run-time debugger always available in a production environment. Consider using it with “emailReport()”
or “saveDebug()”.
Function: propError()
Description: Propagate an Error up the call chain, adding function name and parameter information about each stage in the chain
Returns:
History:
20060302 1145GMT v1 Andrew Urquhart Created
*/
function propError(errError, argsCaller) {
var arrTree = [];
var blnCascade = false;
try {
if (typeof arguments.callee.count != "number") {
arguments.callee.count = 1;
}
else {
++arguments.callee.count;
}
arrTree.push("<dl><dt>LEVEL</dt><dd>" + arguments.callee.count + "</dd>");
// GET FUNCTION NAME AND VALUE OF FUNCTION PARAMETERS
if (argsCaller) {
var arrArgs = [];
for (var i=0, j=argsCaller.length; i<j; ++i) {
var strDelimiter1, strDelimiter2;
switch (typeof argsCaller[i]) {
case "string" : strDelimiter1 = strDelimiter2 = "\""; break;
case "object" : {
if (argsCaller[i] instanceof Array) {
strDelimiter1 = "["; strDelimiter2 = "]"; break;
}
else {
strDelimiter1 = "{"; strDelimiter2 = "}"; break;
}
}
default : strDelimiter1 = strDelimiter2 = ""; break;
}
arrArgs.push(strDelimiter1 + argsCaller[i] + strDelimiter2);
}
var strFunctionName = "[ No function name ]";
if (argsCaller.callee.toString) {
(/function\s+([\w\d]+)\s*\(([^\)]*)/i).test(argsCaller.callee.toString());
strFunctionName = RegExp.$1;
}
arrTree.push("<dt>FUNCTION</span><dd>" + strFunctionName + "(" + hEnc(arrArgs.join(", ")) + ")</dd>");
}
else {
arrTree.push("<dt>FUNCTION</dt><dd>[ Top Level ]</dd>");
}
arrTree.push("<dt>NUMBER</dt><dd>" + errError.number + "</dd>");
arrTree.push("<dt>MESSAGE</dt><dd>" + errError.description + "</dd>");
arrTree.push("</dl>");
blnCascade = true;
}
catch (err) {
throw new Error(err.number, "propError failed with parameters errError=\"" + errError + "\", argsCaller=\"" + argsCaller + "\". Message:\r\n" + err.description);
}
// Propagate the error up the call-tree
if (blnCascade) {
throw new Error(errError.number, arrTree.join("\r\n"));
}
}
Download the JScript ASP source directly.