Monthly Archive for July, 2005

Movable Type Spam Killer

Last week sometime, fed up with the unending comment spam (thousands per
week), I had an epiphany.  Spammers aren't slowed down by changing
the action of the comment submission form, so it's obvious that they're
parsing that out of the markup for the form.  By simply removing
that from the form, theoretically the comment spam should stop.  Could it really be that simple?

Sure
enough, it certainly seems to have worked.  On submission of the
form, the action is populated with JavaScript (view an entry and check
the source), so the form works exactly as before, but the actual
destination URL isn't available in the source without a pretty clever
parser (or a human).

Since I made the change, i haven't gotten a
single spam comment.  Zip.  Zero.  Nadda.  And I'm
not talking zero that have gotten through MT-BlackList; I'm talking
zero.

I know that few who read this are using MovableType, but if
anyone is and is having trouble with spam, I highly recommend this
technique.  Just make sure you also rename mt-comments.cgi, update your mt.cfg file, and rebuild, so you're not using the default template (which spammers don't have to parse out to find).

CFMX At Last

I finally got my copy of CF7 Standard a couple days ago, and have
just started the process of rebuilding with CF rather than JSP. 
There's a lot of stuff to rebuild, not all of it trivial, but I'm
hoping to be mostly done this week.

Hardly even worth posting, I
know, but it'd been over two weeks since my last post, and I'm pretty
fired up to finally have a license of CF after trying to get my hands
on one for many many months.

And Again! (ComboBox)

Based on some user feedback and some more of my own use, I've made a
couple more little tweaks to the script.  In a nutshell, orm
submission blocking now works in a far less intrusive way, hitting TAB
will select the active item before changing focus, and ESCAPE will
close the dropdown if it's open.

I've also been looking for a javadocesque
tool for generating documentation from JavaScript files.  The only
one I found was NaturalDocs, which is similar to javadoc, but uses a
different syntax.  Anyone know of anything that uses standard
javadoc sytax?

ComboBox Update

Yeah, I know it's only been a few hours, but after implementing a few different instances, I quickly decided that async processing was basically required for a performant UI. Your callback function no longer has to return an array of items (it still can, of course), but now it will be passed a second argument, which is a reference to the ComboBox object itself. There is a new setItems method on the object, which simply takes an array of items and rerenders the dropdown with them.

This makes using asynchronous JS remoting very easy to use for popuplating the dropdown with a simple closure (leveraging the Neuromancer JS remoting libraries):

function nameCallback(name, cb) {
  getGateway(true).doGetRequest(
    pathToFacade + "getNames&name=" + name,
    function(s) {
      var result;
      if (s == "")
        result = new Array();
      else
        result = s.split("|");
      cb.setItems(result);
    }
  );
}

I also added a config framework for functional flexibility, and used it to implement multi-item processing. So instead of only being able to enter a single item, you can configure the widget to allow multiple items, and as you enter each one, it will give you completion options for just that single item. I used it for tagging objects in a CMS, where I needed to assign multiple tags to an object, but also be able to create new tags on the fly. So I just type them all in, using completion for the existing tags, and then the backend sorts out what it needs to create before assigning.

The demo, downloads, and project page are still available in their original locations, just they now have updated code.

DHTML ComboBox Widget

With the wife and kid out of town, I didn't have much to do, so I spent the afternoon building a simple DHTML combobox widget. Yes, I'm that much of a geek. I haven't done a lot of testing, but I built it exclusively in FireFox, aiming for compatibility, and IE6 behaved exactly as expected on the first try, so I'm hoping other browsers will behave as well.

It's available for download at widgets.zip, a demo is available at /web/widgets/ (try entering the letter 'a'), and there is a project page as well. The demo is included in the zip file as well.

The architecture will likely seem a bit odd at first, but it's built the way it is for good reason. In a nutshell, you put an INPUT in your document, and pass it's ID and a callback function to the ComboBox constructor, and the rest happens by magic. You'll notice that you don't pass in any options, but that's where the callback function comes in. That function will be called any time the value entered in the field changes and the field has focus, and will be passed the current value. It's responsibility is to return an array of strings that should be displayed.

The demo just uses a simple array of names for the values, but I set it up in the seemingly overflexible way specifically to allow for JS remoting calls to be used for generating the dropdown list. Currently, you only get synchronous processing (since the callback has to return the values), but I might add async capabilities (so your can pass in an array of options at any time).

As always, download and run with it, and give me any feedback you have along the way.

TreeManager CFC Released

