CFExecute Output Not Going in Your Variable?

I’m blogging this because it’s a little tidbit I always waste about 30 minutes figuring out before I remember it.

The <cfexecute> tag can return the output of the execution into a variable if you supply one with the variable=”" attribute. However, I will try to do this, and (a) the script returns too quickly, and (b) there is no output when there should be.

There is an easy solution! <cfexecute> is expecting the timeout=”" attribute. Supply it a timeout value in seconds, and it will then wait for the script to finish executing and thus have output to store in your variable.

You may be wondering why this is necessary, because even without the timeout=”" attribute, the execution still occurs. <cfexecute> just doesn’t return any output. That’s because <cfexecute> is indeed running, it is just immediately timing out–effectively giving up on the executed process–and thus not returning the output. By supplying a timeout, ColdFusion hangs around waiting for the process to complete before returning its output.

Generating a Decrypted Memento for a Transfer Decorator

In my last blog post, I discussed how to efficiently handle multiple encrypted fields while using Transfer. The key was using onMissingMethod in the Transfer decorator. However, what about when we use the memento with Transfer's getMemento() method? This approach can be especially handy to quickly transfer an object's properties when using web services to Flex or AJAX front ends.

For reference, here was the object definition we were using in our sample Transfer configuration.

XML:
  1. <object name="Reg" table="Regs" decorator="MyProj.com.Reg">
  2.   <id name="ID" column="RegID" type="numeric" />
  3.   <property name="FName" type="string" column="RegFName" />
  4.   <property name="LName" type="string" column="RegLName" />
  5.   <property name="LastMod" type="date" column="RegLastMod" />
  6.   <property name="Expires" type="date" column="RegExpires" nullable="true" />
  7.   <property name="EncHome" type="string" column="regHome" />
  8.   <property name="EncWork" type="string" column="regWork" />
  9.   <property name="EncMobile" type="string" column="regMobile" />
  10.   <property name="EncSMS" type="string" column="regSMS" />
  11. </object>

The process is very simple. Recall that we prefixed our Transfer properties with "Enc" to know which fields are encrypted. Let's create a getDecryptedMemento() method. It will loop through all of the keys in the memento, which is just a struct, and decrypt any of the encrypted fields, saving them as new keys in the struct (i.e. "EncHome" is decrypted as "Home" in the struct).

Something like this will do the trick:

CFM:
  1. <cffunction name="getDecryptedMemento" access="public" returntype="struct" output="false">
  2.   <cfset var memento=getMemento()>
  3.   <cfset var key="">
  4.   <cfset var newkey="">
  5.   <cfloop index="key" list="#StructKeyList(memento)#">
  6.     <cfif Left(key,3) is "Enc">
  7.       <cfset newkey=RemoveChars(key,1,3)>
  8.       <cfset memento[newkey]=decryptValue(memento[key])>
  9.     </cfif>
  10.   </cfloop>
  11.   <cfreturn memento>
  12. </cffunction>

Not much to it. Note that we would use the same decryption function as we are using in onMissingMethod for the dynamic accessors. I'm calling it decryptValue() for this sample.

In the end, our getDecryptedMemento() method returns a memento that looks just like the Transfer-generated getMemento() output, with decrypted versions of the encrypted fields!

Handling Multiple Encrypted Fields in a Transfer Decorator

I had a recent project that had multiple fields in a particular table that needed to be encrypted for privacy and security considerations. I was using Transfer for the project. The typical way to handle the encryption is to create custom accessor methods in a decorator component. The Transfer wiki has a decent explanation of this concept on a page entitled How to Encrypt User Passwords Using a Decorator. However, it is intentionally simple, demonstrating a single property. Multiply your getter/setter methods by how many properties you will be working with, and the lines of code can add up. This framework stuff is supposed to prevent that kind of repetition! Well, utilizing onMissingMethod() and the core concept on the Transfer decorator example, we can handle this scenario efficiently.

First, let's consider the object definition in our sample Transfer configuration file.

XML:
  1. <object name="Reg" table="Regs" decorator="MyProj.com.Reg">
  2.   <id name="ID" column="RegID" type="numeric" />
  3.   <property name="FName" type="string" column="RegFName" />
  4.   <property name="LName" type="string" column="RegLName" />
  5.   <property name="LastMod" type="date" column="RegLastMod" />
  6.   <property name="Expires" type="date" column="RegExpires" nullable="true" />
  7.   <property name="EncHome" type="string" column="regHome" />
  8.   <property name="EncWork" type="string" column="regWork" />
  9.   <property name="EncMobile" type="string" column="regMobile" />
  10.   <property name="EncSMS" type="string" column="regSMS" />
  11. </object>

Note that I have prefixed the Transfer properties with "Enc". This isn't required, but will simplify our processing later on. So in this sample, we have 4 properties: Home, Work, Mobile, and SMS. The concept is that these are client phone numbers that we want to protect with encryption. So, Transfer will generate getEncHome(), getEncWork(), getEncMobile(), getEncSMS(), and corresponding setters. However, we want to provide getHome(), getWork(), getMobile(), getSMS(), and corresponding setters, that get and set the properties after encryption/decryption.

Use onMissingMethod()

To accomplish this, we might have an onMissingMethod() function in the decorator like this:

