CLI, Forms, and Lynxcgi

Do you have a question? Post it now! No Registration Necessary.  Now with pictures!

CLI, Forms, and Lynxcgi

This is about how to interact with PHP CLI scripts, using lynxcgi[1].  Some
alternatives would be to use readline() or the ncurses functions.  For
simple prompt and response situations, there is no doubt that readline is
the best choice.  The ncurses functions, still not well documented, are
removed to PECL and are implemented only on certain platforms.  This is not
much of drawback compared to using lynxcgi which is restricted to unix-like
platforms.  The main motivation for using the lynxcgi approach is that HTML
forms, as implemented in lynx, already have a set of text widgets which will
suit many purposes.  Ncurses would certainly be better for interactive
games, ANSI animations, and similar applications.

Shell call to a PHP CLI form:

php /usr/home/blosxom/screens/test.php | lynx -stdin

This is an example of a line in an sh script which could be used wherever
sh will be invoked, such as in a Makefile.  It will also work if entered
at the sh prompt.  This is likely to work in most other shells, but as I
am particularly interested in Makefiles, I am using sh.

At this point, lynxcgi has not come into it.  test.php could simply generate
a message for lynx to display.

Since test.php is executable and has a shebang line, it is not really
necessary to invoke php explicitly:

/usr/home/blosxom/screens/test.php | lynx -stdin


test.php generates an html form.  If it is invoked by php explicitly, it
does not need the shebang to produce the HTML.  But there isn't really a
server, so it needs the shebang to handle the action of the form.  As it is,
the action is "lynxcgi:$_SERVER["PHP_SELF"]".  lynxcgi could be pointed
elsewhere, but to do anything with the form data, elsewhere would have to be
executable and have a shebang.

If you use another kind of executable for the action, you may have to make
it send (echo/print) the cgi header.  It is not clear to me why you don't
with PHP CLI.  Apparently, although according to phpinfo() it is still the
CLI API, PHP knows to send a Content-type header because lynxcgi has dummied
up enough of a server-like environment.  Nonetheless, PHP still acts like
CLI in many ways which is why phpinfo() needs to be in PRE.

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
     " ">


<title>Test Screen</title>


<h1>Test Screen</h1>


echo '<p>Hello, world!</p>';

//echo '<pre>';
//echo '</pre>';

echo '<form action="lynxcgi:',$_SERVER["PHP_SELF"],'" method="GET">';
echo '<p>email <input type="text" name="Email"></p>';
echo '<p>Male <input type="radio" name="sex" value="Male"></p>';
echo '<p>Female <input type="radio" name="sex" value="Female"></p>';
echo '<p>body</p> <input type="textarea" name="body">';
echo '<p><input type="submit" name="foo"></p>';
echo '</form>';

echo '<pre>';
echo '</pre>';

$bar = array();

$bar = emu_parse_query_str();
echo '<pre>';
echo '</pre>';



------------------- end

Parsing the query string:

Although the GET string is passed to PHP as (an) argument(s) and PHP
populates $_SERVER["argv"] with this/these argument(s), any spaces are
interpreted as separating arguments, which makes parsing $_SERVER["argv"]
very problematic.  There is a similar problem with any other type of
executable that may be invoked by the form action.

Fortunately, the whole string urlencoded is put in the environment by
lynxcgi and is picked up as $_SERVER["QUERY_STRING"].

A function to parse the string might look like:

function emu_parse_query_str(){
$ret = array();
$a = explode('&',$_SERVER["QUERY_STRING"]);
$i = 0;
while ($i < count($a)) {
list($key,$value) = split('=',$a[$i]);
$ret[$key] = htmlspecialchars(urldecode($value));
return $ret;

The above is only slightly modified from the example in the urldecode
function page in the manual.  I could have used $_ENV["QUERY_STRING"].

It may not be desirable to encode with htmlspecialchars here.  Since all we
do in this demo is print_r the array, we need htmlspecial characters to
handle angle brackets that might be in the text.  Because of the nature of
this operation, we are not especially worried about malicious HTML.

Other kinds of executables would have to get at the query string in their
own ways, since it is in the environment.  Here is an sh example which
does not parse the string, but merely echos it:


echo Content-type: text/html
echo "<title>Demo</title>
echo "<pre>"
echo "</pre>"

PHP form before:

                                  Test Screen

   Hello, world!

   email ____________________

   Male (_)

   Female (_)



    [] =>

PHP form after:

                                  Test Screen

   Hello, world!

   email ____________________

   Male (_)

   Female (_)


    [Email] => Foo@bar
    [sex] => Female
    [body] => Fee <fie> &
    [foo] => Submit

[1] Lynxcgi works only on unix-like systems and lynx must be compiled with
'--enable-cgi-links'.  By default, any source and path are allowed for
lynxcgi.  This can be a security concern.  Consult lynx.cfg for ways to
restrict lynxcgi.  In the present situation, the point is to work offline
without a server, so these examples work with the default lynx.cfg.  Lynxcgi
can also set environmental variables in the pseudo-server (see lynx.cfg).
Since PHP CLI can access environmental variables directly, there may be no
reason to set them in lynxcgi unless you want the pseudo-server to have
environmental values other than those provided by your shell.

        Lars Eighner <
            118 days since Rick Warren prayed over Bush's third term.
   Obama: No hope, no change, more of the same. Yes, he can, but no, he won't.

Site Timeline