I put together this component a while back, intending to eventually
release it, and it's now time.  Basically it manages a tree of
records in a databas table using the nested set model.  It acts
independantly of your existing persistance operations, and only
requires the addition of two fields to your table for it's use. 
You continue to manage your rows as you do right now, completely
ignoring the two extra fields, and then when you need to do tree-based
operations, you call the tree manager, and it takes care of all the
wizardry.

Included
in the zip (link below) is a very simple
application that creates a table, populates it with a bunch of data,
and then uses the tree manager to create a hierarchy out of the
records.  It doesn't really illustrate any of the action methods
in the component, but I wanted to get it out while I was on a role, and
didn't figure I'd ever finish if I tried to write a complete
example.  However, complete documentation is included, and the CFC
itself is fully commented.

So enough boring chit-chat, here's the code: 

http://www.barneyb.com/web/static/treemanager.zip

I've
only tested it on CFMX 6.1 and MySQL 4.1.  I know it won't work on
database other than MySQL 4.1 and higher (because there are a few LIMIT
clauses), but porting it to other DBs should be relatively
trivial.  I don't have access to anything else, so I can't do it,
but if you feel so inclined, please send me a patch so that I can
integrate it into the distributed version.  And you needn't
understand the nested set model to hack the SQL, most of the queries
are pretty simple, it's just the amalgamation of operations that does
the magic.

There is no license, so do what you will, though I'd
appreciate credit of some sort if that's appropriate for your
application. 

More J2EE Goodness

I recently needed to capture output for a page to email, as well as
actually output it to the page.  No big deal with CFSAVECONTENT,
of course, but there was one little glitch: occasionally, the core code
needed to use CFFLUSH, and in those cases, the email wasn't needed,
just the screen output.  Rather than screw around with separate
page rendering mechanisms for the two different approaches, a quick
look at the JSP spec yielded this little gem:

getPageContext().getOut().getString()

This returns the contents of the current buffer.  Note that
it's context sensitive (i.e. if you call it within a tag, it'll return
the contents of the buffer for the tag's body), and there's the
potential for the getString method not to exist, since
it's defined in the BodyContent subclass of JspWriter (what getOut actually returns) that is
used for tag-body buffers.  However, CFMX 6.1 seems to treat the
top-level page as a tag body, so it seems safe to use.

So to
solve my problem, I render my page just as normal, and then if an email
is needed, use that mechanism to pull the contents of the buffer and
send it off. 

The MySpace.com Cowboys

I've been at CFUNITED all week, and based
on the amount of blog coverage that's occurred without my help, I
didn't feel compelled to post.  However, the day three New Atlanta
/ MySpace.com keynote was an amazing talk that couldn't go without my
opinions being expressed to the world.

First, some background.  MySpace.com is a huge
CFML site that has recently moved from CF5 to BlueDragon.NET. 
They seem to be the centerpoint of New Atlanta's marketing efforts, at
least for the CFUNITED crowd. 
They get about a bazillion hits a day, and have had lots of problems
scaling their infrastructure and codebase over the crazy growth curve
they're on.

However, after listening to one of the
Directors of Something Techical speak at the keynote, it's not hard to
see why they have this problem.  He said several times that they
often push code two, three, four times a day.  They don't have
separate development, staging, QA, and production server
infrastructures.  They don't scale their server architecture, they
just increase it's size (which sounds similar, but is quite different).

One of the specific problems he
mentioned was unsufficient throughput of their database drivers on CF,
specifically that the database servers couldn't handle more than X
connections, and that if you have Y server, you're necessarily limiting
each server to X / Y connetions.  With a huge web farm, that might
mean X / Y is only 5 or so connections, which greatly cripples the
throughput of the web server.  So how do they solve it?  Not
build a more scalable database infrastructure that can handle more
connections (something that I understand MS SQL Server can do easily
with replication and distributed servers, though I've never actually
done it).  They switch to ADO.NET native drivers, rather than the
JDBC drivers that CF uses.

I don't want to rail MySpace.com too much, but I couldn't pass up the chance to share my amazement such that a huge
site does things in such a ridiculous way, and then complains when they
have problems, and looks for a solution to the symptoms, rather than a
solution to the problems.  The moral of the story, of course, is
that your infrastructure (both server, and development processes) is vitally
important.  And unfortunately, that kind of cowboy attitude
reflects rather poorly on New Atlanta, since they seem to consider
MySpace.com to be such a core part of their marketing efforts.

And
to round out some context, I originally had no intention of going to
the keynote, because I figured it'd be an hour of New Atlanta doing
MS's marketing for them.  However, I was pleasantly surprised to
see a truly legit case study from a real client, solving real-world
problems, and it wasn't overtly sales-pitchy.