G'day:
Adobe recently released a security fix for a security issue in ColdFusion's Flash Remoting services. It impacts all versions of ColdFusion which ship with Flash Remoting (that's at least ColdFusion 9 through ColdFusion 11, but possibly older versions too). Only CF10 and CF11 have been patched, although Piyush claims to have instructions for patching CF9 although is not being helpful about sharing this info with the ColdFusion community for some reason.
This morning I read an article from ZDNet ("Adobe issues hotfix patch for ColdFusion vulnerability") wherein Adobe appear to have claimed that this fix is a "A hotfix, otherwise known as a Quick Fix Engineering update (QFE update), is a lightweight software patch". This is somewhat of a misrepresentation of reality on the part of either Adobe or ZDNet. I suspect ZDNet are just reporting what Adobe told them.
The "patch" that was released was rolled into all other previous fixes released for ColdFusion, and one does not have the option to simply apply the one-off security fix; one also needs to apply every single other fix Adobe have ever released for the product.
This represents quite a heavy regression-testing burden for anyone thinking of applying the patch. It is not just a matter of installing one small patch and then regression testing a small subset of potential touchpoints in one's CFML application; it means a complete regression testing of everything Adobe have "fixed" in previous patches. And given the ColdFusion Team have a habit of introducing new bugs with these monolithic updates they give us, this is not something that ought to be taken lightly.
To put things in perspective, here is a list of all the fixes shipped with this "quick fix engineering update", for ColdFusion 11:
Sunday, 30 August 2015
Thursday, 27 August 2015
ColdFusion: another security hole has been patched (CF10 and CF11)
G'day:
Just so yer aware, another update for ColdFusion was released this afternoon (UK time). Apparently there's a security hole in ColdFusion's BlazeDS integration which has been fixed. I don't actually know what CF uses BlazeDS for, I have to admit. I don't even know what BlazeDS even is, now that I come to think of it. [quickly googles...]
So no wonder I didn't know what it was.
Anyway, Anit said on the Slack channel that it will on affect you if yer using BlazeDS, so that's probably not most people.
The Adobe blog article about it is here: "ColdFusion 11 Update 6 and ColdFusion 10 Update 17 now available". Make sure to subscribe to the comments on that thread to keep yourself up to date with anything "untoward" in the update process. I've not installed it myself yet. Obviously make sure to test the update in your test lab first. Don't just stick it straight on your live boxes. Also bear in mind that CF updates are cumulative, so as well as this particular fix, it'll include all the other bugfixes too, so there's a lot of moving parts that could cause you grief. Regression test thoroughly.
I guess if you're using CF9 or older you're SooL, I'm afraid.
That's it.
--
Adam
Just so yer aware, another update for ColdFusion was released this afternoon (UK time). Apparently there's a security hole in ColdFusion's BlazeDS integration which has been fixed. I don't actually know what CF uses BlazeDS for, I have to admit. I don't even know what BlazeDS even is, now that I come to think of it. [quickly googles...]
BlazeDS is a server-based Java remoting and web messaging technology that allows you to connect to back-end distributed data and push data to Adobe Flex and Adobe Integrated Runtime (AIR) Rich Internet applications (RIA).
So no wonder I didn't know what it was.
Anyway, Anit said on the Slack channel that it will on affect you if yer using BlazeDS, so that's probably not most people.
Update:
Seems I've misinterpreted what Anit said, or something, as Rupesh - who is now on the CFML Slack Channel too - has just clarified with this:Regarding the blazeds 0-day vulnerability that we patched a day back, It seems like there is an impression that the server is not impacted if you are not using blazeds. Your server is not impacted *only* if you have disabled flash remoting. By default it is enabled and hence your server is impacted.
Please make sure to apply this update
The Adobe blog article about it is here: "ColdFusion 11 Update 6 and ColdFusion 10 Update 17 now available". Make sure to subscribe to the comments on that thread to keep yourself up to date with anything "untoward" in the update process. I've not installed it myself yet. Obviously make sure to test the update in your test lab first. Don't just stick it straight on your live boxes. Also bear in mind that CF updates are cumulative, so as well as this particular fix, it'll include all the other bugfixes too, so there's a lot of moving parts that could cause you grief. Regression test thoroughly.
I guess if you're using CF9 or older you're SooL, I'm afraid.
Update re ColdFusion 9:
Piyush has indicated Adobe do have instructions as to how to patch ColdFusion 9 servers, but instead of just posting them like a responsible vendor would do, one has to email him to get them. Groan. However Dave Epler has documented his steps to patch CF9 on his blog: "Manually Patching ColdFusion 9 with APSB15-21 (CVE-2015-3269)". Dave knows what he's doing, so you'll be safe in his hands. Safer than in Adobe's, it would seem.That's it.
--
Adam
CFML: how should int()
behave?
G'day:
One of the scintillating conversations on the CFML Slack channel today was regarding people's expectations of CFML's
And he quite legitimately expected the result to be -37 (the float value before converting to an int is -37.357142857143). However because CFML is daft (IMO), its integer conversion follows this rule:
What it should do is simply return the integer part of the number. It's not a rounding function, it's a conversion function.
I thought there might be a precedent in other languages, but here's some code samples:
Returns 37 when passed -37.357142857143.
Ruby:
JavaScript:
Groovy:
Python:
Clojure:
Oops! Almost forgot PHP (I actually did forget... this is being added during a re-edit)
You get the idea.
So... it's a bit late in the game to fix
Note one can use
Is there any precedent in any other language for an
--
Adam
One of the scintillating conversations on the CFML Slack channel today was regarding people's expectations of CFML's
int()
function. Ross had this expression:int(35 - (1013 / (13+1)))
And he quite legitimately expected the result to be -37 (the float value before converting to an int is -37.357142857143). However because CFML is daft (IMO), its integer conversion follows this rule:
Calculates the closest integer that is smaller than number.Which means the result of the expression is -38.
What it should do is simply return the integer part of the number. It's not a rounding function, it's a conversion function.
I thought there might be a precedent in other languages, but here's some code samples:
// testInt.java
public class TestInt {
public static int toInt(Double f){
return f.intValue();
}
}
Returns 37 when passed -37.357142857143.
Ruby:
irb(main):004:0> -37.357142857143.to_i
=> -37
=> -37
JavaScript:
parseInt(-37.357142857143)
-37
-37
Groovy:
groovy:000> (int) -37.357142857143
===> -37
===> -37
Python:
>>> int(-37.357142857143)
-37
-37
Clojure:
user=> (int -37.357142857143)
-37
-37
Oops! Almost forgot PHP (I actually did forget... this is being added during a re-edit)
d:\webSites\www.scribble.local>php
<?php
$f = -37.357142857143;
$i = (int) $f;
echo $i;
^Z
-37
<?php
$f = -37.357142857143;
$i = (int) $f;
echo $i;
^Z
-37
You get the idea.
So... it's a bit late in the game to fix
int()
in CFML, but John Whish has raised a ticket for ColdFusion: "Deprecate `int` in favour of `floor
`" (4044533). This makes good sense to me. CFML already has a ceiling()
function, so it makes sense to also have floor()
.Note one can use
fix()
in CFML to get the right result, ie: just the integer part of the number. But that's just a fix. Pity int()
didn't just do the right thing in the first place.Is there any precedent in any other language for an
int()
operation to actually do rounding instead?--
Adam
Labels:
CFML,
John Whish,
Salted
Wednesday, 26 August 2015
CFML: ways to help or be helped with ColdFusion and Lucee
G'day:
This article has been inspired by "reports of the death of the House of Fusion CFML forums are not greatly exaggerated". I dunno of anyone has been able to reach whoever represented the human manifestation of HoF, or just the continued radio-silence has been inferred as demise.
Russ from CFMLDeveloper has started a new Google Group to fill the void left by HoF disappearing:
Dom Watson also quickly reminded people that there's the #CFML Slack channel too:
If I was being uncharitable, I'd observe that Dom's choice of words there might sound a bit dismissive of Russ's efforts, for some reason. But I'd never be uncharitable.
This article has been inspired by "reports of the death of the House of Fusion CFML forums are not greatly exaggerated". I dunno of anyone has been able to reach whoever represented the human manifestation of HoF, or just the continued radio-silence has been inferred as demise.
Russ from CFMLDeveloper has started a new Google Group to fill the void left by HoF disappearing:
For those that do not know, the well known and long running House Of Fusion and CF-Talk mailing list are now dead.... http://t.co/fYlDFKFVgr
— cfmldeveloper (@cfmldeveloper) August 25, 2015
And, indeed here they are @ https://groups.google.com/forum/#!forum/cfmldeveloper:Dom Watson also quickly reminded people that there's the #CFML Slack channel too:
For those that did not know, there is a new home for #cfml developers on Slack 700+ members http://t.co/2cKFtAhccg https://t.co/uZtTyg16Pj— Dominic Watson (@dom_watson) August 25, 2015
If I was being uncharitable, I'd observe that Dom's choice of words there might sound a bit dismissive of Russ's efforts, for some reason. But I'd never be uncharitable.
Sunday, 23 August 2015
JavaScript: running Jasmine unit tests from the CLI
G'day:
I can't see as this will be very long as I've not much to say about it, and it was surprisingly quick to sort out once I bothered to do so.
My weekend mission was going to be to start getting up to speed with Clojure, by reading & working through the relevant chapters from Seven Languages in Seven Weeks, but whilst that kept me occupied on my flight from London to Shannon, I didn't really revisit it after that, as I got sidetracked on these Jasmine tests. Well firstly I decided my mission would be to do a Clojure version of my "get a subseries" quiz ("Something for the weekend? A wee code quiz (in CFML, PHP, anything really...)"), and before doing that I wanted to get a working version of the code I discussed in "Some CFML code that doesn't work" working, chosing JavaScript as my control language. And in deciding to do that, I decided not to just copy and paste it into the browser console to test it, I decided to do it properly and do a file-system-based exercise running it via Node (note to Acker: I already use Node. Just sparingly because the need for it doesn't crop up for me that often. You don't actually have any special knowledge the rest of us also don't already have). And if I was gonna do that, then I was also gonna get Jasmine working via Node too, as we actually do have a real requirement for this at work. We have an ever increasing amount of ever increasingly complex JS in our application... and so far not a line of testing gets done on it. We're shifting our mindset to be writing more testable JS: reducing inline callbacks; putting a much of our code in "class" file, and writing small, clean, testable methods an the like all ready for testing... but getting the actual test infrastructure up and running is just not happening.
So, anyway... other than installing Clojure via Leiningen and runing "G'day World" via the REPL, my Clojure investigations didn't move much.
But I got the JavaScript version of my CFML code running, and also got its tests running via the commandline too. So that's cool.
I can't see as this will be very long as I've not much to say about it, and it was surprisingly quick to sort out once I bothered to do so.
My weekend mission was going to be to start getting up to speed with Clojure, by reading & working through the relevant chapters from Seven Languages in Seven Weeks, but whilst that kept me occupied on my flight from London to Shannon, I didn't really revisit it after that, as I got sidetracked on these Jasmine tests. Well firstly I decided my mission would be to do a Clojure version of my "get a subseries" quiz ("Something for the weekend? A wee code quiz (in CFML, PHP, anything really...)"), and before doing that I wanted to get a working version of the code I discussed in "Some CFML code that doesn't work" working, chosing JavaScript as my control language. And in deciding to do that, I decided not to just copy and paste it into the browser console to test it, I decided to do it properly and do a file-system-based exercise running it via Node (note to Acker: I already use Node. Just sparingly because the need for it doesn't crop up for me that often. You don't actually have any special knowledge the rest of us also don't already have). And if I was gonna do that, then I was also gonna get Jasmine working via Node too, as we actually do have a real requirement for this at work. We have an ever increasing amount of ever increasingly complex JS in our application... and so far not a line of testing gets done on it. We're shifting our mindset to be writing more testable JS: reducing inline callbacks; putting a much of our code in "class" file, and writing small, clean, testable methods an the like all ready for testing... but getting the actual test infrastructure up and running is just not happening.
So, anyway... other than installing Clojure via Leiningen and runing "G'day World" via the REPL, my Clojure investigations didn't move much.
But I got the JavaScript version of my CFML code running, and also got its tests running via the commandline too. So that's cool.
Labels:
Javascript,
Unit Testing
Thursday, 20 August 2015
Erm...
G'day:
There's always this:
I don't know quite what to make of that, but "thanks" to Nicholas from the CFML Slack channel, anyhow.
--
Batman
There's always this:
I don't know quite what to make of that, but "thanks" to Nicholas from the CFML Slack channel, anyhow.
--
Batman
Killing a muppet
G'day:
Firstly, if you feel so inclined, please take a refresher on my communications policy.
Secondly... I deeply dislike the concept of censorship, and this extends to moderation of the comments on this blog. The only comments I have blocked have been blatant exercises in spam advertising, other than that I have let every single comment through. Sometimes a comment might seem like spam so it gets blocked for a while by Disqus, but I have never - to my recollection - not approved any comment by a person whose intent was to comment on the article.
This changed this morning: I blacklisted my first respondent. This person was Acker Apple.
Acker is a bit of a plank (IMO), and seems to exist solely to bobble up and down like Beaker on The Muppets going "I like Node!" "Node is good!" "I used to use CF now I use Node!" "Node is Good!" "You're Bad, I'm Good!" "node node node node node", and other stuff which demonstrates the Dunning-Kruger effect is alive and well. Examples of this are here: "ColdFusion: Adobe updates their roadmap for ColdFusion. Forgets to give the language directions" and here: "What I'd like to see in ColdFusion 12 (redux, as is happens)".
There's nothing wrong with being a plank, and in very small doses it can be endearing. But when it ends up seeming like a mistake that the grown-ups let the children sit at the dinner table, a sensible and responsible grown-up will usher the children back out of the room so the adults can get on with it.
I was going to just tell Acker to shut up (I put it more directly than that), but having checked my comms over night I have had a couple of actual complaints about his conduct, and the very real fact he's toxifying the comments section on this blog with his continual nonsense, and it's discourgaing participation from more lucid & engaging participants.
To be very clear: the comments on this blog are very important to the content of the blog itself, and oftentimes the comments are more interesting that the article they're commenting on. I welcome all points of view, and especially ones that disagree with me as those are the ones I personally learn the most from. You can, in general, say whatever you like, in whatever tone you like (other than the usual societal / community nonos). I'm not blocking Acker because of his dissenting voice. I'm blocking him cos he's a bit of a cock.
So Acker has been ushered out of this particular room. I have blacklisted his email address (which is about all I can do on Disqus), and will monitor any further input from him by hand. If it is on-topic for any post he decides to reply to: I will consider approving it.
Equally, some other people need to learn to "not feed trolls" as the internet addage goes. This is even worse clutter than the original comments, IMO. I will take a very dim view of anyone adding to clutter in this vein, too. If someone is trolling: just leave them be. Don't become part of the problem.
Finally: apologies to my other readers who might have felt a bit put off by my lack of better/earlier handling of this.
Righto.
--
Adam
* Image from here used without permission. If you are the copyright holder and would prefer I do not use this image, let me know and I'll take it down.
Firstly, if you feel so inclined, please take a refresher on my communications policy.
Secondly... I deeply dislike the concept of censorship, and this extends to moderation of the comments on this blog. The only comments I have blocked have been blatant exercises in spam advertising, other than that I have let every single comment through. Sometimes a comment might seem like spam so it gets blocked for a while by Disqus, but I have never - to my recollection - not approved any comment by a person whose intent was to comment on the article.
This changed this morning: I blacklisted my first respondent. This person was Acker Apple.
Acker is a bit of a plank (IMO), and seems to exist solely to bobble up and down like Beaker on The Muppets going "I like Node!" "Node is good!" "I used to use CF now I use Node!" "Node is Good!" "You're Bad, I'm Good!" "node node node node node", and other stuff which demonstrates the Dunning-Kruger effect is alive and well. Examples of this are here: "ColdFusion: Adobe updates their roadmap for ColdFusion. Forgets to give the language directions" and here: "What I'd like to see in ColdFusion 12 (redux, as is happens)".
There's nothing wrong with being a plank, and in very small doses it can be endearing. But when it ends up seeming like a mistake that the grown-ups let the children sit at the dinner table, a sensible and responsible grown-up will usher the children back out of the room so the adults can get on with it.
I was going to just tell Acker to shut up (I put it more directly than that), but having checked my comms over night I have had a couple of actual complaints about his conduct, and the very real fact he's toxifying the comments section on this blog with his continual nonsense, and it's discourgaing participation from more lucid & engaging participants.
To be very clear: the comments on this blog are very important to the content of the blog itself, and oftentimes the comments are more interesting that the article they're commenting on. I welcome all points of view, and especially ones that disagree with me as those are the ones I personally learn the most from. You can, in general, say whatever you like, in whatever tone you like (other than the usual societal / community nonos). I'm not blocking Acker because of his dissenting voice. I'm blocking him cos he's a bit of a cock.
So Acker has been ushered out of this particular room. I have blacklisted his email address (which is about all I can do on Disqus), and will monitor any further input from him by hand. If it is on-topic for any post he decides to reply to: I will consider approving it.
Equally, some other people need to learn to "not feed trolls" as the internet addage goes. This is even worse clutter than the original comments, IMO. I will take a very dim view of anyone adding to clutter in this vein, too. If someone is trolling: just leave them be. Don't become part of the problem.
Finally: apologies to my other readers who might have felt a bit put off by my lack of better/earlier handling of this.
Righto.
--
Adam
* Image from here used without permission. If you are the copyright holder and would prefer I do not use this image, let me know and I'll take it down.
Labels:
Acker Apple,
Blog
Tuesday, 18 August 2015
ColdFusion: Adobe updates their roadmap for ColdFusion. Forgets to give the language directions
G'day:
Rakshith has today released the latest iteration of the ColdFusion road map: "New Product Roadmap for ColdFusion".
Here's a scrape of the PDF (linked to in that article):
So that's a bit bleak. I'm not sure I needed something to manage web services. But then again I can't think what that might entail, so I'll keep an open mind. It does sound like something aimed at IT managers rather than something which'll end up being well-realised for ColdFusion administrators.
I know PDF stuff is important to a lot of people, but not me. Don't care. This could be quite good for people who do care though, I s'pose.
I don't see how "CLI" comes under language enhancements. But still: this'll be something worth having a look at, I reckon. I'm looking forward to that.
Ordered / sorted structs? Yeah... I guess. I know people seem to want to control the ordering of keys in a struct, but I have always thought that this is a misuse of a struct. Also this seems a bit stuck in a procedural coding mindset. If we want to be able to iterate over a some sort of keyed data structure, wouldn't providing something like IEnumerable so that an object's keys can be iterated over. Still: it's a bit of an edge case to want to do that too. But what an approach like this would give the CFML developer is more control over what they can do with the functionality, rather than being limited to Adobe's implementation.
Storing sessions externally? Cool. But not a language feature. This is an admin feature.
So it's pretty bloody light on areas which I am interested in: the CFML language. Still: it's early days in the pre-release cycle, so maybe more stuff will come in. Also this doc seems like a marketing doc not a technical doc, so perhaps distinct language features are not "marquee" enough for this sort of doc?
It'd be great if for once Rakshith could produce something aimed at ColdFusion's developer community.
I don't care about CF Builder or ColdFusion on Cloud, so someone else can editorialise about those.
I'm actually pretty disappointed in this. I'm certain (-ish) that Rakshith claimed ColdFusion 2016 was gonna be developer-centric, rather than PHB-centric, and it seems they've backed away from that. Pity. There are so many excellent language features CFML could add to make it a more appealing prospect for the rest of the IT industry (obviously it'd also need a marketing push in that direction too). Oh well. I guess it's not surprising really.
There's also mention of ColdFusion 13, but it's pretty nebulous:
Bleah. Don't care at all about that lot. Good to see Language improvements being a "focus". Even if otherwise completely glossed over.
As for the release/support cycle:
Not that Adobe have a habit of sticking to plan, but this suggests that given ColdFusion 10 goes into "extended support" (the yellow bit) in mid 2017 (EOL in mid 2019), then we won't be expecting to see ColdFusion 2016 until mid 2017?! That doesn't seem right. I would more expect it to show up early Q2 next year. I'd guess ColdFusion 2016+1 would be out early 2018. Hopefully I will not care by then ;-)
It's public knowledge I'm on the ColdFusion 2016 pre-release programme, but I can't bloody say anything about it yet. The next milestone I'm looking forward to is being able to write up some of the stuff I've been looking at.
Anyway... I've got work to get back to. And a sandwich to eat.
--
Adam
Rakshith has today released the latest iteration of the ColdFusion road map: "New Product Roadmap for ColdFusion".
Here's a scrape of the PDF (linked to in that article):
So that's a bit bleak. I'm not sure I needed something to manage web services. But then again I can't think what that might entail, so I'll keep an open mind. It does sound like something aimed at IT managers rather than something which'll end up being well-realised for ColdFusion administrators.
I know PDF stuff is important to a lot of people, but not me. Don't care. This could be quite good for people who do care though, I s'pose.
I don't see how "CLI" comes under language enhancements. But still: this'll be something worth having a look at, I reckon. I'm looking forward to that.
Ordered / sorted structs? Yeah... I guess. I know people seem to want to control the ordering of keys in a struct, but I have always thought that this is a misuse of a struct. Also this seems a bit stuck in a procedural coding mindset. If we want to be able to iterate over a some sort of keyed data structure, wouldn't providing something like IEnumerable so that an object's keys can be iterated over. Still: it's a bit of an edge case to want to do that too. But what an approach like this would give the CFML developer is more control over what they can do with the functionality, rather than being limited to Adobe's implementation.
Storing sessions externally? Cool. But not a language feature. This is an admin feature.
So it's pretty bloody light on areas which I am interested in: the CFML language. Still: it's early days in the pre-release cycle, so maybe more stuff will come in. Also this doc seems like a marketing doc not a technical doc, so perhaps distinct language features are not "marquee" enough for this sort of doc?
It'd be great if for once Rakshith could produce something aimed at ColdFusion's developer community.
I don't care about CF Builder or ColdFusion on Cloud, so someone else can editorialise about those.
I'm actually pretty disappointed in this. I'm certain (-ish) that Rakshith claimed ColdFusion 2016 was gonna be developer-centric, rather than PHB-centric, and it seems they've backed away from that. Pity. There are so many excellent language features CFML could add to make it a more appealing prospect for the rest of the IT industry (obviously it'd also need a marketing push in that direction too). Oh well. I guess it's not surprising really.
There's also mention of ColdFusion 13, but it's pretty nebulous:
Bleah. Don't care at all about that lot. Good to see Language improvements being a "focus". Even if otherwise completely glossed over.
As for the release/support cycle:
Not that Adobe have a habit of sticking to plan, but this suggests that given ColdFusion 10 goes into "extended support" (the yellow bit) in mid 2017 (EOL in mid 2019), then we won't be expecting to see ColdFusion 2016 until mid 2017?! That doesn't seem right. I would more expect it to show up early Q2 next year. I'd guess ColdFusion 2016+1 would be out early 2018. Hopefully I will not care by then ;-)
It's public knowledge I'm on the ColdFusion 2016 pre-release programme, but I can't bloody say anything about it yet. The next milestone I'm looking forward to is being able to write up some of the stuff I've been looking at.
Anyway... I've got work to get back to. And a sandwich to eat.
--
Adam
Thursday, 13 August 2015
Adobe ColdFusion Documentation Team: thanks!
G'day:
As hopefully you all know, the latest implementation of the online ColdFusion docs is a wiki, meaning the user-base can edit it. It's not quite as free to edit as - say - Wikipedia, as one does need to contact Adobe for permissions to have editing rights, but that's fairly straight forward: it's just an email (I'm hitting Anit up as I type to get the best official way to contact them, and will update this article when I have it. Or as Mary-Jo points out in the comments below, there is this guidance page: "Moderator Guidelines", which suggests emailing cfdocs@adobe.com).
Anyway, I signed-up a while ago, and whenever I hear of something wrong with the docs, I'll fix 'em if I can. I probably average one change a month or something like that: I don't spend much time on it.
So you could knock me over with a feather when this email arrived yesterday:
Wasn't that nice?
Anyhow, maybe go along and sign-up to be a documentation editor, and you can help the ColdFusion community too. Every small change we make improves things for everyone else.
Righto.
--
Adam
As hopefully you all know, the latest implementation of the online ColdFusion docs is a wiki, meaning the user-base can edit it. It's not quite as free to edit as - say - Wikipedia, as one does need to contact Adobe for permissions to have editing rights, but that's fairly straight forward: it's just an email (I'm hitting Anit up as I type to get the best official way to contact them, and will update this article when I have it. Or as Mary-Jo points out in the comments below, there is this guidance page: "Moderator Guidelines", which suggests emailing cfdocs@adobe.com).
Anyway, I signed-up a while ago, and whenever I hear of something wrong with the docs, I'll fix 'em if I can. I probably average one change a month or something like that: I don't spend much time on it.
So you could knock me over with a feather when this email arrived yesterday:
On the contrary, ColdFusion Documentation Team: thank you.
Dear Adam,
Two years ago, we made a decision to move ColdFusion documentation to a wiki model so that we can open the documentation up to chosen ColdFusion experts to improve and add value to the content.
Today, we took stock and realized we received over 500 contributions from ColdFusion experts.
We received contributions of various kinds – better code samples, various usage scenarios, even a complete developer security guide and much more. We believe this is a good reason to celebrate and pass on our appreciation to you for all your contributions.
We value your contributions and here is a small token of appreciation in the form of an Amazon gift voucher to reciprocate our heartfelt thanks. Enjoy!
Your Amazon Claim Code is [redacted] for 50 dollars.
[...]
Thank you again,
ColdFusion Documentation Team
Wasn't that nice?
Anyhow, maybe go along and sign-up to be a documentation editor, and you can help the ColdFusion community too. Every small change we make improves things for everyone else.
Righto.
--
Adam
Labels:
Adobe
Wednesday, 12 August 2015
Lucee: uncontrolled language design demonstrated
G'day:
My attention was drawn to this this morning via Dom congratulating Geoff at doing a good job improving some of Lucee's docs:
And Dom was right: Geoff's been doing a bunch of thankless donkey work, and Lucee's docs are better for it. However when I looked at Geoff's pull request, I noticed something interesting:
Before we start, I don't know that this is correct. A CFML datetime object extends java.util.Date amongst other things:
And a java.util.Date is time zone aware.
This can be borne out by just looking at one of them:
And as my PC's time zone is currently set to NZST, I get this:
My attention was drawn to this this morning via Dom congratulating Geoff at doing a good job improving some of Lucee's docs:
Kudos to @modius for great work on improving #lucee docs (little by little): https://t.co/RSiUodeEja #cfml http://t.co/EpFHfboiPj— Dominic Watson (@dom_watson) August 10, 2015
And Dom was right: Geoff's been doing a bunch of thankless donkey work, and Lucee's docs are better for it. However when I looked at Geoff's pull request, I noticed something interesting:
minute()
Extracts the minute value from a date/time object.
Returns: number
Usage:Minute( date [, timezone ] )
Arguments:
Argument Type/Required Notes date datetime/required date object timezone string/optional A datetime object is independent of a specific timezone, it is only a offset in milliseconds from 1970-1-1 00.00:00 UTC (Coordinated Universal Time). This means that the timezone only comes into play when you need specific information like hours in a day, minutes in a hour or which day it is since those calculations depend on the timezone. For these calculations, a timezone must be specified in order to translate the date object to something else.[...]
Before we start, I don't know that this is correct. A CFML datetime object extends java.util.Date amongst other things:
public final class lucee.runtime.type.dt.DateTimeImpl
extends lucee.runtime.type.dt.DateTime
extends java.util.Date
extends java.lang.Object
extends implements lucee.runtime.type.SimpleValue, lucee.runtime.type.Objects
And a java.util.Date is time zone aware.
This can be borne out by just looking at one of them:
<cfoutput>#now().getTimezoneOffset()#</cfoutput>
And as my PC's time zone is currently set to NZST, I get this:
-720
Labels:
Lucee
Sunday, 9 August 2015
CFML: an exercise in converting a nested set tree into an adjacency list tree
G'day:
One of the bods on the CFML Slack channel - who coincidentally is a fellow Kiwi - Marty Pine got me interested in this whilst we were chatting about some code last night. I tried to get my brain around the problem at the time, but I was 3-4 pints into a pub session at the time, and it was a bit too complex. I dunno how much use I was to him solving his problem.
However this got me thinking today, during my fortnightly "four hours to kill @ Shannon Airport" stints. As an exercise for myself, I decided to knock together some code to convert a nested set tree into an adjacency list tree.
I couldn't quite solve this one in my head... it requires recursion and my brain doesn't recurse very well (just "curse": f*ckin' fine. Just not recurse). So I've been trying out various versions of my solution for a coupla hours now, but I've finally decided I can't take any more code out, and I've only got one wee niggle with my solution.
So here's the data:
I've just indented it like that to make the hierarchy clearer.
The problem with a vanilla nested set is that whilst it's dead easy to work out a node's full ancestory or its full descendant subtree, but it's not so easy to just find a node's parent or immediate children. On the other hand, an adjacency list is excellent at finding what's adjacent (oddly enough), so the parent and children of a node; but it's not so excellent at finding the hierarchy in either direction, without using recursion. To this end, I usually use a hybrid approach: have a nested set, but as well as the left/right, I also maintain a parent. But... anyhow.
So the deal is here I want to convert this to a nested structure that is based around the parent/child relationship. Well: a parent node knows its children in this case.
The rule I'm using here is that a node's children (if any) are the nodes that "stretch" across the left/right gap of the parent. So the first child has a
Leveraging CFML's iteration functions, this is surprisingly easy:
That's a total of two statements in the function:
Obviously the "returning the result" bit has a coupla iteration method calls, but they're still pretty basic!
The "tricky" thing here - and something that I've never attempted before - is that the filter method progressively changes what it filters on, to just get the "next" child, based on the fact that the next child is immediately to the right of the previous one. And that's a simple calculation.
Dumping-out the result of this gives the following:
This does indeed create an adjacency list hierarchy. Job done.
One thing I thought about is that for a given child, I do not need to filter the entire tree to find its children; just the descendants of said child. I added in a filter in on the recursive bit thus:
So that only passes the descendant subtree into the recursive call. But that was actually doing slightly more work than just using the full tree. I suspect it depends on the size of the tree (or its depth or its width?) as to whether there's a gain to be had here.
I also figured I should put a reference back to the parent into each child too, so the hierarchy is traversable in both directions, which is easily achievable doing this:
Or a variation on that theme in which one passes the entire struct for this level into the recursion as the parent, depending on what one needs. Still: this is all variations on the same theme, so I won't witter on.
Well that wiled away the time waiting for my flight. I might go find my gate now, and sit down there.
Righto.
--
Adam
2020-10-16: new resource
Ben Brumm has hit me up and asked me to link to an excellent article he's written: Hierarchical Data in SQL: The Ultimate Guide. I scanned through it and it's all interesting and useful stuff, and very accessibly written. If you land here... it's probably worth heading over there to have a look at that article too.One of the bods on the CFML Slack channel - who coincidentally is a fellow Kiwi - Marty Pine got me interested in this whilst we were chatting about some code last night. I tried to get my brain around the problem at the time, but I was 3-4 pints into a pub session at the time, and it was a bit too complex. I dunno how much use I was to him solving his problem.
However this got me thinking today, during my fortnightly "four hours to kill @ Shannon Airport" stints. As an exercise for myself, I decided to knock together some code to convert a nested set tree into an adjacency list tree.
I couldn't quite solve this one in my head... it requires recursion and my brain doesn't recurse very well (just "curse": f*ckin' fine. Just not recurse). So I've been trying out various versions of my solution for a coupla hours now, but I've finally decided I can't take any more code out, and I've only got one wee niggle with my solution.
So here's the data:
tree = [
{id=1, left=1, right=28},
{id=2, left=2, right=17},
{id=3, left=3, right=10},
{id=4, left=4, right=5},
{id=5, left=6, right=7},
{id=6, left=8, right=9},
{id=7, left=11, right=16},
{id=8, left=12, right=13},
{id=9, left=14, right=15},
{id=10, left=18, right=27},
{id=11, left=19, right=22},
{id=12, left=20, right=21},
{id=13, left=23, right=26},
{id=14, left=24, right=25}
];
I've just indented it like that to make the hierarchy clearer.
The problem with a vanilla nested set is that whilst it's dead easy to work out a node's full ancestory or its full descendant subtree, but it's not so easy to just find a node's parent or immediate children. On the other hand, an adjacency list is excellent at finding what's adjacent (oddly enough), so the parent and children of a node; but it's not so excellent at finding the hierarchy in either direction, without using recursion. To this end, I usually use a hybrid approach: have a nested set, but as well as the left/right, I also maintain a parent. But... anyhow.
So the deal is here I want to convert this to a nested structure that is based around the parent/child relationship. Well: a parent node knows its children in this case.
The rule I'm using here is that a node's children (if any) are the nodes that "stretch" across the left/right gap of the parent. So the first child has a
child.left
of parent.left+1
; the next immediate child has a nextChild.left
which is previousChild.right+1
(if that makes sense... perhaps just look at the data). And for each child... I get its children via exact the same mechanism (calling it recursively). And if I then just "remember" everything at the right time as I traverse the tree... I'll get a nice recursive data structure.Leveraging CFML's iteration functions, this is surprisingly easy:
function convertNestedSetToAdjacencyList(tree, node=tree[1]){
var nextChildLeft = node.left + 1;
return {
id = node.id,
children = tree.filter(function(node){
if (node.left != nextChildLeft){
return false;
}
nextChildLeft = node.right + 1;
return true;
}).map(function(child){
return convertNestedSetToAdjacencyList(tree,child);
})
};
}
That's a total of two statements in the function:
- setting
nextChildLeft
; - returning the result.
Obviously the "returning the result" bit has a coupla iteration method calls, but they're still pretty basic!
- run a filter to get the children.
- remap the children calling the function again for each one.
The "tricky" thing here - and something that I've never attempted before - is that the filter method progressively changes what it filters on, to just get the "next" child, based on the fact that the next child is immediately to the right of the previous one. And that's a simple calculation.
Dumping-out the result of this gives the following:
This does indeed create an adjacency list hierarchy. Job done.
One thing I thought about is that for a given child, I do not need to filter the entire tree to find its children; just the descendants of said child. I added in a filter in on the recursive bit thus:
convertNestedSetToAdjacencyList(tree.filter(function(potentialDescendant){
return node.left < potentialDescendant.left && node.right > potentialDescendant.right;
}),child)
So that only passes the descendant subtree into the recursive call. But that was actually doing slightly more work than just using the full tree. I suspect it depends on the size of the tree (or its depth or its width?) as to whether there's a gain to be had here.
I also figured I should put a reference back to the parent into each child too, so the hierarchy is traversable in both directions, which is easily achievable doing this:
function convertNestedSetToAdjacencyList(tree, node=tree[1],parent=0){
var nextChildLeft = node.left + 1;
return {
id = node.id,
parent = parent,
children = tree.filter(function(node){
if (node.left != nextChildLeft){
return false;
}
nextChildLeft = node.right + 1;
return true;
}).map(function(child){
return convertNestedSetToAdjacencyList(tree,child, node.id);
})
};
}
Or a variation on that theme in which one passes the entire struct for this level into the recursion as the parent, depending on what one needs. Still: this is all variations on the same theme, so I won't witter on.
Well that wiled away the time waiting for my flight. I might go find my gate now, and sit down there.
Righto.
--
Adam
Labels:
CFML
PHP 7: specifying the context for closure to use
G'day:
Here's a cool new feature of PHP 7 that doesn't seem to have been spouted off about as much as other things like speed (oh, I don't know if anyone has mentioned: did you know PHP 7 is faster than PHP 5? I'm not sure if anyone's mentioned that. In the last 5min, anyhow) and "spaceship operators". In PHP 7 one can specify the context to which a closure should bind to with a single method call.
Here's an example. The code below just calls a closure using the usual approach:
Here's a cool new feature of PHP 7 that doesn't seem to have been spouted off about as much as other things like speed (oh, I don't know if anyone has mentioned: did you know PHP 7 is faster than PHP 5? I'm not sure if anyone's mentioned that. In the last 5min, anyhow) and "spaceship operators". In PHP 7 one can specify the context to which a closure should bind to with a single method call.
Here's an example. The code below just calls a closure using the usual approach:
<?php
//demo.php
class A {
private $v = "A OBJECT CONTEXT\n";
private $closureToInject;
function __construct($b){
$this->b = $b;
$this->injectClosure();
}
private function injectClosure(){
$this->closureToInject = function(){
return $this->v;
};
$this->b->injected = $this->closureToInject;
}
function callDirectly(){
return ($this->b->injected)();
}
}
class B {
private $v = "B OBJECT CONTEXT\n";
public $injected;
}
$b = new B();
$a = new A($b);
echo $a->callDirectly();
- The bulk of this is just getting two disconnected environments which each have their own
$v
property: one in the A class, and one in the B class. - B has a public property which we can inject a closure into if we so choose (we do).
- In A we define a function expression (which uses closure) which simply echoes the value of the
$v
property. - And then we call said function.
Thursday, 6 August 2015
CFML: code challenge from the CFML Slack channel
G'day:
I wasn't gonna write anything today, but then Jessica on Slack (to use her full name) posted a code puzzle on the CFML Slack channel, which I caught whilst I was sardined in a train to Ilford en route home. I nutted out a coupla solutions in my head instead of reading my book, and I saw this as a good opportunity (read: "excuse") to pop down to the local once I got home and squared away a coupla things, and key the code in and see if it worked. I was moderately pleased with the results, and I think I've solved it in an interesting way, so am gonna reproduce here.
Jessica's problem was thus:
On the Slack channel there was talk of loops and recursion and that sort of thing, which all sounded fine (other people came up with answers, but I purposely did not look at them lest they influenced my own efforts). The more I work with CFML and its iteration methods (
Whilst waiting to Skype with my boy I wrote my tests:
I wasn't gonna write anything today, but then Jessica on Slack (to use her full name) posted a code puzzle on the CFML Slack channel, which I caught whilst I was sardined in a train to Ilford en route home. I nutted out a coupla solutions in my head instead of reading my book, and I saw this as a good opportunity (read: "excuse") to pop down to the local once I got home and squared away a coupla things, and key the code in and see if it worked. I was moderately pleased with the results, and I think I've solved it in an interesting way, so am gonna reproduce here.
Jessica's problem was thus:
so, i am attempting to write a function that lets you set variables specifically in a complex structure [...]
cached:{ foo: { bar: "hi" } } setProperty("foo.bar", "chicken"); writeDump(cached); // should == cached.foo.bar = chicken
On the Slack channel there was talk of loops and recursion and that sort of thing, which all sounded fine (other people came up with answers, but I purposely did not look at them lest they influenced my own efforts). The more I work with CFML and its iteration methods (
map()
, reduce()
, etc), the more I think actually having to loop over something seems a bit primitive, and non-descriptive. I looked at this for a few minutes... [furrowed my brow]... and thought "you could reduce that dotted path to a reference to the substruct I reckon". There were a few challenges there - if CFML had proper references it'd be easier - but I got an idea of the code in my head, and it seemed nice and easy.Whilst waiting to Skype with my boy I wrote my tests:
Labels:
CFML,
Jessica Kennedy,
Lucee,
TDD,
TestBox,
Unit Testing
Lucee: FUD from their own comms channel regarding an urgent security fix
G'day:
This just presented itself on Twitter:
This is a pretty crap way of announcing a security issue. I'd like to know who is responsible for that Twitter account, as they need a bullet.
What needs to be done is:
Here's the info from the Lucee Google Group:
So, anyway... comms shortfalls aside... go update your Lucee server.
Oh, and I'll try to find out if it impacts Railo too...
Righto.
--
Adam
This just presented itself on Twitter:
Initially I couldn't find anything else about it, and other people are asking too.New security fix for #Lucee available. Update ASAP.— Lucee Open Source (@lucee_server) August 6, 2015
This is a pretty crap way of announcing a security issue. I'd like to know who is responsible for that Twitter account, as they need a bullet.
What needs to be done is:
- Create release notes.
- Stick the download on the download site, and via the upgrade channel.
- Write a blog article covering the update.
- Probably put something on the LAS website too.
- Then announce it on the Google Group (they have done this, I note).
- Then announce it on Twitter, with links back to one of the above.
Here's the info from the Lucee Google Group:
Security fix and new BER release
There is a new security fix available for Lucee 4.5 on the stable and dev update provider you can install now, as is normal in this type of situation, we will not disclose the issue being addressed so as to protect our current user base, but it is recommended to update as soon as possible.
This security fix is available for our current stable release (4.5.1.023) on the stable release channel and for our BER release (4.5.2.005) on the develop release channel.
For a manual installation you can download the core files from here (https://bitbucket.org/lucee/lucee/downloads)
Micha
So, anyway... comms shortfalls aside... go update your Lucee server.
Oh, and I'll try to find out if it impacts Railo too...
Righto.
--
Adam
Labels:
Lucee
Wednesday, 5 August 2015
Adobe: if you can't be helpful, just get out of the f***ing way
G'day:
The Adobe bugbase has to be one of the sh!ttest things about ColdFusion that Adobe have foisted upon us. From the UI and the UX; to how buggy the bloody thing is; to the length of time it takes to get any action without badgering poor Anit across Twitter and Slack; to the abjectly sh!t-house way the Adobe ColdFusion Team handles client interaction on same.
It's just f***ed.
Just when I thought there was no way they could possibly make it even more f***ed, they actually managed it. I think they have disengaged their brains so far this time that there is probably a (small) grey sloppy mess on the floor of Adobe BugBase Central, because their brains have actually fallen out.
Now I preface this by saying it's been virtually impossible to get Adobe to fix any of the bugs in the bugbase. I don't mean ColdFusion bugs... I mean bugs in the actual bugbase application:
Those are just the ones I've raised. There are 105 altogether.
The Adobe bugbase has to be one of the sh!ttest things about ColdFusion that Adobe have foisted upon us. From the UI and the UX; to how buggy the bloody thing is; to the length of time it takes to get any action without badgering poor Anit across Twitter and Slack; to the abjectly sh!t-house way the Adobe ColdFusion Team handles client interaction on same.
It's just f***ed.
Just when I thought there was no way they could possibly make it even more f***ed, they actually managed it. I think they have disengaged their brains so far this time that there is probably a (small) grey sloppy mess on the floor of Adobe BugBase Central, because their brains have actually fallen out.
Now I preface this by saying it's been virtually impossible to get Adobe to fix any of the bugs in the bugbase. I don't mean ColdFusion bugs... I mean bugs in the actual bugbase application:
Those are just the ones I've raised. There are 105 altogether.
Labels:
Adobe
ColdFusion: it's hard to maintain the CF docs when the language is so buggy
G'day:
I was baking an idea for an article about PHP 7's generator return values - which admittedly had got sidetracked in a thought experiment - but just as I pulled up a pew at the pub, someone said something about ColdFusion and scopes and wrong docs and I decided I need to look at it and fix the docs if they were wrong. FFS.
Here's a simple statement in the ColdFusion docs, regarding scopes ("About scopes"):
So that's all easy enough, and given it's a list of only a dozen items, one would think it would be easy enough to test to make sure the docs matched ColdFusion's actual behaviour. And that ColdFusion's behaviour is actually correct.
I was baking an idea for an article about PHP 7's generator return values - which admittedly had got sidetracked in a thought experiment - but just as I pulled up a pew at the pub, someone said something about ColdFusion and scopes and wrong docs and I decided I need to look at it and fix the docs if they were wrong. FFS.
Here's a simple statement in the ColdFusion docs, regarding scopes ("About scopes"):
Evaluating unscoped variables
If you use a variable name without a scope prefix, ColdFusion checks the scopes in the following order to find the variable:
- Local (function-local, UDFs and CFCs only)
- Arguments
- Thread local (inside threads only)
- Query (not a true scope; variables in query loops)
- Thread
- Variables
- CGI
- Cffile
- URL
- Form
- Cookie
- Client
So that's all easy enough, and given it's a list of only a dozen items, one would think it would be easy enough to test to make sure the docs matched ColdFusion's actual behaviour. And that ColdFusion's behaviour is actually correct.
Labels:
ColdFusion,
himansu,
Mingo Hagen
Tuesday, 4 August 2015
CFML: revision to thread syntax (revisited)
G'day:
Whilst messing around JavaScript Promises ("JavaScript: getting my brain around Promises" and "JavaScript: expectations re-adjusted re Promises") a week or so ago, I also started looking at how CFML's innate multi-threadedness, and how one would leverage this along with a CFML Promise implementation to be able to have clean & tidy & OO asynchronous code.
The general concept of firing off secondary threads in CFML is adequate, but I think the implementation leaves a bit to be desired. I'm going to forget the tag-based implementation as that is an artefact of more primitive times in CFML, and focus on the script implementation.
This is an example of lazy dull-headedness from the Adobe ColdFusion team who simply did a "tags-without-angle-brackets" implementation of
This is just leaden.
A while back I mused about some improvements to the syntax ("CFML: Another suggested tweak to script:
And then further to this:
This would result in code like this:
Whilst messing around JavaScript Promises ("JavaScript: getting my brain around Promises" and "JavaScript: expectations re-adjusted re Promises") a week or so ago, I also started looking at how CFML's innate multi-threadedness, and how one would leverage this along with a CFML Promise implementation to be able to have clean & tidy & OO asynchronous code.
The general concept of firing off secondary threads in CFML is adequate, but I think the implementation leaves a bit to be desired. I'm going to forget the tag-based implementation as that is an artefact of more primitive times in CFML, and focus on the script implementation.
This is an example of lazy dull-headedness from the Adobe ColdFusion team who simply did a "tags-without-angle-brackets" implementation of
<cfthread>
for the script:thread name="t1" action="run" {
// stuff to run in its own thread here
}
This is just leaden.
A while back I mused about some improvements to the syntax ("CFML: Another suggested tweak to script:
thread
" and then "CFML: A possible variation on the thread
idea..."). Initially I just started out suggesting changing the syntax to be a hybrid of standard OO script syntax and tags-without-angle-brackets notation:t1 = Thread.new({someattribute="value"}) {
// stuff to run in its own thread here
}
And then further to this:
t1 = Thread.new(required function functionToRun, optional struct dataToPass, optional struct eventHandlers);
This would result in code like this:
t1 = Thread.new(function(){
// stuff to run in its own thread here
}, {}, {
success = function(){
// stuff to do after the first function finishes
},
failure = function(){
// stuff to do after the first function fails
}
});
Labels:
CFML,
Multi-threading,
Promises
Monday, 3 August 2015
PHP: Has PHP7 implemented function return-type checking syntax poorly?
G'day:
I had a look at PHP 7's new (but very late tot he party) capability to type-check function return types the other day ("PHP 7: functions can now have type-checking on their return values"). The functionality kinda works OK, but I think the syntax is off:
EG:
The problem being that whilst all the other function modifiers are before the function name: the return type modifier is right at the end of the function signature.
This in itself is only slightly crap, but when one considers the type modifiers on arguments are before the argument name, it then just starts being a sloppy implementation.
However I wondered if there was a precedent in other popular languages I was unaware of in which this is actually something that's done, and I just hadn't noticed. So I decided to check. I've gone through what's considered the ten most popular languages and looked at what their syntax is for argument and return type checking.
I had a look at PHP 7's new (but very late tot he party) capability to type-check function return types the other day ("PHP 7: functions can now have type-checking on their return values"). The functionality kinda works OK, but I think the syntax is off:
[access modifier] [static modifier] functionName([[type] argumentName[=defaultValue]][,...])[ : return type] {
// implementation
}
EG:
public static function getFullName(string $firstName, string $lastName) : string {
return "$firstName $lastName";
}
The problem being that whilst all the other function modifiers are before the function name: the return type modifier is right at the end of the function signature.
This in itself is only slightly crap, but when one considers the type modifiers on arguments are before the argument name, it then just starts being a sloppy implementation.
However I wondered if there was a precedent in other popular languages I was unaware of in which this is actually something that's done, and I just hadn't noticed. So I decided to check. I've gone through what's considered the ten most popular languages and looked at what their syntax is for argument and return type checking.
Subscribe to:
Posts (Atom)