,并且能在第二台机器上的网
页浏览器调用它。
在本文中接下来的ISAPI的其余部分将会更加深入。
这里是HttpExtensionProc参数中比较复杂的部分
PExtensionControlBlock = ^TExtensionControlBlock;
TExtensionControlBlock = packed record
cbSize: DWORD; // = sizeof(TExtensionControlBlock)
dwVersion: DWORD; // version info of this spec
ConnID: HCONN; // Context Do not modify!
dwHttpStatusCode: DWORD; // HTTP Status code
// null terminated log info specific to this Extension DLL
lpszLogData: array [0..HSE_LOG_BUFFER_LEN-1] of Char;
lpszMethod: PChar; // REQUEST_METHOD
lpszQueryString: PChar; // QUERY_STRING
lpszPathInfo: PChar; // PATH_INFO
lpszPathTranslated: PChar; // PATH_TRANSLATED
cbTotalBytes: DWORD; // Total bytes from client
cbAvailable: DWORD; // Available number of bytes
lpbData: Pointer; // pointer to cbAvailable bytes
lpszContentType: PChar; // Content type of client data
GetServerVariable: TGetServerVariableProc;
WriteClient: TWriteClientProc;
ReadClient: TReadClientProc;
ServerSupportFunction: TServerSupportFunctionProc;
end;
注意到这个纪录中包含了上面提到过的ConnID字段,并且向 WriteClient 传送第一个参数。
这个纪录中的第一个参数是为版本控制而设的。它应该是TExtensionControlBlock的大小的规定。如果微软公司改变了它的结构,那么它们能够通过检查纪录的大小来判断它们正在处理的结构版本。 您永远也不要这个纪录中的前三个字段,它们早已被ISAPI填充,在您的程序中,它们只能被访问,而不能被改变。
这个纪录中最重要的字段可能就是lpszQueryString了,它包含了从服务器上传来的请求
的信息。例如,假设您已经创建了一个名叫 ISAPI1.Dll。为了调用这个DLL,您就要在您的浏览器的一页上创建一个像这样的HREF [注:HTML语言中的一种格式(译者)] :
Test One
如果您希望响应这个DLL,您就要对上面那行做这样的改动:
Test One
假如HTML代码段中有像上面两行中的第二行,那么,您的DLL就会在lpszQueryString参数
中得到“MyQuery” 的字符串,特别要注意跟在请求字符串后的请求标志的使用。
当然,您可以随心所欲地改变请求字符串。例如,您可以这样写:
Test One
在这个请求中,这个DLL会回答服务器的名称。您在传递这个参数时,不受任何限制。您
可以传递任何您想要的东西,而且,如何分析DLL中的信息也由您的喜好决定。
当您从服务器返回信息至浏览器时,您使用到了这个纪录中的“WriteClient”函数指针
。在初始化这个指针时您不需做任何事;它已经自动地有网络信息服务器传递给您了。
CGI应用程序的作者会注意到传送请求字符串的语法十分熟悉。事实上,ISAPI跟随了CGI
的大多数习惯,在TExtensionControlBlock中的多数字段可以简单地被CGI技术借用。
在TExtensionControlBlock中的另一个关键字段是 lpbData ,它包含了从浏览起上传给您的附加信息。
例如,您有一个伴随几个字段的HTML窗体,这些自断中包含的信息就会被一个叫做“
lpData”的指针传递。本文中的下一个主题,“从‘确认’按钮中获得信息”,将会着重讲述怎样处理这种情况。
到现在为止我已经介绍了TExtensionControlBlock中的四个关键字段:
WriteClient: 一个能够让您传递格式化的HTML数据到浏览器上的指针。这个函数用到了
TExtensionControlBlock的ConnID字段。
lpszQueryString: 从浏览骑上传来的请求。
lpbData: 从浏览器上传给你的人一的附加数据。通常是一个HTML窗体的任意字段的内容
。我将在“确认 按钮”这部分进一步讨论。
要获得其他TExtensionControlBlock中的字段是如何工作的感觉,最好的办法就是亲自在
浏览其中将他们做对照。换句话说,您会希望创建一个HTML页,使得用能够调用客户端的ISAPI DLL。这个ISAPI DLL的目的仅仅是在HTML中格式话TExtensionControlBlock中的每一个字段,然后把它们传回浏览器。这样就把您的浏览器变成了一个有点可怕的调试器,来显示TExtensionControlBlock中的所有字段。
这里有一个程序,由Borland公司的 Danny Thorpe 编写,他会执行这个任务:
library test1;
uses
Windows
SysUtils
HTTPExt;
function GetExtensionVersion( var Ver: THSE_VERSION_INFO ): BOOL; stdcall;
begin
Ver.dwExtensionVersion := $00010000; // 1.0 support
Ver.lpszExtensionDesc := ''''A test DLL written in Delphi 2.0'''';
Result := True;
end;
function HttpExtensionProc( var ECB: TEXTENSION_CONTROL_BLOCK ):
DWORD; stdcall;
var
ResStr: string;
StrLen: Integer;
Buf: array [0..1024] of Char;
begin
ECB.lpszLogData := ''''Delphi DLL Log'''';
ECB.dwHTTPStatusCode := 200;
ResStr := Format(
'''''''' +
''''
Test server results'''' +
''''Size = %d ''''+
''''Version = %.8x ''''+
''''ConnID = %.8x ''''+
''''Method = %s '''' +
''''Query = %s '''' +
''''PathInfo = %s ''''+
''''PathTranslated = %s ''''+
''''TotalBytes = %d ''''+
''''AvailableBytes = %d ''''+
''''ContentType = %s
''''+
''''
Some Server Variables''''
[ECB.cbSize
ECB.dwVersion
ECB.ConnID
ECB.lpszMethod
ECB.lpszQueryString
ECB.lpszPathInfo
ECB.lpszPathTranslated
ECB.cbTotalBytes
ECB.cbAvailable
ECB.lpszContentType]);
with ECB do
begin
StrLen := Sizeof(Buf);
GetServerVariable(ConnID
''''REMOTE_ADDR''''
@Buf
StrLen);
ResStr := ResStr + ''''REMOTE_ADDR = ''''+Buf+'''' '''';
StrLen := SizeOf(Buf);
GetServerVariable(ConnID
''''REMOTE_HOST''''
@Buf
StrLen);
ResStr := ResStr + ''''Remote_Host = ''''+Buf+'''' '''';
StrLen := SizeOf(Buf);
GetServerVariable(ConnID
''''REMOTE_USER''''
@Buf
StrLen);
ResStr := ResStr + ''''Remote_User = ''''+Buf+'''' '''';
StrLen := SizeOf(Buf);
GetServerVariable(ConnID
''''SERVER_NAME''''
@Buf
StrLen);
ResStr := ResStr + ''''SERVER_NAME = ''''+Buf+'''' '''';
StrLen := SizeOf(Buf);
GetServerVariable(ConnID
''''SERVER_PORT''''
@Buf
StrLen);
ResStr := ResStr + ''''SERVER_PORT = ''''+Buf+'''' '''';
StrLen := SizeOf(Buf);
GetServerVariable(ConnID
''''SERVER_PROTOCOL''''
@Buf
StrLen);
ResStr := ResStr + ''''SERVER_PROTOCOL = ''''+Buf+'''' '''';
StrLen := SizeOf(Buf);
GetServerVariable(ConnID
''''SERVER_SOFTWARE''''
@Buf
StrLen);
ResStr := Format(''''%sSERVER_SOFTWARE = %s ''''+
''''ThreadID = %.8x ''''
[ResStr
Buf
GetCurrentThreadID]);
end;
ResStr := ResStr + '''''''';
ResStr := Format(
''''HTTP/1.0 200 OK''''#13#10+
''''Content-Type: text/html''''#13#10+
''''Content-Length: %d''''#13#10+
''''Content:''''#13#10#13#10''''%s''''
[Length(ResStr)
ResStr]);
StrLen := Length(ResStr);
ECB.WriteClient(ECB.ConnID
Pointer(ResStr)
StrLen
0);
Result := HSE_STATUS_SUCCESS;
end;
xports
GetExtensionVersion
HttpExtensionProc;
egin
end.
为了调用这个DLL,您应该建立一个包括下面这行的 HRML 脚本
Test One
从“确认”按钮获得信息
通常向您发送信息的HTML窗体中都有一个确认按钮。只要信息量小于49KB,您就可以
认为TExetensionControlBlock中的 lpbData 字段是可用的。这里显示了您可以如何在大
多数情况下获得由这个字段的指针发来的信息:
var
S: string;
begin
…
S := PChar(ECB.lpbData);
…
end;
如果从这个字段传来的信息大于48KB,那么您必须呼叫 ReadClient 来获得其余的信息。
如果您想要确切地知道在 lpbData 字段中哪些信息是可用的,您可以使用下面两个函数把数据传回到您的网页浏览器中:
function SetUpResString: string;
begin
Result := '''''''' +
'''''''' +
''''
Test server results'''' +
''''lpbData = %s '''' +
'''''''';
end;
function HttpExtensionProc(var ECB: TExtensionControlBlock):
DWORD; stdcall;
var
ResStr: string;
StrLen: Integer;
S
S1: string;
begin
ECB.lpszLogData := ''''Delphi DLL Log'''';
ECB.dwHTTPStatusCode := 200;
ResStr := SetUpResString;
S := PChar(ECB.lpbData);
ResStr := Format(ResStr
[S]);
StrLen := Length(ResStr);
ECB.WriteClient(ECB.ConnID
Pointer(ResStr)
StrLen
0);
Result := HSE_STATUS_SUCCESS;
end;
假设您已经有了附有下面代码的HTML窗体:
这段代码会产生一个包含一个供您输入数字的文本区和一个叫做“submit”按钮的窗体,按钮的名字叫做“GetSquare”。如果有了这个窗体,接着您可以预计上面的两段程序会返回如下的字符串,假设用户在窗体中的文本区输入了数字23:
lpbData = GetSquare=23&GetSquare=Submit
为了理解这时究竟发生了什么,注意一下从上面函数中摘录HTML语句中的主体部分, 这部分语句驻留在服务器上,反映如下:
''''lpbData = %s '''' +
如果您研究过上面 HttpExtensionProc 函数中的代码,您会发现就在这句之前,它使用了 Format 语句中的 %s 参数来代替了 ECB.lpbData 中的值。(如果您不清楚语句Format 是怎样工作的,请参阅有关的 Delphi 文档)[注:在作者所著的 Delphi2 编程大全(Delphi2
Unleashed)中的第三章《字符串与文本文件》中有详细说明(译者)]
假设上面所示的窗体中,当用户按下“确认”按钮时,lpbData 传递给ISAPI DLL的值是:
GetSquare=23&GetSquare=Submit
为了让您有清晰的概念,让我重复一下上面两个语句传回给浏览器的信息是下面的字符串,您已经看过了:
lpbData = GetSquare=23&GetSquare=Submit
观看这个过程的最好办法试运行下面列出的 ISAPI2 程序。 ISAPI2 和ISAPI1 差不多,但他包含了上面显示的新的 HttpExtensionProc 函数,并且它还包含了SetUpResString 这个实用函数。
library Isapi2;
uses
Windows
SysUtils
HTTPExt;
function GetExtensionVersion( var Ver: THSE_VERSION_INFO ):
BOOL; stdcall;
begin
Ver.dwExtensionVersion := $00010000; // 1.0 support
Ver.lpszExtensionDesc := ''''DLL written in Delphi 2.0'''';
Result := True;
end;
function SetUpResString: string;
begin
Result := '''''''' +
'''''''' +
''''
Test server results'''' +
''''lpbData = %s '''' +
'''''''';
end;
function HttpExtensionProc( var ECB: TEXTENSION_CONTROL_BLOCK ):
DWORD; stdcall;
var
ResStr: string;
StrLen: Integer;
S
S1: string;
Len: Integer;
begin
ECB.lpszLogData := ''''Delphi DLL Log'''';
ECB.dwHTTPStatusCode := 200;
ResStr := SetUpResString;
S := PChar(ECB.lpbData);
ResStr := Format(ResStr
上一页 [1] [2] [3] 下一页 [聊天工具]用Windows98第二版直接共享Internet [系统软件]Internet Explorer 编程简述(繁体版) [系统软件]单击链接后无法打开新的 Internet Explorer 窗口或… [系统软件]OLE with the internet explorer [常用软件]Internet Explorer 6 Public Preview 最新出击!! [常用软件]Internet Explorer中的潘多拉魔盒 作者:江海 [常用软件][网络]Becky Internet Mail 软件评测 [VB.NET程序]VB自动登陆网络站点详解(三):Internet Explore… [Delphi程序]谈Delphi 下Internet 编程技巧(二) [Delphi程序]谈Delphi下Internet的编程技巧(一)
|