Dragonsaber Website Design Banners Computer Art Print Design Kerwin"s Resume About Dragonsaber

November 22, 2010

Life Underground

I always wanted to take pictures of Life Underground by Tom Otterness. It's an installation sculpture series created in 2002 for the 14th Street and 8th Avenue station. I finally had a camera with me and just missed the train, so I had a few minutes to capture some of Otterness' playful characters.


Related: Tom Otterness Studio, Wikipedia, Life Underground

October 29, 2010

Wiley Mobile Apps

The Wiley Mobile Apps page was updated with a number of new iPhone applications this week.

  • Wiley Newsletter Mobile Reader
  • CompTIA A+ Flashcards from Sybex
  • Accounting Flashcards and Self-Tests
  • Contemporary Business
  • Exploring Management
[Click Here for Details]

October 18, 2010

Puerto Rico 2009 DVD Cover


October 2010 (10.7" x 7.2") - Since my parents went by themselves to Puerto Rico, the number of shots were limited. Naturally, I wanted a photo of both of them for the cover and there weren't many to choose from. On top of that, whenever a stranger uses their camera, it never comes out good. So I made the most of the one I picked. It's a little grainy, but had the right colors. The red from my Mom's shirt was reflected across the rest of the cover as the accent. The back cover is a nice landscape shot of El Morrow. The blank sky allowed for the 2 thumbnails and chapter menu.

October 3, 2010

Squirrel for Breakfast

August 24, 2010

Frommer's -> Wiley

This is just a note that I changed all items previously labeled as "Frommer's" to Wiley. I started a new position at Wiley's Web Publishing Technology group, so I'll be working on several of the company's websites, including Frommers.com. Here are a couple of updates so far:

Wiley.com Logos
The logo pages on Wiley.com were skinned with an interface designed a few years ago, but their content areas were left in a much older, 800x600 design. I rebuilt the pages as practice in the CMS we have in place. So now all the page are the full width of the content area.
- Logos for Print
- Divisional Logos

Frommers.biz Press Release
These come in every couple of months or so, but it was kind of nice to get one on the week I started the new job because it was still Frommer's in some way. To read about our partnership with AARP, click here.

August Rheumatologist
The Rheumatologist is a monthly online magazine that we post on the website for download and yet another Wiley owned site that I never knew about. Click here for August's issue.

Coming Soon
I can't post any direct links to some of the larger projects yet, but I'll be working on Pfeiffer, Current Protocols, Comprehensive Physiology and Encyclopedia of Life Sciences.

August 21, 2010

A Semi-Secret Garden in Queens

Earlier in the month, Kim & Bock Yeo's house and garden was featured in The New York Time. Since it was a biographical piece, we decided to add it to the website's about section as well. The New York Time actually gave us permission to reprint it as long as it linked back to the original Online edition. I was surprised at this because the New York Daily News did not allow me to reprint an article written about RCT Performance a few years ago.

Click here to read "A Semi-Secret Garden in Queens"

August 7, 2010

July 28, 2010

Leaf Bug



May 30, 2010

MoMA NYC

May 5, 2010

Wicked NYC

Earlier this week, we went up with our monthly contest. It's New York City in May, sponsored by Wicked. So that's why I took all of those pictures last month. I used a generic shot of the NYC skyline for the homepage. That was an older photo I took earlier in April from the Hoboken waterfront. The 3 images on the contest page were shot for the Wicked promo. The play is located in the back of Paramount Plaza, so there weren't that many interesting exterior shots. I tried to get as much green into each photo as possible for the ones of the signage. The surrounding trees helped blend the logos in with the midtown surroundings.

April 24, 2010

April 10, 2010

April 7, 2010

ColdFusion / SAML (Part 3)

The Signature

This is where all of the pieces come together... the libraries & keystore from Part 1 and the XML from Part 2. Here's the script that applies all of the algorithms and transforms:


<cfscript>

// 1) Injest the XML

samlAssertionElement = samlAssertionXML.getDocumentElement();

samlAssertionDocument = samlAssertionElement.GetOwnerDocument();

samlAssertion = samlAssertionDocument.getFirstChild();



// 2) Create Java Objects

SignatureSpecNS = CreateObject("Java", "org.apache.xml.security.utils.Constants").SignatureSpecNS;

TransformsClass = CreateObject("Java","org.apache.xml.security.transforms.Transforms");

