Monday, December 26, 2011

CF: New version of BonCode PGP library released

I had a few request to look into the PGP library I released for ColdFusion and Railo last year. It took me a while to understand my own code, then, a while longer to implement the features that I wanted to add ;o)

The main add on this time is the ability to create single pass signed files. This allows you to create a file where you are assured that only the authorized receiver can read them, while the receiver is assured that the sender is authentic as well.  Yep, I know sound like cold-war stuff, but it is quite common scenario in financial exchanges to assure both sides that everything is the way it should be.

To a lesser level some other additions and bug fixes were completed as well.
All this, as usual is open source.

You can download code, examples, and implementation from here:

http://pgp.riaforge.org

Best,
B.

Tuesday, December 20, 2011

CF: Setting up the OWASP ESAPI Library for use with ColdFusion and Railo

If you are taking application security seriously or have been curious about it you know by now that the native tools built into ColdFusion and Railo are not sufficient to hinder the serious hacker from making headway.

To truly use best practices you can do a lot of code development, or, fall back to a project that has already proven its merit through many years of practical use.

I am referring to the OWASP Enterprise Security API (ESAPI). Unfortunately, getting this puppy running in any shape requires some reading muscle and some luck and some powers of deduction.

I am summarizing here the findings, so you don't have to run through the maze of options and boiling it down to something simple.

First, you will have to download the jar file (as of this writing it would be esapi-2.0.1). The download is around 14MB but you only need the esapi-2.0.1.jar file. Copy the jar file to (backup any esapi file that already exists in there first):
[cfroot]/wwwroot/WEB-INF/lib in Adobe Coldfusion.
WEB-INF/lib in Railo

Then, download a good ESAPI.properties file. Most of my head banging and hair ripping surrounds finding the property definitions. Can't stress this enough. Start with the one from source code it has good comments. Go through this file carefully and make needed changes. Make sure all directories referenced in the properties file actually exist on your drive system and also change default Encryptor.MasterKey and Encryptor.MasterSalt to something you are comfortable with, e.g. do not use something like this:


Encryptor.MasterKey=changeme
Encryptor.MasterSalt=blah

After you made changes save it (e.g. c:\esapi\files).

Thirdly, make environment start up changes.
If you are using Adobe Coldfusion you will need to change the JVM startup properties in CF Administrator to add a property and point to place where you placed ESAPI.properties file. E.g.:
-D org.owasp.esapi.resources=c:\esapi\files

For Railo, the above is done in Tomcat/Jetty startup parameters.

Fourthly, change classpath (Yep, you heard right change JAVA classpath): Add the directory you placed the properties file in to Java classpath. This is something that had me stumped as well.

After all of the above, give your server a good schake (restart), and then test whether all works.
Simple code snippet:

<cfset esapi = CreateObject("java","org.owasp.esapi.ESAPI")>

<cfset encoder = esapi.encoder()>

