Backward compatibility between ColdFusion 9 and ColdFusion 7 with regards to CFScript? - coldfusion

I am a complete ColdFusion newbie so apologies in advance for my upcoming ignorance.
We are having an issue with an existing CFScript. The problematic script contains the following line:
...
if (fields.length() != 0) {
// do something
}
...
The script runs successfully in ColdFusion 9, but we see the following message when trying to run the script in ColdFusion 7:
...
Invalid token '!' found on line...
...
I'm guessing that ColdFusion 7 does not like the '!=' operator, am I correct?
If so, are there any other backward compatibility issues with CFScript that could cause us to trip up? I've been searching for resources but there doesn't seem to be anything definitive.
Thanks.

Yes, in CF7 you need to use ColdFusion's native comparison operators, in your case neq.
Replace
== with eq
!= with neq
> with gt
< with lt
>= with gte
<= with lte
% with mod
and you're good to go. These operators are upward-compatible, CF9 will understand them.
Other than that,
you need to group all your local variables (those declared with var) at the top of a function in ColdFusion 7. This restriction has gone away in later editions of ColdFusion, but scripts written that way will of course continue to run.
there is an automatic local scope as of CF9. This scope was not available in CF7 and CF8, but by convention people added a var local = StructNew(); at the top of their CF7 functions, which will also work in CF > 7.

You're right - the Javascript-like operators (!=, ==, ||, etc.) were only introduced in ColdFusion 9, along with a whole lot more scripting support.
This mostly relates to full script support for CFCs, but there are probably plenty of other other gotchas out there...

Related

Is there a difference with the HTMLEditFormat function in ColdFusion CF9 versus CF10?

I'm seeing a difference in how HTMLEditFormat works in CF9 and CF10.
HTMLEditFormat(">")
In CF9: showing up as ">" (no difference)
In CF10: showing up as "&gt;" (double-escaped, which seems correct to me)
I've looked through the CF10 notes and reviewed the HTMLEditFormat documentation, but cannot find any mention of there being a difference in how this function works. Does anyone know of a difference, or know of documentation that proves there is no difference? ...Or know of any other settings (ColdFusion or web server) that might cause this to work different?
(This question is not a duplicate because am not asking about encodeForHTML. I understand that is the ideal solution, but am asking to understand why HTMLEditFormat might be different in CF9 vs. CF10.)
I can't imagine why that function would behave differently. Especially when it's was planned for deprecation going into CF 10. By chance, are you calling it from within a CFINPUT tag?
<cfinput id="foo" value="#htmlEditFormat(someValue)#" />
If so, in CF6 - CF9, that tag uses HTMLEditFormat() on values automatically. Calling a 2nd instance of HTMLEditFormat() doesn't affect the output. But CF 10+ updated the tag to use encodeForHTML() on values. If you also throw in an HTMLEditFormat(), then you're double-encoding the output.
For better security, you should stop using HTMLEditFormat() and start using encodeForHTML() if it's available (CF10+). As of ColdFusion 11, HTMLEditFormat() has been officially deprecated and by ColdFusion 12, the function should be removed completely.
HTMLEditFormat() only encodes 4 characters: <, >, &, ".
encodeForHTML() encodes almost every character, including UTF-8 characters. The updated "encodeFor" functions are contextual, so you have to pick the right on for the right context (html, htmlattribute, js, css, xml, etc.).

Application.cfc: this.debugipaddress and this.debuggingIPAddresses, what is the difference?

I've seen the following code (A list of ip addresses that need debugging) for Application.cfc:
<!---seen in blogs and perhaps earlier versions of CF documentation, livedocs isn't working for CF 7 & 8 for me tonight--->
<cfset this.debugipaddress = "192.168.1.15,192.168.1.27">
and
<!--- documented in CF 9 & 10--->
<cfset this.debuggingIPAddresses = "192.168.1.15,192.168.1.27">
http://help.adobe.com/en_US/ColdFusion/9.0/CFMLRef/WSc3ff6d0ea77859461172e0811cbec22c24-750b.html
http://help.adobe.com/en_US/ColdFusion/10.0/CFMLRef/WSc3ff6d0ea77859461172e0811cbec22c24-750b.html
I was wondering if there was a difference between the two variables? I'm using ColdFusion 10, is one preferred over the other if they are the same? Perhaps this.debugipaddress was deprecated?
From what I can find it is a documentation bug. According to Ray Camden's blog and the comments in it, it should be debuggingipaddresses not debugipaddress. Ray also used it here and pointed out that there was a correction.
Pretty standard and he appears to have nailed everything. A part of me
strongly wishes that Ben Forta would have never used UPPERCASE scope
names in the WACK books so that my eyes wouldn't have to bleed every
time I see someone else do that, but oh well :). One minor correction
- this.debugipaddress is actually this.debuggingipaddresses (see here) - no points deducted for that since it's a doc bug. I also would have liked to have seen him mention the struct keys for smtpServerSettings
({server="",username="",password=""}).

