home *** CD-ROM | disk | FTP | other *** search
/ PC Online 1999 April / PCO0499.ISO / filesbbs / os2 / apach134.arj / APACH134.ZIP / src / main / http_request.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-01-09  |  43.0 KB  |  1,361 lines

  1. /* ====================================================================
  2.  * Copyright (c) 1995-1999 The Apache Group.  All rights reserved.
  3.  *
  4.  * Redistribution and use in source and binary forms, with or without
  5.  * modification, are permitted provided that the following conditions
  6.  * are met:
  7.  *
  8.  * 1. Redistributions of source code must retain the above copyright
  9.  *    notice, this list of conditions and the following disclaimer.
  10.  *
  11.  * 2. Redistributions in binary form must reproduce the above copyright
  12.  *    notice, this list of conditions and the following disclaimer in
  13.  *    the documentation and/or other materials provided with the
  14.  *    distribution.
  15.  *
  16.  * 3. All advertising materials mentioning features or use of this
  17.  *    software must display the following acknowledgment:
  18.  *    "This product includes software developed by the Apache Group
  19.  *    for use in the Apache HTTP server project (http://www.apache.org/)."
  20.  *
  21.  * 4. The names "Apache Server" and "Apache Group" must not be used to
  22.  *    endorse or promote products derived from this software without
  23.  *    prior written permission. For written permission, please contact
  24.  *    apache@apache.org.
  25.  *
  26.  * 5. Products derived from this software may not be called "Apache"
  27.  *    nor may "Apache" appear in their names without prior written
  28.  *    permission of the Apache Group.
  29.  *
  30.  * 6. Redistributions of any form whatsoever must retain the following
  31.  *    acknowledgment:
  32.  *    "This product includes software developed by the Apache Group
  33.  *    for use in the Apache HTTP server project (http://www.apache.org/)."
  34.  *
  35.  * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY
  36.  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  37.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  38.  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE APACHE GROUP OR
  39.  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  40.  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  41.  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  42.  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  43.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  44.  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  45.  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
  46.  * OF THE POSSIBILITY OF SUCH DAMAGE.
  47.  * ====================================================================
  48.  *
  49.  * This software consists of voluntary contributions made by many
  50.  * individuals on behalf of the Apache Group and was originally based
  51.  * on public domain software written at the National Center for
  52.  * Supercomputing Applications, University of Illinois, Urbana-Champaign.
  53.  * For more information on the Apache Group and the Apache HTTP server
  54.  * project, please see <http://www.apache.org/>.
  55.  *
  56.  */
  57.  
  58. /*
  59.  * http_request.c: functions to get and process requests
  60.  *
  61.  * Rob McCool 3/21/93
  62.  *
  63.  * Thoroughly revamped by rst for Apache.  NB this file reads
  64.  * best from the bottom up.
  65.  *
  66.  */
  67.  
  68. #define CORE_PRIVATE
  69. #include "httpd.h"
  70. #include "http_config.h"
  71. #include "http_request.h"
  72. #include "http_core.h"
  73. #include "http_protocol.h"
  74. #include "http_conf_globals.h"    /* for ap_extended_status */
  75. #include "http_log.h"
  76. #include "http_main.h"
  77. #include "scoreboard.h"
  78. #include "fnmatch.h"
  79.  
  80. /*****************************************************************
  81.  *
  82.  * Getting and checking directory configuration.  Also checks the
  83.  * FollowSymlinks and FollowSymOwner stuff, since this is really the
  84.  * only place that can happen (barring a new mid_dir_walk callout).
  85.  *
  86.  * We can't do it as an access_checker module function which gets
  87.  * called with the final per_dir_config, since we could have a directory
  88.  * with FollowSymLinks disabled, which contains a symlink to another
  89.  * with a .htaccess file which turns FollowSymLinks back on --- and
  90.  * access in such a case must be denied.  So, whatever it is that
  91.  * checks FollowSymLinks needs to know the state of the options as
  92.  * they change, all the way down.
  93.  */
  94.  
  95. /*
  96.  * We don't want people able to serve up pipes, or unix sockets, or other
  97.  * scary things.  Note that symlink tests are performed later.
  98.  */
  99. static int check_safe_file(request_rec *r)
  100. {
  101.     if (r->finfo.st_mode == 0         /* doesn't exist */
  102.         || S_ISDIR(r->finfo.st_mode)
  103.         || S_ISREG(r->finfo.st_mode)
  104.         || S_ISLNK(r->finfo.st_mode)) {
  105.         return OK;
  106.     }
  107.     ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
  108.                 "object is not a file, directory or symlink: %s",
  109.                 r->filename);
  110.     return HTTP_FORBIDDEN;
  111. }
  112.  
  113.  
  114. static int check_symlinks(char *d, int opts)
  115. {
  116. #if defined(OS2) || defined(WIN32)
  117.     /* OS/2 doesn't have symlinks */
  118.     return OK;
  119. #else
  120.     struct stat lfi, fi;
  121.     char *lastp;
  122.     int res;
  123.  
  124.     if (opts & OPT_SYM_LINKS)
  125.         return OK;
  126.  
  127.     /*
  128.      * Strip trailing '/', if any, off what we're checking; trailing slashes
  129.      * make some systems follow symlinks to directories even in lstat().
  130.      * After we've done the lstat, put it back.  Also, don't bother checking
  131.      * '/' at all...
  132.      * 
  133.      * Note that we don't have to worry about multiple slashes here because of
  134.      * no2slash() below...
  135.      */
  136.  
  137.     lastp = d + strlen(d) - 1;
  138.     if (lastp == d)
  139.         return OK;              /* Root directory, '/' */
  140.  
  141.     if (*lastp == '/')
  142.         *lastp = '\0';
  143.     else
  144.         lastp = NULL;
  145.  
  146.     res = lstat(d, &lfi);
  147.  
  148.     if (lastp)
  149.         *lastp = '/';
  150.  
  151.     /*
  152.      * Note that we don't reject accesses to nonexistent files (multiviews or
  153.      * the like may cons up a way to run the transaction anyway)...
  154.      */
  155.  
  156.     if (!(res >= 0) || !S_ISLNK(lfi.st_mode))
  157.         return OK;
  158.  
  159.     /* OK, it's a symlink.  May still be OK with OPT_SYM_OWNER */
  160.  
  161.     if (!(opts & OPT_SYM_OWNER))
  162.         return HTTP_FORBIDDEN;
  163.  
  164.     if (stat(d, &fi) < 0)
  165.         return HTTP_FORBIDDEN;
  166.  
  167.     return (fi.st_uid == lfi.st_uid) ? OK : HTTP_FORBIDDEN;
  168.  
  169. #endif
  170. }
  171.  
  172. /* Dealing with the file system to get PATH_INFO
  173.  */
  174. static int get_path_info(request_rec *r)
  175. {
  176.     char *cp;
  177.     char *path = r->filename;
  178.     char *end = &path[strlen(path)];
  179.     char *last_cp = NULL;
  180.     int rv;
  181. #ifdef WIN32
  182.     BOOL bStripSlash=TRUE;
  183. #endif
  184.  
  185.     if (r->finfo.st_mode) {
  186.     /* assume path_info already set */
  187.     return OK;
  188.     }
  189.  
  190. #ifdef WIN32
  191.     /* If the directory is x:\, then we don't want to strip
  192.      * the trailing slash since x: is not a valid directory.
  193.      */
  194.     if (strlen(path) == 3 && path[1] == ':' && path[2] == '/')
  195.         bStripSlash = FALSE;
  196.  
  197.  
  198.     /* If UNC name == //machine/share/, do not 
  199.      * advance over the trailing slash.  Any other
  200.      * UNC name is OK to strip the slash.
  201.      */
  202.     cp = end;
  203.     if (strlen(path) > 2 && path[0] == '/' && path[1] == '/' && 
  204.         path[2] != '/' && cp[-1] == '/') {
  205.         char *p;
  206.         int iCount=0;
  207.         p = path;
  208.         while (p = strchr(p,'/')) {
  209.             p++;
  210.             iCount++;
  211.         }
  212.     
  213.         if (iCount == 4)
  214.             bStripSlash = FALSE;
  215.     }
  216.  
  217.     if (bStripSlash)
  218. #endif
  219.         /* Advance over trailing slashes ... NOT part of filename 
  220.          * if file is not a UNC name (Win32 only).
  221.          */
  222.         for (cp = end; cp > path && cp[-1] == '/'; --cp)
  223.             continue;
  224.  
  225.  
  226.     while (cp > path) {
  227.  
  228.         /* See if the pathname ending here exists... */
  229.  
  230.         *cp = '\0';
  231.  
  232.         /* We must not stat() filenames that may cause os-specific system
  233.          * problems, such as "/file/aux" on DOS-abused filesystems.
  234.          * So pretend that they do not exist by returning an ENOENT error.
  235.          * This will force us to drop that part of the path and keep
  236.          * looking back for a "real" file that exists, while still allowing
  237.          * the "invalid" path parts within the PATH_INFO.
  238.          */
  239.         if (!ap_os_is_filename_valid(path)) {
  240.             errno = ENOENT;
  241.             rv = -1;
  242.         }
  243.         else {
  244.             errno = 0;
  245.             rv = stat(path, &r->finfo);
  246.         }
  247.  
  248.         if (cp != end)
  249.             *cp = '/';
  250.  
  251.         if (!rv) {
  252.  
  253.             /*
  254.              * Aha!  Found something.  If it was a directory, we will search
  255.              * contents of that directory for a multi_match, so the PATH_INFO
  256.              * argument starts with the component after that.
  257.              */
  258.  
  259.             if (S_ISDIR(r->finfo.st_mode) && last_cp) {
  260.                 r->finfo.st_mode = 0;   /* No such file... */
  261.                 cp = last_cp;
  262.             }
  263.  
  264.             r->path_info = ap_pstrdup(r->pool, cp);
  265.             *cp = '\0';
  266.             return OK;
  267.         }
  268. #if defined(ENOENT) && defined(ENOTDIR)
  269.         else if (errno == ENOENT || errno == ENOTDIR) {
  270.             last_cp = cp;
  271.  
  272.             while (--cp > path && *cp != '/')
  273.                 continue;
  274.  
  275.             while (cp > path && cp[-1] == '/')
  276.                 --cp;
  277.         }
  278.         else {
  279. #if defined(EACCES)
  280.             if (errno != EACCES)
  281. #endif
  282.                 ap_log_rerror(APLOG_MARK, APLOG_ERR, r,
  283.                             "access to %s failed", r->uri);
  284.             return HTTP_FORBIDDEN;
  285.         }
  286. #else
  287. #error ENOENT || ENOTDIR not defined; please see the
  288. #error comments at this line in the source for a workaround.
  289.         /*
  290.          * If ENOENT || ENOTDIR is not defined in one of the your OS's
  291.          * include files, Apache does not know how to check to see why the
  292.          * stat() of the index file failed; there are cases where it can fail
  293.          * even though the file exists.  This means that it is possible for
  294.          * someone to get a directory listing of a directory even though
  295.          * there is an index (eg. index.html) file in it.  If you do not have
  296.          * a problem with this, delete the above #error lines and start the
  297.          * compile again.  If you need to do this, please submit a bug report
  298.          * from http://www.apache.org/bug_report.html letting us know that
  299.          * you needed to do this.  Please be sure to include the operating
  300.          * system you are using.
  301.          */
  302.         else {
  303.             last_cp = cp;
  304.  
  305.             while (--cp > path && *cp != '/')
  306.                 continue;
  307.  
  308.             while (cp > path && cp[-1] == '/')
  309.                 --cp;
  310.         }
  311. #endif  /* ENOENT && ENOTDIR */
  312.     }
  313.     return OK;
  314. }
  315.  
  316. static int directory_walk(request_rec *r)
  317. {
  318.     core_server_config *sconf = ap_get_module_config(r->server->module_config,
  319.                                                   &core_module);
  320.     void *per_dir_defaults = r->server->lookup_defaults;
  321.     void **sec = (void **) sconf->sec->elts;
  322.     int num_sec = sconf->sec->nelts;
  323.     char *test_filename;
  324.     char *test_dirname;
  325.     int res;
  326.     unsigned i, num_dirs, iStart;
  327.     int j, test_filename_len;
  328.  
  329.     /*
  330.      * Are we dealing with a file? If not, we can (hopefuly) safely assume we
  331.      * have a handler that doesn't require one, but for safety's sake, and so
  332.      * we have something find_types() can get something out of, fake one. But
  333.      * don't run through the directory entries.
  334.      */
  335.  
  336.     if (r->filename == NULL) {
  337.         r->filename = ap_pstrdup(r->pool, r->uri);
  338.         r->finfo.st_mode = 0;   /* Not really a file... */
  339.         r->per_dir_config = per_dir_defaults;
  340.  
  341.         return OK;
  342.     }
  343.  
  344.     /*
  345.      * Go down the directory hierarchy.  Where we have to check for symlinks,
  346.      * do so.  Where a .htaccess file has permission to override anything,
  347.      * try to find one.  If either of these things fails, we could poke
  348.      * around, see why, and adjust the lookup_rec accordingly --- this might
  349.      * save us a call to get_path_info (with the attendant stat()s); however,
  350.      * for the moment, that's not worth the trouble.
  351.      *
  352.      * Fake filenames (i.e. proxy:) only match Directory sections.
  353.      */
  354.  
  355.     if (!ap_os_is_path_absolute(r->filename))
  356.     {
  357.         void *this_conf, *entry_config;
  358.         core_dir_config *entry_core;
  359.         char *entry_dir;
  360.  
  361.         for (j = 0; j < num_sec; ++j) {
  362.  
  363.             entry_config = sec[j];
  364.  
  365.             entry_core = (core_dir_config *)
  366.                 ap_get_module_config(entry_config, &core_module);
  367.             entry_dir = entry_core->d;
  368.  
  369.             this_conf = NULL;
  370.             if (entry_core->r) {
  371.                 if (!regexec(entry_core->r, r->filename, 0, NULL, 0))
  372.                     this_conf = entry_config;
  373.             }
  374.             else if (entry_core->d_is_fnmatch) {
  375.                 if (!ap_fnmatch(entry_dir, r->filename, 0))
  376.                     this_conf = entry_config;
  377.             }
  378.             else if (!strncmp(r->filename, entry_dir, strlen(entry_dir)))
  379.                 this_conf = entry_config;
  380.  
  381.             if (this_conf)
  382.                 per_dir_defaults = ap_merge_per_dir_configs(r->pool,
  383.                                                          per_dir_defaults,
  384.                                                          this_conf);
  385.         }
  386.  
  387.         r->per_dir_config = per_dir_defaults;
  388.  
  389.         return OK;
  390.     }
  391.  
  392.     r->filename   = ap_os_case_canonical_filename(r->pool, r->filename);
  393.  
  394.     res = get_path_info(r);
  395.     if (res != OK) {
  396.         return res;
  397.     }
  398.  
  399.     r->filename   = ap_os_canonical_filename(r->pool, r->filename);
  400.  
  401.     test_filename = ap_pstrdup(r->pool, r->filename);
  402.  
  403.     ap_no2slash(test_filename);
  404.     num_dirs = ap_count_dirs(test_filename);
  405.  
  406.     if (!ap_os_is_filename_valid(r->filename)) {
  407.         ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
  408.                       "Filename is not valid: %s", r->filename);
  409.         return HTTP_FORBIDDEN;
  410.     }
  411.  
  412.     if ((res = check_safe_file(r))) {
  413.         return res;
  414.     }
  415.  
  416.     test_filename_len = strlen(test_filename);
  417.     if (test_filename[test_filename_len - 1] == '/')
  418.         --num_dirs;
  419.  
  420.     if (S_ISDIR(r->finfo.st_mode))
  421.         ++num_dirs;
  422.  
  423.     /*
  424.      * We will use test_dirname as scratch space while we build directory
  425.      * names during the walk.  Profiling shows directory_walk to be a busy
  426.      * function so we try to avoid allocating lots of extra memory here.
  427.      * We need 2 extra bytes, one for trailing \0 and one because
  428.      * make_dirstr_prefix will add potentially one extra /.
  429.      */
  430.     test_dirname = ap_palloc(r->pool, test_filename_len + 2);
  431.  
  432.     iStart = 1;
  433. #ifdef WIN32
  434.     /* If the name is a UNC name, then do not walk through the
  435.      * machine and share name (e.g. \\machine\share\)
  436.      */
  437.     if (num_dirs > 3 && test_filename[0] == '/' && test_filename[1] == '/')
  438.         iStart = 4;
  439. #endif
  440.  
  441.     /* j keeps track of which section we're on, see core_reorder_directories */
  442.     j = 0;
  443.     for (i = iStart; i <= num_dirs; ++i) {
  444.         int overrides_here;
  445.         core_dir_config *core_dir = (core_dir_config *)
  446.             ap_get_module_config(per_dir_defaults, &core_module);
  447.  
  448.         /*
  449.          * XXX: this could be made faster by only copying the next component
  450.          * rather than copying the entire thing all over.
  451.          */
  452.         ap_make_dirstr_prefix(test_dirname, test_filename, i);
  453.  
  454.         /*
  455.          * Do symlink checks first, because they are done with the
  456.          * permissions appropriate to the *parent* directory...
  457.          */
  458.  
  459.         if ((res = check_symlinks(test_dirname, core_dir->opts))) {
  460.             ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
  461.                         "Symbolic link not allowed: %s", test_dirname);
  462.             return res;
  463.         }
  464.  
  465.         /*
  466.          * Begin *this* level by looking for matching <Directory> sections
  467.          * from access.conf.
  468.          */
  469.  
  470.         for (; j < num_sec; ++j) {
  471.             void *entry_config = sec[j];
  472.             core_dir_config *entry_core;
  473.             char *entry_dir;
  474.             void *this_conf;
  475.  
  476.             entry_core = (core_dir_config *)
  477.                          ap_get_module_config(entry_config, &core_module);
  478.             entry_dir = entry_core->d;
  479.  
  480.             if (entry_core->r
  481.         || !ap_os_is_path_absolute(entry_dir)
  482.                 || entry_core->d_components > i)
  483.                 break;
  484.  
  485.             this_conf = NULL;
  486.             if (entry_core->d_is_fnmatch) {
  487.                 if (!ap_fnmatch(entry_dir, test_dirname, FNM_PATHNAME)) {
  488.                     this_conf = entry_config;
  489.                 }
  490.             }
  491.             else if (!strcmp(test_dirname, entry_dir))
  492.                 this_conf = entry_config;
  493.  
  494.             if (this_conf) {
  495.                 per_dir_defaults = ap_merge_per_dir_configs(r->pool,
  496.                                                          per_dir_defaults,
  497.                                                          this_conf);
  498.                 core_dir = (core_dir_config *)
  499.                            ap_get_module_config(per_dir_defaults, &core_module);
  500.             }
  501.         }
  502.         overrides_here = core_dir->override;
  503.  
  504.         /* If .htaccess files are enabled, check for one. */
  505.  
  506.         if (overrides_here) {
  507.             void *htaccess_conf = NULL;
  508.  
  509.             res = ap_parse_htaccess(&htaccess_conf, r, overrides_here,
  510.                                  ap_pstrdup(r->pool, test_dirname),
  511.                                  sconf->access_name);
  512.             if (res)
  513.                 return res;
  514.  
  515.             if (htaccess_conf) {
  516.                 per_dir_defaults = ap_merge_per_dir_configs(r->pool,
  517.                                 per_dir_defaults,
  518.                                 htaccess_conf);
  519.         r->per_dir_config = per_dir_defaults;
  520.         }
  521.         }
  522.     }
  523.  
  524.     /*
  525.      * There's two types of IS_SPECIAL sections (see http_core.c), and we've
  526.      * already handled the proxy:-style stuff.  Now we'll deal with the
  527.      * regexes.
  528.      */
  529.     for (; j < num_sec; ++j) {
  530.         void *entry_config = sec[j];
  531.         core_dir_config *entry_core;
  532.  
  533.         entry_core = (core_dir_config *)
  534.                      ap_get_module_config(entry_config, &core_module);
  535.  
  536.         if (entry_core->r) {
  537.             if (!regexec(entry_core->r, test_dirname, 0, NULL, REG_NOTEOL)) {
  538.                 per_dir_defaults =
  539.                     ap_merge_per_dir_configs(r->pool, per_dir_defaults,
  540.                                           entry_config);
  541.             }
  542.         }
  543.     }
  544.     r->per_dir_config = per_dir_defaults;
  545.  
  546.     /*
  547.      * Symlink permissions are determined by the parent.  If the request is
  548.      * for a directory then applying the symlink test here would use the
  549.      * permissions of the directory as opposed to its parent.  Consider a
  550.      * symlink pointing to a dir with a .htaccess disallowing symlinks.  If
  551.      * you access /symlink (or /symlink/) you would get a 403 without this
  552.      * S_ISDIR test.  But if you accessed /symlink/index.html, for example,
  553.      * you would *not* get the 403.
  554.      */
  555.     if (!S_ISDIR(r->finfo.st_mode)
  556.         && (res = check_symlinks(r->filename, ap_allow_options(r)))) {
  557.         ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
  558.                     "Symbolic link not allowed: %s", r->filename);
  559.         return res;
  560.     }
  561.     return OK;                  /* Can only "fail" if access denied by the
  562.                                  * symlink goop. */
  563. }
  564.  
  565. static int location_walk(request_rec *r)
  566. {
  567.     core_server_config *sconf = ap_get_module_config(r->server->module_config,
  568.                                                   &core_module);
  569.     void *per_dir_defaults = r->per_dir_config;
  570.     void **url = (void **) sconf->sec_url->elts;
  571.     int len, num_url = sconf->sec_url->nelts;
  572.     char *test_location;
  573.     void *this_conf, *entry_config;
  574.     core_dir_config *entry_core;
  575.     char *entry_url;
  576.     int j;
  577.  
  578.     if (!num_url) {
  579.     return OK;
  580.     }
  581.  
  582.     /* Location and LocationMatch differ on their behaviour w.r.t. multiple
  583.      * slashes.  Location matches multiple slashes with a single slash,
  584.      * LocationMatch doesn't.  An exception, for backwards brokenness is
  585.      * absoluteURIs... in which case neither match multiple slashes.
  586.      */
  587.     if (r->uri[0] != '/') {
  588.     test_location = r->uri;
  589.     }
  590.     else {
  591.     test_location = ap_pstrdup(r->pool, r->uri);
  592.     ap_no2slash(test_location);
  593.     }
  594.  
  595.     /* Go through the location entries, and check for matches. */
  596.  
  597.     /* we apply the directive sections in some order;
  598.      * should really try them with the most general first.
  599.      */
  600.     for (j = 0; j < num_url; ++j) {
  601.  
  602.     entry_config = url[j];
  603.  
  604.     entry_core = (core_dir_config *)
  605.         ap_get_module_config(entry_config, &core_module);
  606.     entry_url = entry_core->d;
  607.  
  608.     len = strlen(entry_url);
  609.  
  610.     this_conf = NULL;
  611.  
  612.     if (entry_core->r) {
  613.         if (!regexec(entry_core->r, r->uri, 0, NULL, 0))
  614.         this_conf = entry_config;
  615.     }
  616.     else if (entry_core->d_is_fnmatch) {
  617.         if (!ap_fnmatch(entry_url, test_location, FNM_PATHNAME)) {
  618.         this_conf = entry_config;
  619.         }
  620.     }
  621.     else if (!strncmp(test_location, entry_url, len) &&
  622.             (entry_url[len - 1] == '/' ||
  623.         test_location[len] == '/' || test_location[len] == '\0'))
  624.         this_conf = entry_config;
  625.  
  626.     if (this_conf)
  627.         per_dir_defaults = ap_merge_per_dir_configs(r->pool,
  628.                         per_dir_defaults, this_conf);
  629.     }
  630.     r->per_dir_config = per_dir_defaults;
  631.  
  632.     return OK;
  633. }
  634.  
  635. static int file_walk(request_rec *r)
  636. {
  637.     core_dir_config *conf = ap_get_module_config(r->per_dir_config, &core_module);
  638.     void *per_dir_defaults = r->per_dir_config;
  639.     void **file = (void **) conf->sec->elts;
  640.     int num_files = conf->sec->nelts;
  641.     char *test_file;
  642.  
  643.     /* get the basename */
  644.     test_file = strrchr(r->filename, '/');
  645.     if (test_file == NULL) {
  646.     test_file = r->filename;
  647.     }
  648.     else {
  649.     ++test_file;
  650.     }
  651.  
  652.     /* Go through the file entries, and check for matches. */
  653.  
  654.     if (num_files) {
  655.         void *this_conf, *entry_config;
  656.         core_dir_config *entry_core;
  657.         char *entry_file;
  658.         int j;
  659.  
  660.         /* we apply the directive sections in some order;
  661.          * should really try them with the most general first.
  662.          */
  663.         for (j = 0; j < num_files; ++j) {
  664.  
  665.             entry_config = file[j];
  666.  
  667.             entry_core = (core_dir_config *)
  668.                          ap_get_module_config(entry_config, &core_module);
  669.             entry_file = entry_core->d;
  670.  
  671.             this_conf = NULL;
  672.  
  673.             if (entry_core->r) {
  674.                 if (!regexec(entry_core->r, test_file, 0, NULL, 0))
  675.                     this_conf = entry_config;
  676.             }
  677.             else if (entry_core->d_is_fnmatch) {
  678.                 if (!ap_fnmatch(entry_file, test_file, FNM_PATHNAME)) {
  679.                     this_conf = entry_config;
  680.                 }
  681.             }
  682.             else if (!strcmp(test_file, entry_file)) {
  683.                 this_conf = entry_config;
  684.         }
  685.  
  686.             if (this_conf)
  687.                 per_dir_defaults = ap_merge_per_dir_configs(r->pool,
  688.                                                          per_dir_defaults,
  689.                                                          this_conf);
  690.         }
  691.         r->per_dir_config = per_dir_defaults;
  692.     }
  693.     return OK;
  694. }
  695.  
  696. /*****************************************************************
  697.  *
  698.  * The sub_request mechanism.
  699.  *
  700.  * Fns to look up a relative URI from, e.g., a map file or SSI document.
  701.  * These do all access checks, etc., but don't actually run the transaction
  702.  * ... use run_sub_req below for that.  Also, be sure to use destroy_sub_req
  703.  * as appropriate if you're likely to be creating more than a few of these.
  704.  * (An early Apache version didn't destroy the sub_reqs used in directory
  705.  * indexing.  The result, when indexing a directory with 800-odd files in
  706.  * it, was massively excessive storage allocation).
  707.  *
  708.  * Note more manipulation of protocol-specific vars in the request
  709.  * structure...
  710.  */
  711.  
  712. static request_rec *make_sub_request(const request_rec *r)
  713. {
  714.     pool *rrp = ap_make_sub_pool(r->pool);
  715.     request_rec *rr = ap_pcalloc(rrp, sizeof(request_rec));
  716.  
  717.     rr->pool = rrp;
  718.     return rr;
  719. }
  720.  
  721. API_EXPORT(request_rec *) ap_sub_req_lookup_uri(const char *new_file,
  722.                                              const request_rec *r)
  723. {
  724.     request_rec *rnew;
  725.     int res;
  726.     char *udir;
  727.  
  728.     rnew = make_sub_request(r);
  729.     rnew->hostname       = r->hostname;
  730.     rnew->request_time   = r->request_time;
  731.     rnew->connection     = r->connection;
  732.     rnew->server         = r->server;
  733.     rnew->request_config = ap_create_request_config(rnew->pool);
  734.     rnew->htaccess       = r->htaccess;
  735.     rnew->per_dir_config = r->server->lookup_defaults;
  736.  
  737.     ap_set_sub_req_protocol(rnew, r);
  738.  
  739.     if (new_file[0] == '/')
  740.         ap_parse_uri(rnew, new_file);
  741.     else {
  742.         udir = ap_make_dirstr_parent(rnew->pool, r->uri);
  743.         udir = ap_escape_uri(rnew->pool, udir);    /* re-escape it */
  744.         ap_parse_uri(rnew, ap_make_full_path(rnew->pool, udir, new_file));
  745.     }
  746.  
  747.     res = ap_unescape_url(rnew->uri);
  748.     if (res) {
  749.         rnew->status = res;
  750.         return rnew;
  751.     }
  752.  
  753.     ap_getparents(rnew->uri);
  754.  
  755.     if ((res = location_walk(rnew))) {
  756.         rnew->status = res;
  757.         return rnew;
  758.     }
  759.  
  760.     res = ap_translate_name(rnew);
  761.     if (res) {
  762.         rnew->status = res;
  763.         return rnew;
  764.     }
  765.  
  766.     /*
  767.      * We could be clever at this point, and avoid calling directory_walk,
  768.      * etc. However, we'd need to test that the old and new filenames contain
  769.      * the same directory components, so it would require duplicating the
  770.      * start of translate_name. Instead we rely on the cache of .htaccess
  771.      * results.
  772.      *
  773.      * NB: directory_walk() clears the per_dir_config, so we don't inherit
  774.      * from location_walk() above
  775.      */
  776.  
  777.     if ((res = directory_walk(rnew))
  778.         || (res = file_walk(rnew))
  779.         || (res = location_walk(rnew))
  780.         || ((ap_satisfies(rnew) == SATISFY_ALL
  781.              || ap_satisfies(rnew) == SATISFY_NOSPEC)
  782.             ? ((res = ap_check_access(rnew))
  783.                || (ap_some_auth_required(rnew)
  784.                    && ((res = ap_check_user_id(rnew))
  785.                        || (res = ap_check_auth(rnew)))))
  786.             : ((res = ap_check_access(rnew))
  787.                && (!ap_some_auth_required(rnew)
  788.                    || ((res = ap_check_user_id(rnew))
  789.                        || (res = ap_check_auth(rnew)))))
  790.            )
  791.         || (res = ap_find_types(rnew))
  792.         || (res = ap_run_fixups(rnew))
  793.        ) {
  794.         rnew->status = res;
  795.     }
  796.     return rnew;
  797. }
  798.  
  799. API_EXPORT(request_rec *) ap_sub_req_lookup_file(const char *new_file,
  800.                                               const request_rec *r)
  801. {
  802.     request_rec *rnew;
  803.     int res;
  804.     char *fdir;
  805.  
  806.     rnew = make_sub_request(r);
  807.     rnew->hostname       = r->hostname;
  808.     rnew->request_time   = r->request_time;
  809.     rnew->connection     = r->connection;
  810.     rnew->server         = r->server;
  811.     rnew->request_config = ap_create_request_config(rnew->pool);
  812.     rnew->htaccess       = r->htaccess;
  813.  
  814.     ap_set_sub_req_protocol(rnew, r);
  815.     fdir = ap_make_dirstr_parent(rnew->pool, r->filename);
  816.  
  817.     /*
  818.      * Check for a special case... if there are no '/' characters in new_file
  819.      * at all, then we are looking at a relative lookup in the same
  820.      * directory. That means we won't have to redo directory_walk, and we may
  821.      * not even have to redo access checks.
  822.      */
  823.  
  824.     if (strchr(new_file, '/') == NULL) {
  825.         char *udir = ap_make_dirstr_parent(rnew->pool, r->uri);
  826.  
  827.         rnew->uri = ap_make_full_path(rnew->pool, udir, new_file);
  828.         rnew->filename = ap_make_full_path(rnew->pool, fdir, new_file);
  829.         ap_parse_uri(rnew, rnew->uri);    /* fill in parsed_uri values */
  830.         if (stat(rnew->filename, &rnew->finfo) < 0) {
  831.             rnew->finfo.st_mode = 0;
  832.         }
  833.  
  834.         if ((res = check_safe_file(rnew))) {
  835.             rnew->status = res;
  836.             return rnew;
  837.         }
  838.  
  839.         rnew->per_dir_config = r->per_dir_config;
  840.  
  841.         /*
  842.          * no matter what, if it's a subdirectory, we need to re-run
  843.          * directory_walk
  844.          */
  845.         if (S_ISDIR(rnew->finfo.st_mode)) {
  846.             res = directory_walk(rnew);
  847.             if (!res) {
  848.                 res = file_walk(rnew);
  849.             }
  850.         }
  851.         else {
  852.             if ((res = check_symlinks(rnew->filename, ap_allow_options(rnew)))) {
  853.                 ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, rnew,
  854.                             "Symbolic link not allowed: %s", rnew->filename);
  855.                 rnew->status = res;
  856.                 return rnew;
  857.             }
  858.             /*
  859.              * do a file_walk, if it doesn't change the per_dir_config then
  860.              * we know that we don't have to redo all the access checks
  861.              */
  862.             if ((res = file_walk(rnew))) {
  863.                 rnew->status = res;
  864.                 return rnew;
  865.             }
  866.             if (rnew->per_dir_config == r->per_dir_config) {
  867.                 if ((res = ap_find_types(rnew)) || (res = ap_run_fixups(rnew))) {
  868.                     rnew->status = res;
  869.                 }
  870.                 return rnew;
  871.             }
  872.         }
  873.     }
  874.     else {
  875.     /* XXX: @@@: What should be done with the parsed_uri values? */
  876.     ap_parse_uri(rnew, new_file);    /* fill in parsed_uri values */
  877.         /*
  878.          * XXX: this should be set properly like it is in the same-dir case
  879.          * but it's actually sometimes to impossible to do it... because the
  880.          * file may not have a uri associated with it -djg
  881.          */
  882.         rnew->uri = "INTERNALLY GENERATED file-relative req";
  883.         rnew->filename = ((ap_os_is_path_absolute(new_file)) ?
  884.                           ap_pstrdup(rnew->pool, new_file) :
  885.                           ap_make_full_path(rnew->pool, fdir, new_file));
  886.         rnew->per_dir_config = r->server->lookup_defaults;
  887.         res = directory_walk(rnew);
  888.         if (!res) {
  889.             res = file_walk(rnew);
  890.         }
  891.     }
  892.  
  893.     if (res
  894.         || ((ap_satisfies(rnew) == SATISFY_ALL
  895.              || ap_satisfies(rnew) == SATISFY_NOSPEC)
  896.             ? ((res = ap_check_access(rnew))
  897.                || (ap_some_auth_required(rnew)
  898.                    && ((res = ap_check_user_id(rnew))
  899.                        || (res = ap_check_auth(rnew)))))
  900.             : ((res = ap_check_access(rnew))
  901.                && (!ap_some_auth_required(rnew)
  902.                    || ((res = ap_check_user_id(rnew))
  903.                        || (res = ap_check_auth(rnew)))))
  904.            )
  905.         || (res = ap_find_types(rnew))
  906.         || (res = ap_run_fixups(rnew))
  907.        ) {
  908.         rnew->status = res;
  909.     }
  910.     return rnew;
  911. }
  912.  
  913. API_EXPORT(int) ap_run_sub_req(request_rec *r)
  914. {
  915. #ifndef CHARSET_EBCDIC
  916.     int retval = ap_invoke_handler(r);
  917. #else /*CHARSET_EBCDIC*/
  918.     /* Save the EBCDIC conversion setting of the caller across subrequests */
  919.     int convert = ap_bgetflag(r->connection->client, B_EBCDIC2ASCII);
  920.     int retval  = ap_invoke_handler(r);
  921.     ap_bsetflag(r->connection->client, B_EBCDIC2ASCII, convert);
  922. #endif /*CHARSET_EBCDIC*/
  923.     ap_finalize_sub_req_protocol(r);
  924.     return retval;
  925. }
  926.  
  927. API_EXPORT(void) ap_destroy_sub_req(request_rec *r)
  928. {
  929.     /* Reclaim the space */
  930.     ap_destroy_pool(r->pool);
  931. }
  932.  
  933. /*****************************************************************
  934.  *
  935.  * Mainline request processing...
  936.  */
  937.  
  938. API_EXPORT(void) ap_die(int type, request_rec *r)
  939. {
  940.     int error_index = ap_index_of_response(type);
  941.     char *custom_response = ap_response_code_string(r, error_index);
  942.     int recursive_error = 0;
  943.  
  944.     if (type == DONE) {
  945.         ap_finalize_request_protocol(r);
  946.         return;
  947.     }
  948.  
  949.     /*
  950.      * The following takes care of Apache redirects to custom response URLs
  951.      * Note that if we are already dealing with the response to some other
  952.      * error condition, we just report on the original error, and give up on
  953.      * any attempt to handle the other thing "intelligently"...
  954.      */
  955.  
  956.     if (r->status != HTTP_OK) {
  957.         recursive_error = type;
  958.  
  959.         while (r->prev && (r->prev->status != HTTP_OK))
  960.             r = r->prev;        /* Get back to original error */
  961.  
  962.         type = r->status;
  963.         custom_response = NULL; /* Do NOT retry the custom thing! */
  964.     }
  965.  
  966.     r->status = type;
  967.  
  968.     /*
  969.      * This test is done here so that none of the auth modules needs to know
  970.      * about proxy authentication.  They treat it like normal auth, and then
  971.      * we tweak the status.
  972.      */
  973.     if (r->status == AUTH_REQUIRED && r->proxyreq) {
  974.         r->status = HTTP_PROXY_AUTHENTICATION_REQUIRED;
  975.     }
  976.  
  977.     /*
  978.      * If we want to keep the connection, be sure that the request body
  979.      * (if any) has been read.
  980.      */
  981.     if ((r->status != HTTP_NOT_MODIFIED) && (r->status != HTTP_NO_CONTENT)
  982.         && !ap_status_drops_connection(r->status)
  983.         && r->connection && (r->connection->keepalive != -1)) {
  984.  
  985.         (void) ap_discard_request_body(r);
  986.     }
  987.  
  988.     /*
  989.      * Two types of custom redirects --- plain text, and URLs. Plain text has
  990.      * a leading '"', so the URL code, here, is triggered on its absence
  991.      */
  992.  
  993.     if (custom_response && custom_response[0] != '"') {
  994.  
  995.         if (ap_is_url(custom_response)) {
  996.             /*
  997.              * The URL isn't local, so lets drop through the rest of this
  998.              * apache code, and continue with the usual REDIRECT handler.
  999.              * But note that the client will ultimately see the wrong
  1000.              * status...
  1001.              */
  1002.             r->status = REDIRECT;
  1003.             ap_table_setn(r->headers_out, "Location", custom_response);
  1004.         }
  1005.         else if (custom_response[0] == '/') {
  1006.             const char *error_notes;
  1007.             r->no_local_copy = 1;       /* Do NOT send USE_LOCAL_COPY for
  1008.                                          * error documents! */
  1009.             /*
  1010.              * This redirect needs to be a GET no matter what the original
  1011.              * method was.
  1012.              */
  1013.             ap_table_setn(r->subprocess_env, "REQUEST_METHOD", r->method);
  1014.  
  1015.         /*
  1016.          * Provide a special method for modules to communicate
  1017.          * more informative (than the plain canned) messages to us.
  1018.          * Propagate them to ErrorDocuments via the ERROR_NOTES variable:
  1019.          */
  1020.             if ((error_notes = ap_table_get(r->notes, "error-notes")) != NULL) {
  1021.         ap_table_setn(r->subprocess_env, "ERROR_NOTES", error_notes);
  1022.         }
  1023.             r->method = ap_pstrdup(r->pool, "GET");
  1024.             r->method_number = M_GET;
  1025.             ap_internal_redirect(custom_response, r);
  1026.             return;
  1027.         }
  1028.         else {
  1029.             /*
  1030.              * Dumb user has given us a bad url to redirect to --- fake up
  1031.              * dying with a recursive server error...
  1032.              */
  1033.             recursive_error = SERVER_ERROR;
  1034.             ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
  1035.                         "Invalid error redirection directive: %s",
  1036.                         custom_response);
  1037.         }
  1038.     }
  1039.     ap_send_error_response(r, recursive_error);
  1040. }
  1041.  
  1042. static void decl_die(int status, char *phase, request_rec *r)
  1043. {
  1044.     if (status == DECLINED) {
  1045.         ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_CRIT, r,
  1046.                     "configuration error:  couldn't %s: %s", phase, r->uri);
  1047.         ap_die(SERVER_ERROR, r);
  1048.     }
  1049.     else
  1050.         ap_die(status, r);
  1051. }
  1052.  
  1053. API_EXPORT(int) ap_some_auth_required(request_rec *r)
  1054. {
  1055.     /* Is there a require line configured for the type of *this* req? */
  1056.  
  1057.     const array_header *reqs_arr = ap_requires(r);
  1058.     require_line *reqs;
  1059.     int i;
  1060.  
  1061.     if (!reqs_arr)
  1062.         return 0;
  1063.  
  1064.     reqs = (require_line *) reqs_arr->elts;
  1065.  
  1066.     for (i = 0; i < reqs_arr->nelts; ++i)
  1067.         if (reqs[i].method_mask & (1 << r->method_number))
  1068.             return 1;
  1069.  
  1070.     return 0;
  1071. }
  1072.  
  1073. static void process_request_internal(request_rec *r)
  1074. {
  1075.     int access_status;
  1076.  
  1077.     /* Ignore embedded %2F's in path for proxy requests */
  1078.     if (!r->proxyreq && r->parsed_uri.path) {
  1079.     access_status = ap_unescape_url(r->parsed_uri.path);
  1080.     if (access_status) {
  1081.         ap_die(access_status, r);
  1082.         return;
  1083.     }
  1084.     }
  1085.  
  1086.     ap_getparents(r->uri);     /* OK --- shrinking transformations... */
  1087.  
  1088.     if ((access_status = location_walk(r))) {
  1089.         ap_die(access_status, r);
  1090.         return;
  1091.     }
  1092.  
  1093.     if ((access_status = ap_translate_name(r))) {
  1094.         decl_die(access_status, "translate", r);
  1095.         return;
  1096.     }
  1097.  
  1098.     if (!r->proxyreq) {
  1099.     /*
  1100.      * We don't want TRACE to run through the normal handler set, we
  1101.      * handle it specially.
  1102.      */
  1103.     if (r->method_number == M_TRACE) {
  1104.         if ((access_status = ap_send_http_trace(r)))
  1105.         ap_die(access_status, r);
  1106.         else
  1107.         ap_finalize_request_protocol(r);
  1108.         return;
  1109.     }
  1110.     }
  1111.  
  1112.     if (r->proto_num > HTTP_VERSION(1,0) && ap_table_get(r->subprocess_env, "downgrade-1.0")) {
  1113.         r->proto_num = HTTP_VERSION(1,0);
  1114.     }
  1115.  
  1116.     /*
  1117.      * NB: directory_walk() clears the per_dir_config, so we don't inherit
  1118.      * from location_walk() above
  1119.      */
  1120.  
  1121.     if ((access_status = directory_walk(r))) {
  1122.         ap_die(access_status, r);
  1123.         return;
  1124.     }
  1125.  
  1126.     if ((access_status = file_walk(r))) {
  1127.         ap_die(access_status, r);
  1128.         return;
  1129.     }
  1130.  
  1131.     if ((access_status = location_walk(r))) {
  1132.         ap_die(access_status, r);
  1133.         return;
  1134.     }
  1135.  
  1136.     if ((access_status = ap_header_parse(r))) {
  1137.         ap_die(access_status, r);
  1138.         return;
  1139.     }
  1140.  
  1141.     switch (ap_satisfies(r)) {
  1142.     case SATISFY_ALL:
  1143.     case SATISFY_NOSPEC:
  1144.         if ((access_status = ap_check_access(r)) != 0) {
  1145.             decl_die(access_status, "check access", r);
  1146.             return;
  1147.         }
  1148.         if (ap_some_auth_required(r)) {
  1149.             if (((access_status = ap_check_user_id(r)) != 0) || !ap_auth_type(r)) {
  1150.                 decl_die(access_status, ap_auth_type(r)
  1151.             ? "check user.  No user file?"
  1152.             : "perform authentication. AuthType not set!", r);
  1153.                 return;
  1154.             }
  1155.             if (((access_status = ap_check_auth(r)) != 0) || !ap_auth_type(r)) {
  1156.                 decl_die(access_status, ap_auth_type(r)
  1157.             ? "check access.  No groups file?"
  1158.             : "perform authentication. AuthType not set!", r);
  1159.                 return;
  1160.             }
  1161.         }
  1162.         break;
  1163.     case SATISFY_ANY:
  1164.         if (((access_status = ap_check_access(r)) != 0) || !ap_auth_type(r)) {
  1165.             if (!ap_some_auth_required(r)) {
  1166.                 decl_die(access_status, ap_auth_type(r)
  1167.             ? "check access"
  1168.             : "perform authentication. AuthType not set!", r);
  1169.                 return;
  1170.             }
  1171.             if (((access_status = ap_check_user_id(r)) != 0) || !ap_auth_type(r)) {
  1172.                 decl_die(access_status, ap_auth_type(r)
  1173.             ? "check user.  No user file?"
  1174.             : "perform authentication. AuthType not set!", r);
  1175.                 return;
  1176.             }
  1177.             if (((access_status = ap_check_auth(r)) != 0) || !ap_auth_type(r)) {
  1178.                 decl_die(access_status, ap_auth_type(r)
  1179.             ? "check access.  No groups file?"
  1180.             : "perform authentication. AuthType not set!", r);
  1181.                 return;
  1182.             }
  1183.         }
  1184.         break;
  1185.     }
  1186.  
  1187.     if (! (r->proxyreq 
  1188.        && r->parsed_uri.scheme != NULL
  1189.        && strcmp(r->parsed_uri.scheme, "http") == 0) ) {
  1190.     if ((access_status = ap_find_types(r)) != 0) {
  1191.         decl_die(access_status, "find types", r);
  1192.         return;
  1193.     }
  1194.     }
  1195.  
  1196.     if ((access_status = ap_run_fixups(r)) != 0) {
  1197.         ap_die(access_status, r);
  1198.         return;
  1199.     }
  1200.  
  1201.     if ((access_status = ap_invoke_handler(r)) != 0) {
  1202.         ap_die(access_status, r);
  1203.         return;
  1204.     }
  1205.  
  1206.     /* Take care of little things that need to happen when we're done */
  1207.     ap_finalize_request_protocol(r);
  1208. }
  1209.  
  1210. void ap_process_request(request_rec *r)
  1211. {
  1212.     int old_stat;
  1213.  
  1214.     if (ap_extended_status)
  1215.     ap_time_process_request(r->connection->child_num, START_PREQUEST);
  1216.  
  1217.     process_request_internal(r);
  1218.  
  1219.     old_stat = ap_update_child_status(r->connection->child_num,
  1220.                                    SERVER_BUSY_LOG, r);
  1221.  
  1222.     /*
  1223.      * We want to flush the last packet if this isn't a pipelining connection
  1224.      * *before* we start into logging.  Suppose that the logging causes a DNS
  1225.      * lookup to occur, which may have a high latency.  If we hold off on
  1226.      * this packet, then it'll appear like the link is stalled when really
  1227.      * it's the application that's stalled.
  1228.      */
  1229.     ap_bhalfduplex(r->connection->client);
  1230.     ap_log_transaction(r);
  1231.  
  1232.     (void) ap_update_child_status(r->connection->child_num, old_stat, r);
  1233.     if (ap_extended_status)
  1234.     ap_time_process_request(r->connection->child_num, STOP_PREQUEST);
  1235. }
  1236.  
  1237. static table *rename_original_env(pool *p, table *t)
  1238. {
  1239.     array_header *env_arr = ap_table_elts(t);
  1240.     table_entry *elts = (table_entry *) env_arr->elts;
  1241.     table *new = ap_make_table(p, env_arr->nalloc);
  1242.     int i;
  1243.  
  1244.     for (i = 0; i < env_arr->nelts; ++i) {
  1245.         if (!elts[i].key)
  1246.             continue;
  1247.         ap_table_setn(new, ap_pstrcat(p, "REDIRECT_", elts[i].key, NULL),
  1248.                   elts[i].val);
  1249.     }
  1250.  
  1251.     return new;
  1252. }
  1253.  
  1254. static request_rec *internal_internal_redirect(const char *new_uri, request_rec *r)
  1255. {
  1256.     int access_status;
  1257.     request_rec *new = (request_rec *) ap_pcalloc(r->pool, sizeof(request_rec));
  1258.  
  1259.     new->connection = r->connection;
  1260.     new->server     = r->server;
  1261.     new->pool       = r->pool;
  1262.  
  1263.     /*
  1264.      * A whole lot of this really ought to be shared with http_protocol.c...
  1265.      * another missing cleanup.  It's particularly inappropriate to be
  1266.      * setting header_only, etc., here.
  1267.      */
  1268.  
  1269.     new->method          = r->method;
  1270.     new->method_number   = r->method_number;
  1271.     ap_parse_uri(new, new_uri);
  1272.     new->request_config = ap_create_request_config(r->pool);
  1273.     new->per_dir_config = r->server->lookup_defaults;
  1274.  
  1275.     new->prev = r;
  1276.     r->next   = new;
  1277.  
  1278.     /* Inherit the rest of the protocol info... */
  1279.  
  1280.     new->the_request = r->the_request;
  1281.  
  1282.     new->allowed         = r->allowed;
  1283.  
  1284.     new->status          = r->status;
  1285.     new->assbackwards    = r->assbackwards;
  1286.     new->header_only     = r->header_only;
  1287.     new->protocol        = r->protocol;
  1288.     new->proto_num       = r->proto_num;
  1289.     new->hostname        = r->hostname;
  1290.     new->request_time    = r->request_time;
  1291.     new->main            = r->main;
  1292.  
  1293.     new->headers_in      = r->headers_in;
  1294.     new->headers_out     = ap_make_table(r->pool, 12);
  1295.     new->err_headers_out = r->err_headers_out;
  1296.     new->subprocess_env  = rename_original_env(r->pool, r->subprocess_env);
  1297.     new->notes           = ap_make_table(r->pool, 5);
  1298.  
  1299.     new->htaccess        = r->htaccess;
  1300.     new->no_cache        = r->no_cache;
  1301.     new->no_local_copy   = r->no_local_copy;
  1302.     new->read_length     = r->read_length;     /* We can only read it once */
  1303.     new->vlist_validator = r->vlist_validator;
  1304.  
  1305.     ap_table_setn(new->subprocess_env, "REDIRECT_STATUS",
  1306.     ap_psprintf(r->pool, "%d", r->status));
  1307.  
  1308.     /*
  1309.      * XXX: hmm.  This is because mod_setenvif and mod_unique_id really need
  1310.      * to do their thing on internal redirects as well.  Perhaps this is a
  1311.      * misnamed function.
  1312.      */
  1313.     if ((access_status = ap_run_post_read_request(new))) {
  1314.         ap_die(access_status, new);
  1315.         return NULL;
  1316.     }
  1317.  
  1318.     return new;
  1319. }
  1320.  
  1321. API_EXPORT(void) ap_internal_redirect(const char *new_uri, request_rec *r)
  1322. {
  1323.     request_rec *new = internal_internal_redirect(new_uri, r);
  1324.     process_request_internal(new);
  1325. }
  1326.  
  1327. /* This function is designed for things like actions or CGI scripts, when
  1328.  * using AddHandler, and you want to preserve the content type across
  1329.  * an internal redirect.
  1330.  */
  1331. API_EXPORT(void) ap_internal_redirect_handler(const char *new_uri, request_rec *r)
  1332. {
  1333.     request_rec *new = internal_internal_redirect(new_uri, r);
  1334.     if (r->handler)
  1335.         new->content_type = r->content_type;
  1336.     process_request_internal(new);
  1337. }
  1338.  
  1339. /*
  1340.  * Is it the initial main request, which we only get *once* per HTTP request?
  1341.  */
  1342. API_EXPORT(int) ap_is_initial_req(request_rec *r)
  1343. {
  1344.     return
  1345.         (r->main == NULL)       /* otherwise, this is a sub-request */
  1346.         &&
  1347.         (r->prev == NULL);      /* otherwise, this is an internal redirect */
  1348. }
  1349.  
  1350. /*
  1351.  * Function to set the r->mtime field to the specified value if it's later
  1352.  * than what's already there.
  1353.  */
  1354. API_EXPORT(time_t) ap_update_mtime(request_rec *r, time_t dependency_mtime)
  1355. {
  1356.     if (r->mtime < dependency_mtime) {
  1357.         r->mtime = dependency_mtime;
  1358.     }
  1359.     return r->mtime;
  1360. }
  1361.