<cfoutput>

 <cfset myInput="<script>some input for html context; 

  alert('doing something you don't want');</script>">

  #now()# <br/>

  #encoder.encodeForHTML(JavaCast("string", myInput))#

</cfoutput>

The good news is that Adobe is looking into bundling this in the future so you don't have to. However, in the meantime this is good practice ;o)

Best,
B.

Thursday, December 8, 2011

Internet Explorer and the case of the vanishing Forms

So we ran into the problem of a customer's users' not being able to use our application. The users happen to use Internet Explorer and IIS (Internet Information Server) and the behavior was intermittend.
We thought, this is a network issues for sure; so we put sniffers on client and servers sides and observed that nothing was conclusive.
Another thing that threw us was that using an alternate browser such as Chrome everything seemed to be working.
When things did not work, however, we saw that IE (version 6 through 9) would not send any HTTP form information along. So even with simple HTML page that had two form fields "FirstName" and "LastName", we would see through the protocol capture that IE started an HTTP post, but no form fields and values. They had vanished. Poof !
Our further suspicion of maybe a plugin, proxy or firewall stripping this data out was also eliminated and we started staring at each like we are all going crazy. And, of course, we googled. Nothing there either. (Google, oh Google, why did you fail us!)...
Then, a little break, we discovered, that everytime things stopped working and Forms started vanishing, the user had just entered a secured area of the site and returned to an unsecured area. The security access was transparent as IIS was setup to use "Windows Authentication" similar to "Integrated Authentication"; thus, IE was doing this in the background. Thereafter, even if the user returned to the non-secure areas of the site, IE would refuse to send Form data. After more digging we found that this seems to be intentional; we even found an old web-page that descibed this as good feature for IE6. The behavior is this: after, IE authenticates to a site via NTML / Kerberos (i.e. some integrated way), all traffic to that site has to be secured and as part of the security mechanism no plain text form submission is allowed. Great !
The solution to this was to move the secure portions to a seperate site on IIS and thus everything started working as it should. IE was happy, customer was happy, and we could go to sleep.

Hope you don't have to spent as much time on troubleshooting knowing this.

B.

Wednesday, November 23, 2011

CF: Tracing AMF (Action Message Format) packages for Flex/BlazeDS in Coldfusion

I know I had seen this and done this before but for some reason I could not find it. I am looking at a Flex based component that makes remote calls to ColdFusion (Flash Remoting), then, renders some of the data. Now I wanted to find out what is happening and more specifically what data is being exchanged between Flex and ColdFusion.
As you might know, the exchange between CF and Flex is in AMF format, which is a binary format and thus not easily readable over protocol sniffer.
I know, I know, I can get many tools, and ServiceCapture is mentioned many times; but I wanted to do this simpler.
What I done in the past is used the command window to get this, but with many things, you forget, or just get older ;o)
So you can start ColdFusion in a Command / Terminal window, by going to the installation folder and finding the right startup script.
For windows:
[cfroot]\bin\cfstart.bat

This will start the ColdFusion server in command window:
Command Window running ColdFusion


However, this did not automatically decode the AMF messages or gave me insight into flash remoting. In order to that I had to find the flex services-config file. On stand-alone server install on Windows this would be located here:
[cfroot]\wwwroot\WEB-INF\flex\services-config.xml

find the logging section and change logging level to "Debug" like so:

<logging>

        <target class="flex.messaging.log.ConsoleTarget" level="Debug">

        ...

</logging>



You can even change the prefix of the messages, e.g. to Flex like so:



<logging>

        <target class="flex.messaging.log.ConsoleTarget" level="Debug">

            <properties>

                <prefix>[Flex] </prefix>

This is the cheap way of getting debugging going on the protocol and see what is being exchanged.
Hope this helps,

-B


Saturday, October 29, 2011

CF: CFCamp 2011 presentation and sample code

A long day at CFCamp came to a social conclusion at the Marriott-bar. This again confirms the impression that the ColdFusion community is approachable by old and new hands alike.

Another interesting fact about the CF community emerged. According to the custodial support staff, the CFCamp attendees consumed three times as much coffee as crowds of a similar size. Definitively a mark of distinction.

Thanks to the organizers, presenters, and attendees for making this a solid CF event.
Overall, learned new things from all and had a Pretzel to boot.
As discussed, I posted the the presentation slides and sample code for download.

Cheers,
B.

Friday, October 14, 2011

CF: Munich in the Fall, CFCamp 2011

So, you just missed Oktoberfest and were wondering what else there is to do in Munich in the Fall. Well, you happen to be in luck, especially if you are a ColdFusion enthusiast.
It so happens that this year a few fellow believers in the art of the Pretzel and motivated ColdFusion learners are assembling on October 28th for CFCamp 2011.

Even yours truly will make the trek down  to Bavaria's Capital to chat and learn from others. Will also do a talk on application security, sharing some nuggets of the school of hard knocks etc.

As far as I understand it, it is not too late to signup and the Beer and Pretzels are beckoning....

Cheers,
B

Sunday, October 9, 2011

.NET: wddx.net library revision

Before web services, before JSON, before many other things or people ever thought about it,  there was this other way to exchange data across platforms via the Internet using XML. It was called WDDX (Web Distributed Data Exchange).

According to Wikipedia this its definition:

