You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@httpd.apache.org by gr...@apache.org on 2002/08/13 16:27:39 UTC

cvs commit: httpd-2.0/server protocol.c

gregames    2002/08/13 07:27:39

  Modified:    modules/http http_protocol.c http_request.c
               server   protocol.c
  Log:
  fix weird things that happen with canned error messages due to using two
  different request_recs after an ErrorDocument internal redirect failure.
  examples: wrong Content-Type, garbled output from ebcdic servers due to
  double charset translation
  
  Revision  Changes    Path
  1.454     +5 -15     httpd-2.0/modules/http/http_protocol.c
  
  Index: http_protocol.c
  ===================================================================
  RCS file: /home/cvs/httpd-2.0/modules/http/http_protocol.c,v
  retrieving revision 1.453
  retrieving revision 1.454
  diff -u -r1.453 -r1.454
  --- http_protocol.c	8 Aug 2002 20:39:15 -0000	1.453
  +++ http_protocol.c	13 Aug 2002 14:27:39 -0000	1.454
  @@ -2301,16 +2301,6 @@
           const char *title = status_lines[idx];
           const char *h1;
   
  -        /* XXX This is a major hack that should be fixed cleanly.  The
  -         * problem is that we have the information we need in a previous
  -         * request, but the text of the page must be sent down the last
  -         * request_rec's filter stack.  rbb
  -         */
  -        request_rec *rlast = r;
  -        while (rlast->next) {
  -            rlast = rlast->next;
  -        }
  -
           /* Accept a status_line set by a module, but only if it begins
            * with the 3 digit status code
            */
  @@ -2331,24 +2321,24 @@
            * so do ebcdic->ascii translation explicitly (if needed)
            */
   
  -        ap_rvputs_proto_in_ascii(rlast,
  +        ap_rvputs_proto_in_ascii(r,
                     DOCTYPE_HTML_2_0
                     "<html><head>\n<title>", title,
                     "</title>\n</head><body>\n<h1>", h1, "</h1>\n",
                     NULL);
   
  -        ap_rvputs_proto_in_ascii(rlast,
  +        ap_rvputs_proto_in_ascii(r,
                                    get_canned_error_string(status, r, location),
                                    NULL);
   
           if (recursive_error) {
  -            ap_rvputs_proto_in_ascii(rlast, "<p>Additionally, a ",
  +            ap_rvputs_proto_in_ascii(r, "<p>Additionally, a ",
                         status_lines[ap_index_of_response(recursive_error)],
                         "\nerror was encountered while trying to use an "
                         "ErrorDocument to handle the request.</p>\n", NULL);
           }
  -        ap_rvputs_proto_in_ascii(rlast, ap_psignature("<hr />\n", r), NULL);
  -        ap_rvputs_proto_in_ascii(rlast, "</body></html>\n", NULL);
  +        ap_rvputs_proto_in_ascii(r, ap_psignature("<hr />\n", r), NULL);
  +        ap_rvputs_proto_in_ascii(r, "</body></html>\n", NULL);
       }
       ap_finalize_request_protocol(r);
   }
  
  
  
  1.152     +35 -32    httpd-2.0/modules/http/http_request.c
  
  Index: http_request.c
  ===================================================================
  RCS file: /home/cvs/httpd-2.0/modules/http/http_request.c,v
  retrieving revision 1.151
  retrieving revision 1.152
  diff -u -r1.151 -r1.152
  --- http_request.c	27 Jun 2002 04:40:47 -0000	1.151
  +++ http_request.c	13 Aug 2002 14:27:39 -0000	1.152
  @@ -96,6 +96,23 @@
    * Mainline request processing...
    */
   
  +/* XXX A cleaner and faster way to do this might be to pass the request_rec 
  + * down the filter chain as a parameter.  It would need to change for 
  + * subrequest vs. main request filters; perhaps the subrequest filter could 
  + * make the switch.
  + */
  +static void update_r_in_filters(ap_filter_t *f, 
  +                                request_rec *from,
  +                                request_rec *to)
  +{
  +    while (f) {
  +        if (f->r == from) {
  +            f->r = to;
  +        }
  +        f = f->next;
  +    }
  +}
  +
   AP_DECLARE(void) ap_die(int type, request_rec *r)
   {
       int error_index = ap_index_of_response(type);
  @@ -124,6 +141,20 @@
           while (r_1st_err->prev && (r_1st_err->prev->status != HTTP_OK))
               r_1st_err = r_1st_err->prev;  /* Get back to original error */
   
  +        if (r_1st_err != r) {
  +            /* The recursive error was caused by an ErrorDocument specifying
  +             * an internal redirect to a bad URI.  ap_internal_redirect has
  +             * changed the filter chains to point to the ErrorDocument's 
  +             * request_rec.  Back out those changes so we can safely use the 
  +             * original failing request_rec to send the canned error message.
  +             *
  +             * ap_send_error_response gets rid of existing resource filters
  +             * on the output side, so we can skip those.
  +             */
  +            update_r_in_filters(r_1st_err->proto_output_filters, r, r_1st_err);
  +            update_r_in_filters(r_1st_err->input_filters, r, r_1st_err);
  +        }
  +
           custom_response = NULL; /* Do NOT retry the custom thing! */
       }
   
  @@ -301,7 +332,6 @@
   static request_rec *internal_internal_redirect(const char *new_uri,
                                                  request_rec *r) {
       int access_status;
  -    ap_filter_t *f;
       request_rec *new = (request_rec *) apr_pcalloc(r->pool,
                                                      sizeof(request_rec));
   
  @@ -367,21 +397,8 @@
       new->output_filters  = new->proto_output_filters;
       new->input_filters   = new->proto_input_filters;
   
  -    f = new->input_filters;
  -    while (f) {
  -        if (f->r == r) {
  -            f->r = new;
  -        }
  -        f = f->next;
  -    }
  -
  -    f = new->output_filters;
  -    while (f) {
  -        if (f->r == r) {
  -            f->r = new;
  -        }
  -        f = f->next;
  -    }
  +    update_r_in_filters(new->input_filters, r, new);
  +    update_r_in_filters(new->output_filters, r, new);
   
       apr_table_setn(new->subprocess_env, "REDIRECT_STATUS",
                      apr_itoa(r->pool, r->status));
  @@ -402,8 +419,6 @@
   /* XXX: Is this function is so bogus and fragile that we deep-6 it? */
   AP_DECLARE(void) ap_internal_fast_redirect(request_rec *rr, request_rec *r)
   {
  -    ap_filter_t *filters;
  -
       /* We need to tell POOL_DEBUG that we're guaranteeing that rr->pool
        * will exist as long as r->pool.  Otherwise we run into troubles because
        * some values in this request will be allocated in r->pool, and others in
  @@ -449,20 +464,8 @@
        * their f->r structure when it is pointing to rr, the real request_rec
        * will not get updated.  Fix that here.
        */
  -    filters = r->input_filters;
  -    while (filters) {
  -        if (filters->r == rr) {
  -            filters->r = r;
  -        } 
  -        filters = filters->next;
  -    }
  -    filters = r->output_filters;
  -    while (filters) {
  -        if (filters->r == rr) {
  -            filters->r = r;
  -        } 
  -        filters = filters->next;
  -    }
  +    update_r_in_filters(r->input_filters, rr, r);
  +    update_r_in_filters(r->output_filters, rr, r);
   }
   
   AP_DECLARE(void) ap_internal_redirect(const char *new_uri, request_rec *r)
  
  
  
  1.115     +0 -4      httpd-2.0/server/protocol.c
  
  Index: protocol.c
  ===================================================================
  RCS file: /home/cvs/httpd-2.0/server/protocol.c,v
  retrieving revision 1.114
  retrieving revision 1.115
  diff -u -r1.114 -r1.115
  --- protocol.c	17 Jul 2002 13:50:26 -0000	1.114
  +++ protocol.c	13 Aug 2002 14:27:39 -0000	1.115
  @@ -1101,10 +1101,6 @@
   {
       (void) ap_discard_request_body(r);
   
  -    while (r->next) {
  -        r = r->next;
  -    }
  -
       /* tell the filter chain there is no more content coming */
       if (!r->eos_sent) {
           end_output_stream(r);