Saturday, January 30, 2010

HTML 5 Geolocation Functions and Mobile Web Browsers: Show the User Where They Are (Sort Of)

Every April, the University of Maryland holds a huge open-house event called Maryland Day that draws 60,000+ visitors to the campus to view exhibits highlighting the research conducted at the university and participate in various events and activities. All of the event details are entered into a ColdFusion application, and one of those details is the GPS coordinates (latitude and longitude) of where each event is taking place so visitors to the website can see where the events are located on Google Maps.

Now that smartphones are becoming more prevalent, I wanted to see if it was possible to build a web application that would show the user where they were currently located and then show them on a map how to get from their current location to a particular event.

So I did some research and learned that HTML 5 comes with a Geolocation API. This API allows you to execute Javascript functions within the navigator.geolocation object built into the browser that retrieve the supposed latitude and longitude coordinates of where the browser is located (and, if available, the altitude, heading, and speed at which the browser is moving).

Using the code examples I found on the Gelocation API page on the W3C website and on Oliver Wehren's geolocation demo page, I was able to create my own test page for determining my location and marking it on Google Maps. I then tried using the page with my Motorola Droid, my iPod Touch, and my manager's iPhone.

The default web browsers on all three devices implemented the Geolocation API (my preferred browser on my Droid, the Dolphin Browser, did not). Each of the browsers displayed a confirmation dialog asking for permission to share my location information with the web page (as mandated by the standard), and once I permitted the information to be used, my test page was able to place a marker denoting my location on the map.

However, the location wasn't as accurate as I had hoped. Although the API was coded to accept location data from the on-board GPS system in a mobile device, neither the iPhone nor the Droid seem to provide GPS data to the browser. If I was connected to the campus wireless network, my location was determined via the network topography, and it could be off by as much as 150 feet or so. The accuracy was even worse if I was relying solely on 3G: in that scenario, but the iPhone and the Droid had me located on the side of a state road on the outskirts of campus, a good twenty minute walk from where I actually was. I have no idea what caused both devices to pick that particular spot, as there certainly wasn't a cell tower anywhere near that location.

So I came to the conclusion that while the Geolocation API could be used to determine what town, city, or general area a user was currently in, it wasn't accurate enough (at least with these browsers in these devices) to provide walking or driving directions within a small area, especially given the fact that many of the users for the service I had in mind would only have access to the Internet via a 3G connection.

But if someone knows of a way of increasing the location accuracy of the Geolocation API, a way that doesn't require the end-user to modify their mobile browser in order to make it work, I'd love to hear about it.

Monday, January 18, 2010

Quick Tip: Securing Your Model Glue XML Configuration Files

A quick disclaimer: nothing I'm about to say here is all that revolutionary.  Others, particularly Charlie Griefer, have posted about this technique before, just not with a specific focus on using it with Model-Glue or with exact step-by-step instructions.

There are a number of key configuration files in Model-Glue that exist as plain XML files. One of the drawbacks to using XML files on a website is that anyone can point their browser at the XML file and read its contents, which is less than ideal from a security standpoint.

There are a number of ways you can make those XML files secure, such as storing them in a directory outside of the web root or configuring your web server to block access to XML files (see Charlie's post for details on those techniques), but not every developer has the permissions needed to implement those solutions.

So one way that you can protect those XML files without needing access to anything beyond the web root is to convert them to .cfm files and prevent them from executing, and here are the exact steps you would use in a typical Model-Glue application to do just that:
  1. Go to the index.cfm file of your application.  Uncomment the <cfset> line for "CUSTOM APPLICATION CONFIGURATION" and set it to point to "Coldspring.xml.cfm" instead of "Coldspring.xml".
  2. Rename "ColdSpring.xml" to "ColdSpring.xml.cfm". 
  3. In the ColdSpring file, go to the ModelGlue configuration bean definition and change the "configurationPath" and "scaffoldPath" values to point to the .cfm equivalent files instead of the original XML ones.  If you're using Transfer or Reactor in your application, also update any <constructor-arg> tags in those bean definitions that point to the XML configuration files for those ORM frameworks.
  4. If you have any other references  to .xml files in your ColdSpring file, update those as well.
  5. In the ModelGlue.xml file in your application, remove "<cferror>" from the comment above the "page.error" event (if you don't, anyone who does try to browse to that file will generate a ColdFusion error).
  6. Tack on ".cfm" to the file names of all of the .xml files referred to in steps 3, 4, and 5.
  7. Add an Application.cfm file to the "config" directory of ModelGlue with one line in it: <cfabort />  That will ensure that the XML is not shown even in the page source if the .xml.cfm file is directly accessed by the browser.
The end result of taking these steps is that if anyone tries to point their browser to any of these renamed configuration files (ModelGlue.xml.cfm, ColdSpring.xml.cfm, etc.) all they will get back is a blank page with no source code to view.

Tuesday, January 5, 2010

Soft Deletes Verses Real Deletes When Doing CRUD Interactions

I happened to stumble across a blog post today by Phil Haack with the title "Death to confirmation dialogs with jquery.undoable." In it, Phil explained how he was inspired to write his plugin by seeing how his Netflix queue allowed him to "undo" the deletion of an item from the queue. As he said in his post:

"Notice that there’s no confirmation dialog that I’m most likely to ignore questioning my intent requiring me to take yet one more action to remove the movie. No, the movie is removed immediately from my queue just as I requested. I love it when software does what I tell it to do and doesn’t second guess me!"

His post got my attention because I'm currently in the middle of designing a scaffolding/code generation system, specifically to output pages for performing CRUD (Create, Read, Update, Delete) tasks, and it's currently designed so that when the user clicks on a "delete" link for a record (and Javascript is enabled), I make the user confirm their decision via a customizable dialog box (via the jqModal jQuery plugin) before proceeding with the deletion.

So I got to thinking about what would be involved in doing what he was suggesting: allowing the user to "delete" a record without confirmation as long as they had the option of undoing that action while still on the page.

I put "delete" in quotation marks because such a process would almost certainly involve making the delete a "soft" delete: marking/tagging the record as being deleted but not actually deleting the underlying database record. Undoing an actual deletion would be much harder, given that you would lose the unique record id in the deletion in addtion to the rest of the record data. I suppose you could potentially store the data from the record client-side (in the page) so the "undo" record could recreate the record from scratch, but that would be a pain and might not be feasible in every scenario. Undoing a soft delete/changing the delete flag in the record, on the other hand, would be pretty easy.

But if I went the soft delete routine, then the question would become: how do those records get deleted for real? I tend to design my web applications with a long term view, and I don't want the application database tables to fill up with deleted records over a number of years. My clients typically only have access to the database tables via the application itself, so leaving that up to them is not an option. So I would either have to given them another page/tool in the web application (perhaps a tool restricted to a tech-savvy few) to actually remove the deleted records, or perhaps run a scheduled task to remove those database records that have been marked for deletion for a year or more.

After some consideration, my current inclination is to stay with my current confirmation dialog/deletion routine. In most of my applications, the CRUD interactions are reserved for the administrative users of the application, who typically know when it's appropriate to delete a record. And the need to delete a record via the CRUD tools provided is usually rare, so having a confirmation dialog come up for each instance isn't too much of an annoyance.

But I'd be curious to hear other people's thoughts on this topic.