WDDX (Web Distributed Data eXchange) is a programming-language-, platform- and transport-neutral data interchange mechanism to pass data between different environments and different computers. It supports simple data types such as number, string, boolean, etc., and complex aggregates of these in forms such as structures, arrays and recordsets (row/column data, typically coming from database queries).

Support for WDDX is available natively in several languages including ColdFusion, PHP, Ruby, and Python. Other languages implement this through add ons. .NET belongs to the later category, thus needs a library to process WDDX. Unfortunately, this library has not seen updates in a long while. It is open source and was created by Joel Mueller early in the 2000s and not much happened since then.

First, Kudos for Joel taking on this project and making it available. It is well documented and executed; unfortunately, as with any software, there were some issues. Having discovered these and "fixed" them, the question of getting the fixes back into distribution came up. After several attempts to contact the current maintainer of this project and several months of wait time I got very frustrated and decided to take over some of this.

Rather than branching this on Microsoft Codeplex site (this is Microsoft's site for maintaining open source projects) I used Git Hub. The main reason for me to use another site for maintenance was that Codeplex seem to not get any attention from Microsoft. Bug messages were being ignored, documentation did not match to what the site did or operated.

Download WDDX.NET libraryhttps://github.com/Bilal-S/WDDX.net

So I hope that if you need WDDX support in .NET you will check out this project.
As usual please let me know if you find any issues.

Best,
B.

Sunday, September 18, 2011

NCDevCon: Presentation Slides and Code

The NCDevCon 2011 conference is on its way to be concluded. Many interesting and well rounded presentations. Meeting friends from all over again and chatting about the best and worst way of doing things.
I am continuing to be impressed what the team (Dan Wilson, Jim Priest, Shawn Dunning) is able to do with so little resources. Way to go team.

As promised I am posting the links to the slides to my presentations:
Practical Application Security:
Practical Application Security Slides
I posted the code for URLEncoder on RIAforge as open source project.

Client Side MVC with Sencha Touch:
Client Side MVC with Sencha Touch Slides
Download Sencha MVC code. Please review the Readme_first.txt file on how to get this going.

Please feel free to explore code and slides.
The conference also posts the video of the presentations.

Cheers,
 -B.

CF: Using URLEncoder to secure URL Parameter against CSRF and XSS

In my presentation about ColdFusion Application Security I also showed a reference implementation of an URLEncoder that can assist with three scenarios:

Cross Site Scripting: If scripts are injected through URL parameters, this encoder will ensure that no user inputs besides the one set by CF are accepted.

Insecure Direct Object Reference: By encrypting the object references in passed URL the object reference are no longer exposed to users and cannot be changed by users.

Cross Site Request Forgery: By adding additional reference in the encrypted packages the URLEncoder will assist with Cross Site Request forgery attempts.

The URLEncoder allows a very flexible way of transporting data via URL parameters in a secure fashion. It is not restricted to primitive/simple data types. Complex data such as arrays and structures can easily passed  via the URL using this component as well.

Moreover, additional security option are available. During encoding, you can specify whether the generated URL has an expiration and or can only be used from the originating URL.

During the decoding phase the URLEncoder you can specify which scope the transported data from the URL parameters will be placed in. By default this will be placed into Request.URL, however, you can change this to be placed into the regular URL scope so that legacy application will only need minimal change to add this layer of security.

Here is the link to the download to the project from RIA Forge.

Cheers,
-B.

Wednesday, August 31, 2011

NCDevCon 2011: Developer Conference coming up Setp 17-18, Raleigh, NC

For the last three years an amazing thing has happened. The Triangle Area ColdFusion User's Group (TACFUG), has put a lot of blood, sweat and tears into organizing a conference, NCDevCon, that has ColdFusion at its center.
This by itself is an amazing feat; especially given that the large ColdFusion specific conferences are faltering and Adobe, the main source of CF, does not have an independent gathering focused on this topic.
On top of this, the conference manages to have broad coverage of many relevant areas of Colfusion and Web development while also giving beginners options for hands on sessions.
This is a major, major (yes two majors!) achievement. So definetly cudos to the organizers.
All this is available for a very small fee ($60) compared to the several hundreds of dollards we commonly pay. So definetly a deal in light of the knowledge that is being shared.

I have been selected to do two presentations this year on very different topics. The first one on Application Security, I can see eyes already glazing over, nope we'll provide some practical code here as well.
The other one is on mobile application developement with Sencha Touch and ColdFusion. This one is harder to organize as I have lots of material I am trying to decide what to cut out at the moment.

Hope to see you there.

Cheers,
-B

Wednesday, August 24, 2011

CF: Decide if we got enough memory to succeed

Since the beginning of computing there has been the struggle between available resources and the number of computing tasks to run on them. When we had 16KB of RAM our code looked very compact and we were critical of any extra bytes that we stored or computing cycles we ran.
When, today, we easily reach 16GB of RAM the level of individual byte analysis does not quite happen. More likely than not, we tend to worry less about do we have enough memory to run this operation and assume (to our chagrin) that things will work themselves out,... right until they don't.

Which brings me to the problem at hand. Rather than running a process, thread, task and hoping things work, can we predictably make that decision instead?

In my case, this being ColdFusion I needed to find out whether I had a snowballs change in the Hot-Place to open an Excel file. Remember that ColdFusion uses the Apache POI library to read Microsoft Office documents. Works normally fairly transparently but the downfall here (it is documented as well, see POI docs) is that POI will grab big chunks of memory for processing any access to, say, a spreadsheet.

This, if not managed, gets us into an unconfortable situation of crashing the server with OutOfMemroy exceptions. Yep, not good.

So our solution was first determine a common estimation factor (spreadsheet size to JVM memory size), then use it to see whether we would have a chance of opening / loading this spreadsheet at all given the current memory envelope on the server.
Nice message to user if we had no chance, go ahead and process otherwise.
This eliminates unneccesary server crashes. Which is, indeed, a very good thing.

Here is the code snippet we used to determine available CF server memory:

<cffunction name="getMemory" returntype="numeric"
access="private" hint="return server unused available memory">
<cfscript>
var intMB = 1024 * 1024;
var objRuntime = createObject(
"java", "java.lang.Runtime").getRuntime();
var intUsedMem = objRuntime.totalMemory() - objRuntime.freeMemory();
var intAvailableMem = objRuntime.maxMemory() - intUsedMem;
return (intAvailableMem/intMB);
</cfscript>

</cffunction>

The value here will have to be compared against the expected value of memory use for your operation. For example, if you expect your spreadsheet to occupy 100MB memory while loaded into JVM and want to have a margin on 50MB, you can only proceed with the operation if the return of the above function is a value of 150 or greater.

Cheers,
B.

Friday, August 19, 2011

Facebook and Automatic Granting of Permissions to Applications via Mobile Devices

I make it a policy of conduct not to install any Facebook application or grant any Facebook apps rights to my Facebook account. Call me paranoid (many have).
So, needless to say, I was surprised when I was looking at my settings page under application how many applications I seem to have granted access.
There they were, a little more than half a dozen apps that seem to have access to my information and friends, not remembering, having granted any of them the right to do so.
This baffled me to no end. How did this happen?

Well, the only thing that seemed to be a common pattern for these apps is that I had loaded similarly named application on my iPhone from the Appstore. Ahh, yes, here is where the plot thickens. Thus the best I can explain this is that the terms of acceptance of these apps includes that they can access my Facebook profile. Thus, if they detect the Facebook app loaded on your device they establish connection and register themselves as authorized apps with Facebook.

I might get this all completely wrong, but this is the only explanation I can come up with, since I got this policy of no apps etc.

Yes, some of you may now say that I was too trusting a soul, and this, too, might be true, so I am now checking more regularly to see whether I am being hoodwinked into approving this type of behavior.

I am now checking regularly what the Facebook app settings page looks like (see below) and killing the permissions. I truly wish that FB had explicit lock on this type of stuff as this is very sneaky behavior in my opinion.



As usual would appreciate some feedback.

Cheers,
-B.


Thursday, July 28, 2011

CF: ColdFusion Debug trace for remoting (Flex, SOAP, anything else)

One of the things I have always liked with working in ColdFusion is the ability to derive detailed debugging information. You get a good idea of what is going behind the covers and do have a good basis to hunt down bugs.
Unfortunatly, this all breaks down when you start to do any kind of remoting (invoking CFCs from another technology). Currently, this is for Flex and SOAP (Webservices) type calls. If anything goes haywire, or the calls themselves are complex, e.g. call on many other components and tags you fly in the dark more often then not.
The common response to this kind of issue from peers is to use the line debugger, set breakpoints etc. and this does work to a certain degree.
However, where I get a little agitated is that most of the time when problems occur you are nowhere near a line-debugger or IDE to capture the processing.
For standard .cfm pages I can use the Silent Debugger option.
So I was wondering if I could build something similar that worked with CFCs and remoting. I would add this to the Application.cfc and, bingo, I could capture the debugging output to file. Alas, many hours later I had nothing workable. To make a long story short it does not look like there is a way to capture cfc debug output, because no debugging session is seems running.

Unfortunatly, it looks like the auto-wiring that ColdFusion performs makes the decision not to initialize / start a degugging session in the ServiceFactory (coldfusion.server.ServiceFactory).
Thus the call for factory.getDebuggingService() will fail and my attempts to manualy start the debugging service failed for lack of insight into how CF actually does this (what classes and method in what order).
So I was back to square one.
After a little more thinking and tinkering I decided to go for the workaround solution. This happens to be practical enough for me as my remoted cfcs are only stubs, so not much functionality is implemented there.
I have several stub types and, thus, decided to rewrite the call from SOAP / FLEX remoted calls to HTTP Post (REST) calls.

So in the remoted call I would just turnaround and call the REST gateway if I detected that we were trying to debug stuff using the IsDebugMode() function.

This would allow me to use the Silent Debugging option and capture the debug output to file even for calls coming from SOAP and FLEX remoting. I would also need to translate the reponse back correctly for FLEX and SOAP clients to consume.

All this is more overhead but not drastically so, while allowing me to trace errors while they occur even for remoted CFCs. I can access this information afterwards for analysis.

Overall, I am disapointed that I was not able to hook into native CF processes to expose debugging results. Maybe in future iterations this will be possible. However, being able to get this insight is invaluable to me.

Feel free to experiment.

Cheers,
B.

Thursday, July 21, 2011

CF: cfObjective 2011

Meant to provide feedback on the cfObjective conference in Mineapolis, MN.
The conference goes by the tagline of
"The Only Enterprise ColdFusion Conference". Unfortunatly, this may be very true.
Anyways, here is the skinny as I see it (fully my opinion):

Even though this is the biggest CF conference that still is around, I was still disappointed by how small the crowd was. No knock on this conference as it comparitively has grown from last year, but with the demise of cfUnited, I was expecting a larger crowd to carry over to this one.

Conversations with fellow conference attendees lead to the insight that instead of one big conference there are many smaller regional ones that focus on this topic.
If this is the trend, the obvious question would be how CF is CF going to survive? Will many small conferences attract developers by the truck load or will they stay away? Adobe did not sponsor, I hear lots of politics involved. Not a good image if you are trying to convince new people to pick up CF and grow the community.

The location was OK. Downtown Minneapolis is not hot but you can make it work. Weather was a bummer (pretty nippy). The food was good, lunch was better than breakfast.

The presentations followed a similar pattern to cfUnited, the same people are doing the presenting. The quality was just a notch above what was available at cfUnited. I am personally getting a little tired of the same presenters, I think the community needs some fresh blood. Only so many times I can hear an extreme opinion presented as fact ;o)
Overall, still something I will attend, but maybe shorten the time for next year. Do only two days rather than three. The last day was just a rush to get out.

