dans.blog


The miscellaneous ramblings and thoughts of Dan G. Switzer, II

Stupid HTML Tricks: Add a non-selectable option to a select element

Occasionally I've run into a situation where I've wanted to add some whitespace between two options in a <select /> element. The most common solution I've seen people use is to include an empty <option></option> tag pair. While this works, it adds a blank entry that the user can actually select—which means you have to add some code to handle the selection of what is designed to just be used for whitespace.

A better solution is to use an empty <optgroup /> that is disabled:

<select>
  <option>Value 1</option>
  <!---// add a non-selectable space between options, the margin-top is for FF spacing //--->
  <optgroup disabled="disabled" style="margin-top: 1em;"></optgroup>
  <option>Value 2</option>
</select>

This will add a non-selectable blank line between "Value 1" and "Value 2". Here's an example:

I use this technique often before normal <optgroup /> tags as it helps make the menu look a little cleaner by adding some separation between the options and works with all modern browsers. Best of all, you don't have to worry about handling those empty <option /> tags!


Vote now to have ColdFusion provide better XSS protection

Today I submitted the ColdFusion Enhancement Request #80336 to add better tools for preventing XSS attacks. More and more it's becoming common for developers to need to implement some type of WYSIWYG editor, but with that comes the increased risk of XSS attacks.

We've all heard about attacks on MySpace and other major sites and this is because it's actually a pretty difficult problem to solve correctly (since there are so many attack vectors.)

My suggestion would be for Adobe to integrate the OWASP AntiSamy project into ColdFusion. This is an excellent tool for cleaning up input to prevent XSS attacks and is highly configurable via XML.

If you're interested in solving this problem now, see my Using AntiSamy to protect your CFM pages from XSS hacks blog entry for details on implementing AntiSamy right now.


Rounding to the nearest fraction (i.e. specific decimal place)

I'm working on some "star rating" code and I really wanted to round numbers of to the nearest fraction. While the math is really basic, my math skills are rusty and this took me longer to solve than I care to admit. So I thought I'd just blog the solution for anyone else that might find it useful:

round( value/fraction ) * fraction

Like I said, it's very basic math but is very handy when you want to round to something other than to the closest integer.


SVN reporting "Working copy text base is corrupt"

This morning started off to a rough start. I came in to realize the commit of a merge I made at the end of the day yesterday had failed. Whenever I would attempt to commit the merge changes, it would go through the entire process and then finally fail with a error message of:

org.tigris.subversion.javahl.ClientException: Working copy text base is corrupt

After trying a "Cleanup" and several other steps to rectify the problem, I finally did hit Google to try and find a solution. I came across chris' subversion checksum mismatch - easy workaround which offered several various solutions to the problem.

I tried several of the solutions, but wasn't haven't much success until I came across Michael Sparer's comment:

Thanks for the explanation, which shed some light on how svn manages its working copy. My problem seemed to stem from a bogus file under .svn/text-base, which didn't match the file actually on the server.
- server file (.../x.java): OK
- orig copy from server (.svn/text-base/x.java.svn-base): BOGUS (not same as server)
- checksum (in .svn/entries): matches server, but not server copy

If I can make the bogus copy match what's on the server, then it will also match the checksum, and everyone will be happy.
What I did (i'll call the working dir with the corrupt file "orig-dir":
1. Fresh checkout of svn dir matching orig-dir into /tmp/blah
2. Copy /tmp/blah/.svn/text-base/x.java.svn-base into orig-dir/.svn/text-base
3. Check in successfully

I wish svn would let you refresh a given file from the server...maybe there's a command and I just haven't found it or my svn is too old.

In the end, this ended up being my problem as well. The copy of me .svn/text-base/filename.ext.svn-base was out of sync with the actually copy on the server.

To resolve this, I checked out a clean copy from the server to a tmp folder, then I just replaced the copy in my working folder. After doing this, I was able to check in the file without incident.

NOTE:
I also noticed I had a copy of the template in the .svn/tmp/text-base/ folder. I made a copy of this file and then removed the file this directory before committing. I'm not sure if this step is necessary, but I wanted my local working copy to mirror as closely as possible a fresh working copy.
I could have just wiped my local copy altogether, but I wanted to know the root problem incase it every happens again. Since I have a pretty large repository it takes a while to checkout from SVN, so at least know I have an option to try if I ever run into the issue again that won't require me checking out the entire working directory structure.


CF9 can protect SQL statements stored as string from SQL injection

One of the many new features in ColdFusion 9 is the ability to use every tag within a <cfscript /> block. Developers seem to either love or hate <cfscript /> and I've always falling into the love (well, maybe not love but I'm extremely fond of it.) I just find <cfscript /> a better method for writing business logic. So for me, the addition of being able to access any CF tag via <cfscript /> will be really nice. However, I wanted to point out one specific use case where the addition of being able to script any tag really comes in handy.

