Utils.cfc

A utility component with miscellaneous functions you may find handy.

Click to download

<!---
	Name			: Utils.cfc
	Author			: Michael Sharman
	Created			: August 29, 2006
	Last Updated	: November 02, 2007
	History			: Initial release (mps 2007/11/02)
					: September 14, 2006
					: November 02, 2007 - added getEndOfMonth/getStartOfMonth
					: October 16, 2008 - added generateRandomKey
	Purpose			: Simulates ColdFusion tag functions which are not available in cfscript
 --->
<cfcomponent name="Utils" displayname="Utils" hint="Simulates ColdFusion tag functions which are not available in cfscript, also misc functions like sleep" output="false">

	<cffunction name="abort" access="public" output="true" returntype="void" hint="Simulates cfabort from a cfscript block">
		<cfargument name="showerr" required="false" type="string" hint="Used for showerror" />

		<cfif structKeyExists(arguments, "showerr")>
			<cfabort showerror="#arguments.showerr#" />
		<cfelse>
			<cfabort />
		</cfif>

		<cfreturn />

	</cffunction>

	<cffunction name="dump" access="public" output="true" returntype="void" hint="Simulates cfdump from a cfscript block">
		<cfargument name="var" required="true" type="any" hint="Variable to dump" />
		<cfargument name="expand" required="false" type="boolean" hint="Boolean to expand the dump" />
		<cfargument name="top" required="false" type="numeric" hint="Only show the top n layers" />
		<cfargument name="bAbort" required="false" type="boolean" />

		<cfscript>

			var sOptions = "";

			if (structKeyExists(arguments, "expand"))
				sOptions = " expand=" & arguments.expand;

			if (structKeyExists(arguments, "top"))
				sOptions = sOptions & " top=" & arguments.top;

		</cfscript>

		<cfdump var="#arguments.var#"sOptions />

		<cfif structKeyExists(arguments, "bAbort") AND arguments.bAbort>
			<cfabort />
		</cfif>

		<cfreturn />

	</cffunction>

	<cffunction name="generateRandomKey" access="public" output="false" returntype="string">
		<cfargument name="case" type="string" default="upper" hint="Whether upper, lower or mixed" />
		<cfargument name="format" type="string" default="alphanumeric" hint="Whether to generate numeric, string, alphanumeric or special (includes alphanumeric and special characters such as ! @ & etc)" />
		<cfargument name="invalidCharacters" type="string" default="" hint="List of invalid characters which will be excluded from the key. This overrides the default list" />
		<cfargument name="length" type="numeric" default="8" hint="The length of the key to generate" />
		<cfargument name="numericPrefix" type="numeric" default="0" hint="Number of random digits to start the key with (the rest of the key will be whatever the 'format' is)" />
		<cfargument name="numericSuffix" type="numeric" default="0" hint="Number of random digits to end the key with (the rest of the key will be whatever the 'format' is)" />
		<cfargument name="fixedPrefix" type="string" default="" hint="A prefix prepended to the generated key. The length of which is subtracted from the 'length' argument" />
		<cfargument name="fixedSuffix" type="string" default="" hint="A suffix appended to the generated key. The length of which is subtracted from the 'length' argument" />
		<cfargument name="specialChars" type="string" default="" hint="List of special chars to help generate key from. Overrides the default 'characterMap.special' list" />
		<cfargument name="debug" type="boolean" default="false" hint="Returns cfcatch information in the event of an error. Try turning on if function returns no value." />

		<cfscript>

			/**
			* Name			: generateRandomKey
			* Author		: Michael Sharman (michael@chapter31.com)
			* Created		: October 12, 2008
			* Last Updated	: October 12, 2008
			* History		: Initial release (mps 2008/10/12)
			* Purpose		: Returns a random key based on specific rules
			* Usage			: If you pass arguments, pass them as "named arguments"
			*				: 	myKey = generateRandomKey();
			*				: 	myKey = generateRandomKey(case="mixed", format="alphanumeric", length="8");
			*/

			var i = 0;
			var key = "";
			var keyCase = arguments.case;
			var keyLength = arguments.length;
			var uniqueChar = "";
			var invalidChars = "o,i,l,s,O,I,L,S";	//Possibly confusing characters we will remove
			var characterMap = structNew();
			var characterLib = "";
			var libLength = 0;

			try
			{

				characterMap.numeric = "0,1,2,3,4,5,6,7,8,9";
				characterMap.stringLower = "a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z";
				characterMap.stringUpper = UCase(characterMap.stringLower);
				characterMap.stringCombined = listAppend(characterMap.stringLower, characterMap.stringUpper);

				if (len(trim(arguments.specialChars)))
					characterMap.special = arguments.specialChars;
				else
					characterMap.special = "!,@,##,$,%,^,&,*,(,),_,-,=,+,/,\,[,],{,},<,>,~";

				switch (arguments.format)
				{
					case "numeric":
						characterLib = characterMap.numeric;
						break;
					case "string":
						if (keyCase EQ "upper")
						{
							characterLib = characterMap.stringUpper;
						}
						else if (keyCase EQ "lower")
						{
							characterLib = characterMap.stringLower;
						}
						else if (keyCase EQ "mixed")
						{
							characterLib = characterMap.stringCombined;
						}
						break;
					case "alphanumeric":
						invalidChars = invalidChars.concat(",0,1,5");		//Possibly confusing chars removed
						if (keyCase EQ "upper")
						{
							characterLib = listAppend(characterMap.numeric, characterMap.stringUpper);
						}
						else if (keyCase EQ "lower")
						{
							characterLib = listAppend(characterMap.numeric, characterMap.stringLower);
						}
						else if (keyCase EQ "mixed")
						{
							characterLib = listAppend(characterMap.numeric, characterMap.stringCombined);
						}
						break;
					case "special":
						invalidChars = invalidChars.concat(",0,1,5");		//Possibly confusing chars removed
						if (keyCase EQ "upper")
						{
							characterLib = listAppend(listAppend(characterMap.numeric, characterMap.stringUpper), characterMap.special);
						}
						else if (keyCase EQ "lower")
						{
							characterLib = listAppend(listAppend(characterMap.numeric, characterMap.stringLower), characterMap.special);
						}
						else if (keyCase EQ "mixed")
						{
							characterLib = listAppend(listAppend(characterMap.numeric, characterMap.stringCombined), characterMap.special);
						}
						break;
				}

				if (len(trim(arguments.invalidCharacters)))
					invalidChars = arguments.invalidCharacters;

				if (len(trim(arguments.fixedPrefix)))
				{
					key = arguments.fixedPrefix;
					keyLength = keyLength - len(trim(arguments.fixedPrefix));
				}

				if (len(trim(arguments.fixedSuffix)))
				{
					keyLength = keyLength - len(trim(arguments.fixedSuffix));
				}

				libLength = listLen(characterLib);

				for (i = 1;i LTE keyLength;i=i+1)
				{
					do
					{
						if (arguments.numericPrefix GT 0 AND i LTE arguments.numericPrefix)
						{
							uniqueChar = listGetAt(characterMap.numeric, randRange(1, listLen(characterMap.numeric)));
						}
						else if (arguments.numericSuffix GT 0 AND keyLength-i LT arguments.numericSuffix)
						{
							uniqueChar = randRange(characterMap.numeric, randRange(1, listLen(characterMap.numeric)));
						}
						else
						{
							uniqueChar = listGetAt(characterLib, randRange(1, libLength));
						}
					}
					while (listFind(invalidChars, uniqueChar));
					key = key.concat(uniqueChar);
				}

				if (len(trim(arguments.fixedSuffix)))
					key = key.concat(trim(arguments.fixedSuffix));

			}
			catch (Any e)
			{
				if (arguments.debug)
					key = e.message & " " & e.detail;
				else
					key = "";
			}

			return key;

		</cfscript>

	</cffunction>

	<cffunction name="getEndOfMonth" access="public" output="false" returntype="date" hint="Returns a date object for the last day of the month">
		<cfargument name="dDate" required="false" type="date" />	

		<cfscript>

			var dateToCheck = now();

			if(structKeyExists(arguments, "dDate"))
			{
				dateToCheck = arguments.dDate;
			}

			return createODBCDate(year(dateToCheck) & "/" & month(dateToCheck) & "/" & daysInMonth(dateToCheck));

		</cfscript>

	</cffunction>

	<cffunction name="getFileSeparator" access="public" output="false" returntype="string" hint="Returns the system file path separator">

		<cfscript>

			return createObject("java", "java.io.File").separator;

		</cfscript>

	</cffunction>

	<cffunction name="getLineSeparator" access="public" output="false" returntype="string" hint="Returns the system line separator">

		<cfscript>

			return createObject("java", "java.lang.System").getProperty("line.separator");

		</cfscript>

	</cffunction>	

	<cffunction name="getStartOfMonth" access="public" output="false" returntype="date" hint="Returns a date object for the first day of the month">
		<cfargument name="dDate" required="false" type="date" />

		<cfscript>

			var dateToCheck = now();

			if(structKeyExists(arguments, "dDate"))
			{
				dateToCheck = arguments.dDate;
			}

			return createODBCDate(year(dateToCheck) & "/" & month(dateToCheck) & "/01");

		</cfscript>

	</cffunction>	

	<cffunction name="location" access="public" output="false" returntype="void" hint="Simulates cflocation from a cfscript block">
		<cfargument name="template" required="true" type="string" hint="Template to locate to" />
		<cfargument name="addToken" default="false" type="string" hint="Whether to add session token" />

		<cflocation url="#trim(arguments.template)#" addtoken="#trim(arguments.addToken)#" />

		<cfreturn />

	</cffunction>	

	<cffunction name="param" access="public" output="true" returntype="void" hint="Simulates cfparam from a cfscript block">
		<cfargument name="argName" type="string" required="true" />
		<cfargument name="argValue" type="any" default="" />

		<cfparam name="#argName#" default="#argValue#" /> 

		<cfreturn />

	</cffunction>

	<cffunction name="sleeper" access="public" output="false" returntype="void" hint="Leverages Java's sleep() function for pre-CF8 servers. Don't name 'sleep' as it will bomb in CF8">
		<cfargument name="timeToSleep" type="numeric" required="true" />

		<cfscript>

			createObject("java", "java.lang.Thread").sleep(arguments.timeToSleep);	//sleep time in milliseconds
			return;

		</cfscript>

	</cffunction>

</cfcomponent>