Cover V06, I08
Article
Listing 1
Listing 2
Listing 3
Listing 4

aug97.tar


Listing 1: CGI.java

// CGI framework class

import java.io.PrintStream;
import java.io.InputStream;
import java.io.IOException;

import java.util.Enumeration;
import java.util.Vector;
import java.util.Hashtable;
import java.util.Properties;
import java.util.StringTokenizer;

public class CGI {
public static void main(String[] argv) {
CGI cgi = new CGI();
cgi.handle(argv);
}

protected PrintStream outputStream = System.out;

// basic logic for handling a request

protected void handle(String[] argv) {
printHeader();            // make sure that the header gets out
// at least, so that any error messages
// will be displayedin the browser
try {
if (argv.length > 0) {  // are there variables on the command line?
setupVariables(argv);
}
else {
setupVariables();
}
printBody();
}
catch (Exception e) {      // output error message in case of Exception
outputStream.println("Error: " + e);
}
outputStream.println("</HTML>");
}

protected void printHeader() {
outputStream.println("Content-type: text/html\n");
outputStream.println("<HTML>");
}

// default printBody, prints out all of the CGI variables

protected void printBody() throws Exception {
outputStream.println("<HEAD><TITLE>Variables</TITLE></HEAD>");
outputStream.println("<H2>Variables</H2><P>");
outputStream.println("<PRE>");

Enumeration e = getVariables();
while(e.hasMoreElements()) {
String key = (String) e.nextElement();
Enumeration valuesEnum = getValues(key);
while (valuesEnum.hasMoreElements()) {
outputStream.println(key  + " = " + valuesEnum.nextElement());
}
}
outputStream.println("</PRE>");
outputStream.println("</BODY>");
}

// gets a header (environment) variable

public String getHeader(String name) {
String result = System.getProperty(name);
if (result == null) {
result = "";
}
return result;
}

// get request method, either GET or POST

public String getMethod() {
return getHeader("REQUEST_METHOD");
}

// return the value associate with a variable name
// if there are multiple values, return the first value
// if there is no value, return the empty string

public String getValue(String name) {
if (variables != null) {
Enumeration enum = getValues(name);
if (enum.hasMoreElements()) {
return (String) enum.nextElement();
}
}
return "";
}

// get all of the values associated with a variable name
// returning an Enumeration so that they can be iterated over

public Enumeration getValues(String name) {
Object o = variables.get(name);

if ((o != null) && (o instanceof Vector)) {
return ((Vector)o).elements();
}
Vector v = new Vector();
if (o != null) {
v.addElement(o);
}
return v.elements();
}

// has the variable been assigned any value?

public boolean hasValue(String name) {
Object o = variables.get(name);
return (o != null);
}

public boolean hasMultipleValues(String name) {
Object o = variables.get(name);
return ((o != null) && (o instanceof Vector));
}

// return an Enumeration of all of the variables that
// have been defined

public Enumeration getVariables() {
return variables.keys();
}

// save a variable/value pair,or if the variable already
// has a value, add another value to the variable. Primarily used
// by setupVariables() (see above), this can also be used
// by subclass code for temporary variable storage

public void setValue(String name, String value) {
Object o = variables.get(name);
if (o != null) {
if (o instanceof Vector) {
((Vector)o).addElement(value);
}
else {
Vector v = new Vector();
v.addElement(o);
v.addElement(value);
variables.put(name,v);
}
}
else {
variables.put(name,value);
}
}

//----------------------------------------------------------------
// private variables and methods
//----------------------------------------------------------------

private String queryString = "";
private Hashtable variables = new Hashtable(); // internal storage
// of variables
private InputStream inputStream = System.in;

// gets the QUERY_STRING from the environment variable or from
// standard input (if POST), and set up the variables

private void setupVariables() {
if (System.getProperty("QUERY_STRING") != null)  {
queryString = System.getProperty("QUERY_STRING");
}

int requestContentLength = 0;
if (System.getProperty("CONTENT_LENGTH") != null)  {
try {
requestContentLength = \
Integer.parseInt(System.getProperty("CONTENT_LENGTH"));
}
catch (NumberFormatException nfe) {
}
}

try {
if ((getHeader("REQUEST_METHOD").equals("POST")) && \
(requestContentLength > 0)) {
byte[] b = new byte[requestContentLength];
int count = inputStream.read(b);    // read variables from
// standard input
queryString = new String(b,0,0,count);
}
}
catch (IOException e) {
queryString = "";
}
createVariables();
}

// sets variables up by getting the arguments from the command line
// useful for invoking the CGI from command line for testing

private void setupVariables(String[] argv) {
int firstArg = 0;
Properties properties = new Properties(System.getProperties());

StringBuffer b = new StringBuffer();
for (int i = firstArg; i < argv.length; i++) {
if (argv[i].startsWith("-H")) {      // handle "fake"
// environment variables
int equalIndex = argv[i].indexOf("=");
if (equalIndex >= 0) {
properties.put(argv[i].substring(2,equalIndex),
argv[i].substring(equalIndex+1));
}
}
else {                  // add argument to the query string
if (b.length() > 0) { b.append("&"); }
b.append(argv[i]);
}
}
queryString = b.toString();
createVariables();

System.setProperties(properties);      // add "fake" environment
// to System properties

}

// takes a query string and creates variables and values from them

private void createVariables() {
if (queryString == null) { return; }

// split up the string along "&" characters

StringTokenizer tokenizer = new StringTokenizer(queryString, "&");
while (tokenizer.hasMoreTokens()) {
String pair = decodeString(tokenizer.nextToken());
int equalIndex = pair.indexOf('=');    // split into key and
// value components
if ((equalIndex >= 0) && (pair.length() != (equalIndex + 1))) {
setValue(pair.substring(0,equalIndex),pair.substring(equalIndex + 1));
}
}
}

// query strings encode special characters as "%XX", where XX is
// the hexidecimal character number of the character. In addition,
// an "+" character is mapped to a space

private String decodeString(String s) {
// decode arguments
StringBuffer b = new StringBuffer(s.length());
int i = 0;
while (i < s.length()) {
char c = s.charAt(i++);
if (c == '+') {
c = ' ';
}
else if (c == '%') {
try {
char c1 = s.charAt(i++);
char c2 = s.charAt(i++);
c = (char) Integer.parseInt(""+c1+c2,16);
}
catch (NumberFormatException e) {
}
}
b.append(c);
}
return b.toString();
}
}

// End of File