Using FlagShip on
Web
This document describes how to use FlagShip
for html Web document purposes. It tries not to be a detailed manual for
configuration of the Web Server or browser, nor a full reference to the
HTML language, but gives a general overview sufficient for the programmer
to use FlagShip as a database manager for HTML documents. The examples
are hold very simple and are meant as a basis for your own programs even
without or with a basic HTML knowledge only.
As opposite to standard applications,
which are usually screen oriented, runs locally and reacts on user
entries, a Web based application is client-server oriented :
•
|
The client is
your Web browser (Internet Explorer, Netscape, Mozilla, Firefox, Opera
etc), running on local computer. The local browser access HTML
document (located on the Web server) containing "form tags".
These form tags contains either pre-defined data or variable user entries
and selections. One of these tags specifies how the user request (usually
processed by click on the "submit" button) should be handled.
For example, the tag <FORM
ACTION="/cgi-bin/my_application" METHOD="get"> will
invoke the executable named "my_application" located in the
directory "/cgi-bin" on the web-server and will pass current
form data to the application using "get" method. |
|
|
• |
The server application
(named here e.g. my_application)
is started automatically by the <FORM
ACTION=...> tag in HTML document, when the user press the "submit" button.
The application is either a script, or a by FlagShip created executable,
processing following three steps:
- Receive
the form/user data by "get" or "post" method, e.g. by invoking
FlagShip's WebGetFormData() function
- Check
the user input and react accordingly by creating a "reply" HTML
document, which is then automatically displayed by the client's browser.
You may e.g. access database (located on the server) and create reply
by using FlagShip's function WebHtmlBegin() ... create
the text body by using standard ? or Qout(...) commands/functions ... and
then invoke WebHtmlEnd() function to finish the reply document
- Quit the application
Since the Web application
is server-based, and run in background, consider following rules:
- It must be compiled
for the Web-server platform, regardless the used client/browser
environment. I.e. if the Web server is Linux, you need to
compile your application by FlagShip for Linux, or if the server
is SUN compile by FlagShip for SUN Solaris, or if the server is
Windows compile by FlagShip for MS-Windows, and so on.
- Even
when FlagShip supports dynamically linked applications, best to compile
statically (by using the -stat compiler
switch in VFS), you don't then need anything else on the server than
the executable application self (and probably used databases)
- Do not use any screen
oriented input/output or user prompt (e.g. Inkey(),
Wait etc)
nor GUI or Terminal environment, but simple "basic" output
to create the reply document. With VFS, use the -io=b compiler
switch.
|
Hint: a short overview about the used
Common Gateway Interface (or CGI) is e.g. here,
a good introduction is available in several books, e.g. in the O'Reilly Open
Book "CGI
Programming on the World Wide Web" by Shishir Gundavaram
1. Data Structure
on the Linux/Unix Server
1.a. Directory for HTML documents (Document root
directory)
The html documents
(*.html or *.htm)
accessed by the Web browser (Internet Explorer,
Netscape, Mosaic, Mozilla, Firefox, Opera etc.) usually resides in a special
directory on the Web server (e.g.in /usr/local/httpd/htdocs or /var/local/public/html/docs etc).
The Web server (e.g. Apache,
Netscape-server, AOLserver etc.) hides (maps) the true directory structure so,
that the Web browser will see this directory (named "Document root directory")
as "root", i.e. the / path only. Hence, the Web user (usually
of the group "nobody") can access files and subdirectories located below,
but not above this Document root directory (an important security aspect).
The links from a html document to another one on the same server may be
done relatively, e.g. "/other.html" instead of the URL (Uniform
Resource Locator) naming convention "http://www.domain.org/other.html",
which reduce the Internet transfer and increases the access speed significantly.
Configuration: The name of the document root directory is specified
in the /etc/httpd/access.conf and /etc/httpd/srm.conf (or similarly named) configuration files used by the Web server daemon
and described in detail in the server documentation. On a remote Web server,
contact your provider for the setup details.
Permissions: The document
root directory should have a "read" access
for everybody (e.g. 755, drwxr-xr-x). The html documents
itself (*.html or *.htm) have usually only read permission (644, -rw-r--r--).
1.b. Directory for CGI Scripts and Executables
The Common Gateway Interface, or CGI,
is a means for the HTTP server to "talk" to programs (scripts, executables)
on the local or server's machine. As opposite to the static model of reading
predefined html documents, the CGI allows to react on the client request
and creates specific text or html documents for the browser. The requests
from the browser to CGI are passed via environment variables (the most
important are QUERY_STRING and PATH_INFO)
and/or via stdin, depending on the request type. The QUERY_STRING is
filled when the preferred "GET" method
is used. The request is in the form <location>?<content> (e.g. "http://www.domain.org/cgi-bin/myapplic?CUSTOMERID=1234" or
simply "/cgi-bin/myapplic?CUSTOMERID=1234" )
That script directory contains scripts, executables and data accessed
by the HTML documents indirectly via the CGI interface, e.g. by the <FORM
...> tag. This directory will contain the by FlagShip created executable
among the databases and indices.
For security reasons, this CGI directory
should not be equivalent to, or reside below the Document root directory.
Usually, this directory is named cgi-bin and reside parallel
to the Document root directory, e.g. /usr/local/httpd/cgi-bin or /var/local/public/html/cgi-bin.
Keep in mind, your applicattion will usually see this cgi-bin directory as
root path
"/", you hence can access data and subdirectories in and below
cgi-bin, but not in another directories on the server.
Configuration: The location and its mapping to the Web browser
(e.g. visible as /cgi-bin) is specified in the above named Web
server configuration files. You should also change the properties of the
directory to Options none, AllowOveride none in the access.conf
file. On a remote Web server, contact your provider for the setup details.
Permissions: The cgi-bin directory may have only execute, or execute and read permissions for everybody
(711, drwx--x--x or 755, drwxr-xr-x).
The scripts or executables have usually read & execute permission
for everybody (755, -rwxr-xr-x),
while the databases and indices are r/w (666, -rw-rw-rw-).
1.c. First Example
This hello_prg.html calls the
hello_prg.cgi FlagShip executable which displays Hello.. and print the used environment variables.
<!-- hello_prg.html -->
<html><head><title>Welcome</title></head>
<body>
<form action="/cgi-bin/hello_prg.cgi" method="get">
<!-- Enter a username: <input type="text" name="username"></input><br> -->
<!-- <input type="radio" name="whatToDo" value="remove" checked="checked">Value<br> -->
<p>
Click here to Execute /cgi-bin/hello_prg.cgi <p>
<input type="submit" name="subbtn" value="Submit">
</form>
</body></html>
Compile the hello_prg.prg and post the executable
hello_prg.cgi in the
/cgi-bin directory on the Web server (check for 755 permission)
// hello_prg.prg - compile:
// FlagShip -stat -io=b -delc hello_prg.prg -o hello_prg.cgi
set date german
set century on
?? "Content-type: text/html"
? ""
? "<html><head><title>Welcome</title></head>"
? "<body>"
? "Hello from CGI by FlagShip"
? "<P>"
? "Web Environment on", date(), time(), "<P>"
aEnvir := WebGetEnvir()
aeval(aEnvir, {|x| qout(x[1], "=", x[2], "<br>")})
? "<P>"
? "--done--"
? "</body></html>"
quit
2. Access the database executable via a HTML document
2.a. The HTML document
The most common (and on some commercial servers the only) method to access
a CGI script or executable is via the <FORM ...> tag. Here
an example named e.g. "example1.html" posted in the document
directory (see 1.a) and invoked by the browser as URL http://www.my.org/example1.html or
locally http://localhost/example1.html .
Note: if you invoke file:/usr/local/httpd/htdocs/example1.html instead,
you will see and can enter the data in the the document,
but will most probably not be able to access the CGI directory properly.
<HTML>
<HEAD><TITLE>1st example</TITLE></HEAD>
<BODY BCOLOR="#FFFFFF">
<CENTER><B>1st example for access of FlagShip executables</B></CENTER>
<!-- <FORM ACTION="/cgi-bin/example1.sh" METHOD="get"> alternative
1 calling script -->
<FORM ACTION="/cgi-bin/example1" METHOD="get"> <!-- alternative
2 calling executable -->
Select the user ID you want to list :
<SELECT name="CUSTOMERID">
<OPTION VALUE="0">
<OPTION VALUE="1"> 1
<OPTION VALUE="10"> 10
<OPTION VALUE="1234"> 1234
</SELECT>
<P>
<INPUT TYPE="Submit" VALUE="Submit for request">
<INPUT TYPE="Reset" VALUE="Clear data">
</FORM>
</BODY>
</HTML>
Note the name of the shell script "example1.sh" posted
in the CGI directory (see 1.b).
2.b The interface script (optional)
Usually, you will invoke directly the executable posted in the
/cgi-bin directory. In special cases, you may also use shell script,
e.g. the "/cgi-bin/example1.sh" (invoked
in 2.a via the commented-out statement <FORM ACTION...> as
alternative 1) which sets the required environment and invokes the by FlagShip
compiled executable named "example1" :
#!/bin/sh
set -f
TERMINFO=/cgi-bin ; export TERMINFO
TERM=dummy ; export TERM
./example1
Don't forget to make the script executable,
i.e. "chmod 755 example1.sh"
2.c. The Web application/executable
The following FlagShip program is very simple. It checks the incoming request
and prints the html reply-data on stdout. Here, we get a customer ID
(via command line for test purposes, or passed by the Web server in
the environment variable QUERY_STRING which contain here the string "CUSTOMERID=<input-value>" according
to the NAME
parameter in the SETECT (or INPUT) tag.
** example1.prg ----------------------------------------------------
#define DBFNAME "example1" /* modify upon request */
#define DBFPATH "/cgi-bin" /* modify upon request */
parameter cCust //
optional command-line parameter
field custID, name, address //
used database fields
local aWebData, iPos
/* get the HTML form data, if any
*/
if empty(cCust) //
w/o command-line parameter:
aWebData := WebGetFormData() //
get form data
iPos := Ascan(aWebData, {|x| upper(x[1]) == "CUSTOMERID"}
)
if iPos > 0
cCust := aWebData[iPos,2] //
data of CUSTOMERID tag
endif
endif
nCust := val(cCust)
/* write HTML reply prefix
*/
cWebHeaderTitle := "Test Web Page" // title
WebHtmlBegin() //
create HTML prefix
/* Now, we access the database and search it for
* data specified by the given customer-ID,
* and write the HTML reply body text
*/
if !file(DBFNAME + ".dbf")
set default to (DBFPATH)
endif
if !file(DBFNAME + ".dbf") .or. !file(DBFNAME + ".idx")
? "<P>*** sorry, database not available or wrong
path **"
elseif nCust == 0
? "<P>*** sorry, no data without customer ID **"
else
use (DBFNAME) index (DBFNAME) shared
ok := used() .and. !neterr()
? "Listing the data for customer no. " + ltrim(str(nCust))
if !ok
? "<P>*** error, cannot open database
or index"
else
seek nCust
if !found()
? "<P>*** sorry, no data available
for this cust no."
else
? "<P><TT>"
while !eof() .and. custID == nCust
? custID, name, trim(address), "<BR>"
skip
enddo
?? "</TT>"
endif
endif
endif
? "<P>"
/* write HTML reply postfix
*/
WebHtmlEnd() //
write HTML postfix
?
quit
/* disable curses, disable start-up messages if any
*/
FUNCTION ProgramInit() // required for
CALL fgsUse4html // FS 4.4x
RETURN NIL //
see fsman sect SYS.2.9
FUNCTION CursesInit() // required for FS 4.4x
RETURN NIL
** eof example1.prg -----------------------------------------------
Note: this example
use the simple GET method. For larger documents, usually the POST method
is used, which does not restrict the amount of passed data. For processing
both GET and POST methods, there is a function WebGetFormData() available
in FlagShip and used in this example. It determines the used request form,
decodes the passed data and returns an array, which is then simply processed
by your application. There are also several additional Web*() functions
for handling the HTML documents and sending e-mails, see details in
the section FUN of the on-line FlagShip manual named "fsman",
or in the corresponding section of fthe pdf manual. You may decode
the data manually without Web*() functions, see the full source in fs4web.tar.
If you wish to pass HTML documents
or bitmaps links in the reply from your application, use full qualified URLs like
http://www.mydomain.com/mydocument.html
With Visual FlagShip, compile
on the server in basic i/o mode mode by
FlagShip
-stat -io=b example1.prg -o example1
With FlagShip version 4.4x, use the example1.prg source in fs4web.tar and
compile by
FlagShip example1.prg -o example1
and post the executable into the /cgi-bin directory (see 1.b).
Note: of course, the executable posted on the Web server
(e.g. at your provider site)
needs to be created by a FlagShip version corresponding to this operating
system. Since this may differ to the locally used FlagShip, check for
details of the operating system with your provider.
You may invoke it from the command-line by
./example1 1234
It displays a HTML document but first reports en error "database not
available...".
2.d Database maintenance
We have to create a small maintenance
program first (or use e.g. dbu). Often the main program checks for the existence
of database and indices and creates it when required. But for security purposes
on the server, it is better to maintain it separately by the web administrator
which has sufficient access rights, or maintain it locally and then copy the
database back to Web server.
** mainten1.prg ----------------------------------------------------
#define DBFNAME "example1"
if !file(DBFNAME + ".dbf")
dbcreate(DBFNAME, {{"custID", "N",
5, 0}, ;
{"name", "C", 20, 0}, ;
{"address","C", 30, 0}} )
endif
use (DBFNAME) exclusive
if eof() // add some records
append blank
repla custID with 1, name with "Multisoft",
address with "http://www.flagship.de"
append blank
repla custID with 1, name with "FlagShip",
address with "http://www.flagship.de"
append blank
repla custID with 1234, name with "name
1234", address with "address 1234"
append blank
repla custID with 10, name with "name
10", address with "address 10"
endif
if file(DBFNAME + ".idx")
set index to (DBFNAME)
else
index on custID to (DBFNAME)
endif
browse() // maintain, add, edit the database
example1.dbf
use
** eof of mainten1.prg ----------------------------------------------
With Visual FlagShip VFS6 and VFS7, compile
on the server in GUI or hybrid mode
FlagShip -stat mainten1.prg -o mainten1
or for Terminal i/o mode when accessing it via ssh or terminal emulator
FlagShip -stat -io=t mainten1.prg
-o mainten1
With FlagShip version 4.48, use
FlagShip mainten1.prg
-o mainten1
On Linux/Unix based Web server,
set
the access rights for the web administrator only
chmod 700 mainten1
and invoke it to create (or modify) the database and index
./mainten1
After the first invocation, change the permissions of the
database and index:
chmod 666 example1.dbf example1.idx
Check the output of the invocation
./example1 1
it should display a HTML document with two lines of data from the database.
If everything is ok, you're now ready to use the document example1.html
(see 2.a) by your preferred Web browser. If something fails, check the
access rights.
3. Additional hints
-
Keep in mind, the Web user has a very limited access to the system
and will usually not be able to access the most Unix tools as you can as
administrator or ordinary user.
-
You may preferably compile and link statically your public executables
(see the FSconfig file for FS4.48 and the manual sections FSC.1.4.2,
FSC.1.7), or use -stat compiler switch in VFS. Otherwise, when
linking dynamically,
you will need to copy the libFlagShip*.so file from /usr/lib or
the libFlagShip7*.so file
from /usr/local/FlagShip7/lib into
the /cgi-bin directory,
make it readable and executable for all (755) and modify the start-up
script (if used, see 2.b) to read
#!/bin/sh
set -f
TERMINFO=/cgi-bin ; export TERMINFO
TERM=dummy ; export TERM
LD_LIBRARY_PATH=/cgi_bin ; export LD_LIBRARY_PATH
LD_RUN_PATH=/cgi_bin ; export LD_RUN_PATH
./example1
-
You should be very careful when using the RUN command in the application;
it may create a security hole when you use variable parameters and don't
check them properly.
-
The examples and sources used here are available in the fs4web.tar
archive file.
- For testing the communication locally on Windows or Linux, you may use Apache or the complete Apache/PHP suite.
Created 08-May-1998, last updated
5-Jan-2012 by webmaster@flagship.de
Back to FlagShip
home page