SecInit = CreateObject("Java", "org.apache.xml.security.Init").Init().init();

XMLSignatureClass = CreateObject("Java", "org.apache.xml.security.signature.XMLSignature"); // Access XML Signature CLASS

CanonicalizerClass = CreateObject("Java", "org.apache.xml.security.c14n.Canonicalizer"); // Access Canonicalizer CLASS



// 3) Signature

sigType = XMLSignatureClass.ALGO_ID_SIGNATURE_RSA_SHA1; // Define signature algorithm

canonType = CanonicalizerClass.ALGO_ID_C14N_EXCL_OMIT_COMMENTS; // Define canonicalizer algorithm

signature = XMLSignatureClass.init(samlAssertionDocument, javacast("string",""), sigType, canonType); // Create signature and apply algorithms



// 4) Transforms

TransformsClass = CreateObject("Java","org.apache.xml.security.transforms.Transforms"); // Access Transforms CLASS

IncNSClass = CreateObject("Java","org.apache.xml.security.transforms.params.InclusiveNamespaces"); // Access Inclusive Namespaces CLASS

transformEnvStr = TransformsClass.TRANSFORM_ENVELOPED_SIGNATURE;

transformOmitCommentsStr = TransformsClass.TRANSFORM_C14N_EXCL_OMIT_COMMENTS;

transformIncNS = IncNSClass.init(samlAssertionDocument, "ds saml xs xsi");

transforms = TransformsClass.init(samlAssertionDocument); // Apply the base transform

transforms.addTransform(transformEnvStr); // Apply enveloped signature

transforms.addTransform(transformOmitCommentsStr); // Apply comment exclusion

transforms.item(1).getElement().appendChild(transformIncNS.getElement()); // Apply namespaces



// 5) Keystore

ksfile = CreateObject("Java", "java.io.File").init("#FULL_PATH_OF_KEYSTORE#");

inputStream = CreateObject("Java", "java.io.FileInputStream").init(ksfile);

KeyStoreClass = CreateObject("Java" , "java.security.KeyStore");

ks = KeyStoreClass.getInstance("JKS");

ks.load(inputStream,"#STOREPASS#");

keypw = "#STOREPASS#";

key = ks.getKey("#KEYSTORE_ALIAS#",keypw.toCharArray()); // Must be the alias. Using the keystore filename returns an error. This is the private key.

cert = ks.getCertificate("#KEYSTORE_ALIAS#"); // Must be the alias. Using the keystore filename returns an error.

publickey = cert.getPublicKey();


// 6) Putting it Together

signature.addDocument("#ssouser.uuid#", transforms);

signature.addKeyInfo(variables.cert); // adds certificate to the signature

signature.addKeyInfo(variables.publickey); // ads public key to signature

signature.sign(key);



samlAssertionElement.insertBefore(signature.getElement(),samlAssertion.getFirstChild()); // Takes samlAssertionElement and inserts the signature before the first node of saml:Assertion

</cfscript>



1) The first part of this script is for injesting the SAML XML code. Then you're going to traverse the DOM to the location where the signature will be inserted. In this case, it will be the first child node of . This was the part I mentioned in Part 2 that had a CF/Java bug. When I had the full XML as a single variable, no matter what method I used to traverse the DOM (combinations of getFirstChild, getLastChild, getNextSibling, etc.), I couldn't get it to recognize the 2nd level... which is where the signature needs to be inserted (as a child of ). So by splitting it into the 3 variables, the middle variable is only one level. At first, I thought it was just a limitation of my Java skills, but I also had a Java expert look at the code and he also couldn't get out of the first level.

2) This portion is accessing various classes from the XML Security Libraries that were installed in Part 1.

3) Same as #2, but accessing signature related algorithms.

4) Same as #2, but accessing various transforms to apply.

5) This part is accessing the various parts of the keystore also created in Part 1.

6) The last part is adding more unique data to the signature. The unique user ID is thrown in along with the certificate and public key.

If you understood all of those steps... or even if you didn't, this should give you a sense of why SAML is super secure! Now I'm going to clean things up a bit:


<cfset samlAssertionXML = "#Replace(samlAssertionXML, "<?xml version=""1.0"" encoding=""UTF-8""?>", "", "all")#">
<cfset samlAssertionXML = "#Replace(samlAssertionXML, " xmlns:ds=""http://www.w3.org/2000/09/xmldsig##""", "", "all")#">
<cfset samlAssertionXML = "#Replace(samlAssertionXML, "<ds:Signature>", "<ds:Signature xmlns:ds=""http://www.w3.org/2000/09/xmldsig##"">", "all")#">
<cfset samlAssertionXML = "#responseOpen##samlAssertionXML##responseClose#">


