Frontier Tutorials / Writing an ObjectNotFoundHandler / Bonus: The "Penultimate" Master Script

Bonus: The "Penultimate" Master Script

This page is a Fat Page. It includes the "ultimate" ONFH master script, encoded by and for Frontier. To retrieve the script(s), save the page as source text and open it using the File->Open command.

This page contains a more generic version of the master script presented on the Misdirected URLs page. Here's the script:

« #navTitle "Object Not Found"
« ObjectNotFoundHandler Master Script
pageTbl = html.getPageTableAddress()
toolsTbl = pageTbl^.tools
« Parse searchArgs (if any) into temp args table
local ( tempArgs )
new ( tabletype, @tempArgs )
webserver.parseargs( pageTbl^.searchargs, @tempArgs )
if defined( tempArgs.whatObjectNotFound ) « Is this the redirected call?
« This is the redirected call; make Mode 1 return.
pageTbl^.title = "Page Not Found"
pageTbl^.code = 404
if defined( pageTbl^.notFoundText )
« Put missing subpath in page table for inclusion in #notFoundText
pageTbl^.whatObjectNotFound = string.nthField( tempArgs.whatObjectNotFound, "/", 1 )
return ( html.processMacros( string( pageTbl^.notFoundText^ ) ) )
scriptError ("Can't process the request because there is no object named \""
+ string.nthField( tempArgs.whatObjectNotFound, "/", 1 ) + "\".")
toolsTbl^.PageNotFound( pageTbl )
bundle « Mode 2 & 3 ONFH scripts
« Mode 2 & 3 scripts are assumed to return if unsuccessful, but not if successful.
« As a result, we can simply call them one after another.
« Assume that the scripts are in ["#tools"].ONFH_2and3
if defined( toolsTbl^.ONFH_2and3 )
numHandlers = sizeOf( toolsTbl^.ONFH_2and3 )
for idx = 1 to numHandlers
entryAdr = @toolsTbl^.ONFH_2and3
while typeOf( entryAdr^ ) == addressType
entryAdr = entryAdr^
« URL not handled by Mode 3 scripts; do Mode 2 redirect so we can do Mode 1 return without bogus URLs.
myDepth = sizeof(string.parseaddress(this))
nomadDepth = sizeof( string.parseaddress( pageTbl^.lastnomad ) )
targetDepth = string.countfields(pageTbl^.remainingpath, "/")
goUpLevels = nomadDepth + targetDepth - myDepth
relPath = string.filledstring( "../", goUpLevels ) + "nonexistent"
scripterror ("!redirect " + relPath + "?whatObjectNotFound=" + string.urlEncode( pageTbl^.remainingPath ) )

Only the block where the script calls Mode 2 and Mode 3 scripts has changed.

Instead of explicitly calling each subsidiary script from within the master script, it looks for them in a subtable of the #tools table named "ONFH_2and3". It expects each entry to be either a script or an address that can be resolved to a script.

As a result, you can install and remove ONFH scripts without modifying the master script in any way.

Directions For Use

Install the master #objectNotFoundHandler script from this page in your website.

Create a subtable in your #tools table named "ONFH_2and3".

Copy Mode 2 and Mode 3 ONFH handlers (such as the Bonus handlers in this tutorial) into the "ONFH_2and3" table, or enter the addresses of such handlers in the table (e.g., @xfile.mainResponder.ObjectNotFoundHandler).

If you desire, you can create a #notFoundText entry (directive) in your site (or multiple ones at various levels). If you do so, this script will insert the missing path in the page table as whatObjectNotFound, to make it available in #notFoundText. It will then return the text of #notFoundText, after calling html.processMacros on it. For the #notFoundText entry shown in the Mode 1 Example, this would create a hot-link to the site outline (if there were one) and expand the "{whatObjectNotFound}" and "{string( forms^.search )}" macros we inserted in the text.

If you do not create a #notFoundText entry, this script returns a very simple file-not-found page text.

Why Penultimate?

The technique described here to create an ONFH script that works within Manila sites was devised by Jason Levine, and presented in his article, Manila and #objectNotFoundHandler. See that article for a full discussion of the technique.

I call this the penultimate script because it omits something: it doesn't support operation within Manila websites. Because Manila uses an ONFH for its own purposes, you would have to modify this script for use in Manila websites.

In short, the modified script will follow this pattern:

try « Give Manila first try
return ( manilaSuite.hierarchyPage() )
if tryError beginsWith "!"
« It's a special scriptError--pass it on.
scriptError( tryError )
« Do your own ONFH processing here.

For a full discussion of why this is required and how it works, see Jason Levine's article, Manila and #objectNotFoundHandler.

Another bonus script: a utility script for creating Mode 3 ONFH handlers.

Tutorial Contents
Writing an ObjectNotFoundHandler
ONFH Overview
ONFH Modes of Operation
About The Examples
Mode 1 Example
Mode 2 Example
Mode 3 Example
Mixing Modes
Misdirected URLs
ONFH Summary
ONFH Resources
Bonus: The "Penultimate" Master Script
Bonus: Mode 3 Utility Script
About the Author