The modules that provide basic content delivery features are compiled into Stronghold by default. This chapter shows you how to
Imagemaps are files that define coordinates on an image as links. A single imagemap can act as a link to several different destinations, depending on which part of the image a user clicks. While most browsers now support client-side imagemaps, server-side imaginable work with all browsers that support images. Stronghold has an imagemap module that processes server-side imagemaps independent of the CGI module.
To enable imagemap handling
# <ServerRoot>/bin/reload-server
Stronghold now treats all files ending in .map as imagemap files.
With the imagemap handler in place, you can place an image in an HTML files and then create an imagemap file that defines the shapes, coordinates, and destinations of its links. When you link the HTML image tag to the imagemap file, the image becomes an imagemap.
A linked region can take one of four shapes: polygon, circle, rectangle, or point. Your imagemap file must define these parameters:
An imagemap file consists of a list of directives that define these parameters. There are six imagemap directives:
For any directive, there are six possible values:
For example, imagine that you want to use this image as a navigation bar:
Using an image-editing application such as Photoshop, you must first determine the shapes and pixel coordinates of the linked regions on the image:
The imagemap file for this image would look something like this:
base http://www.your_host.org/
default map
poly previous/ 14,36 66,16 66,60
rect products/ 80,18 196,46
circle help/ 245,40 270,60
rect services/ 293,18 410,46
poly next/ 425,16 425,60 478,38
In this example, the URLs specified in the shape definitions are all relative to
http://www.your_host.org/. If a user clicks an unmapped region of the navigation bar, the server returns a linked list of the imagemap's destinations. The linked shapes are defined by x and y pixel coordinates. Polygons require the coordinates of each of their corners, while rectangles only require those of two opposing corners and circles require those of a radius.
With the imagemap file in place, you must link the HTML image reference to it, like this:
<a href=/maps/navigation.map><img src=navbar.gif ISMAP></a>
Test the imagemap by viewing it in your browser and moving the mouse pointer over it. As the pointer passes over a linked region, the destination of the link appears in the browser's status bar. Click an unmapped region to see the linked list defined in the imagemap file. Optionally, you can add quoted description strings to the end of each region definition to make the linked list more descriptive:
rect products/ 80,18 196,46 "BetaCom Products"
The World Wide Web is populated by an enormous variety of users speaking many different languages. To accommodate only the largest segment of users, you can construct a site in English or the language most widely used by your audience, but this alienates other users. To compensate, you can use content negotiation to cater to many varieties of users.
Content negotiation involves an exchange of information between client and server. Under HTTP/1.1, a client's initial request includes headers that specify which file types the client can handle:
GET /home/ HTTP/1.1
Connection: Keep-Alive
User-Agent: Mozilla/3.0 (WinNT; I)
Host: www.host.com
Accept: text/html, text/plain, image/gif, image/jpeg, image/pjpeg ...
Accept-Encoding: compress, gzip, winzip
Accept-Language en; q=1.0, de; q=.8, fr; q=.6,
The request includes a list of acceptable media type in the Accept field, acceptable encoding types in the Accept-Encoding field, and acceptable languages in the Accept-Language field. The numbers in the Accept-Language field are q-values, and they rank the language types according to the user's preference. In this scenario, English is the preferred language, but German and French are also acceptable.
If the root document for the requested directory is only available in a language and format listed in the request, the server simply returns the document. However, imagine that the only root document for /home/happens to be index.pdf.jp, a Portable Document Format (PDF) file in Japanese. Since the server knows from the request that the client cannot handle this file, it responds like this:
HTTP/1.1 406 Not Acceptable
Most requests can be partially fulfilled. For example, imagine that the only root document for /home/ is index.html.en, and that the file references a QuickTime file. All browsers support HTML, but not all have QuickTime plugins. Even if video/quicktime is not among the values in the Accept header, the server returns the HTML file and the client displays a broken link where the animation would have appeared.
Content negotiation provides a mechanism for preventing 406 status codes and broken links by selecting from among several versions of the same file based on the criteria provided in the client request. Although this requires maintaining and organizing parallel file versions, the result is a clean, universally accessible site.
Server-side includes (SSIs) are simple, HTML-embedded directives that instruct Stronghold to execute a program or include data in the HTML document. As a shorthand alternative to CGI, server-side includes can be handy. However, like CGI, they should be used with caution and an eye for security risks.
Since server-side includes are directives for the server, Stronghold must parse them before it delivers the document that contains them. Scanning every requested file for server-side includes can create considerable processor overhead. Instead, you can instruct Stronghold to look for server-side includes only in certain files by including this line in your httpd.conf file:
AddType text/x-server-parsed-html .shtml
When you start Stronghold with this configuration, it only looks for SSI directives when a client requests a file with the .shtml extension. When it finds them, it parses the directives, carries out their instructions, replaces them with their output, and sends the finished document to the client.
All SSI directives follow this format:
<!--#directive parameter="value"-->
Directives can have more than one parameter, and multiple parameters are separated by white space. The valid SSI directives are as follows:
<!--#include file="sample.html"-->
<!--#include virtual="/virtual/sample.html"-->
This file is <!--#fsize file="example.ps"--> bytes.
Similar to fsize, flastmod inserts the modification date for the file specified by path, For example:
This file was last modified on <!--#flastmod file="example.html"-->
The exec directive executes a program, either a command-line string or a CGI program, and inserts the output into the current document. For example:
Finger C2Net's president:
<!--#exec cmd="/bin/finger sameer@c2.net"-->
This page has been accessed
<!--#exec cgi="/cgi-bin/counter.pl"--> times.
<!--#config errmsg="Error: Try again."-->
<!--#config sizefmt="abbrev"-->
<!--#printenv-->
<!--#set var="country" value="Liberia"-->
Stronghold implements Extended SSI, which includes flow control elements much like the ones used in programming languages. With flow control, you can create more sophisticated SSI scripts.
There are four flow control elements:
<!--#if expr="test-condition"-->
<!--#elif expr="test-condition"-->
<!--#else-->
<!--#endif-->
The test-condition is one of the following:
In a server-side include string, you can use any environment variables available to the server, including the CGI variables listed in "CGI Error Logging" on page 10-2. SSI also has its own environment variables, listed here.
The filename of the current HTML document. For example:
This file is called <!--#echo var="DOCUMENT_NAME"-->.
This document is located at <!--#echo var="DOCUMENT_URL"-->.
An unencoded query string whose metacharacters are escaped with a backslash (\).
The local date and time. For example:
Here in San Francisco, it is now <!--#echo var="DATE_LOCAL"-->
The current Greenwich Mean Time. For example:
The current time is <!--#echo var="DATE_GMT"--> GMT.
The date and time when the current file was last modified. For example:
I last modified this page on <!--#echo var="LAST_MODIFIED"-->.
Since HTTP implements single, self-contained transactions, it provides no built-in way to track a whole session, which consists of more than one transaction. Exchanges of requests and responses occur individually, and each exchange appears to be unrelated to the last. However, today's complex interactive Web applications require session tracking in order to implement features such as site customization, preference tracking, and so on.
For example, many online commerce sites implement a "shopping basket" that keeps track of items each user chooses, compiling a list of all the items chosen by each user during the course of his or her entire session. Without session tracking, a shopper would only be able to purchase one item at a time through a single, self-contained HTTP transaction. To keep track of requests that originate with the same client, servers set session identifiers that accompany each request and response. Requests with the same session ID belong to the same session.
There are two ways to perform session tracking:
Cookies, supported by the mod_usertrack module, are session ID's that are exchanged as HTTP metainformation. When the Cookie Tracking directive is set to "on", Stronghold automatically generates a session ID whenever it receives a request that does not already include a cookie. Depending on whether it appears inside a container, Cookie Tracking can apply to the whole server, a single virtual host, or only an object such as a directory or file. A session that uses cookies works like this:
# Set-Cookie name=value; expires=date; path=pathname;domain=domain-name; secure
Stronghold sets only the name field and the domain field, unless httpd.conf contains the
CookieExpires directive. Without this directive, cookies are deleted when the client quits and Stronghold issues a new one at the beginning of the next session. When CookieExpires is set, Stronghold sends the expires field and the client saves the cookie until it expires.
Taking advantage of cookies to produce dynamic, customized content requires external programs that control content based on session ID's. Whenever a cookie is set for the current session, each client request includes the Cookie HTTP header. For example,
cookie:name-gv427516826238200473
By reading the HTTP_COOKIE environment variable, a program can track related requests and produce dynamic content based on multiple requests over the course of a session.
The CustomLog directive sets the path and format of any log. It can be used to log cookies for a file. For example,
Costom logs/clickstream "% (cookie) i %r %t"
In this example, each entry in the clickstream log file shows the contents of the Cookie header, the first line of the request, and the time. If you like, you can create a more detailed cookie log, or combine cookie logging with another log.
The PATH_INFO variable places a session identification token in the URL, instead of in the response header. The client then uses the GET request method to communicate its token to the server, instead of the Cookie header described in the previous section. This method accommodates older browsers that do not support cookies, as well as user who do not accept cookies.
For each initial request, a program must generate a new token, embedded in the URL of every link. When the user follows a link, its URL tells the program to generate another page with the same token embedded in its links. The token is passed from page to page throughout the session.
Dynamic content delivery is the publication of variable content and comes in a variety of forms. It may be content from a database or other non-HTML source, frequently-updated content, user-customized content, and so on. The content delivery method you choose depends on the complexity, location, time-sensitivity, format, and security of the data you want to provide to Web users. Stronghold comes with a number of modules that provide different types of dynamic content delivery:
Use this method to provide the same data in different file formats or languages. See "Content Negotiation" on page 9-6.
Use this method to automatically insert brief, simple, variable strings of information in otherwise static documents. See "Server-Side Includes" on page 9-7.
Use this method for applications best suited to the java language.
Use this method to efficiently run legacy Perl scripts (instead of executing them as external CGI programs) and for new applications for which Perl is the most appropriate language.
PHP provides an extensive language for programming HTML formatting and content, database queries, dynamic image creation, mathematical operations, and more see Chapter 11, "PHP3 Embedded Scripting".
Stronghold's standalone indexing and searching programs provide dynamic lists of server resources based on user-provided criteria, and are wxamples of CGI content.
Use this feature to allow users to search your site. See, " Chapter 12, "Indexing and Searching"."