The horror of IsDate() in ColdFusion and Lucee

Very recently, a small number rounding change had been applied to the business I work at. The new rounding was done with the CFML numberFormat() function, which returns a string representation of the number.
For example, #numberFormat(8.831, "_.0")# would return a string "8.8".

Now, despite testing efforts at the backend, a UI bug emerged after going live with this change. It turned out, the rounded number was shown on-screen as a timestamp. Say what?! Yes, as a timestamp.

After digging into the code, it turned out we used a custom generic function for formatting API output. This function used the check isDate() to determine if the value needed to be rendered as a date string. And that is what triggered the bug: our rounded number, now a string, was seen as a date!

I went to tryCF.com to do some checks, and what I always kinda knew,

"don't trust isDate in CFML"

now became absolutely clear...

2 Comments

Using custom fonts for cfimage in Lucee

In the CFML function imageDrawText() and tag <cfimage action="captcha">, you ca enter a font to be used for the text output. Unfortunately, this font must first be available to the JVM (eg. Tomcat) to be able to use it. I did have the TrueType font file available,  But I did not want to manually add the font file to every Lucee instance. That's not portable code...

Luckily, I found a workaround by programmatically adding the font file to the java.awt.GraphicsEnvironment:

<cfset oFont = createObject('java', 'java.awt.Font') />
<cfset stream = createObject('java', 'java.io.FileInputStream').init(expandPath('./SoftwareFont.ttf')) />
<cfset sFont = oFont.createFont(oFont.TRUETYPE_FONT, stream) />
<cfset createObject('java', 'java.awt.GraphicsEnvironment').getLocalGraphicsEnvironment().registerFont(sFont) />

No Comments

Fix for "the VM is generalized" start-up error in Microsoft Azure

[error msg 'failed to start virtual machine']In the old Azure portal, you could simply stop a "Classic" Linux VM without doing waagent -deprovision+user, and then create a snapshot from it.
That snapshot could then be succesfully used to create new VM instances. But, as I found out the hard way, this does not work with Azure Linux VMs through the new portal / new style VMs.

So I ended up with a VM image that can only created un-bootable VMs, AND the template VM itself could not be started anymore because it was generalized. The well-known error "Failed to start virtual machine 'templateVM1'. Error: Operation 'start' is not allowed on VM 'templateVM1' since the VM is generalized." occurs when I try to start the VM.

Luckily, I found a simple way to bypass the "since the VM is generalized"  message.

1) go to the "Disks" page in the Azure Portal:

16 Comments

Mod_cfml now has full nginx support!

mod_cfml logoA while back, I needed to set up a new Ubuntu server for Lucee web hosting. Luckily, I came across a great install script, which not only installed Tomcat and Lucee, but also set up nginx and mod_cfml.
Having developed the 1.1 version of mod_cfml, I noticed not all options for mod_cfml were yet available in the scripts. So I added path_info support, and now also added support for the X-webserver-context header.

The X-webserver-context header makes sure Tomcat / mod_cfml only creates one Host for each server-block/VirtualHost/web-context. Without this header, if you have multiple hostnames pointing to the same web context (eg server_name *.mysite.com;), Tomcat would create a new Host for each new hostname, which can take up quite some resources.

These additions have now been added into the github repository, and have become the basis for the new mod_cfml installation steps for nginx.

Mod_cfml now supports Apache httpd, IIS, and nginx, on all operating systems. I think we have come a long way now. If you're still missing something, let us know at modcfml.org.

No Comments

Enable PATH_INFO on Nginx with Lucee and Railo

Nginx logoUpdate, 2 hours after posting (11-aug-2015 15:30): I pasted an older code snippet. The correct one is underneath. (nginx: [emerg] "proxy_set_header" directive is not allowed here ...)


While setting up a new Ubuntu server, I decided to install Nginx instead of Apache httpd, having been jealous at the easy config files nginx has. I was really happy to find out Pete Freitag already created install scripts for Nginx + Lucee + Tomcat + some other goodies.

One of the first problems I encountered after install, while moving existing sites to this new server, was the absence of cgi.PATH_INFO. Especially on this blog, it is used on each page, except for the homepage.
It took me a few hours of Googling and trying, and almost gave up, since all examples on how to enable it included the use of fastcgi. Which is not what I am using: I am proxying to Tomcat.

Main problem I encountered was the fact that the PATH_INFO header was just not proxied to (or picked up at?) the Tomcat backend, even while adding "proxy_set_header PATH_INFO /bla/bla" to the config.

Lucee logoThen, it suddenly hit me. For the modcfml project, contributor Bilal Soylu added support for PATH_INFO to his AJP connector for IIS, called the BonCode connector. AJP does not natively support sending the path_info header to the AJP backend.
What Bilal did in the BonCode connector, is adding a request header xajp-path-info, which contains the actual path_info on the IIS side. He also made sure the 3 opensource CFML engines Lucee, Railo, and BlueDragon, accept this incoming header as the fallback path_info source. For example, see Lucee's cgi.path_info implementation at Github. The header is supported in Railo since May 2012, according to the JIRA ticket.

So that's cool: we can use a different header to send to Tomcat, which will still be picked up as regular path_info by Lucee/Railo/BlueDragon!

The following nugget should be placed somewhere in your nginx config:

set $pathinfo "";
# if the extension .cfm or .cfc is found, followed by a slash and optional extra
if ($uri ~ "^(.+?\.cf[mc])(/.*)") {
    # remember the filepath without path_info
    set $script $1;
    set $pathinfo $2;
    # rewrite the url to match the filepath wthout path_info
    rewrite ^.+$ $script break;
}
# set the custom path_info header
proxy_set_header XAJP-PATH-INFO $pathinfo;

After a reload of Nginx, your path_info should be working! If it isn't, let me know.

3 Comments

standup