Redirecting Errors to a File in Windows Batch Scripts

In my post on Redirecting Output to a File in Windows Batch Scripts, I discussed the basics of output redirection into a text file and how this can be used for logging, including error logging by using the >& operator to combine the stderr and stdout streams. But Mark asked, “How do you just pipe stderr without joining it to stdout?” Good question!

So normal output redirection is handled with just the > or >> operators (depending on whether you want to overwrite or append the target file), like so:

dir >> myfile.txt

The operator outputs the stdout stream by default. But it can be modified to output the stderr stream by just specifying that stream with the operator. Remember, stderr is stream 2. So, you would do like so:

dir 2>> myfile.txt

This would write only the error output to the file.

Get a Struct or Array in That Simple Value Field

In some environments and scenarios, I used to use initialization (*.ini) files for storing simple configuration settings. Now I typically store this kind of information in a ColdSpring configuration file, or at least in an XML file of some sort. But at times I have to live (and work) with the apps I wrote that use *.ini configuration files.

The nice thing about *.ini files. Not that they're all bad. It's ridiculously easy to extract settings from these files with ColdFusion. For instance:

TEXT:
  1. [Settings]
  2. mysetting=Hello
  3. anothersetting=Goodbye

To retrieve the mysetting configuration setting, I just make one call:

CFM:
  1. x=GetProfileString(pathToFile,"Settings","mysetting");

It can't get much easier than that to retrieve a value from a configuration file!

The bad thing about *.ini files. The only problem is that these files are restricted to name=value pairs of simple values. You may go into a project with no need for configuration settings that are any more complicated than simple numbers or strings, but what about 3 years from now when the business logic now could use some structs or arrays in the configuration?

Of course, you could change your whole configuration methodology when--and if--that time comes, but ugh. Using XML (especially in conjunction with IoC such as ColdSpring) is so much more scalable. The future you will thank you.

But it's too late. You and I already have complex app XYZ that is using *.ini config files, and you need to add feature X without rebuilding the configuration logic of the app. What to do?

Embed a string representation of your struct or array in the config file! After all, ColdFusion 8 allows implicit struct and array creation, right? Well, half-right. Doing something like x=Evaluate(myStructString) just isn't allowed by ColdFusion.

However, we can effectively do the same thing with JSON representations of structs and arrays. So, try this:

TEXT:
  1. [Settings]
  2. mysetting={"one":"Hello","two":"Goodbye"}
  3. anothersetting=Yomomma

Now, retrieving mysetting with GetProfileString() will still get you a string, but using JSON functions built into ColdFusion 8 will get you a struct:

CFM:
  1. x=GetProfileString(pathToFile,"Settings","mysetting");
  2. myStruct=DeserializeJSON(x);

Your myStruct variable will be a struct with two keys ("one" and "two") just as you would expect from the JSON.

You could achieve similar results using XmlParse(), but in a case like this, the less verbose, the better. And JSON is less verbose than XML.

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.

  Theme Brought to you by Directory Journal and Elegant Directory.