Server Side Includes
While standard HTML files are fine for storing pages, it is very useful to be able to create some content dynamically. For example, to add a footer or header to all files, or to insert document information such as last modified times automatically. This can be done with CGI, but that can be complex and requires programming or scripting skills. For simple dynamic documents there is an alternative: server-side-includes (SSI).
SSI lets you embed a number of special 'commands' into the HTML itself. When the server reads an SSI document, it looks for these commands and performs the necessary action. For example, there is an SSI command which inserts the document's last modification time. When the server reads a file with this command in, it replaces the command with the appropriate time.
Before beginning to use any server side includes, you need to change the way in which the HTML documents are named. In most instances, people will give their pages names like "default.htm" or "default.html". In order for the spa!'s web server to process the server side includes it needs to know that your page contains the server side includes. This is accomplished by naming your documents in a fashion such as "default.html-ssi". So basically you need to add the extension "-ssi" to all of your HTML files you want to add server side includes to. You cannot however name the file with the extension "htm-ssi", it must be "html-ssi".
The actual syntax of server side includes is very simple. Server side includes are contained inside comment tags in the HTML itself. All you need to do is insert the SSI code wherever you'd like the counter to appear on your page; normally, counters appear at the bottom of a page. Below is an example of an HTML comment tag:
<!-- comments go here -->
In the "comments go here" space is where the server side includes go. Here are a few examples of some server side includes, and then below them the results of these directives and a description of what the ssi did:
<!--#echo var="date_local"-->
This server side include will produce the date and time in local format for the user.
<!--#echo var="last_modified"-->
This line of code will produce the date and time that the HTML document was last modified. This is useful for showing the last date that an HTML page was updated.
For more commands and examples.
CGI-BIN Applications - Perl
CGI stands for "Common Gateway Inferface," a fancy name meaning computer programs running on the webserver that can be invoked from a www page at the browser. The "bin" part alludes to the binary executables that result from compiled or assembled programs. It is a bit misleading because cgi's can also be Unix shell scripts or interpreted languages like Perl. CGI scripts need to be saved in ASCII format and uploaded to your server's cgi-bin in ASCII or text format. This is very important.
We don't provide free support for CGI scripts which we did not install on your server. So if you are not already familiar with CGI scripting, you may want to read a book on the subject or find places on the Internet with CGI scripting information. There are many good resources for CGI scripts found on the web. The scripts at Matt's Script Archive found at http://www.worldwidemart.com/scripts/ are very good. Many of our scripts come from here. Another excellent resource is The CGI Resource Index found at http://www.cgi-perl.com/ -- if you are not an expert, look for scripts that are very well documented and come with step-by-step instructions, or contact us for help or installation.
Where to Put CGI-bin Scripts
Put your cgi-bin scripts in the /home/user_name/ directory named "mainwebsite_cgi-bin".
Paths to Date, Mail, Perl, etc
Here are your paths to the common server resources that CGI scripts often require
Perl: /usr/bin/perl
Sendmail: /usr/sbin/sendmail
HTML Domain path: /home/userid/mainwebsite_html/
(puts you in your web directory)
Cgi-bin path: /home/userid/mainwebsite_cgi-bin
(puts you in your cgi-bin)
HTML link to your cgi-bin www.yourdomain.com/cgi-bin/
Setting Permissions - chmod
The following is a simple explanation of file permissions in Unix. To list the access permissions of a file or directory, telnet to your server, then:
cd directoryname to change the directory until you are either in the directory above the file you are interested in, or above the directory you are checking.
Type: ls -l filename and you will see what the current permission settings are for that file, along with a bunch of other stuff.
PEOPLE
PERMISSIONS
u = the file's user (you)
r = read access
g = the file's group
x = execute access
o = others
w = write access
a = the user, the group, and others
To change permissions for a file named filename.cgi, you need to chmod the file (change mode). For example, when you type this:
chmod u=rwx,g=rx,o=rx filename.cgi
you've given: read, execute, and write access to the user (that's you) read and execute access to the group and read and execute access to others
Some scripts will tell you to chmod 775 (for example). Doing the above is the same thing as typing chmod 775. You can use either method with our Unix servers. Let me explain:
When using the numeric system, the code for permissions is as follows:
r = 4 w = 2 x = 1 rwx = 7
The first 7 of our chmod 775 tells Unix to change the user's permissions to rxw (because r=4 + w=2 + x=1 adds up to 7. The second 7 applies to the group, and the last number 5, refers to others (4+1=5).
When doing an ls -l on the file, telnet always shows the permissions this way:
-rwxr-xr-x
Ignore the first dash, then break up the above into three groups of letters. If there's a dash where a letter should be, it means that there is no permission for those people.
Remember: the first 3 apply to user, the second 3 apply to group, and the third 3 apply to others.
Some FTP clients support changing permissions in a more graphical way. If you have Fetch for the Mac, you have an easy way to change permissions. Go to the file you want to change the permissions on, and highlight it. Under the Remote menu, select Change Permissions. A window will pop up showing the current permissions for the file you had highlighted, as in Figure below. Click on the boxes to change permissions as needed.