1) The first line is removing the XML declaration because I have it hardcoded into the first piece of the XML already.

2) The next line is removing the namespace declaration because somewhere along the lines, in one of the Java methods, the declaration is getting added to every tag. You may not need to do this step, but I just implemented it because I wanted to get the XML as close as possible to my SP's XML spec.

3) The 3rd line just adds the namespace declaration back to <DS:SIGNATURE> tag.

4) The last line combines the 3 variables back together so that "samlAsertionXML" contains the entire XML document.

To get this ready for transport, the next step is to convert the XML to Base64...


<cfset samlAssertionXML = "#toBase64(toString(samlAssertionXML), "utf-8")#">


And finally, this can be sent over to the SP with an auto-submit form...


<form action="#SPService#" method="post">

<input type="hidden" name="SAMLResponse" value="#samlAssertionXML#" />

<input type="submit" value="Send to SP>

</form>

March 24, 2010

ColdFusion Builder Tour Notes (Part 2)

Although I've tried CFEclipse and ColdFusion Builder BETA, I always ended up reverting back to the old, outdated copy of ColdFusion Studio for 2 reasons. Neither of these advanced programs had a good batch search/replace and neither had keyboard shortcuts for commonly used HTML tags. Both of these issue were addressed last night:

RegEx Replace
Ben Nadel, one of pioneers in the language was also a CF Studio/Homesite user for the same reason. So fortunately, he wrote the RegEx Replace extension that does a better search/replace than CF Studio. There's a preview & commit since any batch processing can be dangerous. It also visually highlights the changes made so there are no surprised at the end. The only con is that it doesn't process multiple files or directories. But just having this extension available was a major factor for me in purchasing ColdFusion Builder. There's always potential for a future release to cover multiple files.

Keyboard Shortcuts
I can't live without keyboard shortcuts. I'm used to developing with the mouse and keyboard at the same time, so shortcuts are essential to productivity. Since ColdFusion Builder evolved from Eclipse and not the CF Studio/Homesite family, it lost the common shortcuts for HTML code. It's already second nature for me to hit CTRL+B for STRONG, CTRL+I for EM, CTRL+SHIFT+A for links, etcs. So I felt CF Builder was inefficient when all of these went missing. There are shortcuts for common CF tags, which balances things out. At the meeting, Adam Lehman also mentioned that an XML-based config file could be hacked for custom shortcuts. So I think I can add these back in... more updates when my copy arrives.

ColdFusion Builder Tour Notes (Part 1)

Presented by Adam Lehman
ColdFusion Product Manager
Adobe


March 23, 2010
NYU Medical Center
550 1st Avenue
New York, NY

Introduction
Adobe found that an IDE was more in demand than any other CF feature. It's something that always came up whenever they surveyed users. We didn't really have an official one since ColdFusion Studio since CFEclipse was from the community. Adobe saw IDEs as a way to attract new developers. It makes CF a legitimate, accepted language. A productive language needed a productive environment. Adobe is fully dedicated to this product as it has a rapid development roadmap:

  • CB2 BETA by end of 2010
  • CB2 = Storm
  • CB3 = Thunder (will release before or at the same time as CF Server X)
  • CFX = Link


Pricing
As expected, ColdFusion Builder sells for $299... the usual price for a basic Adobe product... same as Dreamweaver. It's worth every penny as there are a ton of productivity features packed into it. Additionally, FlashBuilder Standard is included with the buy. Both ColdFusion Builder and ColdFusion Server 9 are FREE for educational and non-profit organizations. Volume pricing and package deals are available.

ColdFusion Server 9
The most attractive selling point of the new version is performance. Without even converting to the new code, it's already 40% faster than version 8 and 6 times faster than version 7 right out of the box. CFCs also get a significant boost... 8x faster for creation and 3x faster for invocation. UUIC creation is a whopping 100x faster!

Office Integration
Previously, in order to get data from Oracle to an Excel spreadsheet, we would have to make a CF page with queries, save the output as HTML and open it up in Excel. CF9 allows us to go directly to Excel. Features include:
  • generate PPT from HTML/CFM content
  • create, read, update XLS
  • XLS formulas
  • visual formatting controls
  • supports PowerPoint '97 through 2007
  • supports OpenOffice.org