One of issue I've run into in the past with ColdFusion is that there's no good way to protect a SQL statement from SQL injections if your SQL is coming from a string variable. In most cases you're going to build dynamic SQL statements within a <cfquery /> block, occasionally I've found situations were this isn't ideal.

In these cases I've wanted to use a UDF to generate a block of SQL for me, because I can easily re-use the function to re-use common blocks of SQL.

The problem with building the statement via a UDF is that when your SQL is generated as a string, there's you can't use <cfqueryparam /> to secure your data (unless you were to save the string to disk, include it in the query and then clean up the temp file.)

This is where CF9's new functionality of being able to script any tag will become handy. ColdFusion 9 introduces a way to bind a token to a SQL parameter. This would allow you to build a SQL statement completely from a string and then bind tokens in the string to parameters.

The following example code comes from John Whish's cfquery in cfml with parameters post:

// create a query
q = new Query();

// don't need to set datasource if using this.datasource in Application.cfc 
q.setDatasource( "cfartgallery" );

// build the SQL statement 
q.setSQL( "select * from Art where artistid = :artistid and issold = :issold" );

// this is the equivalent of cfqueryparam 
q.addParam( name="artistid", value=2, cfsqltype="CF_SQL_INTEGER" );
q.addParam( name="issold", value=1, cfsqltype="CF_SQL_BIT" );

// run the query and get a query object
result = q.execute();

// dump query object
writeDump( result );

As you can see from the code, the setSQL() method takes a string of SQL to execute. You'll also notice two unique tokens in the SQL ":artistid" and ":issold". When you invoke the q.addParam() method, you're replacing the tokens with a binding SQL variable—which protects you from SQL injections.

So, the addition to the new Query() object ends up solving a problem that I've run into in the past to which there's never been a really good solution for in the past.

I've been meaning to post this since the CF9 beta became public, but work kept getting in the way. :)


structFilter() UDF - Filtering a structure based upon a regular expression

Today I thought I'd share a little ColdFusion helper function I've been using for years: structFilter(). The structFilter() parses a structure and returns only the keys that match a given regular expression.

<!---
 Searches a structure for keys matching a regex and returns a structure containing the
 matched keys.

 @param input        The structure to filter. (struct; required)
 @param regex        The regular expression to filter keys against. (string; required)
 @param useNoCase    Do a case insensitive search? (boolean; default = true)
 @param useDeepCopy  Do a deep copy on the keys? (boolean; default = false)

 @return Returns a structure containing the matching keys.
 @author Dan G. Switzer, II (dan.switzer@givainc.com)
 @version 1, June 17, 2009
--->
<cffunction name="structFilter" returntype="struct" output="false" access="public"
    hint="Filters keys in a structure to those matching the regular expression.">
  <!---// define valid arguments //--->
  <cfargument name="input" type="struct" required="true" />
  <cfargument name="regex" type="string" required="true" />
  <cfargument name="useNoCase" type="boolean" required="false" default="true" />
  <cfargument name="useDeepCopy" type="boolean" required="false" default="false" />

  <!---// define local variables //--->
  <cfset var result = structNew() />

  <!---// if using NoCase and the (?i) directive doesn't exist, append to regex //--->
  <cfif arguments.useNoCase and not reFind("^\(\?[mx]*i[mx]*\)", arguments.regex)>
    <cfset arguments.regex = "(?i)" & arguments.regex />
  </cfif>

  <cfloop item="key" collection="#arguments.input#">
    <cfif reFind(arguments.regex, key)>
      <cfif arguments.useDeepCopy>
        <cfset result[key] = duplicate(arguments.input[key]) />
      <cfelse>
        <cfset result[key] = arguments.input[key] />
      </cfif>
    </cfif>
  </cfloop>

  <!---// return the new structure //--->
  <cfreturn result />
