Example #1
0
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;
}
Example #2
0
/*
   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;
}