A coworker of mine has been researching secure Flex 2 remote object calls to ColdFusion cfc’s over HTTPS. Seems simple enough, but anytime sensitive information is passed over the Internets I’d really like it to be bulletproof. Sure, I’m comfortable with HTTPS, but opening a flash swf over HTTP and trusting that it’s using HTTPS behind the scenes makes me a queasy system admin.

By default, a Flash movie can only access data through the exact domain where it was itself accessed. So, when you open a Flash swf over HTTP it can’t open a remote object over HTTPS to the same domain. The data host server can be tweaked to allow HTTP to HTTPS communication. But do I really want to make this tweak?

Adobe has this to say about it in a Flash tech note:

A secure server that allows access to movies hosted via a non-secure protocol
It is not advisable to permit HTTP content to access HTTPS content. This practice can compromise the security offered by HTTPS.

Most of the developers using our CF servers for Flex purposes are only using HTTPS for authentication. The rest of their app data is generally non-sensitive and doesn’t require encryption.

Is there really a security risk in opening a swf over HTTP and then making HTTPS remote object calls? If the endpoint is set in the Flex 2 app to an https address, all signs indicate that communication from the swf is going over HTTPS.

Microsoft offers up its view on what makes for a good gadget in a document buried under their Windows Vista User Experience Guidelines: Windows Sidebar Gadgets.

Despite being hidden away on the MSDN site, this is actually a really focused, useful set of guidelines for anyone thinking about creating desktop gadgets.

After some basic info on what a gadget is, the document explores what type of functionality belongs in a desktop gadget. There are visuals comparing examples of good and bad gadget layouts. There’s also guidelines for making the most of the Sidebar gadget framework, advice on handling different states of interaction visually, and recommended sizing standards.

I’ve been keeping this under wraps, but since I turned in the signed contracts there’s really no turning back. I’m working on a book about Windows Vista Sidebar gadgets.

The book’s part of a series called Visual Blueprint targeted to technically inclined people looking to learn a new skill. It’s really for people who have put together a few web sites and want to learn how to make interactive gadgets for the Vista desktop. It covers all the basics you need to make a gadget with lots of helpful screen-shots.

It’s going to take up most of my time for the next few months, but I’m really happy to be working on it. I think it’s a great subject — gadgets of all types are really going to change the way people interact with their desktop and with the web. It’s exciting to help people create their own gadgets.

One of my first projects in ColdFusion was a tool that compares files between two different folders and reports differences. The tool was intended for developers to identify differences between code in different phases of development. It wasn’t very fast, and when run against a large amount of files it crapped out completely.

I recently overhauled the code and was able to make it much faster. Maybe someone else will find it useful.

In the process I learned a few things:

  • <cfdirectory action=”list” recurse=”yes” /> is not always efficient. Directly using java.io.file can be dramatically faster — up to 200% faster when listing files & directories from a network location.
  • Opening two files into memory using <cffile> and comparing the contents is not the most efficient way to tell if they are different. Duh.
  • Recursively calling a function is a great way to walk through multi-level data.

I ended up tightening things down to two functions. BuildFileDictionary walks through a given base folder using java.io.File path and builds a struct of file information. The struct is keyed on the relative path of each file, thus the FileDictionary naming. This way, I can access information for a specific file using simple code like this: FileDictionary[relativeFilePath]. It also helps determine which files from one source do not exist under another by simply checking for the existence of a struct key.

The second function, CompareFileDictionaries compares two file dictionary structs and returns a couple lists: files only in dictionary one, files only in dictionary two, and files in common but out-of-synch. I settled on file size and last modified date as an acceptable basis to indicate file differences. There are other indicators, but these values were the most efficient to access.

BuildFileDictionary

<cffunction name="BuildFileDictionary" returntype="struct" access="public" output="false"
hint="Recurses through a directory, building a struct with file information. The result struct is keyed on each file's path relative to the passed-in base path. ie - details on TopFolder/SubFolder/File.txt are accessed through ReturnStruct['TopFolder/SubFolder/File.txt']">

<cfargument name="BasePath" type="string"
hint="Full path to the folder you want to build a dictionary for. UNC paths are acceptable.">
<cfargument name="ExcludeFileExtensions" type="string"
hint="List of file extensions to exclude from results.">
<cfargument name="ExcludeDirectories" type="string"
hint="List of directories to exclude from results. Leave off trailing / for each.">
<cfargument name="Files" type="any" default="-999" required="false"
hint="Optional Java File collection to recurse. Leave this arg off to start with the BasePath location.">
<cfargument name="FileDictionary" type="struct" default="#StructNew()#" required="false"
hint="FileDictionary to append results to. Leave this arg off to start fresh.">

<cfset var fileWalker = ArrayNew(1) />
<cfset var fileCounter = "" />
<cfset var relFilePath = "" />

