Сервер 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 |