Friday, May 27, 2016

Security+ Certification!

After weeks of study, I am now officially CompTIA Security+ Certified!



This is my happy face >> :-)

Monday, May 2, 2016

Testing: A Confession

I have a confession to make. In the software world, this confession probably ranks right up there with kicking kittens or believing that Firefly deserved to be cancelled, but it's one that I still feel I should make. I've been a developer for over 15 years, and almost all of that time has been spent NOT WRITING TESTS. I have always done the traditional developer QA and smoke testing, but I have spent years making all sorts of excuses as to why I don't actually write tests: I don't have the time to do it. My company's infrastructure isn't set up for it. We have a QA team that does our testing. Or my favorite: We have a mass of legacy code and it's too hard to test.

Those may be some valid "reasons", but they're really just excuses.

I'm a hypocrite, too. I've known the value of testing for most of my career. I've preached that it should be done. But I've never really strongly advocated for it where I've worked. I'm changing that.

I work on a fairly significant code base that doesn't currently have any tests. We constantly make changes and we deploy often. In the last couple of weeks, I've been bitten twice by code that I just created that affected other pieces of my site in ways that I didn't expect. Proper Unit Tests would have picked up those regressions before I ever even checked in my code. So this has given me a bit of a kick to actually start doing something about it. I'm fortunate in that I have a few allies at work who see this need, too. I don't have to be the new guy bucking the system.

We work mostly with ColdFusion and jQuery, so a large hurdle has been just figuring out what the best way to test is. I've chosen Ortus' TestBox for my CF code. It's got great support. It's fairly easy to setup and use. I like it a lot. I've only got a couple dozen tests in place, but I already see several ways that I should have written my code better. I'm seeing some things that appear to be hard to test, but I think that's because I'm just not well-versed in actually testing software like this. I'm determined to get much better at it.

I've confessed my sin. I don't really feel that much better, but let the adventure begin.

Tuesday, April 26, 2016

[REVIEW] Guess What Came In The Mail: Pine64