Is there any difference between these ColdFusion components?

I know the result is the same but is there any real difference? Maybe speed or something?
component {
remote function getMath(){
math = 2 + 2;
return math;
}
}
or
<cfcomponent>
<cfscript>
remote function getMath(){
math = 2 + 2;
return math;
}
</cfscript>
</cfcomponent>
or
<cfcomponent>
<cffunction name="getMath" access="remote">
<cfscript>
math = 2 + 2;
return math;
</cfscript>
</cffunction>
</cfcomponent>
Not especially.
Version 3, full tags, will be backwards compatible with ColdFusion 8 and the open source versions of ColdFusion server eg. Railo or OpenBD.
Version 2 is neither something or nothing.
Version 1 is the full ColdFusion 9 script version.
I would recommend that you choose between the first and last versions and stick to it. Version 2 is not backwards compatible to coldfusion 8 and is neither tag nor script. Coding like this will get messy quickly.
If you plan on writing everything in script, then example 1 is the way to go.
You can do anything in script that you wish, and if something is missing you can write a cfc that will implement the missing functionality and then invoke it with the new syntax.
If your starting fresh with a new codebase i'd be trying to avoid any tags all together, thus option 1.
In terms of execution speed, they all compile to the same byte code, so should be identical.
In terms of number of characters typed (excluding line breaks/tabs):
eg 1: 64
eg 2: 100
eg 3: 129
If you are running Adobe CF9, go with option 1. It's much more succinct. You can pretty much do everything in <cfscript> these days.
If you want to check the compiled byte code for each, switch on saving .class files in your cf admin and view the files in the /Classes dir with a decompiler. eg. JD-Gui
The cfscript is probably a bit faster, and more consistent with other languages while the approach is simpler (hides complexity more) and more like .
CF started as a based language and has evolved to include a complete scripting style alternative to the approach.
Differences are a question of developer style.

Safe to call underlying java method on String in ColdFusion?

Adobe ColdFusion is built on Java. Almost all simple variables in CFML/CFSCRIPT are java.lang.String until the operation needs it to be of a certain type.
I've always want to use startsWith() in String instead of the more bulky CFML variant.
left(str,4) EQ "test"
However, what's the general consensus of using underlying Java method in ColdFusion?
Would this be any safer to javacast() the var first?
javacast("String",x).startsWith("test");
What if the CF engine is not built on top of Java?
Thanks
Yes, you can do this with Adobe ColdFusion and other CFML engines that are built on Java. It's actually simpler than you thought.
<cfset str = "hello what's up" />
#str.startsWith("hello")# <!--- returns "YES" --->
<cfif str.startsWith("h")>
This text will be output
</cfif>
#str.startsWith("goodbye")# <!--- returns "NO" --->
<cfif str.startsWith("g")>
This text will NOT be output
</cfif>
This is possible because CFML strings in ColdFusion are the same as Java strings. You can use any native string method (Java.lang.String) on a CFML string.
If you haven't guessed, this also works with CFML arrays (some kind of list, probably a java.util.Vector) and structs (probably a java.util.Map). Experiment with data types and the cfdump tag, you will find a lot of secrets.
One word of warning, this is not standard CFML, so if your underlying engine changes, including just upgrading to a new version, there are no guarantees that it will still work.
That said, string.startsWith() is native to Java as well as .NET, so this will also work if your CFML engine is BlueDragon.NET. The only CFML engines it will not work on are ColdFusion 5 and previous.
Is it safe to use? I would say yes. As long as CFML engines run on Java or .NET, it's perfectly safe. It's undocumented, but easy to understand, so I would say use it freely.
I have found that using built in cf functions in most cases is faster than leveraging their java counterparts, mainly as it costs so much in cf wrapping the java methods.
If you are using .startsWith(), remember it's case sensitive, whereas cf's eq isn't.
Same goes for most of the other java String methods - .endsWith(), .contains() etc.
Unless you can bundle large sets of functionality as roll your own java util classes, mixing cf and java calls seems slow. If you are in some java code, and you have a string, and you call its startsWith() method, it just executes. Done. In cf code, you have to javaCast or blindly hope the variable is in the correct data type, which is risky with things like entirely numeric strings, and when you call a .startsWith(), there is a bunch of cf code that runs before it even gets down to the java level, which is where the slowness lives. Eg. Cf's dynamic arguments means that it has to check if there is a method on the supplied object with that many args, and of those data types (or compatible types). There is just a whole bunch of code that unavoidably runs, bridging the two languages.
But don't trust our experiences, benchmark for yourselves. eg.
<cfscript>
var sys = createObject( 'java', 'java.lang.System' );
var timer = sys.nanoTime();
// run some code here
timer = sys.nanoTime() - timer;
writeDump( var: timer );
</cfscript>
If you are using the Adobe cf engine, watch out of entirely numeric strings, they bounce between java Doubles and Strings, and don't get me started with serializeJSON()...

