static apr_status_t ajp_unmarshal_response(ajp_msg_t *msg, request_rec *r, proxy_dir_conf *dconf) { apr_uint16_t status; apr_status_t rc; const char *ptr; apr_uint16_t num_headers; int i; rc = ajp_msg_get_uint16(msg, &status); if (rc != APR_SUCCESS) { ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00983) "ajp_unmarshal_response: Null status"); return rc; } r->status = status; rc = ajp_msg_get_string(msg, &ptr); if (rc == APR_SUCCESS) { #if APR_CHARSET_EBCDIC /* copy only if we have to */ ptr = apr_pstrdup(r->pool, ptr); ap_xlate_proto_from_ascii(ptr, strlen(ptr)); #endif r->status_line = apr_psprintf(r->pool, "%d %s", status, ptr); } else { r->status_line = NULL; } ap_log_rerror(APLOG_MARK, APLOG_TRACE4, 0, r, "ajp_unmarshal_response: status = %d", status); rc = ajp_msg_get_uint16(msg, &num_headers); if (rc == APR_SUCCESS) { apr_table_t *save_table; /* First, tuck away all already existing cookies */ /* * Could optimize here, but just in case we want to * also save other headers, keep this logic. */ save_table = apr_table_make(r->pool, num_headers + 2); apr_table_do(addit_dammit, save_table, r->headers_out, "Set-Cookie", NULL); r->headers_out = save_table; } else { r->headers_out = NULL; num_headers = 0; } ap_log_rerror(APLOG_MARK, APLOG_TRACE4, 0, r, "ajp_unmarshal_response: Number of headers is = %d", num_headers); for(i = 0 ; i < (int) num_headers ; i++) { apr_uint16_t name; const char *stringname; const char *value; rc = ajp_msg_peek_uint16(msg, &name); if (rc != APR_SUCCESS) { return rc; } if ((name & 0XFF00) == 0XA000) { ajp_msg_get_uint16(msg, &name); stringname = long_res_header_for_sc(name); if (stringname == NULL) { ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00984) "ajp_unmarshal_response: " "No such sc (%08x)", name); return AJP_EBAD_HEADER; } } else { name = 0; rc = ajp_msg_get_string(msg, &stringname); if (rc != APR_SUCCESS) { ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00985) "ajp_unmarshal_response: " "Null header name"); return rc; } ap_xlate_proto_from_ascii(stringname, strlen(stringname)); } rc = ajp_msg_get_string(msg, &value); if (rc != APR_SUCCESS) { ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00986) "ajp_unmarshal_response: " "Null header value"); return rc; } /* Set-Cookie need additional processing */ if (!strcasecmp(stringname, "Set-Cookie")) { value = ap_proxy_cookie_reverse_map(r, dconf, value); } /* Location, Content-Location, URI and Destination need additional * processing */ else if (!strcasecmp(stringname, "Location") || !strcasecmp(stringname, "Content-Location") || !strcasecmp(stringname, "URI") || !strcasecmp(stringname, "Destination")) { value = ap_proxy_location_reverse_map(r, dconf, value); } ap_xlate_proto_from_ascii(value, strlen(value)); ap_log_rerror(APLOG_MARK, APLOG_TRACE5, 0, r, "ajp_unmarshal_response: Header[%d] [%s] = [%s]", i, stringname, value); apr_table_add(r->headers_out, stringname, value); /* Content-type needs an additional handling */ if (strcasecmp(stringname, "Content-Type") == 0) { /* add corresponding filter */ ap_set_content_type(r, apr_pstrdup(r->pool, value)); ap_log_rerror(APLOG_MARK, APLOG_TRACE5, 0, r, "ajp_unmarshal_response: ap_set_content_type to '%s'", value); } } return APR_SUCCESS; }
/* AJPV13_RESPONSE/AJPV14_RESPONSE:= response_prefix (2) status (short) status_msg (short) num_headers (short) num_headers*(res_header_name header_value) *body_chunk terminator boolean <! -- recycle connection or not --> req_header_name := sc_req_header_name | (string) res_header_name := sc_res_header_name | (string) header_value := (string) body_chunk := length (short) body length*(var binary) */ ngx_int_t ajp_unmarshal_response(ajp_msg_t *msg, ngx_http_request_t *r, ngx_http_ajp_loc_conf_t *alcf) { int i; u_char line[1024], *last; uint16_t status; uint16_t name; uint16_t num_headers; ngx_int_t rc; ngx_str_t str; ngx_log_t *log; ngx_table_elt_t *h; ngx_http_upstream_t *u; ngx_http_upstream_header_t *hh; ngx_http_upstream_main_conf_t *umcf; log = r->connection->log; umcf = ngx_http_get_module_main_conf(r, ngx_http_upstream_module); u = r->upstream; ngx_log_debug0(NGX_LOG_DEBUG_HTTP, log, 0, "ajp_unmarshal_response"); rc = ajp_msg_get_uint16(msg, &status); if (rc != NGX_OK) { return rc; } u->headers_in.status_n = status; ngx_log_debug1(NGX_LOG_DEBUG_HTTP, log, 0, "ajp_unmarshal_response: status = %d", status); rc = ajp_msg_get_string(msg, &str); if (rc == NGX_OK) { if (str.len > 0) { last = ngx_snprintf(line, 1024, "%d %V", status, &str); str.data = line; str.len = last - line; u->headers_in.status_line.data = ngx_pstrdup(r->pool, &str); u->headers_in.status_line.len = str.len; } else { u->headers_in.status_line.data = NULL; u->headers_in.status_line.len = 0; } } else { return rc; } ngx_log_debug1(NGX_LOG_DEBUG_HTTP, log, 0, "ajp_unmarshal_response: status_line = \"%V\"", &u->headers_in.status_line); if (u->state) { u->state->status = u->headers_in.status_n; } num_headers = 0; rc = ajp_msg_get_uint16(msg, &num_headers); if (rc != NGX_OK) { return rc; } ngx_log_debug1(NGX_LOG_DEBUG_HTTP, log, 0, "ajp_unmarshal_response: Number of headers is = %d", num_headers); for(i = 0 ; i < (int) num_headers ; i++) { rc = ajp_msg_peek_uint16(msg, &name); if (rc != NGX_OK) { return rc; } /* a header line has been parsed successfully */ h = ngx_list_push(&u->headers_in.headers); if (h == NULL) { return NGX_ERROR; } if ((name & 0XFF00) == 0XA000) { ajp_msg_get_uint16(msg, &name); ngx_log_debug1(NGX_LOG_DEBUG_HTTP, log, 0, "http ajp known header: %08Xd", name); rc = get_res_header_for_sc(name, h); if (rc != NGX_OK) { ngx_log_error(NGX_LOG_ERR, log, 0, "ajp_unmarshal_response: No such sc (%08Xd)", name); return NGX_ERROR; } } else { name = 0; rc = ajp_msg_get_string(msg, &str); if (rc != NGX_OK) { if (rc != AJP_EOVERFLOW) { ngx_log_error(NGX_LOG_ERR, log, 0, "ajp_unmarshal_response: Null header name"); } return rc; } ngx_log_debug1(NGX_LOG_DEBUG_HTTP, log, 0, "http ajp unknown header: %V", &str); rc = get_res_unknown_header_by_str(&str, h, r->pool); if (rc != NGX_OK) { return rc; } } rc = ajp_msg_get_string(msg, &h->value); if (rc != NGX_OK) { if (rc != AJP_EOVERFLOW) { ngx_log_error(NGX_LOG_ERR, log, 0, "ajp_unmarshal_response: Null header value"); } return rc; } hh = ngx_hash_find(&umcf->headers_in_hash, h->hash, h->lowcase_key, h->key.len); if (hh && hh->handler(r, h, hh->offset) != NGX_OK) { ngx_log_error(NGX_LOG_ERR, log, 0, "ajp_unmarshal_response: hh->handler error: \"%V: %V\"", &h->key, &h->value); return NGX_ERROR; } ngx_log_debug2(NGX_LOG_DEBUG_HTTP, log, 0, "http ajp header: \"%V: %V\"", &h->key, &h->value); } return NGX_OK; }