18. February 2010 13:26 by Markus Wollny

The real Y2K problem: LongInt Unix-Timestamps

18
Feb/10
0

On January 19th 2038 I’ll be 63 years, 9 months and 23 days old. So unfortunately there are still a couple of days until I can think about retirement. What’s wrong with this date?

The Unix timestamp of 2038-01-19 03:14:07 is 2147483647. This is the maximum number that fits into the int4 data type. One second later we’ll be getting integer overflow for any operations on Unix timestamps. Like getting the actual date from that Unix timestamp via dateAdd() in ColdFusion.

17. February 2010 10:27 by Markus Wollny

Death to isDefined()

17
Feb/10
0

Ever come across a couple of lengthy stack traces in your ColdFusion logfile that start with something like “Error in blah – java.net.SocketException: Broken pipe”? Here’s what that’s about:

While isDefined() may be a convenient way to check the existence of a certain variable, you just should avoid it at all cost and use structKeyExists([SCOPE],”[variableName]“) instead.

Not only will structKeyExists() be much faster than isDefined(), as you’ve told ColdFusion where to look for your variable, so it doesn’t have to check through all available scopes. You’ll also avoid a lot of useless chatter clogging up your server’s log files.

Say you’re looking for a variable which at this point is in fact not defined in any of the available scopes and you’re using evil isDefined() to do the job. ColdFusion will scan all the available scopes and eventually it would check the CGI-scope, too. And here’s our problem: If the original connection from browser to webserver has already been closed in the meantime, which may happen for various reasons, the JRun connector (i.e. the bit that does the communication between webserver and the Coldfusion Application Server) will obviously fail to read the HTTP connection header and tell that tale in the log file in quite excessive detail, full stack trace and everything, although you really couldn’t care less about it.

So in essence: Just pretend you never heard of isDefined(). structKeyExists() ist so much nicer and will give you a warm fuzzy feeling all over every time you use it.

4. February 2010 18:51 by Markus Wollny

A little ReReplace CFConfusion (solved)

4
Feb/10
0

The following two snippets are only different in regard to the iSomeVal string which is used in a Regex replacement string. The first is a string that starts with a character (‘fortytwo’) the second is a string that starts with a number (‘42′). The first example is working fine, whereas the second is somewhat lacking something quite essential:

<cfscript>
 variables.strSource = 'The answer is: Hmm.';
 variables.iSomeVal = 'fortytwo';
 variables.strTarget = ReReplace(variables.strSource,'^(.*:\s).*$','\1'&variables.iSomeVal,'ALL');
 writeOutput('~~' & variables.strTarget & '~~');
</cfscript>

Output: ~~The answer is: fortytwo~~

<cfscript>
 variables.strSource = 'The answer is: Hmm.';
 variables.iSomeVal = '42';
 variables.strTarget = ReReplace(variables.strSource,'^(.*:\s).*$','\1'&variables.iSomeVal,'ALL');
 writeOutput('~~' & variables.strTarget & '~~');
</cfscript>

Output: ~~The answer is:~~

WTF?

A few brain processor cycles later you realize what’s going on: The replacement string now reads ‘\142′ – and there’s no back reference with that number.

So we need a little ugly trick because slash-escaping won’t help us here either. We’ll use the \u operator which usually would indicate to uppercase the following character (which in our case is an integer, so this doesn’t harm us):

<cfscript>
 variables.strSource = 'The answer is: Hmm.';
 variables.iSomeVal = '42';
 variables.strTarget = ReReplace(variables.strSource,'^(.*:\s).*$','\1\u'&variables.iSomeVal,'ALL');
 writeOutput('~~' & variables.strTarget & '~~');
</cfscript>

Output: ~~The answer is: 42~~

Now in this case we’re lucky. Any suggestions on what could be done if we don’t actually know if the variable replacement bit after the first back reference would begin with a character or a number? I don’t want to hack around it with a separating space or something similar – which could of course be removed in a second pass, but this doesn’t seem elegant… Feels like I’m missing something extremely obvious here…

Update: Seems like I’m not missing anything ColdFusion-wise. There’s actually a RegEx feature described on regular-expression.info as ‘$10 through $99 treated as $1 through $9 (and a literal digit) if fewer than 10 groups’. There’s no clue as to the implementation in ColdFusion here, but judging from what I’ve seen in my example code, I’d say it’s fair to assume that CF does not deliver the desired result in this category. But alas, all is not lost as we’re running on top of Java, which I cannot ever shout out happily quite often enough under such circumstances. For behold:

<cfscript>
 variables.objRegex = createObject('component','JavaRegExp');
 variables.strSource = 'The answer is: Hmm.';
 variables.iSomeVal = '42';
 variables.strTarget = variables.objRegex.regExpReplace('^(.*:\s).*$',variables.strSource,'$1'&variables.iSomeVal,true);
 writeOutput('~~' & variables.strTarget & '~~');
</cfscript>

Output: ~~The answer is: 42~~

Yay! This snipped doesn’t use ReReplace but the Java RegEx Component by massimocorner.com I mentioned in an earlier post UDF to strip certain chars, but leave UBB tags alone.