CGI Add example

The following CGI script expects two variables in the query string that specifies the two integers to add together.

AddCgi.java
public class AddCgi {

    private static long[] parseParams( String query )
	throws NumberFormatException, IllegalArgumentException
    {
        long[] result = new long[2];

        String [] params = query.split("&");
	for( int i = 0 ; i < params.length; i++ ) {
	    String [] words = params[i].split("=");
	    if ( words.length != 2 ) continue;
	    if ( words[0].equals("a") ) {
	        result[0] = Long.parseLong( words[1] );
	    }
	    else if ( words[0].equals("b") ) {
	        result[1] = Long.parseLong( words[1] );
	    }
	    else {
		throw new IllegalArgumentException("unknown param");
	    }
	}
	return result;
    }

    public static void main( String[] args ) {
	long[] params;
	try {
	    params = parseParams( System.getenv("QUERY_STRING") );
	}
	catch( Exception ex ) {
	    System.out.print("Content-Type: text/plain\r\n\r\n");
	    System.out.println(ex.getMessage() );
	    return;
	}
	long a = params[0];
	long b = params[1];
	System.out.print("Content-Type: text/html\r\n\r\n");
	System.out.println("<html>" );
	System.out.println("<body>" );
	System.out.println("<h1>" );
	System.out.println("Sum of " + a + " + " + b + " = " + (a+b) );
	System.out.println("</h1>" );
	System.out.println("</body>" );
	System.out.println("</html>" );
    }
}

Testing the script

The add cgi script can be tested with the mini-webserver.py web server and the following directory setup. The base directory contains:

The cgi-bin directory contains:

The cgi-bin script contains:

add.sh
#!/bin/sh
exec java -cp cgi-bin AddCgi

The add-form.html document contains:

add-form.html
<html>
<head>
</head>
<body>
<p>
Calculate the sum of:
</p>
<form action="cgi-bin/add.sh">
<label>A:
<input type="text" name="a"  value="0" size="5">
</label>
<label>B:
<input type="text" name="b"  value="0" size="5">
</label>
<input type="submit" value="add">
</form>
</body>
</html>

The mini-webserver.py program contains:

mini-webserver.py
#!/usr/bin/python
import sys
import CGIHTTPServer
import BaseHTTPServer

# Use supplied port
if sys.argv[1:] :
    port = int(sys.argv[1])
else :
    port = 8000

#
# set up and run the server
#
addr = ('',port)
handler = CGIHTTPServer.CGIHTTPRequestHandler
httpd = BaseHTTPServer.HTTPServer(addr, handler)
sa = httpd.socket.getsockname()
print "Serving HTTP on", sa[0], "port", sa[1], "..."
httpd.serve_forever()

Running the CGI script

If the mini-webserver.py is run with the command python mini-webserver.py then the line: http://localhost:8000/add-form.html will access the HMTL form that submits a request to the add cgi script.

The script can be invoked without a web browser with the command:

wget http://localhost:8000/cgi-bin/add.sh?a=2\&b=3

or with the command

curl -O http://localhost:8000/cgi-bin/add.sh?a=2\&b=3

The above commands can be used to test a web site during development. They are also used to copy documents from web sites.

A counter CGI script

In the early days of the WEB a cgi scripts that counted that number of times that a page was accessed was very common. Here is a simple script that counts the number of times it was accessed.

CounterCgi.java
import java.io.File;
import java.io.RandomAccessFile;

public class CounterCgi {
    public static void main( String[] args ) {
	int count = -1;
	try {
	    File file = new File("counter");
	    boolean flag =  file.exists() ;
	    RandomAccessFile fw = new RandomAccessFile( file, "rws" );
	    // handle an initially empty file
	    if ( flag ) {
		fw.seek( 0 );
		count = fw.readInt();
	    }
	    else {
		count = 0;
	    }
	    fw.seek( 0 );
	    fw.writeInt( count+1 );
	    fw.close();
	}
	catch( Exception ex ) {
	    // ignore exception, use count -1 to indicate error
	}
	System.out.print("Content-Type: text/html\r\n\r\n");
	System.out.println("<html>" );
	System.out.println("<body>" );
	System.out.println("<h1>" );
	if ( count < 0 ) {
	    System.out.println( "Error in accessing count file" );
	}
	else {
	    System.out.printf( "Count is %07d", count );
	}
	System.out.println("</h1>" );
	System.out.println("</body>" );
	System.out.println("</html>" );
    }
}

A link to the script is: http://www.cs.mun.ca/cgi-bin/user-cgi/~yzchen/cs3715/Counter/counter.sh .

An image counter

The Java API provides packages and classes for the creation of images. The following CGI script can be used as a page counter.

ImgCounterCgi.java
import java.io.File;
import java.io.IOException;
import java.awt.image.BufferedImage;
import java.awt.Graphics2D;
import java.awt.Color;
import java.awt.Font;
import java.awt.FontMetrics;
import javax.imageio.ImageIO;
import java.awt.geom.Rectangle2D;
import java.io.RandomAccessFile;

public class ImgCounterCgi {

    public static void writePNGImageString(
	int imgWidth, int imgHeight, String str ) throws IOException
    {
        BufferedImage image =
	    new BufferedImage( imgWidth, imgHeight, BufferedImage.TYPE_3BYTE_BGR);
	Graphics2D g2d = image.createGraphics(); 
	Font f = new Font( "Monospaced", Font.BOLD, 14 );
	g2d.setFont( f );
	FontMetrics fm = g2d.getFontMetrics();
	g2d.setColor( Color.white );
	g2d.fillRect(0, 0, imgWidth, imgHeight );
	g2d.setColor( Color.red );

	Rectangle2D bounds = fm.getStringBounds( str, g2d );
	int w = (int)bounds.getWidth();
	int h = (int)bounds.getHeight();
	int x = (imgWidth - w)/2;
	int y = imgHeight - (imgHeight - h)/2;
	g2d.drawString( str, x, y );

	ImageIO.write(image, "png", System.out );
    }
    public static void main( String[] args ) {
	int count = -1;
	try {
	    File file = new File("counter");
	    boolean flag =  file.exists() ;
	    RandomAccessFile fw = new RandomAccessFile( file, "rws" );
	    // handle an initially empty file
	    if ( flag ) {
		fw.seek( 0 );
		count = fw.readInt();
	    }
	    else {
		count = 0;
	    }
	    fw.seek( 0 );
	    fw.writeInt( count+1 );
	    fw.close();
	}
	catch( Exception ex ) {
	    // ignore exception, use count -1 to indicate error
	}
	String str;
	if ( count < 0 ) {
	    str = "no count";
	}
	else {
	    str = String.format( "%07d", count );
	}
	try {
	    System.out.print("Content-Type: image/png\r\n\r\n");
	    writePNGImageString( 90, 20, str );
	}
	catch( Exception ex ) {
	}
    }
}

How can the writePNGImageString method be made more useful?

This page provides a web pages that links to the image counter script. The source of the page is:

count.html
<html>
<body>
<p>
A counter
<img src="http://www.cs.mun.ca/cgi-bin/user-cgi/~yzchen/cs3715/Counter/img.sh">
</p>
</body>
</html>