I always seem to have many ideas for (small) projects but never enough time to get to the things that I want to do. I guess it's all about timing and priorities. Many of the ideas are for small projects that are stepping stones to bigger and better ideas and projects. I've written a lot of (bad) code over the years (and here is some more!), but some of the simplest ideas and code is still in use many years after initial implementation without any subsequent modifications or bug fixes. So, I figure if it's useful to me, it might be useful for other people and thus I should share the things I work on in case they are useful in any way -- even if it's to show how not to do something. Code may look great when it's being done, but then when it is looked back upon at a later time, it can be seen in a new way due to more experience and skill and sometimes makes the coder wonder what they, themselves, were thinking at the time. Yet, at the same time, with coding as it is today, just getting something working is still not always so easily done.

It seems the web is here to stay and it's already pretty ubiquitous, so it seems like a decent channel for distribution. The only thing is, in my opinion, maintaining websites is really, truly, honestly, mind-numbingly boring. Due to wanting (needing?) to use the web for distribution and yet not wanting to maintain web pages and sites, I decided to work on a few experiments and programs to make an application to help take away all the tediousness and annoyances I personally find in maintaining web pages and sites. OF course, there have been other things designed to just allow distribution whether it's some pre-made forum, wiki or CMS, but the idea here was also to learn as I went along. And, of course, this application certainly won't help with CSS and that nightmare, but not having to update a site's worth of pages just to add a tag seems like a wonderful thing, at least to me.

The idea behind cs3web is to have a small and quick to write C++ program to assemble web pages and web sites. Of course, nothing stays truly simple for long, especially when dealing with something as complex as what this application intended to do. The intended design of a site is to make "dynamic" pages from a database (sqlite3) where the assembler program is not a daemon and doesn't "cache" between invocations. Caching may be done external to this application. Additionally, the intention is not to write a full C++ program for each and every website to generate truly dynamic content and interactions, so the pages themselves are "static" but they are put together in a "dynamic" way. Finally, javascript will be used in conjunction with AJAX to provide for true dynamic data. This will become clearer as the application is explained.

Therefore, with few exeptions, all "sites" hosted by Neurillion will be served via cs3web. The software was developed on Linux and tested with Apache 2.0.x.

The code will also evolve as new issues arise and as I learn more about C++ and techniques and best practices. There is absolutely no claim that any of the code is worth anything at all more than the lessons learned while writing it (please see the disclaimer). I suspect that many of the objects will be redesigned along the way -- such is the fun of Object Oriented Design!

Each distribution has a README and INSTALL file, although each is probably very minimal. If you have any questions, please send feedback with your question[s].

How To Use

Basically, cs3web is used to set up small sites quickly. Although I have tested the program using no prefix, the preferred configuration is to use a prefix. What that means is instead of just "" the URLs would be something like "" ... where "x" could be anything like "x" or "html" or "web/page" etc. This "prefix" becomes the default script name for the site. The reason for this is to allow top level URLs to be accessed without having to address (ie: alias) each one in the web server config (ie: Apache's httpd.conf). Specifically, URLs such as "/favicon.ico" "/icons/" and "robots.txt" and others would have to be taken care of via individual exceptions in the config. So, by using the prefix, it isn't necessary to make these exceptions in the config file.

Although my preferred implementation aliases a "/static/" path to circumvent the script, this wouldn't match for things at the top level. Additionally, by using a script prefix, this application may be dropped in place on an already existing site and will not affect the site's current operation for either hosting all new pages, or will pages are migrated over. The default script name that is configured for each web server will be replaced with a standard string "/html". This means that it is possible to set up keys in the database such that a copy of one site's database to another site's database and then a few modifications will allow an entire site to be set up in seconds. cs3web does not currently have a "search and replace" function for values in the database, but this feature may be added at a later time.

So, for example, the cs3web site is Project 46 at Neurillion and uses the prefix "/p/46/". The database has keys without the prefix such as "cs3web" so that this key may be used on various pages, as well as keys that begin with "/html/" and are this accessible via the web directly. To reiterate -- all URLs containing the prefix will run the cs3web application and then have the URL prefix (ie: /p/46/ in this case) changed to "/html/". The words without the prefix are used as "safe" tokens as they can't be accessed directly via a URL and may only be accessed via via the cs3web application itself.

When cs3web is assembling a page, special tokens in the form of <$...> are operated upon. The basic operation is to look up the word after the $ and before the next > as a key in the database. In this way, a page with the key "/html/homepage" may have the token <$cs3web> and then "cs3web" will be looked up (ie: as a safe token) and the value, if any, will be used to replace the entire token from the first < to the next >. One advanced feature is that a token may reference a key from another database using the suffix "@database" such as with <$copyright@default> which will look up the key "copyright" in the database "default". The name "default" is arbitrary, but the concept remains the same.

So, as a technique, each site could have a token <$footer> which would look up the value of the key "footer" in the current database, but if that key had the value of <$footer@default> then the value of the key "footer" would be looked up in the database "default". This allows for a type of "double hop" where each site first looks for a value locally, but then is instructed to look in another database. The reason for this is two-fold: First, if many sites are hosted via cs3web and they all do this, this it is possible to modify a single database entry and update multiple sites and secondly, it allows for each individual site to have a site specific value put in place that would take precedent over a site-wide default.


DB HTML and "Dynamic" Static pages

As was discussed above, the primary purpose of cs3web is to assemble web pages on the "back end" of the webserver and then let javascript and AJAX provide for truly dynamic content on via the "front-end" of the web browser. In this way, cs3web balances not becoming too specificly tied to a single site, yet still allows for powerful page generation.

The simplest mode of operation is just looking up a web page in a database as specified via a URL. The next step up is to use "safe" tokens that can't be accessed directly via URL as substitions in pages. For instance, if the footer is going to contain the same components for the entire site, a key "footer" could be made an each page would have the token <$footer> in its source. In this way, since pages are not cached by cs3web itself, any change to the value of the database key "footer" would instantly be visible on any page loaded from the site.


Simple tokens: <$word>

Look up the value of "word" and replace the entire token from the first < to the next > with the value of the key "word" (if any).

Redirect tokens: <$@URL>

Stop all processing and output an HTTP header with a "redirect" status to the location of "URL". This causes only the header to be returned to the client, absolutely no (HTML) body will be sent.

Conditional tokens: <$?word1 word2 word3>

Look up the value of "word1" and if there is any, then replace this token with the value returned from looking up "word2" -- otherwise, replace this token with the value returned from looking up "word3". For example: <$account login@default admin@default>

Stop processing tokens token: <$>

This is a special token used to instruct cs3web to stop processing tokens. Currently, this is only used in the "edit" page and it may, in fact, not have practical use anywhere else.

Command Line

/www/neurillion/exec/cs3web -h
Usage: /www/neurillion/exec/cs3web [options ...] [pagename]
-b database     set database
-c column       set column
-d page         delete page "page"
-e page         edit page "page" using $EDITOR
-h              help (this information)
-l              list keys (in database)
-r path         set root path
-- ...          stop processing command line options