There you have it. Catching up on writing.
B.

Thursday, April 21, 2011

CF: Coldfusion java.lang.StackOverflowError

If you run into this with ColdFusion, it probably will appear to come out of no-where.
One day everything will work fine and, the next, without any change you can think of, you see your site stop to respond.
Upon digging into the exception.log file you see something like this:

"Error","jrpp-0","04/20/10","17:33:53",,"'' The specific sequence of files included or processed is: C:\Webroot\Test4\TestFile.cfm'' "
java.lang.StackOverflowError
at java.io.ObjectInputStream$PeekInputStream.read(ObjectInputStream.java:2263)

This for me occurred when serializing/de-serializing data. But anytime you run into this you have to ask yourself one primary question.
Did this happen because of my logic? If yes, go revise your logic first.
If you are certain your stuff is solid, you need to increase the Stack Size by providing the -Xss directive to the jvm upon ColdFusion startup.

I would bump it four fold; while the default seems to be slightly different based on OS, it is normally in the 300-400kb range.

I bumped mine up first to 10MB, then, reduced it to find out exactly what was workable.

The -Xss argument can be specified in kb e.g. -Xss512k or in mb, e.g. -Xss1m.

here is an image with configured jvm:



Cheers,
B.

Friday, April 1, 2011

inno: converting Ansi string to string

