📄 mod_isapi.c
字号:
/* Seems IIS does not enforce the requirement for \r\n termination * on HSE_REQ_SEND_RESPONSE_HEADER, but we won't panic... * ap_scan_script_header_err_strs handles this aspect for us. * * Parse them out, or die trying */ old_status = cid->r->status; if (stat) { res = ap_scan_script_header_err_strs(cid->r, NULL, &termch, &termarg, stat, head, NULL); } else { res = ap_scan_script_header_err_strs(cid->r, NULL, &termch, &termarg, head, NULL); } /* Set our status. */ if (res) { /* This is an immediate error result from the parser */ cid->r->status = res; cid->r->status_line = ap_get_status_line(cid->r->status); cid->ecb->dwHttpStatusCode = cid->r->status; } else if (cid->r->status) { /* We have a status in r->status, so let's just use it. * This is likely to be the Status: parsed above, and * may also be a delayed error result from the parser. * If it was filled in, status_line should also have * been filled in. */ cid->ecb->dwHttpStatusCode = cid->r->status; } else if (cid->ecb->dwHttpStatusCode && cid->ecb->dwHttpStatusCode != HTTP_OK) { /* Now we fall back on dwHttpStatusCode if it appears * ap_scan_script_header fell back on the default code. * Any other results set dwHttpStatusCode to the decoded * status value. */ cid->r->status = cid->ecb->dwHttpStatusCode; cid->r->status_line = ap_get_status_line(cid->r->status); } else if (old_status) { /* Well... either there is no dwHttpStatusCode or it's HTTP_OK. * In any case, we don't have a good status to return yet... * Perhaps the one we came in with will be better. Let's use it, * if we were given one (note this is a pendantic case, it would * normally be covered above unless the scan script code unset * the r->status). Should there be a check here as to whether * we are setting a valid response code? */ cid->r->status = old_status; cid->r->status_line = ap_get_status_line(cid->r->status); cid->ecb->dwHttpStatusCode = cid->r->status; } else { /* None of dwHttpStatusCode, the parser's r->status nor the * old value of r->status were helpful, and nothing was decoded * from Status: string passed to us. Let's just say HTTP_OK * and get the data out, this was the isapi dev's oversight. */ cid->r->status = HTTP_OK; cid->r->status_line = ap_get_status_line(cid->r->status); cid->ecb->dwHttpStatusCode = cid->r->status; ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, cid->r, "ISAPI: Could not determine HTTP response code; using %d", cid->r->status); } if (cid->r->status == HTTP_INTERNAL_SERVER_ERROR) { return -1; } /* If only Status was passed, we consumed nothing */ if (!head_present) return 0; cid->headers_set = 1; /* If all went well, tell the caller we consumed the headers complete */ if (!termch) return(ate + headlen); /* Any data left must be sent directly by the caller, all we * give back is the size of the headers we consumed (which only * happens if the parser got to the head arg, which varies based * on whether we passed stat+head to scan, or only head. */ if (termch && (termarg == (stat ? 1 : 0)) && head_present && head + headlen > termch) { return ate + termch - head; } return ate;}int APR_THREAD_FUNC WriteClient(isapi_cid *cid, void *buf_ptr, apr_uint32_t *size_arg, apr_uint32_t flags){ request_rec *r = cid->r; conn_rec *c = r->connection; apr_uint32_t buf_size = *size_arg; char *buf_data = (char*)buf_ptr; apr_bucket_brigade *bb; apr_bucket *b; apr_status_t rv = APR_SUCCESS; if (!cid->headers_set) { /* It appears that the foxisapi module and other clients * presume that WriteClient("headers\n\nbody") will work. * Parse them out, or die trying. */ apr_ssize_t ate; ate = send_response_header(cid, NULL, buf_data, 0, buf_size); if (ate < 0) { apr_set_os_error(APR_FROM_OS_ERROR(ERROR_INVALID_PARAMETER)); return 0; } buf_data += ate; buf_size -= ate; } if (buf_size) { bb = apr_brigade_create(r->pool, c->bucket_alloc); b = apr_bucket_transient_create(buf_data, buf_size, 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: WriteClient ap_pass_brigade " "failed: %s", r->filename); } if ((flags & HSE_IO_ASYNC) && cid->completion) { if (rv == APR_SUCCESS) { cid->completion(cid->ecb, cid->completion_arg, *size_arg, ERROR_SUCCESS); } else { cid->completion(cid->ecb, cid->completion_arg, *size_arg, ERROR_WRITE_FAULT); } } return (rv == APR_SUCCESS);}/* A "safe" maximum bucket size, 1Gb */#define MAX_BUCKET_SIZE (0x40000000)apr_bucket *brigade_insert_file(apr_bucket_brigade *bb, apr_file_t *f, apr_off_t start, apr_off_t length, apr_pool_t *p){ apr_bucket *e; if (sizeof(apr_off_t) == sizeof(apr_size_t) || length < MAX_BUCKET_SIZE) { e = apr_bucket_file_create(f, start, (apr_size_t)length, p, bb->bucket_alloc); } else { /* Several buckets are needed. */ e = apr_bucket_file_create(f, start, MAX_BUCKET_SIZE, p, bb->bucket_alloc); while (length > MAX_BUCKET_SIZE) { apr_bucket *ce; apr_bucket_copy(e, &ce); APR_BRIGADE_INSERT_TAIL(bb, ce); e->start += MAX_BUCKET_SIZE; length -= MAX_BUCKET_SIZE; } e->length = (apr_size_t)length; /* Resize just the last bucket */ } APR_BRIGADE_INSERT_TAIL(bb, e); return e;}int APR_THREAD_FUNC ServerSupportFunction(isapi_cid *cid, apr_uint32_t HSE_code, void *buf_ptr, apr_uint32_t *buf_size, apr_uint32_t *data_type){ request_rec *r = cid->r; conn_rec *c = r->connection; char *buf_data = (char*)buf_ptr; request_rec *subreq; apr_status_t rv; switch (HSE_code) { 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! */ buf_data = apr_pstrdup(r->pool, (char*)buf_data); ap_internal_redirect(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) { apr_set_os_error(APR_FROM_OS_ERROR(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); rv = ap_pass_brigade(cid->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_SEND_RESPONSE_HEADER " "ap_pass_brigade failed: %s", r->filename); return (rv == APR_SUCCESS); } /* Deliberately hold off sending 'just the headers' to begin to * accumulate the body and speed up the overall response, or at * least wait for the end the session. */ 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); } apr_set_os_error(APR_FROM_OS_ERROR(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(cid->r->pool, file, *buf_size), r, NULL); if (!subreq->filename) { ap_destroy_sub_req(subreq); return 0; } len = (apr_uint32_t)strlen(r->filename); if ((subreq->finfo.filetype == APR_DIR) && (!subreq->path_info) && (file[len - 1] != '/')) file = apr_pstrcat(cid->r->pool, subreq->filename, "/", NULL); else file = apr_pstrcat(cid->r->pool, subreq->filename, subreq->path_info, NULL); ap_destroy_sub_req(subreq);#ifdef WIN32 /* We need to make this a real Windows path name */ 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:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -