cdServer is designed to be a stand-alone application with minimum requirements
for external support. The only additional requirement is a minimum Python
installation (interpreter and libraries).
1.1 POSIX (Unix, BSD, Linux)
On most Unix-style workstations Python is installed by default. If this is not the
case contact your system administrator.
Unpack the cdServer archive (.tar.gz file) and you are done. To start this demo
open a terminal, change to the bin
directory and start
Windows machines usually don't have Python installed. Therefore it is necessary
to download Python. It is suggested to download Python from the main Python website
http://www.python.org/ as the original
distribution does not restrict commercial use.
Start the installation wizard and do a minimum install (interpreter and libraries only).
In order to utilize this demo to its full extent it is necessary to install Python in
the bin/python/ subdirectory of this demo. The reason for this is explained below.
After the installation of Python the bin/python/ directory of this demo should look
something like this:
To start the demo double-click on file "autorun.bat". This will open a DOS window with
cdServer running and launch a webbroser with the initial URL
2 Windows Autostart
With the preparations described above the demo is (almost) ready to be auto-run on
Windows machines. Just burn the demo directory to a CD-R or -- even simpler -- copy
the demo directory to an USB memory stick and insert the CD / USB stick into a
Windows machine (USB requires Win 2k / XP). Make sure that the root directory of the CD-R
/ USB stick contains the following files and directories:
Voilą, the demo auto-runs off the CD / USB stick.
3 cdServer operation
Upon startup cdServer evaluates the options given at the
command line. All options default to a "reasonable" behaviour. See the
manual page for details.
Next cdServer tries to start an application (a Python module
named cdApp.py, see demo cdApp in file bin/cdApp.py). If the start succeeds the
application is supposed to provide a request handler which is used instead of
the built-in SimpleHTTPRequesthandler from the Python standard library (see below).
The application's request handler is in charge of intercepting special URLs
and providing additional functionality.
cdServer then starts a simple webserver based on Python's
built-in SimpleHTTPServer module in a separate thread.
When invoked without options,
cdServer serves HTTP requests through port 8000. In case port
8000 is already in use the server searches for an unused port.
The server's root directory is set to the parent directory of the directory
that contains the script cdServer.py, i.e. the main directory of this demo.
Therfore only files in and below the main directory are able to be served by
After launching the webserver the main thread tries to connect to the webserver
in order to check if a firewall is blocking local intra-machine IP traffic.
Subsequently the default web browser is launched with the initial URL pointing
to the webserver that has previously been started
(by default http://localhost:8000/). If the firewall test failed the browser
is launched with an URL pointing to the local filesystem instead and the webserver
After the initialization phase the server thread keeps running and cdApp's
request handler is in charge of serving all requests to the server. The
request handler analyzes the request, forwards requests for regular files
to Python's built-in SimpleHTTPRequestHandler and generates dynamic pages
for special URLs / pathnames, e.g. pathnames that start with '/func/' in this demo.
In this demo a request to '/func/exit_' sets a global variable 'end_flag' which is
inspected by cdServer after each request. If 'end_flag' is set to
a non-zero value the webserver thread and subsequently cdServer
terminate. This allows for the termination of the program by simply clicking on a link.
4 How to create your own CD applications
The sample application cdApp.py supplied with cdServer was
intentionally put into the public domain to give you a starting point for your own developments
without having to worry about licensing details. Just hack away with cdApp.py
and do with it whatever you like -- the sky's the limit.
Please keep in mind, however, that cdServer itself is licensed under version 2
of the GNU LIBRARY GENERAL PUBLIC LICENSE (see license for
4.1 Preliminary thoughts
It might be tempting to use the infrastructure provided by cdServer
to get the webserver up and running and to create all content dynamically from whatever
data you have. On a second thought, however, you will notice that this idea would lock
out an increasing number of Mac, Linux and other non-Windows users.
An alternate approach would be to convert as much of the content to static .html files
and to generate only those pages on the fly which are necessarily interactive. This way
your application -- except for the interactive pages, of course -- will be accessible
by non-Windows users as browsable .html file. This demo uses the latter approach and
incorporates a neat trick described below..
4.2 Layout of the CD-ROM filesystem
The design of your CD-ROM filesystem should not confuse users which -- for whatever reasons
-- browse the contents of the CD-ROM directly. The main directory should only the minimum
possible number of files and directories.
It might be desireable to have a copy of the main 'index.html' named
'START_HERE.html' or thelike to guide the 90% of us who would not know what to do otherwise.
If your application is multi-lingual it is a good idea that the main 'index.html'
provides a language selection and to create language specific first level subdirectories.
The cdServer script should be placed in a first level subdirectory
as cdServer.py takes its parent directory as its serverroot by default.
cdApp.py shall be in the same directory as cdServer.py so it can be imported without
errors -- remember you are creating a stand-alone system where your developer system's
PYTHON_PATH doesn't exist.
favicon.ico is a bitmap (.bmp file) which nowadays is requested by almost all browsers
automatically. Please replace my favicon.ico with your artwork.
All links to static files should be relative, i.e. ../images/image.png instead of
/images/image.png. By using relative links your application is not only
easier to debug, it will be independent from any location / drive letter where
it is accessible via the filesystem.
4.3 Diving into cdApp.py
The easiest way to find files in the CD-ROM filesystem, e.g. a database which you might want to read
into memory during initialization, is to get the current working directory which is
identical to the serverroot. From there your file(s) is/are only a couple of os.path.join()s
away. It is safer to use os.path.join() that to concatenate with "/" as path delimiter.
Let Python do the work -- it usually knows better than you.
cdApp.py is supposed to provide a subclassed SimpleHTTPRequestHandler which implements
your special functions. Two overridden methods need to be present: do_HEAD() and do_GET().
New in version 0.8:
cdAPP.py is responsible to check whether the requesting host is allowed to connect
to the server.
In order to to so do_HEAD() and do_GET() call global function checkACL() which returns
True if the host's IP number is 127.0.0.1, i.e. only localhost is able to connect. Other
hosts will receive a 403 error.
Global function checkACL() will be overridden by cdServer after import of cdApp.py
with a function provided by cdServer which checks the host's IP number against a list
of allowed hosts and a list of allowed networks (which can be specified by options -a
and -n respectively). cdServer also sets the variable cdApp.debug to True if cdServer
was started with option -d.
As far as I know do_HEAD() is only requested by proxies such as squid. In do_HEAD the method
is_special() is called to check if the request refers to a regular file or a special function.
If the request refers to an ordinary .html file the request is not forwarded to the
built-in SimpleHTTPRequestHandler. The file is being read by cdApp.py itself in order to
do some neat tricks:
More uses of this trick easily come to mind.
- cdApp.py inserts links to the search and exit functions
which are not visible when browsing the files via the filesystem (the placeholders
<!--@@exit--> and <!--search--> are replaced with links to
/func/exit_ and /func/query respectively)
- cdApp.py replaces all occurences of "@@ DATABASE" with the contents of the database
(one copy of the db is more than enough for this demo...)
The format of the request path for special functions is assumed to be as follows:
where the first path segment ('/func/') is taken from variable prefix,
command is the name of the command to be performed, and
additional parameters are encoded as expected.
The variable end_flag is checked by cdServer.py after each request. If set to a non-zero
value cdServer terminates.
The roots of cdServer go back to the year 2000 where I wrote a program
called bzServer which was used to add a search function to an existing html-based
catalogue. bzServer was a hobby project and more a proof-of-concept than a serious
In 2003 faced a similar problem when I was creating a CD with a complex
buyer's guide. I rembered my old pet project and rewrote the application-specific
stuff. dbhmServer saw the light of day, went into production and is still is
being in wide use today.
Only after completing the buyer's guide I realized that dbhmServer (or bzServer for
that matter) would be a good tool for a much wider range of problems. So I separated
the application-specific logic from dbhmServer. cdServer and a specialized
cdApp which will be used e.g. at the next update of the buyer's guide were born.
Additional functionality was subsequently added to cdServer and
-- finally -- this demo cdApp so I am able to share my work with the FLOSS community.