<!--- Grab collection of files from Java.io.File if not passed in --->
<!--- Java.io.File is much faster than cfdirectory action='list' especially when accessing UNC paths --->
<cfif arguments.Files EQ -999>
<cfif DirectoryExists(BasePath)>
<cfset arguments.Files = createObject("java","java.io.File").init(arguments.BasePath).listFiles() />
<cfelse>
<cfthrow type="Application" message="BasePath does not exist" detail="The provided BasePath does not exist. Please enter a valid BasePath." />
</cfif>
</cfif>

<cfset fileWalker = arguments.Files />

<!--- Loop through current level of files and directories --->
<cfloop from="1" to="#ArrayLen(fileWalker)#" index="fileCounter">
<cfset relFilePath = Replace(fileWalker[fileCounter].getAbsolutePath(),arguments.BasePath,"") />

<!--- Recursively call this function for sub-directory --->
<cfif fileWalker[fileCounter].isDirectory()>
<cfif ListFindNoCase(arguments.ExcludeDirectories,relFilePath) EQ 0>
<cfinvoke method="BuildFileDictionary">
<cfinvokeargument name="BasePath" value="#arguments.BasePath#">
<cfinvokeargument name="ExcludeFileExtensions" value="#arguments.ExcludeFileExtensions#">
<cfinvokeargument name="ExcludeDirectories" value="#arguments.ExcludeDirectories#">
<cfinvokeargument name="Files" value="#fileWalker[fileCounter].listFiles()#">
<cfinvokeargument name="FileDictionary" value="#arguments.FileDictionary#">
</cfinvoke>
</cfif>
<!--- Grab details about this file --->
<cfelseif fileWalker[fileCounter].isFile()>
<cfif ListContainsNoCase(arguments.ExcludeFileExtensions,ListLast(relFilePath,".")) EQ 0>
<cfset arguments.FileDictionary[relFilePath] = StructNew() />
<cfset arguments.FileDictionary[relFilePath].FileName = fileWalker[fileCounter].getName() />
<cfset arguments.FileDictionary[relFilePath].FilePath = fileWalker[fileCounter].getPath() />
<cfset arguments.FileDictionary[relFilePath].AbsolutePath = fileWalker[fileCounter].getAbsolutePath() />
<!--- The hash value can be used to identify file contents, but it seems to slow things down to grab it --->
<!--- <cfset arguments.FileDictionary[dictionaryKey].HashCode = fileWalker[fileCounter].hashCode() /> --->
<cfset arguments.FileDictionary[relFilePath].LastModified = fileWalker[fileCounter].lastModified() />
<cfset arguments.FileDictionary[relFilePath].Size = fileWalker[fileCounter].length() />
</cfif>
</cfif>

</cfloop>

<cfreturn arguments.FileDictionary />

</cffunction>

CompareFileDictionaries

<cffunction name="CompareFileDictionaries" access="public" output="false" returntype="struct"
hint="Compares two file dictionaries and returns a struct containing files only in one, files only in two, and common files out of synch.">

<cfargument name="fileDictionaryOne" type="struct" required="yes" hint="File dictionary one">
<cfargument name="fileDictionaryTwo" type="struct" required="yes" hint="File dictionary two">

<!--- Variable declarations --->
<cfset var comparisonResults = StructNew() />
<cfset var relFilePath = "" />

<!--- Build up struct properties for results --->
<cfset comparisonResults.NamesOneOnly = ArrayNew(1) />
<cfset comparisonResults.NamesTwoOnly = ArrayNew(1) />
<cfset comparisonResults.OutOfSynch = false />
<cfset comparisonResults.NamesCommonOutOfSynch = ArrayNew(1) />

<!--- Loop through the relative file paths in the first file dictionary checking if the --->
<!--- same file relative path exists in the second file dictionary. If it does exist in --->
<!--- second dictionary, check if files attributes are out of synch between the two. --->
<cfloop list="#ListSort(StructKeyList(arguments.fileDictionaryOne),"textnocase","ASC")#" index="fileRelativePath">
<cfif StructKeyExists(arguments.fileDictionaryTwo,fileRelativePath)>
<cfif (arguments.fileDictionaryOne[fileRelativePath].LastModified NEQ arguments.fileDictionaryTwo[fileRelativePath].LastModified)
AND (arguments.fileDictionaryOne[fileRelativePath].Size NEQ arguments.fileDictionaryTwo[fileRelativePath].Size)>
<!--- File last modified data and file size does not match, add to NamesCommonOutOfSynch array --->
<cfset ArrayAppend(comparisonResults.NamesCommonOutOfSynch,fileRelativePath) />
</cfif>
<cfelse>
<!--- File does not exist in second dictionary, add to NamesOneOnly --->
<cfset ArrayAppend(comparisonResults.NamesOneOnly,fileRelativePath) />
</cfif>
</cfloop>