When you work in Unicode Inno Setup the data typing of strings for functions seems to always get you one way or the other.
There are no easy build in conversions either.
After running into this repeatdly I build a helper function that simply converts the Ansi string to regulare string.

May come in handy for others:

//convert Ansi String to String
function ConvertToString(AString:AnsiString):String;
var
i : Integer;
iChar : Integer;
outString : String;
begin
outString :='';
for i := 1 to Length(AString) do
begin
iChar := Ord(AString[i]); //get int value
outString := outString + Chr(iChar);
end;

Result := outString;
end;

Cheers,
B.

Wednesday, March 23, 2011

tomcat: Another way to connect IIS and Tomcat

If you were working with tomcat and IIS for a while you know things are getting a little long in the tooth. The last principle update to how IIS and Tomcat interact was made in early 2000. In the meantime many changes have occured to IIS and Tomcat with more capabilities added.
So, I thought it would be time to also update the way IIS and Tomcat connect.
I just published a project on RIAForge whose goal is to modernize this part:

http://tomcatiis.riaforge.org/

Here are some reasons to consider a new connector:
• no ISAPI code
• no IIS6 vestiges or backward compatibility elements needed on IIS7
• all managed code using the modern extensibility framework
• works on IIS6 and IIS7
• speed improvements
• easier control by file type on IIS side
• no virtual directories and virtual mapping needed
• configuration can be inherited to sub-sites and virtual sites
• easy install/uninstall
• support partial stream sending to browser (automatic flushing) with faster response to client
• support both 32/64 bit of Windows with same process and files
• transfer of all request headers to servlet container
• build in simple-security for web-administration pages

