Tuesday, July 25, 2006

Dynamically add/subtract upload fields to form: Chapter 2, the backend

In the previous chapter, we covered what it takes to build XHTML-compliant dynamic content inside a webpage. One of the things we did not do was use some kind of input element name iteration. We don't need to.

Let's reconsider the way the name attribute behaves in HTML forms. While it's true that XHTML deprecates name in favor of id in most situations, inside forms name still serves a critical function: defining a collection of noncounted elements.

Forms are all about collections: checkboxes and multiple selections inside a select box send collections to CGIs. When multiple checkboxes inside a form share the same name, they send their values as a collection. Checkboxes are input elements, and so are file uploads. In other words, an array.

Lincoln Stein's CGI Perl module is capable of handling these arrays, and has been since version 2.47. The mental block here is assuming that CGI's param method only returns scalars. Fortunately, it doesn't. The problem, however, is that Stein's own documentation says the following:
To be safe, use the upload() function (new in version 2.47). When called with the name of an upload field, upload() returns a filehandle, or undef if the parameter is not a valid filehandle. In an list context, upload() will return an array of filehandles. This makes it possible to create forms that use the same name for multiple upload fields. This is the recommended idiom.
This would be beautiful, if it were true. Unfortunately, it is not. param() returns lists, upload() only returns the first member of the list passed to it. I mention this here because forum posts indicate this has been a land mine for many since upload() was introduced a few years back. So, if all the potential upload inputs have a name attribute of 'mypix', the following neatly harvests them:
@mypictures = param('mypix');
The array sent to param() is merely the upload filenames as filehandles -- to which various methods return metadata for preprocessing. uploadInfo($file)->{'Content-Type'} returns the MIME-type, tmpFileName($file) returns the path to the actual file on the server, and there are others you'll see.

First, a bit of housecleaning. The array param() returns is obedient and dumb; it will contain blank elements for every unused input field or those filled with nonsense text instead of filepaths. We can neatly purge these with a single statement:
@mypictures = grep {$_} @mypictures;
The expression tells Perl to return the results of a regex search against non-null members in @mypictures. No second temporary array, no loops. $_ can be your friend. (FYI: your browser is the one purging the nonsense fields, not CGI.pm)

Dynamically add/subtract upload fields to form: Chapter 1, the frontend

The assignment: create a webpage which permits faculty to upload digital course reserves materials, using XHTML frontend and Perl backend, then attach those uploads to an email sent to a clearinghouse mailbox.

The complications:
  1. backend needs to be agnostic towards how many uploads are being sent, preferably no iteration over numbered input name attributes
  2. frontend is proper XHTML, therefore adding new input elements can't use document.write JavaScript methods

Let's deal with the frontend first. XHTML deprecates document.write because it breaks the idea of XHTML as a properly formed XML document: anything could be inserted into your webpage no matter how well or poorly formed it is. If I'm not mistaken XHTML served as its correct MIMEtype results in browsers throwing errors when they encounter document.write.

Fortunately, XHTML nominally being XML, it supports XML's methods for inserting, removing and changing internal content. Let's take a look at some sample JavaScript:

Thursday, July 06, 2006

Everything old is new again, or: the future of OS X.

An anonymous poster on Slashdot who claims to have friends in high places in the OS X world makes an interesting speculation on the future of Bootcamp and Windows on Macs. While his contact refuses to say specifically what Apple intends, it's not difficult to read between the lines:
Getting to the point, talking to the guy and asking him about the possibility of using my Windows skills to port applications using WINE but with a translated front end on the Mac side. [snip] His response was one of the most direct responses I've ever gotten about future plans without him saying anything. Claimed to have looked into WINE, had it running internally ... and he said that while it was a good product, they weren't going to use 'compromised' APIs to do this. When asked if they had any plans to license or develop any of their own non-compromised APIs, he responded that there was no plans to license anything. It was a pretty strongly worded statement, especially when looking into the point by point claims and what was missing from my original query.

On my G5, Classic runs inside the same partition and shares a similar filesystem to OS X -- by design. Nevertheless, it shares common elements with OS X: the menu bar, the Trash, and a common paradigm for the window GUI even if the chrome is different. X11 lives in what another /.er calls the "penalty box" -- its UI is too decentralized and unpredictable to translate all menus to the top of the screen, so its interface can't be Aqua-fied.

Enter Windows XP. A completely documented API per the 1997 agreement with Microsoft (which granted Apple total access to the Win32 API until 2002, the year after XP came out), and now Macs have dual Intel processors. It doesn't take much thinking to imagine the second core running XP inside the Windows partition: no hassle of translating Windows apps' expectations of a C:/-based filesystem to the Apple-flavored BSD filesystem, and more importantly, it sandboxes inept and malicious applications' behavior to that partition. If you need to share a file, OS X reads (and writes) NTFS. This last point isn't trivial: Linux is still battling the ogre of full read/write support for NTFS and its partitioning utilities won't grow an NTFS partition.

It isn't virtualization, at least not like we know it. Let's go back nine years to a column from 1997, the year of the Apple/Microsoft agreement:


Remarkably, Apple is running ahead of schedule developing Rhapsody and has already shipped its first developer release and blue box release. (Microsoft, take a hint.) Rhapsody will run on at least two hardware platforms: PowerPC and Intel. It's based on the Mach Unix kernel, either version 2.5 or 3.0. It will allow different levels of OS compatibility, allowing use of the Mac OS and Windows on a Rhapsody core. Remember that the Mach kernel is underneath everything. Symmetric multiprocessing is integral to the kernel, which means that Rhapsody applications will be able to take advantage of multiple processors.
  1. Rhapsody for PowerPC, a PPC-native OS with Blue Box support for Mac applications.
  2. Rhapsody for Intel, an Intel-native OS with Red Box support for Windows applications.
  3. Yellow Box for the Mac OS, an environment for running Rhapsody applications on a Power Mac.
  4. Yellow Box for Windows, an environment for running Rhapsody applications on a Windows-based computer.

Suddenly, Apple ditching Classic and their continuing support of Mach despite its recent performance speed comparisons makes a little more sense. Blue Box is what currently runs Classic apps on PPC Macs, and capably.

As you can see, this is not virtualization. It's Red Box: XP in place of Classic, running on the second core, APIs gently tweaked to put menus and system tray items at the top of the screen. I suspect this has been in the works for longer than The Switch: in the three years since Apple started selling dual G5s, the amount of Apple software actually exploiting the second processor is minimal at best. In retrospect, an x86 emulator seems like the most likely reason for the spare processor on those doomed PPC platforms, at least until IBM sucker punched Apple by removing the endian-switch register VirtualPC depended on.

Where pundits are right on the money is XP compatibility's impact on Vista: Apple extending the lifespan of XP dilutes Vista's urgency. In an amusing way, this is actually good for both Apple and Microsoft in the mid-term. It makes a Mac more attractive to people who might otherwise complain it doesn't run their favorite games or whatnot. It also buys Microsoft more time to revisit Vista and perhaps negotiate with Apple over how Vista could work as a client OS inside this environment (selling more Vista licenses in the bargain).

This raises an interesting question, however. If Apple's had Red Box in its back pocket all this time, why encourage Boot Camp?