/* Licensed to the Apache Software Foundation (ASF) under one or more *contributorlicenseagreements.SeetheNOTICEfiledistributedwith *thisworkforadditionalinformationregardingcopyrightownership. *TheASFlicensesthisfiletoYouundertheApacheLicense,Version2.0 *(the"License");youmaynotusethisfileexceptincompliancewith *theLicense.YoumayobtainacopyoftheLicenseat * *http://www.apache.org/licenses/LICENSE-2.0 * *Unlessrequiredbyapplicablelaworagreedtoinwriting,software *distributedundertheLicenseisdistributedonan"ASIS"BASIS, *WITHOUTWARRANTIESORCONDITIONSOFANYKIND,eitherexpressorimplied. *SeetheLicenseforthespecificlanguagegoverningpermissionsand *limitationsundertheLicense.
*/
/* Our isapi per-dir config structure */ typedefstruct isapi_dir_conf { int read_ahead_buflen; int log_unsupported; int log_to_errlog; int log_to_query; int fake_async;
} isapi_dir_conf;
/* ### Just an observation ... it would be terribly cool to be *abletousethisper-dir,relativetothedirectoryblockbeing *defined.Thehashresultremainsglobal,butshorthandof *<Directory"c:/webapps/isapi"> *ISAPICacheFilemyapp.dllanotherapp.dllthirdapp.dll *</Directory> *wouldbeveryconvienent.
*/
fspec = ap_server_root_relative(cmd->pool, filename); if (!fspec) {
ap_log_error(APLOG_MARK, APLOG_WARNING, APR_EBADPATH, cmd->server, APLOGNO(02103) "invalid module path, skipping %s", filename); return NULL;
} if ((rv = apr_stat(&tmp, fspec, APR_FINFO_TYPE,
cmd->temp_pool)) != APR_SUCCESS) {
ap_log_error(APLOG_MARK, APLOG_WARNING, rv, cmd->server, APLOGNO(02104) "unable to stat, skipping %s", fspec); return NULL;
} if (tmp.filetype != APR_REG) {
ap_log_error(APLOG_MARK, APLOG_WARNING, 0, cmd->server, APLOGNO(02105) "not a regular file, skipping %s", fspec); return NULL;
}
/* Load the extension as cached (with null request_rec) */
rv = isapi_lookup(cmd->pool, cmd->server, NULL, fspec, &isa); if (rv != APR_SUCCESS) {
ap_log_error(APLOG_MARK, APLOG_WARNING, rv, cmd->server, APLOGNO(02106) "unable to cache, skipping %s", fspec); return NULL;
}
return NULL;
}
staticconst command_rec isapi_cmds[] = {
AP_INIT_TAKE1("ISAPIReadAheadBuffer", ap_set_int_slot,
(void *)APR_OFFSETOF(isapi_dir_conf, read_ahead_buflen),
OR_FILEINFO, "Maximum client request body to initially pass to the" " ISAPI handler (default: 49152)"),
AP_INIT_FLAG("ISAPILogNotSupported", ap_set_flag_slot,
(void *)APR_OFFSETOF(isapi_dir_conf, log_unsupported),
OR_FILEINFO, "Log requests not supported by the ISAPI server" " on or off (default: off)"),
AP_INIT_FLAG("ISAPIAppendLogToErrors", ap_set_flag_slot,
(void *)APR_OFFSETOF(isapi_dir_conf, log_to_errlog),
OR_FILEINFO, "Send all Append Log requests to the error log" " on or off (default: off)"),
AP_INIT_FLAG("ISAPIAppendLogToQuery", ap_set_flag_slot,
(void *)APR_OFFSETOF(isapi_dir_conf, log_to_query),
OR_FILEINFO, "Append Log requests are concatenated to the query args" " on or off (default: on)"),
AP_INIT_FLAG("ISAPIFakeAsync", ap_set_flag_slot,
(void *)APR_OFFSETOF(isapi_dir_conf, fake_async),
OR_FILEINFO, "Fake Asynchronous support for isapi callbacks" " on or off [Experimental] (default: off)"),
AP_INIT_ITERATE("ISAPICacheFile", isapi_cmd_cachefile, NULL,
RSRC_CONF, "Cache the specified ISAPI extension in-process"),
{NULL}
};
/* TODO: These aught to become overridable, so that we *assureagivenisapicanbefooledintobehavingwell. * *Thetrickybit,theyaren'treallyaper-dirsortof *config,theywillalwaysbeconstantacrossevery *referencetothe.dllnomatterwhatcontext(vhost, *location,etc)theyapplyto.
*/
isa->report_version = 0x500; /* Revision 5.0 */
isa->timeout = 300 * 1000000; /* microsecs, not used */
/* If we find this lock exists, use a set-aside copy of gainlock *toavoidraceconditionsonNULLingthein_progressvariable *whentheloadhascompleted.Releasetheglobalisapihash *locksootherrequestscanproceed,thenrdlockforcompletion *ofloadingourdesireddllorwrlockifwewouldliketoretry *loadingthedll(becauselast_load_rvfailedandretryisup.)
*/
apr_thread_rwlock_t *gainlock = (*isa)->in_progress;
/* gainlock is NULLed after the module loads successfully. *Thisfree-threadedmodulecanbeusedwithoutanylocking.
*/ if (!gainlock) {
rv = (*isa)->last_load_rv;
apr_thread_mutex_unlock(loaded.lock); return rv;
}
if (apr_time_now() > (*isa)->last_load_time + ISAPI_RETRY) {
/* Remember last_load_time before releasing the global *hashlocktoavoidcollidingwithanotherthread *thathitthisexceptionatthesametimeasour *retryattempt,sinceweunlocktheglobalmutex *beforeattemptingawritelockforthismodule.
*/
apr_time_t check_time = (*isa)->last_load_time;
apr_thread_mutex_unlock(loaded.lock);
if ((rv = apr_thread_rwlock_wrlock(gainlock))
!= APR_SUCCESS) { return rv;
}
/* If last_load_time is unchanged, we still own this *retry,otherwisepresumeanotherthreadprovided *ourretry(forgoodorill).Relocktheglobal *hashforupdatinglast_load_vars,sotheirupdate *isalwaysatomictothegloballock.
*/ if (check_time == (*isa)->last_load_time) {
/* We haven't hit timeup on retry, let's grab the last_rv *withinthehashmutexbeforeunlocking.
*/
rv = (*isa)->last_load_rv;
apr_thread_mutex_unlock(loaded.lock);
return rv;
}
/* If the module was not found, it's time to create a hash key entry *beforereleasingthehashlocktoavoidmultiplethreadsfrom *loadingthesamemodule.
*/
key = apr_pstrdup(loaded.pool, fpath);
*isa = apr_pcalloc(loaded.pool, sizeof(isapi_loaded));
(*isa)->filename = key; if (r) { /* A mutex that exists only long enough to attempt to *loadthisisapidll,thereleasethismoduletoall *othertakersthatcamealongduringtheone-time *loadprocess.Shortlifetimeforthislockwould *begreat,however,usingr->poolisnastyifthose *blockedonthelockhaven'tallunlockedbeforewe *attempttodestroy.Anastierraceconditionthan *Iwanttodealwithatthismoment...
*/
apr_thread_rwlock_create(&(*isa)->in_progress, loaded.pool);
apr_thread_rwlock_wrlock((*isa)->in_progress);
}
if (r && (rv == APR_SUCCESS)) { /* Let others who are blocked on this particular *moduleresumetheirrequests,forbetterorworse.
*/
apr_thread_rwlock_t *unlock = (*isa)->in_progress;
(*isa)->in_progress = NULL;
apr_thread_rwlock_unlock(unlock);
} elseif (!r && (rv != APR_SUCCESS)) { /* We must leave a rwlock around for requests to retry *loadingthisdllaftertimeup...sincewewerein *thesetupcodewehadavoidedcreatingthislock.
*/
apr_thread_rwlock_create(&(*isa)->in_progress, loaded.pool);
}
/* Not a special case */
result = apr_table_get(r->subprocess_env, variable_name);
if (result) {
len = strlen(result); if (*buf_size < len + 1) {
*buf_size = len + 1;
apr_set_os_error(APR_FROM_OS_ERROR(ERROR_INSUFFICIENT_BUFFER)); return0;
}
strcpy(buf_data, result);
*buf_size = len + 1; return1;
}
/* Not Found */
apr_set_os_error(APR_FROM_OS_ERROR(ERROR_INVALID_INDEX)); return0;
}
/* Common code invoked for both HSE_REQ_SEND_RESPONSE_HEADER and *thenewerHSE_REQ_SEND_RESPONSE_HEADER_EXServerSupportFunction(s) *aswellasotherfunctionsthatwriteresponsesandpresumethat *thesupportfunctionsaboveareoptional. * *Othercallerstryingtosplitheadersandbodybytesshouldpass *head/headlenalone(leavingstat/statlenNULL/0),sothatthey *getapropercountofbytesconsumed.Theargumentpassedtostat *isn'tcountedastheheadbytesare.
*/ static apr_ssize_t send_response_header(isapi_cid *cid, constchar *stat, constchar *head,
apr_size_t statlen,
apr_size_t headlen)
{ int head_present = 1; int termarg; int res; int old_status; constchar *termch;
apr_size_t ate = 0;
if (!head || headlen == 0 || !*head) {
head = stat;
stat = NULL;
headlen = statlen;
statlen = 0;
head_present = 0; /* Don't eat the header */
}
if (!stat || statlen == 0 || !*stat) { if (head && headlen && *head && ((stat = memchr(head, '\r', headlen))
|| (stat = memchr(head, '\n', headlen))
|| (stat = memchr(head, '\0', headlen))
|| (stat = head + headlen))) {
statlen = stat - head; if (memchr(head, ':', statlen)) {
stat = "Status: 200 OK";
statlen = strlen(stat);
} else { constchar *flip = head;
head = stat;
stat = flip;
headlen -= statlen;
ate += statlen; if (*head == '\r' && headlen)
++head, --headlen, ++ate; if (*head == '\n' && headlen)
++head, --headlen, ++ate;
}
}
}
if (stat && (statlen > 0) && *stat) { char *newstat; if (!apr_isdigit(*stat)) { constchar *stattok = stat; int toklen = statlen; while (toklen && *stattok && !apr_isspace(*stattok)) {
++stattok; --toklen;
} while (toklen && apr_isspace(*stattok)) {
++stattok; --toklen;
} /* Now decide if we follow the xxx message *orthehttp/x.xxxxmessageformat
*/ if (toklen && apr_isdigit(*stattok)) {
statlen = toklen;
stat = stattok;
}
}
newstat = apr_palloc(cid->r->pool, statlen + 9);
strcpy(newstat, "Status: ");
apr_cpystrn(newstat + 8, stat, statlen + 1);
stat = newstat;
statlen += 8;
}
if (!head || headlen == 0 || !*head) {
head = "\r\n";
headlen = 2;
} else
{ if (head[headlen - 1] && head[headlen]) { /* Whoops... not NULL terminated */
head = apr_pstrndup(cid->r->pool, head, headlen);
}
}
/* Seems IIS does not enforce the requirement for \r\n termination *onHSE_REQ_SEND_RESPONSE_HEADER,butwewon'tpanic... *ap_scan_script_header_err_strshandlesthisaspectforus. * *Parsethemout,ordietrying
*/
old_status = cid->r->status;
if (stat) {
res = ap_scan_script_header_err_strs_ex(cid->r, NULL,
APLOG_MODULE_INDEX, &termch, &termarg, stat, head, NULL);
} else {
res = ap_scan_script_header_err_strs_ex(cid->r, NULL,
APLOG_MODULE_INDEX, &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;
} elseif (cid->r->status) { /* We have a status in r->status, so let's just use it. *ThisislikelytobetheStatus:parsedabove,and *mayalsobeadelayederrorresultfromtheparser. *Ifitwasfilledin,status_lineshouldalsohave *beenfilledin.
*/
cid->ecb->dwHttpStatusCode = cid->r->status;
} elseif (cid->ecb->dwHttpStatusCode
&& cid->ecb->dwHttpStatusCode != HTTP_OK) { /* Now we fall back on dwHttpStatusCode if it appears *ap_scan_script_headerfellbackonthedefaultcode. *AnyotherresultssetdwHttpStatusCodetothedecoded *statusvalue.
*/
cid->r->status = cid->ecb->dwHttpStatusCode;
cid->r->status_line = ap_get_status_line(cid->r->status);
} elseif (old_status) { /* Well... either there is no dwHttpStatusCode or it's HTTP_OK. *Inanycase,wedon'thaveagoodstatustoreturnyet... *Perhapstheonewecameinwithwillbebetter.Let'suseit, *ifweweregivenone(notethisisapedanticcase,itwould *normallybecoveredaboveunlessthescanscriptcodeunset *ther->status).Shouldtherebeacheckhereastowhether *wearesettingavalidresponsecode?
*/
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 *oldvalueofr->statuswerehelpful,andnothingwasdecoded *fromStatus:stringpassedtous.Let'sjustsayHTTP_OK *andgetthedataout,thiswastheisapidev'soversight.
*/
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, APLOGNO(02111) "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) return0;
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 *givebackisthesizeoftheheadersweconsumed(whichonly *happensiftheparsergottotheheadarg,whichvariesbased *onwhetherwepassedstat+headtoscan,oronlyhead.
*/ if (termch && (termarg == (stat ? 1 : 0))
&& head_present && head + headlen > termch) { return ate + termch - head;
} return ate;
}
if (!cid->headers_set) { /* It appears that the foxisapi module and other clients *presumethatWriteClient("headers\n\nbody")willwork. *Parsethemout,ordietrying.
*/
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)); return0;
}
switch (HSE_code) { case HSE_REQ_SEND_URL_REDIRECT_RESP: /* Set the status to be returned when the HttpExtensionProc() *isdone. *WARNING:MicrosoftnowadvertisesHSE_REQ_SEND_URL_REDIRECT_RESP *andHSE_REQ_SEND_URLasequivalentpertheJan2000SDK. *Theymostdefinitelyarenot,evenintheirownsamples.
*/
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; return1;
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 = "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); return1;
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)); return0;
} elseif ((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, APLOGNO(03177) "ServerSupportFunction " "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 *accumulatethebodyandspeeduptheoverallresponse,orat *leastwaitfortheendthesession.
*/ return1;
}
case HSE_REQ_DONE_WITH_SESSION: /* Signal to resume the thread completing this request, *leaveittothepoolcleanuptodisposeofourmutex.
*/ if (cid->completed) {
(void)apr_thread_mutex_unlock(cid->completed); return1;
} elseif (cid->dconf.log_unsupported) {
ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, APLOGNO(02671) "ServerSupportFunction " "HSE_REQ_DONE_WITH_SESSION is not supported: %s",
r->filename);
}
apr_set_os_error(APR_FROM_OS_ERROR(ERROR_INVALID_PARAMETER)); return0;
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); return0;
}
/* Use tf->pfnHseIO + tf->pContext, or if NULL, then use cid->fnIOComplete *passpContecttotheHseIOcallback.
*/ 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);
}
} elseif (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, APLOGNO(02675) "ServerSupportFunction " "HSE_REQ_REFRESH_ISAPI_ACL " "is not supported: %s", r->filename);
apr_set_os_error(APR_FROM_OS_ERROR(ERROR_INVALID_PARAMETER)); return0;
case HSE_REQ_IS_KEEP_CONN:
*((int *)buf_data) = (r->connection->keepalive == AP_CONN_KEEPALIVE); return1;
case HSE_REQ_ASYNC_READ_CLIENT:
{
apr_uint32_t read = 0; int res = 0; if (!cid->dconf.fake_async) { if (cid->dconf.log_unsupported)
ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, APLOGNO(02986) "asynchronous I/O not supported: %s",
r->filename);
apr_set_os_error(APR_FROM_OS_ERROR(ERROR_INVALID_PARAMETER)); return0;
}
if (r->remaining < *buf_size) {
*buf_size = (apr_size_t)r->remaining;
}
/* Mapping started with assuming both strings matched. *Nowrollonthepath_infoasamismatchandhandle *terminatingslashesfordirectorymatches.
*/ 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;
}
} elseif (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 = '\\';
case HSE_REQ_ABORTIVE_CLOSE: if (cid->dconf.log_unsupported)
ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, APLOGNO(02677) "ServerSupportFunction HSE_REQ_ABORTIVE_CLOSE" " is not supported: %s", r->filename);
apr_set_os_error(APR_FROM_OS_ERROR(ERROR_INVALID_PARAMETER)); return0;
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, APLOGNO(02678) "ServerSupportFunction " "HSE_REQ_GET_CERT_INFO_EX " "is not supported: %s", r->filename);
apr_set_os_error(APR_FROM_OS_ERROR(ERROR_INVALID_PARAMETER)); return0;
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) {
apr_set_os_error(APR_FROM_OS_ERROR(ERROR_INVALID_PARAMETER)); return0;
} elseif ((apr_size_t)ate < shi->cchHeader) {
apr_bucket_brigade *bb;
apr_bucket *b;
bb = apr_brigade_create(cid->r->pool, c->bucket_alloc);
b = apr_bucket_transient_create(shi->pszHeader + ate,
shi->cchHeader - 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, APLOGNO(03179) "ServerSupportFunction " "HSE_REQ_SEND_RESPONSE_HEADER_EX " "ap_pass_brigade failed: %s", r->filename); return (rv == APR_SUCCESS);
} /* Deliberately hold off sending 'just the headers' to begin to *accumulatethebodyandspeeduptheoverallresponse,orat *leastwaitfortheendthesession.
*/ return1;
}
case HSE_REQ_CLOSE_CONNECTION: /* Added after ISAPI 4.0 */ if (cid->dconf.log_unsupported)
ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, APLOGNO(02679) "ServerSupportFunction " "HSE_REQ_CLOSE_CONNECTION " "is not supported: %s", r->filename);
apr_set_os_error(APR_FROM_OS_ERROR(ERROR_INVALID_PARAMETER)); return0;
case HSE_REQ_IS_CONNECTED: /* Added after ISAPI 4.0 */ /* Returns True if client is connected c.f. MSKB Q188346 *assumingtheidenticalreturnmechanismasHSE_REQ_IS_KEEP_CONN
*/
*((int *)buf_data) = (r->connection->aborted == 0); return1;
case HSE_REQ_EXTENSION_TRIGGER: /* Added after ISAPI 4.0 */ /* Undocumented - defined by the Microsoft Jan '00 Platform SDK
*/ if (cid->dconf.log_unsupported)
ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, APLOGNO(02680) "ServerSupportFunction " "HSE_REQ_EXTENSION_TRIGGER " "is not supported: %s", r->filename);
apr_set_os_error(APR_FROM_OS_ERROR(ERROR_INVALID_PARAMETER)); return0;
default: if (cid->dconf.log_unsupported)
ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, APLOGNO(02681) "ServerSupportFunction (%d) not supported: " "%s", HSE_code, r->filename);
apr_set_os_error(APR_FROM_OS_ERROR(ERROR_INVALID_PARAMETER)); return0;
}
}
if (strcmp(r->handler, "isapi-isa")
&& strcmp(r->handler, "isapi-handler")) { /* Hang on to the isapi-isa for compatibility with older docs *(wtfdid'-isa'meaninthefirstplace?)butintroduce *anewerandclearer"isapi-handler"name.
*/ return DECLINED;
}
dconf = ap_get_module_config(r->per_dir_config, &isapi_module);
e = r->subprocess_env;
/* Use similar restrictions as CGIs * *Ifthisfails,it'spointlesstoloadtheisapidll.
*/ if (!(ap_allow_options(r) & OPT_EXECCGI)) { return HTTP_FORBIDDEN;
} if (r->finfo.filetype == APR_NOFILE) { return HTTP_NOT_FOUND;
} if (r->finfo.filetype != APR_REG) { return HTTP_FORBIDDEN;
} if ((r->used_path_info == AP_REQ_REJECT_PATH_INFO) &&
r->path_info && *r->path_info) { /* default to accept */ return HTTP_NOT_FOUND;
}
/* All right... try and run the sucker */
rv = (*isa->HttpExtensionProc)(cid->ecb);
/* Check for a log message - and log it */ if (*cid->ecb->lpszLogData) {
ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, APLOGNO(02113) "%s: %s", r->filename, cid->ecb->lpszLogData);
}
switch(rv) { case0: /* Strange, but MS isapi accepts this as success */ case HSE_STATUS_SUCCESS: case HSE_STATUS_SUCCESS_AND_KEEP_CONN: /* Ignore the keepalive stuff; Apache handles it just fine without *theISAPIHandler's"advice". *PerMicrosoft:"InIISversions4.0andlater,thereturn *valuesHSE_STATUS_SUCCESSandHSE_STATUS_SUCCESS_AND_KEEP_CONN *arefunctionallyidentical:Keep-Aliveconnectionsare *maintained,ifsupportedbytheclient." *...sowewerepatallthistime
*/ break;
case HSE_STATUS_PENDING: /* emulating async behavior...
*/ if (cid->completed) { /* The completion port was locked prior to invoking *HttpExtensionProc().Oncewecanregainthelock, *whenServerSupportFunction(HSE_REQ_DONE_WITH_SESSION) *iscalledbytheextensiontoreleasethelock, *wemayfinallydestroytherequest.
*/
(void)apr_thread_mutex_lock(cid->completed); break;
} elseif (cid->dconf.log_unsupported) {
ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, APLOGNO(02114) "asynch I/O result HSE_STATUS_PENDING " "from HttpExtensionProc() is not supported: %s",
r->filename);
r->status = HTTP_INTERNAL_SERVER_ERROR;
} break;
case HSE_STATUS_ERROR: /* end response if we have yet to do so.
*/
ap_log_rerror(APLOG_MARK, APLOG_WARNING, apr_get_os_error(), r, APLOGNO(02115) "HSE_STATUS_ERROR result from " "HttpExtensionProc(): %s", r->filename);
r->status = HTTP_INTERNAL_SERVER_ERROR; break;
if (rv != APR_SUCCESS) {
ap_log_rerror(APLOG_MARK, APLOG_DEBUG, rv, r, APLOGNO(02117) "ap_pass_brigade failed to " "complete the response: %s ", r->filename);
}
return OK; /* NOT r->status, even if it has changed. */
}
/* As the client returned no error, and if we did not error out *ourselves,trustdwHttpStatusCodetosaysomethingrelevant.
*/ if (!ap_is_HTTP_SERVER_ERROR(r->status) && cid->ecb->dwHttpStatusCode) {
r->status = cid->ecb->dwHttpStatusCode;
}
/* For all missing-response situations simply return the status, *andletthecorerespondtotheclient.
*/ return r->status;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.