About : POST

While working on a new project I was exploring what the content looks like when evaluating a form with method POST. Based on the aboutvars program I wrote the aboutpost source. Here it is:

MODULE	aboutpost;

IMPORT	Arguments, InOut, MemPools, Strings, SYSTEM, NumConv;

TYPE	VarPtr	= POINTER TO VarNode;
	VarNode	= RECORD
		    varName, value	: Strings.String;
		    next		: VarPtr
		  END;

VAR	envTab		: Arguments.ArgTable;
	Env0		: VarPtr;
	VarPool		: MemPools.MemPool;


PROCEDURE spaces (n : CARDINAL);

BEGIN
  WHILE  n > 0  DO  InOut.Write (" ");  DEC (n)  END
END spaces;


PROCEDURE Init;

BEGIN
  Arguments.GetEnv (envTab);
  MemPools.NewPool (VarPool);
  MemPools.PoolAllocate (VarPool, Env0, SYSTEM.TSIZE (VarNode));
END Init;


PROCEDURE Split (VAR src, dest  : Strings.String) : INTEGER;

VAR	delta, eq	: CARDINAL;

BEGIN
  eq := Strings.pos ("=", src);
  IF  eq > HIGH (src)  THEN   RETURN -1  END;
  delta := Strings.Length (src) - eq;
  Strings.Copy (src, eq + 1, delta, dest);
  src [eq] := 0C;
  RETURN eq
END Split;


PROCEDURE StoreEnv () : BOOLEAN;

VAR	this, prev		: VarPtr;
	result, i		: INTEGER;
	cgivar, load		: Strings.String;
	  
BEGIN
  this := Env0;		prev := NIL;
  i := 0;
  WHILE  envTab^ [i] # NIL  DO
    Strings.Assign (cgivar, envTab^ [i]^);
    IF  Split (cgivar, load) = -1  THEN
      InOut.WriteString ("String cannot be split! ");
      InOut.WriteString (cgivar);
      InOut.WriteLn;
      RETURN FALSE
    END;
    WITH  this^  DO
      varName := cgivar;
      value := load
    END;
    IF  prev # NIL  THEN  prev^.next := this  END;
    prev := this;
    MemPools.PoolAllocate (VarPool, this, SYSTEM.TSIZE (VarNode));
    IF  this = NIL  THEN
      InOut.WriteString ("Cannot allocate memory; aborting.");
      InOut.WriteLn;
      RETURN FALSE
    END;
    INC (i)
  END;
  this^.next := NIL;
  this^.varName := "The End";
  RETURN TRUE
END StoreEnv;


PROCEDURE SearchEnv (var  : Strings.String; VAR res  : Strings.String) : BOOLEAN;

VAR	this		: VarPtr;

BEGIN
  this := Env0;
  REPEAT
    IF  Strings.compare (var, this^.varName) = 0  THEN
      res := this^.value;
      RETURN TRUE
    END;
    this := this^.next
  UNTIL  this = NIL;
  RETURN FALSE
END SearchEnv;


PROCEDURE  ShowList;

VAR     thisOne		: VarPtr;
	str		: Strings.String;

BEGIN
  thisOne := Env0;
  REPEAT
    str := thisOne^.varName;
    spaces (24 - Strings.Length (str));
    InOut.WriteString (str);
    InOut.WriteString ("  =  ");
    InOut.WriteString (thisOne^.value);		InOut.WriteLn;
    thisOne := thisOne^.next
  UNTIL thisOne = NIL
END  ShowList;


PROCEDURE run;

VAR	ok	: BOOLEAN;
	n	: CARDINAL;
	str	: Strings.String;
	ch	: CHAR;

BEGIN
  InOut.WriteString ("Content-type:text/html");
  InOut.WriteLn;
  InOut.WriteLn;
  InOut.WriteString ("<html>");			InOut.WriteLn;
  InOut.WriteString ("<head><title>About : post</title></head>");
  InOut.WriteLn;
  InOut.WriteString ("<body>");			InOut.WriteLn;
  InOut.WriteString ("<h1>ABOUT : post</h1>");	InOut.WriteLn;
  InOut.WriteString ("<hr><pre>");		InOut.WriteLn;
  IF SearchEnv ("CONTENT_LENGTH", str) = TRUE  THEN  
    NumConv.Str2Num (n, 10, str, ok);
    IF  ok  THEN
      REPEAT
        InOut.Read (ch);	InOut.Write (ch);	DEC (n)
      UNTIL n = 0
    ELSE
      InOut.WriteString ("Error in Content length variable.<br>Aborting.<br>");
      InOut.WriteLn
    END
  END;
  InOut.WriteString ("</pre><hr>");		InOut.WriteLn;
  InOut.WriteString ("</body></html>");		InOut.WriteLn;
END run;

BEGIN
  Init;
  IF  StoreEnv () = TRUE  THEN  run  END
END aboutpost.
   
And it works great! As can be seen in the picture in the top right of this page. The 'aboutpost' executable is called from the form as follows:
<form action="/cgi-bin/aboutpost" method="post" enctype="text/plain">
but you may as well run it via the internet as in
<form action="https://verhoeven272.nl/cgi-bin/aboutpost" method="post" enctype="text/plain">
and the data is sent back and forth to/from my webhost.

Test it out yourself

Start by downloading source, test webpage and executable in aboutpost.tgz, install the 'aboutpost' executable in /var/www/cgi-bin and then run the webpage extracted from the TGZ archive. aboutpost.html

Source of aboutpost.html

Below is the sourcecode of the HTML file that launches the aboutpost executable:

<!doctype html>
<html lang="en">

 <head>
  <meta charset	= 'utf-8'>
  <title>CGI testing : about post</title>
  <link type="text/css" rel="stylesheet" href="../frutt.css">
 </head>
 
 <body>
  <form action="http://localhost/cgi-bin/aboutpost" method="post" enctype="text/plain">
  <textarea name="tekst" rows="10" cols="40">Jantje zag eens pruimen hangen, als eieren zo groot</textarea>
   <table>
    <tr>
     <td><input type="hidden" name="Done" value="Klaar"></td>
     <td><input type="submit" value="About Post!"></td>
    </tr>
   </table>
  </form>

  <p class="summ">
   Page created then,
   <script>
    let date = new Date (document.lastModified);
    document.write ("last revised on " + date.toDateString() + "<br>");
    document.write ("This page located at " + document.URL + "<br>");
   </script>
  </p>
 </body>
</html>
   
AboutPost reads data from the webserver and prints it on screen. Therfore this CGI program must be launched from a form that supplies text data. It will not run from a URL bar entry.


Page created on 24 March 2013 and