I took a at the source for mod_rewrite (modules/mappers/mod_rewrite.c) and it looks like it wouldn't be too tough to add a special RewriteCond flag for my purpose. It's probably more trouble than it's worth in the long run though.
I'd probably have to start by adding a new flag for my purpose.
Here's the enum. Adding a flag could force me to rewrite it if Apache adds a new flag later on, and I don't know how defining the constant outside of the enum for a number out of conflict range would work out.
/* special pattern types for RewriteCond */
typedef enum {
CONDPAT_REGEX = 0,
CONDPAT_FILE_EXISTS, // -f flag
CONDPAT_FILE_SIZE,
CONDPAT_FILE_LINK,
CONDPAT_FILE_DIR,
CONDPAT_FILE_XBIT,
CONDPAT_LU_URL,
CONDPAT_LU_FILE,
CONDPAT_STR_GT,
CONDPAT_STR_LT,
CONDPAT_STR_EQ
} pattern_type;
- /* special pattern types for RewriteCond */
- typedef enum {
- CONDPAT_REGEX = 0,
- CONDPAT_FILE_EXISTS, // -f flag
- CONDPAT_FILE_SIZE,
- CONDPAT_FILE_LINK,
- CONDPAT_FILE_DIR,
- CONDPAT_FILE_XBIT,
- CONDPAT_LU_URL,
- CONDPAT_LU_FILE,
- CONDPAT_STR_GT,
- CONDPAT_STR_LT,
- CONDPAT_STR_EQ
- } pattern_type;
Then I'd have to jump down and work my flag into here.
I could keep it simple and just add a one character flag where it hardcoded in the 24 hours I'm looking for at the moment, but that wouldn't be very useful.
a2 is defined as "char *a2;" earlier up in the function, I'm not sure I could squeeze more bytes into that so I could append an interval to my flag or not.
/* determine the pattern type */
newcond->ptype = CONDPAT_REGEX;
if (*a2 && a2[1]) {
if (!a2[2] && *a2 == '-') {
switch (a2[1]) {
case 'f': newcond->ptype = CONDPAT_FILE_EXISTS; break;
case 's': newcond->ptype = CONDPAT_FILE_SIZE; break;
case 'l': newcond->ptype = CONDPAT_FILE_LINK; break;
case 'd': newcond->ptype = CONDPAT_FILE_DIR; break;
case 'x': newcond->ptype = CONDPAT_FILE_XBIT; break;
case 'U': newcond->ptype = CONDPAT_LU_URL; break;
case 'F': newcond->ptype = CONDPAT_LU_FILE; break;
}
}
else {
switch (*a2) {
case '>': newcond->ptype = CONDPAT_STR_GT; break;
case '<': newcond->ptype = CONDPAT_STR_LT; break;
case '=': newcond->ptype = CONDPAT_STR_EQ;
/* "" represents an empty string */
if (*++a2 == '"' && a2[1] == '"' && !a2[2]) {
a2 += 2;
}
break;
}
}
}
- /* determine the pattern type */
- newcond->ptype = CONDPAT_REGEX;
- if (*a2 && a2[1]) {
- if (!a2[2] && *a2 == '-') {
- switch (a2[1]) {
- case 'f': newcond->ptype = CONDPAT_FILE_EXISTS; break;
- case 's': newcond->ptype = CONDPAT_FILE_SIZE; break;
- case 'l': newcond->ptype = CONDPAT_FILE_LINK; break;
- case 'd': newcond->ptype = CONDPAT_FILE_DIR; break;
- case 'x': newcond->ptype = CONDPAT_FILE_XBIT; break;
- case 'U': newcond->ptype = CONDPAT_LU_URL; break;
- case 'F': newcond->ptype = CONDPAT_LU_FILE; break;
- }
- }
- else {
- switch (*a2) {
- case '>': newcond->ptype = CONDPAT_STR_GT; break;
- case '<': newcond->ptype = CONDPAT_STR_LT; break;
- case '=': newcond->ptype = CONDPAT_STR_EQ;
- /* "" represents an empty string */
- if (*++a2 == '"' && a2[1] == '"' && !a2[2]) {
- a2 += 2;
- }
- break;
- }
- }
- }
Then I'd need to work out checking the age of the file here.
At first glance, I'd guess that something like "sb.mtime" would be available from apr_stat.
I'm not sure how I would access my interval, though perhaps I could work it out so that the RewriteCond parser set newcond->ptype to my interval once it determined it was using it.
Though, the interval would need to be seconds to reduce the chances of it conflicing with the other constants, yet, I bet seconds would be the way to go since any mtime returned is likely to be a UNIX timestamp. It would be awkward to have the interval be seconds, and force a restriction that it be greater than 60 seconds to prevent conflict though. Maybe have it be defined using minutes, then convert it to seconds in the module.
static int apply_rewrite_cond(rewritecond_entry *p, rewrite_ctx *ctx)
{
char *input = do_expand(p->input, ctx, NULL);
apr_finfo_t sb;
request_rec *rsub, *r = ctx->r;
ap_regmatch_t regmatch[AP_MAX_REG_MATCH];
int rc = 0;
switch (p->ptype) {
case CONDPAT_FILE_EXISTS:
if ( apr_stat(&sb, input, APR_FINFO_MIN, r->pool) == APR_SUCCESS
&& sb.filetype == APR_REG) {
rc = 1;
}
break;
case CONDPAT_FILE_SIZE:
if ( apr_stat(&sb, input, APR_FINFO_MIN, r->pool) == APR_SUCCESS
&& sb.filetype == APR_REG && sb.size > 0) {
rc = 1;
}
break;
- static int apply_rewrite_cond(rewritecond_entry *p, rewrite_ctx *ctx)
- {
- char *input = do_expand(p->input, ctx, NULL);
- apr_finfo_t sb;
- request_rec *rsub, *r = ctx->r;
- ap_regmatch_t regmatch[AP_MAX_REG_MATCH];
- int rc = 0;
-
- switch (p->ptype) {
- case CONDPAT_FILE_EXISTS:
- if ( apr_stat(&sb, input, APR_FINFO_MIN, r->pool) == APR_SUCCESS
- && sb.filetype == APR_REG) {
- rc = 1;
- }
- break;
-
- case CONDPAT_FILE_SIZE:
- if ( apr_stat(&sb, input, APR_FINFO_MIN, r->pool) == APR_SUCCESS
- && sb.filetype == APR_REG && sb.size > 0) {
- rc = 1;
- }
- break;
-
Strong with this one, the sudo is.