<!--- Loop through the relative file paths in the second dictionary checking if each exists --->
<!--- in the first dictionary. --->
<cfloop list="#ListSort(StructKeyList(arguments.fileDictionaryTwo),"textnocase","ASC")#" index="fileRelativePath">
<cfif not StructKeyExists(arguments.fileDictionaryOne,fileRelativePath)>
<cfset ArrayAppend(comparisonResults.NamesTwoOnly,fileRelativePath) />
</cfif>
</cfloop>

<cfif ArrayLen(comparisonResults.NamesCommonOutOfSynch) GT 0
OR ArrayLen(comparisonResults.NamesOneOnly) GT 0
OR ArrayLen(comparisonResults.NamesTwoOnly) GT 0>
<cfset comparisonResults.OutOfSynch = true />
</cfif>

<cfreturn comparisonResults />

</cffunction>

I needed to set the expiration date for Active Directory accounts in a VB.net web service today. Sounds simple, but it’s actually a bit tricky.

Turns out there’s a way to get around using the nonsensical large integer that AD uses to store the accountExpires field:

Dim NewADObject As DirectoryEntry
Dim ADContainer As DirectoryEntry

ADContainer = New DirectoryEntry(adPath,user,pass,authtype) NewADObject = ADContainer.Children.Add(cn,objectClass)

NewADObject.Properties("SAMAccountName") = "newusername"

... yadda yadda yadda ...

'Set expiration date for account Dim expireDate As DateTime = DomainAccountExpDate NewADObject.NativeObject.AccountExpirationDate = expireDate

NewADObject.CommitChanges()

The bold bit is the pertinent section. NativeObject allows direct access to the properties of the underlying DirectoryEntry COM component. AccountExpirationDate can be set as a DateTime value.

Twitter is sort of like instant messaging. Scratch that — it’s really more like instant message away messages.

So why is a feed of other people’s away messages interesting? And why do I need to keep a running tally of my own? Somewhere in the mix of web application and desktop gadgets, the folks behind Twitter have struck gold.

While I visit the Twitter site from time to time, my main interaction with the service is through desktop mini-apps. I’ve got Twadget (yeah, that name… not the best) loaded on my Vista Sidebar at work, and Twitterific installed on my personal MacBook. With a mouse click or two and a few quick keystrokes, I can post a short message without ever opening a web browser.

The process is simple, it doesn’t interrupt whatever else I’m doing. It’s become part of my routine just like having an IM window open to chat with friends.

This is really the power of web enabled gadgets. They break web apps outside of the browser, taking away another barrier to entry for your application. Just like RSS has done for following information on the web, gadgets can be used to extend interaction out of a web site and make it part of your users’ routine.

Mesa Dynamics has released Amnesty Generator, a freeware app that packages various formats of web gadgets automagically into Vista Sidebar Gadgets.

The site claims Google gadgets and other web widgets can be quickly added to the Sidebar. While I can certainly live without annoying MySpace audio players on my desktop, if this works as advertised, it would bring an immediate boost to the library of available Sidebar gadgets out there.

I wrote up a walk-through at work on creating a simple Sidebar Gadget: Vista Sidebar Gadgets.

Although the example app may not be useful to the public, the concepts might help you create a Gadget of your own.

My boss Terry released his first open source software project yesterday. It’s called Squidhead, and it’s ColdFusion code that automagically creates… ColdFusion code.

Using only database tables and a few configuration settings, it builds up all the CF code needed to list, add, update, and delete database records in a web app. It will even read a step further into the database and generate ColdFusion components for your custom stored procedures.

Code generation seems to be gaining steam with developers, and with good reason. It’s a great way to make sure you stick to standards when it comes to interacting with a database. And it’s cuts out a lot of the busy work usually involved with building a web app.

If ColdFusion isn’t your tool of choice, I’d recommend checking out his presentation on how Squidhead works. This sort of code generation might be something you can apply to your own programming work flow.

Backing up a database on a shared MS SQL Server is painful. Sure, DTS can make pretty maps with lots of stripey, candy cane looking pipes. But has anyone ever been able to backup and restore a database on a shared hosting server? No. Don’t lie. You’ve never done it.

There’s finally an easy way to do remote backups against a SQL Server. Microsoft has released a utility entitled: SQL Server Hosted Toolkit. And, believe it or not, it actually works.

(Confused about the CodePlex site? It’s just “Microsoft’s open source project hosting web site.”)

Install the package and run the Database Publishing Wizard. Enter your credentials, select your database, and the utility will script the structure and data from a database to a text file. There’s also an option to move between databases, if you want to migrate between servers or clone a database.

Best of all, the utility can handle both 2005 and 2000 version databases. So it’s worth a look if you’re thinking about upgrading a database.