(******************************************************************************************** ** PROGRAM : cgiform ** VERSION : 1.0.0 ** DESCRIPTION : Demonstrates how to process HTML forms in CGI programs. ** AUTHOR : Stuart King ** COPYRIGHT : Copyright (c) Irie Tools, 2002. All Rights Reserved. ** NOTES : ** This sample program is distributed with Irie Pascal, and was written to illustrate ** how to process HTML forms. To make best use of this sample you should have a basic ** understanding of Pascal as well as a basic understanding of the Common Gateway Interface ** (CGI). ** ** HTML forms provide a way for websites to receive input from visitors, and to process ** this input in some way. HTML forms contain different kinds of input elements in order ** to conveniently receive different kinds of visitor input. The most common kinds of ** input elements are: ** 1. One line text entry boxes ** 2. Multi-line text entry boxes ** 3. Checkboxes ** 4. Radio buttons ** 5. Hidden fields ** 6. Selection lists (Drop-down menus and List boxes). ** 7. Reset button ** 8. Submit button ** ** HTML forms have action attributes that indicate what should happen when the submit ** button is clicked. It is very common for the action attribute to point at the URL of ** a CGI program. In this case when the submit button is pressed the CGI program is executed ** and the form's input is passed to the program for processing. Each input element in the ** form has a name and the form's input is sent to the CGI program in the form of name/value ** pairs, where the values are the input received by the input elements. ** ** What this program actually does is retrieve any form input passed to it. If it receives ** form input then this program just displays the name/value pairs, along with a link that ** can be used to execute the program again. If the program does not receive any form input ** then it displays a form with a variaty of input elements. The form's action element points ** back to the program, so that the program will receive the input from the form when the ** submit button is pressed. **********************************************************************************************) program cgiform; const MAX_BUFFER = 8000; MAX_NAME = 20; MAX_VALUE = 400; type positive = 0..maxint; BufferType = string[MAX_BUFFER]; NameValuePair = record Name : string[MAX_NAME]; Value : string[MAX_VALUE] end; var buffer : BufferType; NameValuePairs : list of NameValuePair; ScriptName : filename; function EscapeCharacters(s : string) : string; forward; //PURPOSE: Initializes the program //NOTES: // Initializes the list that will be used to store the name/value pairs //passed to the program. The program also retrieves it's name so that it can //refer to itself in the generated response. procedure Initialize; begin (* Initialize *) new(NameValuePairs); ScriptName := getenv('SCRIPT_NAME'); end; (* Initialize *) //PURPOSE: Retrieves the information passed to the CGI applications. //GLOBAL(s) - buffer - Used to store the GET or POST information passed to the CGI program procedure GetCGIData; var RequestMethod : string; //PURPOSE: Retrieves information sent to by a GET request (i.e. in the QUERY_STRING // environment variable). procedure GetRequest; begin (* GetRequest *) buffer := getenv('QUERY_STRING') end; (* GetRequest *) //PURPOSE: Retrieves information sent to by a POST request (i.e. through the standard // input stream, with the length of the data in the environment variable // CONTENT_LENGTH). procedure PostRequest; var len, i : positive; err : integer; ContentLength : string; c : char; begin (* PostRequest *) buffer := ''; ContentLength := getenv('CONTENT_LENGTH'); if ContentLength <> '' then val(ContentLength, len, err) else len := 0; if len <= MAX_BUFFER then for i := 1 to len do begin read(c); buffer := buffer + c end end; (* PostRequest *) begin (* GetCGIData *) RequestMethod := getenv('REQUEST_METHOD'); if RequestMethod = 'GET' then GetRequest else PostRequest end; (* GetCGIData *) //PURPOSE: Process the data passed to the program. //NOTES: This is the main part of the program. After retreiving // the information passed to the program this procedure is // called to perform the required processing. procedure ProcessCGIData; var i, num, p : integer; EncodedVariable, DecodedVariable, name, value : string; //PURPOSE: Processes the named value pairs sent with the GET or POST request. // Which in this case is the information entered by the user about the // cookie to add or delete. //ARGUMENT(s): name - name part of the name/value pair // value - value part of name/value pair //NOTES: // The information entered by the user is sent as name/value pairs (i.e. name-value) //with the name part being the name of the form element holding the information and //the value part being the actual information held by the form element. procedure ProcessNameValuePair(var name, value : string); var pair : NameValuePair; begin (* ProcessNameValuePair *) pair.name := name; pair.value := value; insert(pair, NameValuePairs); end; (* ProcessNameValuePair *) begin (* ProcessCGIData *) //Retrieve each name/value pair from the form and processes them. num := CountWords(buffer, '&'); for i := 1 to num do begin EncodedVariable := CopyWord(buffer, i, '&'); DecodedVariable := URLDecode(EncodedVariable); p := pos('=', DecodedVariable); if p > 0 then begin name := lowercase(trim(copy(DecodedVariable, 1, p-1))); value := trim(copy(DecodedVariable, p+1)); ProcessNameValuePair(name, value); end end; end; (* ProcessCGIData *) //PURPOSE: Generates the response to send back to the browser. procedure GenerateResponse; procedure GenerateHeader; begin (* GenerateHeader *) //Generate the response headers (including the blank line at the end). writeln('content-type: text/html'); writeln; writeln(''); writeln(''); writeln('Irie Pascal sample CGI application'); writeln('

CGIFORM

'); writeln('

This program displays the data entered into a form.

'); writeln(''); writeln('
'); end; (* GenerateHeader *) procedure GenerateBody; procedure WriteForm; begin (* WriteForm *) writeln('
'); writeln('

One Line Text Box:

'); writeln('

OneLine

'); writeln('
'); writeln('

Scrolling Text Box:

'); writeln('

Scrolling

'); writeln('
'); writeln('

Check Boxes

'); writeln('

Box1 '); writeln('         Box2

'); writeln('

Box3 '); writeln('         Box4

'); writeln('
'); writeln('

Radio Buttons

'); writeln('

Radio1 '); writeln('         Radio2

'); writeln('

Radio3 '); writeln('         Radio4

'); writeln('
'); writeln('

Drop-Down Menu

'); writeln('

DropDown

'); writeln('
'); writeln('

'); writeln('
'); end; (* WriteForm *) procedure WriteFormData; var pair : NameValuePair; i : positive; begin (* WriteFormData *) writeln('

Form Data

'); for i := 1 to length(NameValuePairs) do begin pair := NameValuePairs[i]; writeln('

', EscapeCharacters(pair.name), ' = ', EscapeCharacters(pair.value), '

'); end; writeln('
'); writeln('

Click here to go back to the form.

'); end; (* WriteFormData *) begin (* GenerateBody *) writeln(''); if length(NameValuePairs) = 0 then begin //Generate the HTML for the form WriteForm; end else begin //Generate the HTML that displays the form data WriteFormData; end; writeln(''); end; (* GenerateBody *) procedure GenerateFooter; begin (* GenerateFooter *) writeln(''); end; (* GenerateFooter *) begin (* GenerateResponse *) GenerateHeader; GenerateBody; GenerateFooter; end; (* GenerateResponse *) procedure Shutdown; begin (* Shutdown *) dispose(NameValuePairs); end; (* Shutdown *) //************************************************************************* //PURPOSE: This function converts certain characters that have a // special meaning in HTML documents to their HTML representation. //ARGUMENT(s): s - The string to be escaped. //RETURNS: The string with all special characters escaped. //NOTES: The characters converted are < > " function EscapeCharacters; const LessThanChar = '<'; GreaterThanChar = '>'; QuoteChar = '"'; HTMLLessThan = '<'; HTMLGreaterThan = '>'; HTMLQuote = '"'; var i : positive; procedure ReplaceChar(var strBuffer : string; strReplace : string; i : positive); begin (* ReplaceChar *) delete(strBuffer, i, 1); insert(strReplace, strBuffer, i) end; (* ReplaceChar *) begin (* EscapeCharacters *) repeat i := pos(LessThanChar, s, 1); if i > 0 then ReplaceChar(s, HTMLLessThan, i) until i = 0; repeat i := pos(GreaterThanChar, s, 1); if i > 0 then ReplaceChar(s, HTMLGreaterThan, i) until i = 0; repeat i := pos(QuoteChar, s, 1); if i > 0 then ReplaceChar(s, HTMLQuote, i) until i = 0; EscapeCharacters := s; end; (* EscapeCharacters *) begin Initialize; GetCGIData; ProcessCGIData; GenerateResponse; Shutdown; end.