Link to home
Start Free TrialLog in
Avatar of sderaadt
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
ASKER CERTIFIED SOLUTION
Avatar of williams2
williams2

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of sderaadt
sderaadt

ASKER

williams2

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


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">Firstname
<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">Firstname
<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,PicID: 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('SQLPASSTHRU 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=masterkey');

    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.ReadString('Form 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.ReadString('Form 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('Firstname').asString;
        Sname:= DBase.FieldByName('Surname').asString;
        User:= DBase.FieldByName('Username').asString;
        Age:= DBase.FieldByName('Age').asString;
        Tlf:= DBase.FieldByName('Tlf').asString;
        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+'"></CENTER><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?
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.
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/mycgi.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. :-)