📄 mod_isapi.c
字号:
apr_filepath_merge(&file, "", file, APR_FILEPATH_NATIVE, r->pool);
#endif
*buf_size = apr_cpystrn(buf_data, file, *buf_size) - buf_data;
return 1;
}
case HSE_REQ_GET_SSPI_INFO:
if (cid->dconf.log_unsupported)
ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r,
"ISAPI: ServerSupportFunction HSE_REQ_GET_SSPI_INFO "
"is not supported: %s", r->filename);
apr_set_os_error(APR_FROM_OS_ERROR(ERROR_INVALID_PARAMETER));
return 0;
case HSE_APPEND_LOG_PARAMETER:
/* Log buf_data, of buf_size bytes, in the URI Query (cs-uri-query) field
*/
apr_table_set(r->notes, "isapi-parameter", (char*) buf_data);
if (cid->dconf.log_to_query) {
if (r->args)
r->args = apr_pstrcat(r->pool, r->args, (char*) buf_data, NULL);
else
r->args = apr_pstrdup(r->pool, (char*) buf_data);
}
if (cid->dconf.log_to_errlog)
ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r,
"ISAPI: %s: %s", cid->r->filename,
(char*) buf_data);
return 1;
case HSE_REQ_IO_COMPLETION:
/* Emulates a completion port... Record callback address and
* user defined arg, we will call this after any async request
* (e.g. transmitfile) as if the request executed async.
* Per MS docs... HSE_REQ_IO_COMPLETION replaces any prior call
* to HSE_REQ_IO_COMPLETION, and buf_data may be set to NULL.
*/
if (cid->dconf.fake_async) {
cid->completion = (PFN_HSE_IO_COMPLETION) buf_data;
cid->completion_arg = (void *) data_type;
return 1;
}
if (cid->dconf.log_unsupported)
ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r,
"ISAPI: ServerSupportFunction HSE_REQ_IO_COMPLETION "
"is not supported: %s", r->filename);
apr_set_os_error(APR_FROM_OS_ERROR(ERROR_INVALID_PARAMETER));
return 0;
case HSE_REQ_TRANSMIT_FILE:
{
/* we do nothing with (tf->dwFlags & HSE_DISCONNECT_AFTER_SEND)
*/
HSE_TF_INFO *tf = (HSE_TF_INFO*)buf_data;
apr_uint32_t sent = 0;
apr_ssize_t ate = 0;
apr_bucket_brigade *bb;
apr_bucket *b;
apr_file_t *fd;
apr_off_t fsize;
if (!cid->dconf.fake_async && (tf->dwFlags & HSE_IO_ASYNC)) {
if (cid->dconf.log_unsupported)
ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r,
"ISAPI: ServerSupportFunction HSE_REQ_TRANSMIT_FILE "
"as HSE_IO_ASYNC is not supported: %s", r->filename);
apr_set_os_error(APR_FROM_OS_ERROR(ERROR_INVALID_PARAMETER));
return 0;
}
/* Presume the handle was opened with the CORRECT semantics
* for TransmitFile
*/
if ((rv = apr_os_file_put(&fd, &tf->hFile,
APR_READ | APR_XTHREAD, r->pool))
!= APR_SUCCESS) {
return 0;
}
if (tf->BytesToWrite) {
fsize = tf->BytesToWrite;
}
else {
apr_finfo_t fi;
if (apr_file_info_get(&fi, APR_FINFO_SIZE, fd) != APR_SUCCESS) {
apr_set_os_error(APR_FROM_OS_ERROR(ERROR_INVALID_PARAMETER));
return 0;
}
fsize = fi.size - tf->Offset;
}
/* apr_dupfile_oshandle (&fd, tf->hFile, r->pool); */
bb = apr_brigade_create(r->pool, c->bucket_alloc);
/* According to MS: if calling HSE_REQ_TRANSMIT_FILE with the
* HSE_IO_SEND_HEADERS flag, then you can't otherwise call any
* HSE_SEND_RESPONSE_HEADERS* fn, but if you don't use the flag,
* you must have done so. They document that the pHead headers
* option is valid only for HSE_IO_SEND_HEADERS - we are a bit
* more flexible and assume with the flag, pHead are the
* response headers, and without, pHead simply contains text
* (handled after this case).
*/
if ((tf->dwFlags & HSE_IO_SEND_HEADERS) && tf->pszStatusCode) {
ate = send_response_header(cid, tf->pszStatusCode,
(char*)tf->pHead,
strlen(tf->pszStatusCode),
tf->HeadLength);
}
else if (!cid->headers_set && tf->pHead && tf->HeadLength
&& *(char*)tf->pHead) {
ate = send_response_header(cid, NULL, (char*)tf->pHead,
0, tf->HeadLength);
if (ate < 0)
{
apr_brigade_destroy(bb);
apr_set_os_error(APR_FROM_OS_ERROR(ERROR_INVALID_PARAMETER));
return 0;
}
}
if (tf->pHead && (apr_size_t)ate < tf->HeadLength) {
b = apr_bucket_transient_create((char*)tf->pHead + ate,
tf->HeadLength - ate,
c->bucket_alloc);
APR_BRIGADE_INSERT_TAIL(bb, b);
sent = tf->HeadLength;
}
sent += (apr_uint32_t)fsize;
brigade_insert_file(bb, fd, tf->Offset, fsize, r->pool);
if (tf->pTail && tf->TailLength) {
sent += tf->TailLength;
b = apr_bucket_transient_create((char*)tf->pTail,
tf->TailLength, c->bucket_alloc);
APR_BRIGADE_INSERT_TAIL(bb, b);
}
b = apr_bucket_flush_create(c->bucket_alloc);
APR_BRIGADE_INSERT_TAIL(bb, b);
rv = ap_pass_brigade(r->output_filters, bb);
cid->response_sent = 1;
if (rv != APR_SUCCESS)
ap_log_rerror(APLOG_MARK, APLOG_DEBUG, rv, r,
"ISAPI: ServerSupport function "
"HSE_REQ_TRANSMIT_FILE "
"ap_pass_brigade failed: %s", r->filename);
/* Use tf->pfnHseIO + tf->pContext, or if NULL, then use cid->fnIOComplete
* pass pContect to the HseIO callback.
*/
if (tf->dwFlags & HSE_IO_ASYNC) {
if (tf->pfnHseIO) {
if (rv == APR_SUCCESS) {
tf->pfnHseIO(cid->ecb, tf->pContext,
ERROR_SUCCESS, sent);
}
else {
tf->pfnHseIO(cid->ecb, tf->pContext,
ERROR_WRITE_FAULT, sent);
}
}
else if (cid->completion) {
if (rv == APR_SUCCESS) {
cid->completion(cid->ecb, cid->completion_arg,
sent, ERROR_SUCCESS);
}
else {
cid->completion(cid->ecb, cid->completion_arg,
sent, ERROR_WRITE_FAULT);
}
}
}
return (rv == APR_SUCCESS);
}
case HSE_REQ_REFRESH_ISAPI_ACL:
if (cid->dconf.log_unsupported)
ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r,
"ISAPI: ServerSupportFunction "
"HSE_REQ_REFRESH_ISAPI_ACL "
"is not supported: %s", r->filename);
apr_set_os_error(APR_FROM_OS_ERROR(ERROR_INVALID_PARAMETER));
return 0;
case HSE_REQ_IS_KEEP_CONN:
*((int *)buf_data) = (r->connection->keepalive == AP_CONN_KEEPALIVE);
return 1;
case HSE_REQ_ASYNC_READ_CLIENT:
{
apr_uint32_t read = 0;
int res;
if (!cid->dconf.fake_async) {
if (cid->dconf.log_unsupported)
ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r,
"ISAPI: asynchronous I/O not supported: %s",
r->filename);
apr_set_os_error(APR_FROM_OS_ERROR(ERROR_INVALID_PARAMETER));
return 0;
}
if (r->remaining < *buf_size) {
*buf_size = (apr_size_t)r->remaining;
}
while (read < *buf_size &&
((res = ap_get_client_block(r, (char*)buf_data + read,
*buf_size - read)) > 0)) {
read += res;
}
if ((*data_type & HSE_IO_ASYNC) && cid->completion) {
/* XXX: Many authors issue their next HSE_REQ_ASYNC_READ_CLIENT
* within the completion logic. An example is MS's own PSDK
* sample web/iis/extensions/io/ASyncRead. This potentially
* leads to stack exhaustion. To refactor, the notification
* logic needs to move to isapi_handler() - differentiating
* the cid->completed event with a new flag to indicate
* an async-notice versus the async request completed.
*/
if (res >= 0) {
cid->completion(cid->ecb, cid->completion_arg,
read, ERROR_SUCCESS);
}
else {
cid->completion(cid->ecb, cid->completion_arg,
read, ERROR_READ_FAULT);
}
}
return (res >= 0);
}
case HSE_REQ_GET_IMPERSONATION_TOKEN: /* Added in ISAPI 4.0 */
if (cid->dconf.log_unsupported)
ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r,
"ISAPI: ServerSupportFunction "
"HSE_REQ_GET_IMPERSONATION_TOKEN "
"is not supported: %s", r->filename);
apr_set_os_error(APR_FROM_OS_ERROR(ERROR_INVALID_PARAMETER));
return 0;
case HSE_REQ_MAP_URL_TO_PATH_EX:
{
/* Map a URL to a filename */
HSE_URL_MAPEX_INFO *info = (HSE_URL_MAPEX_INFO*)data_type;
char* test_uri = apr_pstrndup(r->pool, (char *)buf_data, *buf_size);
subreq = ap_sub_req_lookup_uri(test_uri, r, NULL);
info->cchMatchingURL = strlen(test_uri);
info->cchMatchingPath = apr_cpystrn(info->lpszPath, subreq->filename,
sizeof(info->lpszPath)) - info->lpszPath;
/* Mapping started with assuming both strings matched.
* Now roll on the path_info as a mismatch and handle
* terminating slashes for directory matches.
*/
if (subreq->path_info && *subreq->path_info) {
apr_cpystrn(info->lpszPath + info->cchMatchingPath,
subreq->path_info,
sizeof(info->lpszPath) - info->cchMatchingPath);
info->cchMatchingURL -= strlen(subreq->path_info);
if (subreq->finfo.filetype == APR_DIR
&& info->cchMatchingPath < sizeof(info->lpszPath) - 1) {
/* roll forward over path_info's first slash */
++info->cchMatchingPath;
++info->cchMatchingURL;
}
}
else if (subreq->finfo.filetype == APR_DIR
&& info->cchMatchingPath < sizeof(info->lpszPath) - 1) {
/* Add a trailing slash for directory */
info->lpszPath[info->cchMatchingPath++] = '/';
info->lpszPath[info->cchMatchingPath] = '\0';
}
/* If the matched isn't a file, roll match back to the prior slash */
if (subreq->finfo.filetype == APR_NOFILE) {
while (info->cchMatchingPath && info->cchMatchingURL) {
if (info->lpszPath[info->cchMatchingPath - 1] == '/')
break;
--info->cchMatchingPath;
--info->cchMatchingURL;
}
}
/* Paths returned with back slashes */
for (test_uri = info->lpszPath; *test_uri; ++test_uri)
if (*test_uri == '/')
*test_uri = '\\';
/* is a combination of:
* HSE_URL_FLAGS_READ 0x001 Allow read
* HSE_URL_FLAGS_WRITE 0x002 Allow write
* HSE_URL_FLAGS_EXECUTE 0x004 Allow execute
* HSE_URL_FLAGS_SSL 0x008 Require SSL
* HSE_URL_FLAGS_DONT_CACHE 0x010 Don't cache (VRoot only)
* HSE_URL_FLAGS_NEGO_CERT 0x020 Allow client SSL cert
* HSE_URL_FLAGS_REQUIRE_CERT 0x040 Require client SSL cert
* HSE_URL_FLAGS_MAP_CERT 0x080 Map client SSL cert to account
* HSE_URL_FLAGS_SSL128 0x100 Require 128-bit SSL cert
* HSE_URL_FLAGS_SCRIPT 0x200 Allow script execution
*
* XxX: As everywhere, EXEC flags could use some work...
* and this could go further with more flags, as desired.
*/
info->dwFlags = (subreq->finfo.protection & APR_UREAD ? 0x001 : 0)
| (subreq->finfo.protection & APR_UWRITE ? 0x002 : 0)
| (subreq->finfo.protection & APR_UEXECUTE ? 0x204 : 0);
return 1;
}
case HSE_REQ_ABORTIVE_CLOSE:
if (cid->dconf.log_unsupported)
ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r,
"ISAPI: ServerSupportFunction HSE_REQ_ABORTIVE_CLOSE"
" is not supported: %s", r->filename);
apr_set_os_error(APR_FROM_OS_ERROR(ERROR_INVALID_PARAMETER));
return 0;
case HSE_REQ_GET_CERT_INFO_EX: /* Added in ISAPI 4.0 */
if (cid->dconf.log_unsupported)
ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r,
"ISAPI: ServerSupportFunction "
"HSE_REQ_GET_CERT_INFO_EX "
"is not supported: %s", r->filename);
apr_set_os_error(APR_FROM_OS_ERROR(ERROR_INVALID_PARAMETER));
return 0;
case HSE_REQ_SEND_RESPONSE_HEADER_EX: /* Added in ISAPI 4.0 */
{
HSE_SEND_HEADER_EX_INFO *shi = (HSE_SEND_HEADER_EX_INFO*)buf_data;
/* Ignore shi->fKeepConn - we don't want the advise
*/
apr_ssize_t ate = send_response_header(cid, shi->pszStatus,
shi->pszHeader,
shi->cchStatus,
shi->cchHeader);
if (ate < 0) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -