Tuesday, June 26, 2007

At CFunited 07

I am posting this from Bethesda Marriott where I am attending CFUnited. I would love to meet you guys if you are here. You can catch me near our booth or at the end of my session where I will be speaking on "Language Enhancements in ColdFusion 8" on Thursday morning 8.30 - 9.30. Apart from tons of feature, we have done lots and lots of enhancements in Scorpio which should help you write better and faster application. I have selected some of the exciting enhancements for this session which I am sure you would love.
See you there !

Monday, June 18, 2007

New CFDocument hotfix released !

We have released ColdFusion MX 7.02 - CFDocument Cumulative Hot Fix that fixes lot of CFDocument related issues.
Some of the important issues that we fixed in this hotfix are

1. Text getting chopped / clipped
2. Image zoom or image cropped
3. Header/Footer overwriting the text in the page body.

If you use cfdocument, it is a must have hotfix for you.

You can download the hotfix here but do not forget to read the instructions to apply this hotfix. Enjoy !

Friday, June 08, 2007

Finding Image Type for a file

This is a follow up on my previous post on URLConnection APIs
We will use this API to find out the image type of a given file. Here is the udf.


<cffunction name="getMimeType">
<cfargument name="filepath">

<cfset var urlConn = createObject("java", "java.net.URLConnection")>
<cfset var fileobj = fileopen(filepath, "readbinary")>
<!--- just read the first 20 characters of the file as thats sufficient --->

<cfset var bytes = fileread(fileobj, 20)>
<cfset var istream = createObject("java", "java.io.ByteArrayInputStream").init(bytes)>
<cfset fileobj.close()>
<cfreturn urlConn.guessContentTypeFromStream(istream)>
</cffunction>

<cffunction name="GetImageType">
<cfargument name="filepath">
<cfset var mimetype = getMimeType(filepath)>
<cfset var imagetype="">
<cfif not isDefined("mimetype")>
<cfthrow message="Not an Image file">
</cfif>
<cfswitch expression="#mimetype#">
<cfcase Value="image/gif">
<cfset imagetype="gif">
</cfcase>
<cfcase Value="image/x-bitmap">
<cfset imagetype="bmp">
</cfcase>
<cfcase Value="image/png">
<cfset imagetype="png">
</cfcase>
<cfcase Value="image/jpeg">
<cfset imagetype="jpeg">
</cfcase>
<cfcase Value="image/jpg">
<cfset imagetype="jpeg">
</cfcase>
<cfdefaultcase>
<cfthrow message="Not an Image file">
</cfdefaultcase>
</cfswitch>
<cfreturn imagetype>
</cffunction>

If I run the code below

<cfset filepath = "C:\temp\test.jpg">
<cfoutput>#GetImageType(filepath)#</cfoutput>

It nicely prints out "jpeg".



You should note that I used the new File IO function added in ColdFusion 8 using which I can read as many no of bytes from the file as I want. No more reading the entire file into memory.

More extensive post on File IO functions coming next !

Finding mime type of any file

Hemant recently told me about this cool API in java.net.URLConnection which can tell you the mime type for common file types.


guessContentTypeFromName(String name) - that simply checks the extension of the file name specified and gets the mime type from a static map it maintains. This can be very useful in many scenarios. The map it uses is quite extensive and contains almost all the mime types.

But this has a problem. What if some one has renamed a gif to jpg? This method will say that the file is a jpg image whereas it was a gif.

Thankfully there is another method in the same class which can address this problem.


guessContentTypeFromStream(InputStream stream) - which reads the stream, takes a look at the initial bits of the file and uses that to determine the file type.
This method does a check for the following mime types :-


- application/java-vm
- application/x-java-serialized-object
- text/html
- application/xml
- image/gif
- image/x-bitmap
- image/x-pixmap
- image/png
- image/jpeg
- image/jpg
- image/vnd.fpx
- audio/basic
- audio/x-wav


Though this method leaves out many of other common types such as mp3, it is still very useful. This makes it so easy to find out the type of an image.

Saturday, June 02, 2007

ListToArray with empty elements - Part II

Yesterday I had posted about how to convert List to Array that would include empty elements. Charlie rightly pointed out a problem with that which is - it does not consider the empty elements at the end of the list.
So, a list "a,b,,c,d,," when converted to array will have only 5 elements instead of 7.

Incidently Charlie had also talked about the same some time back here and he mentions another problem with this approach. The array that is returned after split method is read only and you can not modify this array.
In order to address both these, I had to write this UDF which I guess many people would have written anyways..





<cfscript>
function list2Array(list)
{
var endCommaCount = 0;
var i = 0; var c = "";
var stringForSplit = ""; var retList=""; var arr = "";

for(i=len(list); i > 0; i--)
{
c = list.charAt(i-1);
if(c == ',')
endCommaCount++;
if( c != ',' && c != ' ')
break;
}
retlist = ArrayNew(1);

if(i != 0)
{
stringForSplit = left(list, i);
arr = stringForSplit.split("\s*,\s*");

for(i = 1; i <= ArrayLen(arr); i++)
ArrayAppend(retList, arr[i]);
}

for(i = 0; i < endCommaCount; i++)
ArrayAppend(retList, "");

return retList;
}
</cfscript>



UPDATE : Thanks to Andrew Clark for the split tip which makes it more slim and elegant. The code above changes like



<cfscript>
function list2Array(list)
{
var i = 0;
var retlist = ArrayNew(1);
var arr = list.split(",", -1);
for(i = 1; i <= ArrayLen(arr); i++)
ArrayAppend(retList, arr[i]);
return retList;
}
</cfscript>

Lets test this udf and see if it works..


<cfset cflist = "a,b,,c,,d, ,">
<cfset cfarr1 = ListToArray(cflist)>
<cfset ArrayAppend(cfarr1, "END")>
<cfset cfarr2 = List2Array(cflist)>
<cfset ArrayAppend(cfarr2, "END")>

With CF Function : <cfdump var="#cfarr1#" format="text">
With UDF : <cfdump var="#cfarr2#" format="text">


And this produces this result.
With CF Function :
array - Top 6 of 6 rows

1) a
2) b
3) c
4) d
5)
6) END
With UDF :
array - Top 9 of 9 rows

1) a
2) b
3) [empty string]
4) c
5) [empty string]
6) d
7) [empty string]
8) [empty string]
9) END


One thing to note here is that I am using new cfscript operators added in ColdFusion 8 which is so cool!!!

Friday, June 01, 2007

ListToArray with empty elements

Recently there was a request on our forum to support empty elements in ListToArray function for Scorpio i.e ColdFusion 8. it might not be done in Scorpio since it is too late to add a new function. However it can be very easily achieved in cfm itself. Here is the code to do it.

<cfset cflist="a,b,,c,,,d">
<cfset cfarr1 = ListToArray(cflist)>

<cfset cfarr2 = cflist.split(",")>
<cfset cfarr2 = cflist.split(",", -1)>

<cfdump var="#cfarr1#">
<cfdump var="#cfarr2#">

<cfscript>
for(i=1; i <= ArrayLen(cfarr2); i++)
{
writeoutput("Element #i# : #cfarr2[i]# <br>");
}
</cfscript>



As you can see, 3rd, 5th and 6th element in this cfarr2 are empty.

ColdFusion 8 beta has arrived

I think I am the last person to say that ColdFusion 8 i.e Scorpio beta is out. Yayyy !!! :)

And that means I am back on blogsphere after a long hiatus. Seriosuly, what a fabulous journey it has been! It is a result of nearly one and half year of hard work, huge amount of research, so many design discussions, fights over nitties-gritties of features, many spec review meetings (which many a times reminded me of the college time ragging or soap box for elections at IIT kgp), many beer parties (because some one was beer boy coz he broke the build) and eating rubber chicken few times (becoz the build was broken again !!) etc etc etc.. -- all to ensure that there is enough sting in the Scorpio. :)

Everyone of us in the team is really proud of the stuff that we have built and I am sure people gonna love it.

And we are not done yet! Ashwin's cartoon says it all !!!