sderaadt
asked on
Referencing cgi program
Hi
I have a cgi program written in Delphi. It is a basic counter/stats program that when referenced records details in a log file and outputs a 'location:' header to the server pointing to an image.
So far I have been referencing it in an IMG tag, this works well the first time, but the browser caches the image and returns this every time thereafter.
Also, text-only browsers and those whose 'display images' is turned off, it isn't referenced.
How do I get around these problems?
(Would returning an image rather than a reference to an image help? How do I do this? I've heard of a command/tag something like <!--#exec-->, how does this work?)
Thanks
I have a cgi program written in Delphi. It is a basic counter/stats program that when referenced records details in a log file and outputs a 'location:' header to the server pointing to an image.
So far I have been referencing it in an IMG tag, this works well the first time, but the browser caches the image and returns this every time thereafter.
Also, text-only browsers and those whose 'display images' is turned off, it isn't referenced.
How do I get around these problems?
(Would returning an image rather than a reference to an image help? How do I do this? I've heard of a command/tag something like <!--#exec-->, how does this work?)
Thanks
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Ok! ..I'll illustrate an example
First, here's the HTML code:
<html>
<title>Testing CGI</title>
<body>
<body background = http://mis.lamar.edu/mis/Grundy/parchmen.gif>
<form action="http://localhost/cgi-win/findperson.exe" method=post>
<h2><Center>Searching persons</Center></h2>
<HR>Word to search:
<input type= text name= searchfield1 size=20><br>
(with automatic wildcard selection)<br>
Kategori:
<select name=formfield1>
<option value="Firstname">Firstnam e
<option value="Surname">Surname
<option value="Username">Username
<option value="Age">Age
</select><BR>
<HR><select name=formfield3>
<option value="IGNORE">ignore
<option value="AND">and
<option value="OR">or
</select>
second word:
<input type= text name= searchfield2 size=20><br>
(with automatic wildcard selection)<br>
Kategori:
<select name=formfield2>
<option value="Firstname">Firstnam e
<option value="Surname">Surname
<option value="UserID">Username
<option value="Age">Age
</select><BR>
<HR>
<input type=submit value="Begin search">
<h5><Center><b>Example made by:</b><br><k>Thomas Williams</k></Center></h5>
</form>
</body>
</html>
..And then some sourcecode (First Program, then unit):
program FindPerson;
uses
Forms,
CGIunit in 'CGIunit.pas';
{$R *.RES}
begin
Application.Initialize;
Application.Run;
end.
unit CGIunit;
interface
uses
SysUtils, DB, DBTables;
// See to that the HTML-page contains http://localhost/cgi-win/FindPerson.exe
// and 'PicDir' should be directed to a public path
// like 'file:///F|/Pictures/'
// (You can change this at the end of this unit)
// The DBase contains a table 'persons' containing following attributes:
// firstname,Surname,Username ,Age,Tlf,P icID: String;
// PicID is a unique name of the picture of a person
// The DBase could be replaced by an .INI file, to fasten up querying
// and avoid use of SQL (SQL servers are expensive.)
Const
DBName = 'MyDB';
// DBName is the name of an INTRBASE dbase located at C:\
var
db1: Tdatabase;
dBase: TQuery;
PicDir: String;
implementation
Uses Inifiles;
procedure InitDB;
begin
db1 := TDatabase.create(nil);
db1.databasename := 'MyDB';
db1.drivername := 'INTRBASE';
db1.params.clear;
db1.params.add('SERVER NAME=C:\'+DBName+'.GDB');
db1.params.add('USER NAME=SYSDBA');
db1.params.add('OPEN MODE=READ/WRITE');
db1.params.add('SCHEMA CACHE SIZE=8');
db1.params.add('LANGDRIVER =');
db1.params.add('SQLQRYMODE =');
db1.params.add('SQLPASSTHR U MODE=SHARED AUTOCOMMIT');
db1.params.add('SCHEMA CACHE TIME=-1');
db1.params.add('MAX ROWS=-1');
db1.params.add('BATCH COUNT=200');
db1.params.add('ENABLE SCHEMA CACHE=FALSE');
db1.params.add('SCHEMA CACHE DIR=');
db1.params.add('PASSWORD=m asterkey') ;
db1.loginprompt := false;
db1.connected := true;
DBase:= TQuery.create(nil);
DBase.databaseName:= DBName;
DBase.requestLive:= true
end;
function Correct(s: String): String;
var // Makes every first letter a capital letter.
i: Integer;
oldc: Char;
begin
oldc:=' ';
For i:=1 to length(s) do
begin
if (oldc=' ') and (s[i]<>' ') then s[i]:=ANSIUpperCase(s[i])[ 1];
oldc:=s[i];
end;
Correct:=s;
end;
Procedure GetTabel(var IniFile: TIniFile);
var
s: String; // Searching String
t: String; // Search types
DoubleSearch: String;
Statement: String; //SQL udtryk
Bool: String;
begin
dbase.sql.clear;
t := IniFile.ReadString('Form Literal','formfield1','');
s := ANSILowerCase(IniFile.Read String('Fo rm Literal','searchfield1','" "'));
Statement:='select * from Persons where ('+t+' Like ' + s + ')';
dbase.sql.add(Statement);
Bool := IniFile.ReadString('Form Literal','formfield3','');
if Bool<>'IGNORE'then
begin
t := IniFile.ReadString('Form Literal','formfield2','');
s := ANSILowerCase(IniFile.Read String('Fo rm Literal','searchfield2','" "'));
Statement:=Bool+' ('+t+' Like ' + s + ')';
dbase.sql.add(Statement);
end;
dbase.open;
end;
Procedure WriteResult(var f: textFile);
var
Fname, Sname, User: String;
Age, Tlf, PicID: String;
begin
DBase.first;
If DBase.RecordCount>0 then
begin
while not DBase.eof do
begin
Fname:= DBase.FieldByName('Firstna me').asStr ing;
Sname:= DBase.FieldByName('Surname ').asStrin g;
User:= DBase.FieldByName('Usernam e').asStri ng;
Age:= DBase.FieldByName('Age').a sString;
Tlf:= DBase.FieldByName('Tlf').a sString;
PicID:= DBase.FieldByName('PicID') .asString;
Writeln(f,'<B>Firstname: </B>'+Correct(Fname)+'<BR> ');
Writeln(f,'<B>Surname: </B>'+Correct(Sname)+'<BR> ');
Writeln(f,'<B>User Ident.: </B>'+ANSIUppercase(User)+ '<BR>');
Writeln(f,'<B>Age: </B>'+Age+'<BR>');
Writeln(f,'<B>Telephone #: </B>'+Tlf+'<BR>');
Writeln(f,'<CENTER><IMG SRC="'+PicDir+PicID+'"></C ENTER><br> <hr>');
dBase.next;
end;
end else
begin
Writeln(f,'<BR><HR><BR><B> The query returned nothing </B><BR>');
end;
end;
Procedure ProcessScript;
var
IniFile: TInifile;
filename: string;
f: textfile;
i: integer;
begin
IniFile:= TInifile.create(Paramstr(1 ));
// *** header start ***
filename:= IniFile.Readstring('System ','Output File','');
assignfile(f,filename);
rewrite(f);
writeln(f,'HTTP/1.0 200 OK');
writeln(f,'Date: Friday, 28 Nov-97, 13:36:12 GMT');
writeln(f,'Server:Website/ 1.1e');
writeln(f,'Allow-ranges: bytes');
writeln(f,'Content-type: text/html');
writeln(f,'Content-length: 0');
writeln(f);
writeln(f,'<HTML>');
writeln(f,'<Title>Result</ Title>');
writeln(f,'<Body>');
writeln(f,'<body background = http://mis.lamar.edu/mis/Grundy/parchmen.gif>');
writeln(f,'Following matched the query: <BR><BR>');
// *** header end ***
GetTabel(IniFile);
WriteResult(f);
writeln(f,'</body>');
writeln(f,'</HTML>');
DBase.Close;
Closefile(f);
end;
begin
PicDir:= 'file:///F|/Pictures/';
InitDB;
ProcessScript;
end.
..As you see, I only reference the name of the picture. If you are planning to build a counter CGI, then you should keep an image each number, like "0".."9".
When then a textonly browser is used, an alternative text is used instead like:
<img src="http://www.Something.com/" alt="Click Here">
Does this answer you question?
First, here's the HTML code:
<html>
<title>Testing CGI</title>
<body>
<body background = http://mis.lamar.edu/mis/Grundy/parchmen.gif>
<form action="http://localhost/cgi-win/findperson.exe" method=post>
<h2><Center>Searching persons</Center></h2>
<HR>Word to search:
<input type= text name= searchfield1 size=20><br>
(with automatic wildcard selection)<br>
Kategori:
<select name=formfield1>
<option value="Firstname">Firstnam
<option value="Surname">Surname
<option value="Username">Username
<option value="Age">Age
</select><BR>
<HR><select name=formfield3>
<option value="IGNORE">ignore
<option value="AND">and
<option value="OR">or
</select>
second word:
<input type= text name= searchfield2 size=20><br>
(with automatic wildcard selection)<br>
Kategori:
<select name=formfield2>
<option value="Firstname">Firstnam
<option value="Surname">Surname
<option value="UserID">Username
<option value="Age">Age
</select><BR>
<HR>
<input type=submit value="Begin search">
<h5><Center><b>Example made by:</b><br><k>Thomas Williams</k></Center></h5>
</form>
</body>
</html>
..And then some sourcecode (First Program, then unit):
program FindPerson;
uses
Forms,
CGIunit in 'CGIunit.pas';
{$R *.RES}
begin
Application.Initialize;
Application.Run;
end.
unit CGIunit;
interface
uses
SysUtils, DB, DBTables;
// See to that the HTML-page contains http://localhost/cgi-win/FindPerson.exe
// and 'PicDir' should be directed to a public path
// like 'file:///F|/Pictures/'
// (You can change this at the end of this unit)
// The DBase contains a table 'persons' containing following attributes:
// firstname,Surname,Username
// PicID is a unique name of the picture of a person
// The DBase could be replaced by an .INI file, to fasten up querying
// and avoid use of SQL (SQL servers are expensive.)
Const
DBName = 'MyDB';
// DBName is the name of an INTRBASE dbase located at C:\
var
db1: Tdatabase;
dBase: TQuery;
PicDir: String;
implementation
Uses Inifiles;
procedure InitDB;
begin
db1 := TDatabase.create(nil);
db1.databasename := 'MyDB';
db1.drivername := 'INTRBASE';
db1.params.clear;
db1.params.add('SERVER NAME=C:\'+DBName+'.GDB');
db1.params.add('USER NAME=SYSDBA');
db1.params.add('OPEN MODE=READ/WRITE');
db1.params.add('SCHEMA CACHE SIZE=8');
db1.params.add('LANGDRIVER
db1.params.add('SQLQRYMODE
db1.params.add('SQLPASSTHR
db1.params.add('SCHEMA CACHE TIME=-1');
db1.params.add('MAX ROWS=-1');
db1.params.add('BATCH COUNT=200');
db1.params.add('ENABLE SCHEMA CACHE=FALSE');
db1.params.add('SCHEMA CACHE DIR=');
db1.params.add('PASSWORD=m
db1.loginprompt := false;
db1.connected := true;
DBase:= TQuery.create(nil);
DBase.databaseName:= DBName;
DBase.requestLive:= true
end;
function Correct(s: String): String;
var // Makes every first letter a capital letter.
i: Integer;
oldc: Char;
begin
oldc:=' ';
For i:=1 to length(s) do
begin
if (oldc=' ') and (s[i]<>' ') then s[i]:=ANSIUpperCase(s[i])[
oldc:=s[i];
end;
Correct:=s;
end;
Procedure GetTabel(var IniFile: TIniFile);
var
s: String; // Searching String
t: String; // Search types
DoubleSearch: String;
Statement: String; //SQL udtryk
Bool: String;
begin
dbase.sql.clear;
t := IniFile.ReadString('Form Literal','formfield1','');
s := ANSILowerCase(IniFile.Read
Statement:='select * from Persons where ('+t+' Like ' + s + ')';
dbase.sql.add(Statement);
Bool := IniFile.ReadString('Form Literal','formfield3','');
if Bool<>'IGNORE'then
begin
t := IniFile.ReadString('Form Literal','formfield2','');
s := ANSILowerCase(IniFile.Read
Statement:=Bool+' ('+t+' Like ' + s + ')';
dbase.sql.add(Statement);
end;
dbase.open;
end;
Procedure WriteResult(var f: textFile);
var
Fname, Sname, User: String;
Age, Tlf, PicID: String;
begin
DBase.first;
If DBase.RecordCount>0 then
begin
while not DBase.eof do
begin
Fname:= DBase.FieldByName('Firstna
Sname:= DBase.FieldByName('Surname
User:= DBase.FieldByName('Usernam
Age:= DBase.FieldByName('Age').a
Tlf:= DBase.FieldByName('Tlf').a
PicID:= DBase.FieldByName('PicID')
Writeln(f,'<B>Firstname: </B>'+Correct(Fname)+'<BR>
Writeln(f,'<B>Surname: </B>'+Correct(Sname)+'<BR>
Writeln(f,'<B>User Ident.: </B>'+ANSIUppercase(User)+
Writeln(f,'<B>Age: </B>'+Age+'<BR>');
Writeln(f,'<B>Telephone #: </B>'+Tlf+'<BR>');
Writeln(f,'<CENTER><IMG SRC="'+PicDir+PicID+'"></C
dBase.next;
end;
end else
begin
Writeln(f,'<BR><HR><BR><B>
end;
end;
Procedure ProcessScript;
var
IniFile: TInifile;
filename: string;
f: textfile;
i: integer;
begin
IniFile:= TInifile.create(Paramstr(1
// *** header start ***
filename:= IniFile.Readstring('System
assignfile(f,filename);
rewrite(f);
writeln(f,'HTTP/1.0 200 OK');
writeln(f,'Date: Friday, 28 Nov-97, 13:36:12 GMT');
writeln(f,'Server:Website/
writeln(f,'Allow-ranges: bytes');
writeln(f,'Content-type: text/html');
writeln(f,'Content-length:
writeln(f);
writeln(f,'<HTML>');
writeln(f,'<Title>Result</
writeln(f,'<Body>');
writeln(f,'<body background = http://mis.lamar.edu/mis/Grundy/parchmen.gif>');
writeln(f,'Following matched the query: <BR><BR>');
// *** header end ***
GetTabel(IniFile);
WriteResult(f);
writeln(f,'</body>');
writeln(f,'</HTML>');
DBase.Close;
Closefile(f);
end;
begin
PicDir:= 'file:///F|/Pictures/';
InitDB;
ProcessScript;
end.
..As you see, I only reference the name of the picture. If you are planning to build a counter CGI, then you should keep an image each number, like "0".."9".
When then a textonly browser is used, an alternative text is used instead like:
<img src="http://www.Something.com/" alt="Click Here">
Does this answer you question?
ASKER
Hi williams2
Your example is good. However, I have no problem calling my program, recieving query_string, parsing and determining output. Then I send back a reference to the image by way of a location header.
So, I have this html
<IMG SRC="cgi-bin/myprog.exe?1" >
And I return to the server this header
location : images/pic.gif
This displays pic.gif. No problem there. However - when I call this
<IMG SRC="cgi-bin/myprog.exe?1" >
again, it will take pic.gif out the of cache rather than running my program, because it has linked cgi-bin/myprog.exe?1 with pic.gif somehow. However, I want it to run my program every time it is referenced.
I don't care if it is using the IMG tag or not. I used it because it was convenient. But my program doesn't need to return an image - it just needs to process every time it appears in the document.
I know there is an SSI something like this:
<!--#exec file=cgi-bin/myprog.exe-->
however, I can't get it to run with my test server (Omnihttpd1.01).
Thanks, though for your help.
Your example is good. However, I have no problem calling my program, recieving query_string, parsing and determining output. Then I send back a reference to the image by way of a location header.
So, I have this html
<IMG SRC="cgi-bin/myprog.exe?1"
And I return to the server this header
location : images/pic.gif
This displays pic.gif. No problem there. However - when I call this
<IMG SRC="cgi-bin/myprog.exe?1"
again, it will take pic.gif out the of cache rather than running my program, because it has linked cgi-bin/myprog.exe?1 with pic.gif somehow. However, I want it to run my program every time it is referenced.
I don't care if it is using the IMG tag or not. I used it because it was convenient. But my program doesn't need to return an image - it just needs to process every time it appears in the document.
I know there is an SSI something like this:
<!--#exec file=cgi-bin/myprog.exe-->
however, I can't get it to run with my test server (Omnihttpd1.01).
Thanks, though for your help.
I see.. I've been using Website 1.1, but that shouldn't make a difference though. It is either a problem with the webbrowser. If it's set to cache everything, there's nothing you can do to change that. Else there should be an option in the service configuration (That I don't know with omnihttpd1.01) where disabling a cache might be.
However, I'm a little familiar with the last thing you wrote.
I got this from
http://webreview.com/97/10/10/bookshelf/
<!--#config errmsg="Bungled again!"-->
We're now going to execute the file 'do_this'.
<< <!--#exec cmd="rubbish/do_this"--> >>
and now /usr/www/cgi-bin/mycgi.ok:
<< <!--#exec cmd="/usr/www/cgi-bin/mycg i.ok"--> >>
That was it.
Try go there yourself, you might try an example or two. Search for "Execute CGI" when altering the page and you'll be there.
Have fun, and add a comment if it works. :-)
However, I'm a little familiar with the last thing you wrote.
I got this from
http://webreview.com/97/10/10/bookshelf/
<!--#config errmsg="Bungled again!"-->
We're now going to execute the file 'do_this'.
<< <!--#exec cmd="rubbish/do_this"--> >>
and now /usr/www/cgi-bin/mycgi.ok:
<< <!--#exec cmd="/usr/www/cgi-bin/mycg
That was it.
Try go there yourself, you might try an example or two. Search for "Execute CGI" when altering the page and you'll be there.
Have fun, and add a comment if it works. :-)
ASKER
It seems your method still references an image - is that right? In which case it will still cache the image once it has downloaded it once.
However, an example would be great :)
Thanks