📄 shorthand_isapi.cpp
字号:
///////////////////////////////////////////////////////////////////////////////
// $Header: /shorthand/src/shorthand_isapi.cpp 1 2/08/03 6:40a Arm $
//-----------------------------------------------------------------------------
// Project: ShortHand interpreter
// Author: Andrei Remenchuk <andrei@remenchuk.com>
//-----------------------------------------------------------------------------
// shorthand_isapi.cpp: implementations of ISAPI Module mod_shorthand
///////////////////////////////////////////////////////////////////////////////
#include <windows.h>
#include <process.h>
#include <httpext.h>
#include <httpfilt.h>
#include <httpext.h>
#include "version.h"
#include "shorthand.h"
#include "array.h"
#include "nodes.h"
#include "http.h"
#include "utils.h"
#include "module.h"
#include "version.h"
#include "regexx.h"
#undef putenv
#define PHP_ENABLE_SEH
#define MAX_STATUS_LENGTH sizeof("xxxx LONGEST STATUS DESCRIPTION")
#define ISAPI_SERVER_VAR_BUF_SIZE 1024
#define ISAPI_POST_DATA_BUF 1024
int isapi_shorthand_main(LPEXTENSION_CONTROL_BLOCK ecb, int display_source_mode);
/**
* HTTPStream implementation that is responsible for handling
* HTTP i/o tasks for ShortHand core.
*/
class ISAPIHttpStream : public HttpStream
{
protected:
LPEXTENSION_CONTROL_BLOCK m_ecb;
int m_chunk_number;
map<string*> m_in_cookies; // inbound cookies
CHttpCookieJar m_out_cookies;
map<string*> m_out_headers; // outbound headers
string m_content_type;
bool m_headers_sent;
bool m_did_client_block;
bool m_have_input;
bool m_cookies_grabbed;
int m_response_code;
string m_response_message;
DWORD m_input_offset;
public:
ISAPIHttpStream(LPEXTENSION_CONTROL_BLOCK ecb)
{
m_ecb = ecb;
m_headers_sent = false;
m_did_client_block = false;
m_have_input = false;
m_response_code = 200;
m_response_message = "OK";
m_cookies_grabbed = false;
m_content_type = "text/html";
m_input_offset = 0;
}
bool http_headers_sent() { return m_headers_sent; }
int http_read(void* buffer, int buffer_size);
int code() const { return m_response_code; }
int http_add_header(const char* name, const char* value);
int http_send_headers();
int http_write_chunk(const void* chunk_data, unsigned int chunk_length);
void grab_cookies();
const char* http_get_cookie(const char* name);
int http_set_cookie(const CHttpCookie* cookie);
// overrides HTTP response code (with optional status line message)
// most servers will allow to change code, but few allow to change message
void http_set_response_code(int code, const char* msg);
int http_finalize();
};
static bool bFilterLoaded = false;
static bool bTerminateThreadsOnError = false;
static char *isapi_special_server_variable_names[] =
{
"ALL_HTTP",
"HTTPS",
"SCRIPT_NAME",
NULL
};
#define NUM_SPECIAL_VARS (sizeof(isapi_special_server_variable_names)/sizeof(char *))
#define SPECIAL_VAR_ALL_HTTP 0
#define SPECIAL_VAR_HTTPS 1
#define SPECIAL_VAR_PHP_SELF 2
static char *isapi_server_variable_names[] =
{
"AUTH_PASSWORD",
"AUTH_TYPE",
"AUTH_USER",
"CONTENT_LENGTH",
"CONTENT_TYPE",
"HTTP_ACCEPT",
"HTTP_ACCEPT_LANGUAGE",
"HTTP_COOKIE",
"HTTP_USER_AGENT",
"HTTP_HOST",
"HTTP_REFERER",
"PATH_INFO",
"PATH_TRANSLATED",
"QUERY_STRING",
"REMOTE_ADDR",
"REMOTE_HOST",
"REMOTE_PORT",
"REMOTE_USER",
"REQUEST_METHOD",
"REQUEST_URI",
"SCRIPT_NAME",
"SERVER_ADMIN",
"SERVER_NAME",
"SERVER_PORT",
"SERVER_PROTOCOL",
"SERVER_SOFTWARE",
"REQUEST_URI",
"URL",
NULL
};
static char *isapi_secure_server_variable_names[] = {
"CERT_COOKIE",
"CERT_FLAGS",
"CERT_ISSUER",
"CERT_KEYSIZE",
"CERT_SECRETKEYSIZE",
"CERT_SERIALNUMBER",
"CERT_SERVER_ISSUER",
"CERT_SERVER_SUBJECT",
"CERT_SUBJECT",
"HTTPS_KEYSIZE",
"HTTPS_SECRETKEYSIZE",
"HTTPS_SERVER_ISSUER",
"HTTPS_SERVER_SUBJECT",
"SERVER_PORT_SECURE",
NULL
};
/*
static void php_info_isapi(ZEND_MODULE_INFO_FUNC_ARGS)
{
char **p;
char variable_buf[ISAPI_SERVER_VAR_BUF_SIZE];
DWORD variable_len;
char **all_variables[] = {
isapi_server_variable_names,
isapi_special_server_variable_names,
isapi_secure_server_variable_names,
NULL
};
char ***server_variable_names;
LPEXTENSION_CONTROL_BLOCK lpECB;
lpECB = (LPEXTENSION_CONTROL_BLOCK) SG(server_context);
php_info_print_table_start();
php_info_print_table_header(2, "Server Variable", "Value");
server_variable_names = all_variables;
while (*server_variable_names) {
p = *server_variable_names;
while (*p) {
variable_len = ISAPI_SERVER_VAR_BUF_SIZE;
if (lpECB->GetServerVariable(lpECB->ConnID, *p, variable_buf, &variable_len)
&& variable_buf[0]) {
php_info_print_table_row(2, *p, variable_buf);
} else if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
char *tmp_variable_buf;
tmp_variable_buf = (char *) emalloc(variable_len);
if (lpECB->GetServerVariable(lpECB->ConnID, *p, tmp_variable_buf, &variable_len)
&& variable_buf[0]) {
php_info_print_table_row(2, *p, tmp_variable_buf);
}
efree(tmp_variable_buf);
}
p++;
}
server_variable_names++;
}
php_info_print_table_end();
}
static zend_module_entry php_isapi_module = {
STANDARD_MODULE_HEADER,
"ISAPI",
NULL,
NULL,
NULL,
NULL,
NULL,
php_info_isapi,
NULL,
STANDARD_MODULE_PROPERTIES
};
*/
static int isapi_write_client(LPEXTENSION_CONTROL_BLOCK ecb, const char *str, int str_length = -1)
{
if (str_length == -1) str_length = strlen(str);
DWORD num_bytes = str_length;
if (ecb->WriteClient(ecb->ConnID, (char *) str, &num_bytes, HSE_IO_SYNC ) == FALSE)
{
//php_handle_aborted_connection();
}
return num_bytes;
}
/*
static int sapi_isapi_header_handler(sapi_header_struct *sapi_header, sapi_headers_struct *sapi_headers TSRMLS_DC)
{
return SAPI_HEADER_ADD;
}
static void accumulate_header_length(sapi_header_struct *sapi_header, uint *total_length TSRMLS_DC)
{
*total_length += sapi_header->header_len+2;
}
*/
/*
static void concat_header(sapi_header_struct *sapi_header, char **combined_headers_ptr TSRMLS_DC)
{
memcpy(*combined_headers_ptr, sapi_header->header, sapi_header->header_len);
*combined_headers_ptr += sapi_header->header_len;
**combined_headers_ptr = '\r';
(*combined_headers_ptr)++;
**combined_headers_ptr = '\n';
(*combined_headers_ptr)++;
}
*/
/*
static int sapi_isapi_send_headers(sapi_headers_struct *sapi_headers TSRMLS_DC)
{
uint total_length = 2; // account for the trailing \r\n
char *combined_headers, *combined_headers_ptr;
LPEXTENSION_CONTROL_BLOCK lpECB = (LPEXTENSION_CONTROL_BLOCK) SG(server_context);
HSE_SEND_HEADER_EX_INFO header_info;
char status_buf[MAX_STATUS_LENGTH];
sapi_header_struct default_content_type;
// Obtain headers length
if (SG(sapi_headers).send_default_content_type) {
sapi_get_default_content_type_header(&default_content_type TSRMLS_CC);
accumulate_header_length(&default_content_type, (void *) &total_length TSRMLS_CC);
}
zend_llist_apply_with_argument(&SG(sapi_headers).headers, (llist_apply_with_arg_func_t) accumulate_header_length, (void *) &total_length TSRMLS_CC);
// Generate headers
combined_headers = (char *) emalloc(total_length+1);
combined_headers_ptr = combined_headers;
if (SG(sapi_headers).send_default_content_type) {
concat_header(&default_content_type, (void *) &combined_headers_ptr TSRMLS_CC);
sapi_free_header(&default_content_type); // we no longer need it
}
zend_llist_apply_with_argument(&SG(sapi_headers).headers, (llist_apply_with_arg_func_t) concat_header, (void *) &combined_headers_ptr TSRMLS_CC);
*combined_headers_ptr++ = '\r';
*combined_headers_ptr++ = '\n';
*combined_headers_ptr = 0;
switch (SG(sapi_headers).http_response_code) {
case 200:
header_info.pszStatus = "200 OK";
break;
case 302:
header_info.pszStatus = "302 Moved Temporarily";
break;
case 401:
header_info.pszStatus = "401 Authorization Required";
break;
default:
snprintf(status_buf, MAX_STATUS_LENGTH, "%d Undescribed", SG(sapi_headers).http_response_code);
header_info.pszStatus = status_buf;
break;
}
header_info.cchStatus = strlen(header_info.pszStatus);
header_info.pszHeader = combined_headers;
header_info.cchHeader = total_length;
header_info.fKeepConn = FALSE;
lpECB->dwHttpStatusCode = SG(sapi_headers).http_response_code;
lpECB->ServerSupportFunction(lpECB->ConnID, HSE_REQ_SEND_RESPONSE_HEADER_EX, &header_info, NULL, NULL);
efree(combined_headers);
return SAPI_HEADER_SENT_SUCCESSFULLY;
}
*/
/*
static int php_isapi_startup(sapi_module_struct *sapi_module)
{
if (php_module_startup(sapi_module)==FAILURE
|| zend_startup_module(&php_isapi_module)==FAILURE) {
return FAILURE;
} else {
bTerminateThreadsOnError = (zend_bool) INI_INT("isapi.terminate_threads_on_error");
return SUCCESS;
}
}
static int sapi_isapi_read_post(char *buffer, uint count_bytes TSRMLS_DC)
{
LPEXTENSION_CONTROL_BLOCK lpECB = (LPEXTENSION_CONTROL_BLOCK) SG(server_context);
DWORD read_from_buf=0;
DWORD read_from_input=0;
DWORD total_read=0;
if ((DWORD) SG(read_post_bytes) < lpECB->cbAvailable) {
read_from_buf = MIN(lpECB->cbAvailable-SG(read_post_bytes), count_bytes);
memcpy(buffer, lpECB->lpbData+SG(read_post_bytes), read_from_buf);
total_read += read_from_buf;
}
if (read_from_buf<count_bytes
&& (SG(read_post_bytes)+read_from_buf) < lpECB->cbTotalBytes) {
DWORD cbRead=0, cbSize;
read_from_input = MIN(count_bytes-read_from_buf, lpECB->cbTotalBytes-SG(read_post_bytes)-read_from_buf);
while (cbRead < read_from_input) {
cbSize = read_from_input - cbRead;
if (!lpECB->ReadClient(lpECB->ConnID, buffer+read_from_buf+cbRead, &cbSize) || cbSize==0) {
break;
}
cbRead += cbSize;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -