Server-Side Includes (SSIs) look like HTML tags (they look like HTML
_comment_ tags, actually) can do much of what CGIs or JavaScript can do
-- painlessly. SSIs are processed by our Web server _before_ the page
is transmitted to your visitor, and since our computer is much bigger
than theirs, for all intents and purposes they're instantaneous. Unlike
a CGI, no external scripts are being called -- the SSI tags (called
"directives") are embedded directly in your page. And visitors to your
site can't see the source code of your SSIs in their Web browser --
ever -- or any evidence that you did anything tricky.
What does this mean to you? Let's look at an example. Let's say you
want your page to say at the bottom, "Last modified on January 5, 1998",
entirely automatically, without you having to remember to type in the
date every time you change the page.
At your end you would write:
<P>This page was last updated on <!--#echo var="LAST_MODIFIED">.</P>
At their end they would receive this HTML:
<P>This page was last updated on January 11, 1998.</P>
In other words, our Web server processes the SSIs (which are disguised
as Web comment tags) and removes them before sending the page to your
visitor. All they see is a custom-generated page.
You could also have done this by writing a CGI to generate the whole
page, but typically that involves having the CGI generate the whole
page, and programming a CGI (and deploying it in /cgi-bin) is probably
more labor-intensive than just dropping an SSI or two into your HTML.
You could also have done it with JavaScript, except, because JavaScript
varies so much from browser to browser and from version to version,
it might not work, or your visitors might not have a JavaScript-capable
browser, or they might have turned it off, or it might run slowly.
SSIs are absolutely painless to use. They're not as flexible as
JavaScript or a CGI for "real programming" but they can do all kinds
of things, and they're so simple that you'll want to use them in every
project you do. (I use them on every page I design.)
Our Web server supports not just SSIs (as devised by NCSA years ago)
but also Apache's XSSIs (the "X" is for "extended") which include the
coolest feature of all, "<!--#if -->". That's right, an "if" tag.
So that you can have parts of your pages change depending on conditions
such as what browser the visitors are using, what time of day it is,
what link they came from, etc. You'll see examples of many useful
apllications of this later.
The three key things to remember about SSIs:
1.) Your file must be "something.shtml". That's s-h-t-m-l with an "s".
SSIs are not enabled in ".html" files, only ".shtml".
2.) SSIs can go anywhere. They can be mixed in with your text, they
can be in your <HEAD>...</HEAD> section, they can even be inside
regular HTML tags.
3.) SSIs are finicky about their formatting. They must have NO SPACE
AFTER THE OPENING OF THE TAG and A SPACE BEFORE THE END OF THE TAG:
<!--#echo var="DATE_LOCAL" -->
^^^^^ ^^^^
no space space
Note that the SSIs, which are handled by our Web server, won't do anything
until you upload the file. If you view the file locally on your computer
while writing it, the SSIs will be treated as HTML comments and ignored.
(This way your syntax-checker won't complain.)
Now let's look at each available SSI and some uses.
The SSI named "#echo" will display one of the many environment variables
which stores information about the Web server, the page being displayed,
or your visitor. The variables SSIs can access include the ones
available to CGI programs, the ones we log (in "kioskacct"), and some
others that you can't get elsewhere.
Echoing dates and times:
<!--#echo var="DATE_LOCAL" -->
displays the current date and/or time, such as
"Wednesday, 06-Jan-1999 16:39:07 EST". Use "config timefmt"
(shown later) to set the options. DATE_LOCAL is Boston time.
Why would you want to put the current date and time on your page?
(Are people so stupid that they have to look at _your_ page to
find out what time it is? Can't they just buy a clock? Well,
a reason some people put the current date and/or time on their pages
is that when someone runs a "freshness checker" to see what bookmarked
pages have changed, that page will always be marked as updated...)
<!--#echo var="DATE_GMT" -->
same thing in Greenwich Mean Time.
<!--#echo var="LAST_MODIFIED" -->
displays the date this page was last modified. This is very useful.
It will also work if it's inside a separate file included by the main
page. For instance, I like to create a file named "include/footer.shtml"
which contains this:
<!--#config timefmt="%B %e, %Y" -->
<P>This page was last updated on <!--#echo var="LAST_MODIFIED" -->.</P>
...and then I include it at the bottom of every one of my pages with this:
<!--#include virtual="/include/footer.shtml" -->
...you'll learn about "#config timefmt" and "#include virtual" later.
Echoing information about the current visitor:
<!--#echo var="DOCUMENT_URI" -->
Displays the address of the current page. ("URI" is basically the same
as the term "URL".) It will be relative to the root of the server,
i.e., it will start with "/". There is also DOCUMENT_NAME, which is the
filename with no slashes or directory names in front.
<!--#echo var="REQUEST_URI" -->
Displays the address that the browser asked for. How is this different?
Suppose that you have a customized "Error 404" page for your site
(you'd need to ask us to install this error page for you once you've
created it) named 404.shtml. When people see it, DOCUMENT_URI would
be "/404.shtml". REQUEST_URI would be whatever nonexistent page the
visitor was _trying_ to reach. In other words, DOCUMENT_URI is the URL
of the page that's actually being served, while REQUEST_URI is the URL
as it was requested. (If you set up a customized "403" or "404" page,
you might want to have it log REQUEST_URI and HTTP_REFERER. More later.)
<!--#echo var="HTTP_REFERER" -->
This is the URL of the page your visitor came _from_ to get to this
page, if they followed a link. (If they came by typing in the URL or
by selecting a bookmark, it will be "", which is displayed as "(none)".)
NOTE: THERE IS NO DOUBLE "R" IN "HTTP_REFERER"! Yes, I know they
spelled it funny.
A fancy example:
<!--#if expr="\"$HTTP_REFERER\" = /yahoo/" -->
<P>Thank you for coming to my site from Yahoo!</P>
<!--#elif expr="\"$HTTP_REFERER\" = /altavista/" -->
<P>Thank you for coming to my site from AltaVista!</P>
<!--#elif expr="\"$HTTP_REFERER\" != /mysite.com/" -->
<P>Thank you for coming to my site!</P>
<!--#else -->
<!-- they came from one of my own pages, don't welcome them again -->
<!--#endif -->
...if their HTTP_REFERER contains "yahoo" or "altavista", display the
appropriate message. Otherwise, if HTTP_REFERER is from outside the
site (either blank or another site) display a generic welcome; do nothing
if they came from another page at the same site.
Another use for HTTP_REFERER is that you may want to log it to see where
people are coming from. I only log visitors if they come from outside
my site and if HTTP_REFERER isn't blank:
<!--#if expr="\"$HTTP_REFERER\" != \"\" && \"$HTTP_REFERER\" != /mysite.com/"
<!--#include virtual="/cgi-bin/log-it.cgi" -->
<!--#endif -->
"#if" and integration with CGIs will be covered later.
<!--#echo var="HTTP_USER_AGENT" -->
Displays the string which the visitor's Web browser uses to identify itself.
For instance, at the moment mine is "Mozilla/4.0 (compatible; MSIE 4.01;
Mac_PowerPC)". You'll see what you can do with these when we get to "#if".
Some Web browsers (such as Internet Explorer) also send HTTP_UA_OS and
HTTP_UA_CPU variables that are easier to work with, but HTTP_USER_AGENT
is the one which should always be available.
There are many more variables you can access with "#echo" (or "#if" or a CGI)
and you can see them all by using the <!--#printenv --> directive, which will
display all of the variables. I suggest making a test page ("test.shtml" or
something) which you can refer to later while debugging your site which prints
the variables inside <PRE>...</PRE>:
<PRE>
<!--#printenv -->
</PRE>
Fun fact: Because the SSI directives are converted into plain text or HTML
by the Web server before the HTML is transmitted to the browser, you can
put them inside tags without breaking anything. For instance, if you want
to record people's HTTP_REFERER variables when they mail you a form:
<INPUT TYPE="hidden" NAME="body"
VALUE="Referer = <!--#echo var="HTTP_REFERER" -->">
...which then turns into something like this:
<INPUT TYPE="hidden" NAME="body"
VALUE="Referer = http://www.yahoo.com/page.html">
"#config" is the SSI directive which configures options related to the other
SSIs. It is used to set the date and time format, the format for reporting
the sizes of files, and the error message displayed by any broken SSIs.
Dates & Times
<!--#config timefmt="..." -->
Sets the date and/or time format which is used by DATE_LOCAL,
DATE_GMT, LAST_MODIFIED, and the "#flastmod" directive.
You can read about all of the options by typing "man strftime"
from the UNIX command line. Some of the more useful items are:
%a abbreviated weekday "Mon"
%A weekday "Monday"
%d day of month (01-31) "04"
%e day of month (1-31) "4"
%w day of week (0-6, Sunday=0) "1"
%j day of year (001 to 366) "004"
%U week number (00 to 53, week 1 starts on first Sunday of year)
%W week number (00 to 53, week 1 starts on first Monday of year)
%b abbreviated month "Jan"
%B full month "January"
%m month (01 to 12) "1"
%y two-digit year "99"
%Y year "1999"
%c standard date and time "Mon Jan 04 17:47:16 1999"
%x standard date "01/04/99"
%X standard time "17:47:16"
%D MM/DD/YY date "01/04/99"
%H hour (00 to 23) "17"
%I hour (01 to 12) "5"
%M minute (00 to 59) "47"
%S seconds (00 to 59) "16"
%p AM or PM "PM"
%Z time zone "EST"
%n new line
(See "man strftime" for details.)
So, for example, to display your dates as "4 January, '99" you
would use:
<!--#config timefmt="%d %B, '%y" -->
If you wanted your Web page to have a Happy Hour at 5:00 PM,
you would say:
<!--#config timefmt="%H" -->
<!--#if expr="\"$DATE_LOCAL\" = \"17\"" -->
<H1>It's HAPPY HOUR! Free drinks for everyone!</H1>
<!--#elif expr="\"$DATE_LOCAL\" > \"17\"" -->
<P>Happy Hour is over.</P>
<!--#endif -->
File Sizes
<!--#config sizefmt="bytes" -->
<!--#config sizefmt="abbrev" -->
When getting the size of a file with "#fsize", this specifies
whether you want the number of bytes or the number of "k".
Example:
<!--#config sizefmt="bytes" -->
Size of download.zip is <!--#fsize file="download.zip" --> bytes.
<!--#config sizefmt="abbrev" -->
Size of download.zip is <!--#fsize file="download.zip" -->.
...displays:
Size of download.zip is 4,449 bytes.
Size of download.zip is 4k.
More on "#fsize" later.
Error Messages
Normally, any sort of error generated by SSIs (a syntax error, file
not found, etc.) will produce "[an error occurred while processing
this directive]". You can change that.
<!--#config errmsg="Hey! An error occurred! Tell webmaster@mysite.com!" -->
Why would you want to do this?
1.) You might want to customize the errors to tell people what to
do if they see them, like the example above.
2.) You might be trying to figure out which SSI has the error so
you would change the error message before each directive on the page.
3.) You might want to just set errmsg to "" so that no errors are shown.
Your site's visitors will probably never see any errors once you remove
any typos from your SSIs, but errmsg is there if you need it.
Here's the SSI that started it all. If you've programmed in C (or other
similar computer languages) you may be familiar with "#include filename.txt"
to include one file inside another. With SSIs, you can have your Web pages
contain other (external) files.
<!--#include virtual="/include/footer.shtml" -->
<!--#include file="footer.shtml" -->
With those examples, you could have a standardized footer stored in
footer.shtml and then display it on all your pages by using "#include"
on each of them. Then when you change footer.shtml, all your pages
reflect that change. (Great for navigation bars, site news, and even
common <META> tags in your <HEAD> section.)
There are two forms of "#include" (and similar SSIs that look for files,
such as "#fsize" and "#flastmod".) "virtual" means that you are specifying
a path relative to the site's root, in other words, starting with "/"
and navigating downwards. (If your included file is in "/include", this
is a good option, because that way any page can reference virtual="/include"
to get the same directory.) On the other hand, if your included file is
in the same directory as the main file, or a subdirectory of this
directory, you would use "file".
<!--#include virtual="/include/footer.shtml" -->
^^^^^^^ ^path from site root
<!--#include file="footer.shtml" -->
^^^^ ^path from current directory
Note: "file" cannot begin with "/" or "..". I suggest keeping all your
common page-parts in "/include" and using "virtual".
Here's an example in which a page of HTML includes a text file:
<HTML>
<HEAD>
<TITLE>Our Newsletter</TITLE>
</HEAD>
<BODY>
<H1>Our Newsletter</H1>
<BR>
<PRE>
<!--#include file="newsletter.txt" -->
</PRE>
</BODY>
</HTML>
You could do that so that someone else who is typing in the daily
newsletter doesn't have to much around inside your HTML document,
they just have to type in text. (You could put HTML tags or even
more SSI directives in the included file, too!)
The included file needs to have the .shtml or .html extension as
appropriate, or anything else (.txt or nothing) if it's plain text.
Any references to LAST_MODIFIED or DOCUMENT_URI, etc., will do what
you want, referring to the main file, not the included one.
"#include" can also include the output of a CGI program!
<!--#include virtual="/cgi-bin/log-it.cgi" -->
In that example, log-it.cgi is this:
#!/bin/sh
echo 'Content-type: text/plain'
echo
OUTPUT = '/usr/WWW/kiosk/Newbury/mykiosk/data/data1'
echo `date` >>$OUTPUT
echo 'DOCUMENT_URI = ' $DOCUMENT_URI >>$OUTPUT
echo 'REQUEST_URI = ' $REQUEST_URI >>$OUTPUT
echo 'HTTP_REFERER = ' $HTTP_REFERER >>$OUTPUT
echo 'HTTP_USER_AGENT = ' $HTTP_USER_AGENT >>$OUTPUT
echo 'REMOTE_ADDR = ' $REMOTE_ADDR >>$OUTPUT
echo 'REMOTE_HOST = ' $REMOTE_HOST >>$OUTPUT
echo >>$OUTPUT
(this assumes you already have a file named data/data1
that the CGI can write to. See the relevant section of
our CGI writeup for more on file accessibility to CGIs.)
What did we just do? Well, the CGI above produces NO VISIBLE OUTPUT
at all, it just writes to a secret logfile. Site visitors can't
even tell there WAS a CGI involved -- the page looks normal and there
is no evidence of the CGI if they view the source. Let's
try another:
<P>Current system status:<BR>
<I><!--#include virtual="/cgi-bin/status.cgi" --></I></P>
status.cgi is this:
#!/bin/sh
echo 'Content-type: text/plain'
echo
uptime
so you get:
Current system status:
6:16pm up 31 days, 17 mins, 14 users, load average: 8.86, 5.83, 4.97
If you call your CGIs with #include, they can return any arbitrary part
of a page (or a whole page), whereas linking to them with <A HREF="...">
or <FORM ACTION="..."> means the CGI must generate the whole page (and people
can see that it's coming out of a CGI, whereas SSIs hide things.)
However, if you need to pass data to your CGI (with GET or POST methods)
you can't do that with #include, you have to use <A HREF="..."> or
<FORM ACTION="...">.
Don't forget that your CGI must be executable by other users (meaning
you need to "chmod 755 myfile.cgi"), its name should end with ".cgi",
the first line needs to say "#/bin/sh" (or whatever other program will
execute it, such as /usr/local/bin/perl) in the first column,
and it must output "Content-type: text/plain" followed by a blank line.
If you're uploading your CGI from your computer, you MUST (MUST MUST MUST)
set your FTP program to "text" ("ASCII") mode, "binary" WILL NOT WORK!!!
NOTE: If you've been using <!--#exec cgi="..." -->, you must change
it to <!--#include virtual="..." --> due to changes to our server's
configuration. <!--#include virtual="..." --> does exactly the
same thing as <!--#exec cgi="..." --> when given the URL of a CGI
(and of course it also work to include text or HTML files.)
"#fsize" displays the size of a file (subject to "#config sizefmt")
and "#flastmod" displays the modification date of a file (subject to
#config timefmt"). Both date a "file" or "virtual" option just
like "#include". To return to a previous example:
<!--#config sizefmt="bytes" -->
Size of download.zip is <!--#fsize file="download.zip" --> bytes.
<!--#config sizefmt="abbrev" -->
Size of download.zip is <!--#fsize file="download.zip" -->.
<!--#config timefmt="%c" -->
download.zip was last modified on <!--#flastmod file="download.zip" -->.
This page was last modified on <!--#echo var="LAST_MODIFIED" -->.
We saw this earlier. "#printenv" simply lists every variable it can.
Great for debugging or seeing what things you can log. Try it.
<!--#printenv -->
"#set" allows you to define your own variables. These variables
can be used in "#echo", "#printenv", and "#if". This probably isn't
useful most of the time, as you can't do math with the variables or
generate random numbers, but you can set them for your convenience
or to cut down redundancy.
<!--#set var="AGENT1" value="$HTTP_USER_AGENT" -->
<!--#if expr="\"$AGENT1\" = /Lynx/ || \"$AGENT1\" = /Emacs/" -->
<!--#set var="TEXT_BROWSER" value="true" -->
<!--#endif -->
<!--#if expr="\"$TEXT_BROWSER\" = /true/" -->
<P>Here is some text for you graphics-impaired people.</P>
<!--#else -->
<P>Here is a picture: <IMG SRC="xyz.gif"></P>
<!--#endif -->
I've saved the best for last!
Imagine what you can do with all that information you can collect about
your site's visitor (all those variables listed in <!--#printenv -->)
if you can make decisions based on it. We've already seen several
examples if "#if" in action. Here's the real deal:
syntax: <!--#if expr="things being compared" -->
...stuff to display or do if that's true...
<!--#endif -->
The "#endif" is required. "#elif" ("else if") and "#else"
are optional, and you can have multiple "#elif"s:
syntax: <!--#if expr="things being compared" -->
...stuff to display or do if that's true...
<!--#elif expr="things being compared" -->
...stuff to display or do if that's true...
<!--#elif expr="things being compared" -->
...stuff to display or do if that's true...
<!--#else expr="things being compared" -->
...stuff to display or do if that's true...
<!--#endif -->
Now, the tricky part is the "things being compared" bit, which is
already in quotes, and will get more as we build our expression.
The part on the left should be a variable value, and the part on
the right can either be a string (in quotes) or a substring (in slashes):
<!--#if expr="\"$DATE_LOCAL\" = /Monday/" -->
<P>The DATE_LOCAL contains the word Monday somewhere.</P>
<!--#endif -->
<!--#if expr="\"$DATE_LOCAL\" = \"Monday\"" -->
<P>The DATE_LOCAL is exactly the word "Monday".</P>
<!--#endif -->
Do you see the weird syntax there? The whole expression,
"variable = string", has a pair of quotes around it, and within
it there are escaped quotes (\"...\") or slashes (/.../)
around the variable and string that are being matched.
(Also, the variable is prefixed with a dollar sign.)
I highly recommend always comparing with /substrings/ and
not \"strings\" on the right because the thing you're comparing
them too may (or may not) have hidden characters in it (a space
at the beginning of a date, a carriage return at the end of
a text string, etc.) so my experience is that only the substring
matches work reliably. NOTE: all matching is case-sensitive!
You have several comparison operators to work with:
= true if strings match (or if substring is present)
!= true if strings are different (or substring not found)
> true if "greater than" These four should
< true if "less than" be used only with
>= true if "greater than or equal to" \"strings\", not
<= true if "less than or equal to" /substrings/.
And you can do Boolean operations to combine expressions:
condition1 && condition2 true if 1 AND 2 are true
condition1 || condition2 true if 1 OR 2 are true
!condition true if condition is false
(condition) parentheses group things
A ridiculous example:
<!--#if expr="(\"$DATE_LOCAL\" = /Mon/ && \"$DATE_LOCAL\" = /Jan/) ||
(\"$DATE_LOCAL\" = /Tue/ && \"$DATE_LOCAL\" = /Feb/)" -->
<H1>Hooray! It's a Monday on January OR a Tuesday in February!</H1>
<!--#endif -->
A more practical example:
<!--#set var="AGENT1" value="$HTTP_USER_AGENT" -->
<!--#if expr="\"$AGENT1\" = /MSIE/ && \"$AGENT1\" != /WebTV/" -->
<!-- WebTV pretends to be Internet Explorer and Mozilla -->
<H1>You're using Microsoft Internet Explorer!</H1>
<!--#elif expr="\"$AGENT1\" = /Mozilla/ && \"$AGENT1\" != /compatible/" -->
<!-- Internet Explorer pretends to be Mozilla -->
<H1>You're using Mozilla (Netscape Navigator or Communicator)!</H1>
<!--#else -->
<H1>You're using some other Web browser!</H1>
<!--#endif -->
Do you see how the first expression is checking for things that say
"MSIE" but NOT "WebTV", and the second is "Mozilla" but NOT "compatible",
and the "#else" part is everything else? Congratulations, if you didn't
get lost you just learned how to detect the two most popular Web browsers.
(More about that later.)
More useful examples:
Let's say you've put up a file for download (a shareware program or a
naughty picture) and people are required to go past your "I Agree"
page before they can get to it. You _could_ do this with JavaScript...
providing your JavaScript program works in everyone's Web browser
and providing that nobody turns JavaScript off. Or, you could do it
with an SSI very simply and nobody would be able to bypass it in
any Web browser:
<!--#if expr="\"$HTTP_REFERER\" = /www.mysite.com\/agree.shtml/"
...all the content goes here...
<!--#else -->
<H1>Hey! Don't do that!</H1>
<P>Go to <A HREF="/agree.shtml">my agreement page</A> first.</P>
<!--#endif -->
...note that because "/" is a special character we used "\/" to make
it work inside the /substring/. Or you could spell out the full
URL as a string, \"http://www.mysite.com/agree.shtml\". (We don't
just check for "agree.shtml" because some evil person could create
a page on _their_ site with the same filename, so we need to check
that they're coming from _our_ site's agreement page.)
Now suppose you want a banner at the top of your page to change every
day. You could do that with a CGI, which would slow down the page a
little (SSIs slow it down a tiny amount, CGIs slow it down a little
more) and would require you to actually write and/or install a CGI for
banner rotation. Well, SSIs let you do that sort of thing right
in your HTML:
<!-- day of the week from 0 to 6 -->
<!--#config timefmt="%w" -->
<!--#if expr="\"$DATE_LOCAL\" = /0/" -->
...Sunday banner...
<!--#elif expr="\"$DATE_LOCAL\" = /1/" -->
...Monday banner...
<!--#elif expr="\"$DATE_LOCAL\" = /2/" -->
...Tuesday banner...
<!--#elif expr="\"$DATE_LOCAL\" = /3/" -->
...Wednesday banner...
<!--#elif expr="\"$DATE_LOCAL\" = /4/" -->
...Thursday banner...
<!--#elif expr="\"$DATE_LOCAL\" = /5/" -->
...Friday banner...
<!--#else -->
...Saturday and any new days that get invented...
<!--#endif -->
You could also hide stuff until a certain date, let's say January 13:
<!-- day of the year from 0 to 365 -->
<!--#config timefmt="%j" -->
<!--#if expr="\"$DATE_LOCAL\" > \"013\"" -->
<H1>New! We are unveiling our special new product!</H1>
<!--#elif expr="\"$DATE_LOCAL\" = \"012\"" -->
<H1>Big news coming tomorrow!</H1>
<!--#else -->
<P>At midnight on January 13, this page will unveil
our secret new product!</P>
<!--#endif -->
Think of all the other things you could do with "#if". You could
look at REMOTE_HOST or REMOTE_ADDR to see what ISP people are
connecting from, you could have your navigation links change depending
on the value of DOCUMENT_URI, you could say "click here" for
graphical browsers and "follow this link" for others,
you could provide a scaled-down page just for WebTVs,
you could say "right-click to save this image" for Windows users
and "hold the button down to save this image" for Mac users...
As promised earlier, he's a large chunk of code that you can use
(in whole or in part) to determine what browser and what operating
system people are using. Leave out any tests for browsers you're
not designing special versions of your site for.
<!-- /////////////////////////////////////////////////////////////// -->
<!-- Browser check -->
<!-- copy the HTTP_USER_AGENT into a variable for speed and clarity -->
<!--#set var="AGENT1" value="$HTTP_USER_AGENT" -->
<!--#if expr="\"$AGENT1\" = /Lynx/ || \"$AGENT1\" = /Emacs/" -->
<!-- text browsers -->
<!--#elif expr="\"$AGENT1\" = /WebTV/" -->
<!-- WebTV -->
<!--#elif expr="\"$AGENT1\" = /MSIE/ && \"$AGENT1\" != /WebTV/" -->
<!-- Microsoft Internet Explorer. -->
<!--#elif expr="\"$AGENT1\" = /Mozilla/ && \"$AGENT1\" != /compatible/" -->
<!-- Netscape Navigator or Communicator (Mozilla). -->
<!--#else -->
<!-- all other browsers: "Mozilla (compatible)" (such as Opera)
and others (Mosaic) -->
<!--#endif -->
<!-- /////////////////////////////////////////////////////////////// -->
<!-- operating system check -->
<!-- copy the HTTP_USER_AGENT into a variable for speed and clarity -->
<!--#set var="AGENT2" value="$HTTP_USER_AGENT" -->
<!--#if expr="\"$AGENT2\" = /Mac/" -->
<!-- Mac OS -->
<!--#elif expr="\"$AGENT2\" = /Win95/ || \"$AGENT2\" = /Windows 95/ ||
\"$AGENT2\" = /Win98/ || \"$AGENT2\" = /Windows 98/ ||
\"$AGENT2\" = /WinNT/ || \"$AGENT2\" = /Windows NT/" -->
<!-- Windows 95/98/NT -->
<!--#elif expr="\"$AGENT2\" = /Win16/ || \"$AGENT2\" = /Windows 3.1/" -->
<!-- Windows 3.1 -->
<!--#elif expr="\"$AGENT2\" = /SunOS/ || \"$AGENT2\" = /Solaris/ ||
\"$AGENT2\" = /IRIX/ || \"$AGENT2\" = /AIX/ ||
\"$AGENT2\" = /HP-UX/ || \"$AGENT2\" = /FreeBSD/ ||
\"$AGENT2\" = /Linux/ || \"$AGENT2\" = /X11/" -->
<!-- UNIX (or at least X11) -->
<!--#else -->
<!-- anything else (AmigaOS, Windows CE, and things that don't say -->
<!--#endif -->
<!-- /////////////////////////////////////////////////////////////// -->
Instead of putting different copies of the page in each section of
the browser check, you could simply set flags:
<!--#set var="Mozilla" value="true" -->
<!--#set var="UNIX" value="true" -->
...and then later on, in the site's content, you could simply interpolate
little sections that say:
<P>If you have too many files on your computer, maybe you should
<!--#if expr="\"$UNIX\" = /true/" -->
rm
<!--#else -->
delete
<!--#endif -->
some of them.</P>
...which avoids repeating the complex test, and you could even combine
results if you want to be really fussy about which browsers get what:
<!--#if expr="\"$UNIX\" = /true/ && \"$Mozilla\" = /true/" -->
<P>You're using a Netscape browser under UNIX!</P>
<!--#endif -->
Plan ahead. When designing your pages for your new site, give all the
filenames ".shtml" extensions (you'll want to use SSIs at some point,
even if just to display LAST_MODIFIED) and create three empty files,
"/include/head.shtml", "/include/body-top.shtml",
"/include-body-bottom.shtml". Use "#include virtual" to place them in
the <HEAD> section and the top and bottom of <BODY> on each page you
make. Then when you later want to add a note to every page, you can
put it in one of the three include files to modify all the <HEAD>s
or page tops or page bottoms at once!
Also remember that if your include files are in a directory by
themselves ("/include" or whatever) it means that the path to them
with "#include virtual" will always be the same, so you can paste the
same "#include" directive into every page you create.
Note that if you make a page that changes itself frequently, you
may want to include the headers that tell the Web browser that
it expires at a certain time or should simply not be cached.
(Or you could include the "Refresh" header to make it reload itself.)
This is because the browser has no idea that the page is dynamic;
its name doesn't end in ".cgi" or anything. Hence you may need
to clear your cache or click the "Reload" button often while
experimenting.
(This also applies to any other form of dynamic content, such as
CGIs, but .shtml files are especially susceptible to not being
reloaded every time they're visited, as they're treated like
normal cache-able Web pages unless you mark them otherwise.)
Examples of some headers that alter browser behavior:
<META HTTP-EQUIV="Expires" CONTENT="Thu, 01 Dec 1999 16:00:00 GMT">
...specifies when the page is flushed from the browser cache.
<META HTTP-EQUIV="Pragma" CONTENT="no-cache">
<META HTTP-EQUIV="Cache-Control" CONTENT="no-cache">
...the former is obsolete, the latter is now standard, so
you may want to use both in case someone has an old browser.
<META HTTP-EQUIV="Refresh" CONTENT="600;url=http://www.mysite.com/page.html">
...forcibly reload in 600 seconds if page is still displayed.
Or you could just not worry about this stuff. If your page is changing
every 30 seconds, it may not be important if someone sees a copy from
two minutes ago. (Unless it's a webcam.)
For more details about SSIs (XSSIs) on our Kiosk Web server, which
is Stronghold 2.3 (Apache 1.2.6), see:
Full Stronghold 2.3 documentation:
http://www.int.c2.net/external/?link=sh23/index.html
...for XSSIs, you want Chapter 9 of the Admin Guide.
Apache documentation on XSSIs (for version 1.3)
http://www.apache.org/docs/mod/mod_include.html
...that's correct as far as I can tell, except that "#if" does
NOT take egrep-style regular expressions in our version (1.2.6).
For details on the HTTP headers that control
caching, refreshing, etc., see the HTTP specification (RFC 2068):
RFC 2068, HTTP 1.1 specification (technical):
http://www.w3.org/Protocols/rfc2068/rfc2068
General information about <META HTTP-EQUIV> tags:
http://vancouver-webpages.com/META/
|
|
Comments? Questions? Problems? Contact us. Page last modified February 14, 2003. Web site contents & design Copyright © 2003 Software Tool & Die. Legal info. |