📄 mod_isapi.c
字号:
case HSE_REQ_SEND_URL_REDIRECT_RESP: /* Set the status to be returned when the HttpExtensionProc() * is done. * WARNING: Microsoft now advertises HSE_REQ_SEND_URL_REDIRECT_RESP * and HSE_REQ_SEND_URL as equivalant per the Jan 2000 SDK. * They most definately are not, even in their own samples. */ apr_table_set (r->headers_out, "Location", buf_data); cid->r->status = cid->ecb->dwHttpStatusCode = HTTP_MOVED_TEMPORARILY; cid->r->status_line = ap_get_status_line(cid->r->status); cid->headers_set = 1; return 1; case HSE_REQ_SEND_URL: /* Soak up remaining input */ if (r->remaining > 0) { char argsbuffer[HUGE_STRING_LEN]; while (ap_get_client_block(r, argsbuffer, HUGE_STRING_LEN)); } /* Reset the method to GET */ r->method = apr_pstrdup(r->pool, "GET"); r->method_number = M_GET; /* Don't let anyone think there's still data */ apr_table_unset(r->headers_in, "Content-Length"); /* AV fault per PR3598 - redirected path is lost! */ (char*)buf_data = apr_pstrdup(r->pool, (char*)buf_data); ap_internal_redirect((char*)buf_data, r); return 1; case HSE_REQ_SEND_RESPONSE_HEADER: { /* Parse them out, or die trying */ apr_size_t statlen = 0, headlen = 0; apr_ssize_t ate; if (buf_data) statlen = strlen((char*) buf_data); if (data_type) headlen = strlen((char*) data_type); ate = send_response_header(cid, (char*) buf_data, (char*) data_type, statlen, headlen); if (ate < 0) { SetLastError(ERROR_INVALID_PARAMETER); return 0; } else if ((apr_size_t)ate < headlen) { apr_bucket_brigade *bb; apr_bucket *b; bb = apr_brigade_create(cid->r->pool, c->bucket_alloc); b = apr_bucket_transient_create((char*) data_type + ate, headlen - ate, c->bucket_alloc); APR_BRIGADE_INSERT_TAIL(bb, b); b = apr_bucket_flush_create(c->bucket_alloc); APR_BRIGADE_INSERT_TAIL(bb, b); ap_pass_brigade(cid->r->output_filters, bb); cid->response_sent = 1; } return 1; } case HSE_REQ_DONE_WITH_SESSION: /* Signal to resume the thread completing this request, * leave it to the pool cleanup to dispose of our mutex. */ if (cid->completed) { (void)apr_thread_mutex_unlock(cid->completed); return 1; } else if (cid->dconf.log_unsupported) { ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, "ISAPI: ServerSupportFunction " "HSE_REQ_DONE_WITH_SESSION is not supported: %s", r->filename); } SetLastError(ERROR_INVALID_PARAMETER); return 0; case HSE_REQ_MAP_URL_TO_PATH: { /* Map a URL to a filename */ char *file = (char *)buf_data; apr_uint32_t len; subreq = ap_sub_req_lookup_uri(apr_pstrndup(r->pool, file, *buf_size), r, NULL); len = apr_cpystrn(file, subreq->filename, *buf_size) - file; /* IIS puts a trailing slash on directories, Apache doesn't */ if (subreq->finfo.filetype == APR_DIR) { if (len < *buf_size - 1) { file[len++] = '\\'; file[len] = '\0'; } } *buf_size = len; 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); SetLastError(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); SetLastError(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_status_t rv; 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); SetLastError(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) { SetLastError(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); SetLastError(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;#if APR_HAS_LARGE_FILES if (r->finfo.size > AP_MAX_SENDFILE) { /* APR_HAS_LARGE_FILES issue; must split into mutiple buckets, * no greater than MAX(apr_size_t), and more granular than that * in case the brigade code/filters attempt to read it directly. */ b = apr_bucket_file_create(fd, tf->Offset, AP_MAX_SENDFILE, r->pool, c->bucket_alloc); while (fsize > AP_MAX_SENDFILE) { apr_bucket *bc; apr_bucket_copy(b, &bc); APR_BRIGADE_INSERT_TAIL(bb, bc); b->start += AP_MAX_SENDFILE; fsize -= AP_MAX_SENDFILE; } b->length = (apr_size_t)fsize; /* Resize just the last bucket */ } else#endif b = apr_bucket_file_create(fd, tf->Offset, (apr_size_t)fsize, r->pool, c->bucket_alloc); APR_BRIGADE_INSERT_TAIL(bb, b); 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); ap_pass_brigade(r->output_filters, bb); cid->response_sent = 1; /* 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 == OK) { 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 == OK) { cid->completion(cid->ecb, cid->completion_arg, sent, ERROR_SUCCESS); } else { cid->completion(cid->ecb, cid->completion_arg, sent, ERROR_WRITE_FAULT); } } } return (rv == OK); } 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); SetLastError(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); SetLastError(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) { 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); SetLastError(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)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -