You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@httpd.apache.org by "Ralf S. Engelschall" <rs...@engelschall.com> on 1997/01/31 21:54:57 UTC

mod_rewrite 3.0.0 for Apache 1.2b7 !!! (PATCH)

As a result of the current problems, I decided a change for mod_rewrite:

1. Version 2.4.x (currently 2.4.1) is the latest release available
   for Apache 1.1.x. There will be only bugfixes applied to 2.4.x
   to provide a stable version for the Apache 1.1.x users.

2. Version 3.0.0 was created by manually merging (hmm... I like
   those jobs) the 2.4.1 version and the aligned 2.3.10+ version currently
   found in the 1.2b7-dev snapshot sources. Actually this is 2.4.1 with Marcs
   snprintf/strncpy patches re-applied.  All other changes from the Apache
   Group (OS\2 EMX, const, etc.) were already included into 2.4.1.

Version 3.0.0 is still not released. Below is a standard patch for review
_AND_ a context diff to bring the current CVS sources up to date.

NOW, APACHE GROUP MEMBERS, ATTENTION PLEASE:

Go to the patch and review it. And do it immediately so it don't get lost in
the processing ;-) and Apache 1.2b7 can contain mod_rewrite 3.0.0. Please vote
for this change NOW!

Thanks!
                                       Ralf S. Engelschall
                                       rse@engelschall.com
                                       www.engelschall.com