</cffunction>

I've found this helper UDF to be extremely handy in when you have a bunch of serialized form fields that follow a given nomenclature. For example, if you have a bunch of form fields like:

<input type="text" name="name" value="" />
<input type="text" name="description" value="" />

<!---// dynamic list of variables //--->
<cfloop index="i" from="1" to="10">
  <cfoutput>
    <input type="text" name="id_#i#" value="" />
  </cfoutput>
</cfloop>

Using the structFilter() UDF you can vary easily process all the fields starting with "id_" by doing:

<!---//
  get all the fields:
  * starting with "id_"
  * and ending with one or more numbers
//--->
<cfset stIds = structFilter(form, "^id_\d+$") />

This will give you a structure containing all the "id_" fields that you can then process in a collection-based loop. This method is much more effective then passing in some kind of hidden "counter" variable where you loop from 1 to the counter variable (which is a technique I've used in the past) as it doesn't rely on the numbers being serialized.

There are obviously many other uses for this function, but I use it a lot for processing complex forms that have dynamically generated fields that have a fixed nomenclature.


Safari 4 z-index issue with Flash

I was doing some testing with Safari 4 (on Windows Vista) and noticed that it was running into the z-index issue that's normally fixed by having a wmode attribute. The issue is that Flash was always displaying on top of all other elements. Normally this can be fixed by applying the wmode attribute of either "opaque" or "transparent" to your SWF, however that was already present.

After playing around with the problem for a good bit trying various solutions of applying an z-index to elements, I decided to check to see if I had the latest version of Flash installed. Turns out I was running Flash 10,0,22,54 and 10,0,22,87 is the latest version. Sure enough, after upgrading Flash everything started working as expected.

So, if you're having problems with Flash being overlaid over all of your elements in Safari, try upgrading to the latest version of Flash to see if it fixes the problem.

(To see how things should work, check out http://pipwerks.com/lab/swfobject/z-index/2.0/dynamic.html. If mousing over the menu options is not showing some pop-up elements, then something has gone awry—so try upgrading Flash.)


CFHTTP "Connection Failures" issues when using mod_rewrite

Several years ago I ran into some issues with CFHTTP giving "Connection Failures" when using GZIP, but recently I ran into some new "Connection Failures" when using CFHTTP. I recently installed some mod_rewrite rules on our server to:

  • Redirect naked domains to the www subdomain (i.e. map domain.com to www.domain.com)
  • Force SSL

My rules were pretty simple and worked great when invoked from the browser, but I quickly realized they were causing issues with CFHTTP.

more…


Pagination in MSSQL 2005 with one-to-many joins

I was working on restructuring some old code that needed some pagination. The query in question used a one-to-many join the required information together. Imagine a search engine where you're wanting to search over orders, but want to group the results by customer. The output might look something like:

Gary Dell'Abate
  Order #: 12098
  Order #: 13232
  Order #: 14551
  Order #: 16770
Fred Norris
  Order #: 11021
  Order #: 11029
Robin Quivers
  Order #: 10010
  Order #: 11001
  Order #: 12001
Howard Stern
  Order #: 13001

So, in my situation I want to also paginate by the customers. When SQL Server 2005 was introduced, it added a new feature called Common Table Expressions (CTEs.) One of the most useful features of CTEs is to paginate recordsets. Typically when paginating results, you will use the row_number() function—which creates a new unique row number for each row in your recordset:

more…


Targeting specific Browsers with CSS

Pail Irish posted a nice concise list of CSS hacks for targeting specific browsers. While I'd love to avoid using hacks altogether, I just continually find cases where it's necessary so this list is a handy little reference:

/***** Selector Hacks ******/

/* IE 6 and below */
* html #uno  { color: red }

/* IE 7 and below */
*:first-child+html #dos { color: red }

/* IE 7 and modern browsers */
html>body #tres { color: red }

/* Modern browsers (not IE 7) */
html>/**/body #cuatro { color: red }

/* Opera 9.27 and below */
html:first-child #cinco { color: red }

/* Safari */
html[xmlns*=""] body:last-child #seis { color: red }

/*safari 3+, chrome 1+, opera9+, ff 3.5+ */
body:nth-of-type(1) #siete { color: red }

/* safari 3+, chrome 1+, opera9+, ff 3.5+ */
body:first-of-type #ocho {  color: red }

/* saf3, chrome1+ */
@media screen and (-webkit-min-device-pixel-ratio:0) {
 #diez  { background: #FFDECE; border: 2px solid #ff0000  }
}

/***** Attribute Hacks ******/

/* ie6 and below */
#once { _color:blue }

/* ie7 and below */
#doce { *color: blue } /* or #color:blue */

/* 'Modern Browsers' includes IE8, whether you agree or not.. :) */

I did notice that the "*" hack (i.e. "*color: blue") also seems to get picked up by IE8, while he lists the hack as for being for IE7 and below.

Paul even set up a test page with all the hacks for testing.

Nice job Paul!


Ganymede Mylyn v3.1.1 not working with Trac 0.10.4

I recently upgraded to Eclipse 3.4.2 (Ganymede) and started having problems connecting to Trac. I didn't have any problems with Mylyn v2.3.2 in Eclipse v3.3, so I knew there were no configuration issues my installation.

The first thing I did was bust out an HTTP proxy tool so I could view the HTTP traffic being sent. Turns out that Mylyn was not sending the authentication header, so my servers was just spitting back a 401 authentication failed message.

I did a lot of searching and finally found the authentification fails with mod_auth_sspi or NTLM issue in the Mylyn bug tracker—which appears to be the exact issue I'm having, but alas upgrading to even the weekly (Mylyn v3.2) did not fix the problem.

Finally, I decided to just uninstall all the versions of Mylyn I had installed, but v3.0.5 that came with my Ganymede installation. To do that, you've first got to disable all the plug-ins and then you can uninstall.

Fortunately, rolling back to v3.0.5 has gotten me up and running again.

NOTE:
Our Trac server is running Apache 2.4 with Trac 0.10.4. We also are using SSL with a custom cert and using Windows Authentication.


Eclipse showing .svn-base files in "Open Resource" dialog…

Recently after installing a fresh copy of Eclipse 3.4 on my PC, I ran into an issue with the "Open Resouce" dialog ([CTRL]+[SHIFT]+[R]) where it was showing all my SVN files. Installing Subclipse is supposed to make the Eclipse IDE automatically hide the .svn-base files from showing up (via the "Team" interface) but it wasn't working out for me.

Turns out there was a very easy solution to this problem—just right click on the project and choose "Close Project" from the menu. After the project closes, just right-click on the project and select "Open Project." This should reinitialize all the settings on a project and appears to registered the handling of automatically hiding the .svn-base files.

An alternative, would be to add the find your org.eclipse.ui.ide_3.4.*.jar (org.eclipse.ui.ide_3.4.2.M20090127-1700.jar) and then modify the plugin.xml file to include the filter "*.svn-base". I don't like this option because it requires you to change a JAR that could later be updated.

If you choose that route, close Eclipse and open the JAR with a Zip extraction tool. Next, search the plugin.xml for the text "<filter". There should be one filter tag:

more…


Flash + IE7 + SSL + XML = Epic Fail…

Yesterday I ran into a very weird issue that one of our users reported. They complained that a Flex component was not working. Originally they described the problem as the Flash wasn't loading at all, but after digging around (and having the user send a screenshot) I realized the Flash was running, but it just wasn't getting the data.

Sure enough, I fired up Internet Explorer 7 and I saw the exact same issue. This was working fine in other browsers (such as Firefox, Safari and Chrome.) I was also having no issues using SSL on our development server. All I can think was "WTF?"

So, off to Google I went looking for an answer.

After some digging, I finally came across Mark Speck's IE7 + SSL + XML? = Flex "Error #2032: Stream Error" post. While I had found a number of similar posts declaring the same problem, every other article I found indicated this was only a problem if the "Cache-Control" header was being sent—which my production server was not sending. However, Mark also documented that this issue could occur with no "Cache-Control" heading—which matched what my production server was doing.

Since I wanted to be able to handle this problem programmatically (because I didn't want this issue to crop up again if we ever migrate servers or add more servers to the cluster,) I decided the best method to solve this problem was to serve up the XML dynamically using ColdFusion. I was able to resolve the problem by moving my XML into a CF template with the following code:

<!---// send the headers //--->
<cfheader name="Content-type" value="text/xml" />
<!---// this is required so IE7 will load the XML over SSL //--->
<cfheader name="Cache-Control" value="no-store, must-revalidate" />
<cfheader name="Pragma" value="public" />
<cfheader name="Expires" value="-1" />
<cfcontent reset="true" />
<xml>
    <goes />
    <here />
</xml>

Thankfully this resolved the issue.

However, I was never able to figure out why I was not having the problem in our development environment. The headers were virtually the same between the two servers. I'm beginning to think this problem might have also been related to the static XML being served via GZIP over SSL, but my dynamically served file is still being GZIP and is using SSL—so I'm not positive GZIP played a part.

I did find one other solution and that was to serve the static XML over HTTP instead of HTTPS. However, we're forcing traffic over SSL, so that option would work for us.


Vince Bonfanti gets OpenBlueDragon CFML engine running on Google Apps

I thought this would hit the blogsphere a little harder, but Vince Bonfanti was able to get a heavily modified version of Open BlueDragon running on Google Apps. The announcement is a bit buried in a Google Group list for Open Blue Dragon, but the announcement is pretty exciting, because it opens up a new alternative for hosting a ColdFusion application and it's free for pageviews less than 5 million a month.

Here's what Vince had to say about what was required to get things running:

No, this wasn't done using precompiled CFML templates--it's running a
"raw" CFML page just as you normally would.

The Google App Engine (GAE) puts a number of restrictions on Java
servlets, the most significant for OpenBD are: (1) you can't write to
the file system (but you can read from it); (2) you can't create
"background" threads; (3) you can't use any of the java.net.* classes;
and, (4) you can't use any of the java.awt.* classes. There are a
number of other restrictions when accessing the Java class libraries.

Basically, I modified the OpenBD code to workaround these
restrictions. This meant things like not writing out the
bluedragon.xml configuration file, writing logs to System.out instead
of the bluedragon.log file, disabling runtime error logging, etc. It
also meant removing or disabling some features, such as CFCHART,
CFTHREAD, CFHTTP, CFLDAP, CFMAIL, CFSCHEDULE, etc., which won't run in
the GAE environment due to the Java class library restrictions.

We still have a bit of work to do to clean this up to make it ready
for public consumption. I've handed this off to Alan Williamson, who's
going to work on modifying CFQUERY to work with the datastore (GAE
does not support SQL datasources).

While we're working on this, I'd recommend becoming familiar with the
Google App Engine for Java:

http://code.google.com/appengine/docs/java/overview.html

I'd especially recommend becoming familiar with the Eclipse plug-in:

http://code.google.com/appengine/docs/java/tools/eclipse.html

As you can see, there's a lot of modifications that were required and some that may even be deal killers depending on your requirements, but there's still plenty of opportunities to build something exciting.

This would be an excellent way to put an idea to production without investing anything but your time.


Illustrating how sorting algorithms work with animations…

I ran across a cool site today called Sorting Algorithm Animations. The site covers 8 popular sorting algorithms and gives you animated illustrations so you can see how each sorting algorithm works. You can even run the animations for all sorting methods at the same time to see how each compare in performance to one another.

What's really interesting is that it shows there is no "best" sorting algorithm. While "bubble" sorting works great when the data is nearly sorted, it's horribly slow when the data is ordered in reverse order. Other methods tend to perform about the same regardless of the randomness of it's data.

The other nice thing is that it details the algorithm used for each sort technique.

This is a great resource if you need to roll out your own sorting algorithms and are trying to decide which algorithm makes the most sense for you application.