CSCI A348/548
Lecture Notes Four

Spring 2001 (Second semester 2000-2001)


Simple CGI scripting.

In this lab you will write a script that returns a random image from a predetermined sequence of available images every time it is invoked. The script includes in its output a link to its own URL to make it easy for the user to call the script over and over again (without having to reload the page). Here's a demo of the script you will be building in this lab. This should help you with your next homework assignment and will help you get started with CGI.

Log into your burrowww account and go straight to your cgi-bin directory. Write the hello script that returns the following simple HTML page as output:

<html>
<head>
<title>
the hello script 
</title>
</head>
<body bgcolor=white>
<h1>Hello!</h1> 
<img src="http://www.cs.indiana.edu/dept/img/lh08.gif">
</body>
</html>
Eseentially this means writing this script:
#!/usr/bin/perl
 
print qq{Content-type: text/html\n\n<html>
  <head>
  <title>
  the hello script
  </title>
  </head>
  <body bgcolor=white>
  <h1>Hello!</h1> 
  <img src="http://www.cs.indiana.edu/dept/img/lh08.gif">
  </body>
  </html>
};
Then run the script from the command line
./hello
and also invoke it from Netscape, over the web:
http://burrowww.cs.indiana.edu:20xxx/cgi-bin/hello
Here's a working version of the script installed on my server.

Let's summarize what the script does: it always always gives me the same picture.

Now let's modify the script a little. Copy

hello
into
helloTwo
in the same directory (cgi-bin).

Then make the following changes into the new script, as indicated below, in blue.

#!/usr/bin/perl

$imgname = "lh08.gif"; 

print qq{Content-type: text/html\n\n<html>
  <head>
  <title>
  the helloTwo script 
  </title>
  </head>
  <body bgcolor=white>
  <h1>Hello!</h1> 
  <img src="http://www.cs.indiana.edu/dept/img/$imgname">
  </body>
  </html>
};
So you need to add a line and change a line.

Check the new script from the command line and from the web.

Here's my version of helloTwo.

It works exactly as the one before, except that in the URL that's used to identify the image (in the image tag,) a string that contains the name of the image is interpolated (included) at the time the line is written out. This may not look like a significant change but it really is.

Copy

helloTwo
into
helloThree
and make the following changes to it:
#!/usr/bin/perl

@images = ("lh08.gif", "lh07.gif", "lh09.gif", "lh01.gif");  
 
$imgname = $images[0]; 
 
print qq{Content-type: text/html\n\n<html>
  <head>
  <title>
  the helo three script 
  </title>
  </head>
  <body bgcolor=white>
  <h1>Hello!</h1> 
  <img src="http://www.cs.indiana.edu/dept/img/$imgname">
  </body>
  </html>
};
Again, the parts in blue are new, the rest is unchanged (compared to helloTwo).

Before you try the script think about the changes.

We still show one and the same image, but the name of the image is in a string variable, and we have more than one such string available in a list of strings. All these strings represent names of images located on the departmental web server, and with an index we can scan the entire list.

Can we pick a random image everytime the script is invoked?

Yes, if we use a variable $index and set it to random values between 0 and $#names (including) and then use it as an index when we set the value for the string $imgname.

That takes us to

helloFour
that looks like this:
#!/usr/bin/perl
 
@images = ("lh08.gif", "lh07.gif", "lh09.gif", "lh01.gif");  
 