Productivity
The intelligence of the new code insight is a huge time saver because one previously had to open up Toad, SQL Developer or SQL*Plus to reference a table. Now, all of the fields show up as the query is typed in CFQUERY. It’s smart enough to pull them up even if the datasource is a variable! Other than CFM, the insight also works for SQL & JS. Tag Wizard allows users to display a form (for each tag) that contains all possible attributes.

March 23, 2010

ColdFusion Builder Tour


Adobe launched the long awaited ColdFusion Builder yesterday. As part of their tour, Product Manager, Adam Lehman presented tonight at the NY ColdFusion User Group. Notes coming soon!

February 26, 2010

Snow Day II

February 10, 2010

Snow Day

January 14, 2010

Donations to Haiti

I gathered some links for donating to the earthquake relief efforts in Haiti. Each item below was personally link-checked to make sure there was an option for the specific crisis:

Also check out NY1's relief list. They made it a point to review organizations to insure that donations would really make it to their intended destinations.

Please feel free to republish this post on your own blog. Click here to download the source code for Blogger.

Thank you.

January 11, 2010

ColdFusion / SAML (Part 2)

The XML

I'm going to start with the base XML (before adding in the ColdFusion processing) to give an idea of what I'm going to generate. Here it is below with the items you need to replace marked off as ColdFusion variable calls:


<?xml version="1.0" encoding="UTF-8"?>

<samlp:Response Destination="#SPService#" ID="#ssouser.uuid#" IssueInstant="#nowDateTime#" Version="2.0" xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol">

<saml:Issuer xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">#IDPDomain#</saml:Issuer>

<samlp:Status><samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"/></samlp:Status>

<saml:Assertion ID="#ssouser.uuid#" IssueInstant="#nowDateTime#" Version="2.0" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">

<saml:Issuer>#IDPDomain#</saml:Issuer>

<saml:Subject>

<saml:NameID>#ssouser.email#</saml:NameID>

<saml:SubjectConfirmation Method="urn:oasis:names:tc:2.0:cm:bearer">

<saml:SubjectConfirmationData InResponseTo="#ssouser.uuid#" NotOnOrAfter="#nowDateTimePlus1#" Recipient="#SPService#"/>

</saml:SubjectConfirmation>

</saml:Subject>

<saml:Conditions NotBefore="#nowDateTime#" NotOnOrAfter="#nowDateTimePlus1#">

<saml:AudienceRestriction>

<saml:Audience>#SPDomain#</saml:Audience>

</saml:AudienceRestriction>

</saml:Conditions>

<saml:AuthnStatement AuthnInstant="#nowDateTime#">

<saml:AuthnContext>

<saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport</saml:AuthnContextClassRef>

</saml:AuthnContext>

</saml:AuthnStatement>

<saml:AttributeStatement>

<saml:Attribute Name="screenName">

<saml:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">#ssouser.name#</saml:AttributeValue>

</saml:Attribute>

</saml:AttributeStatement>

</saml:Assertion>

</samlp:Response>



- #IDPDomain# = The base URL of the IDP
- #SPService# = The full URL of the SP's authentication system
- #ssouser.uuid# = The user ID from the IDP that will be used as a unique identifier in several parts of this file
- #nowDateTime# = The current date/time to mark the initiation of the assertion
- #nowDateTimePlus1# = A date/time stamp after the current date/time to limit the time frame an assertion can occur. This prevents a user from trying to simulate/mimic one. Generally a 1 min differential is good. Assertions will always occur behind the scenes through one or more redirects.
- #ssouser.name# = Username/Display Name
- #SPDomain# = The base URL of the SP

The #SPDomain# and #SPService# will come from the SP and can just be hardcoded into the XML template. The #ssouser.uuid# and #ssouser.name# will be pulled from the IDP database or cookie. The date/time stamps will be pulled from #Now()#.

Now here's that same XML wrapped in ColdFusion:


<cfoutput>

<cfset nowDateTime = "#DateFormat(DateConvert('local2utc', Now()),'YYYY-MM-DDT')# & #TimeFormat(DateConvert('local2utc',Now()),'HH:mm:SS.LZ')#">