WS_FTP accomplishes the same task as above. Just highlight the file you want to check, and right-click on it. A menu will pop up, then select CHMOD. You will see the window below, as in Figure below:

Troubleshooting CGI-bin Problems
Below are solutions to some of the more common CGI script problems, in question and answer format.
Error: When I activate my CGI program, I get back a page that says "Internal Server Error. The server encountered an internal error or misconfiguration and was unable to complete your request."
Cause & Solution: This is generally caused by a problem within the script. Log in via Telnet and test your script in local mode to get a better idea of what the problem is. To do this, go into the directory in which your script is located, then execute the script. To execute the script, you can do it by two ways
1) Type "perl myscript.pl" (Perl being the language interpreter in this case).
2) Or simply type "myscript.pl" alone, that will work if the first line is well written to indicate the location of Perl.
The first one is useful to see if there's any error IN your script. The second one is useful to test if your "calling line" (the first line of the script) is okay, i.e. if you entered the right location of Perl.
Error: I am being told "File Not Found," or "No Such File or Directory."
Cause & Solution: Upload your Perl or CGI script in ASCII mode, not binary mode
Error: When I test my Perl script in local mode (by Telnet), I have the following error: "Literal @domain now requires backslash at myscript.pl line 3, within string. Execution of myscript.pl aborted due to compilation errors."
Cause & Solution: This is caused by a misinterpretation by Perl. You see, the "@" sign has a special meaning in Perl; it identifies an array (a table of elements). Since it cannot find the array named domain, it generates an error. You should place a backslash (\) before the "@" symbol to tell Perl to see it as a regular symbol, as in an email address. For example your email
This e-mail address is being protected from spam bots, you need JavaScript enabled to view it
should be set to
This e-mail address is being protected from spam bots, you need JavaScript enabled to view it
Error: I am getting the message "POST not implemented."
Cause & Solution: You are probably using the wrong reference for Sendmail. Another possibility is that you are pointing to a cgi-bin script that you have not put in your cgi-bin directory. In general, this message really means that the web server is not recognizing the cgi-bin script you are calling as a program. It thinks it is a regular text file.
Error: It's saying I don't have permission to access /
Cause & Solution: This error message means that you are missing your index.htm file. Note that files that start with a "." are hidden files. To see them, type ls -al. If you wish to FTP this file in, go to the home/yourdomain directory.
PHP
PHP is a server-side, cross-platform, HTML embedded scripting language. It has a syntax familiar to both Perl and C. PHP-enabled web pages are treated just like regular HTML pages and you can create and edit them the same way you normally create regular HTML pages. For more information check out www.php.net
PHP Tutorial from php.net
PHP is a tool that lets you create dynamic web pages. PHP-enabled web pages are treated just like regular HTML pages and you can create and edit them the same way you normally create regular HTML pages.
What do I need?
In this tutorial we assume that your server has support for PHP activated and that all files ending in .php are handled by PHP. On most servers this is the default extension for PHP files, but ask your server administrator to be sure. If your server supports PHP then you don't need to do anything. Just create your .php files and put them in your web directory and the server will magically parse them for you. There is no need to compile anything nor do you need to install any extra tools. Think of these PHP-enabled files as simple HTML files with a whole new family of magical tags that let you do all sorts of things.
Your first PHP-enabled page
Create a file named hello.php and in it put the following lines:
<html><head><title>PHP Test</title></head>
<body>
<?php echo "Hello World<p>"; ?>
</body></html>
The colours you see are just a visual aid to make it easier to see the PHP tags and the different parts of a PHP expression. Note also that this is not like a CGI script. The file does not need to be executable or special in any way. Think of it as a normal HTML file which happens to have a set of special tags available to you that do a lot of interesting things.
This program is extremely simple and you really didn't need to use PHP to create a page like this. All it does is display: Hello World
If you tried this example and it didn't output anything, chances are that the server you are on does not have PHP enabled. Ask your administrator to enable it for you.
The point of the example is to show the special PHP tag format. In this example we used <?php to indicate the start of a PHP tag. Then we put the PHP statement and left PHP mode by adding the closing tag, ?>. You may jump in and out of PHP mode in an HTML file like this all you want.
Something Useful
Let's do something a bit more useful now. We are going to check what sort of browser the person viewing the page is using. In order to do that we check the user agent string that the browser sends as part of its request. This information is stored in a variable. Variables always start with a dollar-sign in PHP. The variable we are interested in is $HTTP_USER_AGENT. To display this variable we can simply do:
<?php echo $HTTP_USER_AGENT; ?>
For the browser that you are using right now to view this page, this displays:
Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Q312461)
There are many other variables that are automatically set by your web server. You can get a complete list of them by creating a file that looks like this:
<?php phpinfo(); ?>
Then load up this file in your browser and you will see a page full of information about PHP along with a list of all the variables available to you.
You can put multiple PHP statements inside a PHP tag and create little blocks of code that do more than just a single echo. For example, if we wanted to check for Internet Explorer we could do something like this:
<?php
if(strstr($HTTP_USER_AGENT,"MSIE")) {
echo "You are using Internet Explorer<br>";
}
?>
Here we introduce a couple of new concepts. We have an "if" statement. If you are familiar with the basic syntax used by the C language this should look logical to you. If you don't know enough C or some other language where the syntax used above is used, you should probably pick up any introductory C book and read the first couple of chapters. All the tricky string and memory manipulation issues you have to deal with in C have been eliminated in PHP, but the basic syntax remains.
The second concept we introduced was the strstr() function call. strstr() is a function built into PHP which searches a string for another string. In this case we are looking for "MSIE" inside $HTTP_USER_AGENT. If the string is found the function returns true and if it isn't, it returns false. If it returns true the following statement is executed.
We can take this a step further and show how you can jump in and out of PHP mode even in the middle of a PHP block:
<?php
if(strstr($HTTP_USER_AGENT,"MSIE")) {
?>
<center><b>You are using Internet Explorer</b></center>
<?
} else {
?>
<center><b>You are not using Internet Explorer</b></center>
<?
}
?>
Instead of using a PHP echo statement to output something, we jumped out of PHP mode and just sent straight HTML. The important and powerful point to note here is that the logical flow of the script remain intact. Only one of the HTML blocks will end up getting sent to the viewer.
Dealing with Forms
One of the most powerful features of PHP is the way it handles HTML forms. The basic concept that is important to understand is that any form element in a form will automatically result in a variable with the same name as the element being created on the target page. This probably sounds confusing, so here is a simple example. Assume you have a page with a form like this on it:
<form action="action.php" method="post">
Your name: <input type="text" name="name">
You age: <input type="text" name="age">
<input type="submit">
</form>
There is nothing special about this form. It is a straight HTML form with no special tags of any kind. When the user fills in this form and hits the submit button, the action.php page is called. In this file you would have something like this:
Hi <?php echo $name; ?>.
You are <?php echo $age; ?> years old.
It should be obvious what this does. There is nothing more to it. The $name and $age variables are automatically set for you by PHP.
Useful Links
Python (info from Python.org)
python: (Gr. Myth. An enormous serpent that lurked in the cave of Mount Parnassus and was slain by Apollo) 1. any of a genus of large, non-poisonous snakes of Asia, Africa and Australia that suffocate their prey to death. 2. popularly, any large snake that crushes its prey. 3. totally awesome programming language.
Python is an interpreted, interactive, object-oriented programming language. It is often compared to Tcl, Perl, Scheme or Java.
Python combines remarkable power with very clear syntax. It has modules, classes, exceptions, very high level dynamic data types, and dynamic typing. There are interfaces to many system calls and libraries, as well as to various windowing systems (X11, Motif, Tk, Mac, MFC). New built-in modules are easily written in C or C++. Python is also usable as an extension language for applications that need a programmable interface.
The Python implementation is portable: it runs on many brands of UNIX, on Windows, DOS, OS/2, Mac, Amiga... If your favorite system isn't listed here, it may still be supported, if there's a C compiler for it. Ask around on comp.lang.python -- or just try compiling Python yourself.
Python is copyrighted but freely usable and distributable, even for commercial use.
Python is a portable, interpreted, object-oriented programming language. Its development started in 1990 at CWI in Amsterdam, and continues at CNRI in Reston, Va. The language has an elegant (but not over-simplified) syntax; a small number of powerful high-level data types are built in. Python can be extended in a systematic fashion by adding new modules implemented in a compiled language such as C or C++. Such extension modules can define new functions and variables as well as new object types.
Here's a simple function written in Python, which inverts a table (represented as a Python dictionary):
def invert(table):
index = {} # empty dictionary
for key in table.keys():
value = table[key]
if not index.has_key(value):
index[value] = [] # empty list
index[value].append(key)
return index
Note how Python uses indentation for statement grouping. Comments are introduced by a `#' character.
Basic Tutorial
There's a tradition in programming tutorials to always begin with a program that prints "Hello, world!" to the screen. In Python, this is quite simple:
print "Hello, world!"
This is basically like the recipe above (although it is much shorter!). It tells the computer what to do: To print "Hello, world!". Piece of cake. What if we would want it to do more stuff?
print "Hello, world!"
print "Goodbye, world!"
Not much harder, was it? And not really very interesting... We want to be able to do something with the ingredients, just like in the spam salad. Well what ingredients do we have? For one thing, we have strings of text, like "Hello, world!", but we also have numbers. Say we wanted the computer to calculate the area of a rectangle for us. Then we could give it the following little recipe:
# The Area of a Rectangle
# Ingredients:
width = 20
height = 30
# Instructions:
area = width*height
print area
You can probably see the similarity (albeit slight) to the spam salad recipe. But how does it work? First of all, the lines beginning with # are called comments and are actually ignored by the computer. However, inserting small explanations like this can be important in making your programs more readable to humans.
Now, the lines that look like foo = bar are called assignments. In the case of width = 20 we tell the computer that the width should be 20 from this point on. What does it mean that "the width is 20"? It means that a variable by the name "width" is created (or if it already exists, it is reused) and given the value 20. So, when we use the variable later, the computer knows its value. Thus,
width*height
is essentially the same as
20*30
which is calculated to be 600, which is then assigned to the variable by the name "area". The final statement of the program prints out the value of the variable "area", so what you see when you run this program is simply
600
Note: In some languages you have to tell the computer which variables you need at the beginning of the program (like the ingredients of the salad) Python is smart enough to figure this out as it goes along.
Feedback
OK. Now you can perform simple, and even quite advanced calculations. For instance, you might want to make a program to calculate the area of a circle instead of a rectangle:
radius = 30
print radius*radius*3.14
However, this is not significantly more interesting than the rectangle program. At least not in my opinion. It is somewhat inflexible. What if the circle we were looking at had a radius of 31? How would the computer know? It's a bit like the part of the salad recipe that says: "Cook 3 to 4 minutes or until SPAM is heated." To know when it is cooked, we have to check. We need feedback, or input. How does the computer know the radius of our circle? It too needs input... What we can do is to tell it to check the radius:
radius = input("What is the radius?")
print radius*radius*3.14
Now things are getting snazzy... input is something called a function. (You'll learn to create your own in a while. input is a function that is built into the Python language.) Simply writing
input
won't do much... You have to put a pair of parantheses at the end of it. So input() would work it would simply wait for the user to enter the radius. The version above is perhaps a bit more user-friendly, though, since it prints out a question first. When we put something like the question-string "What is the radius?" between the parentheses of a function call it is called passing a parameter to the function. The thing (or things) in the parentheses is (or are) the parameter(s). In this case we pass a question as a parameter so that input knows what to print out before getting the answer from the user.
But how does the answer get to the radius variable? The function input, when called, returns a value (like many other functions). You don't have to use this value, but in our case, we want to. So, the following two statements have very different meanings:
foo = input
bar = input()
foo now contains the input function itself (so it can actually be used like foo("What is your age?"); this is called a dynamic function call) while bar contains whatever is typed in by the user.
Flow
Now we can write programs that perform simple actions (arithmetic and printing) and that can receive input from the user. This is useful, but we are still limited to so-called sequential execution of the commands, that is they have to executed in a fixed order. Most of the spam salad recipe is sequential or linear like that. But what if we wanted to tell the computer how to check on the cooked spam? If it is heated, then it should be removed from the oven otherwise, it should be cooked for another minute or so. How do we express that?
What we want to do, is to control the flow of the program. It can go in two directions either take out the spam, or leave it in the oven. We can choose, and the condition is whether or not it is properly heated. This is called conditional execution. We can do it like this:
temperature = input("What is the temperature of the spam?")
if temperature > 50:
print "The salad is properly cooked."
else:
print "Cook the salad some more."
The meaning of this should be obvious: If the temperature is higher than 50 (centigrades), then print out a message telling the user that it is properly cooked, otherwise, tell the user to cook the salad some more.
Note: The indentation is important in Python. Blocks in conditional execution (and loops and function definitions see below) must be indented (and indented by the same amount of whitespace; a <tab> counts as 8 spaces) so that the interpreter can tell where they begin and end. It also makes the program more readable to humans.
Let's return to our area calculations. Can you see what this program does?
# Area calculation program
print "Welcome to the Area calculation program"
print "---------------------------------------"
print
# Print out the menu:
print "Please select a shape:"
print "1 Rectangle"
print "2 Circle"
# Get the user's choice:
shape = input("> ")
# Calculate the area:
if shape == 1:
height = input("Please enter the height: ")
width = input("Please enter the width: ")
area = height*width
print "The area is", area
else:
radius = input("Please enter the radius: ")
area = 3.14*(radius**2)
print "The area is", area
New things in this example:
print used all by iself prints out an empty line
== checks whether two things are equal, as opposed to =, which assigns the value on the right side to the variable on the left. This is an important distinction!
** is Python's power operator thus the squared radius is written radius**2.
print can print out more than one thing. Just separate them with commas. (They will be separated by single spaces in the output.)
The program is quite simple: It asks for a number, which tells it whether the user wants to calculate the area of a rectangle or a circle. Then, it uses an if-statement (conditional execution) to decide which block it should use for the area calculation. These two blocks are essentially the same as those used in the previous area examples. Notice how the comments make the code more readable. It has been said that the first commandment of programming is: "Thou shalt comment!" Anyway it's a nice habit to acquire.
Exercise:
Extend the program above to include area calculations on squares, where the user only has to enter the length of one side. There is one thing you need to know to do this: If you have more than two choices, you can write something like:
if foo == 1:
# Do something...
elif foo == 2:
# Do something else...
elif foo == 3:
# Do something completely different...
else:
# If all else fails...
Here elif is a mysterious code which means "else if" :). So; if foo is one, then do something; otherwise, if foo is two, then do something else, etc. You might want to add other options to the programs too like triangles or arbitrary polygons. It's up to you.
Loops
Sequential execution and conditionals are only two of the three fundamental building blocks of programming. The third is the loop. In the previous section I proposed a solution for checking if the spam was heated, but it was quite clearly inadequate. What if the spam wasn't finished the next time we checked either? How could we know how many times we needed to check it? The truth is, we couldn't. And we shouldn't have to. We should be able to ask the computer to keep checking until it was done. How do we do that? You guessed it we use a loop, or repeated execution.
Python has two loop types: while-loops and for-loops. For-loops are perhaps the simplest. For instance:
for food in "spam", "eggs", "tomatoes":
print "I love", food
This means: For every element in the list "spam", "eggs", "tomatoes", print that you love it. The block inside the loop is executed once for every element, and each time, the current element is assigned to the variable food (in this case). Another example:
for number in range(1,100):
print "Hello, world!"
print "Just", 100 - number, "more to go..."
print "Hello, world"
print "That was the last one... Phew!"
The function range returns a list of numbers in the range given (including the first, excluding the last... In this case, [1..99]). So, to paraphrase this:
The contents of the loop is executed for each number in the range of numbers from (and including) 1 up to (and excluding) 100. (What the loop body and the following statements actually do is left as an exercise.)
But this doesn't really help us with our cooking problem. If we want to check the spam a hundred times, then it would be quite a nice solution; but we don't know if that's enough or if it's too much. We just want to keep checking it while it is not hot enough (or, until it is hot enough a matter of point-of-view). So, we use while:
# Spam-cooking program
# Fetch the function sleep
from time import sleep
print "Please start cooking the spam. (I'll be back in 3 minutes.)"
# Wait for 3 minutes (that is, 3*60 seconds)...
sleep(180)
print "I'm baaack :)"
# How hot is hot enough?
hot_enough = 50
temperature = input("How hot is the spam? ")
while temperature < hot_enough:
print "Not hot enough... Cook it a bit more..."
sleep(30)
temperature = input("OK. How hot is it now? ")
print "It's hot enough - You're done!"
New things in this example...
Some useful functions are stored in modules and can be imported. In this case we import the function sleep (which sleeps for a given number of seconds) from the module time which comes with Python. (It is possible to make your own modules too...)
Exercise
Write a program that continually reads in numbers from the user and adds them together until the sum reaches 100. Write another program that reads 100 numbers from the user and prints out the sum.
Bigger Programs Abstraction
If you want an overview of the contents of a book, you don't plow through all pages you take a look at the table of contents, right? It simply lists the main topics of the book. Now imagine writing a cookbook. Many of the recipes, like "Creamy Spam and Macaroni" and "Spam Swiss Pie" may contain similar things, like spam, in this case - yet you wouldn't want to repeat how to make spam in every recipe. (OK... So you don't actually make spam... But bear with me for the sake of example :)). You'd put the recipe for spam in a separate chapter, and simply refer to it in the other recipes. So instead of writing the entire recipe every time, you only had to use the name of a chapter. In computer programming this is called abstraction.
Have we run into something like this already? Yup. Instead of telling the computer exactly how to get an answer from the user (OK - so we couldn't really do this... But we couldn't really make spam either, so there... :)) we simply used input - a function. We can actually make our own functions, to use for this kind of abstraction.
Let's say we want to find the largest integer that is less than a given positive number. For instance, given the number 2.7, this would be 2. This is often called the "floor" of the given number. (This could actually be done with built-in Python function int, but again, bear with me...) How would we do this? A simple solution would be to try all possibilities from zero:
number = input("What is the number? ")
floor = 0
while floor < number:
floor = floor+1
floor = floor-1
print "The floor of", number, "is", floor
Notice that the loop ends when floor is no longer less than the number; we add one too much to it. Therefore we have to subtract one afterwards. What if we want to use this "floor"-thing in a complex mathematical expression? We would have to write the entire loop for every number that needed "floor"-ing. Not very nice... You have probably guessed what we will do instead: Put it all in a function of our own, called "floor":
def floor(number):
result = 0
while result < number:
result = result+1
result = result-1
return result
New things in this example...
Functions are defined with the keyword def, followed by their name and the expected parameters in parentheses.
If the function is to return a value, this is done with the keyword return (which also automatically ends the function.
Now that we have defined it, we can use it like this:
x = 2.7
y = floor(2.7)
After this, y should have the value 2. It is also possible to make functions with more than one parameter:
def sum(x,y):
return x+y
Useful Links
|