Happy experimenting,
B.

Thursday, February 24, 2011

.NET: C# find pattern in byte array

Byte Arrays are not as easily handled as strings when it comes to finding what they contain, especially if we are searching for a pattern of matching bytes.
It seems like everyone is rolling their own on this one. Most examples I have seen look at converting bytes to strings and then using IndexOf operators.
However, if you use bytes that cannot be converted to a string easily or do not want to use string comparison here is my version of a working function that does the trick.


private static int ByteSearch(byte[] searchIn, byte[] searchBytes, int start = 0)
{
int found = -1;
bool matched = false;
//only look at this if we have a populated search array and search bytes with a sensible start
if (searchIn.Length > 0 && searchBytes.Length > 0 && start <= (searchIn.Length - searchBytes.Length) && searchIn.Length >= searchBytes.Length)
{
//iterate through the array to be searched
for (int i = start; i <= searchIn.Length - searchBytes.Length; i++)
{
//if the start bytes match we will start comparing all other bytes
if (searchIn[i] == searchBytes[0])
{
if (searchIn.Length > 1)
{
//multiple bytes to be searched we have to compare byte by byte
matched = true;
for (int y = 1; y <= searchBytes.Length - 1; y++)
{
if (searchIn[i + y] != searchBytes[y])
{
matched = false;
break;
}
}
//everything matched up
if (matched)
{
found = i;
break;
}

}
else
{
//search byte is only one bit nothing else to do
found = i;
break; //stop the loop
}

}
}

}
return found;
}





Cheers,
B.

Tuesday, February 8, 2011

CF: ColdFusion Report Builder migration errors with Invalid construct.A script statement must end with ";"