$index = int(rand($#images + 1)); 
 
$imgname = $images[$index]; 
 
print qq{Content-type: text/html\n\n<html>
  <head>
  <title>
  the hello four script 
  </title>
  </head>
  <body bgcolor=white>
  <h1>Hello!</h1> 
  <img src="http://www.cs.indiana.edu/dept/img/$imgname">
  </body>
  </html>
};
And behaves like this (don't forget to reload the page).

Type man perlfunc at the prompt. What does the rand do?

The last thing we do is to provide a link to the program itself in the HTML file that is its output. This way the user does not need to reload the page for a new image, (s)he can click on the link on the page and obtain a new image).

This is helloFive

#!/usr/bin/perl
 
@images = ("lh08.gif", "lh07.gif", "lh09.gif", "lh01.gif");  
 
$index = int(rand($#images + 1)); 
 
$imgname = $images[$index]; 
 
print qq{Content-type: text/html\n\n<html>
  <head>
  <title>
  in-lab assignment 1
  </title>
  </head>
  <body bgcolor=white>
  <h1>Hello!</h1> 
 
  <p> The image below has index $index. <p> Click <a href=
  "http://burrowww.cs.indiana.edu:20006/cgi-bin/helloFive">here</a> 
  for a new random image. <p>  

  <img src="http://www.cs.indiana.edu/dept/img/$imgname">
 
  </body>
  </html>
};
And here's a working version of helloFive.

This completes our introduction to scripting.

We're now ready for serious CGI scripts (next week).


Now here's a supplement to these notes, in case you're curious.

What a simple server looks like.

burrowww.cs.indiana.edu% cat echo 
#!/usr/bin/perl

while ($x = <STDIN>) {
  print "Echo: ", $x;
} 

burrowww.cs.indiana.edu% ./echo
Hello. 
Echo: Hello. 
What's up.
Echo: What's up. 
You repeat everything don't you.
Echo: You repeat everything don't you.
I said it first
Echo: I said it first
Bye
Echo: Bye
^Cburrowww.cs.indiana.edu%
And here's how we could write a simple perl server.

#!/usr/bin/perl

use IO::Socket;

$sock = new IO::Socket::INET ( LocalHost => 'www.burrow.cs.indiana.edu',
                               LocalPort => 10000, 
                               Proto => 'tcp', 
                               Listen => 5,
                               Reuse  => 1 
                             ); 

die "Socket could not be create. Reason: $!" unless $sock; 

while ($new_sock = $sock->accept()) {
  while (defined ($buf = <$new_sock>)) {
    print $new_sock "Echo: ", $buf; 
  } 
} 

close($sock); 
In the process we introduce a few networking concepts, reproduced below.

The networking world assigns each computer an internet address, also called an IP address (short for Internet Protocol), a sequence of four numbers typically written in a dot sequence. Just as you have phone aliases, computers are often given unique aliases, called DNS names. The IP number of the machine you're working can be found easily but it's easier to remember the name.

burrowww.cs.indiana.edu% nslookup www.burrow.cs.indiana.edu
Server:  moose.cs.indiana.edu
Address:  129.79.254.191

Name:    burrowww.cs.indiana.edu
Address:  129.79.245.98
Aliases:  www.burrow.cs.indiana.edu

burrowww.cs.indiana.edu% 
The program above uses Graham Barr's IO library (part of the standard Perl distribution) to illustrate a few points on networking. The description that follows (and the program above) are both taken from Sriram Srinivasan's "Advanced Perl Programming" that you could borrow from me. Here we go:

Just as you would ask the phone company for a telephone number and a physical handset, both the sender and receiver ask the module to create sockets. Sockets, like telephones, are bidirectional endpoints: once a connection is established, either side can send and receive data, as long as there is an understanding between the two programs about the direction of communication.

Because only the receiving side needs to have a well-known address, we create the receiving socket as follows (this is an excerpt from the program above):

use IO::Socket;

$sock = new IO::Socket::INET ( LocalHost => 'www.burrow.cs.indiana.edu',
                               LocalPort => 10000, 
                               Proto => 'tcp', 
                               Listen => 5,
                               Reuse  => 1 
                             ); 

die "Socket could not be create. Reason: $!" unless $sock;
The IO::Socket::INET module provides a nice wrapper for Internet domain sockets. The LocalHost and LocalPort parameters specify the host and port on which this socket is going to listen.

So overall it looks as if we import java.util; when we need a HashTable.

We then create the desired object using the new operator, and we specify the parameters to the constructor:

Once created, the socket is all set to receive incoming calls. The accept() method listens on the given port until another program attempts to connect to it. At this point, accept returns a new socket:

$new_sock = $sock->accept();

This is analoguous to a switchboard operator indicating a different handset for you to converse on, while he goes back to waiting for the main number to ring. Messages sent by the client can now be obtained by reading from $new_sock. You can use this socket as a filehandle and call any of the input operators, such as <>. It will return undef on an end of file condition.

Once you receive something you write it back to the socket.

Here's how you start the server:

burowww.cs.indiana.edu% ./server

And here's how you access it from some other machine, e.g. tucotuco.cs.indiana.edu:

tucotuco.cs.indiana.edu% telnet www.burrow.cs.indiana.edu 10000
Trying 129.79.245.98...
Connected to burrowww.cs.indiana.edu.
Escape character is '^]'.
I am here
Echo: I am here
You don't say...
Echo: You don't say...
OK, I need to go now
Echo: OK, I need to go now
Bye.
Echo: Bye.
^C^?
^D

Connection closed by foreign host.tucotuco.cs.indiana.edu% 


Last updated on Jan 18, 2001, by Adrian German for A348/A548