<!---
Define function that will recursively search a
struct and it's nested elements for keys that should
be considered secure and blacked out.
--->
<cffunction
name="MakeStructSecure"
access="public"
returntype="any"
output="false"
hint="Does a very cursory job of cleaning up a struct by blacking out secure information.">
<!--- Define argumets. --->
<cfargument
name="Struct"
type="struct"
required="true"
hint="The struct we are going to clean."
/>
<cfargument
name="Depth"
type="numeric"
required="false"
default="1"
hint="The depth of the current search - this will stop the function from looping infinitely."
/>
<!--- Define the local scope. --->
<cfset var LOCAL = StructNew() />
<!---
Check to see if we have reached our max depth
for this search.
--->
<cfif (ARGUMENTS.Depth GTE 5)>
<!---
You're going too deep, it hurts! We might be
looping in a circular struct reference.
--->
<cfreturn />
</cfif>
<!---
ASSERT: If we have made it this far, then we have
to check all the struct keys at this level.
--->
<!---
Define the list of keys that would be considered
to hold secure data.
--->
<cfsavecontent variable="LOCAL.SecureKeys">
CreditCard
CCNumber
CCNum
ExpirationDate
Expry
ExpDate
CCExp
</cfsavecontent>
<!---
Loop over the struct looking for keys that would
flag secure data to be removed.
--->
<cfloop
item="LOCAL.Key"
collection="#ARGUMENTS.Struct#">
<!---
Check to see if the key is to be considered
secure AND that the value in it is simple.
--->
<cfif (
FindNoCase( LOCAL.Key, LOCAL.SecureKeys ) AND
IsSimpleValue( ARGUMENTS.Struct[ LOCAL.Key ] )
)>
<!--- Black out value. --->
<cfset ARGUMENTS.Struct[ LOCAL.Key ] = RepeatString(
"*",
Len( ARGUMENTS.Struct[ LOCAL.Key ] )
) />
<!---
Check to see if this key is a struct that we
might have to search through.
--->
<cfelseif IsStruct( ARGUMENTS.Struct[ LOCAL.Key ] )>
<!---
Recurse through this one. Be sure to send
through a new depth value so we don't loop
forever.
--->
<cfset MakeStructSecure(
Struct = ARGUMENTS.Struct[ LOCAL.Key ],
Depth = (ARGUMENTS.Depth + 1)
) />
</cfif>
</cfloop>
<!--- Return out. --->
<cfif (ARGUMENTS.Depth EQ 1)>
<!--- Return the cleaned struct. --->
<cfreturn ARGUMENTS.Struct />
<cfelse>
<cfreturn />
</cfif>
</cffunction>