bool qEnvApache::AppendHeader(const char *str, const char *val) { if (!IsFlushed()) { ap_table_add(GetRequest()->headers_out, str, val); if (!stricmp(str,"set-cookie")) ap_table_add(GetRequest()->err_headers_out, str, val); return true; } return false; }
static void do_set_header( void *_c, const char *key, const char *value, bool add ) { mcontext *c = (mcontext*)_c; if( add ) ap_table_add(c->r->headers_out,key,value); else if( strcmpi(key,"Content-Type") == 0 ) { int len = (int)strlen(value); char *ct = (char*)ap_palloc(c->r->pool,len+1); memcpy(ct,value,len+1); c->r->content_type = ct; } else ap_table_set(c->r->headers_out,key,value); }
/** set_cookie : name:string -> val:string -> void <doc>Set a cookie</doc> **/ static value set_cookie( value name, value v ) { mcontext *c = CONTEXT(); buffer b; value str; val_check(name,string); val_check(v,string); HEADERS_NOT_SENT("Cookie"); b = alloc_buffer(NULL); val_buffer(b,name); buffer_append(b,"="); val_buffer(b,v); buffer_append(b,";"); str = buffer_to_string(b); ap_table_add(c->r->headers_out,"Set-Cookie",val_string(str)); return val_true; }
static void split_to_parms(ApacheRequest *req, const char *data) { request_rec *r = req->r; const char *val; while (*data && (val = my_urlword(r->pool, &data))) { const char *key = ap_getword(r->pool, &val, '='); req_plustospace((char*)key); ap_unescape_url((char*)key); req_plustospace((char*)val); ap_unescape_url((char*)val); ap_table_add(req->parms, key, val); } }
int ApacheRequest_parse_multipart(ApacheRequest *req) { request_rec *r = req->r; int rc = OK; const char *ct = ap_table_get(r->headers_in, "Content-Type"); long length; char *boundary; multipart_buffer *mbuff; ApacheUpload *upload = NULL; if (!ct) { ap_log_rerror(REQ_ERROR, "[libapreq] no Content-type header!"); return HTTP_INTERNAL_SERVER_ERROR; } if ((rc = ap_setup_client_block(r, REQUEST_CHUNKED_ERROR))) { return rc; } if (!ap_should_client_block(r)) { return rc; } if ((length = r->remaining) > req->post_max && req->post_max > 0) { ap_log_rerror(REQ_ERROR, "[libapreq] entity too large (%d, max=%d)", (int)length, req->post_max); return HTTP_REQUEST_ENTITY_TOO_LARGE; } (void)ap_getword(r->pool, &ct, '='); boundary = ap_getword_conf(r->pool, &ct); if (!(mbuff = multipart_buffer_new(boundary, length, r))) { return DECLINED; } while (!multipart_buffer_eof(mbuff)) { table *header = multipart_buffer_headers(mbuff); const char *cd, *param=NULL, *filename=NULL; char buff[FILLUNIT]; int blen, wlen; if (!header) { #ifdef DEBUG ap_log_rerror(REQ_ERROR, "[libapreq] silently drop remaining '%ld' bytes", r->remaining); #endif ap_hard_timeout("[libapreq] parse_multipart", r); while ( ap_get_client_block(r, buff, sizeof(buff)) > 0 ) /* wait for more input to ignore */ ; ap_kill_timeout(r); return OK; } if ((cd = ap_table_get(header, "Content-Disposition"))) { const char *pair; while (*cd && (pair = ap_getword(r->pool, &cd, ';'))) { const char *key; while (ap_isspace(*cd)) { ++cd; } if (ap_ind(pair, '=')) { key = ap_getword(r->pool, &pair, '='); if(strEQ(key, "name")) { param = ap_getword_conf(r->pool, &pair); } else if(strEQ(key, "filename")) { filename = ap_getword_conf(r->pool, &pair); } } } if (!filename) { char *value = multipart_buffer_read_body(mbuff); ap_table_add(req->parms, param, value); continue; } if (!param) continue; /* shouldn't happen, but just in case. */ if (req->disable_uploads) { ap_log_rerror(REQ_ERROR, "[libapreq] file upload forbidden"); return HTTP_FORBIDDEN; } ap_table_add(req->parms, param, filename); if (upload) { upload->next = ApacheUpload_new(req); upload = upload->next; } else { upload = ApacheUpload_new(req); req->upload = upload; } if (! req->upload_hook && ! ApacheRequest_tmpfile(req, upload) ) { return HTTP_INTERNAL_SERVER_ERROR; } upload->info = header; upload->filename = ap_pstrdup(req->r->pool, filename); upload->name = ap_pstrdup(req->r->pool, param); /* mozilla empty-file (missing CRLF) hack */ fill_buffer(mbuff); if( strEQN(mbuff->buf_begin, mbuff->boundary, strlen(mbuff->boundary)) ) { r->remaining -= 2; continue; } while ((blen = multipart_buffer_read(mbuff, buff, sizeof(buff)))) { if (req->upload_hook != NULL) { wlen = req->upload_hook(req->hook_data, buff, blen, upload); } else { wlen = fwrite(buff, 1, blen, upload->fp); } if (wlen != blen) { return HTTP_INTERNAL_SERVER_ERROR; } upload->size += wlen; } if (upload->size > 0 && (upload->fp != NULL)) { fseek(upload->fp, 0, 0); } } } return OK; }
/* ==================================================================== * Here's the PSP Handler. * ==================================================================== */ static int psp_handler(request_rec *r) { ap_table_add(r->subprocess_env, "WK_ABSOLUTE", "1"); return content_handler(r); }
static am_status_t set_header(char *key, char *values, void **args) { request_rec *r = (request_rec *)args[0]; ap_table_add(r->headers_in, key, values); return (AM_SUCCESS); }
API_EXPORT(int) ap_scan_script_header_err_core(request_rec *r, char *buffer, int (*getsfunc) (char *, int, void *), void *getsfunc_data) { char x[MAX_STRING_LEN]; char *w, *l; int p; int cgi_status = HTTP_OK; table *merge; table *cookie_table; if (buffer) { *buffer = '\0'; } w = buffer ? buffer : x; ap_hard_timeout("read script header", r); /* temporary place to hold headers to merge in later */ merge = ap_make_table(r->pool, 10); /* The HTTP specification says that it is legal to merge duplicate * headers into one. Some browsers that support Cookies don't like * merged headers and prefer that each Set-Cookie header is sent * separately. Lets humour those browsers by not merging. * Oh what a pain it is. */ cookie_table = ap_make_table(r->pool, 2); ap_table_do(set_cookie_doo_doo, cookie_table, r->err_headers_out, "Set-Cookie", NULL); while (1) { if ((*getsfunc) (w, MAX_STRING_LEN - 1, getsfunc_data) == 0) { ap_kill_timeout(r); ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r, "Premature end of script headers: %s", r->filename); return HTTP_INTERNAL_SERVER_ERROR; } /* Delete terminal (CR?)LF */ p = strlen(w); /* Indeed, the host's '\n': '\012' for UNIX; '\015' for MacOS; '\025' for OS/390 -- whatever the script generates. */ if (p > 0 && w[p - 1] == '\n') { if (p > 1 && w[p - 2] == CR) { w[p - 2] = '\0'; } else { w[p - 1] = '\0'; } } /* * If we've finished reading the headers, check to make sure any * HTTP/1.1 conditions are met. If so, we're done; normal processing * will handle the script's output. If not, just return the error. * The appropriate thing to do would be to send the script process a * SIGPIPE to let it know we're ignoring it, close the channel to the * script process, and *then* return the failed-to-meet-condition * error. Otherwise we'd be waiting for the script to finish * blithering before telling the client the output was no good. * However, we don't have the information to do that, so we have to * leave it to an upper layer. */ if (w[0] == '\0') { int cond_status = OK; ap_kill_timeout(r); if ((cgi_status == HTTP_OK) && (r->method_number == M_GET)) { cond_status = ap_meets_conditions(r); } ap_overlap_tables(r->err_headers_out, merge, AP_OVERLAP_TABLES_MERGE); if (!ap_is_empty_table(cookie_table)) { /* the cookies have already been copied to the cookie_table */ ap_table_unset(r->err_headers_out, "Set-Cookie"); r->err_headers_out = ap_overlay_tables(r->pool, r->err_headers_out, cookie_table); } return cond_status; } /* if we see a bogus header don't ignore it. Shout and scream */ #ifdef CHARSET_EBCDIC /* Chances are that we received an ASCII header text instead of * the expected EBCDIC header lines. Try to auto-detect: */ if (!(l = strchr(w, ':'))) { int maybeASCII = 0, maybeEBCDIC = 0; char *cp; for (cp = w; *cp != '\0'; ++cp) { if (isprint(*cp) && !isprint(os_toebcdic[*cp])) ++maybeEBCDIC; if (!isprint(*cp) && isprint(os_toebcdic[*cp])) ++maybeASCII; } if (maybeASCII > maybeEBCDIC) { ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, "CGI Interface Error: Script headers apparently ASCII: (CGI = %s)", r->filename); ascii2ebcdic(w, w, cp - w); } } #endif if (!(l = strchr(w, ':'))) { char malformed[(sizeof MALFORMED_MESSAGE) + 1 + MALFORMED_HEADER_LENGTH_TO_SHOW]; strcpy(malformed, MALFORMED_MESSAGE); strncat(malformed, w, MALFORMED_HEADER_LENGTH_TO_SHOW); if (!buffer) { /* Soak up all the script output - may save an outright kill */ while ((*getsfunc) (w, MAX_STRING_LEN - 1, getsfunc_data)) { continue; } } ap_kill_timeout(r); ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r, "%s: %s", malformed, r->filename); return HTTP_INTERNAL_SERVER_ERROR; } *l++ = '\0'; while (*l && ap_isspace(*l)) { ++l; } if (!strcasecmp(w, "Content-type")) { char *tmp; /* Nuke trailing whitespace */ char *endp = l + strlen(l) - 1; while (endp > l && ap_isspace(*endp)) { *endp-- = '\0'; } tmp = ap_pstrdup(r->pool, l); ap_content_type_tolower(tmp); r->content_type = tmp; } /* * If the script returned a specific status, that's what * we'll use - otherwise we assume 200 OK. */ else if (!strcasecmp(w, "Status")) { r->status = cgi_status = atoi(l); r->status_line = ap_pstrdup(r->pool, l); } else if (!strcasecmp(w, "Location")) { ap_table_set(r->headers_out, w, l); } else if (!strcasecmp(w, "Content-Length")) { ap_table_set(r->headers_out, w, l); } else if (!strcasecmp(w, "Transfer-Encoding")) { ap_table_set(r->headers_out, w, l); } /* * If the script gave us a Last-Modified header, we can't just * pass it on blindly because of restrictions on future values. */ else if (!strcasecmp(w, "Last-Modified")) { time_t mtime = ap_parseHTTPdate(l); ap_update_mtime(r, mtime); ap_set_last_modified(r); } else if (!strcasecmp(w, "Set-Cookie")) { ap_table_add(cookie_table, w, l); } else { ap_table_add(merge, w, l); } } }
apr_status_t jxr_process_response_headers(request_rec *r, char *buf) { apr_status_t rv = APR_SUCCESS; apr_size_t pos; apr_size_t len; char type; int nHeaders; int i; char name[MAX_STRING_LEN]; char value[MAX_STRING_LEN]; apr_size_t nlen, vlen; table *merge; table *cookie_table; char *w, *l; type = jxr_msg_get_type(buf); len = jxr_msg_get_length(buf, &pos); if (type != BLOCKTYPE_HTTP_HEADER) { // Invalid data compat_log_rerror(APLOG_MARK, APLOG_WARNING, rv, r, "mod_jaxer: invalid data type (%c) received, while expecting a header (%d)", type, BLOCKTYPE_HTTP_HEADER); return HTTP_INTERNAL_SERVER_ERROR; } /* temporary place to hold headers to merge in later */ merge = ap_make_table(r->pool, 10); cookie_table = ap_make_table(r->pool, 2); ap_table_do(set_cookie_doo_doo, cookie_table, r->err_headers_out, "Set-Cookie", NULL); nHeaders = jxr_msg_get_int16(buf, &pos); for (i=0; i<nHeaders; i++) { // Process one header -- name -- val nlen = jxr_msg_get_string(buf, &pos, name); vlen = jxr_msg_get_string(buf, &pos, value); w = name; l = value; if (!strcasecmp(w, "Content-type")) { char *tmp; /* Nuke trailing whitespace */ char *endp = l + strlen(l) - 1; while (endp > l && apr_isspace(*endp)) { *endp-- = '\0'; } tmp = ap_pstrdup(r->pool, l); ap_content_type_tolower(tmp); ap_set_content_type(r, tmp); } else if (!strcasecmp(w, "Status")) { /* * If the server returned a specific status, that's what * we'll use - otherwise we assume 200 OK. */ r->status = atoi(l); r->status_line = ap_pstrdup(r->pool, l); } else if (!strcasecmp(w, "Location")) { ap_table_set(r->headers_out, w, l); } else if (!strcasecmp(w, "Content-Length")) { ap_table_set(r->headers_out, w, l); } else if (!strcasecmp(w, "Content-Range")) { ap_table_set(r->headers_out, w, l); } else if (!strcasecmp(w, "Transfer-Encoding")) { ap_table_set(r->headers_out, w, l); } else if (!strcasecmp(w, "Last-Modified")) { /* * If the script gave us a Last-Modified header, we can't just * pass it on blindly because of restrictions on future values. */ ap_update_mtime(r, apr_date_parse_http(l)); ap_set_last_modified(r); } else if (!strcasecmp(w, "Set-Cookie")) { ap_table_add(cookie_table, w, l); } else { ap_table_add(merge, w, l); } } // now merge stuff ap_overlap_tables(r->err_headers_out, merge, AP_OVERLAP_TABLES_MERGE); if (!ap_is_empty_table(cookie_table)) { /* the cookies have already been copied to the cookie_table */ ap_table_unset(r->err_headers_out, "Set-Cookie"); r->err_headers_out = ap_overlay_tables(r->pool, r->err_headers_out, cookie_table); } return rv; }
/** * 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; }