<cfset nowDateTimePlus1 = "#DateFormat(DateConvert('local2utc', Now()),'YYYY-MM-DDT')# & #TimeFormat(DateConvert('local2utc', DateAdd('n',1,Now())),'HH:mm:SS.LZ')#">


<cfsavecontent variable="responseOpen">

<?xml version="1.0" encoding="UTF-8"?>

<samlp:Response Destination="#SPService#" ID="#ssouser.uuid#" IssueInstant="#nowDateTime#" Version="2.0" xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol">

<saml:Issuer xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">#IDPDomain#</saml:Issuer>

<samlp:Status><samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"/></samlp:Status>

</cfsavecontent>


<cfxml variable="samlAssertionXML">

<saml:Assertion ID="#ssouser.uuid#" IssueInstant="#nowDateTime#" Version="2.0" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">

<saml:Issuer>#IDPDomain#</saml:Issuer>

<saml:Subject>

<saml:NameID>#ssouser.email#</saml:NameID>

<saml:SubjectConfirmation Method="urn:oasis:names:tc:2.0:cm:bearer">

<saml:SubjectConfirmationData InResponseTo="#ssouser.uuid#" NotOnOrAfter="#nowDateTimePlus1#" Recipient="#SPService#"/>

</saml:SubjectConfirmation>

</saml:Subject>

<saml:Conditions NotBefore="#nowDateTime#" NotOnOrAfter="#nowDateTimePlus1#">

<saml:AudienceRestriction>

<saml:Audience>#SPDomain#</saml:Audience>

</saml:AudienceRestriction>

</saml:Conditions>

<saml:AuthnStatement AuthnInstant="#nowDateTime#">

<saml:AuthnContext>

<saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport</saml:AuthnContextClassRef>

</saml:AuthnContext>

</saml:AuthnStatement>

<saml:AttributeStatement>

<saml:Attribute Name="screenName">

<saml:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">#ssouser.name#</saml:AttributeValue>

</saml:Attribute>

</saml:AttributeStatement>

</saml:Assertion>

</cfxml>


<cfsavecontent variable="responseClose">

</samlp:Response>

</cfsavecontent>

</cfoutput>



The immediate question is why do I have the XML split up into 3 variable? The whole thing could be enclosed as 1 inside <CFXML>. The reason is that I ran into a bug (to come in Part 3) where I had trouble traversing the DOM beyond the first level of depth. So by cutting out the opening and closing <SAMLP:RESPONSE> tags, I can deal with the middle piece by itself, where <SAML:ASSERTION> is the root level. It might not make sense yet, but I promise it will be cleared up once you read Part 3!

So on to the other ColdFusion pieces:

1) The 2 <CFSET>s in the beginning handle the 2 date/time stamps (now & 1 minute later). I'm not sure if they actually need to be formatted this way, but the other sites I studied had it like this and it worked for me as well.

2) The 1st and 3rd variables I'm saving out use <CFSAVECONTENT> because I'm going to be adding these back in after the signing process and they don't need to be recognized as XML yet.

3) The 2nd variable needs to use <CFXML> rather than <CFSAVECONTENT> because it needs to retain the XML DOM. Later on, when I create and insert the signature piece, it will need to reference this 2nd variable as if it were a valid XML document.

While your at this step, I encourage you to dump out these variables right on the document you're creating so you can get a visual of the unsigned XML to compare with the signed version later on. Just be sure to delete it when it's finalized.

January 8, 2010

Frommer's Slideshow

Just before the holidays, one of the projects that I was devoted to was a new slideshow format for Frommers.com. We wanted something that highlighted the photo. It also had to be fast and easy to navigate. I went with a neutral color scheme so the only colored item on the page would be the photos. Here are some of the one's we've published so far:


On the technology side, the play/pause feature is actually very simple. It's just a basic META refresh that's controlled by a URL variable, but it works well and fast. I threw in another script that activates the arrow keystokes to manually move forward and back in the slideshow. I'm used this feature from Facebook and Picasa and think every slideshow should have it. The links pass the slideshow URL over to the top social networks. "Get Link" uses a JQuery modal window with an autoselect onFocus so users can grab and save the URL of each photo.

Malware Detection

This a pretty useful tool in trying to weed out malware from a website. It checks against a database of blacklisted sites created by Google. All of the good browsers (Firefox, SeaMonkey, Safari & Chrome) check against this database whenever you visit a site.



 
Dragonsaber