=REVIEW DIFF===========================
0a1
>  
63c64
< **  URL Rewriting Module, Version 2.3.10 (20-12-1996)
---
> **  URL Rewriting Module, Version 3.0.0 (xx-02-1997)
83c84
< **  Copyright (c) 1996 Ralf S. Engelschall, All rights reserved.
---
> **  Copyright (c) 1996-1997 Ralf S. Engelschall, All rights reserved.
88c89
< **      http://www.engelschall.com/
---
> **      www.engelschall.com
98a100,102
> #include <errno.h>
> #include <pwd.h>
> #include <grp.h>
113,117d116
< #ifdef __EMX__
< /* OS/2 dosen't support links. */
< #define S_ISLNK
< #endif
< 
134c133
< **  keep in mind:
---
> **  keep in mind: 
231d229
< #ifdef HAS_APACHE_REGEX_LIB
235,238d232
< #else
< #define MAPFILE_OUTPUT "\\1,\\2"
< static regexp *lookup_map_txtfile_regexp = NULL;
< #endif
359c353
< static _const char *cmd_rewriteengine(cmd_parms *cmd, rewrite_perdir_conf *dconf, int flag)
---
> static const char *cmd_rewriteengine(cmd_parms *cmd, rewrite_perdir_conf *dconf, int flag)
372c366
< static _const char *cmd_rewriteoptions(cmd_parms *cmd, rewrite_perdir_conf *dconf, char *option)
---
> static const char *cmd_rewriteoptions(cmd_parms *cmd, rewrite_perdir_conf *dconf, char *option)
375c369
<     _const char *err;
---
>     const char *err;
386c380
< static _const char *cmd_rewriteoptions_setoption(pool *p, int *options, char *name)
---
> static const char *cmd_rewriteoptions_setoption(pool *p, int *options, char *name)
395c389
< static _const char *cmd_rewritelog(cmd_parms *cmd, void *dconf, char *a1)
---
> static const char *cmd_rewritelog(cmd_parms *cmd, void *dconf, char *a1)
405c399
< static _const char *cmd_rewriteloglevel(cmd_parms *cmd, void *dconf, char *a1)
---
> static const char *cmd_rewriteloglevel(cmd_parms *cmd, void *dconf, char *a1)
415c409
< static _const char *cmd_rewritemap(cmd_parms *cmd, void *dconf, char *a1, char *a2)
---
> static const char *cmd_rewritemap(cmd_parms *cmd, void *dconf, char *a1, char *a2)
459c453
< static _const char *cmd_rewritebase(cmd_parms *cmd, rewrite_perdir_conf *dconf, char *a1)
---
> static const char *cmd_rewritebase(cmd_parms *cmd, rewrite_perdir_conf *dconf, char *a1)
473c467
< static _const char *cmd_rewritecond(cmd_parms *cmd, rewrite_perdir_conf *dconf, char *str)
---
> static const char *cmd_rewritecond(cmd_parms *cmd, rewrite_perdir_conf *dconf, char *str)
477d470
< #ifdef HAS_APACHE_REGEX_LIB
479,482d471
< #else
<     regexp *regexp;
<     int i;
< #endif
487c476
<     _const char *err;
---
>     const char *err;
525d513
< #ifdef HAS_APACHE_REGEX_LIB
530,536d517
< #else
<     if (new->flags & CONDFLAG_NOCASE) {
<         for (i = 0; cp[i] != '\0'; i++)
<             cp[i] = tolower(cp[i]);
<     }
<     rc = ((regexp = regcomp(cp)) == NULL);
< #endif
545c526
< static _const char *cmd_rewritecond_parseflagfield(pool *p, rewritecond_entry *cfg, char *str)
---
> static const char *cmd_rewritecond_parseflagfield(pool *p, rewritecond_entry *cfg, char *str)
553c534
<     _const char *err;
---
>     const char *err;
579c560
<                 val = "yes";
---
>                 val = "";
591c572
< static _const char *cmd_rewritecond_setflag(pool *p, rewritecond_entry *cfg, char *key, char *val)
---
> static const char *cmd_rewritecond_setflag(pool *p, rewritecond_entry *cfg, char *key, char *val)
608c589
< _const char *cmd_rewriterule(cmd_parms *cmd, rewrite_perdir_conf *dconf, char *str)
---
> const char *cmd_rewriterule(cmd_parms *cmd, rewrite_perdir_conf *dconf, char *str)
612d592
< #ifdef HAS_APACHE_REGEX_LIB
614,617d593
< #else
<     regexp *regexp;
<     int i;
< #endif
622c598
<     _const char *err;
---
>     const char *err;
644d619
< #ifdef HAS_APACHE_REGEX_LIB
646,648d620
< #else
<     if ((regexp = regcomp(cp)) == NULL)
< #endif
656,661d627
< #ifndef HAS_APACHE_REGEX_LIB
<     for (i = 0; a2[i] != '\0'; i++) {
<         if (a2[i] == '$' && a2[i+1] >= '1' && a2[i+1] <= '9') 
<             a2[i] = '\\';
<     }
< #endif
665a632,633
>     new->forced_responsecode = HTTP_MOVED_TEMPORARILY;
>     new->env[0] = NULL;
687c655
< static _const char *cmd_rewriterule_parseflagfield(pool *p, rewriterule_entry *cfg, char *str)
---
> static const char *cmd_rewriterule_parseflagfield(pool *p, rewriterule_entry *cfg, char *str)
695c663
<     _const char *err;
---
>     const char *err;
721c689
<                 val = "yes";
---
>                 val = "";
733c701
< static _const char *cmd_rewriterule_setflag(pool *p, rewriterule_entry *cfg, char *key, char *val)
---
> static const char *cmd_rewriterule_setflag(pool *p, rewriterule_entry *cfg, char *key, char *val)
734a703,705
>     int status = 0;
>     int i;
> 
737a709,721
>         if (strlen(val) > 0) {
>             if (strcasecmp(val, "permanent") == 0)
>                 status = HTTP_MOVED_PERMANENTLY;
>             else if (strcasecmp(val, "temp") == 0)
>                 status = HTTP_MOVED_TEMPORARILY;
>             else if (strcasecmp(val, "seeother") == 0)
>                 status = HTTP_SEE_OTHER;
>             else if (isdigit(*val))
>                 status = atoi(val);
>             if (!is_HTTP_REDIRECT(status))
>                 return pstrdup(p, "RewriteRule: invalid HTTP response code for flag 'R'");
>             cfg->forced_responsecode = status;
>         }
754a739,749
>     else if (   strcasecmp(key, "env") == 0
>              || strcasecmp(key, "E") == 0   ) {
>         for (i = 0; (cfg->env[i] != NULL) && (i < MAX_ENV_FLAGS); i++)
>             ;
>         if (i < MAX_ENV_FLAGS) {
>             cfg->env[i] = pstrdup(p, val);
>             cfg->env[i+1] = NULL;
>         }
>         else 
>             return pstrdup(p, "RewriteRule: to much environment flags 'E'");
>     }
774a770,773
>     else if (   strcasecmp(key, "gone") == 0
>              || strcasecmp(key, "G") == 0   ) {
>         cfg->flags |= RULEFLAG_GONE;
>     }
808d806
< #ifdef HAS_APACHE_REGEX_LIB
810,812d807
< #else
<     lookup_map_txtfile_regexp = regcomp(MAPFILE_PATTERN);
< #endif
973a969,977
>             /* determine HTTP redirect response code */
>             if (is_HTTP_REDIRECT(r->status)) {
>                 n = r->status; 
>                 r->status = HTTP_OK; /* make Apache kernel happy */
>             }
>             else
>                 n = REDIRECT;
> 
>             /* now do the redirection */
975,976c979,980
<             rewritelog(r, 1, "redirect to %s [REDIRECT]", r->filename);
<             return REDIRECT;
---
>             rewritelog(r, 1, "redirect to %s [REDIRECT/%d]", r->filename, n);
>             return n;
982a987,991
>         else if (strlen(r->filename) > 5 &&
>                  strncmp(r->filename, "gone:", 5) == 0) {
>             /* This URLs is forced to be gone */
>             return HTTP_GONE; 
>         }
1012c1021
<                - when we allways prefix with document_root
---
>                - when we always prefix with document_root
1014,1015c1023,1024
<                  remulating a ScriptAlias directive, etc.
<                - when we allways NOT prefix with document_root
---
>                  emulating a ScriptAlias directive, etc.
>                - when we always NOT prefix with document_root
1030c1039
< 		    docroot[sizeof(docroot)-1] = '\0';
---
>                     docroot[sizeof(docroot)-1] = '\0';
1095a1105
>     int n;
1202a1213,1221
>             /* determine HTTP redirect response code */
>             if (is_HTTP_REDIRECT(r->status)) {
>                 n = r->status; 
>                 r->status = HTTP_OK; /* make Apache kernel happy */
>             }
>             else
>                 n = REDIRECT;
> 
>             /* now do the redirection */
1204,1205c1223,1224
<             rewritelog(r, 1, "[per-dir %s] redirect to %s [REDIRECT]", dconf->directory, r->filename);
<             return REDIRECT;
---
>             rewritelog(r, 1, "[per-dir %s] redirect to %s [REDIRECT/%d]", dconf->directory, r->filename, n);
>             return n;
1211a1231,1235
>         else if (strlen(r->filename) > 5 &&
>                  strncmp(r->filename, "gone:", 5) == 0) {
>             /* This URLs is forced to be gone */
>             return HTTP_GONE; 
>         }
1344a1369,1374
>             if (p->flags & RULEFLAG_GONE) {
>                 rewritelog(r, 2, "forcing '%s' to be gone", r->filename);
>                 r->filename = pstrcat(r->pool, "gone:", r->filename, NULL);
>                 changed = 1;
>                 break;
>             }
1381a1412
>     char env[MAX_STRING_LEN];
1383c1414
< #ifdef HAS_APACHE_REGEX_LIB
---
>     char env2[MAX_STRING_LEN];
1386,1388d1416
< #else
<     regexp *regexp;
< #endif
1421d1448
< #ifdef HAS_APACHE_REGEX_LIB
1423,1425d1449
< #else
<     rc = (regexec(regexp, uri) != 0);   /* try to match the pattern */
< #endif
1476c1500
< 		newuri[sizeof(newuri)-1] = '\0';
---
>                 newuri[sizeof(newuri)-1] = '\0';
1482d1505
< #ifdef HAS_APACHE_REGEX_LIB
1484,1487c1507,1511
< 		newuri[sizeof(newuri)-1] = '\0';
< #else
<                 regsub(regexp, output, newuri);                      /* substitute in output */
< #endif
---
>                 for (i = 0; p->env[i] != NULL; i++) {
>                     strcpy(env2, p->env[i]);
>                     strcpy(env, pregsub(r->pool, env2, uri, regexp->re_nsub+1, regmatch));    /* substitute in output */
>                     add_env_variable(r, env);
>                 }
1510c1534
< 		newuri[sizeof(newuri)-1] = '\0';
---
>                 newuri[sizeof(newuri)-1] = '\0';
1515d1538
< #ifdef HAS_APACHE_REGEX_LIB
1517,1520c1540,1545
< 		newuri[sizeof(newuri)-1] = '\0';
< #else
<                 regsub(regexp, output, newuri);                      /* substitute in output */
< #endif
---
>                 newuri[sizeof(newuri)-1] = '\0';
>                 for (i = 0; p->env[i] != NULL; i++) {
>                     strcpy(env2, p->env[i]);
>                     strcpy(env, pregsub(r->pool, env2, uri, regexp->re_nsub+1, regmatch));    /* substitute in output */
>                     add_env_variable(r, env);
>                 }
1541c1566
< 	    newuri[sizeof(newuri)-1] = '\0';
---
>             newuri[sizeof(newuri)-1] = '\0';
1545d1569
< #ifdef HAS_APACHE_REGEX_LIB
1547,1550c1571,1576
< 	    newuri[sizeof(newuri)-1] = '\0'; 
< #else
<             regsub(regexp, output, newuri);                      /* substitute in output */
< #endif
---
>             newuri[sizeof(newuri)-1] = '\0'; 
>             for (i = 0; p->env[i] != NULL; i++) {
>                 strcpy(env2, p->env[i]);
>                 strcpy(env, pregsub(r->pool, env2, uri, regexp->re_nsub+1, regmatch));    /* substitute in output */
>                 add_env_variable(r, env);
>             }
1553c1579
<         expand_map_lookups(r, newuri, sizeof(newuri));   /* expand ${...} */
---
>         expand_map_lookups(r, newuri, sizeof(newuri));         /* expand ${...} */
1613a1640
>                 r->status = p->forced_responsecode;
1625,1628d1651
< #ifndef HAS_APACHE_REGEX_LIB
<     char inputbuf[LONG_STRING_LEN];
<     int i;
< #endif
1631a1655
>     request_rec *rsub;
1647a1672,1673
> #ifndef __EMX__
> /* OS/2 dosen't support links. */
1650a1677
> #endif
1656a1684,1732
>     else if (strcmp(p->pattern, "-U") == 0) {
>         /* avoid infinite subrequest recursion */
>         if (strlen(input) > 0               /* nonempty path, and */
>             && (   r->main == NULL          /* - either not in a subrequest */
>                 || (   r->main->uri != NULL /* - or in a subrequest...*/
>                     && r->uri != NULL       /*   ...and then URIs aren't NULL... */
>                                             /*   ...and sub and main URIs differ */
>                     && strcmp(r->main->uri, r->uri) != 0) ) ) {
> 
>             /* run a URI-based subrequest */
>             rsub = sub_req_lookup_uri(input, r);
> 
>             /* URI exists for any result up to 3xx, redirects allowed */
>             if (rsub->status < 400)
>                 rc = 1;
> 
>             /* log it */
>             rewritelog(r, 5, "RewriteCond URI (-U) check: path=%s -> status=%d", input, rsub->status);
> 
>             /* cleanup by destroying the subrequest */
>             destroy_sub_req(rsub);
>         }
>     }
>     else if (strcmp(p->pattern, "-F") == 0) {
>         /* avoid infinite subrequest recursion */
>         if (strlen(input) > 0               /* nonempty path, and */
>             && (   r->main == NULL          /* - either not in a subrequest */
>                 || (   r->main->uri != NULL /* - or in a subrequest...*/
>                     && r->uri != NULL       /*   ...and then URIs aren't NULL... */
>                                             /*   ...and sub and main URIs differ */
>                     && strcmp(r->main->uri, r->uri) != 0) ) ) {
> 
>             /* process a file-based subrequest: 
>                this differs from -U in that no path translation is done. */
>             rsub = sub_req_lookup_file(input, r);
>  
>             /* file exists for any result up to 2xx, no redirects */
>             if (rsub->status < 300 &&
>                 /* double-check that file exists since default result is 200 */
>                 stat(rsub->filename, &sb) == 0)
>                 rc = 1;
> 
>             /* log it */
>             rewritelog(r, 5, "RewriteCond file (-F) check: path=%s -> file=%s status=%d", input, rsub->filename, rsub->status);
> 
>             /* cleanup by destroying the subrequest */
>             destroy_sub_req(rsub);
>         }
>     }
1659d1734
< #ifdef HAS_APACHE_REGEX_LIB
1661,1672d1735
< #else
<         if (p->flags & CONDFLAG_NOCASE) {
<             for (i = 0; input[i] != '\0' && i < sizeof(inputbuf)-1 ; i++)
<                 inputbuf[i] = tolower(input[i]);
<             inputbuf[i] = '\0';
<         }
<         else {
<             strncpy(inputbuf, input, sizeof(inputbuf)-1);
< 	    inputbuf[sizeof(inputbuf)-1] = '\0';
<         }
<         rc = (regexec(p->regexp, inputbuf) != 0);
< #endif
1758c1821
< 	buf[sizeof(buf)-1] = '\0';
---
>         buf[sizeof(buf)-1] = '\0';
1766c1829
< 	    host[sizeof(host)-1] = '\0';
---
>             host[sizeof(host)-1] = '\0';
1782c1845
< 	    host[sizeof(host)-1] = '\0';
---
>             host[sizeof(host)-1] = '\0';
1792c1855
< 	    host[sizeof(host)-1] = '\0';
---
>             host[sizeof(host)-1] = '\0';
1861c1924,1925
< #define limit_length(n)	(n > LONG_STRING_LEN-1 ? LONG_STRING_LEN-1 : n)
---
> #define limit_length(n) (n > LONG_STRING_LEN-1 ? LONG_STRING_LEN-1 : n)
> 
1921,1924c1985,1988
< 		if (cpO + n >= newuri + sizeof(newuri)) {
< 		    log_printf(r->server, "insufficient space in expand_map_lookups, aborting");
< 		    return;
< 		}
---
>                 if (cpO + n >= newuri + sizeof(newuri)) {
>                     log_printf(r->server, "insufficient space in expand_map_lookups, aborting");
>                     return;
>                 }
1930,1933c1994,1997
< 		if (cpO + n >= newuri + sizeof(newuri)) {
< 		    log_printf(r->server, "insufficient space in expand_map_lookups, aborting");
< 		    return;
< 		}
---
>                 if (cpO + n >= newuri + sizeof(newuri)) {
>                     log_printf(r->server, "insufficient space in expand_map_lookups, aborting");
>                     return;
>                 }
1943,1946c2007,2010
< 	    if (cpO + n >= newuri + sizeof(newuri)) {
< 		log_printf(r->server, "insufficient space in expand_map_lookups, aborting");
< 		return;
< 	    }
---
>             if (cpO + n >= newuri + sizeof(newuri)) {
>                 log_printf(r->server, "insufficient space in expand_map_lookups, aborting");
>                 return;
>             }
1957d2020
< #undef limit_length
1958a2022
> #undef limit_length
2064c2128
<     strncpy(output,  MAPFILE_OUTPUT, sizeof(output)-1);
---
>     strncpy(output, MAPFILE_OUTPUT, sizeof(output)-1);
2069d2132
< #ifdef HAS_APACHE_REGEX_LIB
2071,2074d2133
< #else
<         if (regexec(lookup_map_txtfile_regexp, line) != 0) {
< #endif
< #ifdef HAS_APACHE_REGEX_LIB
2076,2079c2135
< 	    result[sizeof(result)-1] = '\0';
< #else
<             regsub(lookup_map_txtfile_regexp, output, result);
< #endif
---
>             result[sizeof(result)-1] = '\0';
2105c2161
<     dbmkey.dsize = strlen(key) < sizeof(buf) - 1 : strlen(key) ? sizeof(buf)-1;
---
>     dbmkey.dsize = (strlen(key) < sizeof(buf) - 1 : strlen(key) ? sizeof(buf)-1);
2124a2181,2183
>     /* lock the channel */
>     fd_lock(fpin);
> 
2137a2197,2199
>     /* unlock the channel */
>     fd_unlock(fpin);
> 
2200c2262
<     /* For OS/2 we need to use a '/' */
---
>     /* OS/2 needs a '/' */
2217d2278
<     char *ruser;
2220a2282
>     char *ruser;
2238c2300,2301
<     } else if (strlen (connect->user) != 0) {
---
>     }
>     else if (strlen (connect->user) != 0) {
2240c2303,2304
<     } else {
---
>     }
>     else {
2242c2306
<     };
---
>     }
2246,2247c2310
<                             ruser,
<                             NULL);
---
>                             ruser, NULL);
2250,2256c2313,2316
<     if (r->main == NULL) {
<         strncpy(type, "initial", sizeof(type)-1);
< 	type[sizeof(type)-1] = '\0';
<     } else {
<         strncpy(type, "subreq", sizeof(type)-1);
< 	type[sizeof(type)-1] = '\0';
<     }
---
>     if (r->main == NULL)
>         strcpy(type, "initial");
>     else
>         strcpy(type, "subreq");
2261c2321
<         strcpy(redir, "");
---
>         redir[0] = '\0';
2266a2327
>     fd_lock(conf->rewritelogfp);
2267a2329
>     fd_unlock(conf->rewritelogfp);
2275d2336
< #ifdef IS_APACHE_12
2277,2279d2337
< #else
<     long timz;
< #endif
2289,2291c2347
<     strftime(tstr, 80,"[%d/%b/%Y:%H:%M:%S ",t);
< 
< #ifdef IS_APACHE_12
---
>     strftime(tstr, 80, "[%d/%b/%Y:%H:%M:%S ", t);
2293,2296d2348
< #else
<     ap_snprintf(tstr + strlen(tstr), 80-strlen(tstr), "%c%02ld%02ld]", sign, timz/3600, timz%3600);
< #endif
< 
2356c2408
<     /* For OS/2 we need to use a '/' */
---
>     /* OS/2 needs a '/' */
2360c2412
< #endif    
---
> #endif
2382c2434
< 	buf[buf_len-1] = '\0';
---
>         buf[buf_len-1] = '\0';
2404a2457
> 
2415c2468
< 	output[sizeof(output)-1] = '\0';
---
>         output[sizeof(output)-1] = '\0';
2426a2480,2483
>     request_rec *rsub;
>     struct passwd *pw;
>     struct group *gr;
>     struct stat finfo;
2493a2551,2553
>     else if (strcasecmp(var, "IS_SUBREQ") == 0) { /* non-standard */
>         result = (r->main != NULL ? "true" : "false");
>     }
2553c2613,2685
<         result = getenv(var+4);
---
>         /* first try the internal Apache notes structure */
>         result = table_get(r->notes, var+4);
>         /* second try the internal Apache env structure  */
>         if (result == NULL) 
>             result = table_get(r->subprocess_env, var+4);
>         /* third try the external OS env */
>         if (result == NULL) 
>             result = getenv(var+4);
>     }
> 
> #define LOOKAHEAD(subrecfunc) \
>         if ( \
>           /* filename is safe to use */ \
>           r->filename != NULL \
>               /* - and we're either not in a subrequest */ \
>               && ( r->main == NULL \
>                   /* - or in a subrequest where paths are non-NULL... */ \
>                     || ( r->main->uri != NULL && r->uri != NULL \
>                         /*   ...and sub and main paths differ */ \
>                         && strcmp(r->main->uri, r->uri) != 0))) { \
>             /* process a file-based subrequest */ \
>             rsub = subrecfunc(r->filename, r); \
>             /* now recursively lookup the variable in the sub_req */ \
>             result = lookup_variable(rsub, var+5); \
>             /* copy it up to our scope before we destroy the sub_req's pool */ \
>             result = pstrdup(r->pool, result); \
>             /* cleanup by destroying the subrequest */ \
>             destroy_sub_req(rsub); \
>             /* log it */ \
>             rewritelog(r, 5, "lookahead: path=%s var=%s -> val=%s", r->filename, var+5, result); \
>             /* return ourself to prevent re-pstrdup */ \
>             return result; \
>         }
> 
>     /* look-ahead for parameter through URI-based sub-request */
>     else if (strlen(var) > 5 && strncasecmp(var, "LA-U:", 5) == 0) {
>         LOOKAHEAD(sub_req_lookup_uri)
>     }
>     /* look-ahead for parameter through file-based sub-request */
>     else if (strlen(var) > 5 && strncasecmp(var, "LA-F:", 5) == 0) {
>         LOOKAHEAD(sub_req_lookup_file)
>     }
> 
>     /* file stuff */
>     else if (strcasecmp(var, "SCRIPT_USER") == 0) {
>         result = pstrdup(r->pool, "<unknown>");
>         if (r->finfo.st_mode != 0) {
>             if ((pw = getpwuid(r->finfo.st_uid)) != NULL) { 
>                 result = pstrdup(r->pool, pw->pw_name);
>             }
>         }
>         else {
>             if (stat(r->filename, &finfo) == 0) {
>                 if ((pw = getpwuid(finfo.st_uid)) != NULL) { 
>                     result = pstrdup(r->pool, pw->pw_name);
>                 }
>             }
>         }
>     }
>     else if (strcasecmp(var, "SCRIPT_GROUP") == 0) {
>         result = pstrdup(r->pool, "<unknown>");
>         if (r->finfo.st_mode != 0) {
>             if ((gr = getgrgid(r->finfo.st_gid)) != NULL) { 
>                 result = pstrdup(r->pool, gr->gr_name);
>             }
>         }
>         else {
>             if (stat(r->filename, &finfo) == 0) {
>                 if ((gr = getgrgid(finfo.st_gid)) != NULL) { 
>                     result = pstrdup(r->pool, gr->gr_name);
>                 }
>             }
>         }
2555,2556d2686
< 
<     /* uptime, load average, etc. .. */
2724d2853
< 
2738c2867
< 	substbuf[sizeof(substbuf)-1] = '\0';
---
>         substbuf[sizeof(substbuf)-1] = '\0';
2835a2965,2981
> void add_env_variable(request_rec *r, char *s)
> {
>     char var[MAX_STRING_LEN];
>     char val[MAX_STRING_LEN];
>     char *cp;
> 
>     if ((cp = strchr(s, ':')) != NULL) {
>         memcpy(var, s, cp-s);
>         var[cp-s] = '\0';
>         strcpy(val, cp+1);
>         table_set(r->subprocess_env, pstrdup(r->pool, var), pstrdup(r->pool, val));
>         rewritelog(r, 5, "setting env variable '%s' to '%s'", var, val);
>     }
> }
> 
> 
> 
2872c3018
<     _const char *names;
---
>     const char *names;
2995d3140
< #ifdef IS_APACHE_12
3011,3012c3156,3169
< #else
< int is_proxy_available(server_rec *s)
---
> 
> 
> /*
> **
> **  File locking
> **
> */
> 
> #ifdef USE_FCNTL
> static struct flock   lock_it = { F_WRLCK, 0, 0, 0 };
> static struct flock unlock_it = { F_UNLCK, 0, 0, 0 };
> #endif 
> 
> static void fd_lock(int fd)
3014,3020c3171,3186
<     extern char *module_names[];
<     int n;
<     
<     for (n = 0; module_names[n] != NULL; n++) {
<         if (strcmp(module_names[n], "proxy_module") == 0) {
<             return 1;
<         }
---
>     int rc;
> 
> #ifdef USE_FCNTL
>     while (   ((rc = fcntl(fd, F_SETLKW, &lock_it)) < 0) 
>            && (errno == EINTR)                               )
>         continue;
> #endif
> #ifdef USE_FLOCK
>     while (   ((rc = flock(fd, LOCK_EX)) < 0) 
>            && (errno == EINTR)               )
>         continue;
> #endif
> 
>     if (rc < 0) {
>         fprintf(stderr, "Error getting lock. Exiting!");
>         exit(1);
3022c3188
<     return 0;
---
>     return;
3023a3190,3196
> 
> static void fd_unlock(int fd)
> {
>     int rc;
> 
> #ifdef USE_FCNTL 
>     rc = fcntl(fd, F_SETLKW, &unlock_it);
3024a3198,3206
> #ifdef USE_FLOCK 
>     rc = flock(fd, LOCK_UN);
> #endif 
> 
>     if (rc < 0) {
>         fprintf(stderr, "Error freeing lock. Exiting!");
>         exit(1);
>     }
> }
0a1
> 
66c67
< **  URL Rewriting Module, Version 2.3.10 (20-12-1996)
---
> **  URL Rewriting Module, Version 3.0.0 (xx-02-1997)
86c87
< **  Copyright (c) 1996 Ralf S. Engelschall, All rights reserved.
---
> **  Copyright (c) 1996-1997 Ralf S. Engelschall, All rights reserved.
91c92
< **      http://www.engelschall.com/
---
> **      www.engelschall.com
97,123d97
<     /* Check Apache Release */
< #if (MODULE_MAGIC_NUMBER >= 19960725)
< #define IS_APACHE_12         1
< #define HAS_APACHE_REGEX_LIB 1
< #endif
< 
< 
<     /* The const problem:
<        The Apache Group changed some essential prototypes
<        to have an additional "const" qualifier. To be backward
<        compatible with Apache 1.1.1 we use a special define */
< #ifdef IS_APACHE_12
< #define _const const
< #else
< #define _const  
< #endif
< 
< 
<     /* The RegExp support:
<        For Apache 1.1.1 we provide our own Spencer V8 library,
<        for Apache 1.2 and higher there is a Spencer POSIX library
<        in the distribution */
< #ifndef HAS_APACHE_REGEX_LIB
< #include "regexp/regexp.h"
< #endif
< 
< 
137a112,135
>     /* The locking support:
>        Try to determine whether we should use
>        fcntl() or flock(). */
> #if defined(USE_FCNTL_SERIALIZED_ACCEPT)
> #define USE_FCNTL 1
> #include <fcntl.h>
> #endif
> #if defined(USE_FLOCK_SERIALIZED_ACCEPT)
> #define USE_FLOCK 1
> #include <sys/file.h>
> #endif
> #if !defined(USE_FCNTL) && !defined(USE_FLOCK)
> #define USE_FLOCK 1
> #include <sys/file.h>
> #ifndef LOCK_UN
> #undef USE_FLOCK
> #define USE_FCNTL 1
> #include <fcntl.h>
> #endif
> #endif
> 
> 
> 
> 
167a166
> #define RULEFLAG_GONE               1<<10
195a195,196
> #define MAX_ENV_FLAGS 5
> 
218d218
< #ifdef HAS_APACHE_REGEX_LIB
220,222d219
< #else
<     regexp  *regexp;               /* the RegExp pattern compilation */
< #endif
229d225
< #ifdef HAS_APACHE_REGEX_LIB
231,237c227,232
< #else
<     regexp       *regexp;
< #endif
<     char         *output;          /* the Substitution string */
<     int           flags;           /* Flags which control the substitution */
<     char         *forced_mimetype; /* forced MIME-type of substitution */
<     int           skip;            /* number of next rules to skip */
---
>     char         *output;              /* the Substitution string */
>     int           flags;               /* Flags which control the substitution */
>     char         *forced_mimetype;     /* forced MIME type of substitution */
>     int           forced_responsecode; /* forced HTTP redirect response status */
>     char         *env[MAX_ENV_FLAGS+1];/* added environment variables */
>     int           skip;                /* number of next rules to skip */
301,316c296,311
< static _const char *cmd_rewriteengine  (cmd_parms *cmd, rewrite_perdir_conf *dconf, int flag);
< static _const char *cmd_rewriteoptions (cmd_parms *cmd, rewrite_perdir_conf *dconf, char *option);
< static _const char *cmd_rewriteoptions_setoption(pool *p, int *options, char *name);
< static _const char *cmd_rewritelog     (cmd_parms *cmd, void *dconf, char *a1);
< static _const char *cmd_rewriteloglevel(cmd_parms *cmd, void *dconf, char *a1);
< static _const char *cmd_rewritemap     (cmd_parms *cmd, void *dconf, char *a1, char *a2);
< 
< static _const char *cmd_rewritebase(cmd_parms *cmd, rewrite_perdir_conf *dconf, char *a1);
< 
< static _const char *cmd_rewritecond    (cmd_parms *cmd, rewrite_perdir_conf *dconf, char *str);
< static _const char *cmd_rewritecond_parseflagfield(pool *p, rewritecond_entry *new, char *str);
< static _const char *cmd_rewritecond_setflag       (pool *p, rewritecond_entry *cfg, char *key, char *val);
< 
< extern _const char *cmd_rewriterule    (cmd_parms *cmd, rewrite_perdir_conf *dconf, char *str);
< static _const char *cmd_rewriterule_parseflagfield(pool *p, rewriterule_entry *new, char *str);
< static _const char *cmd_rewriterule_setflag       (pool *p, rewriterule_entry *cfg, char *key, char *val);
---
> static const char *cmd_rewriteengine  (cmd_parms *cmd, rewrite_perdir_conf *dconf, int flag);
> static const char *cmd_rewriteoptions (cmd_parms *cmd, rewrite_perdir_conf *dconf, char *option);
> static const char *cmd_rewriteoptions_setoption(pool *p, int *options, char *name);
> static const char *cmd_rewritelog     (cmd_parms *cmd, void *dconf, char *a1);
> static const char *cmd_rewriteloglevel(cmd_parms *cmd, void *dconf, char *a1);
> static const char *cmd_rewritemap     (cmd_parms *cmd, void *dconf, char *a1, char *a2);
> 
> static const char *cmd_rewritebase(cmd_parms *cmd, rewrite_perdir_conf *dconf, char *a1);
> 
> static const char *cmd_rewritecond    (cmd_parms *cmd, rewrite_perdir_conf *dconf, char *str);
> static const char *cmd_rewritecond_parseflagfield(pool *p, rewritecond_entry *new, char *str);
> static const char *cmd_rewritecond_setflag       (pool *p, rewritecond_entry *cfg, char *key, char *val);
> 
> extern const char *cmd_rewriterule    (cmd_parms *cmd, rewrite_perdir_conf *dconf, char *str);
> static const char *cmd_rewriterule_parseflagfield(pool *p, rewriterule_entry *new, char *str);
> static const char *cmd_rewriterule_setflag       (pool *p, rewriterule_entry *cfg, char *key, char *val);
372a368
> static void   add_env_variable(request_rec *r, char *s);
380a377,380
> 
>     /* File locking */
> static void fd_lock(int fd);
> static void fd_unlock(int fd);














=CONTEXT DIFF===========================
*** SNAP/src/mod_rewrite.c	Thu Jan 30 03:00:09 1997
--- src/mod_rewrite.c	Fri Jan 31 21:45:33 1997
***************
*** 1,3 ****
--- 1,4 ----
+  
  /* ====================================================================
   * Copyright (c) 1996,1997 The Apache Group.  All rights reserved.
   *
***************
*** 60,66 ****
  **  |_| |_| |_|\___/ \__,_|___|_|  \___| \_/\_/ |_|  |_|\__\___|
  **                       |_____|
  **
! **  URL Rewriting Module, Version 2.3.10 (20-12-1996)
  **
  **  This module uses a rule-based rewriting engine (based on a
  **  regular-expression parser) to rewrite requested URLs on the fly. 
--- 61,67 ----
  **  |_| |_| |_|\___/ \__,_|___|_|  \___| \_/\_/ |_|  |_|\__\___|
  **                       |_____|
  **
! **  URL Rewriting Module, Version 3.0.0 (xx-02-1997)
  **
  **  This module uses a rule-based rewriting engine (based on a
  **  regular-expression parser) to rewrite requested URLs on the fly. 
***************
*** 80,91 ****
  **  The documentation and latest release can be found on
  **  http://www.engelschall.com/sw/mod_rewrite/
  **
! **  Copyright (c) 1996 Ralf S. Engelschall, All rights reserved.
  **
  **  Written for The Apache Group by
  **      Ralf S. Engelschall
  **      rse@engelschall.com
! **      http://www.engelschall.com/
  */
  
  
--- 81,92 ----
  **  The documentation and latest release can be found on
  **  http://www.engelschall.com/sw/mod_rewrite/
  **
! **  Copyright (c) 1996-1997 Ralf S. Engelschall, All rights reserved.
  **
  **  Written for The Apache Group by
  **      Ralf S. Engelschall
  **      rse@engelschall.com
! **      www.engelschall.com
  */
  
  
***************
*** 96,101 ****
--- 97,105 ----
  #include <stdarg.h>
  #include <time.h>
  #include <signal.h>
+ #include <errno.h>
+ #include <pwd.h>
+ #include <grp.h>
  #include <sys/types.h>
  #include <sys/stat.h>
  #include <netinet/in.h>
***************
*** 110,120 ****
      /* now our own stuff ... */
  #include "mod_rewrite.h"
  
- #ifdef __EMX__
- /* OS/2 dosen't support links. */
- #define S_ISLNK
- #endif
- 
   
  
  
--- 114,119 ----
***************
*** 131,137 ****
  **
  **  our interface to the Apache server kernel
  **
! **  keep in mind:
  **
  **  o  Runtime logic of a request is as following:
  **
--- 130,136 ----
  **
  **  our interface to the Apache server kernel
  **
! **  keep in mind: 
  **
  **  o  Runtime logic of a request is as following:
  **
***************
*** 228,241 ****
  
      /* the txt mapfile parsing stuff */
  #define MAPFILE_PATTERN "^([^ ]+) +([^ ]+).*$"
- #ifdef HAS_APACHE_REGEX_LIB
  #define MAPFILE_OUTPUT "$1,$2"
  static regex_t   *lookup_map_txtfile_regexp = NULL;
  static regmatch_t lookup_map_txtfile_regmatch[10];
- #else
- #define MAPFILE_OUTPUT "\\1,\\2"
- static regexp *lookup_map_txtfile_regexp = NULL;
- #endif
  
  
  
--- 227,235 ----
***************
*** 356,362 ****
  **
  */
  
! static _const char *cmd_rewriteengine(cmd_parms *cmd, rewrite_perdir_conf *dconf, int flag)
  {
      rewrite_server_conf *sconf;
  
--- 350,356 ----
  **
  */
  
! static const char *cmd_rewriteengine(cmd_parms *cmd, rewrite_perdir_conf *dconf, int flag)
  {
      rewrite_server_conf *sconf;
  
***************
*** 369,378 ****
      return NULL;
  }
  
! static _const char *cmd_rewriteoptions(cmd_parms *cmd, rewrite_perdir_conf *dconf, char *option)
  {
      rewrite_server_conf *sconf;
!     _const char *err;
  
      sconf = (rewrite_server_conf *)get_module_config(cmd->server->module_config, &rewrite_module);
      if (cmd->path == NULL) /* is server command */
--- 363,372 ----
      return NULL;
  }
  
! static const char *cmd_rewriteoptions(cmd_parms *cmd, rewrite_perdir_conf *dconf, char *option)
  {
      rewrite_server_conf *sconf;
!     const char *err;
  
      sconf = (rewrite_server_conf *)get_module_config(cmd->server->module_config, &rewrite_module);
      if (cmd->path == NULL) /* is server command */
***************
*** 383,389 ****
      return err;
  }
  
! static _const char *cmd_rewriteoptions_setoption(pool *p, int *options, char *name)
  {
      if (strcasecmp(name, "inherit") == 0)
          *options |= OPTION_INHERIT;
--- 377,383 ----
      return err;
  }
  
! static const char *cmd_rewriteoptions_setoption(pool *p, int *options, char *name)
  {
      if (strcasecmp(name, "inherit") == 0)
          *options |= OPTION_INHERIT;
***************
*** 392,398 ****
      return NULL;
  }
  
! static _const char *cmd_rewritelog(cmd_parms *cmd, void *dconf, char *a1)
  {
      rewrite_server_conf *sconf;
  
--- 386,392 ----
      return NULL;
  }
  
! static const char *cmd_rewritelog(cmd_parms *cmd, void *dconf, char *a1)
  {
      rewrite_server_conf *sconf;
  
***************
*** 402,408 ****
      return NULL;
  }
  
! static _const char *cmd_rewriteloglevel(cmd_parms *cmd, void *dconf, char *a1)
  {
      rewrite_server_conf *sconf;
  
--- 396,402 ----
      return NULL;
  }
  
! static const char *cmd_rewriteloglevel(cmd_parms *cmd, void *dconf, char *a1)
  {
      rewrite_server_conf *sconf;
  
***************
*** 412,418 ****
      return NULL;
  }
  
! static _const char *cmd_rewritemap(cmd_parms *cmd, void *dconf, char *a1, char *a2)
  {
      rewrite_server_conf *sconf;
      rewritemap_entry *new;
--- 406,412 ----
      return NULL;
  }
  
! static const char *cmd_rewritemap(cmd_parms *cmd, void *dconf, char *a1, char *a2)
  {
      rewrite_server_conf *sconf;
      rewritemap_entry *new;
***************
*** 456,462 ****
      return NULL;
  }
  
! static _const char *cmd_rewritebase(cmd_parms *cmd, rewrite_perdir_conf *dconf, char *a1)
  {
      if (cmd->path == NULL || dconf == NULL)
          return "RewriteBase: only valid in per-directory config files";
--- 450,456 ----
      return NULL;
  }
  
! static const char *cmd_rewritebase(cmd_parms *cmd, rewrite_perdir_conf *dconf, char *a1)
  {
      if (cmd->path == NULL || dconf == NULL)
          return "RewriteBase: only valid in per-directory config files";
***************
*** 470,490 ****
      return NULL;
  }
  
! static _const char *cmd_rewritecond(cmd_parms *cmd, rewrite_perdir_conf *dconf, char *str)
  {
      rewrite_server_conf *sconf;
      rewritecond_entry *new;
- #ifdef HAS_APACHE_REGEX_LIB
      regex_t *regexp;
- #else
-     regexp *regexp;
-     int i;
- #endif
      char *a1;
      char *a2;
      char *a3;
      char *cp;
!     _const char *err;
      int rc;
  
      sconf = (rewrite_server_conf *)get_module_config(cmd->server->module_config, &rewrite_module);
--- 464,479 ----
      return NULL;
  }
  
! static const char *cmd_rewritecond(cmd_parms *cmd, rewrite_perdir_conf *dconf, char *str)
  {
      rewrite_server_conf *sconf;
      rewritecond_entry *new;
      regex_t *regexp;
      char *a1;
      char *a2;
      char *a3;
      char *cp;
!     const char *err;
      int rc;
  
      sconf = (rewrite_server_conf *)get_module_config(cmd->server->module_config, &rewrite_module);
***************
*** 522,539 ****
      /* now be careful: Under the POSIX regex library
         we can compile the pattern for case-insensitive matching,
         under the old V8 library we have to do it self via a hack */
- #ifdef HAS_APACHE_REGEX_LIB
      if (new->flags & CONDFLAG_NOCASE)
          rc = ((regexp = pregcomp(cmd->pool, cp, REG_EXTENDED|REG_ICASE)) == NULL);
      else
          rc = ((regexp = pregcomp(cmd->pool, cp, REG_EXTENDED)) == NULL);
- #else
-     if (new->flags & CONDFLAG_NOCASE) {
-         for (i = 0; cp[i] != '\0'; i++)
-             cp[i] = tolower(cp[i]);
-     }
-     rc = ((regexp = regcomp(cp)) == NULL);
- #endif
      if (rc)
          return pstrcat(cmd->pool, "RewriteCond: cannot compile regular expression '", a2, "'\n", NULL);
      new->pattern = pstrdup(cmd->pool, cp);
--- 511,520 ----
***************
*** 542,548 ****
      return NULL;
  }
  
! static _const char *cmd_rewritecond_parseflagfield(pool *p, rewritecond_entry *cfg, char *str)
  {
      char *cp;
      char *cp1;
--- 523,529 ----
      return NULL;
  }
  
! static const char *cmd_rewritecond_parseflagfield(pool *p, rewritecond_entry *cfg, char *str)
  {
      char *cp;
      char *cp1;
***************
*** 550,556 ****
      char *cp3;
      char *key;
      char *val;
!     _const char *err;
  
      if (str[0] != '[' || str[strlen(str)-1] != ']')
          return pstrdup(p, "RewriteCond: bad flag delimiters");
--- 531,537 ----
      char *cp3;
      char *key;
      char *val;
!     const char *err;
  
      if (str[0] != '[' || str[strlen(str)-1] != ']')
          return pstrdup(p, "RewriteCond: bad flag delimiters");
***************
*** 576,582 ****
              }
              else {
                  key = cp1;
!                 val = "yes";
              }
              if ((err = cmd_rewritecond_setflag(p, cfg, key, val)) != NULL)
                  return err;
--- 557,563 ----
              }
              else {
                  key = cp1;
!                 val = "";
              }
              if ((err = cmd_rewritecond_setflag(p, cfg, key, val)) != NULL)
                  return err;
***************
*** 588,594 ****
      return NULL;
  }
  
! static _const char *cmd_rewritecond_setflag(pool *p, rewritecond_entry *cfg, char *key, char *val)
  {
      if (   strcasecmp(key, "nocase") == 0
          || strcasecmp(key, "NC") == 0    ) {
--- 569,575 ----
      return NULL;
  }
  
! static const char *cmd_rewritecond_setflag(pool *p, rewritecond_entry *cfg, char *key, char *val)
  {
      if (   strcasecmp(key, "nocase") == 0
          || strcasecmp(key, "NC") == 0    ) {
***************
*** 605,625 ****
  }
  
  /* NON static */
! _const char *cmd_rewriterule(cmd_parms *cmd, rewrite_perdir_conf *dconf, char *str)
  {
      rewrite_server_conf *sconf;
      rewriterule_entry *new;
- #ifdef HAS_APACHE_REGEX_LIB
      regex_t *regexp;
- #else
-     regexp *regexp;
-     int i;
- #endif
      char *a1;
      char *a2;
      char *a3;
      char *cp;
!     _const char *err;
  
      sconf = (rewrite_server_conf *)get_module_config(cmd->server->module_config, &rewrite_module);
  
--- 586,601 ----
  }
  
  /* NON static */
! const char *cmd_rewriterule(cmd_parms *cmd, rewrite_perdir_conf *dconf, char *str)
  {
      rewrite_server_conf *sconf;
      rewriterule_entry *new;
      regex_t *regexp;
      char *a1;
      char *a2;
      char *a3;
      char *cp;
!     const char *err;
  
      sconf = (rewrite_server_conf *)get_module_config(cmd->server->module_config, &rewrite_module);
  
***************
*** 641,651 ****
          new->flags |= RULEFLAG_NOTMATCH;
          cp++;
      }
- #ifdef HAS_APACHE_REGEX_LIB
      if ((regexp = pregcomp(cmd->pool, cp, REG_EXTENDED)) == NULL)
- #else
-     if ((regexp = regcomp(cp)) == NULL)
- #endif
          return pstrcat(cmd->pool, "RewriteRule: cannot compile regular expression '", a1, "'\n", NULL);
      new->pattern = pstrdup(cmd->pool, cp);
      new->regexp  = regexp;
--- 617,623 ----
***************
*** 653,668 ****
      /*  arg2: the output string
          replace the $<N> by \<n> which is needed by the currently
          used Regular Expression library */
- #ifndef HAS_APACHE_REGEX_LIB
-     for (i = 0; a2[i] != '\0'; i++) {
-         if (a2[i] == '$' && a2[i+1] >= '1' && a2[i+1] <= '9') 
-             a2[i] = '\\';
-     }
- #endif
      new->output = pstrdup(cmd->pool, a2);
  
      /* arg3: optional flags field */
      new->forced_mimetype = NULL;
      new->skip = 0;
      if (a3 != NULL) {
          if ((err = cmd_rewriterule_parseflagfield(cmd->pool, new, a3)) != NULL)
--- 625,636 ----
      /*  arg2: the output string
          replace the $<N> by \<n> which is needed by the currently
          used Regular Expression library */
      new->output = pstrdup(cmd->pool, a2);
  
      /* arg3: optional flags field */
      new->forced_mimetype = NULL;
+     new->forced_responsecode = HTTP_MOVED_TEMPORARILY;
+     new->env[0] = NULL;
      new->skip = 0;
      if (a3 != NULL) {
          if ((err = cmd_rewriterule_parseflagfield(cmd->pool, new, a3)) != NULL)
***************
*** 684,690 ****
      return NULL;
  }
  
! static _const char *cmd_rewriterule_parseflagfield(pool *p, rewriterule_entry *cfg, char *str)
  {
      char *cp;
      char *cp1;
--- 652,658 ----
      return NULL;
  }
  
! static const char *cmd_rewriterule_parseflagfield(pool *p, rewriterule_entry *cfg, char *str)
  {
      char *cp;
      char *cp1;
***************
*** 692,698 ****
      char *cp3;
      char *key;
      char *val;
!     _const char *err;
  
      if (str[0] != '[' || str[strlen(str)-1] != ']')
          return pstrdup(p, "RewriteRule: bad flag delimiters");
--- 660,666 ----
      char *cp3;
      char *key;
      char *val;
!     const char *err;
  
      if (str[0] != '[' || str[strlen(str)-1] != ']')
          return pstrdup(p, "RewriteRule: bad flag delimiters");
***************
*** 718,724 ****
              }
              else {
                  key = cp1;
!                 val = "yes";
              }
              if ((err = cmd_rewriterule_setflag(p, cfg, key, val)) != NULL)
                  return err;
--- 686,692 ----
              }
              else {
                  key = cp1;
!                 val = "";
              }
              if ((err = cmd_rewriterule_setflag(p, cfg, key, val)) != NULL)
                  return err;
***************
*** 730,740 ****
      return NULL;
  }
  
! static _const char *cmd_rewriterule_setflag(pool *p, rewriterule_entry *cfg, char *key, char *val)
  {
      if (   strcasecmp(key, "redirect") == 0
          || strcasecmp(key, "R") == 0       ) {
          cfg->flags |= RULEFLAG_FORCEREDIRECT;
      }
      else if (   strcasecmp(key, "last") == 0
               || strcasecmp(key, "L") == 0   ) {
--- 698,724 ----
      return NULL;
  }
  
! static const char *cmd_rewriterule_setflag(pool *p, rewriterule_entry *cfg, char *key, char *val)
  {
+     int status = 0;
+     int i;
+ 
      if (   strcasecmp(key, "redirect") == 0
          || strcasecmp(key, "R") == 0       ) {
          cfg->flags |= RULEFLAG_FORCEREDIRECT;
+         if (strlen(val) > 0) {
+             if (strcasecmp(val, "permanent") == 0)
+                 status = HTTP_MOVED_PERMANENTLY;
+             else if (strcasecmp(val, "temp") == 0)
+                 status = HTTP_MOVED_TEMPORARILY;
+             else if (strcasecmp(val, "seeother") == 0)
+                 status = HTTP_SEE_OTHER;
+             else if (isdigit(*val))
+                 status = atoi(val);
+             if (!is_HTTP_REDIRECT(status))
+                 return pstrdup(p, "RewriteRule: invalid HTTP response code for flag 'R'");
+             cfg->forced_responsecode = status;
+         }
      }
      else if (   strcasecmp(key, "last") == 0
               || strcasecmp(key, "L") == 0   ) {
***************
*** 752,757 ****
--- 736,752 ----
               || strcasecmp(key, "T") == 0   ) {
          cfg->forced_mimetype = pstrdup(p, val);
      }
+     else if (   strcasecmp(key, "env") == 0
+              || strcasecmp(key, "E") == 0   ) {
+         for (i = 0; (cfg->env[i] != NULL) && (i < MAX_ENV_FLAGS); i++)
+             ;
+         if (i < MAX_ENV_FLAGS) {
+             cfg->env[i] = pstrdup(p, val);
+             cfg->env[i+1] = NULL;
+         }
+         else 
+             return pstrdup(p, "RewriteRule: to much environment flags 'E'");
+     }
      else if (   strcasecmp(key, "nosubreq") == 0
               || strcasecmp(key, "NS") == 0      ) {
          cfg->flags |= RULEFLAG_IGNOREONSUBREQ;
***************
*** 772,777 ****
--- 767,776 ----
               || strcasecmp(key, "F") == 0   ) {
          cfg->flags |= RULEFLAG_FORBIDDEN;
      }
+     else if (   strcasecmp(key, "gone") == 0
+              || strcasecmp(key, "G") == 0   ) {
+         cfg->flags |= RULEFLAG_GONE;
+     }
      else {
          return pstrcat(p, "RewriteRule: unknown flag '", key, "'\n", NULL);
      }
***************
*** 805,815 ****
  
      /* precompile a static pattern 
         for the txt mapfile parsing */
- #ifdef HAS_APACHE_REGEX_LIB
      lookup_map_txtfile_regexp = pregcomp(p, MAPFILE_PATTERN, REG_EXTENDED);
- #else
-     lookup_map_txtfile_regexp = regcomp(MAPFILE_PATTERN);
- #endif
  }
  
  
--- 804,810 ----
***************
*** 971,985 ****
              if (r->args != NULL)
                 r->filename = pstrcat(r->pool, r->filename, "?", r->args, NULL);
  
              table_set(r->headers_out, "Location", r->filename);
!             rewritelog(r, 1, "redirect to %s [REDIRECT]", r->filename);
!             return REDIRECT;
          }
          else if (strlen(r->filename) > 10 &&
                   strncmp(r->filename, "forbidden:", 10) == 0) {
              /* This URLs is forced to be forbidden for the requester */
              return FORBIDDEN; 
          }
          else if (strlen(r->filename) > 12 &&
                   strncmp(r->filename, "passthrough:", 12) == 0) {
              /* Hack because of underpowered API: passing the current
--- 966,994 ----
              if (r->args != NULL)
                 r->filename = pstrcat(r->pool, r->filename, "?", r->args, NULL);
  
+             /* determine HTTP redirect response code */
+             if (is_HTTP_REDIRECT(r->status)) {
+                 n = r->status; 
+                 r->status = HTTP_OK; /* make Apache kernel happy */
+             }
+             else
+                 n = REDIRECT;
+ 
+             /* now do the redirection */
              table_set(r->headers_out, "Location", r->filename);
!             rewritelog(r, 1, "redirect to %s [REDIRECT/%d]", r->filename, n);
!             return n;
          }
          else if (strlen(r->filename) > 10 &&
                   strncmp(r->filename, "forbidden:", 10) == 0) {
              /* This URLs is forced to be forbidden for the requester */
              return FORBIDDEN; 
          }
+         else if (strlen(r->filename) > 5 &&
+                  strncmp(r->filename, "gone:", 5) == 0) {
+             /* This URLs is forced to be gone */
+             return HTTP_GONE; 
+         }
          else if (strlen(r->filename) > 12 &&
                   strncmp(r->filename, "passthrough:", 12) == 0) {
              /* Hack because of underpowered API: passing the current
***************
*** 1009,1018 ****
  
                 NOTICE:
                 We cannot leave out the prefix_stat because
!                - when we allways prefix with document_root
                   then no absolute path can be created, e.g. via 
!                  remulating a ScriptAlias directive, etc.
!                - when we allways NOT prefix with document_root
                   then the files under document_root have to
                   be references directly and document_root
                   gets never used and will be a dummy parameter -
--- 1018,1027 ----
  
                 NOTICE:
                 We cannot leave out the prefix_stat because
!                - when we always prefix with document_root
                   then no absolute path can be created, e.g. via 
!                  emulating a ScriptAlias directive, etc.
!                - when we always NOT prefix with document_root
                   then the files under document_root have to
                   be references directly and document_root
                   gets never used and will be a dummy parameter -
***************
*** 1027,1033 ****
              if (n == 0) {
                  if ((cp = document_root(r)) != NULL) {
                      strncpy(docroot, cp, sizeof(docroot)-1);
! 		    docroot[sizeof(docroot)-1] = '\0';
  
                      /* allways NOT have a trailing slash */
                      l = strlen(docroot);
--- 1036,1042 ----
              if (n == 0) {
                  if ((cp = document_root(r)) != NULL) {
                      strncpy(docroot, cp, sizeof(docroot)-1);
!                     docroot[sizeof(docroot)-1] = '\0';
  
                      /* allways NOT have a trailing slash */
                      l = strlen(docroot);
***************
*** 1093,1098 ****
--- 1102,1108 ----
      char *cp2;
      char *prefix;
      int l;
+     int n;
  
      dconf = (rewrite_perdir_conf *)get_module_config(r->per_dir_config, &rewrite_module);
  
***************
*** 1200,1214 ****
              if (r->args != NULL)
                 r->filename = pstrcat(r->pool, r->filename, "?", r->args, NULL);
  
              table_set(r->headers_out, "Location", r->filename);
!             rewritelog(r, 1, "[per-dir %s] redirect to %s [REDIRECT]", dconf->directory, r->filename);
!             return REDIRECT;
          }
          else if (strlen(r->filename) > 10 &&
                   strncmp(r->filename, "forbidden:", 10) == 0) {
              /* This URLs is forced to be forbidden for the requester */
              return FORBIDDEN; 
          }
          else {
              /* it was finally rewritten to a local path */
  
--- 1210,1238 ----
              if (r->args != NULL)
                 r->filename = pstrcat(r->pool, r->filename, "?", r->args, NULL);
  
+             /* determine HTTP redirect response code */
+             if (is_HTTP_REDIRECT(r->status)) {
+                 n = r->status; 
+                 r->status = HTTP_OK; /* make Apache kernel happy */
+             }
+             else
+                 n = REDIRECT;
+ 
+             /* now do the redirection */
              table_set(r->headers_out, "Location", r->filename);
!             rewritelog(r, 1, "[per-dir %s] redirect to %s [REDIRECT/%d]", dconf->directory, r->filename, n);
!             return n;
          }
          else if (strlen(r->filename) > 10 &&
                   strncmp(r->filename, "forbidden:", 10) == 0) {
              /* This URLs is forced to be forbidden for the requester */
              return FORBIDDEN; 
          }
+         else if (strlen(r->filename) > 5 &&
+                  strncmp(r->filename, "gone:", 5) == 0) {
+             /* This URLs is forced to be gone */
+             return HTTP_GONE; 
+         }
          else {
              /* it was finally rewritten to a local path */
  
***************
*** 1342,1347 ****
--- 1366,1377 ----
                  changed = 1;
                  break;
              }
+             if (p->flags & RULEFLAG_GONE) {
+                 rewritelog(r, 2, "forcing '%s' to be gone", r->filename);
+                 r->filename = pstrcat(r->pool, "gone:", r->filename, NULL);
+                 changed = 1;
+                 break;
+             }
              if (p->flags & RULEFLAG_PROXY) 
                  break;
              if (p->flags & RULEFLAG_LASTRULE) 
***************
*** 1379,1391 ****
      char *output;
      int flags;
      char newuri[MAX_STRING_LEN];
      char port[32];
! #ifdef HAS_APACHE_REGEX_LIB
      regex_t *regexp;
      regmatch_t regmatch[10];
- #else
-     regexp *regexp;
- #endif
      int rc;
      int prefixstrip;
      int i;
--- 1409,1419 ----
      char *output;
      int flags;
      char newuri[MAX_STRING_LEN];
+     char env[MAX_STRING_LEN];
      char port[32];
!     char env2[MAX_STRING_LEN];
      regex_t *regexp;
      regmatch_t regmatch[10];
      int rc;
      int prefixstrip;
      int i;
***************
*** 1418,1428 ****
      if (perdir != NULL) 
          rewritelog(r, 3, "[per-dir %s] applying pattern '%s' to uri '%s'", perdir, p->pattern, uri);
  
- #ifdef HAS_APACHE_REGEX_LIB
      rc = (regexec(regexp, uri, regexp->re_nsub+1, regmatch, 0) == 0);   /* try to match the pattern */
- #else
-     rc = (regexec(regexp, uri) != 0);   /* try to match the pattern */
- #endif
      if (( rc && !(p->flags & RULEFLAG_NOTMATCH)) ||
          (!rc &&  (p->flags & RULEFLAG_NOTMATCH))   ) {     
  
--- 1446,1452 ----
***************
*** 1473,1490 ****
              if (p->flags & RULEFLAG_NOTMATCH) {
                  output = pstrcat(r->pool, "proxy:", output, NULL);
                  strncpy(newuri, output, sizeof(newuri)-1);
! 		newuri[sizeof(newuri)-1] = '\0';
                  expand_variables_inbuffer(r, newuri, sizeof(newuri));/* expand %{...} */
                  expand_map_lookups(r, newuri, sizeof(newuri));       /* expand ${...} */
              }
              else {
                  output = pstrcat(r->pool, "proxy:", output, NULL);
- #ifdef HAS_APACHE_REGEX_LIB
                  strncpy(newuri, pregsub(r->pool, output, uri, regexp->re_nsub+1, regmatch), sizeof(newuri)-1);    /* substitute in output */
! 		newuri[sizeof(newuri)-1] = '\0';
! #else
!                 regsub(regexp, output, newuri);                      /* substitute in output */
! #endif
                  expand_variables_inbuffer(r, newuri, sizeof(newuri));   /* expand %{...} */
                  expand_map_lookups(r, newuri, sizeof(newuri));          /* expand ${...} */
              }
--- 1497,1514 ----
              if (p->flags & RULEFLAG_NOTMATCH) {
                  output = pstrcat(r->pool, "proxy:", output, NULL);
                  strncpy(newuri, output, sizeof(newuri)-1);
!                 newuri[sizeof(newuri)-1] = '\0';
                  expand_variables_inbuffer(r, newuri, sizeof(newuri));/* expand %{...} */
                  expand_map_lookups(r, newuri, sizeof(newuri));       /* expand ${...} */
              }
              else {
                  output = pstrcat(r->pool, "proxy:", output, NULL);
                  strncpy(newuri, pregsub(r->pool, output, uri, regexp->re_nsub+1, regmatch), sizeof(newuri)-1);    /* substitute in output */
!                 for (i = 0; p->env[i] != NULL; i++) {
!                     strcpy(env2, p->env[i]);
!                     strcpy(env, pregsub(r->pool, env2, uri, regexp->re_nsub+1, regmatch));    /* substitute in output */
!                     add_env_variable(r, env);
!                 }
                  expand_variables_inbuffer(r, newuri, sizeof(newuri));   /* expand %{...} */
                  expand_map_lookups(r, newuri, sizeof(newuri));          /* expand ${...} */
              }
***************
*** 1507,1523 ****
  #endif
              if (p->flags & RULEFLAG_NOTMATCH) {
                  strncpy(newuri, output, sizeof(newuri)-1);
! 		newuri[sizeof(newuri)-1] = '\0';
                  expand_variables_inbuffer(r, newuri, sizeof(newuri));/* expand %{...} */
                  expand_map_lookups(r, newuri, sizeof(newuri));       /* expand ${...} */
              }
              else {
- #ifdef HAS_APACHE_REGEX_LIB
                  strncpy(newuri, pregsub(r->pool, output, uri, regexp->re_nsub+1, regmatch), sizeof(newuri)-1);    /* substitute in output */
! 		newuri[sizeof(newuri)-1] = '\0';
! #else
!                 regsub(regexp, output, newuri);                      /* substitute in output */
! #endif
                  expand_variables_inbuffer(r, newuri, sizeof(newuri));/* expand %{...} */
                  expand_map_lookups(r, newuri, sizeof(newuri));       /* expand ${...} */
              }
--- 1531,1548 ----
  #endif
              if (p->flags & RULEFLAG_NOTMATCH) {
                  strncpy(newuri, output, sizeof(newuri)-1);
!                 newuri[sizeof(newuri)-1] = '\0';
                  expand_variables_inbuffer(r, newuri, sizeof(newuri));/* expand %{...} */
                  expand_map_lookups(r, newuri, sizeof(newuri));       /* expand ${...} */
              }
              else {
                  strncpy(newuri, pregsub(r->pool, output, uri, regexp->re_nsub+1, regmatch), sizeof(newuri)-1);    /* substitute in output */
!                 newuri[sizeof(newuri)-1] = '\0';
!                 for (i = 0; p->env[i] != NULL; i++) {
!                     strcpy(env2, p->env[i]);
!                     strcpy(env, pregsub(r->pool, env2, uri, regexp->re_nsub+1, regmatch));    /* substitute in output */
!                     add_env_variable(r, env);
!                 }
                  expand_variables_inbuffer(r, newuri, sizeof(newuri));/* expand %{...} */
                  expand_map_lookups(r, newuri, sizeof(newuri));       /* expand ${...} */
              }
***************
*** 1538,1556 ****
          if (p->flags & RULEFLAG_NOTMATCH) {
              /* just overtake the URI */
              strncpy(newuri, output, sizeof(newuri)-1);
! 	    newuri[sizeof(newuri)-1] = '\0';
          }
          else {
              /* substitute in output */
- #ifdef HAS_APACHE_REGEX_LIB
              strncpy(newuri, pregsub(r->pool, output, uri, regexp->re_nsub+1, regmatch), sizeof(newuri)-1);    /* substitute in output */
! 	    newuri[sizeof(newuri)-1] = '\0'; 
! #else
!             regsub(regexp, output, newuri);                      /* substitute in output */
! #endif
          }
          expand_variables_inbuffer(r, newuri, sizeof(newuri));  /* expand %{...} */
!         expand_map_lookups(r, newuri, sizeof(newuri));   /* expand ${...} */
  
          if (perdir == NULL)
              rewritelog(r, 2, "rewrite %s -> %s", uri, newuri);
--- 1563,1582 ----
          if (p->flags & RULEFLAG_NOTMATCH) {
              /* just overtake the URI */
              strncpy(newuri, output, sizeof(newuri)-1);
!             newuri[sizeof(newuri)-1] = '\0';
          }
          else {
              /* substitute in output */
              strncpy(newuri, pregsub(r->pool, output, uri, regexp->re_nsub+1, regmatch), sizeof(newuri)-1);    /* substitute in output */
!             newuri[sizeof(newuri)-1] = '\0'; 
!             for (i = 0; p->env[i] != NULL; i++) {
!                 strcpy(env2, p->env[i]);
!                 strcpy(env, pregsub(r->pool, env2, uri, regexp->re_nsub+1, regmatch));    /* substitute in output */
!                 add_env_variable(r, env);
!             }
          }
          expand_variables_inbuffer(r, newuri, sizeof(newuri));  /* expand %{...} */
!         expand_map_lookups(r, newuri, sizeof(newuri));         /* expand ${...} */
  
          if (perdir == NULL)
              rewritelog(r, 2, "rewrite %s -> %s", uri, newuri);
***************
*** 1611,1616 ****
--- 1637,1643 ----
                  else
                      rewritelog(r, 2, "[per-dir %s] prepare forced redirect %s -> %s", perdir, r->filename, newuri);
                  r->filename = pstrdup(r->pool, newuri);
+                 r->status = p->forced_responsecode;
                  return 1;
              }
          }
***************
*** 1622,1634 ****
  
  static int apply_rewrite_cond(request_rec *r, rewritecond_entry *p, char *perdir)
  {
- #ifndef HAS_APACHE_REGEX_LIB
-     char inputbuf[LONG_STRING_LEN];
-     int i;
- #endif
      char *input;
      int rc;
      struct stat sb;
  
      /* first, we have to expand the input string to match */
      input = expand_variables(r, p->input);
--- 1649,1658 ----
  
  static int apply_rewrite_cond(request_rec *r, rewritecond_entry *p, char *perdir)
  {
      char *input;
      int rc;
      struct stat sb;
+     request_rec *rsub;
  
      /* first, we have to expand the input string to match */
      input = expand_variables(r, p->input);
***************
*** 1645,1675 ****
                  rc = 1;
      }
      else if (strcmp(p->pattern, "-l") == 0) {
          if (stat(input, &sb) == 0)
              if (S_ISLNK(sb.st_mode))
                  rc = 1;
      }
      else if (strcmp(p->pattern, "-d") == 0) {
          if (stat(input, &sb) == 0)
              if (S_ISDIR(sb.st_mode))
                  rc = 1;
      }
      else {
          /* it is really a regexp pattern, so apply it */
- #ifdef HAS_APACHE_REGEX_LIB
          rc = (regexec(p->regexp, input, 0, NULL, 0) == 0);
- #else
-         if (p->flags & CONDFLAG_NOCASE) {
-             for (i = 0; input[i] != '\0' && i < sizeof(inputbuf)-1 ; i++)
-                 inputbuf[i] = tolower(input[i]);
-             inputbuf[i] = '\0';
-         }
-         else {
-             strncpy(inputbuf, input, sizeof(inputbuf)-1);
- 	    inputbuf[sizeof(inputbuf)-1] = '\0';
-         }
-         rc = (regexec(p->regexp, inputbuf) != 0);
- #endif
      }
  
      /* if this is a non-matching regexp, just negate the result */ 
--- 1669,1738 ----
                  rc = 1;
      }
      else if (strcmp(p->pattern, "-l") == 0) {
+ #ifndef __EMX__
+ /* OS/2 dosen't support links. */
          if (stat(input, &sb) == 0)
              if (S_ISLNK(sb.st_mode))
                  rc = 1;
+ #endif
      }
      else if (strcmp(p->pattern, "-d") == 0) {
          if (stat(input, &sb) == 0)
              if (S_ISDIR(sb.st_mode))
                  rc = 1;
      }
+     else if (strcmp(p->pattern, "-U") == 0) {
+         /* avoid infinite subrequest recursion */
+         if (strlen(input) > 0               /* nonempty path, and */
+             && (   r->main == NULL          /* - either not in a subrequest */
+                 || (   r->main->uri != NULL /* - or in a subrequest...*/
+                     && r->uri != NULL       /*   ...and then URIs aren't NULL... */
+                                             /*   ...and sub and main URIs differ */
+                     && strcmp(r->main->uri, r->uri) != 0) ) ) {
+ 
+             /* run a URI-based subrequest */
+             rsub = sub_req_lookup_uri(input, r);
+ 
+             /* URI exists for any result up to 3xx, redirects allowed */
+             if (rsub->status < 400)
+                 rc = 1;
+ 
+             /* log it */
+             rewritelog(r, 5, "RewriteCond URI (-U) check: path=%s -> status=%d", input, rsub->status);
+ 
+             /* cleanup by destroying the subrequest */
+             destroy_sub_req(rsub);
+         }
+     }
+     else if (strcmp(p->pattern, "-F") == 0) {
+         /* avoid infinite subrequest recursion */
+         if (strlen(input) > 0               /* nonempty path, and */
+             && (   r->main == NULL          /* - either not in a subrequest */
+                 || (   r->main->uri != NULL /* - or in a subrequest...*/
+                     && r->uri != NULL       /*   ...and then URIs aren't NULL... */
+                                             /*   ...and sub and main URIs differ */
+                     && strcmp(r->main->uri, r->uri) != 0) ) ) {
+ 
+             /* process a file-based subrequest: 
+                this differs from -U in that no path translation is done. */
+             rsub = sub_req_lookup_file(input, r);
+  
+             /* file exists for any result up to 2xx, no redirects */
+             if (rsub->status < 300 &&
+                 /* double-check that file exists since default result is 200 */
+                 stat(rsub->filename, &sb) == 0)
+                 rc = 1;
+ 
+             /* log it */
+             rewritelog(r, 5, "RewriteCond file (-F) check: path=%s -> file=%s status=%d", input, rsub->filename, rsub->status);
+ 
+             /* cleanup by destroying the subrequest */
+             destroy_sub_req(rsub);
+         }
+     }
      else {
          /* it is really a regexp pattern, so apply it */
          rc = (regexec(p->regexp, input, 0, NULL, 0) == 0);
      }
  
      /* if this is a non-matching regexp, just negate the result */ 
***************
*** 1755,1761 ****
  #else
          strncpy(buf, r->filename+7, sizeof(buf)-1);
  #endif
! 	buf[sizeof(buf)-1] = '\0';
          hostp = buf;
          for (cp = hostp; *cp != '\0' && *cp != '/' && *cp != ':'; cp++)
              ;
--- 1818,1824 ----
  #else
          strncpy(buf, r->filename+7, sizeof(buf)-1);
  #endif
!         buf[sizeof(buf)-1] = '\0';
          hostp = buf;
          for (cp = hostp; *cp != '\0' && *cp != '/' && *cp != ':'; cp++)
              ;
***************
*** 1763,1769 ****
              /* set host */
              *cp++ = '\0';
              strncpy(host, hostp, sizeof(host)-1);
! 	    host[sizeof(host)-1] = '\0';
              /* set port */
              portp = cp;
              for (; *cp != '\0' && *cp != '/'; cp++)
--- 1826,1832 ----
              /* set host */
              *cp++ = '\0';
              strncpy(host, hostp, sizeof(host)-1);
!             host[sizeof(host)-1] = '\0';
              /* set port */
              portp = cp;
              for (; *cp != '\0' && *cp != '/'; cp++)
***************
*** 1779,1785 ****
              /* set host */
              *cp = '\0';
              strncpy(host, hostp, sizeof(host)-1);
! 	    host[sizeof(host)-1] = '\0';
              *cp = '/';
              /* set port */
              port = 80;
--- 1842,1848 ----
              /* set host */
              *cp = '\0';
              strncpy(host, hostp, sizeof(host)-1);
!             host[sizeof(host)-1] = '\0';
              *cp = '/';
              /* set port */
              port = 80;
***************
*** 1789,1795 ****
          else {
              /* set host */
              strncpy(host, hostp, sizeof(host)-1);
! 	    host[sizeof(host)-1] = '\0';
              /* set port */
              port = 80;
              /* set remaining url */
--- 1852,1858 ----
          else {
              /* set host */
              strncpy(host, hostp, sizeof(host)-1);
!             host[sizeof(host)-1] = '\0';
              /* set port */
              port = 80;
              /* set remaining url */
***************
*** 1858,1864 ****
  **
  */
  
! #define limit_length(n)	(n > LONG_STRING_LEN-1 ? LONG_STRING_LEN-1 : n)
  static void expand_map_lookups(request_rec *r, char *uri, int uri_len)
  {
      char newuri[MAX_STRING_LEN];
--- 1921,1928 ----
  **
  */
  
! #define limit_length(n) (n > LONG_STRING_LEN-1 ? LONG_STRING_LEN-1 : n)
! 
  static void expand_map_lookups(request_rec *r, char *uri, int uri_len)
  {
      char newuri[MAX_STRING_LEN];
***************
*** 1918,1936 ****
              cpT = lookup_map(r, mapname, mapkey);
              if (cpT != NULL) {
                  n = strlen(cpT);
! 		if (cpO + n >= newuri + sizeof(newuri)) {
! 		    log_printf(r->server, "insufficient space in expand_map_lookups, aborting");
! 		    return;
! 		}
                  memcpy(cpO, cpT, n);
                  cpO += n;
              }
              else {
                  n = strlen(defaultvalue);
! 		if (cpO + n >= newuri + sizeof(newuri)) {
! 		    log_printf(r->server, "insufficient space in expand_map_lookups, aborting");
! 		    return;
! 		}
                  memcpy(cpO, defaultvalue, n);
                  cpO += n;
              }
--- 1982,2000 ----
              cpT = lookup_map(r, mapname, mapkey);
              if (cpT != NULL) {
                  n = strlen(cpT);
!                 if (cpO + n >= newuri + sizeof(newuri)) {
!                     log_printf(r->server, "insufficient space in expand_map_lookups, aborting");
!                     return;
!                 }
                  memcpy(cpO, cpT, n);
                  cpO += n;
              }
              else {
                  n = strlen(defaultvalue);
!                 if (cpO + n >= newuri + sizeof(newuri)) {
!                     log_printf(r->server, "insufficient space in expand_map_lookups, aborting");
!                     return;
!                 }
                  memcpy(cpO, defaultvalue, n);
                  cpO += n;
              }
***************
*** 1940,1949 ****
              if (cpT == NULL)
                  cpT = cpI+strlen(cpI);
              n = cpT-cpI;
! 	    if (cpO + n >= newuri + sizeof(newuri)) {
! 		log_printf(r->server, "insufficient space in expand_map_lookups, aborting");
! 		return;
! 	    }
              memcpy(cpO, cpI, n);
              cpO += n;
              cpI += n;
--- 2004,2013 ----
              if (cpT == NULL)
                  cpT = cpI+strlen(cpI);
              n = cpT-cpI;
!             if (cpO + n >= newuri + sizeof(newuri)) {
!                 log_printf(r->server, "insufficient space in expand_map_lookups, aborting");
!                 return;
!             }
              memcpy(cpO, cpI, n);
              cpO += n;
              cpI += n;
***************
*** 1954,1961 ****
      uri[uri_len-1] = '\0';
      return;
  }
- #undef limit_length
  
  
  
  
--- 2018,2025 ----
      uri[uri_len-1] = '\0';
      return;
  }
  
+ #undef limit_length
  
  
  
***************
*** 2061,2082 ****
      if ((fp = pfopen(r->pool, file, "r")) == NULL)
          return NULL;
  
!     strncpy(output,  MAPFILE_OUTPUT, sizeof(output)-1);
      output[sizeof(output)-1] = '\0';
      while (fgets(line, sizeof(line), fp) != NULL) {
          if (line[strlen(line)-1] == '\n')
              line[strlen(line)-1] = '\0';
- #ifdef HAS_APACHE_REGEX_LIB
          if (regexec(lookup_map_txtfile_regexp, line, lookup_map_txtfile_regexp->re_nsub+1, lookup_map_txtfile_regmatch, 0) == 0) {
- #else
-         if (regexec(lookup_map_txtfile_regexp, line) != 0) {
- #endif
- #ifdef HAS_APACHE_REGEX_LIB
              strncpy(result, pregsub(r->pool, output, line, lookup_map_txtfile_regexp->re_nsub+1, lookup_map_txtfile_regmatch), sizeof(result)-1); /* substitute in output */
! 	    result[sizeof(result)-1] = '\0';
! #else
!             regsub(lookup_map_txtfile_regexp, output, result);
! #endif
              cpT = strchr(result, ',');
              *cpT = '\0';
              curkey = result;
--- 2125,2138 ----
      if ((fp = pfopen(r->pool, file, "r")) == NULL)
          return NULL;
  
!     strncpy(output, MAPFILE_OUTPUT, sizeof(output)-1);
      output[sizeof(output)-1] = '\0';
      while (fgets(line, sizeof(line), fp) != NULL) {
          if (line[strlen(line)-1] == '\n')
              line[strlen(line)-1] = '\0';
          if (regexec(lookup_map_txtfile_regexp, line, lookup_map_txtfile_regexp->re_nsub+1, lookup_map_txtfile_regmatch, 0) == 0) {
              strncpy(result, pregsub(r->pool, output, line, lookup_map_txtfile_regexp->re_nsub+1, lookup_map_txtfile_regmatch), sizeof(result)-1); /* substitute in output */
!             result[sizeof(result)-1] = '\0';
              cpT = strchr(result, ',');
              *cpT = '\0';
              curkey = result;
***************
*** 2102,2108 ****
      char buf[MAX_STRING_LEN];
  
      dbmkey.dptr  = key;
!     dbmkey.dsize = strlen(key) < sizeof(buf) - 1 : strlen(key) ? sizeof(buf)-1;
      if ((dbmfp = dbm_open(file, O_RDONLY, 0666)) != NULL) {
          dbmval = dbm_fetch(dbmfp, dbmkey);
          if (dbmval.dptr != NULL) {
--- 2158,2164 ----
      char buf[MAX_STRING_LEN];
  
      dbmkey.dptr  = key;
!     dbmkey.dsize = (strlen(key) < sizeof(buf) - 1 : strlen(key) ? sizeof(buf)-1);
      if ((dbmfp = dbm_open(file, O_RDONLY, 0666)) != NULL) {
          dbmval = dbm_fetch(dbmfp, dbmkey);
          if (dbmval.dptr != NULL) {
***************
*** 2122,2127 ****
--- 2178,2186 ----
      char c;
      int i;
  
+     /* lock the channel */
+     fd_lock(fpin);
+ 
      /* write out the request key */
      write(fpin, key, strlen(key));
      write(fpin, "\n", 1);
***************
*** 2135,2140 ****
--- 2194,2202 ----
      }
      buf[i] = '\0';
  
+     /* unlock the channel */
+     fd_unlock(fpin);
+ 
      if (strcasecmp(buf, "NULL") == 0)
          return NULL;
      else
***************
*** 2197,2203 ****
      cleanup_for_exec();
      signal(SIGHUP, SIG_IGN);
  #ifdef __EMX__
!     /* For OS/2 we need to use a '/' */
      execl(SHELL_PATH, SHELL_PATH, "/c", (char *)cmd, NULL);
  #else
      execl(SHELL_PATH, SHELL_PATH, "-c", (char *)cmd, NULL);
--- 2259,2265 ----
      cleanup_for_exec();
      signal(SIGHUP, SIG_IGN);
  #ifdef __EMX__
!     /* OS/2 needs a '/' */
      execl(SHELL_PATH, SHELL_PATH, "/c", (char *)cmd, NULL);
  #else
      execl(SHELL_PATH, SHELL_PATH, "-c", (char *)cmd, NULL);
***************
*** 2214,2223 ****
      static char str3[HUGE_STRING_LEN];
      static char type[20];
      static char redir[20];
-     char *ruser;
      va_list ap;
      int i;
      request_rec *req;
      
      va_start(ap, text);
      conf = get_module_config(r->server->module_config, &rewrite_module);
--- 2276,2285 ----
      static char str3[HUGE_STRING_LEN];
      static char type[20];
      static char redir[20];
      va_list ap;
      int i;
      request_rec *req;
+     char *ruser;
      
      va_start(ap, text);
      conf = get_module_config(r->server->module_config, &rewrite_module);
***************
*** 2235,2270 ****
  
      if (connect->user == NULL) {
          ruser = "-";
!     } else if (strlen (connect->user) != 0) {
          ruser = connect->user;
!     } else {
          ruser = "\"\"";
!     };
  
      str1 = pstrcat(r->pool, get_remote_host(connect, r->server->module_config, REMOTE_NAME), " ",
                              (connect->remote_logname != NULL ? connect->remote_logname : "-"), " ",
!                             ruser,
!                             NULL);
      ap_vsnprintf(str2, sizeof(str2), text, ap);
  
!     if (r->main == NULL) {
!         strncpy(type, "initial", sizeof(type)-1);
! 	type[sizeof(type)-1] = '\0';
!     } else {
!         strncpy(type, "subreq", sizeof(type)-1);
! 	type[sizeof(type)-1] = '\0';
!     }
  
      for (i = 0, req = r->prev; req != NULL; req = req->prev) 
          ;
      if (i == 0)
!         strcpy(redir, "");
      else
          ap_snprintf(redir, sizeof(redir), "/redir#%d", i);
  
      ap_snprintf(str3, sizeof(str3), "%s %s [%s/sid#%x][rid#%x/%s%s] (%d) %s\n", str1, current_logtime(r), r->server->server_hostname, (unsigned int)(r->server), (unsigned int)r, type, redir, level, str2);
  
      write(conf->rewritelogfp, str3, strlen(str3));
  
      va_end(ap);
      return;
--- 2297,2332 ----
  
      if (connect->user == NULL) {
          ruser = "-";
!     }
!     else if (strlen (connect->user) != 0) {
          ruser = connect->user;
!     }
!     else {
          ruser = "\"\"";
!     }
  
      str1 = pstrcat(r->pool, get_remote_host(connect, r->server->module_config, REMOTE_NAME), " ",
                              (connect->remote_logname != NULL ? connect->remote_logname : "-"), " ",
!                             ruser, NULL);
      ap_vsnprintf(str2, sizeof(str2), text, ap);
  
!     if (r->main == NULL)
!         strcpy(type, "initial");
!     else
!         strcpy(type, "subreq");
  
      for (i = 0, req = r->prev; req != NULL; req = req->prev) 
          ;
      if (i == 0)
!         redir[0] = '\0';
      else
          ap_snprintf(redir, sizeof(redir), "/redir#%d", i);
  
      ap_snprintf(str3, sizeof(str3), "%s %s [%s/sid#%x][rid#%x/%s%s] (%d) %s\n", str1, current_logtime(r), r->server->server_hostname, (unsigned int)(r->server), (unsigned int)r, type, redir, level, str2);
  
+     fd_lock(conf->rewritelogfp);
      write(conf->rewritelogfp, str3, strlen(str3));
+     fd_unlock(conf->rewritelogfp);
  
      va_end(ap);
      return;
***************
*** 2272,2282 ****
  
  static char *current_logtime(request_rec *r)
  {
- #ifdef IS_APACHE_12
      int timz;
- #else
-     long timz;
- #endif
      struct tm *t;
      char tstr[80];
      char sign;
--- 2334,2340 ----
***************
*** 2286,2299 ****
      if(timz < 0) 
          timz = -timz;
  
!     strftime(tstr, 80,"[%d/%b/%Y:%H:%M:%S ",t);
! 
! #ifdef IS_APACHE_12
      ap_snprintf(tstr + strlen(tstr), 80-strlen(tstr), "%c%.2d%.2d]", sign, timz/60, timz%60);
- #else
-     ap_snprintf(tstr + strlen(tstr), 80-strlen(tstr), "%c%02ld%02ld]", sign, timz/3600, timz%3600);
- #endif
- 
      return pstrdup(r->pool, tstr);
  }
  
--- 2344,2351 ----
      if(timz < 0) 
          timz = -timz;
  
!     strftime(tstr, 80, "[%d/%b/%Y:%H:%M:%S ", t);
      ap_snprintf(tstr + strlen(tstr), 80-strlen(tstr), "%c%.2d%.2d]", sign, timz/60, timz%60);
      return pstrdup(r->pool, tstr);
  }
  
***************
*** 2353,2363 ****
      cleanup_for_exec();
      signal(SIGHUP, SIG_IGN);
  #ifdef __EMX__
!     /* For OS/2 we need to use a '/' */
      execl(SHELL_PATH, SHELL_PATH, "/c", (char *)cmd, NULL);
  #else
      execl(SHELL_PATH, SHELL_PATH, "-c", (char *)cmd, NULL);
! #endif    
      exit(1);
  }
  
--- 2405,2415 ----
      cleanup_for_exec();
      signal(SIGHUP, SIG_IGN);
  #ifdef __EMX__
!     /* OS/2 needs a '/' */
      execl(SHELL_PATH, SHELL_PATH, "/c", (char *)cmd, NULL);
  #else
      execl(SHELL_PATH, SHELL_PATH, "-c", (char *)cmd, NULL);
! #endif
      exit(1);
  }
  
***************
*** 2379,2385 ****
      newbuf = expand_variables(r, buf);
      if (strcmp(newbuf, buf) != 0) {
          strncpy(buf, newbuf, buf_len-1);
! 	buf[buf_len-1] = '\0';
      }
      return;
  }
--- 2431,2437 ----
      newbuf = expand_variables(r, buf);
      if (strcmp(newbuf, buf) != 0) {
          strncpy(buf, newbuf, buf_len-1);
!         buf[buf_len-1] = '\0';
      }
      return;
  }
***************
*** 2402,2407 ****
--- 2454,2460 ----
              if ((cp3 = strstr(cp2, "}")) != NULL) {
                  *cp2 = '\0';
                  strncpy(&output[strlen(output)], cp, sizeof(output)-strlen(output)-1);
+ 
                  cp2 += 2;
                  *cp3 = '\0';
                  strncpy(&output[strlen(output)], lookup_variable(r, cp2), sizeof(output)-strlen(output)-1);
***************
*** 2412,2418 ****
              }
          }
          strncpy(&output[strlen(output)], cp, sizeof(output)-strlen(output)-1);
! 	output[sizeof(output)-1] = '\0';
          break;
      }
      return expanded ? pstrdup(r->pool, output) : str;
--- 2465,2471 ----
              }
          }
          strncpy(&output[strlen(output)], cp, sizeof(output)-strlen(output)-1);
!         output[sizeof(output)-1] = '\0';
          break;
      }
      return expanded ? pstrdup(r->pool, output) : str;
***************
*** 2424,2429 ****
--- 2477,2486 ----
      char resultbuf[LONG_STRING_LEN];
      time_t tc;
      struct tm *tm;
+     request_rec *rsub;
+     struct passwd *pw;
+     struct group *gr;
+     struct stat finfo;
  
      result = NULL;
  
***************
*** 2491,2496 ****
--- 2548,2556 ----
      else if (strcasecmp(var, "AUTH_TYPE") == 0) {
          result = r->connection->auth_type;
      }
+     else if (strcasecmp(var, "IS_SUBREQ") == 0) { /* non-standard */
+         result = (r->main != NULL ? "true" : "false");
+     }
  
      /* internal server stuff */
      else if (strcasecmp(var, "DOCUMENT_ROOT") == 0) {
***************
*** 2550,2559 ****
  
      /* all other env-variables from the parent Apache process */
      else if (strlen(var) > 4 && strncasecmp(var, "ENV:", 4) == 0) {
!         result = getenv(var+4);
      }
- 
-     /* uptime, load average, etc. .. */
  
      if (result == NULL)
          return pstrdup(r->pool, "");
--- 2610,2689 ----
  
      /* all other env-variables from the parent Apache process */
      else if (strlen(var) > 4 && strncasecmp(var, "ENV:", 4) == 0) {
!         /* first try the internal Apache notes structure */
!         result = table_get(r->notes, var+4);
!         /* second try the internal Apache env structure  */
!         if (result == NULL) 
!             result = table_get(r->subprocess_env, var+4);
!         /* third try the external OS env */
!         if (result == NULL) 
!             result = getenv(var+4);
!     }
! 
! #define LOOKAHEAD(subrecfunc) \
!         if ( \
!           /* filename is safe to use */ \
!           r->filename != NULL \
!               /* - and we're either not in a subrequest */ \
!               && ( r->main == NULL \
!                   /* - or in a subrequest where paths are non-NULL... */ \
!                     || ( r->main->uri != NULL && r->uri != NULL \
!                         /*   ...and sub and main paths differ */ \
!                         && strcmp(r->main->uri, r->uri) != 0))) { \
!             /* process a file-based subrequest */ \
!             rsub = subrecfunc(r->filename, r); \
!             /* now recursively lookup the variable in the sub_req */ \
!             result = lookup_variable(rsub, var+5); \
!             /* copy it up to our scope before we destroy the sub_req's pool */ \
!             result = pstrdup(r->pool, result); \
!             /* cleanup by destroying the subrequest */ \
!             destroy_sub_req(rsub); \
!             /* log it */ \
!             rewritelog(r, 5, "lookahead: path=%s var=%s -> val=%s", r->filename, var+5, result); \
!             /* return ourself to prevent re-pstrdup */ \
!             return result; \
!         }
! 
!     /* look-ahead for parameter through URI-based sub-request */
!     else if (strlen(var) > 5 && strncasecmp(var, "LA-U:", 5) == 0) {
!         LOOKAHEAD(sub_req_lookup_uri)
!     }
!     /* look-ahead for parameter through file-based sub-request */
!     else if (strlen(var) > 5 && strncasecmp(var, "LA-F:", 5) == 0) {
!         LOOKAHEAD(sub_req_lookup_file)
!     }
! 
!     /* file stuff */
!     else if (strcasecmp(var, "SCRIPT_USER") == 0) {
!         result = pstrdup(r->pool, "<unknown>");
!         if (r->finfo.st_mode != 0) {
!             if ((pw = getpwuid(r->finfo.st_uid)) != NULL) { 
!                 result = pstrdup(r->pool, pw->pw_name);
!             }
!         }
!         else {
!             if (stat(r->filename, &finfo) == 0) {
!                 if ((pw = getpwuid(finfo.st_uid)) != NULL) { 
!                     result = pstrdup(r->pool, pw->pw_name);
!                 }
!             }
!         }
!     }
!     else if (strcasecmp(var, "SCRIPT_GROUP") == 0) {
!         result = pstrdup(r->pool, "<unknown>");
!         if (r->finfo.st_mode != 0) {
!             if ((gr = getgrgid(r->finfo.st_gid)) != NULL) { 
!                 result = pstrdup(r->pool, gr->gr_name);
!             }
!         }
!         else {
!             if (stat(r->filename, &finfo) == 0) {
!                 if ((gr = getgrgid(finfo.st_gid)) != NULL) { 
!                     result = pstrdup(r->pool, gr->gr_name);
!                 }
!             }
!         }
      }
  
      if (result == NULL)
          return pstrdup(r->pool, "");
***************
*** 2721,2727 ****
      /* first, remove the local directory prefix */
      strncpy(matchbuf, match, sizeof(matchbuf)-1);
      matchbuf[sizeof(matchbuf)-1] = '\0';
- 
      /* allways have a trailing slash */
      l = strlen(matchbuf);
      if (matchbuf[l-1] != '/') {
--- 2851,2856 ----
***************
*** 2735,2741 ****
  
          /* and now add the base-URL as replacement prefix */
          strncpy(substbuf, subst, sizeof(substbuf)-1);
! 	substbuf[sizeof(substbuf)-1] = '\0';
          /* allways have a trailing slash */
          l = strlen(substbuf);
          if (substbuf[l-1] != '/') {
--- 2864,2870 ----
  
          /* and now add the base-URL as replacement prefix */
          strncpy(substbuf, subst, sizeof(substbuf)-1);
!         substbuf[sizeof(substbuf)-1] = '\0';
          /* allways have a trailing slash */
          l = strlen(substbuf);
          if (substbuf[l-1] != '/') {
***************
*** 2833,2838 ****
--- 2962,2984 ----
  }
  
  
+ void add_env_variable(request_rec *r, char *s)
+ {
+     char var[MAX_STRING_LEN];
+     char val[MAX_STRING_LEN];
+     char *cp;
+ 
+     if ((cp = strchr(s, ':')) != NULL) {
+         memcpy(var, s, cp-s);
+         var[cp-s] = '\0';
+         strcpy(val, cp+1);
+         table_set(r->subprocess_env, pstrdup(r->pool, var), pstrdup(r->pool, val));
+         rewritelog(r, 5, "setting env variable '%s' to '%s'", var, val);
+     }
+ }
+ 
+ 
+ 
  /*
  **
  **  stat() for only the prefix of a path
***************
*** 2869,2875 ****
      char **cppHNLtest;
      char *ourhostname;
      char *ourhostip;
!     _const char *names;
      char *name;
      int i, j;
  
--- 3015,3021 ----
      char **cppHNLtest;
      char *ourhostname;
      char *ourhostip;
!     const char *names;
      char *name;
      int i, j;
  
***************
*** 2992,2998 ****
  **
  */
  
- #ifdef IS_APACHE_12
  int is_proxy_available(server_rec *s)
  {
      extern module *preloaded_modules[];
--- 3138,3143 ----
***************
*** 3008,3027 ****
      }
      return 0;
  }
! #else
! int is_proxy_available(server_rec *s)
  {
!     extern char *module_names[];
!     int n;
!     
!     for (n = 0; module_names[n] != NULL; n++) {
!         if (strcmp(module_names[n], "proxy_module") == 0) {
!             return 1;
!         }
      }
!     return 0;
  }
  #endif
  
  
  /*EOF*/
--- 3153,3209 ----
      }
      return 0;
  }
! 
! 
! /*
! **
! **  File locking
! **
! */
! 
! #ifdef USE_FCNTL
! static struct flock   lock_it = { F_WRLCK, 0, 0, 0 };
! static struct flock unlock_it = { F_UNLCK, 0, 0, 0 };
! #endif 
! 
! static void fd_lock(int fd)
  {
!     int rc;
! 
! #ifdef USE_FCNTL
!     while (   ((rc = fcntl(fd, F_SETLKW, &lock_it)) < 0) 
!            && (errno == EINTR)                               )
!         continue;
! #endif
! #ifdef USE_FLOCK
!     while (   ((rc = flock(fd, LOCK_EX)) < 0) 
!            && (errno == EINTR)               )
!         continue;
! #endif
! 
!     if (rc < 0) {
!         fprintf(stderr, "Error getting lock. Exiting!");
!         exit(1);
      }
!     return;
  }
+ 
+ static void fd_unlock(int fd)
+ {
+     int rc;
+ 
+ #ifdef USE_FCNTL 
+     rc = fcntl(fd, F_SETLKW, &unlock_it);
  #endif
+ #ifdef USE_FLOCK 
+     rc = flock(fd, LOCK_UN);
+ #endif 
+ 
+     if (rc < 0) {
+         fprintf(stderr, "Error freeing lock. Exiting!");
+         exit(1);
+     }
+ }
  
  
  /*EOF*/
*** SNAP/src/mod_rewrite.h	Mon Jan 20 09:00:17 1997
--- src/mod_rewrite.h	Fri Jan 31 21:39:52 1997
***************
*** 1,3 ****
--- 1,4 ----
+ 
  /* ====================================================================
   * Copyright (c) 1996,1997 The Apache Group.  All rights reserved.
   *
***************
*** 63,69 ****
  **  |_| |_| |_|\___/ \__,_|___|_|  \___| \_/\_/ |_|  |_|\__\___|
  **                       |_____|
  **
! **  URL Rewriting Module, Version 2.3.10 (20-12-1996)
  **
  **  This module uses a rule-based rewriting engine (based on a
  **  regular-expression parser) to rewrite requested URLs on the fly. 
--- 64,70 ----
  **  |_| |_| |_|\___/ \__,_|___|_|  \___| \_/\_/ |_|  |_|\__\___|
  **                       |_____|
  **
! **  URL Rewriting Module, Version 3.0.0 (xx-02-1997)
  **
  **  This module uses a rule-based rewriting engine (based on a
  **  regular-expression parser) to rewrite requested URLs on the fly. 
***************
*** 83,126 ****
  **  The documentation and latest release can be found on
  **  http://www.engelschall.com/sw/mod_rewrite/
  **
! **  Copyright (c) 1996 Ralf S. Engelschall, All rights reserved.
  **
  **  Written for The Apache Group by
  **      Ralf S. Engelschall
  **      rse@engelschall.com
! **      http://www.engelschall.com/
  */
  
  
  
  
-     /* Check Apache Release */
- #if (MODULE_MAGIC_NUMBER >= 19960725)
- #define IS_APACHE_12         1
- #define HAS_APACHE_REGEX_LIB 1
- #endif
- 
- 
-     /* The const problem:
-        The Apache Group changed some essential prototypes
-        to have an additional "const" qualifier. To be backward
-        compatible with Apache 1.1.1 we use a special define */
- #ifdef IS_APACHE_12
- #define _const const
- #else
- #define _const  
- #endif
- 
- 
-     /* The RegExp support:
-        For Apache 1.1.1 we provide our own Spencer V8 library,
-        for Apache 1.2 and higher there is a Spencer POSIX library
-        in the distribution */
- #ifndef HAS_APACHE_REGEX_LIB
- #include "regexp/regexp.h"
- #endif
- 
- 
      /* The NDBM support:
         We support only NDBM files. 
         But we have to stat the file for the mtime,
--- 84,100 ----
  **  The documentation and latest release can be found on
  **  http://www.engelschall.com/sw/mod_rewrite/
  **
! **  Copyright (c) 1996-1997 Ralf S. Engelschall, All rights reserved.
  **
  **  Written for The Apache Group by
  **      Ralf S. Engelschall
  **      rse@engelschall.com
! **      www.engelschall.com
  */
  
  
  
  
      /* The NDBM support:
         We support only NDBM files. 
         But we have to stat the file for the mtime,
***************
*** 135,140 ****
--- 109,138 ----
  #endif
  
  
+     /* The locking support:
+        Try to determine whether we should use
+        fcntl() or flock(). */
+ #if defined(USE_FCNTL_SERIALIZED_ACCEPT)
+ #define USE_FCNTL 1
+ #include <fcntl.h>
+ #endif
+ #if defined(USE_FLOCK_SERIALIZED_ACCEPT)
+ #define USE_FLOCK 1
+ #include <sys/file.h>
+ #endif
+ #if !defined(USE_FCNTL) && !defined(USE_FLOCK)
+ #define USE_FLOCK 1
+ #include <sys/file.h>
+ #ifndef LOCK_UN
+ #undef USE_FLOCK
+ #define USE_FCNTL 1
+ #include <fcntl.h>
+ #endif
+ #endif
+ 
+ 
+ 
+ 
  /*
  **
  **  Some defines
***************
*** 165,170 ****
--- 163,169 ----
  #define RULEFLAG_PROXY              1<<7
  #define RULEFLAG_PASSTHROUGH        1<<8
  #define RULEFLAG_FORBIDDEN          1<<9
+ #define RULEFLAG_GONE               1<<10
  
  #define MAPTYPE_TXT                 1<<0
  #define MAPTYPE_DBM                 1<<1
***************
*** 193,198 ****
--- 192,199 ----
  #define LONG_STRING_LEN 2048
  #endif
  
+ #define MAX_ENV_FLAGS 5
+ 
  
  /*
  **
***************
*** 215,240 ****
  typedef struct {
      char    *input;                /* Input string of RewriteCond */
      char    *pattern;              /* the RegExp pattern string */
- #ifdef HAS_APACHE_REGEX_LIB
      regex_t *regexp;
- #else
-     regexp  *regexp;               /* the RegExp pattern compilation */
- #endif
      int      flags;                /* Flags which control the match */
  } rewritecond_entry;
  
  typedef struct {
      array_header *rewriteconds;    /* the corresponding RewriteCond entries */
      char         *pattern;         /* the RegExp pattern string */
- #ifdef HAS_APACHE_REGEX_LIB
      regex_t      *regexp;          /* the RegExp pattern compilation */
! #else
!     regexp       *regexp;
! #endif
!     char         *output;          /* the Substitution string */
!     int           flags;           /* Flags which control the substitution */
!     char         *forced_mimetype; /* forced MIME-type of substitution */
!     int           skip;            /* number of next rules to skip */
  } rewriterule_entry;
  
  
--- 216,235 ----
  typedef struct {
      char    *input;                /* Input string of RewriteCond */
      char    *pattern;              /* the RegExp pattern string */
      regex_t *regexp;
      int      flags;                /* Flags which control the match */
  } rewritecond_entry;
  
  typedef struct {
      array_header *rewriteconds;    /* the corresponding RewriteCond entries */
      char         *pattern;         /* the RegExp pattern string */
      regex_t      *regexp;          /* the RegExp pattern compilation */
!     char         *output;              /* the Substitution string */
!     int           flags;               /* Flags which control the substitution */
!     char         *forced_mimetype;     /* forced MIME type of substitution */
!     int           forced_responsecode; /* forced HTTP redirect response status */
!     char         *env[MAX_ENV_FLAGS+1];/* added environment variables */
!     int           skip;                /* number of next rules to skip */
  } rewriterule_entry;
  
  
***************
*** 298,319 ****
  static void *config_perdir_merge (pool *p, void *basev, void *overridesv);
  
      /* config directive handling */
! static _const char *cmd_rewriteengine  (cmd_parms *cmd, rewrite_perdir_conf *dconf, int flag);
! static _const char *cmd_rewriteoptions (cmd_parms *cmd, rewrite_perdir_conf *dconf, char *option);
! static _const char *cmd_rewriteoptions_setoption(pool *p, int *options, char *name);
! static _const char *cmd_rewritelog     (cmd_parms *cmd, void *dconf, char *a1);
! static _const char *cmd_rewriteloglevel(cmd_parms *cmd, void *dconf, char *a1);
! static _const char *cmd_rewritemap     (cmd_parms *cmd, void *dconf, char *a1, char *a2);
! 
! static _const char *cmd_rewritebase(cmd_parms *cmd, rewrite_perdir_conf *dconf, char *a1);
! 
! static _const char *cmd_rewritecond    (cmd_parms *cmd, rewrite_perdir_conf *dconf, char *str);
! static _const char *cmd_rewritecond_parseflagfield(pool *p, rewritecond_entry *new, char *str);
! static _const char *cmd_rewritecond_setflag       (pool *p, rewritecond_entry *cfg, char *key, char *val);
! 
! extern _const char *cmd_rewriterule    (cmd_parms *cmd, rewrite_perdir_conf *dconf, char *str);
! static _const char *cmd_rewriterule_parseflagfield(pool *p, rewriterule_entry *new, char *str);
! static _const char *cmd_rewriterule_setflag       (pool *p, rewriterule_entry *cfg, char *key, char *val);
  
      /* initialisation */
  static void init_module(server_rec *s, pool *p);
--- 293,314 ----
  static void *config_perdir_merge (pool *p, void *basev, void *overridesv);
  
      /* config directive handling */
! static const char *cmd_rewriteengine  (cmd_parms *cmd, rewrite_perdir_conf *dconf, int flag);
! static const char *cmd_rewriteoptions (cmd_parms *cmd, rewrite_perdir_conf *dconf, char *option);
! static const char *cmd_rewriteoptions_setoption(pool *p, int *options, char *name);
! static const char *cmd_rewritelog     (cmd_parms *cmd, void *dconf, char *a1);
! static const char *cmd_rewriteloglevel(cmd_parms *cmd, void *dconf, char *a1);
! static const char *cmd_rewritemap     (cmd_parms *cmd, void *dconf, char *a1, char *a2);
! 
! static const char *cmd_rewritebase(cmd_parms *cmd, rewrite_perdir_conf *dconf, char *a1);
! 
! static const char *cmd_rewritecond    (cmd_parms *cmd, rewrite_perdir_conf *dconf, char *str);
! static const char *cmd_rewritecond_parseflagfield(pool *p, rewritecond_entry *new, char *str);
! static const char *cmd_rewritecond_setflag       (pool *p, rewritecond_entry *cfg, char *key, char *val);
! 
! extern const char *cmd_rewriterule    (cmd_parms *cmd, rewrite_perdir_conf *dconf, char *str);
! static const char *cmd_rewriterule_parseflagfield(pool *p, rewriterule_entry *new, char *str);
! static const char *cmd_rewriterule_setflag       (pool *p, rewriterule_entry *cfg, char *key, char *val);
  
      /* initialisation */
  static void init_module(server_rec *s, pool *p);
***************
*** 370,375 ****
--- 365,371 ----
  static char  *subst_prefix_path(request_rec *r, char *input, char *match, char *subst);
  static int    parseargline(char *str, char **a1, char **a2, char **a3);
  static int    prefix_stat(const char *path, struct stat *sb);
+ static void   add_env_variable(request_rec *r, char *s);
  
      /* DNS functions */
  static int    is_this_our_host(request_rec *r, char *testhost);
***************
*** 378,383 ****
--- 374,383 ----
  
      /* Proxy Module check */
  static int is_proxy_available(server_rec *s);
+ 
+     /* File locking */
+ static void fd_lock(int fd);
+ static void fd_unlock(int fd);
  
  #endif /* _MOD_REWRITE_H */
  

Re: mod_rewrite 3.0.0 for Apache 1.2b7 !!! (PATCH)

Posted by Marc Slemko <ma...@znep.com>.
On Fri, 31 Jan 1997, Ralf S. Engelschall wrote:

> 
> As a result of the current problems, I decided a change for mod_rewrite:
> 
> 1. Version 2.4.x (currently 2.4.1) is the latest release available
>    for Apache 1.1.x. There will be only bugfixes applied to 2.4.x
>    to provide a stable version for the Apache 1.1.x users.
> 
> 2. Version 3.0.0 was created by manually merging (hmm... I like
>    those jobs) the 2.4.1 version and the aligned 2.3.10+ version currently
>    found in the 1.2b7-dev snapshot sources. Actually this is 2.4.1 with Marcs
>    snprintf/strncpy patches re-applied.  All other changes from the Apache
>    Group (OS\2 EMX, const, etc.) were already included into 2.4.1.
> 
> Version 3.0.0 is still not released. Below is a standard patch for review
> _AND_ a context diff to bring the current CVS sources up to date.
> 
> NOW, APACHE GROUP MEMBERS, ATTENTION PLEASE:
> 
> Go to the patch and review it. And do it immediately so it don't get lost in
> the processing ;-) and Apache 1.2b7 can contain mod_rewrite 3.0.0. Please vote
> for this change NOW!
> 

+1 once the following concerns are addressed by either convincing me I'm
stupid or changing the source.  All the quotes below are from the
output of a diff -u.


-**      http://www.engelschall.com/
+**      www.engelschall.com

Why?  www.engelschall.com isn't a URL, or don't you want it to be. 
(No, I will not object to the patch based on this but I just have
this thing about so-called URLs, not that is is necessarily one)

+                for (i = 0; p->env[i] != NULL; i++) {
+                    strcpy(env2, p->env[i]);
+                    strcpy(env, pregsub(r->pool, env2, uri, regexp->re_nsub+1,
regmatch));    /* substitute in output */
+                    add_env_variable(r, env);
+                }
        
Please use strncpy.  strcpy at that place is almost certainly safe
today because of fake limits imposed on nearly all input, but that
may change.  (this bit of code is duplicated 3 times).  If it isn't
_extremely_ obvious that it is impossible for there to be an overflow (eg.
one of my modifications that used strncpy(foo, "this") instead of strcpy),
don't use strcpy.  

+    if ((cp = strchr(s, ':')) != NULL) { 
+        memcpy(var, s, cp-s);
+        var[cp-s] = '\0';
+        strcpy(val, cp+1);
+        table_set(r->subprocess_env, pstrdup(r->pool, var), pstrdup(r->pool, va
l)); 
+        rewritelog(r, 5, "setting env variable '%s' to '%s'", var, val);
+    }       

Check the memcpy to be sure (cp-s < sizeof(var)).  And the strcpy.

+#ifdef USE_FCNTL
+static struct flock   lock_it = { F_WRLCK, 0, 0, 0 };
+static struct flock unlock_it = { F_UNLCK, 0, 0, 0 };
+#endif

Init it by naming the members explicitly.  I know this is done the
same way in the accept_mutex stuff as you do it, but it is broken
if you try to compile it on many platforms because the member order
differs; that code currently isn't used on those platforms.  Using
names _should_ be portable, but it will need to be tested.

+    /* The locking support:
+       Try to determine whether we should use
+       fcntl() or flock(). */ 
+#if defined(USE_FCNTL_SERIALIZED_ACCEPT)
+#define USE_FCNTL 1 
+#include <fcntl.h>
+#endif  
+#if defined(USE_FLOCK_SERIALIZED_ACCEPT)
+#define USE_FLOCK 1
+#include <sys/file.h>
+#endif
+#if !defined(USE_FCNTL) && !defined(USE_FLOCK)
+#define USE_FLOCK 1
+#include <sys/file.h>
+#ifndef LOCK_UN
+#undef USE_FLOCK
+#define USE_FCNTL 1
+#include <fcntl.h>
+#endif
+#endif

Perhaps it is worthwhile changing the server code to have USE_FCNTL and 
USE_FLOCK defined elsewhere, and removing USE_FCNTL_SERIALIZED_ACCEPT and 
USE_FLOCK_SERIALIZED_ACCEPT, replacing them with a USE_SERIALIZED_ACCEPT
that checks USE_FCNTL and USE_FLOCK.  Actually, those should be
HAVE_FCNTL and HAVE_FLOCK if in conf.h.  

I would also be wary of the portability of that method of testing
which one to use.  Not that I have a better suggestion, but just something
to keep in mind.

Other than the above, looks good.