Introduction
I needed a web development platform to do the impossible. As a single developer I needed to rapidly assemble a large web application in a very short time. Furthermore I knew that I would be developing the programming while others would be commissioned to do the art design, and that they would need to be able to use the HTML & graphics packages with which they were already experienced. I needed to incorporate a flexible object architecture: I knew that the same components would need to reappear on different pages, at times with varying forms. What's more, like all web projects, I knew that this one would need to continue to evolve as our site matured and userbase increased. I'd had enough experience writing CGI to know that program navigation in a stateless environment becomes a convoluted mess without some higher structure to assist the programmer. In summary I needed:
* a rapid prototyping and deployment tool
* with simple to create and use reusable objects
* objects need to be able to change according to their context
* the entire project will be need to be able to be edited in
Frontpage, Dreamweaver or the like and preserve its object
structure
* the project needs to be based on portable, opensource tools (I'm
cheap and don't know where this will end up)
* it needs to be fast enough to support lots of users on
economical hardware
MySQL proved to be an appropriate backend component for dynamic data storage. PERL was where I wanted to base development.
After quite a few theoretical forays I settled on the following language description.
The JMH Web OBjects Language (wob)
I should begin by saying that my objects are not true objects in the OOP sense. What they really are are reusable, context-overridable html/perl subroutines which can survive being edited in a wysiwyg html editor.
The entire project file is written in an HTML authoring environment, Frontpage or the like. When rendering, page properties are taken from the properties of the HTML document.
A WOB HTML document contains a series of object definitions separated by ###objectname. The first object is treated as the base object which all other objects will modify or redefine completely if necessary. However, the first object is treated as the default object. The last object in the file must "end" and is used to produce the closing HTML tags; it can also include material you want inserted at the bottom of every page no matter what.
If an "init" object is defined, it is executed when the wob system starts. This is especially useful for establishing database connections and initializing global variables.
Object names must start with a letter and can contain a-z, A-Z, 0-9 and _. The object file is scanned for links (either go=ObjectName or name="go" value="ObjectName") and these files are classified as public access. If any other object is attempted to be called through CGI an "access denied" error will be generated. The first (default) object is also classified as public access..
Objects contain HTML, wob-perl, variable references, references to other objects, and object redefinitions with the following syntax:
* ->ObjectName -- generates a href link to
ObjectName
* <a href="?"> -- the name of the script is
substituted in before the ? -- it's assumed you'll add some cgi
parameters following the ?. For example <a href="?go=ObjectName&size=6">
will make a link to ObjectName and set $size to 6. Objects
referenced this way get classified as public access.
* &ObjectName -- In HTML this is an object reference. Like a
subroutine call, this object is executed at this point in the
HTML file.
* $variable -- The value of the session variable is inserted here.
These values are preserved per user according to session rules.
Sessions are cookie based and expire after 120 minutes of unuse.
Session data is stored on the server.
* $_localVariable -- This is a perl global whose value is not
preserved with the session data.
* $SQLfield -- the "field" field from the last SQL
expression is inserted here
* `` #perl script goes here `` -- Any valid perl material can be
inserted here. <p>, </p>, <br> are removed and
> < & are replaced with their
corresponding values. The assumption here is that the perl is
being written in the HTML editor environment. $variable and $SQLfield
substitutions are made. &function is not touched.
* <script language="wob">#perl script goes here</script>
-- like above, but HTML conversions (<p>... and <...)
are not made.
* !!ObjectName; -- within a script this is the proper notation
for a object reference.
* [sql statement here;] -- wob-perl calls the default DBI
datasource (the first ->connect reference in the project file)
with the enclosed SQL. Note that the semicolon and closing
bracket cannot be separated by white space. The result hash is
returned or false on failure. The result hash is usually
referenced with $SQLfield syntax.
* delete $variable -- It is beneficial to delete $variables when
they are no longer needed -- this shortens the session data. This
is especially important for large items (text uploads for example)
* $_insertid -- contains the last Mysql AUTO_INCREMENT value
* private $var; -or- private $var=... -- dissallows $var from CGI
input -- only your code can set this value. This is important for
markers for being logged in, etc.
* $_sqlresult -- contains the results from the last sql execute,
usually the number of rows affected.
* $debug -- if 0 or undef no debugging; 1 shows session data and
redfines; 2 shows all item calls -- you can put &debug=2 on
the URL line to turn on debugging. Disabled (commented out) in
compiled version.
* #insert filename -- inserts the content of filename into the
current file, stripping off html header (... <body>) and
</body... -- Note the filename must not contain spaces, even
if quoted. The name must include an absolute path.
* #include filename -- same as #insert
* Autoquoting in [ ;] sql constructs -- if you have the structure
'$variable' (single quotes with just a variable) in a square
bracketed SQL statement, the contents are automatically quoted
for SQL so you don't need to use the ->quote($string) operator.
Object redefinitions require a bit more explanation. When an object is called it can redefine any other object. This behavior has nearly unlimited potential in structuring your program. For example, a login object verify a password and either report a login error, or redefine certain objects to give access to protected objects. Another typical use is to have the default object contain a series of standard objects (eg topBar, leftBar, rightBar, centerPaine...) which have default definitions, but which are redefined by externally-accessible objects.
With the current implementation redefinitions are not carried in the session. This means that each rendering starts from the default state.
Object redefinitions take effect at their point of definition. The syntax is ##objectName at the beginning of a line. Note this is two ## instead of three ### as for the object definition. Redifinitions carry to the next object definition or redefinition. Most redefinitions will redefine lowercase-named objects.
The package also include a few useful functions:
* "e4url($string) -- returns a string
suitably quoted for use in a href.
* &badlanguage($string) -- returns a non-null string if $string
contains rude language. The return value is the first offensive
word found.
* &clearsession -- resets the session data. This is
particularly useful as part of a LogOut object, or if you want to
manually expire the session.
* &wf($filename,$content) -- writes a file named $filename
full of content $content
* &rf($filename) -- returns the content of file $filename
* &autoformat(text) -- changes plain text to html with some
degree of smarts
How WOB Works & Deployment
The program works by parsing the wob html file into a perl script. In the development phase this script is simply eval'ed, but for deployment the script can be wrapped and executed as a stand-alone perl cgi script. Similarly it can be easily modified to work with speedy-cgi, mod-perl or fast-cgi for higher performance systems.
Instalation
Download the current source file from http://wob.sourceforge.net/wob.txt. Rename it to wob.pl, move it to an appropriate location, and mark it executable (if you want). Create a CGI executable shell script like this one:
Of course your perl path, wob.pl path and MyWobFile.wob should be replaced by actual paths.
Edit the wob.pl file to set the following globals to appropriate values:
CompiledOutput should be a filename and path to put the result perl script, as is mentioned in the Deployment section above. sqllog is used for debugging -- leave it blank if you don't want to log SQL requests and responses; set it to a file & path if you want to inspect them for debugging purposes. You sould make it blank for deployment. _sid_base is a directory to put session data files and must be writable by your web server process.
You should now be ready to try your cgi script.
Limitations
At this point CGI parsing is limited to text only data. Actually any data is ok except \001 - \002.
Since wysiwyg html editors often wrap text automatically, new lines are often undesirably inserted into `` code segments. Comments are especially problematic, but any strings where the formatting is significant can be affected. Use the <script> construct instead as a workaround.
Example
What follows is a brief example to show what a basic WOB file might look like.
###Default
&TopLeft | &TopCenter | &TopRight |
&Left | &Center | &Right |
This text appears on all pages which don't override Default. :-)
###TopLeft
###TopLeft
###TopRight
Brought to you by WOB
###Left
->Choice1
->Choice2
->Choice3
###Center
This text will end up in the center frame portion by default.
``$count++;`` The count is now $count.
###Right
Context
Sensitive
Material
Here?
###Choice1
##Center
Choice 1 will redefine the title to be Monty-Python-esque
##TopCenter
###Choice2
##Center
etc...
License
Copyright (C) 2000, John M. Hanna. The WOB components may be distributed under the terms of the General Public License (GPL). THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
ToDo (Comming Soon)
A secondary script to hide & unhide ``
scripts into <script> format
Auto-quoting of sql variables -- important for security.
Option to preserve redef overrides in session.
Form validation, success, cancel processing
Example code snippets file.
Script to find use of uninitialized $_xxx variables (mod_perl
compatibility).
About the Author
John Hanna is the e-media coordinator at Caleb Project, a non-profit Christian organization. <jhanna@cproject.com>
updated 00-06-19