CFM:
  1. <cffunction name="onMissingMethod" access="public" returntype="any" output="false">
  2.   <cfargument name="missingMethodName" type="string" required="true">
  3.   <cfargument name="missingMethodArguments" type="struct" required="true">
  4.   <cfscript>
  5.     var func="";
  6.     var encList="Home,Mobile,SMS,Work";
  7.     var method=Arguments.missingMethodName;
  8.     var args=Arguments.missingMethodArguments;
  9.     var firstArg=args[ListFirst(StructKeyList(args))];
  10.     var prop=RemoveChars(method,1,3);
  11.     // Handle encryption/decryption of encrypted values:
  12.     if( ListFindNoCase("get,set",Left(method,3)) and
  13.         ListFindNoCase(encList,prop) )
  14.     {
  15.       func=variables[Insert("Enc",method,3)];
  16.       if( Left(method,3) is "get")
  17.         return decryptValue(func());
  18.       else
  19.         func(encryptValue(firstArg));
  20.     }
  21.   </cfscript>
  22. </cffunction>

As a good security measure, we use an "encList" string to check that only proper methods can be called. Then we examine the method name. If it starts with "get" or "set" and ends with one of the list items, we proceed. Thus, we'll process a method like getHome(), but not a method like getFoo(). We then call getEncHome() and decrypt it for getters, encrypt and call setEncHome() for setters.

Dynamic Method Calling

But alas, how do we do this dynamically without a long if-then-else chain? We call the proper method by referencing it from the component's variables scope. Terrence Ryan describes this in his blog post Cheap and Easy Dynamic Method Calling in CFScript. We construct the method name, in our case, by inserting "Enc" after the "get" or "set" prefix of the method name passed into onMissingMethod (thus "getHome" becomes the Transfer method "getEncHome"). Assign the function to the local "func" variable, then call it as if "func" was the function. Finally, handle any encryption or decryption that you will be doing. For this sample, I have encryptValue() and decryptValue() methods handling the details of that work.

Summary

We've used two solutions to handle multiple encrypted fields in the decorator. First, we used onMissingMethod() to handle processing of all of the properties in a single method. Then, we used dynamic method calling to call the Transfer-generated accessors within onMissingMethod().

The end result is being able to use setHome(), getHome(), etc. with the encryption and decryption being handled automatically. Great!

In addition to accessors, we may sometimes want to use the object's memento with the Transfer method getMemento(). In my next blog post, I'll demonstrate how that process can also be done very efficiently.

Best Reason to Use CFQueryParam: Avoid Odd SQL Parsing by ColdFusion

After banging my head against the wall for a couple hours over an odd application error, I've finally come up with the best, most definitive reason to use <cfqueryparam> absolutely 100% of the time: It helps you avoid odd--dare I say erroneous--SQL parsing performed by ColdFusion in the <cfquery> tag. 

Huh? Say again?

That's right. In my experience, anyway, the <cfquery> tag will erroneously parse the SQL and tag legitimate content as disallowed SQL. Let's take a look at an example.

Here's a basic query that inserts some HTML content into a field:

CFM:
  1. <cfquery name="insertStuff" datasource="myDS">
  2.    INSERT INTO myTable (fldTitle,fldContent)
  3.    VALUES ('Title','&middot; Grant Deadline Extended')
  4. </cfquery>

Never mind why you might do this; the point is that it is allowable SQL. There's just an HTML special entity in the string. However, ColdFusion 8 sees the semicolon followed by the word "GRANT", and if the GRANT statement is disallowed for the ColdFusion data source, ColdFusion will throw an error similar to: "Error Executing Database Query. Executing the SQL statement is not allowed."

Of course, there is no error in the SQL, and the same statement executes just fine when you run it at the command line or SQL Query Analyzer. ColdFusion is doing a security check by parsing the SQL and attempting to verify that the SQL statement(s) only use allowed SQL as defined for the data source in ColdFusion Administrator.

If a SQL keyword is not immediately following the semicolon, ColdFusion won't make this mistake. And naturally, if your data source is configured to allow the offending keyword (in my example, "GRANT"), it will execute the SQL and it will execute properly, not actually executing the grant statement.

But if my code had used <cfqueryparam>, this wouldn't have been an issue:

CFM:
  1. <cfquery name="insertStuff" datasource="myDS">
  2.    INSERT INTO myTable (fldTitle,fldContent)
  3.    VALUES (
  4.    <cfqueryparam value="Title" cfsqltype="cf_sql_varchar">,
  5.    <cfqueryparam value="&middot; Grant Deadline Extended" cfsqltype="cf_sql_varchar">
  6.    )
  7. </cfquery>

This code will happily pass the SQL on to the database server.

This scenario may be a bit apparent when presented cleanly as I have here, but when the string being passed in is 3,000 characters or something similar, you're banging your head on the wall wondering what the heck is wrong with your query, especially when it has been working for years and now fails on just a single particular set of data. To my credit, the offending code is about 6 years old and all of my queries do indeed use <cfqueryparam> now. And more than ever, I'm now convinced to continue that habit. ;-)

This oddity probably comes up rarely, but I'm sure someone else has or will experience this. I hope this post will help you.

  Theme Brought to you by Directory Journal and Elegant Directory.