First of all, thanks for all the effort that goes into apache. We
switched from NCSA to apache1 longer ago than I like to remember..
The rewriting guide has a short section called "On-the-fly
Content-Regeneration" but it's actually just "Generation" as there's no
way for the server to know if the page needs to be regenerated. To my
mind this somewhat limits the usefulness of the '-s' switch. I need the
ability to have an 'options' file and for mod_rewrite to update the
generated file in a make-like fashion whenever the options file changes,
rather than the collection of kludges I used to have.
So I've added an option ('mtime|M') to RewriteCond that causes the
expression to be treated as two filenames:
RewriteCond genfile <optionfile [M]
is True if the modification time of genfile is less than optionfile.
Since I figure that options files are, well, optional it defaults to
being True if genfile and optionfile both don't exist and I've put in an
option 'exist|X' so that:
RewriteCond genfile <optionfile [M,X]
is only True if optionfile exists and is newer than genfile.
The result is that I have a per-directory file that controls the header
and sidebar and when I change it apache now updates my static include
file for me. (I could have just made everything dynamic with php but
we've always been speed freaks and I hate doing anything that stops
caching.) If I want to I can also tell my server to put the w3c 'tick'
logo on a page only if it's been validated since it last changed which
helps my QA no end.
Of course I've added a test to check for incompatible options.
It's changed our web server, hope you like it. If it's accepted I'll
happily write some docs. I've made separate patches for
mod_rewrite.[ch], both against 2.49.
Regards.
John
Dr John Rowe
School of Physics
University of Exeter
UK
--- /tmp/mod_rewrite.c 2004-04-16 20:32:43.000000000 +0100
+++ mod_rewrite.c 2004-04-16 22:41:09.000000000 +0100
@@ -597,6 +597,19 @@
return NULL;
}
+static const char *cmd_rewritecond_checkflagsanity(rewritecond_entry *cfg)
+{
+ if ( cfg->flags & CONDFLAG_ATIME
+ && cfg->flags & CONDFLAG_MTIME) {
+ return "RewriteCond: only one of 'atime|A' or 'mtime|M' may be specified.";
+ }
+ else if ( cfg->flags & CONDFLAG_EXIST &&
+ (cfg->flags & (CONDFLAG_ATIME | CONDFLAG_MTIME)) == 0) {
+ return "RewriteCond: 'exist|X' requires 'atime|A' or 'mtime|M'.";
+ }
+ return NULL;
+}
+
static const char *cmd_rewritecond_parseflagfield(apr_pool_t *p,
rewritecond_entry *cfg,
char *str)
@@ -646,7 +659,7 @@
}
}
- return NULL;
+ return cmd_rewritecond_checkflagsanity(cfg);
}
static const char *cmd_rewritecond_setflag(apr_pool_t *p,
@@ -661,7 +674,19 @@
|| strcasecmp(key, "OR") == 0 ) {
cfg->flags |= CONDFLAG_ORNEXT;
}
- else {
+ else if ( strcasecmp(key, "atime") == 0
+ || strcasecmp(key, "A") == 0 ) {
+ cfg->flags |= CONDFLAG_ATIME;
+ }
+ else if ( strcasecmp(key, "mtime") == 0
+ || strcasecmp(key, "M") == 0 ) {
+ cfg->flags |= CONDFLAG_MTIME;
+ }
+ else if ( strcasecmp(key, "exist") == 0
+ || strcasecmp(key, "X") == 0 ) {
+ cfg->flags |= CONDFLAG_EXIST;
+ }
+ else {
return apr_pstrcat(p, "RewriteCond: unknown flag '", key, "'", NULL);
}
return NULL;
@@ -2260,7 +2285,36 @@
*/
rc = 0;
- if (strcmp(p->pattern, "-f") == 0) {
+
+ if (p->flags & (CONDFLAG_MTIME | CONDFLAG_ATIME)) {
+ if (strlen(p->pattern) > 1
+ && (*(p->pattern) == '>' || *(p->pattern) == '<')) {
+ apr_finfo_t sb2;
+ char *file[2], file2[MAX_STRING_LEN];
+
+ do_expand(r, p->pattern + 1, file2, sizeof(file2), briRR, briRC);
+
+ /* tranform expression to filename[0] < filename[1] */
+ file[*(p->pattern) != '<'] = input;
+ file[*(p->pattern) == '<'] = file2;
+ if (apr_stat(&sb, file[0], APR_FINFO_MIN, r->pool) != APR_SUCCESS) {
+ if ( (p->flags & CONDFLAG_EXIST) == 0
+ || apr_stat(&sb, file[1], APR_FINFO_MIN,
+ r->pool) == APR_SUCCESS) {
+ rc = 1;
+ }
+ }
+ else if (apr_stat(&sb2, file[1], APR_FINFO_MIN, r->pool)
+ == APR_SUCCESS) {
+ apr_time_t earlier, later;
+
+ earlier = p->flags & CONDFLAG_MTIME ? sb.mtime : sb.atime;
+ later = p->flags & CONDFLAG_MTIME ? sb2.mtime : sb2.atime;
+ rc = earlier < later;
+ }
+ }
+ }
+ else if (strcmp(p->pattern, "-f") == 0) {
if (apr_stat(&sb, input, APR_FINFO_MIN, r->pool) == APR_SUCCESS) {
if (sb.filetype == APR_REG) {
rc = 1;
--- /tmp/mod_rewrite.h 2004-04-16 20:32:43.000000000 +0100
+++ mod_rewrite.h 2004-04-16 22:05:23.000000000 +0100
@@ -107,6 +107,9 @@
#define CONDFLAG_NOCASE 1<<1
#define CONDFLAG_NOTMATCH 1<<2
#define CONDFLAG_ORNEXT 1<<3
+#define CONDFLAG_MTIME 1<<4
+#define CONDFLAG_ATIME 1<<5
+#define CONDFLAG_EXIST 1<<6
#define RULEFLAG_NONE 1<<0
#define RULEFLAG_FORCEREDIRECT 1<<1