You may had the opportunity to work with ColdFusion Report Builder in the past. It was a cool little tool that we used with ColdFusion 7 when you could not afford anything else to write reports with.
In its first iteration it was pretty buggy; today, it still is around but I see fewer people using or mentioning it. It barely gets any play at the user conferences and is treated more like a red-headed step child (I have nothing against red headed people of any kind ;o).
In my opinion it is still a useful tool that does not get its share of attention. However, when you migrate from older versions of reports that you have written with, say, ColdFusion Report Builder (CFRB) 7, to ColdFusion Report Builder 8 or 9 you may get some fairly unexpected errors.
Such as this:

Invalid construct.A script statement must end with ";"

The only thing you did it just open and save the report. No changes were actually made. All of a sudden, errors jump up from seemingly nowhere. Well, for me, that resulted in many hours of ghost hunting (since I cannot see what's in the cfr files) until I finally got the bright idea to dig up an old copy of Report Writer 7 for those reports.

I restored the .cfr file from backup, made a change using CFRB 7 and everything worked. Just to check for sanity, I, then, restored the file again, made a simple change using either CFRB 8 or 9 and, boom, broken again.

The lesson here is to make sure you ask before you touch a ColdFusion report (.cfr) file with which version of ColdFusion/ColdFusion Report Builder it was created. Then, make the modifications only with that tool.

This in the end may save you many hours of frustration.

Cheers,
B.

Monday, January 10, 2011

CF: Explicit "undefined" in ColdFusion 9 results in Bug when using CustomTag Attribute collections

Adobe ColdFusion 9 introduced many new enhancements but as with any major release there are new behaviors and new problems galore.
This particular bug I encountered deals with a change in behavior of component function processing. I encountered this while migrating an application from CF8 to CF9.
In previous releases of ColdFusion an Argument that was not passed would not exist in the arguments scope. With ColdFusion 9, an argument is always created even if not passed if it is part of the arguments declaration in your function.

For example this simple function:


<cffunction name="fTwo">
<cfargument name="argA" default="1">
<cfargument name="argB" required="no">
<cfreturn arguments>

</cffunction>


a dump of this function will return:

1: <cfdump var="#fTwo()#">
2:



ARGA 1
ARGB undefined

Rather than just

ARGA 1

Thus ColdFusion 9 is introducing a new state in the variables, the Explicit "undefined".
Since this is a new state all function working with CF objects/ i.e. variables will also need to be aware of it. And most are and, thus, little problem.

However, if you introduce some slight alterations, e.g. call a custom tag from a component, this system fails.
You will get errors as the IsDefined() function will identify something as defined while it is not.

Let's introduce a simple custom tag (CT9Test) with the following 6 lines of code:


1: <cfdump var="#Attributes#">
2:
<cfif IsDefined("Attributes.ArgB")>
3: Attributes B is defined
4:
<cfelse>
5: Attributes B is NOT Defined
6:
</cfif>
7:
8:



First let's call this custom tag from the function like so:

1: <cffunction name="fTwo">
2:
<cfargument name="argA" default="1">
3:
<cfargument name="argB" required="no">
4:
<cf_CT9Test attributeCollection = "#Arguments#">
5:
</cffunction>
6:



Nope. This is still good. No problem here. But, let's go ahead and break ColdFusion:

1: <cffunction name="fThree">
2:
<cfargument name="argA" default="1">
3:
<cfargument name="argB" required="no">
4:
<cf_CT9Test anotherVar="something" attributeCollection = "#Arguments#">
5:
</cffunction>
6:


You see the difference?
We are simply adding another parameter to be passed to the custom tag in addition to the attribute collection received from the function arguments.
In the above case, the attributes.argB all of a sudden becomes defined. But since it is explicitly "undefined" using it will throw weird errors.
Something like:
if (IsDefined("attributes.argB") ) calc=attributes.argB + 1;
will fail.

The workaround to this is to go back to scenario one and not use any additional parameters when calling your custom tags and using attributeCollection. Package all parameters into one structure, e.g.

1: <cffunction name="fFour">
2:
<cfargument name="argA" default="1">
3:
<cfargument name="argB" required="no">
4:
<cfset arguments.anotherVar="something">
5:
<cf_CT9Test attributeCollection = "#Arguments#">
6:
</cffunction>
7:


Now that you know this. Happy migrating.
-B