The CGI
Script
Today,
as even the majority of the Amiga community have begun to conquer
the waste territories, and utilize the fairly unmatchable opportunities
of the land called internet, the lack of javascript interpreters
and java engines in the most common Amiga browsers received much
greater interest and importance than ever in the past.
Until thereīs no need to do something, but to demonstrate, exhibit
and present something - anything is it even from animations up
to huge amounts of cross linked and anchored texts - the simple
html is over all expectations. The problems will begin where presentation
is less than required: if the creator behind the curtain wants
some more, for example at least virtually interactive communication
with the user, to have some excitement on line.
And the Creator at this point swallows a great deal of breath,
and... Stands still. What the heck he can do? (Maybe that quit
button will be sufficient in the upper left corner?)
He has seen things at different pages (as he can resemble to them
in NetScape under Linux and Shapeshifter), like filling out queries
at those ominous pages, and by pressing a Submit button, or just
hitting the enter there happened marvellous things... As there
are those search engines, not? Our Creator decides to make something
like those, and gets up on his feets and wanders around for some
advice.
Javascript
- sounds the first answer from one of his bewildered fellow Creators,
and an other went as far as Java at once, and suggested the Microsoft
J++ in one to our excited Creator, who asks for some internet
addys in order to check out the possibilities of these remarkable
solutions.
Indeed,
these were remarkable sites for him. Out Creator went home, and
tried these URL-s, and saw nothing... At least nothing happened,
except in NetScape... But that wonīt be sufficient for him, as
he wanted to aim traditional Amiga users as well, not just the
users of Shapeshifter or Linux.
So he returns to those fellow Creators, and asks them what to
do? They were puzzled for a while, and finally they agreed in
one possible solution:
cgi
script...
Very
good, very good indeed! Out Creator is delighted. But... What
the heck is that cgi script?
Really...
Whatīs that?
This
marvellous CGI Script in practice is a simple program, situated
in one of the web serverīs directories. If our html receives some
problem to solve it collects the datas and sends the whole package
to our CGI Script, and the script will return a Html page, containing
the solution.
It
sounds quite simple. How can we create a cgi script? At first
easily. At second a little bit harder. At first easily because
we can write our cgi script almost in any programming language,
which can handle a standard in- and output. So we can do it easily
for example both in assembler or a C compiler, of which I suggest
the latter, and let me explain why. Because there is an "at second"
part of the problem: the cgi script is a server side program,
and thus, involving a Windows server an exe, involving a Linux
one and out or an elf, and on every server itīs own executable
format needed for our program to exist in. In order to convert
our 68K or PPC assembly sources into such formats will mean an
interestion excursion into the world of the machine language of
the mentioned serversī processors, and system environments, and
will mean the complete rewrite of the original: but if we do it
in C, it wonīt be a great trick to get it run on an Intel, PPC
or even on a Sparc processor, in almost any system environment
by simply recompiling our original source with a native C compiler.
In case of the C language our only difficulty will be the task
of compiling the source on a native compiler, delivering the output
to itīs destination (depends from the type of the server, usually
a directory called cgi-bin, scripts or so) and finally we have
to make this program accessible to all users (usually the programs
in that dedicated drawer automatically can be reached by the browser,
but it depends on the server)
The
fact is, as based on experience, that in hungary the internet
service providers do not make the cgi directory accessible, and
in most cases the whole directory is invisible for the webspace
owner, what makes quite difficult the job of placing a script
file there, and even more harder to make it accessible for all
browsers. So anyhow annoying it is, we have to ask the provider
directly for access over this quite important directory. (Letting
the providers protect themselves, we have to tell that the cgi
scripts can be quite vulnerable against hacker attacks, and in
many server environments this means a serious problem. In case
of tons of cgi scripts on line, uploaded absolutely uncontrolled
by the general public, this can easily lead to totally unreliable
service.)
Almost
all of the negatives have been told by me above, and if the fact,
that we have to write our cgi script in c, and that we have to
face difficulties requiring time and courage when we try to place
it on the server couldnīt terrorize you enough to drop the project:
thereīs nothing further to frighten you.
Letīs
see then, a little bit more detailed, that how can we, and a browser
create and utilize our cgi script. The browser, along with the
server sets many environment variables for the cgi script, and
in the case described below we have to do nothing save than to
read and examine these environment variables, and output a html
document via the stdout - this will be what the browser will get
back from the server, practically without noticing that the output
generated by a cgi script, and does not come directly from a file
stored on the server.
The
required data used to be collected by a html tag, namely the FORM,
and we will use two fields to complete our task, the TEXTFIELD
to receive some information in pure text format and a SUBMIT button
to send the data of the FORM html tag directly to our cgi script
on the server.
The
FORM tag will submit itīs contents when the submit button pressed,
or the user finishes the text input in the textfield with an enter.
Usually the browser uses the http-post method to send the data
to the cgi-script, but we, in simplifying the process will use
the default method instead. The difference will be, that the data
will arrive in an environment variable called Query_String, instead
of arriving to the stdin port of the cgi script. The content of
the environment variable in case of "apple" written into the textfield,
and presuming that the data submitted by pressing the submit button
will be the follow:
textfield=alma&submit=submit
As we can see, this text can be easily tokenised, and after two
strtoks we are in posession of the inputted text "alma" in the
Query_String environment variable, as can be seen below.
Let us see, what environment variables do we have, set by the
the server:
char
*Auth_Password;
char *Auth_Type;
char *Auth_User;
char *Content_Length;
char *Content_Type;
char *Gateway_Interface;
char *HTTP_Accept;
char *HTTP_Form;
char *HTTP_Referer;
char *HTTP_User_Agent;
char *Path_Info;
char *Path_Translated;
char *Query_String;
char *Remote_Addr;
char *Remote_Host;
char *Remote_Ident;
char *Remote_User;
char *Request_Method;
char *Server_Name;
char *Server_Port;
char *Server_Protocol;
char *Server_Software;
char *Script_Name;
char *Server_Admin;
Nice list, but letīs see what these environment variables contain?
AUTH_TYPE
The
level of the accessing user stored here, if the server supports
passwords and the option and users are enabled. Before the user
can access the cgi script an username and a password will be requested
from the user, and the AUTH_TYPE will be set based on the login.
AUTH_USER
If
the above mentioned option enabled, the AUTH_USER variable will
contain the username of the accessing user.
AUTH_PASSWORD
If
the above mentioned option enabled, the AUTH_PASSWORD variable
will contain the password of the accessing user.
CONTENT_LENGTH
If
we pass the data to the cgi-script via http_post method, then
it will arrive to the stdin port of the script, and the length
of the arrived data will be in this variable. So, CONTENT_LENGTH
will contain the value of how many characters do we have to read
from stdin.
CONTENT_TYPE
CONTENT_TYPE contains the MIME type of the data arrived to the
stdin, for example text/html, etc.
GATEWAY_INTERFACE
The
version number of the CGI handler of the server.
PATH_INFO
We can receive a path of a file from the browser. This path will
be here relative to the cgi itself. It depends on the client and
the cgi, what to do with this.
PATH_TRANSLATED
The
same path as above, but not relative to cgi, in the PATH_TRANSLATED
we receive the complete path of the file in the server.
QUERY_STRING
Here
we get all parameters listed behind the cgi URL and a questionmark.
When we use default submit method, the browser will send the form
data here too.
REMOTE_ADDR
The
IP address of the calling browser. Some people make serious efforts
to obtain other peopleīs IP address, but we can have this free
of charge.
REMOTE_HOST
The host name of the calling machine, on which the browser runs.
If it doesnīt have one, the server will set the REMOTE_IDENT instead.
REMOTE_IDENT
The
name of the user and the address of the machine will be present
here.
REMOTE_USER
The name of the user can be found here.
REQUEST_METHOD
This variable contains the method, with which the browser called
our cgi-script. The value should be GET, HEAD or POST, depending
on the set value in the form tag.
SCRIPT_NAME
This
is the name of our script. If our script called "apple.cgi", and
situated in the cgi-bin drawer, the value will be - for surprise
- "cgi-bin/apple.cgi"
SERVER_NAME
Here we can have the name of our server, or if it doesnīt have
one, the IP number of the server.
SERVER_PORT
Here
is the number of the port, through which the browser have accessed
us.
SERVER_PROTOCOL
The
protocoll and itīs version number used to establish the connection.
SERVER_SOFTWARE
The name and version number of the server and operating system
software.
HTTP_ACCEPT
A list of the acceptable MIME types ofthe browser.
HTTP_USER_AGENT
The type, name and version number of the calling browser.
As we can see, the informations at our disposal are numerous and
some of them very valuable, and unreachable for the simple user.
We can use and abuse these datas: a great part of server hijacks
made through cgi scripts - but as we will only use our Query_String,
and in addition indirectly, the hacker must be an extremely skilled
one, who can use our cgi-script for such purposes.
We can place our varuables into a single structure, in a way like
this:
struct EnvironmentVariables
{
}
if we place the long list above between the brackets. And then
if we create a variable with this structure:
struct
EnvironmentVariables EV;
Then we can use the elements via the getenv command. Along the
getenv we have no other thing to do, than repeating the variable
name in capitals. For example we can get our Query_String variable
in the following way:
EV.Query_String
= getenv("QUERY_STRING");
After
doing so we can (almost) tokenize it in the following way, supposing
that we have a textfield and a submit button in our form, and
so the second token will be the content of our textfield:
EV.Query_String = strtok(EV.Query_String, "=&");
EV.Query_String = strtok(NULL, "=&");
As
we can see, at first we slice our variable by the = and & characters
into tokens, and after the first call we will have the first token
"textfield". Calling the strtok with a null it gives back the
second token, and the value of our variable, supposing that the
entered text into the textfield was "apple", will be - for surprise
- "apple".
Now we can compile the source, and wonīt get a warn, but: compiling
it with gcc under a linux environment, we will get back segment
violation error, if the strtok have to tokenise an empty textfield.
Sad but true, we have to check it before every strtok. (And wonder
who the f*** invented the C language?) Of course we have to make
TWO checks, one for the case when the user presses the submit
button, and one for the case when the user presses enter (as then
we wonīt receive the state of the submit button) Letīs see the
source (quite ugly) in the case of submit button pressed: (the
received data is "textfield=&submit=submit")
char
*duplatoken = {"=&"};
char *myptr;
char *myptr2;
myptr2
= myptr;
myptr = strstr (EV.Query_String,duplatoken);
if (myptr2 == myptr)
{
//here comes our program
}
else
{
//here comes a message to the user, that he entered an empty string
}
And now let us check the second case, when the user tries a simple
enter, to confuse us. (received data is "textfield=")
a = strlen(EV.Query_String);
if (EV.Query_String[a-1]==61) //61 is =
{
//here comes our program
}
else
{
//here comes a message to the user, that the textfield is empty
}
We
should use this two together. Of course, to make our life a little
bit more difficult, the browser converts the inputed text, for
example all space characters morph into "+", and all extra characters
(accents,%,= etc.) will became a three characters long thingie,
beginning with a "%", and followsed by the hexadecimal value of
the original character (for example "á" will became "%e1"). Prepare
to handle this!
So, weīve at least received out variables, we have the value of
the textfield in our variable - and we have only two more things
to do. At first we have to examine the value of the textfield,
and we have to generate an answer html, depending on the examined
value.
As
we cannot give back anything, we have to tell to the browser that
he will get a html back, what the browser will readily display.
The browser will get what we send to it via the stdout - and now
we will prepare the browser to receive our html data with the
following three lines:
printf("Content-type:
text/html\n"); printf("\n"); printf("<!DOCTYPE HTML PUBLIC
\"-//W30//DTD W3 HTML 4.0//EN'\">\n");
As we can possibly deduct, we send him the MIME type of the following
data. Now we can do anything, as an example we will return the
value of the read variable:
printf("<html>\n");
printf("<head>\n");
printf("</head>\n");
printf("<title>Ez egy cgi script altal generalt html
file\n");
printf("</title>\n");
printf("<body>\n");
printf("Az EV.Query_String valtozo erteke: %s\n",EV.Query_String);
printf("</body>\n");
printf("</html>\n");
So,
in this way we have a working cgi script. We have to do nothing
else
save compiling the source into a suitable format, placing it to
the good
place on the server, and we have to place a form tag into our
html, with a
textfield and a submit button, and we have to give our cgi´s
url as the form
tag´s link. This will look like this:
<form
action="HERE_COMES_THE_URL_OF_THE_CGI" name="">
<input type="text" name="textfield" value="">
<input type="submit" name="submit" value="submit">
</form>
And we are ready, we can test our cgi script at last. All my best
wishes to
the new CGI creators around...
Emeric SH