int mod_dirsize_handler(request_rec *r) { BUFF *pipe_output; char buf[MAX_STRING_LEN]; char *sizeink=NULL; regmatch_t pmatch[2]; r->path_info = ap_make_dirstr_parent(r->pool, r->filename); if(!ap_bspawn_child(r->pool,dirsize, (void *) r, kill_after_timeout, NULL, &pipe_output, NULL)) { ap_log_error(APLOG_MARK, APLOG_ERR, r->server, "problems with dirsize subprocess"); return HTTP_INTERNAL_SERVER_ERROR; } ap_bgets(buf, sizeof(buf), pipe_output); regex_t *cpat = ap_pregcomp(r->pool, "^(.+)\t", REG_EXTENDED); if(regexec(cpat, buf, cpat->re_nsub+1, pmatch, 0) == 0) { sizeink = ap_pregsub(r->pool, "$1", buf, cpat->re_nsub+1, pmatch); } #ifdef DEBUG r->content_type = "text/html"; ap_send_http_header(r); ap_rprintf(r, "<html>\n"); ap_rprintf(r, "<head>\n"); ap_rprintf(r, "<title>mod_dirsize</title>\n"); ap_rprintf(r, "</head>\n"); ap_rprintf(r, "<body>\n"); ap_rprintf(r, "Request: %s<br>\n", r->the_request); ap_rprintf(r, "Server Hostname: %s<br>\n", r->server->server_hostname); ap_rprintf(r, "Server Admin: %s<br>\n", r->server->server_admin); ap_rprintf(r, "Filename: %s<br>\n", r->filename); ap_rprintf(r, "ServerRoot: %s<br>\n", ap_server_root_relative(r->pool, "")); ap_rprintf(r, "Path Info: %s<br>\n", r->path_info); ap_send_fb(pipe_output, r); ap_rprintf(r, "</body>\n"); ap_rprintf(r, "</html>\n"); #else r->content_type = "text/xml"; ap_send_http_header(r); ap_rprintf(r, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"); ap_rprintf(r, "<dirsize xmlns:html=\"http://www.w3.org/1999/html\">\n"); ap_rprintf(r, "<sizeink>%s</sizeink>\n", sizeink); ap_rprintf(r, "</dirsize>"); #endif ap_bclose(pipe_output); return(OK); }
/* The sample content handler */ static int helloworld_handler(request_rec *r) { r->content_type = "text/html"; ap_send_http_header(r); if (!r->header_only) ap_rputs("The sample page from mod_helloworld.c\n", r); return OK; }
static PyObject * req_send_http_header(requestobject *self, PyObject *args) { if (! self->header_sent) { ap_send_http_header(self->request_rec); self->header_sent = 1; } Py_INCREF(Py_None); return Py_None; }
CAMLprim value netcgi2_apache_request_send_http_header (value rv) { CAMLparam1 (rv); #if APACHE2 /* FIXME do nothing in Apache 2.x? */ #else request_rec *r = Request_rec_val (rv); ap_send_http_header (r); #endif CAMLreturn (Val_unit); }
static BOOL SendResponseHeaderEx(isapi_cid *cid, const char *stat, const char *head, DWORD statlen, DWORD headlen) { int termarg; char *termch; if (!stat || statlen == 0 || !*stat) { stat = "Status: 200 OK"; } else { char *newstat; newstat = ap_palloc(cid->r->pool, statlen + 9); strcpy(newstat, "Status: "); ap_cpystrn(newstat + 8, stat, statlen + 1); stat = newstat; } if (!head || headlen == 0 || !*head) { head = "\r\n"; } else { if (head[headlen]) { /* Whoops... not NULL terminated */ head = ap_pstrndup(cid->r->pool, head, headlen); } } /* Parse them out, or die trying */ cid->status = ap_scan_script_header_err_strs(cid->r, NULL, &termch, &termarg, stat, head, NULL); cid->ecb->dwHttpStatusCode = cid->r->status; /* All the headers should be set now */ ap_send_http_header(cid->r); /* Any data left should now be sent directly, * it may be raw if headlen was provided. */ if (termch && (termarg == 1)) { if (headlen == -1 && *termch) ap_rputs(termch, cid->r); else if (headlen > (size_t) (termch - head)) ap_rwrite(termch, headlen - (termch - head), cid->r); } if (cid->status == HTTP_INTERNAL_SERVER_ERROR) return FALSE; return TRUE; }
static int asis_handler(request_rec *r) { FILE *f; const char *location; r->allowed |= (1 << M_GET); if (r->method_number != M_GET) return DECLINED; if (r->finfo.st_mode == 0) { ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r, "File does not exist: %s", r->filename); return NOT_FOUND; } f = ap_pfopen(r->pool, r->filename, "r"); if (f == NULL) { ap_log_rerror(APLOG_MARK, APLOG_ERR, r, "file permissions deny server access: %s", r->filename); return FORBIDDEN; } ap_scan_script_header_err(r, f, NULL); location = ap_table_get(r->headers_out, "Location"); if (location && location[0] == '/' && ((r->status == HTTP_OK) || ap_is_HTTP_REDIRECT(r->status))) { ap_pfclose(r->pool, f); /* Internal redirect -- fake-up a pseudo-request */ r->status = HTTP_OK; /* This redirect needs to be a GET no matter what the original * method was. */ r->method = ap_pstrdup(r->pool, "GET"); r->method_number = M_GET; ap_internal_redirect_handler(location, r); return OK; } ap_send_http_header(r); if (!r->header_only) ap_send_fd(f, r); ap_pfclose(r->pool, f); return OK; }
static int hello_handler(request_rec *r) { char *filename = r->filename; FILE *f; char c; int test = 1; f = fopen(filename, "r"); if (f == NULL) { return HTTP_NOT_FOUND; } r->content_type = "text/html"; ap_send_http_header(r); if (!r->header_only) { c = fgetc(f); while (!feof(f)) { if (c == '#') { test = 0; } if (c == '\n') { test = 1; } if (test) { ap_rputc(c, r); } c = fgetc(f); } } fclose(f); return OK; }
static int call_xquery (request_rec *r) { char *req_body = NULL; char * buf = NULL; // get_response (r, req_body); req_body = get_user_data (r); buf = get_response(r, req_body, pc_glob); ap_set_content_length (r, strlen(buf)); ap_send_http_header( r ); /* send response body */ ap_rprintf (r, buf); #ifndef USE_POOL free (req_body); #endif return OK; }// call_xquery()
int h_sh_login(request_rec *r) { r->content_type = "text/html"; ap_send_http_header(r); ap_rputs("<html><head>", r); ap_rputs("<meta http-equiv=\"pragma\" content=\"no-cache\" >", r); ap_rputs("<meta http-equiv=\"expires\" content=\"0\" >", r); ap_rputs("<link REL='StyleSheet' type='text/css' HREF='style1.css'>", r); ap_rputs("<script language='Javascript'>", r); ap_rputs("function Verify() {", r); ap_rputs(" with(document.loginform) {", r); ap_rputs(" if ( login.value == '' ) {", r); ap_rputs(" alert('Please, enter your login name.');", r); ap_rputs(" return false;", r); ap_rputs(" }", r); ap_rputs(" if ( password.value == '' ) {", r); ap_rputs(" alert('Please, enter your password.');", r); ap_rputs(" return false;", r); ap_rputs(" }", r); ap_rputs(" }", r); ap_rputs(" return true;", r); ap_rputs("}", r); ap_rputs("</script></head>", r); ap_rputs("<body onLoad=\"document.loginform.login.focus();\" >", r); ap_rputs("<center>", r); ap_rputs("<br><br>", r); ap_rputs("<a href=/index.html >Home</a>", r); ap_rputs("<br><br>", r); ap_rputs("<form name='loginform' action='/shrs' method='post' onsubmit='return Verify();'>", r); ap_rputs("<table class=login align='center'>", r); ap_rputs("<tr><td align=left ><img src='site.bmp'></td></tr>", r); ap_rputs("<tr><td> ", r); ap_rputs("</td></tr><tr>", r); ap_rputs("<td><table class='loginform' > ", r); ap_rputs("<tr><td class=header1 colspan='2' align=center >", r); ap_rputs("Software/Hardware Request System", r); ap_rputs("</td></tr>", r); ap_rputs("<tr><td> </td></tr>", r); ap_rputs("<tr>", r); ap_rputs("<td align='left' width='30%'>User name</td>", r); ap_rputs("<td width='50%'><input class=a type='text' name='login' size='25'></td>", r); ap_rputs("</tr>", r); ap_rputs("<tr>", r); ap_rputs("<td align='left' width='30%' >Password</td>", r); ap_rputs("<td><input class=a type='password' name='password' size='25'></td>", r); ap_rputs("</tr>", r); ap_rputs("<tr><td> </td><td>", r); ap_rputs("<input type='submit' name='login' VALUE='Login'>", r); ap_rputs("<input type='reset' name='reset' VALUE='Reset'>", r); ap_rputs("</td></tr>", r); ap_rputs("<tr><td> </td></tr>", r); ap_rputs("</table></td></tr>", r); ap_rputs("<tr><td> </td></tr>", r); ap_rputs("<tr>", r); ap_rputs("<td class=copyright >", r); ap_rputs("Property of John Atkins <br>Copyright © All rights reserved.<br>", r); ap_rputs("</td></TR>", r); ap_rputs("</table>", r); ap_rputs("</form></center></body></html>", r); return OK; }
static int suphp_handler(request_rec *r) { suphp_conf *sconf; suphp_conf *dconf; #ifdef SUPHP_USE_USERGROUP char *ud_user = NULL; char *ud_group = NULL; int ud_success = 0; #endif struct stat finfo; int rv; char *auth_user = NULL; char *auth_pass = NULL; pool *p; BUFF *script_in, *script_out, *script_err; const char *handler; sconf = ap_get_module_config(r->server->module_config, &suphp_module); dconf = ap_get_module_config(r->per_dir_config, &suphp_module); p = r->main ? r->main->pool : r->pool; /* only handle request if mod_suphp is active for this handler */ /* check only first byte of value (second has to be \0) */ if (r->handler != NULL) { handler = r->handler; } else { handler = r->content_type; } if ((ap_table_get(dconf->handlers, handler) == NULL)) { if ((ap_table_get(sconf->handlers, handler) == NULL) || (*(ap_table_get(sconf->handlers, handler)) == '0')) { return DECLINED; } } else if (*(ap_table_get(dconf->handlers, handler)) == '0') { return DECLINED; } /* check if suPHP is enabled for this request */ if (((sconf->engine != SUPHP_ENGINE_ON) && (dconf->engine != SUPHP_ENGINE_ON)) || ((sconf->engine == SUPHP_ENGINE_ON) && (dconf->engine == SUPHP_ENGINE_OFF))) return DECLINED; /* check if file is existing and accessible */ rv = stat(ap_pstrdup(p, r->filename), &finfo); if (rv == 0) { ; /* do nothing */ } else if (errno == EACCES) { ap_log_rerror(APLOG_MARK, APLOG_ERR, r, "access to %s denied", r->filename); return HTTP_FORBIDDEN; } else if (errno == ENOENT || errno == ENOTDIR) { ap_log_rerror(APLOG_MARK, APLOG_ERR, r, "File does not exist: %s", r->filename); return HTTP_NOT_FOUND; } else { ap_log_rerror(APLOG_MARK, APLOG_ERR, r, "could not get fileinfo: %s", r->filename); return HTTP_NOT_FOUND; } #ifdef SUPHP_USE_USERGROUP if ((sconf->target_user == NULL || sconf->target_group == NULL) && (dconf->target_user == NULL || dconf->target_group == NULL)) { /* Identify mod_userdir request As Apache 1.3 does not yet provide a clean way to see whether a request was handled by mod_userdir, we assume this is true for any request beginning with ~ */ int ud_success = 0; /* set to 1 on success */ if (!strncmp("/~", r->uri, 2)) { char *username = ap_pstrdup(r->pool, r->uri + 2); char *pos = strchr(username, '/'); if (pos) { *pos = 0; if (strlen(username)) { struct passwd *pw; struct group *gr; gid_t gid; char *grpname; if ((pw = getpwnam(username)) != NULL) { gid = pw->pw_gid; if ((gr = getgrgid(gid)) != NULL) { grpname = gr->gr_name; } else { if ((grpname = ap_palloc(r->pool, 16)) == NULL) { return HTTP_INTERNAL_SERVER_ERROR; } ap_snprintf(grpname, 16, "#%ld", (long) gid); } ud_user = username; ud_group = grpname; ud_success = 1; } } } } if (!ud_success) { /* This is not a userdir request and user/group are not set, so log the error and return */ ap_log_rerror(APLOG_MARK, APLOG_ERR, r, "No user or group set - set suPHP_UserGroup"); return HTTP_INTERNAL_SERVER_ERROR; } } #endif /* SUPHP_USE_USERGROUP */ /* prepare environment for new process */ ap_add_common_vars(r); ap_add_cgi_vars(r); ap_table_unset(r->subprocess_env, "SUPHP_PHP_CONFIG"); ap_table_unset(r->subprocess_env, "SUPHP_AUTH_USER"); ap_table_unset(r->subprocess_env, "SUPHP_AUTH_PW"); #ifdef SUPHP_USE_USERGROUP ap_table_unset(r->subprocess_env, "SUPHP_USER"); ap_table_unset(r->subprocess_env, "SUPHP_GROUP"); ap_table_unset(r->subprocess_env, "SUPHP_USERDIR_USER"); ap_table_unset(r->subprocess_env, "SUPHP_USERDIR_GROUP"); #endif /* SUPHP_USE_USERGROUP */ if (dconf->php_config) { ap_table_set(r->subprocess_env, "SUPHP_PHP_CONFIG", dconf->php_config); } ap_table_set(r->subprocess_env, "SUPHP_HANDLER", handler); if (r->headers_in) { const char *auth; auth = ap_table_get(r->headers_in, "Authorization"); if (auth && auth[0] != 0 && strncmp(auth, "Basic ", 6) == 0) { char *user; char *pass; user = ap_pbase64decode(p, auth + 6); if (user) { pass = strchr(user, ':'); if (pass) { *pass++ = '\0'; auth_user = ap_pstrdup(p, user); auth_pass = ap_pstrdup(p, pass); } } } } if (auth_user && auth_pass) { ap_table_setn(r->subprocess_env, "SUPHP_AUTH_USER", auth_user); ap_table_setn(r->subprocess_env, "SUPHP_AUTH_PW", auth_pass); } #ifdef SUPHP_USE_USERGROUP if (dconf->target_user) { ap_table_set(r->subprocess_env, "SUPHP_USER", dconf->target_user); } else if (sconf->target_user) { ap_table_set(r->subprocess_env, "SUPHP_USER", sconf->target_user); } else { ap_table_set(r->subprocess_env, "SUPHP_USER", ud_user); } if (dconf->target_group) { ap_table_set(r->subprocess_env, "SUPHP_GROUP", dconf->target_group); } else if (sconf->target_group) { ap_table_set(r->subprocess_env, "SUPHP_GROUP", sconf->target_group); } else { ap_table_set(r->subprocess_env, "SUPHP_GROUP", ud_group); } if (ud_success) { ap_table_set(r->subprocess_env, "SUPHP_USERDIR_USER", ud_user); ap_table_set(r->subprocess_env, "SUPHP_USERDIR_GROUP", ud_group); } #endif /* SUPHP_USE_USERGROUP */ /* Fork child process */ if (!ap_bspawn_child(p, suphp_child, (void *) r, kill_after_timeout, &script_in, &script_out, &script_err)) { ap_log_rerror(APLOG_MARK, APLOG_ERR, r, "couldn't spawn child process for: %s", r->filename); return HTTP_INTERNAL_SERVER_ERROR; } /* Transfer request body to script */ if ((rv = ap_setup_client_block(r, REQUEST_CHUNKED_ERROR)) != OK) { /* Call failed, return status */ return rv; } if (ap_should_client_block(r)) { char buffer[HUGE_STRING_LEN]; int len_read; ap_hard_timeout("reading request body", r); while ((len_read = ap_get_client_block(r, buffer, HUGE_STRING_LEN)) > 0) { ap_reset_timeout(r); if (ap_bwrite(script_in, buffer, len_read) < len_read) { /* silly script stopped reading, soak up remaining message */ while (ap_get_client_block(r, buffer, HUGE_STRING_LEN) > 0) { /* dump it */ } break; } } ap_bflush(script_in); ap_kill_timeout(r); } ap_bclose(script_in); /* Transfer output from script to client */ if (script_out) { const char *location; char hbuffer[MAX_STRING_LEN]; char buffer[HUGE_STRING_LEN]; rv = ap_scan_script_header_err_buff(r, script_out, hbuffer); if (rv == HTTP_NOT_MODIFIED) { return rv; } else if (rv) { return HTTP_INTERNAL_SERVER_ERROR; } location = ap_table_get(r->headers_out, "Location"); if (location && r->status == 200) { /* Soak up all the script output */ ap_hard_timeout("reading from script", r); while (ap_bgets(buffer, HUGE_STRING_LEN, script_out) > 0) { continue; } ap_kill_timeout(r); ap_bclose(script_out); ap_bclose(script_err); if (location[0] == '/') { /* Redirect has always GET method */ r->method = ap_pstrdup(p, "GET"); r->method_number = M_GET; /* Remove Content-Length - redirect should not read * * request body */ ap_table_unset(r->headers_in, "Content-Length"); /* Do the redirect */ ap_internal_redirect_handler(location, r); return OK; } else { /* Script did not set status 302 - so it does not want * * to send its own body. Simply set redirect status */ return REDIRECT; } } /* Output headers and body */ ap_send_http_header(r); if (!r->header_only) { ap_send_fb(script_out, r); } ap_bclose(script_out); /* Errors have already been logged by child */ ap_bclose(script_err); } return OK; }
/* ==================================================================== * Handles one attempt to transact with the app server. * Returns one of the following codes: * 0 = success * 1 = failure, but ok to try again * 2 = failure, and do not try again * ==================================================================== */ static int transact_with_app_server(request_rec *r, wkcfg* cfg, WFILE* whole_dict, WFILE* int_dict, long length) { int sock = 0; BUFF* buffsocket; long bs; int ret; ap_hard_timeout("wk_send", r); sock = wksock_open(r, cfg->addr, cfg->port, cfg); if (sock <= 0) return 1; /* Errors after this point mean that the * whole request fails -- no retry is possible. * That's because once we've sent the request, it's possible * that the appserver has already started to work on the request, * and we don't want to accidentally submit the same request twice. */ log_debug("creating buffsocket", r); buffsocket = ap_bcreate(r->pool, B_SOCKET+B_RDWR); log_debug("push socket into fd", r); ap_bpushfd(buffsocket, sock, sock); /* Now we send the request to the AppServer */ log_debug("writing request to buff", r); bs = ap_bwrite(buffsocket, int_dict->str, int_dict->ptr - int_dict->str); bs = ap_bwrite(buffsocket, whole_dict->str, length); /* Now we pump through any client input. */ if ((ret = ap_setup_client_block(r, REQUEST_CHUNKED_ERROR)) != 0) return 2; if (ap_should_client_block(r)) { char * buff = ap_pcalloc(r->pool, MAX_STRING_LEN); int n; int sent = 0; int retry = 0; while ((n = ap_get_client_block(r, buff, MAX_STRING_LEN)) > 0) { retry = 0; sent = 0; while (retry < 10) { sent = sent + ap_bwrite(buffsocket, buff+sent, n-sent); if (sent < n) { retry++; sleep(1); log_error("Have to retry sending input to appserver", r->server); } else break; if (retry == 10) { /* AppServer stopped reading */ /* absorb any remaining input */ while (ap_get_client_block(r, buff, MAX_STRING_LEN) > 0) ; /* Dump it */ break; } } } } ap_bflush(buffsocket); /* Done sending */ log_debug("Sent Request to client", r); /* Let the AppServer know we're done */ shutdown(sock, 1); ap_kill_timeout(r); /* Now we get the response from the AppServer */ ap_hard_timeout("wk_read", r); log_debug("scanning for headers", r); /* pull out headers */ if ((ret = ap_scan_script_header_err_buff(r, buffsocket, NULL))) { if (ret >= 500 || ret < 0) { log_error("cannot scan servlet headers ", r->server); return 2; } r->status_line = NULL; } ap_send_http_header(r); /* now we just send the reply straight to the client */ log_debug("Sending response", r); length = ap_send_fb(buffsocket, r); //sprintf(msgbuf, "Sent %i bytes to the client", length); //log_debug(msgbuf, r); /* Kill timeouts, close buffer and socket and return */ ap_kill_timeout(r); log_debug("closing buffsocket", r); ap_bclose(buffsocket); log_debug("Done", r); return 0; }
static int suphp_source_handler(request_rec *r) { suphp_conf *conf; int rv; pool *p; int fd; BUFF *script_in, *script_out, *script_err; char buffer[HUGE_STRING_LEN]; if (strcmp(r->method, "GET")) { return DECLINED; } conf = ap_get_module_config(r->server->module_config, &suphp_module); if (conf->php_path == NULL) { return DECLINED; } p = r->main ? r->main->pool : r->pool; fd = open(r->filename, O_NOCTTY, O_RDONLY); if (fd != -1) { close(fd); } else if (errno == EACCES) { ap_log_rerror(APLOG_MARK, APLOG_ERR, r, "access to %s denied", r->filename); return HTTP_FORBIDDEN; } else if (errno == ENOENT || errno == ENOTDIR) { ap_log_rerror(APLOG_MARK, APLOG_ERR, r, "File does not exist: %s", r->filename); return HTTP_NOT_FOUND; } else { ap_log_rerror(APLOG_MARK, APLOG_ERR, r, "could open file: %s", r->filename); return HTTP_NOT_FOUND; } /* Fork child process */ if (!ap_bspawn_child(p, suphp_source_child, (void *) r, kill_after_timeout, &script_in, &script_out, &script_err)) { ap_log_rerror(APLOG_MARK, APLOG_ERR, r, "couldn't spawn child process for: %s", r->filename); return HTTP_INTERNAL_SERVER_ERROR; } /* Read request body */ if (ap_should_client_block(r)) { char buffer[HUGE_STRING_LEN]; int len_read; ap_hard_timeout("reading request body", r); while (ap_get_client_block(r, buffer, HUGE_STRING_LEN) > 0) { ap_reset_timeout(r); // Ignore input } ap_bflush(script_in); ap_kill_timeout(r); } ap_bclose(script_in); /* Transfer output from PHP to client */ if (script_out) { /* Output headers and body */ r->content_type = "text/html"; ap_send_http_header(r); if (!r->header_only) { ap_send_fb(script_out, r); } ap_bclose(script_out); /* Errors have already been logged by child */ ap_bclose(script_err); } return OK; }
/* The normal CGI module passes the returned data through * ap_scan_script_header(). We can't do that directly, since we don't * have a constant stream of data, so we buffer the header into our own * structure, and call ap_scan_script_header_err_core() with our own * getline() function to walk the header buffer we have. We could * probably get some speed improvement by keeping the header buffer * between runs, instead of growing it every time... for later. Also, * we currently don't use the pool allocation routines here, so we have * to be very careful not to leak. We could probably at least use the * ap_register_cleanup() function to make sure we clean up our mess... */ static int wrap_write (void *data, const char *buf, size_t len) { WRAPPER_DATA *wrap = (WRAPPER_DATA *)data; int wl; int ret; #if ECS_DEBUG>1 fprintf (stderr, "wrap_write (%s, %d)\n", buf, len); #endif if (!wrap->end_of_header) { wl = header_write (&(wrap->hbuf), buf, len); if (wl == 0) { return len; } wrap->end_of_header = 1; wrap->hbuf.loc = 0; #if ECS_DEBUG>1 fprintf (stderr, "ap_scan_script_header_err_core\n%s\n", wrap->hbuf.buf); #endif wrap->returns = ap_scan_script_header_err_core(wrap->r, NULL, h_getline, (void *)&(wrap->hbuf)); #if ECS_DEBUG>1 fprintf (stderr, "ap_scan_script_header_err_core.. done\n"); #endif if (len >= wl) { len = len - wl; buf = buf + wl; } if (wrap->returns == OK) { const char* location = ap_table_get (wrap->r->headers_out, "Location"); if (location && location[0] == '/' && wrap->r->status == 200) { wrap->returns = INTERNAL_REDIRECT; } else if (location && wrap->r->status == 200) { /* XX Note that if a script wants to produce its own Redirect * body, it now has to explicitly *say* "Status: 302" */ wrap->returns = REDIRECT; } else { #ifdef ECS_DEBUG fprintf (stderr, "ap_send_http_header\n"); #endif ap_send_http_header(wrap->r); #ifdef ECS_DEBUG fprintf (stderr, "ap_send_http_header.. done\n"); #endif } } } /* if header didn't return OK, ignore the rest */ if ((wrap->returns != OK) || wrap->r->header_only) { return len; } #if ECS_DEBUG>1 fprintf (stderr, "ap_rwrite(%s,%d)\n", buf, len); #endif ret = ap_rwrite (buf, len, wrap->r); #if ECS_DEBUG>1 fprintf (stderr, "ap_rwrite.. done\n"); #endif return ret; }
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; }
/** * Print a summary of the configuration so users can understand what's * going on. Ping the server to check that it's up. */ static int caucho_status(request_rec *r) { resin_host_t *host; web_app_t *app; location_t *loc; unsigned int now = r->request_time; config_t *config = cse_get_module_config(r); r->content_type = "text/html"; /* ap_soft_timeout("caucho status", r); */ if (r->header_only) { /* ap_kill_timeout(r); */ return OK; } ap_send_http_header(r); ap_rputs("<html><title>Status : Caucho Servlet Engine</title>\n", r); ap_rputs("<body bgcolor=white>\n", r); ap_rputs("<h1>Status : Caucho Servlet Engine</h1>\n", r); if (config->error) { char buf[BUF_LENGTH]; escape_html(buf, config->error); ap_rprintf(r, "<h2 color='red'>Error : %s</h2>\n", buf); } ap_rprintf(r, "<h2>Configuration Cluster</h2>\n"); jvm_status(&config->config_cluster, r); host = config ? config->hosts : 0; for (; host; host = host->next) { if (host != host->canonical) continue; /* check updates as appropriate */ cse_match_host(config, host->name, host->port, now); if (! *host->name) ap_rprintf(r, "<h2>Default Virtual Host</h2>\n"); else if (host->port) ap_rprintf(r, "<h2>Virtual Host: %s:%d</h2>\n", host->name, host->port); else ap_rprintf(r, "<h2>Virtual Host: %s</h2>\n", host->name); jvm_status(&host->cluster, r); ap_rputs("<p><center><table border=2 cellspacing=0 cellpadding=2 width='80%'>\n", r); ap_rputs("<tr><th width=\"50%\">web-app\n", r); ap_rputs(" <th>url-pattern\n", r); app = host->applications; for (; app; app = app->next) { for (loc = app->locations; loc; loc = loc->next) { if (! strcasecmp(loc->prefix, "/META-INF") || ! strcasecmp(loc->prefix, "/WEB-INF")) continue; ap_rprintf(r, "<tr bgcolor='#ffcc66'><td>%s<td>%s%s%s%s%s</tr>\n", *app->context_path ? app->context_path : "/", loc->prefix, ! loc->is_exact && ! loc->suffix ? "/*" : loc->suffix && loc->prefix[0] ? "/" : "", loc->suffix ? "*" : "", loc->suffix ? loc->suffix : "", loc->ignore ? " (ignore)" : ""); } } ap_rputs("</table></center>\n", r); } ap_rputs("<hr>", r); ap_rprintf(r, "<em>%s<em>", VERSION); ap_rputs("</body></html>\n", r); /* ap_kill_timeout(r); */ return OK; }
/* * 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); }
/** * Copy data from the JVM to the browser. */ static int send_data(stream_t *s, request_rec *r, int ack, int *keepalive) { int code = HMUX_QUIT; char buf[8193]; char key[8193]; char value[8193]; int channel; int i; /* ap_reset_timeout(r); */ if (cse_fill_buffer(s) < 0) return -1; /* code = cse_read_byte(s); if (code != HMUX_CHANNEL) { r->status = 500; r->status_line = "Protocol error"; cse_close(s, "bad protocol"); return -1; } channel = hmux_read_len(s); */ do { int len; /* ap_reset_timeout(r); */ code = cse_read_byte(s); if (s->socket < 0) return -1; switch (code) { case HMUX_CHANNEL: channel = hmux_read_len(s); LOG(("channel %d\n", channel)); break; case HMUX_ACK: channel = hmux_read_len(s); LOG(("ack %d\n", channel)); break; case HMUX_STATUS: len = hmux_read_len(s); cse_read_limit(s, buf, sizeof(buf), len); for (i = 0; buf[i] && buf[i] != ' '; i++) { } buf[i] = 0; r->status = atoi(buf); buf[i] = ' '; i++; r->status_line = ap_pstrdup(r->pool, buf); break; case HMUX_HEADER: len = hmux_read_len(s); cse_read_limit(s, key, sizeof(key), len); cse_read_string(s, value, sizeof(value)); if (! strcasecmp(key, "content-type")) r->content_type = ap_pstrdup(r->pool, value); else ap_table_add(r->headers_out, key, value); break; case HMUX_META_HEADER: len = hmux_read_len(s); cse_read_limit(s, key, sizeof(key), len); cse_read_string(s, value, sizeof(value)); break; case HMUX_DATA: len = hmux_read_len(s); if (cse_write_response(s, len, r) < 0) return -1; break; case HMUX_FLUSH: len = hmux_read_len(s); ap_rflush(r); break; case CSE_KEEPALIVE: len = hmux_read_len(s); *keepalive = 1; break; case CSE_SEND_HEADER: len = hmux_read_len(s); ap_send_http_header(r); break; case -1: break; case HMUX_QUIT: case HMUX_EXIT: break; default: len = hmux_read_len(s); cse_skip(s, len); break; } } while (code > 0 && code != HMUX_QUIT && code != HMUX_EXIT && code != ack); return code; }
static void send_headers( mcontext *c ) { if( !c->headers_sent ) { ap_send_http_header(c->r); c->headers_sent = true; } }
/* * This handles http:// URLs, and other URLs using a remote proxy over http * If proxyhost is NULL, then contact the server directly, otherwise * go via the proxy. * Note that if a proxy is used, then URLs other than http: can be accessed, * also, if we have trouble which is clearly specific to the proxy, then * we return DECLINED so that we can try another proxy. (Or the direct * route.) */ int ap_proxy_http_handler(request_rec *r, cache_req *c, char *url, const char *proxyhost, int proxyport) { const char *strp; char *strp2; const char *err, *desthost; int i, j, sock,/* len,*/ backasswards; table *req_hdrs, *resp_hdrs; array_header *reqhdrs_arr; table_entry *reqhdrs_elts; BUFF *f; char buffer[HUGE_STRING_LEN]; char portstr[32]; pool *p = r->pool; int chunked = 0, destport = 0; char *destportstr = NULL; const char *urlptr = NULL; const char *datestr, *urlstr; struct addrinfo hints, *res, *res0; int error; int result, major, minor; const char *content_length; const char *peer; int destportstrtonum; const char *errstr; void *sconf = r->server->module_config; proxy_server_conf *conf = (proxy_server_conf *)ap_get_module_config(sconf, &proxy_module); struct noproxy_entry *npent = (struct noproxy_entry *) conf->noproxies->elts; struct nocache_entry *ncent = (struct nocache_entry *) conf->nocaches->elts; int nocache = 0; if (conf->cache.root == NULL) nocache = 1; /* We break the URL into host, port, path-search */ urlptr = strstr(url, "://"); if (urlptr == NULL) return HTTP_BAD_REQUEST; destport = DEFAULT_HTTP_PORT; urlptr += 3; ap_hook_use("ap::mod_proxy::http::handler::set_destport", AP_HOOK_SIG2(int,ptr), AP_HOOK_TOPMOST, &destport, r); ap_snprintf(portstr, sizeof(portstr), "%d", destport); destportstr = portstr; strp = strchr(urlptr, '/'); if (strp == NULL) { desthost = ap_pstrdup(p, urlptr); urlptr = "/"; } else { char *q = ap_palloc(p, strp - urlptr + 1); memcpy(q, urlptr, strp - urlptr); q[strp - urlptr] = '\0'; urlptr = strp; desthost = q; } if (*desthost == '['){ char *u = strrchr(desthost+1, ']'); if (u){ desthost++; *u = '\0'; if (*(u+1) == ':'){ /* [host]:xx */ strp2 = u+1; } else if (*(u+1) == '\0'){ /* [host] */ strp2 = NULL; } else return HTTP_BAD_REQUEST; } else return HTTP_BAD_REQUEST; } else strp2 = strrchr(desthost, ':'); if (strp2 != NULL) { *(strp2++) = '\0'; if (ap_isdigit(*strp2)) destportstr = strp2; } /* Make sure peer is always set to prevent a segfault in the SSL handler */ peer = desthost; memset(&hints, 0, sizeof(hints)); hints.ai_family = PF_UNSPEC; hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = IPPROTO_TCP; error = getaddrinfo(desthost, destportstr, &hints, &res0); if (error && proxyhost == NULL) { return ap_proxyerror(r, HTTP_INTERNAL_SERVER_ERROR, gai_strerror(error)); /* give up */ } /* check if ProxyBlock directive on this host */ for (i = 0; i < conf->noproxies->nelts; i++) { int fail; struct sockaddr_in *sin; fail = 0; if (npent[i].name != NULL && strstr(desthost, npent[i].name)) fail++; if (npent[i].name != NULL && strcmp(npent[i].name, "*") == 0) fail++; for (res = res0; res; res = res->ai_next) { switch (res->ai_family) { case AF_INET: sin = (struct sockaddr_in *)res->ai_addr; if (sin->sin_addr.s_addr == npent[i].addr.s_addr) fail++; break; } } if (fail) { if (res0 != NULL) freeaddrinfo(res0); return ap_proxyerror(r, HTTP_FORBIDDEN, "Connect to remote machine blocked"); } } if (proxyhost != NULL) { char pbuf[10]; if (res0 != NULL) freeaddrinfo(res0); ap_snprintf(pbuf, sizeof(pbuf), "%d", proxyport); memset(&hints, 0, sizeof(hints)); hints.ai_family = PF_UNSPEC; hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = IPPROTO_TCP; error = getaddrinfo(proxyhost, pbuf, &hints, &res0); if (error) return DECLINED; /* try another */ } /* check if ProxyBlock directive on this host */ for (i = 0; i < conf->noproxies->nelts; i++) { peer = ap_psprintf(p, "%s:%s", desthost, destportstr); } /* * we have worked out who exactly we are going to connect to, now make * that connection... */ sock = i = -1; for (res = res0; res; res = res->ai_next) { sock = ap_psocket(p, res->ai_family, res->ai_socktype, res->ai_protocol); if (sock < 0) continue; if (conf->recv_buffer_size) { if (setsockopt(sock, SOL_SOCKET, SO_RCVBUF, (const char *)&conf->recv_buffer_size, sizeof(int)) == -1) { ap_log_rerror(APLOG_MARK, APLOG_ERR, r, "setsockopt(SO_RCVBUF): Failed to set ProxyReceiveBufferSize, using default"); } } i = ap_proxy_doconnect(sock, res->ai_addr, r); if (i == 0) break; ap_pclosesocket(p, sock); } freeaddrinfo(res0); if (i == -1) { if (proxyhost != NULL) return DECLINED; /* try again another way */ else return ap_proxyerror(r, HTTP_BAD_GATEWAY, ap_pstrcat(r->pool, "Could not connect to remote machine: ", strerror(errno), NULL)); } /* record request_time for HTTP/1.1 age calculation */ c->req_time = time(NULL); /* * build upstream-request headers by stripping r->headers_in from * connection specific headers. We must not remove the Connection: header * from r->headers_in, we still have to react to Connection: close */ req_hdrs = ap_copy_table(r->pool, r->headers_in); ap_proxy_clear_connection(r->pool, req_hdrs); /* * At this point, we start sending the HTTP/1.1 request to the remote * server (proxy or otherwise). */ f = ap_bcreate(p, B_RDWR | B_SOCKET); ap_bpushfd(f, sock, sock); { char *errmsg = NULL; ap_hook_use("ap::mod_proxy::http::handler::new_connection", AP_HOOK_SIG4(ptr,ptr,ptr,ptr), AP_HOOK_DECLINE(NULL), &errmsg, r, f, peer); if (errmsg != NULL) return ap_proxyerror(r, HTTP_BAD_GATEWAY, errmsg); } ap_hard_timeout("proxy send", r); ap_bvputs(f, r->method, " ", proxyhost ? url : urlptr, " HTTP/1.1" CRLF, NULL); { int rc = DECLINED; ap_hook_use("ap::mod_proxy::http::handler::write_host_header", AP_HOOK_SIG6(int,ptr,ptr,ptr,ptr,ptr), AP_HOOK_DECLINE(DECLINED), &rc, r, f, desthost, destportstr, destportstr); if (rc == DECLINED) { destportstrtonum = strtonum(destportstr, 0, 65535, &errstr); if (errstr) errx(1, "The destination port is %s: %s", errstr, destportstr); if (destportstr != NULL && destportstrtonum != destport) ap_bvputs(f, "Host: ", desthost, ":", destportstr, CRLF, NULL); else ap_bvputs(f, "Host: ", desthost, CRLF, NULL); } } if (conf->viaopt == via_block) { /* Block all outgoing Via: headers */ ap_table_unset(req_hdrs, "Via"); } else if (conf->viaopt != via_off) { /* Create a "Via:" request header entry and merge it */ i = ap_get_server_port(r); if (ap_is_default_port(i, r)) { strlcpy(portstr, "", sizeof(portstr)); } else { ap_snprintf(portstr, sizeof portstr, ":%d", i); } /* Generate outgoing Via: header with/without server comment: */ ap_table_mergen(req_hdrs, "Via", (conf->viaopt == via_full) ? ap_psprintf(p, "%d.%d %s%s (%s)", HTTP_VERSION_MAJOR(r->proto_num), HTTP_VERSION_MINOR(r->proto_num), ap_get_server_name(r), portstr, SERVER_BASEVERSION) : ap_psprintf(p, "%d.%d %s%s", HTTP_VERSION_MAJOR(r->proto_num), HTTP_VERSION_MINOR(r->proto_num), ap_get_server_name(r), portstr) ); } /* the X-* headers are only added if we are a reverse * proxy, otherwise we would be giving away private information. */ if (r->proxyreq == PROXY_PASS) { const char *buf; /* * Add X-Forwarded-For: so that the upstream has a chance to determine, * where the original request came from. */ ap_table_mergen(req_hdrs, "X-Forwarded-For", r->connection->remote_ip); /* Add X-Forwarded-Host: so that upstream knows what the * original request hostname was. */ if ((buf = ap_table_get(r->headers_in, "Host"))) { ap_table_mergen(req_hdrs, "X-Forwarded-Host", buf); } /* Add X-Forwarded-Server: so that upstream knows what the * name of this proxy server is (if there are more than one) * XXX: This duplicates Via: - do we strictly need it? */ ap_table_mergen(req_hdrs, "X-Forwarded-Server", r->server->server_hostname); } /* we don't yet support keepalives - but we will soon, I promise! */ ap_table_set(req_hdrs, "Connection", "close"); reqhdrs_arr = ap_table_elts(req_hdrs); reqhdrs_elts = (table_entry *)reqhdrs_arr->elts; for (i = 0; i < reqhdrs_arr->nelts; i++) { if (reqhdrs_elts[i].key == NULL || reqhdrs_elts[i].val == NULL /* * Clear out hop-by-hop request headers not to send: RFC2616 13.5.1 * says we should strip these headers: */ || !strcasecmp(reqhdrs_elts[i].key, "Host") /* Already sent */ || !strcasecmp(reqhdrs_elts[i].key, "Keep-Alive") || !strcasecmp(reqhdrs_elts[i].key, "TE") || !strcasecmp(reqhdrs_elts[i].key, "Trailer") || !strcasecmp(reqhdrs_elts[i].key, "Transfer-Encoding") || !strcasecmp(reqhdrs_elts[i].key, "Upgrade") /* * XXX: @@@ FIXME: "Proxy-Authorization" should *only* be suppressed * if THIS server requested the authentication, not when a frontend * proxy requested it! * * The solution to this problem is probably to strip out the * Proxy-Authorisation header in the authorisation code itself, not * here. This saves us having to signal somehow whether this request * was authenticated or not. */ || !strcasecmp(reqhdrs_elts[i].key, "Proxy-Authorization")) continue; ap_bvputs(f, reqhdrs_elts[i].key, ": ", reqhdrs_elts[i].val, CRLF, NULL); } /* the obligatory empty line to mark the end of the headers */ ap_bputs(CRLF, f); /* and flush the above away */ ap_bflush(f); /* and kill the send timeout */ ap_kill_timeout(r); /* read the request data, and pass it to the backend. * we might encounter a stray 100-continue reponse from a PUT or POST, * if this happens we ignore the 100 continue status line and read the * response again. */ { /* send the request data, if any. */ ap_hard_timeout("proxy receive request data", r); if (ap_should_client_block(r)) { while ((i = ap_get_client_block(r, buffer, sizeof buffer)) > 0) { ap_reset_timeout(r); ap_bwrite(f, buffer, i); } } ap_bflush(f); ap_kill_timeout(r); /* then, read a response line */ ap_hard_timeout("proxy receive response status line", r); result = ap_proxy_read_response_line(f, r, buffer, sizeof(buffer)-1, &backasswards, &major, &minor); ap_kill_timeout(r); /* trap any errors */ if (result != OK) { ap_bclose(f); return result; } /* if this response was 100-continue, a stray response has been caught. * read the line again for the real response */ if (r->status == 100) { ap_hard_timeout("proxy receive response status line", r); result = ap_proxy_read_response_line(f, r, buffer, sizeof(buffer)-1, &backasswards, &major, &minor); ap_kill_timeout(r); /* trap any errors */ if (result != OK) { ap_bclose(f); return result; } } } /* * We have our response status line from the convoluted code above, * now we read the headers to continue. */ ap_hard_timeout("proxy receive response headers", r); /* * Is it an HTTP/1 response? Do some sanity checks on the response. (This * is buggy if we ever see an HTTP/1.10) */ if (backasswards == 0) { /* read the response headers. */ /* N.B. for HTTP/1.0 clients, we have to fold line-wrapped headers */ /* Also, take care with headers with multiple occurences. */ resp_hdrs = ap_proxy_read_headers(r, buffer, sizeof(buffer), f); if (resp_hdrs == NULL) { ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_NOERRNO, r->server, "proxy: Bad HTTP/%d.%d header returned by %s (%s)", major, minor, r->uri, r->method); resp_hdrs = ap_make_table(p, 20); nocache = 1; /* do not cache this broken file */ } /* handle Via header in the response */ if (conf->viaopt != via_off && conf->viaopt != via_block) { /* Create a "Via:" response header entry and merge it */ i = ap_get_server_port(r); if (ap_is_default_port(i, r)) { strlcpy(portstr, "", sizeof(portstr)); } else { ap_snprintf(portstr, sizeof portstr, ":%d", i); } ap_table_mergen((table *)resp_hdrs, "Via", (conf->viaopt == via_full) ? ap_psprintf(p, "%d.%d %s%s (%s)", major, minor, ap_get_server_name(r), portstr, SERVER_BASEVERSION) : ap_psprintf(p, "%d.%d %s%s", major, minor, ap_get_server_name(r), portstr) ); } /* is this content chunked? */ chunked = ap_find_last_token(r->pool, ap_table_get(resp_hdrs, "Transfer-Encoding"), "chunked"); /* strip hop-by-hop headers defined by Connection and RFC2616 */ ap_proxy_clear_connection(p, resp_hdrs); content_length = ap_table_get(resp_hdrs, "Content-Length"); if (content_length != NULL) { c->len = ap_strtol(content_length, NULL, 10); if (c->len < 0) { ap_kill_timeout(r); return ap_proxyerror(r, HTTP_BAD_GATEWAY, ap_pstrcat(r->pool, "Invalid Content-Length from remote server", NULL)); } } } else { /* an http/0.9 response */ /* no headers */ resp_hdrs = ap_make_table(p, 20); } ap_kill_timeout(r); /* * HTTP/1.1 requires us to accept 3 types of dates, but only generate one * type */ /* * we SET the dates here, obliterating possible multiple dates, as only * one of each date makes sense in each response. */ if ((datestr = ap_table_get(resp_hdrs, "Date")) != NULL) ap_table_set(resp_hdrs, "Date", ap_proxy_date_canon(p, datestr)); if ((datestr = ap_table_get(resp_hdrs, "Last-Modified")) != NULL) ap_table_set(resp_hdrs, "Last-Modified", ap_proxy_date_canon(p, datestr)); if ((datestr = ap_table_get(resp_hdrs, "Expires")) != NULL) ap_table_set(resp_hdrs, "Expires", ap_proxy_date_canon(p, datestr)); /* handle the ProxyPassReverse mappings */ if ((urlstr = ap_table_get(resp_hdrs, "Location")) != NULL) ap_table_set(resp_hdrs, "Location", proxy_location_reverse_map(r, urlstr)); if ((urlstr = ap_table_get(resp_hdrs, "URI")) != NULL) ap_table_set(resp_hdrs, "URI", proxy_location_reverse_map(r, urlstr)); if ((urlstr = ap_table_get(resp_hdrs, "Content-Location")) != NULL) ap_table_set(resp_hdrs, "Content-Location", proxy_location_reverse_map(r, urlstr)); /* check if NoCache directive on this host */ { struct sockaddr_in *sin; struct sockaddr_in6 *sin6; if (nocache == 0) { for (i = 0; i < conf->nocaches->nelts; i++) { if (ncent[i].name != NULL && (ncent[i].name[0] == '*' || strstr(desthost, ncent[i].name) != NULL)) { nocache = 1; break; } switch (res->ai_addr->sa_family) { case AF_INET: sin = (struct sockaddr_in *)res->ai_addr; if (sin->sin_addr.s_addr == ncent[i].addr.s_addr) { nocache = 1; break; } } } /* update the cache file, possibly even fulfilling the request if * it turns out a conditional allowed us to serve the object from the * cache... */ i = ap_proxy_cache_update(c, resp_hdrs, !backasswards, nocache); if (i != DECLINED) { ap_bclose(f); return i; } /* write status line and headers to the cache file */ ap_proxy_write_headers(c, ap_pstrcat(p, "HTTP/1.1 ", r->status_line, NULL), resp_hdrs); } } /* Setup the headers for our client from upstreams response-headers */ ap_proxy_table_replace(r->headers_out, resp_hdrs); /* Add X-Cache header - be careful not to obliterate any upstream headers */ ap_table_mergen(r->headers_out, "X-Cache", ap_pstrcat(r->pool, "MISS from ", ap_get_server_name(r), NULL)); /* The Content-Type of this response is the upstream one. */ r->content_type = ap_table_get(r->headers_out, "Content-Type"); ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "Content-Type: %s", r->content_type); /* finally output the headers to the client */ ap_send_http_header(r); /* * Is it an HTTP/0.9 respose? If so, send the extra data we read from * upstream as the start of the reponse to client */ /* FIXME: This code is broken: we try and write a buffer and length that * were never intelligently initialised. Rather have a bit of broken protocol * handling for now than broken code. */ /* if (backasswards) { ap_hard_timeout("proxy send assbackward", r); ap_bwrite(r->connection->client, buffer, len); if (c != NULL && c->fp != NULL && ap_bwrite(c->fp, buffer, len) != len) { ap_log_rerror(APLOG_MARK, APLOG_ERR, c->req, "proxy: error writing extra data to %s", c->tempfile); c = ap_proxy_cache_error(c); } ap_kill_timeout(r); } */ /* send body */ /* if header only, then cache will be NULL */ /* HTTP/1.0 tells us to read to EOF, rather than content-length bytes */ /* XXX CHANGEME: We want to eventually support keepalives, which means * we must read content-length bytes... */ if (!r->header_only) { /* we need to set this for ap_proxy_send_fb()... */ c->cache_completion = conf->cache.cache_completion; /* XXX CHECKME: c->len should be the expected content length, or -1 if the * content length is not known. We need to make 100% sure c->len is always * set correctly before we get here to correctly do keepalive. */ ap_proxy_send_fb(f, r, c, c->len, 0, chunked, conf->io_buffer_size); } /* ap_proxy_send_fb() closes the socket f for us */ ap_proxy_cache_tidy(c); ap_proxy_garbage_coll(r); return OK; }
/* * 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; }