View | Details | Raw Unified | Return to bug 41963
Collapse All | Expand All

(-)mod_expires.c.ORIG (-22 / +109 lines)
Lines 115-120 Link Here
115
 *      ExpiresByType text/html "access plus 1 month 15 days 2 hours"
115
 *      ExpiresByType text/html "access plus 1 month 15 days 2 hours"
116
 *      ExpiresByType image/gif "modification plus 5 hours 3 minutes"
116
 *      ExpiresByType image/gif "modification plus 5 hours 3 minutes"
117
 *
117
 *
118
 * Finally, there is a special form for differing expiration times based
119
 * on the age of the file, as in this example:
120
 *
121
 *     ExpiresByType image/jpg "aged 2 days then 10 years else 1 hour"
122
 *
123
 * This means that JPG image files who last modification time was two days
124
 * ago or more, are served with an expires time 10 years from the current
125
 * access time, while those image files that are less than 2 days old are
126
 * served with an expire time 1 hour from the current access time.
127
 *
128
 * The form is "aged <timespan> then <timespan> [else <timespan>]"
129
 *
130
 * The "else...." clause can be omitted, which means that files newer than
131
 * the threshold time are not given an expires header.
132
 *
133
 * This form may also be used for ExpiresDefault.
134
 *
118
 * ---
135
 * ---
119
 *
136
 *
120
 * Change-log:
137
 * Change-log:
Lines 139-144 Link Here
139
 *              the table_get check and then looking for an ExpiresDefault.
156
 *              the table_get check and then looking for an ExpiresDefault.
140
 *              [Rob Hartill]
157
 *              [Rob Hartill]
141
 * 04.Nov.96    'const' definitions added.
158
 * 04.Nov.96    'const' definitions added.
159
 * 27.Mar.07    added the 'aged' form
142
 *
160
 *
143
 * TODO
161
 * TODO
144
 * add support for Cache-Control: max-age=20 from the HTTP/1.1
162
 * add support for Cache-Control: max-age=20 from the HTTP/1.1
Lines 194-199 Link Here
194
    return NULL;
212
    return NULL;
195
}
213
}
196
214
215
static const char *parse_timespan(pool *p, char *word, const char **code, unsigned int *timespan, const char *end_at);
216
217
197
/* check_code() parse 'code' and return NULL or an error response
218
/* check_code() parse 'code' and return NULL or an error response
198
 * string.  If we return NULL then real_code contains code converted
219
 * string.  If we return NULL then real_code contains code converted
199
 * to the cnnnn format.
220
 * to the cnnnn format.
Lines 203-210 Link Here
203
    char *word;
224
    char *word;
204
    char base = 'X';
225
    char base = 'X';
205
    int modifier = 0;
226
    int modifier = 0;
206
    int num = 0;
227
    const char *error;
207
    int factor = 0;
228
    unsigned age;
229
    unsigned num1;
230
    unsigned num2;
208
231
209
    /* 0.0.4 compatibility?
232
    /* 0.0.4 compatibility?
210
     */
233
     */
Lines 213-224 Link Here
213
        return NULL;
236
        return NULL;
214
    };
237
    };
215
238
216
    /* <base> [plus] {<num> <type>}*
239
    word = ap_getword_conf(p, &code);
217
     */
218
240
219
    /* <base>
241
    /* aged {<num> <type>}+  then {<num> <type>}+ [else {<num> <type>}+ ] */
242
    if (!strncasecmp(word, "aged", 4)) {
243
        error = parse_timespan(p, NULL, &code, &age, "then");
244
        if (error)
245
            return error;
246
247
        error = parse_timespan(p, NULL, &code, &num1, "else");
248
        if (error)
249
            return error;
250
251
        num2 = 0;
252
        if (*code) {
253
            error = parse_timespan(p, NULL, &code, &num2, NULL);
254
            if (error)
255
                return error;
256
        }
257
        *real_code = ap_psprintf(p, ">%010d %010d %010d", age, num1, num2);
258
259
        /* ap_log_error(APLOG_MARK, APLOG_NOERRNO, NULL, "result[%s]", *real_code); */
260
        return NULL;
261
    }
262
263
264
    /* <base> [plus] {<num> <type>}*
220
     */
265
     */
221
    word = ap_getword_conf(p, &code);
222
    if (!strncasecmp(word, "now", 1) ||
266
    if (!strncasecmp(word, "now", 1) ||
223
        !strncasecmp(word, "access", 1)) {
267
        !strncasecmp(word, "access", 1)) {
224
        base = 'A';
268
        base = 'A';
Lines 238-245 Link Here
238
        word = ap_getword_conf(p, &code);
282
        word = ap_getword_conf(p, &code);
239
    };
283
    };