Why does a long cfc file work in CF8, but not CF9? Getting "Branch target offset too large for short" error

I have a fairly long cfc file, about 1800 lines long, that worked fine in ColdFusion 8, but after upgrading my development system to ColdFusion 9 and doing some testing I get a compile error for a cfc and the message says "Branch target offset too large for short". I modified the file to eliminate some unused functions and consolidated one to make it shorter and this resolved the problem to get it to work. But still, why did it die on me now when I upgraded to CF9? Anyone else run into this problem in previous or the current version of ColdFusion? Are there any solutions other than modifying the cfc file such as upgrading the jvm?
EDIT
If you have an answer to the questions I have, great! Post that, but don't waste time telling me something that I already know. If you are going to post a response, please read the question carefully and answer only if you know the answer. Don't do a google search and post crap that I already know and utilized to get the code to work. The question is, why did it work in CF8 and now not in CF9? Are there other solutions besides what I did?
This is a problem inherent with the JVM as you already know, CF9 has likely added more innate functions to a component and if the methods are all referenced via a giant switch statement with a short being used as the offset, we have less offset pointer space to work with each successive version. People moving from CF7 to CF8 also had the same problems.
So short answer is no.
Most recommendations you find basically tell you to split a large method into a smaller method and several helper methods. The first time I ran into an issue this worked for a large cfc I had. But then as it got bigger no number of helper functions would fix it. Eventually it had to be split into multiple cfcs.
PS: This guy said removing a transaction helped (CF7), there are none wrapping my calls though, so it's not a guaranteed fix I guess http://www.coldfusionmuse.com/index.cfm/2007/9/28/Branch.Target.Offset
Edit
Looks like my previous issue was a different function being too large, splitting the CFC into multiple CFCs was in error. I've since split that problem method into smaller methods, and have been able to consolidate all the functions in one CFC. So that is the solution it seems.
If you haven't already, try running the Code Analyzer in the CFAdmin page, "Debugging & Logging > Code Analyzer". This is a useful tool to find some changes which were made in the language between CF8 and CF9.
We had to change several variable names and function names as CF added them in 9.
Also check here:
http://help.adobe.com/en_US/ColdFusion/9.0/CFMLRef/WSc3ff6d0ea77859461172e0811cbec22c24-7ff0.html
CF version: 10
OS: Linux CentOS 6.0
Did face a similar issue where I had 1300+ lines of code in my cfc and one fine day I get the "Branch Target offset.." error. I tried
Code Analyser to find any loopholes of legacy- DID NOT FIX
Edited the cfc to trim down any last bit of redundant code or comments - reduced around 20+ lines of code - DID NOT FIX
I split the code into 2 cfc and extended one to the other- DID NOT FIX
I removed any unwanted dump of queries and arrays (part of testing) : THIS WORKED
so I would suggest ensure you don't have any dumps of large data content. Hope this helps.