Сервер Web своими руками. Язык HTML, приложения CGI и ISAPI, установка серверов Web для Windows© Александр Фролов, Григорий ФроловТом 29, М.: Диалог-МИФИ, 1997, 288 стр. Приложение ISHELLOВ качестве нашего первого расширения ISAPI мы предлагаем приложение ISHELLO, выполняющее простейшие функции. Вызов расширения ishello.dll выполняется из формы, исходный текст которой приведен в листинге 8.1. Листинг 8.1. Файл chap8\ishello\ishello.htm
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
<HTML>
<HEAD>
<TITLE>ISAPI Script Test</TITLE>
</HEAD>
<BODY BGCOLOR=#FFFFFF>
<H1>Вызов расширения ISAPI</H1>
<FORM METHOD=POST ACTION="http://frolov/scripts/ishello.dll?Param1|Param2|Param3">
<INPUT TYPE=submit VALUE="Send">
</FORM>
</BODY>
</HTML>
Расширение вызывается в параметре ACTION оператора <FORM> аналогично тому, как это делается для программ CGI. Расширение ishello.dll динамически создает документ HTML, представленный на рис. 8.1.
Рис. 8.1. Документ HTML, созданный динамически расширением ishello.dll В верхней части этого документа отображается содержимое некоторых полей структуры EXTENSION_CONTROL_BLOCK XE "EXTENSION_CONTROL_BLOCK" , а в нижней в качетсве примера отображается содержимое переменной ALL_HTTP, полученное с помощью функции GetServerVariable. Исходный текст расширения ishello.dll представлен в листинге 8.2.
// ===============================================
// Расширение ISAPI ishello.c
// Пример простейшего расширения ISAPI
//
// (C) Фролов А.В., 1997
// E-mail: frolov@glas.apc.org
// WWW: http://www.glasnet.ru/~frolov
// или
// http://www.dials.ccas.ru/frolov
// ===============================================
#include <windows.h>
#include <httpext.h>
// =============================================================
// Функция GetExtensionVersion
// Запись версии интерфейса ISAPI и
// строки описания расширения
// =============================================================
BOOL WINAPI GetExtensionVersion(HSE_VERSION_INFO *pVer)
{
// Записываем версию интерфейса ISAPI
pVer->dwExtensionVersion =
MAKELONG(HSE_VERSION_MINOR,HSE_VERSION_MAJOR );
// Записываем строку описания расширения
lstrcpyn(pVer->lpszExtensionDesc,
"Simple ISAPI DLL", HSE_MAX_EXT_DLL_NAME_LEN);
return TRUE;
}
// =============================================================
// Функция HttpExtensionProc
// =============================================================
DWORD WINAPI HttpExtensionProc(EXTENSION_CONTROL_BLOCK *lpECB)
{
CHAR szBuff[4096];
CHAR szTempBuf[4096];
DWORD dwSize;
// Нулевой код состояния - признак успешного выполнения
lpECB->dwHttpStatusCode = 0;
// Записываем в буфер заголовок HTTP и начальный
// фрагмент формируемого динамически документа HTML
wsprintf(szBuff,
"Content-Type: text/html\r\n\r\n"
"<HTML><HEAD><TITLE>Simple ISAPI Extension</TITLE></HEAD>\n"
"<BODY BGCOLOR=#FFFFFF><H1>Hello from ISAPI Extension!</H1>\n");
// Добавляем разделительную линию
strcat(szBuff, "<HR>");
// Добавляем версию интерфейса ISAPI
wsprintf(szTempBuf, "<P>Extension Version: %d.%d",
HIWORD(lpECB->dwVersion), LOWORD(lpECB->dwVersion));
strcat(szBuff, szTempBuf);
// Название метода передачи данных
wsprintf(szTempBuf, "<BR>Method: %s", lpECB->lpszMethod);
strcat(szBuff, szTempBuf);
// Строка параметров запуска расширения ISAPI
wsprintf(szTempBuf, "<BR>QueryString: %s",
lpECB->lpszQueryString);
strcat(szBuff, szTempBuf);
// Физический путь к программному файлу расширения ISAPI
wsprintf(szTempBuf, "<BR>PathTranslated: %s",
lpECB->lpszPathTranslated);
strcat(szBuff, szTempBuf);
// Полный размер данных, которые нужно получить
wsprintf(szTempBuf, "<BR>TotalBytes: %d",
lpECB->cbTotalBytes);
strcat(szBuff, szTempBuf);
// Тип данных
wsprintf(szTempBuf, "<BR>ContentType: %s",
lpECB->lpszContentType);
strcat(szBuff, szTempBuf);
// Отображаем содержимое переменных сервера
strcat(szBuff, "<HR><P><B>Server Variables:</B><BR>");
dwSize = 4096;
lpECB->GetServerVariable(lpECB->ConnID,
(LPSTR)"ALL_HTTP", (LPVOID)szTempBuf, &dwSize);
strcat(szBuff, szTempBuf);
// Конечный фрагмент документа HTML
strcat(szBuff, "</BODY></HTML>");
// Посылаем содержимое буфера удаленному пользователю
if(!lpECB->ServerSupportFunction(lpECB->ConnID,
HSE_REQ_SEND_RESPONSE_HEADER, NULL, NULL,
(LPDWORD)szBuff))
{
// Если послать данные не удалось,
// завершаем работу нашего расширения ISAPI
// с кодом ошибки
return HSE_STATUS_ERROR;
}
// Записываем код успешного завершения
lpECB->dwHttpStatusCode = 200;
// Возвращаем признак успешного завершения
return HSE_STATUS_SUCCESS;
}
Обратите внимание, что наряду с обычным для приложений Windows файлом windows.h мы включили в наш исходный текст файл httpext.h, в котором определены все необходимые константы, структуры данных и прототипы функций. Этот файл поставляется в составе Microsoft Visual C++ версии 4.2, а также в составе Internet SDK, который можно получить на сервере www.microsoft.com. В приложении определена функция GetExtensionVersion, которая уже была рассмотрена нами ранее. Эта функция с небольшими изменениями будет встречаться во всех наших примерах расширений ISAPI. Она записывает версию интерфейса ISAPI и текстовую строку описания расширения в поля структуры типа HSE_VERSION_INFO с именами dwExtensionVersion и lpszExtensionDesc, сответственно. Адрес структуры HSE_VERSION_INFO передается функции GetExtensionVersion через единственный параметр. Функция HttpExtensionProc использует буфер szBuff для подготовки динамически создаваемого документа HTML, который будет послан удаленному пользователю в результате работы нашего расширения. В качестве вспомогательного буфера применяется буфер szTempBuf. Прежде всего в буфер szBuff записывается заголовок HTTP и начальный фрагмент документа HTML, для чего используется функция wsprintf. Далее к буферу szBuff с помощью функции strcat будут добавляться другие строки документа. Например, разделительная линия добавляется так: strcat(szBuff, "<HR>"); После первой разделительной линии в документ добавляется несколько строк со значениями некоторых полей структуры типа EXTENSION_CONTROL_BLOCK. В следующем фрагменте кода добавляется строка версии интерфейса ISAPI: wsprintf(szTempBuf, "<P>Extension Version: %d.%d", HIWORD(lpECB->dwVersion), LOWORD(lpECB->dwVersion)); strcat(szBuff, szTempBuf); Далее в документ выводятся строка с названием метода передачи данных (поле lpszMethod), строка параметров запуска расширения ISAPI (поле lpszQueryString), физический путь к программному файлу библиотеки DLL расширения (поле lpszPathTranslated), полный размер данных, которые нужно прочитать (поле cbTotalBytes), а также тип данных (поле lpszContentType). После этого в документ снова выводится разделительная линия и отображается содержимое переменных сервера с префиксом имени HTTP, для чего используется рассмотренная ранее функция GetServerVariable. В завершении в документ записывается финальная строка: strcat(szBuff, "</BODY></HTML>"); Документ посылается удаленному пользователю функцией ServerSupportFunction, как это показано ниже:
if(!lpECB->ServerSupportFunction(lpECB->ConnID,
HSE_REQ_SEND_RESPONSE_HEADER, NULL, NULL, (LPDWORD)szBuff))
{
return HSE_STATUS_ERROR;
}
Если при посылке данных произошла ошибка, расширение завершает свою работу с кодом HSE_STATUS_ERROR. В случае успеха в поле состояния dwHttpStatusCode записывается код 200, вслед за чем расширение завершает свою работу с кодом HSE_STATUS_SUCCESS. Файл определения модуля для библиотеки DLL расширения ISAPI представлен в листинге 8.3. Листинг 8.3. Файл chap8\ishello\ishello.def
LIBRARY ishello
DESCRIPTION 'Simple ISAPI DLL'
EXPORTS
GetExtensionVersion
HttpExtensionProc
|