240
284
241
    /* {<num> <type>}*
285
    error = parse_timespan(p, word, &code, &modifier, NULL);
242
     */
286
    if (error)
287
            return error;
288
289
    *real_code = ap_psprintf(p, "%c%d", base, modifier);
290
291
    return NULL;
292
}
293
294
static const char *parse_timespan(pool *p, char *word, const char **code, unsigned int *timespan, const char *end_at)
295
{
296
    int num = 0;
297
    int factor = 0;
298
299
    *timespan = 0;
300
301
    if (!word)
302
            word = ap_getword_conf(p, code);
303
243
    while (word[0]) {
304
    while (word[0]) {
244
        /* <num>
305
        /* <num>
245
         */
306
         */
Lines 247-265 Link Here
247
            num = atoi(word);
308
            num = atoi(word);
248
        }
309
        }
249
        else {
310
        else {
250
            return ap_pstrcat(p, "bad expires code, numeric value expected <num> '",
311
            return ap_pstrcat(p, "bad expires code, numeric value expected <num>, got '",
251
                           word, "'", NULL);
312
                              word, "'", NULL);
252
        };
313
        };
253
314
254
        /* <type>
315
        /* <type>
255
         */
316
         */
256
        word = ap_getword_conf(p, &code);
317
        word = ap_getword_conf(p, code);
257
        if (word[0]) {
318
        if (!word[0])
258
            /* do nothing */
259
        }
260
        else {
261
            return ap_pstrcat(p, "bad expires code, missing <type>", NULL);
319
            return ap_pstrcat(p, "bad expires code, missing <type>", NULL);
262
        };
263
320
264
        factor = 0;
321
        factor = 0;
265
        if (!strncasecmp(word, "years", 1)) {
322
        if (!strncasecmp(word, "years", 1)) {
Lines 288-305 Link Here
288
                           "'", word, "'", NULL);
345
                           "'", word, "'", NULL);
289
        };
346
        };
290
347
291
        modifier = modifier + factor * num;
348
        *timespan  += factor * num;
292
349
293
        /* next <num>
350
        /* next <num>
294
         */
351
         */
295
        word = ap_getword_conf(p, &code);
352
        word = ap_getword_conf(p, code);
296
    };
297
353
298
    *real_code = ap_psprintf(p, "%c%d", base, modifier);
354
        if (end_at && !strncasecmp(word, end_at, strlen(end_at)))
299
355
            return(NULL);
300
    return NULL;
356
    };
357
    return(NULL);
301
}
358
}
302
359
360
303
static const char *set_expiresbytype(cmd_parms *cmd, expires_dir_config * dir_config, char *mime, char *code)
361
static const char *set_expiresbytype(cmd_parms *cmd, expires_dir_config * dir_config, char *mime, char *code)
304
{
362
{
305
    char *response, *real_code;
363
    char *response, *real_code;
Lines 427-432 Link Here
427
        base = r->request_time;
485
        base = r->request_time;
428
        additional = atoi(&code[1]);
486
        additional = atoi(&code[1]);
429
        break;
487
        break;
488
    case '>':
489
	if (r->finfo.st_mode == 0) { 
490
	    /* file doesn't exist on disk, so we can't do anything based on
491
	     * modification time.  Note that this does _not_ log an error.
492
	     */
493
	    return DECLINED;
494
	}
495
496
        /* code is of the form ">0031536000 0031536000 0000003600", where
497
         * all numbers are 10 digits long, the first number (starting at
498
         * code[1]) is the age threashold. If the file is at least that
499
         * many seconds old, the second number (starting at code[12]) is
500
         * used as "additional", while if the file is newer than that
501
         * threshold, the third number (starting at code[23]) is used as
502
         * "additional". */
503
504
        if (r->request_time - r->finfo.st_mtime >= atoi(&code[1]))
505
            additional = atoi(&code[12]);
506
        else
507
            additional = atoi(&code[23]);
508
509
        /* ap_log_rerror(APLOG_MARK, APLOG_NOERRNO, r, "additional = %d", additional); */
510
511
        if (additional == 0)
512
            return DECLINED;
513
        else
514
            base = r->request_time;
515
        break;
516
430
    default:
517
    default:
431
        /* expecting the add_* routines to be case-hardened this 
518
        /* expecting the add_* routines to be case-hardened this 
432
         * is just a reminder that module is beta
519
         * is just a reminder that module is beta

Return to bug 41963