static int do_print( void *_c, const char *buf, int len ) { mcontext *c = (mcontext*)_c; ap_soft_timeout("Client Timeout",c->r); send_headers(c); ap_rwrite(buf,len,c->r); ap_kill_timeout(c->r); return c->r->connection->aborted == 0; }
static void request_print( const char *data, int size, void *_c ) { mcontext *c = (mcontext *)_c; if( c == NULL ) c = CONTEXT(); if( size == -1 ) size = (int)strlen(data); ap_soft_timeout("Client Timeout",c->r); send_headers(c); ap_rwrite(data,size,c->r); ap_kill_timeout(c->r); }
static int handle_request(request_rec *r) { tmcdreq_t tmcdreq, *reqp = &tmcdreq; tmcdresp_t *response = NULL; char *command; struct in_addr local_addr; struct in_addr remote_addr; struct sockaddr_in redir_client; int tmcd_status; int status = OK; char *status_line = NULL; char *args = NULL; char *function_args = NULL; char *p; char **argv = NULL; int argc, i; reqp->istcp = 1; reqp->isssl = 1; /* FIXME */ if (strcmp(r->handler, "tmcd")) { status = DECLINED; goto err; } #if 0 r->allowed |= (AP_METHOD_BIT << M_GET); if (r->method_number != M_GET) { status = DECLINED; goto err; } #endif memset(reqp, 0, sizeof(*reqp)); local_addr = r->connection->local_addr.sin_addr; remote_addr = r->connection->remote_addr.sin_addr; reqp->version = 1; /* FIXME need sane default */ tmcd_init(reqp, &local_addr, NULL); command = r->path_info; while (*command && *command == '/') { command++; } if (command[0] == '\0') { status = HTTP_BAD_REQUEST; goto err; } if (r->args) { args = malloc(strlen(r->args) + 1); if (args == NULL) { status = HTTP_INTERNAL_SERVER_ERROR; goto err; } strcpy(args, r->args); argv = make_argv(args, &argc, '&'); if (argv == NULL) { status = HTTP_INTERNAL_SERVER_ERROR; goto err; } for (i = 0; i < argc; i++) { /* Unescape the arguments */ p = args; while (*p) { if (*p == '+') *p = ' '; p++; } status = ap_unescape_url(args); if (status != OK) { goto err; } if (strncasecmp(argv[i], "version=", 8) == 0) { long version; char *end; version = strtol(argv[i] + 8, &end, 10); if (*end != '\0' || *(argv[i] + 8) == '\0') { status = HTTP_BAD_REQUEST; status_line = "Invalid Version"; goto err; } reqp->version = version; } else if (strncasecmp(argv[i], "redirect=", 9) == 0) { if (inet_pton(AF_INET, argv[i] + 9, &redir_client.sin_addr) <= 0) { status = HTTP_BAD_REQUEST; status_line = "Invalid IP Address"; goto err; } /* FIXME info message */ if (remote_addr.s_addr != local_addr.s_addr) { status = HTTP_FORBIDDEN; status_line = "Redirection Not Allowed"; goto err; } remote_addr = redir_client.sin_addr; } else if (strncasecmp(argv[i], "vnodeid=", 8) == 0) { if (strlen(argv[i] + 8) >= sizeof(reqp->vnodeid)) { status = HTTP_BAD_REQUEST; status_line = "Virtual Node ID Too Long"; goto err; } reqp->isvnode = 1; strcpy(reqp->vnodeid, argv[i] + 8); } else if (strncasecmp(argv[i], "args=", 5) == 0) { function_args = argv[i] + 5; } } } /* FIXME handle wanodekey */ if ((tmcd_status = iptonodeid(reqp, remote_addr, NULL))) { if (reqp->isvnode) { status_line = "Invalid Virtual Node"; } else { status_line = "Invalid Node"; } status = HTTP_NOT_FOUND; goto err; } if (reqp->tmcd_redirect[0]) { /* FIXME what if https should be used? */ /* FIXME do I need to specify the args should be passed too? */ char *uri = ap_psprintf(r->pool, "http://%s%s?%s", reqp->tmcd_redirect, r->uri, r->args); ap_table_setn(r->headers_out, "Location", uri); status = HTTP_MOVED_TEMPORARILY; goto done; } tmcd_status = tmcd_handle_request(reqp, &response, command, function_args); if (tmcd_status == TMCD_STATUS_OK) { r->content_type = response->type; ap_set_content_length(r, response->length); /* FIXME doctype */ ap_soft_timeout("tmcd response call trace", r); ap_send_http_header(r); ap_rprintf(r, "%s", response->data); ap_kill_timeout(r); status = OK; goto done; } else { switch(tmcd_status) { case TMCD_STATUS_UNKNOWN_COMMAND: status = HTTP_NOT_FOUND; status_line = "Unknown Command"; break; case TMCD_STATUS_REQUIRES_ENCRYPTION: status = HTTP_FORBIDDEN; status_line = "SSL Required"; break; case TMCD_STATUS_NODE_NOT_ALLOCATED: status = HTTP_FORBIDDEN; status_line = "Node Not Allocated"; break; case TMCD_STATUS_COMMAND_FAILED: status = HTTP_INTERNAL_SERVER_ERROR; if (response && response->data) { status_line = response->data; } break; case TMCD_STATUS_MALLOC_FAILED: status = HTTP_INTERNAL_SERVER_ERROR; break; } goto err; } err: done: if (argv) free(argv); if (args) free(args); if (response) tmcd_free_response(response); if (status_line) { r->status_line = ap_psprintf(r->pool, "%3.3u %s", status, status_line); } return status; }
/* * ic_transfer_response() * ---------------------- * Read the response from the Interchange server * and relay it to the client */ static int ic_transfer_response(request_rec *r,BUFF *ic_buff) { const char *location; int rc,ic_sock; char sbuf[MAX_STRING_LEN],argsbuffer[MAX_STRING_LEN]; /* * get the socket we are using to talk to the * Interchange server, and wait for Interchange to * send us some data */ ic_sock = ap_bfileno(ic_buff,B_RD); rc = ic_select(ic_sock,0,IC_DEFAULT_TIMEOUT,0); if (rc < 0){ ap_log_reason("Failed to select the response header",r->uri,r); return HTTP_INTERNAL_SERVER_ERROR; } /* * check the HTTP header to make sure that it looks valid */ if ((rc = ap_scan_script_header_err_buff(r,ic_buff,sbuf)) != OK) { if (rc == HTTP_INTERNAL_SERVER_ERROR) { ap_log_rerror(APLOG_MARK,APLOG_ERR|APLOG_NOERRNO,r,"Malformed header return by Interchange: %s",sbuf); } return rc; } /* * check the header for an HTTP redirect request */ location = ap_table_get(r->headers_out,"Location"); if (r->status == 200 && location){ fd_set sock_set; /* * check if we need to do an external redirect */ if (*location != '/') return REDIRECT; /* * we are here because we need to do an internal redirect * * soak up any data from the Interchange socket */ rc = ic_select(ic_sock,0,IC_DEFAULT_TIMEOUT,0); if (rc < 0){ ap_log_reason("Failed to select the response text",r->uri,r); return HTTP_INTERNAL_SERVER_ERROR; } /* * soak up any body-text sent by the Interchange server */ ap_soft_timeout("mod_interchange: Interchange read",r); while (ap_bgets(argsbuffer,MAX_STRING_LEN,ic_buff) > 0) ; ap_kill_timeout(r); /* * always use the GET method for internal redirects * also, unset the Content-Length so that nothing * else tries to re-read the text we just soaked up */ r->method = ap_pstrdup(r->pool,"GET"); r->method_number = M_GET; ap_table_unset(r->headers_in,"Content-Length"); ap_internal_redirect(location,r); return OK; } /* * we were not redirected, so send the HTTP headers * to the client */ ap_hard_timeout("mod_interchange: Client write",r); ap_send_http_header(r); if (ap_rflush(r) < 0){ ap_log_reason("error sending headers to client",r->uri,r); return HTTP_INTERNAL_SERVER_ERROR; } /* * if Interchange is sending body text (HTML), then * relay this to the client */ if (!r->header_only){ ap_reset_timeout(r); if ((rc = ap_bnonblock(ic_buff,B_RD)) != 0){ ap_log_reason("error turning non blocking I/O on Interchange socket",r->uri,r); return HTTP_INTERNAL_SERVER_ERROR; } ap_bsetflag(ic_buff,B_SAFEREAD,1); if (ap_send_fb(ic_buff,r) <= 0){ ap_log_reason("error sending response body to client",r->uri,r); return HTTP_INTERNAL_SERVER_ERROR; } } ap_kill_timeout(r); return OK; }
static int ipp_handler(request_rec *r) { papi_attribute_t **request = NULL, **response = NULL; IPPListenerConfig *config; papi_status_t status; int ret; /* Really, IPP is all POST requests */ if (r->method_number != M_POST) return (DECLINED); #ifndef APACHE2 /* * An IPP request must have a MIME type of "application/ipp" * (RFC-2910, Section 4, page 19). If it doesn't match this * MIME type, we should decline the request and let someone else * try and handle it. */ if (r->headers_in != NULL) { char *mime_type = (char *)ap_table_get(r->headers_in, "Content-Type"); if ((mime_type == NULL) || (strcasecmp(mime_type, "application/ipp") != 0)) return (DECLINED); } #endif /* CHUNKED_DECHUNK might not work right for IPP? */ if ((ret = ap_setup_client_block(r, REQUEST_CHUNKED_DECHUNK)) != OK) return (ret); if (!ap_should_client_block(r)) return (HTTP_INTERNAL_SERVER_ERROR); #ifndef APACHE2 ap_soft_timeout("ipp_module: read/reply request ", r); #endif /* read the IPP request off the network */ status = ipp_read_message(read_data, r, &request, IPP_TYPE_REQUEST); if (status != PAPI_OK) _log_rerror(APLOG_MARK, APLOG_ERR, r, "read failed: %s\n", papiStatusString(status)); #ifdef DEBUG papiAttributeListPrint(stderr, request, "request (%d) ", getpid()); #endif (void) papiAttributeListAddString(&request, PAPI_ATTR_EXCL, "originating-host", (char *) #ifdef APACHE2 ap_get_remote_host (r->connection, r->per_dir_config, REMOTE_NAME, NULL)); #else ap_get_remote_host (r->connection, r->per_dir_config, REMOTE_NAME)); #endif (void) papiAttributeListAddInteger(&request, PAPI_ATTR_EXCL, "uri-port", ap_get_server_port(r)); if (r->headers_in != NULL) { char *host = (char *)ap_table_get(r->headers_in, "Host"); if ((host == NULL) || (host[0] == '\0')) host = (char *)ap_get_server_name(r); (void) papiAttributeListAddString(&request, PAPI_ATTR_EXCL, "uri-host", host); } (void) papiAttributeListAddString(&request, PAPI_ATTR_EXCL, "uri-path", r->uri); config = ap_get_module_config(r->per_dir_config, &ipp_module); if (config != NULL) { (void) papiAttributeListAddInteger(&request, PAPI_ATTR_EXCL, "conformance", config->conformance); (void) papiAttributeListAddCollection(&request, PAPI_ATTR_EXCL, "operations", config->operations); if (config->default_user != NULL) (void) papiAttributeListAddString(&request, PAPI_ATTR_EXCL, "default-user", config->default_user); if (config->default_svc != NULL) (void) papiAttributeListAddString(&request, PAPI_ATTR_EXCL, "default-service", config->default_svc); } /* * For Trusted Solaris, pass the fd number of the socket connection * to the backend so the it can be forwarded to the backend print * service to retrieve the sensativity label off of a multi-level * port. */ (void) papiAttributeListAddInteger(&request, PAPI_ATTR_EXCL, "peer-socket", ap_bfileno(r->connection->client, B_RD)); /* process the request */ status = ipp_process_request(request, &response, read_data, r); if (status != PAPI_OK) { errno = 0; _log_rerror(APLOG_MARK, APLOG_ERR, r, "request failed: %s\n", papiStatusString(status)); discard_data(r); } #ifdef DEBUG fprintf(stderr, "processing result: %s\n", papiStatusString(status)); papiAttributeListPrint(stderr, response, "response (%d) ", getpid()); #endif /* * If the client is using chunking and we have not yet received the * final "0" sized chunk, we need to discard any data that may * remain in the post request. */ if ((r->read_chunked != 0) && (ap_table_get(r->headers_in, "Content-Length") == NULL)) discard_data(r); /* write an IPP response back to the network */ r->content_type = "application/ipp"; #ifndef APACHE2 ap_send_http_header(r); #endif status = ipp_write_message(write_data, r, response); if (status != PAPI_OK) _log_rerror(APLOG_MARK, APLOG_ERR, r, "write failed: %s\n", papiStatusString(status)); #ifdef DEBUG fprintf(stderr, "write result: %s\n", papiStatusString(status)); fflush(stderr); #endif papiAttributeListFree(request); papiAttributeListFree(response); #ifndef APACHE2 ap_kill_timeout(r); if (ap_rflush(r) < 0) _log_rerror(APLOG_MARK, APLOG_ERR, r, "flush failed, response may not have been sent"); #endif return (OK); }
static int neko_handler_rec( request_rec *r ) { mcontext ctx; neko_vm *vm; const char *ctype; value exc = NULL; /* Seems to crash on Windows. And on Linux, we rarely have libGC 7.x installed anyway # if defined(APACHE_2_X) || defined(NEKO_WINDOWS) // we are using threads, so let's make sure that the current thread is registered neko_thread_register(true); # endif */ config.hits++; ctx.r = r; ctx.main = cache_find(r); ctx.post_data = val_null; ctx.headers_sent = false; ctx.content_type = alloc_string("text/html"); r->content_type = val_string(ctx.content_type); if( ap_setup_client_block(r,REQUEST_CHUNKED_ERROR) != 0 ) { send_headers(&ctx); apache_error(APLOG_WARNING,r,"ap_setup_client_block failed"); return OK; } ctype = ap_table_get(r->headers_in,"Content-Type"); if( (!ctype || strstr(ctype,"multipart/form-data") == NULL) && ap_should_client_block(r) ) { # define MAXLEN 1024 char buf[MAXLEN]; int len; int tlen = 0; buffer b = alloc_buffer(NULL); while( (len = ap_get_client_block(r,buf,MAXLEN)) > 0 ) { if( tlen < config.max_post_size ) buffer_append_sub(b,buf,len); tlen += len; } if( tlen >= config.max_post_size ) { send_headers(&ctx); apache_error(APLOG_WARNING,r,"Maximum POST data exceeded. Try using multipart encoding"); return OK; } ctx.post_data = buffer_to_string(b); } vm = neko_vm_alloc(NULL); if( config.use_stats ) neko_vm_set_stats(vm,neko_stats_measure,config.use_prim_stats?neko_stats_measure:NULL); neko_vm_set_custom(vm,k_mod_neko,&ctx); if( config.use_jit && !neko_vm_jit(vm,1) ) { send_headers(&ctx); apache_error(APLOG_WARNING,r,"JIT required by env. var but not enabled in NekoVM"); return OK; } neko_vm_redirect(vm,request_print,&ctx); neko_vm_select(vm); if( ctx.main != NULL ) { value old = ctx.main; if( config.use_stats ) neko_stats_measure(vm,r->filename,1); val_callEx(val_null,old,NULL,0,&exc); if( config.use_stats ) neko_stats_measure(vm,r->filename,0); if( old != ctx.main ) cache_module(r->filename,FTIME(r),ctx.main); } else { char *base_uri = request_base_uri(r); value mload = neko_default_loader(&base_uri,1); value args[] = { alloc_string(r->filename), mload }; char *p = strrchr(val_string(args[0]),'.'); if( p != NULL ) *p = 0; val_callEx(mload,val_field(mload,val_id("loadmodule")),args,2,&exc); if( ctx.main != NULL && config.use_cache ) cache_module(r->filename,FTIME(r),ctx.main); } if( exc != NULL ) { buffer b = alloc_buffer(NULL); value v; int i; const char *p, *start; value st = neko_exc_stack(vm); val_buffer(b,exc); config.exceptions++; ap_soft_timeout("Client Timeout",r); send_headers(&ctx); v = buffer_to_string(b); p = val_string(v); start = p; ap_rprintf(r,"Uncaught exception - "); while( *p ) { if( *p == '<' || *p == '>' ) { ap_rwrite(start,(int)(p - start),r); ap_rwrite((*p == '<')?"<":">",4, r); start = p + 1; } p++; } ap_rwrite(start,(int)(p - start),r); ap_rprintf(r,"<br/><br/>"); for(i=0;i<val_array_size(st);i++) { value s = val_array_ptr(st)[i]; if( val_is_null(s) ) ap_rprintf(r,"Called from a C function<br/>"); else if( val_is_string(s) ) { ap_rprintf(r,"Called from %s (no debug available)<br/>",val_string(s)); } else if( val_is_array(s) && val_array_size(s) == 2 && val_is_string(val_array_ptr(s)[0]) && val_is_int(val_array_ptr(s)[1]) ) ap_rprintf(r,"Called from %s line %d<br/>",val_string(val_array_ptr(s)[0]),val_int(val_array_ptr(s)[1])); else { b = alloc_buffer(NULL); val_buffer(b,s); ap_rprintf(r,"Called from %s<br/>",val_string(buffer_to_string(b))); } } ap_kill_timeout(r); return OK; } send_headers(&ctx); return OK; }
static PyObject * req_readline(requestobject *self, PyObject *args) { int rc, chunk_len, bytes_read; char *buffer; PyObject *result; int copied = 0; int len = -1; if (! PyArg_ParseTuple(args, "|i", &len)) return NULL; if (len == 0) { return PyString_FromString(""); } /* is this the first read? */ if (! self->request_rec->read_length) { /* then do some initial setting up */ rc = ap_setup_client_block(self->request_rec, REQUEST_CHUNKED_ERROR); if(rc != OK) { PyObject *val = PyInt_FromLong(rc); if (val == NULL) return NULL; PyErr_SetObject(Mp_ServerReturn, val); Py_DECREF(val); return NULL; } if (! ap_should_client_block(self->request_rec)) { /* client has nothing to send */ return PyString_FromString(""); } } if (len < 0) len = self->request_rec->remaining + (self->rbuff_len - self->rbuff_pos); /* create the result buffer */ result = PyString_FromStringAndSize(NULL, len); /* possibly no more memory */ if (result == NULL) return NULL; buffer = PyString_AS_STRING((PyStringObject *) result); /* is there anything left in the rbuff from previous reads? */ if (self->rbuff_pos < self->rbuff_len) { /* if yes, process that first */ while (self->rbuff_pos < self->rbuff_len) { buffer[copied++] = self->rbuff[self->rbuff_pos]; if ((self->rbuff[self->rbuff_pos++] == '\n') || (copied == len)) { /* our work is done */ /* resize if necessary */ if (copied < len) if(_PyString_Resize(&result, copied)) return NULL; return result; } } } /* if got this far, the buffer should be empty, we need to read more */ /* create a read buffer */ self->rbuff_len = len > HUGE_STRING_LEN ? len : HUGE_STRING_LEN; self->rbuff_pos = self->rbuff_len; self->rbuff = ap_palloc(self->request_rec->pool, self->rbuff_len); if (! self->rbuff) return PyErr_NoMemory(); /* set timeout */ ap_soft_timeout("mod_python_read", self->request_rec); /* read it in */ Py_BEGIN_ALLOW_THREADS chunk_len = ap_get_client_block(self->request_rec, self->rbuff, self->rbuff_len); Py_END_ALLOW_THREADS; bytes_read = chunk_len; /* if this is a "short read", try reading more */ while ((chunk_len != 0 ) && (bytes_read + copied < len)) { Py_BEGIN_ALLOW_THREADS chunk_len = ap_get_client_block(self->request_rec, self->rbuff + bytes_read, self->rbuff_len - bytes_read); Py_END_ALLOW_THREADS ap_reset_timeout(self->request_rec); if (chunk_len == -1) { ap_kill_timeout(self->request_rec); PyErr_SetObject(PyExc_IOError, PyString_FromString("Client read error (Timeout?)")); return NULL; } else bytes_read += chunk_len; } self->rbuff_len = bytes_read; self->rbuff_pos = 0; ap_kill_timeout(self->request_rec); /* now copy the remaining bytes */ while (self->rbuff_pos < self->rbuff_len) { buffer[copied++] = self->rbuff[self->rbuff_pos]; if ((self->rbuff[self->rbuff_pos++] == '\n') || (copied == len)) /* our work is done */ break; } /* resize if necessary */ if (copied < len) if(_PyString_Resize(&result, copied)) return NULL; return result; }
static PyObject * req_read(requestobject *self, PyObject *args) { int rc, bytes_read, chunk_len; char *buffer; PyObject *result; int copied = 0; int len = -1; if (! PyArg_ParseTuple(args, "|i", &len)) return NULL; if (len == 0) { return PyString_FromString(""); } /* is this the first read? */ if (! self->request_rec->read_length) { /* then do some initial setting up */ rc = ap_setup_client_block(self->request_rec, REQUEST_CHUNKED_ERROR); if(rc != OK) { PyObject *val = PyInt_FromLong(rc); if (val == NULL) return NULL; PyErr_SetObject(Mp_ServerReturn, val); Py_DECREF(val); return NULL; } if (! ap_should_client_block(self->request_rec)) { /* client has nothing to send */ return PyString_FromString(""); } } if (len < 0) len = self->request_rec->remaining + (self->rbuff_len - self->rbuff_pos); result = PyString_FromStringAndSize(NULL, len); /* possibly no more memory */ if (result == NULL) return NULL; buffer = PyString_AS_STRING((PyStringObject *) result); /* if anything left in the readline buffer */ while ((self->rbuff_pos < self->rbuff_len) && (copied < len)) buffer[copied++] = self->rbuff[self->rbuff_pos++]; if (copied == len) return result; /* we're done! */ /* set timeout */ ap_soft_timeout("mod_python_read", self->request_rec); /* read it in */ Py_BEGIN_ALLOW_THREADS chunk_len = ap_get_client_block(self->request_rec, buffer, len); Py_END_ALLOW_THREADS bytes_read = chunk_len; /* if this is a "short read", try reading more */ while ((bytes_read < len) && (chunk_len != 0)) { Py_BEGIN_ALLOW_THREADS chunk_len = ap_get_client_block(self->request_rec, buffer+bytes_read, len-bytes_read); Py_END_ALLOW_THREADS ap_reset_timeout(self->request_rec); if (chunk_len == -1) { ap_kill_timeout(self->request_rec); PyErr_SetObject(PyExc_IOError, PyString_FromString("Client read error (Timeout?)")); return NULL; } else bytes_read += chunk_len; } ap_kill_timeout(self->request_rec); /* resize if necessary */ if (bytes_read < len) if(_PyString_Resize(&result, bytes_read)) return NULL; return result; }
/* * Sample content handler. All this does is display the call list that has * been built up so far. * * The return value instructs the caller concerning what happened and what to * do next: * OK ("we did our thing") * DECLINED ("this isn't something with which we want to get involved") * HTTP_mumble ("an error status should be reported") */ static int example_handler(request_rec *r) { excfg *dcfg; dcfg = our_dconfig(r); trace_add(r->server, r, dcfg, "example_handler()"); /* * We're about to start sending content, so we need to force the HTTP * headers to be sent at this point. Otherwise, no headers will be sent * at all. We can set any we like first, of course. **NOTE** Here's * where you set the "Content-type" header, and you do so by putting it in * r->content_type, *not* r->headers_out("Content-type"). If you don't * set it, it will be filled in with the server's default type (typically * "text/plain"). You *must* also ensure that r->content_type is lower * case. * * We also need to start a timer so the server can know if the connexion * is broken. */ r->content_type = "text/html"; ap_soft_timeout("send example call trace", r); ap_send_http_header(r); #ifdef CHARSET_EBCDIC /* Server-generated response, converted */ ap_bsetflag(r->connection->client, B_EBCDIC2ASCII, r->ebcdic.conv_out = 1); #endif /* * If we're only supposed to send header information (HEAD request), we're * already there. */ if (r->header_only) { ap_kill_timeout(r); return OK; } /* * Now send our actual output. Since we tagged this as being * "text/html", we need to embed any HTML. */ ap_rputs(DOCTYPE_HTML_3_2, r); ap_rputs("<HTML>\n", r); ap_rputs(" <HEAD>\n", r); ap_rputs(" <TITLE>mod_example Module Content-Handler Output\n", r); ap_rputs(" </TITLE>\n", r); ap_rputs(" </HEAD>\n", r); ap_rputs(" <BODY>\n", r); ap_rputs(" <H1><SAMP>mod_example</SAMP> Module Content-Handler Output\n", r); ap_rputs(" </H1>\n", r); ap_rputs(" <P>\n", r); ap_rprintf(r, " Apache HTTP Server version: \"%s\"\n", ap_get_server_version()); ap_rputs(" <BR>\n", r); ap_rprintf(r, " Server built: \"%s\"\n", ap_get_server_built()); ap_rputs(" </P>\n", r);; ap_rputs(" <P>\n", r); ap_rputs(" The format for the callback trace is:\n", r); ap_rputs(" </P>\n", r); ap_rputs(" <DL>\n", r); ap_rputs(" <DT><EM>n</EM>.<SAMP><routine-name>", r); ap_rputs("(<routine-data>)</SAMP>\n", r); ap_rputs(" </DT>\n", r); ap_rputs(" <DD><SAMP>[<applies-to>]</SAMP>\n", r); ap_rputs(" </DD>\n", r); ap_rputs(" </DL>\n", r); ap_rputs(" <P>\n", r); ap_rputs(" The <SAMP><routine-data></SAMP> is supplied by\n", r); ap_rputs(" the routine when it requests the trace,\n", r); ap_rputs(" and the <SAMP><applies-to></SAMP> is extracted\n", r); ap_rputs(" from the configuration record at the time of the trace.\n", r); ap_rputs(" <STRONG>SVR()</STRONG> indicates a server environment\n", r); ap_rputs(" (blank means the main or default server, otherwise it's\n", r); ap_rputs(" the name of the VirtualHost); <STRONG>DIR()</STRONG>\n", r); ap_rputs(" indicates a location in the URL or filesystem\n", r); ap_rputs(" namespace.\n", r); ap_rputs(" </P>\n", r); ap_rprintf(r, " <H2>Static callbacks so far:</H2>\n <OL>\n%s </OL>\n", trace); ap_rputs(" <H2>Request-specific callbacks so far:</H2>\n", r); ap_rprintf(r, " <OL>\n%s </OL>\n", ap_table_get(r->notes, TRACE_NOTE)); ap_rputs(" <H2>Environment for <EM>this</EM> call:</H2>\n", r); ap_rputs(" <UL>\n", r); ap_rprintf(r, " <LI>Applies-to: <SAMP>%s</SAMP>\n </LI>\n", dcfg->loc); ap_rprintf(r, " <LI>\"Example\" directive declared here: %s\n </LI>\n", (dcfg->local ? "YES" : "NO")); ap_rprintf(r, " <LI>\"Example\" inherited: %s\n </LI>\n", (dcfg->congenital ? "YES" : "NO")); ap_rputs(" </UL>\n", r); ap_rputs(" </BODY>\n", r); ap_rputs("</HTML>\n", r); /* * We're all done, so cancel the timeout we set. Since this is probably * the end of the request we *could* assume this would be done during * post-processing - but it's possible that another handler might be * called and inherit our outstanding timer. Not good; to each its own. */ ap_kill_timeout(r); /* * We did what we wanted to do, so tell the rest of the server we * succeeded. */ return OK; }