I am fascinated with tiny computers and the things that a unit like the popular RaspberryPi enables. And when I saw the Pine64 on Kickstarter, I was intrigued. A 64-bit computer for $15!!!! No way!!! I became a backer at the original $15 price (+shipping, but really, at this price shipping doesn't matter).

I watched the Kickstarter move to become a successfully funded project, and then watched some people get frustrated that they didn't get their P64 in February when originally told. Apparently they didn't think about what would happen to an unexpectedly popular and successful Kickstarter campaign. Plus, I guess I value my $15 pledge much less than some of them do. The way I look at Kickstarter, I fund the dreams of other people. When I tell them I'm gonna give them some $, it's a dream that I like, but still a DREAM. If their dream fizzles, then that sucks. I'm still glad I could help them realize their dream. But if they succeed and I get to be part of something cool, then Bonus For Me! I helped make a Veronica Marrs movie, and now I've helped make a $15 computer become a reality. Even if I saw nothing, it was all money well spent.

All that said...  I got a package in the mail today. Guess what it was.....

Guess what came in the mail!
Yup, I am now a proud owner of a 64-bit hand-sized computer with 2gb of memory!

When I first became a web monkey, I was building enterprise-level apps on a Pentium server that wasn't even in the neighborhood of thinking about multiple cores. I still have some "large" 256 MEGABYTE memory chips from those machines. I could build my entire system architecture in virtual machines on my laptop. The power that is now able to be packed into a palm-sized machine is crazy.

Anyway.... back to my mail.

I was an early backer of this thing, and more importantly, a believer. I was a bit giddy when I opened up my mailbox today. I knew what it had to be, but I still felt like a kid in a candy shop. So what did I get....

A PINE64!!! <shamelessPlug>www.pine64.org</shamelessPlug>

For those who haven't hear about this one, it's a VERY tiny computer, a lot like a RaspberryPi, but it's only about 15 bucks. You just can't beat that price. I saw it; I backed it; I bought some accessories: I have it now.
The Package Contents!

Here's my review:

In my former life as a Fulfillment Guy, I would have wanted to use sturdier packaging to prevent damage in transit. I received this thing, with the accessories I ordered, in a normal padded envelope. I would have preferred heftier packaging, but nothing was even remotely damaged, and most importantly, let's not forget that this is essentially A $15 COMPUTER!!!

When I unpacked everything, I assumed that the larger box was the actual unit. WRONG. That was the acrylic case that I ordered. The unit is TINY. To be fair, it's larger than my older model RaspberryPi, but if I hold it up next to another motherboard, I'm not sure this scale is much of an issue.


After getting everything unpacked, I began putting it all together. I bought the acrylic case from the site, and it's a little bit bigger than I thought it would be. I expected something more commensurate with the form-factor of the unit itself. But the size isn't really an issue, because the case looks AWESOME!

Pine64 Acrylic Case
To this point, putting the thing together has been dead simple. The hardest part I've found so far is WHERE ARE ALL MY POWER STRIPS???

Now that I've found power, I need to crank this thing up. But a computer won't do much without some sort of operating system. I was lazy. I went for the first option on the Pine64 Wiki (wiki.pine64.org): Debian Linux with Mate GUI by lenny.raposo. Thank you, Lenny!

  • I used my RasPi tools to prep the SD card for the OS: SDFormatter to prep the disk and then Win32DiskImager to write it. It was a 1.4gb download, but it extracted to an 8gb image. Make sure you have enough SD card for it.
  • Pine64 vs Mobo
  • One very big difference between this and the RasPi is in the size of the card the OS runs on. RaspberryPi runs on a full-sized SD card. The Pine64 runs on a micro-SD card. Many modern SD cards already come with an adapter for a micro-SD to a full-size SD port, but we don't need the adapter here.

RasPi vs Pine64
This unit is tiny. But it's still larger than my older RaspberryPi. However, to put it into perspective, it's not even worth comparing the size to a full motherboard.

Now that we're all hooked up, it's time for the moment of truth: Does this thing power on? Fewer things in life are more disappointing than spending time to carefully put together a computer only to have nothing happen when you finally push the power button.


FLASHY LIGHTS == POWER!!!

Ladies and Gentlemen, here we go......







AND..... BOOTED!!!

WE HAVE SUCCESS!!!!







CONCLUSION: In my very limited experience with small boards like the Pine64 or Raspberry Pi, I can't really give much of a valid comparison yet. However, I will say that I REALLY like the Pine64 so far. The unit itself was $24 for the 2gb model, and all-in-all, I think I spent a grand total of around $80 on this entire setup. And that includes two additional power supplies for my other RasPi units and two HDMI-to-DVI and -VGA adapters. The case is large, but it looks very nice. All-in-all, I am VERY pleased with this purchase.

Now the fun begins... what do I make with this thing?

Monday, April 25, 2016

Adobe ColdFusion Developer Week 2016

For those of you who haven't heard yet:

http://blogs.coldfusion.com/post.cfm/adobe-coldfusion-developer-week-2016-april-24-29

Adobe Developer Week is currently going on. Two sessions per day. Good info. David Epler's Security Enhancements in ColdFusion 2016 is about to start. 

For the other sessions (from Adobe): 


Monday, April 25, 2016
9:00 - 10:00 am
ColdFusion 2016 Overview
12:00 - 1:00 pm
Security Enhancements in ColdFusion 2016
Tuesday, April 26, 2016
9:00 - 10:00 am
Mobile Applications Made Easy with ColdFusion
12:00 - 1:00 pm
Exploring PDF Capabilities in ColdFusion
Wednesday, April 27, 2016
9:00 - 10:00 am
Protecting APIs using CF 2016 API Manager
12:00 - 1:00 pm
MVC With and Without a Framework
Thursday, April 28, 2016
9:00 - 10:00 am
Realtime with WebSockets
12:00 - 1:00 pm
ColdFusion Performance Tuning and Caching
Friday, April 29, 2016
9:00 - 10:00 am
Extending PDF capabilities using DDX
12:00 - 1:00 pm
CFML Features for More Modern Coding
Follow their link and sign up.

Monday, February 29, 2016

Date Masking Inconsistency

What better way to celebrate Leap Day than with a Date Masking post? It's been cooking in my noggin a while and has been in some form of draft for a month, but better late than never, right? :-/

TL;DR: ALWAYS VERIFY YOUR DATE MASKS ARE DOING WHAT YOU THINK THEY'RE DOING!

I originally encountered this at the beginning of February and while digging for the cause, came across the issue in the CFDocs site (https://github.com/foundeo/cfdocs/issues/266). I played a bit with some of the masking and learned that some of my old ways were smacking me. I've been in the habit of masking a DateTime object with "MM/DD/YYYY..." or something like that. I absolutely hate date math and manipulation, but that hatred has led me to learning more than I ever wanted to know about the bazillion different epoch times and how 12:59:59.998 can sometimes be the same as 00:00:00.000. There's a bit of a rabbit hole there, and I've fallen down it more than I care for.

But I digress. The CFDocs site referenced an Adobe bug for CF10 (https://bugbase.adobe.com/index.cfm?event=bug&id=4105828) reported by Alexander Kwaschny, and as I was playing with this, I began to realize how big of an issue this actually could be for us. FORTUNATELY I didn't find anywhere in our code where we were using dateTimeFormat(), just dateFormat(), but we _were_ using the "YYYY" mask. I'm a firm believer in consistency (that may be a holdover from my piloting days), and I think that if you're going to do something, you should always try to do it the same way to minimize the opportunity for error. Date Masking is a big area that has a lot of potential to cause hard-to-detect problems, and we were setting ourselves up for a big one here. Though I can't really fault anyone, since pretty much every example of date masking or formatting that I've ever seen uses capital letters. I think it's insane for a language (THANKS JAVA, and maybe even ISO8601) to treat "Y" and "y" as two different things for such a narrow edge case. Until this issue, I had never even heard of a Week Year ("Y") (https://docs.oracle.com/javase/8/docs/api/java/text/SimpleDateFormat.html). And to make the issue more fun, it would only even come into play at most about 6 days out of an entire year. You probably wouldn't even notice the problem.

So, my solution.... make sure my date masks reflect the proper things in the languages that I'm using. My years now are formatted with "yyyy" instead of "YYYY", though most of the time, it doesn't make a difference either way. Grrrr.....

======= MY RESEARCH ========
First, I wanted to verify that Oracle is documented to behave as I expect it to. https://docs.oracle.com/cd/B28359_01/server.111/b28286/sql_elements004.htm#CDEHIFJA Oracle 11g Datetime Format Elements

Yup, Oracle treats "Y" and "y" as the same thing in its formatting. Note: even the Oracle examples show "Y" for the date mask.

One other cool thing I discovered about Oracle... the capitalization of the Month mask will determine the capitalization of the output.
'' Months : To_Char(myDate,'MONTH') AS CAPDATE, To_Char(myDate,'Month') AS Casedate, To_Char(myDate,'month') AS lowdate ''
I guess it's not something I've ever used nor paid attention to, but it's still kinda cool to know.

Now, back to ColdFusion:

For the Year difference, DateFormat() doesn't seem to have the problem, but DateTimeFormat() does. Interesting. And Lucee/Railo gets even weirder. http://trycf.com/gist/908f3b1ed6d7490bc470/acf11?theme=monokai

<cfscript>
myDate = CreateODBCDateTime('12/30/2015 12:34:56.789') ;
writeDump(dateFormat(myDate,'mm/dd/yyyy')) ;
writeDump(dateFormat(myDate,'mm/dd/YYYY')) ;
writeOutput('<br>') ;
writeDump(dateTimeFormat(myDate,'mm/dd/yyyy')) ;
writeDump(dateTimeFormat(myDate,'mm/dd/YYYY')) ;
</cfscript>

Will return "12/30/Y'Y'Y'Y" for the dateTimeFormat(), but the proper date for simple dateFormat(). Isn't that old pre-CFMX behavior?

The other mask that bugs me is "S" and "s". "s" is Seconds and "S" is milliseconds, except for when "l" or "L" are milliseconds. And, "S" returns Seconds in dateTimeFormat() and timeFormat(), where it returns the milliseconds in dateFormat(), which technically doesn't even specify a time component to return. ARGH!!!!

Once again, CONSISTENCY CONSISTENCY CONSISTENCY. And the case of a mask shouldn't affect its functionality. There's just too much room for a silent error.

Anyway, that's enough for tonight. I guess these things are semi-documented in various places, but I still don't like it. It just seems way too common to not be an issue. The Adobe ticket says the documentation in CF was fixed to be clearer. I'll check that. And I need to pull down CFDocs and change the date function masks to note these differences in behavior. But this post became the rabit hole that I warned about earlier.


===== OTHER NOTES ========================================================

CF > DateFormat() vs DateTimeFormat()
DateFormat -
 9 = http://help.adobe.com/en_US/ColdFusion/9.0/CFMLRef/WSc3ff6d0ea77859461172e0811cbec22c24-7ff4.html
 10+ = https://helpx.adobe.com/coldfusion/cfml-reference/coldfusion-functions/functions-c-d/DateFormat.html

TimeFormat - http://help.adobe.com/en_US/ColdFusion/9.0/CFMLRef/WSc3ff6d0ea77859461172e0811cbec22c24-6de0.html
DateTimeFormat - CF10+ - https://helpx.adobe.com/coldfusion/cfml-reference/coldfusion-functions/functions-c-d/DateTimeFormat.html
 "The function also follows Java date time mask. For more information, refer to Date and Time Patterns topic in SimpleDateFormat Java API page."

--------------------------

<cfscript>
myDate = CreateODBCDateTime('12/30/2015 15:16:17.19') ;
writeDump(dateFormat(myDate,'s')) ; // 17
writeDump(dateFormat(myDate,'S')) ; // 190
writeDump(timeFormat(myDate,'s')) ; // 17
writeDump(timeFormat(myDate,'S')) ; // 17
writeOutput('<br>') ;
writeDump(dateTimeFormat(myDate,'mm/dd/yyyy hh:nn:ss.l')) ; // 12/30/2015 03:16:17.190
writeDump(dateTimeFormat(myDate,'mm/dd/YYYY HH:NN:SS.L')) ; // 12/30/2016 15:16:17.190
writeOutput('<br>') ;
writeDump(datePart('yyyy',myDate)); // 2015
writeDump(datePart('YYYY',myDate)); // 2015
writeOutput('<br>') ;
writeDump(dateAdd('yyyy',1,myDate)); // {ts '2016-12-30 15:16:17'}
writeDump(dateAdd('YYYY',1,myDate)); // {ts '2016-12-30 15:16:17'}
</cfscript>
>>>>>>>>>>>>

http://trycf.com/gist/5a4209466ccf5e5ea854/acf11?theme=monokai
http://trycf.com/gist/ef686d4c4bf45fb85619/acf11?theme=monokai
http://trycf.com/gist/b24b9c91e6cee5e3c12e/acf?theme=monokai
http://trycf.com/gist/9db92000bb204a561edd/acf?theme=monokai

Links:
Original CFDocs Issue: https://github.com/foundeo/cfdocs/issues/266
http://www.sql-server-helper.com/tips/date-formats.aspx
http://www.java2s.com/Tutorial/Java/0040__Data-Type/SimpleDateFormat.htm
https://helpx.adobe.com/coldfusion/cfml-reference/coldfusion-functions/functions-by-category/date-and-time-functions.html
https://helpx.adobe.com/coldfusion/cfml-reference/coldfusion-functions/functions-c-d/DatePart.html
http://www.petefreitag.com/cheatsheets/coldfusion/dateformat/
https://helpx.adobe.com/coldfusion/cfml-reference/coldfusion-functions/functions-c-d/DateFormat.html




Friday, February 26, 2016

ColdFusion Scope Precedence

A while back (August 2015), Himansu Sekhar Khuntia logged a bug for ColdFusion 10 that dealt with the scope precedence of LOCAL and ARGUMENTS scopes within a function, and specifically how unscoped variables were effected with CF's scope hunting. Current behavior of ColdFusion 10 has ARGUMENTS taking precedence over LOCAL, and I really don't know how far back this problem goes, but apparently the behavior should be LOCAL over ARGUMENTS.

Original bug report for CF10: https://bugbase.adobe.com/index.cfm?event=bug&id=4031746
Possibly related for CF2016: https://bugbase.adobe.com/index.cfm?event=bug&id=4119653

Inside a function, LOCAL scope SHOULD take precedence over ARGUMENTS scope. This is fixed in 2016 (need to try it out) and planned to be fixed in 10/11. We'll see which patch it makes it into.

To make things interesting, I decided to play with the function scopes in CF10 (pre-scope order fix), and got some interesting results. See below.

Moral of the Story: ALWAYS SCOPE YOUR VARIABLES!!!!! To be extra safe, it probably wouldn't be a bad idea to try to keep from naming a variable the same in multiple scopes. ARGUMENTS and LOCAL are SUPPOSED to be mutually exclusive, but they aren't always.

Anyway, thank you to Adobe for actually clarifying that. Now I need to start reporting the discrepancy when I see it documented incorrectly, ie http://www.learncfinaweek.com/week1/Scopes/.

========================================================================