space Baylys
Just practicing to pass the Turing test.
space
space
space
space
Developer for Hire!
space
addedValues Plugin
space
space
Join Now
Login
space space space

URLchains Suite

Abstract

One of the hidden mechanisms of Manila websites is the urls table. It can be a useful mechanism for head and tail patching key Manila scripts called from each website by , for example, Manila plugins. However , if multiple clients attempt to to use it this way they will interfere with each other unless the management protocol is moved into a distinct module. urlChains is that module. This paper describes the protocol it implements and is unlikely to be of much interest to anyone except advanced developers of Manila plugins.

The URLs Table

Every new Manila website has one, it is copied from the website template at site creation time. It contains more than 50 entries with names such as newsHome, editorialNewStory and gemPostMessage. Their value is the url for predefined pages in the containing website for example, the home page, the page that displays a new story form, and the response page when a gem is posted. Most of Manila tends to use these values when constructing forms, re-direction urls and more. This is made convenient because the urls table is stored in the page table under the name #urls, so to the underlying rendering engine its is seen as a directive, and an address entry is inserted into the page table with the name urls (the leading hash is stripped).

Example

When Manila displays a story to an Editor, it builds a small form that displays the Edit this Page button. Lets suppose that the message number of story that is to be displayed is 17. Note also that the conventional variable name for the page table in Manila scripts is pta;, a convention we adopt here. The action url of the form tag must be appropriate to direct a hit that indicates a click on that button to the script that displays message 17 The Manila scripts that build the form with the Edit This Page button at the end of a story, can find the appropriate url at pta^.urls^. discussEditInBrowser and append 17 on the end to end up with an actual url such as

http://www.baylys.com:8080/discuss/edit/editinBrowser$17

If you look inside a Manila website table on your server, and knowing that the first part of the url has been used to locate the website table - baylysManilawebsite - you can see how the rendering engine can use the remainder of the url to locate the script within that website table at baylysManilaWebsite.discuss.edit.editInbrowser.

Exploiting the Mechanism

The idea is to call a script that does its work before and after the standard Manila script runs. To continue the example, let's suppose we want to place the text "Bayly was here!" adjacent to the submit button in the edit page. We do this by changing the action url that the Edit this Page button form, so that it goes to another script in the website table, such as one installed by the manilaFixer plugin at baylysManilawebsite.manilaFixer.discuss.edit.editinbrowser. To achieve that it is enough to change the entry in the urls table to the matching url

http://www.baylys.com:8080/manilaFixer/discuss/edit/editinBrowser$

Now when Manila builds the edit this page button appends the message number, 17 on the end and we have subverted the form. Clicking on the button will end up in the new script, which has to have the same parameters as the original. .Typically that script will call the original script, sometimes as in this case that isn't possible because the entry at discuss.edit.editthispage is not a script , it's a wpText. It does however call a script in the Manila suite, so provided one takes care to replicate the effects of the directives in that wpText, you can call the script it calls as a macro. For example,

on editInbrowser()
//do our thing before the mania script does
local (pta = html.getPageTableAddress())
pta^.title = manilaSuite.discuss.getEditTitle ()
pta^.autoParagraphs = false
pta^.addLineFeeds = false
local (htmltext = manilaSuite.discuss.editInBrowser ())
// now do our thing after manila has built the page;
bundle //logic to put Bayly was here left as exercise to the reader :-)
return htmltext

The Need for a Protocol

This technique works fine as long as only one client is doing it. But if a second plugin made a similar change to the urls table at discussEditInBrowser, only the latest client to do that will actually get its script called. We need a way to allow multiple clients to do this transparently, and this leads to the notion of url chains. To achieve the desired result, the second client must call not manilaSuite.discuss.getEditTitle, but baylysManilawebsite.manilaFixer.discuss.edit.editinbrowser, which then calls manilaSuite.discuss.getEditTitle. So it needs a way ask for the address of a script that corresponds to the url of a urls table entry. If you think the problem through, each element in the chain needs to find the address of its predecessor. There needs to be way to add and delete entries from the chain of scripts, and there needs to be a distinct chain maintained for each entry in the urls table. This is what the urlChains suite does.

The protocol

There are 4 key scripts; listed here for completeness. If you are developing at this level you don't need an explanation of how they work.

Call linkAdd from your plugins enable script; once for each entry in the URL table you wish to subvert.

on linkAdd (adrSite, urlID, myURL, flCallFirstAlways=false) adrSite - address of the site
urlID - the name of an entry in the sites #urls table. If it does not exist, it will eb added for you
myURL - the replacement url. It must point within the site and map to a script.
flCallFirstAlways - true if this needs to be the first in the chain. Only one caller can do this for each urlID. A conflict causes a script error.

Call linkDelete to undo subverting a URL tables entry.

on linkDelete (adrSite, urlID, myURL)

Call getNextScriptAddress to find what script your subverting script should call; for example if you override Manila discuss.edit.editInBrowser ; you will want to call it as a basis for your own response; but you don't know if some other plugin has interposed itself in the chain, so instead call getNextScriptAddress.

on getNextScriptAddress (urlID)
urlId is a the name of the entry in the #URLS table

Call getNextScriptAddressAtURL to find what script your subverting script should call; relative to the script addressed by the url. This is needed when addedValues validates a post of an edited message, rejects the input and wants to re-construct the form. It cannot start again from the editInBrowser urls table entry, so it calls this script.

urlChains.getNextScriptAddressAtURL(URL)

Installing the protocol

Version control of the suite is critical. My approach is to store the whole suite in my plugins data table and at install time; call mypluginname.data.urlChains.installMe which will update the suites table entry or not, as determined by the suites version number. .

Public Domain

This is an open project; I make the protocol and the suite freely available - I'm open to suggestions on distribution. If there is demand, I will do something elegant. For now just send me an email for a copy of the suite. I will be shipping it in the addedValues plugin and some of my other plugins, so it can be copied from the table at addedValuesPi.data.urlChains.