var
Data: String;
function Value(Const Field: ShortString): ShortString;
var i: Integer;
begin
Result := '';
i := Pos(Field+'=',Data);
if i = 0 then
begin
Inc(i,Length(Field)+1);
while Data[i] <> '&' do
begin
Result := Result + Data[i];
Inc(i)
end
end
end {Value};
Следующий шаблон кода показывает как динамически создать переменную TBDosEnvironment, прочитать информацию со стандартного ввода и получить строку готовую для анализа переменных формы.
{$APPTYPE CONSOLE}
var
Data: String;
ContentLength,i,j: Integer;
begin
writeln('HTTP/1.0 200 OK');
writeln('SERVER: Dr.Bob''s Intranet WebServer 1.0');
writeln('CONTENT-TYPE: TEXT/HTML');
writeln;
writeln('<HTML>');
writeln('<BODY>');
writeln('<I>Generated by Dr.Bob''s CGI-Expert on </I>',DateTimeToStr(Now));
with TBDosEnvironment.Create(nil) do
begin
for i := 0 to Pred(DosEnvCount) do
begin
if Pos('REQUEST_METHOD',DosEnvList[i]) 0 then
begin
Data := DosEnvList[i];
Delete(Data,1,Pos('=',Data))
end
end;
if Data = 'POST' then
begin
ContentLength := StrToInt(GetDosEnvStr('CONTENT_LENGTH'));
SetLength(Data,ContentLength+1);
j := 0;
for i:=1 to ContentLength do
begin
Inc(j);
read(Data[j]);
end;
Data[j+1] := '&';
{ now call Value or ValueAsInteger to obtain individual values }
end;
Заметим, что первые три "writeln" строки, посылаемые на стандартный вывод, необходимы для браузера, что бы сообщить ему, что содержимое страницы имеет тип TEXT/HTML.
При написании CGI приложений, вам необходим, какой то путь для доступа к данным базы. Одним из простых решений будет использование BDE и помещение ваших данных в таблицы Парадокса или dBASE. Если по какой либо причине BDE не инсталлировано на вашем NT Web сервере (может быть ваш дружественный Internet Provider не предоставляет вам BDE), вы можете использовать технику старых дней, используйте вместо базы данных файл записей.. Все что вам нужно, определить тип TRecord и написать программу, которая конвертирует вашу базу данных в file of TRecord.
Если вы посмотрите на список полей Парадокса, то вам не составит труда понять, что не все поля можно просто конвертировать в текстовый формат, например типа Memo обычно не помещаются в короткие строки (Short String). А как начет Blob? Для данного типа полей я составил небольшую таблицу конвертирования.
Paradox field type ObjectPascal conversion type TStringField (size) String[length] TIntegerField, TWordField, TSmallIntField Integer Currency Double Memo, Blob n/a (ignored)
Использую данную таблицу не трудно небольшую программу, которая берет на вход таблицу и создает программу определения записи на Паскале.
{$APPTYPE CONSOLE}
uses DB, DBTables;
var i: Integer;
begin
if ParamCount = 1 then with TTable.Create(nil) do
try
TableName := ParamStr(1);
Active := True;
writeln('Type');
writeln(' TRecord = record');
for i:=0 to Pred(FieldDefs.Count) do
begin
if (FieldDefs[i].FieldClass = TStringField) then
writeln(' ':4,FieldDefs[i].Name,': String[',FieldDefs[i].Size,'];')
else
begin
if (FieldDefs[i].FieldClass = TIntegerField) or
(FieldDefs[i].FieldClass = TWordField) or
(FieldDefs[i].FieldClass = TSmallintField) then
writeln(' ':4,FieldDefs[i].Name,': Integer;')
else
if (FieldDefs[i].FieldClass = TCurrencyField) then
writeln(' ':4,FieldDefs[i].Name,': Double;')
else
writeln('{ ':6,FieldDefs[i].Name,' }')
end
end
finally
writeln(' end;');
Free
end
else
writeln('Usage: record tablename')
end.
Конечно, таблица трансляции и программа определения записи должны быть расширены, что включить и другие типы полей Парадокса, но для примера и этого достаточно.
После осознания, что мы можем писать на Delphi 2 CGI приложения без использования BDE, мы решили сгенерировать тип записи для нашей таблицы delbooks.db и конвертировать ее записи в файл записей. Использую программ RECORD.EXE из предыдущей главы мы получили следующее определение записи.
Type
TRecord = record
ISBN: String[16];
Title: String[64];
Author: String[64];
Publisher: String[32];
Price: Double;
Code: String[7];
{ Comments }
Level: Integer;
TechnicalContentsQuality: Integer;
QualityOfWriting: Integer;
ValueForMoney: Integer;
OverallAssessment: Integer;
{ Cover }
end;
Теперь нам осталось написать сам конвертор, который в цикле просматривает записи таблицы, помещает их в запись и записывает в файл.
{$APPTYPE CONSOLE}
uses DB, DBTables, SysUtils;
var i: Integer;
Rec: TRecord;
F: File of TRecord;
begin
if ParamCount = 1 then with TTable.Create(nil) do
try
System.Assign(f,ChangeFileExt(ParamStr(1),'.REC'));
Rewrite(f);
TableName := ParamStr(1);
Active := True;
First;
while not Eof do with Rec do
begin
ISBN := FieldByName('ISBN').AsString;
Title := FieldByName('Title').AsString;
Author := FieldByName('Author').AsString;
Publisher := FieldByName('Publisher').AsString;
Price := FieldByName('Price').AsFloat;
Code := FieldByName('Code').AsString;
Level := FieldByName('Level').AsInteger;
TechnicalContentsQuality :=
FieldByName('TechnicalContentsQuality').AsInteger;
QualityOfWriting := FieldByName('QualityOfWriting').AsInteger;
ValueForMoney := FieldByName('ValueForMoney').AsInteger;
OverallAssessment := FieldByName('OverallAssessment').AsInteger;
write(f,Rec);
Next
end
finally
System.Close(f);
Free
end
else
writeln('Usage: convert tablename')
end.
Данная программа может использоваться для полного преобразования таблицы delbooks.db в файл delbooks.rec с типом записи TRecord. Delphi 2 CGI приложение может просто открыть этот файл и читать любую запись без использования BDE. Конечно, преобразование записей не просто сделать, но для этого мы имеем всегда оригинальную базу и можем запускать периодически программу преобразования. Так как я добавляю всего несколько записей примерно раз в два месяца, то меня это не очень волнует.
2.2.8. Производительность
Единственное различие между обычным CGI приложением, которое использует BDE для получения данных и нашим приложением без использования BDE это производительность. Кроме того, наше CGI всего лишь 70 KB, оно не нуждается в загрузке BDE, так что время загрузки еще меньше (в результате еще более высокая производительность). В действительности реальные CGI приложения, использующие BDE, часто используют ISAPI (Information Server API) или NSAPI (Netscape Server API) расширения для сохранения CGI приложения "все-время-в-полете (in the air)".