httpd-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Roy T. Fielding" <field...@liege.ICS.UCI.EDU>
Subject Re: patch to 1.2 for tom tromey's HTTP compliance patches
Date Tue, 24 Sep 1996 00:37:37 GMT
> This patch merges the three patches Tom posted, and has them applied to
> the current 1.2 cvs snapshot.  It compiles fine, and I tested each
> condition Tom claims to have fixed.  
> 
> 
> Index: http_protocol.c
> ===================================================================
> RCS file: /export/home/cvs/apache/src/http_protocol.c,v
> retrieving revision 1.46
> diff -C3 -r1.46 http_protocol.c
> *** http_protocol.c	1996/09/17 14:53:54	1.46
> --- http_protocol.c	1996/09/23 03:15:10
> ***************
> *** 327,332 ****
> --- 327,333 ----
>       char *if_unmodified = table_get (r->headers_in, "If-Unmodified-Since");
>       char *if_nonematch = table_get (r->headers_in, "If-None-Match");
>       char *if_match = table_get (r->headers_in, "If-Match");
> +     time_t server_time = time (NULL);
>   
>       /* Invalid, future time... just ignore it */
>       if (mtime > r->request_time) return OK;
> ***************
> *** 369,375 ****
>       if ((r->status < 200) || (r->status >= 300))
>           return OK;
>   
> !     if (if_modified_since && later_than(gmtime(&mtime), if_modified_since))
>           return USE_LOCAL_COPY;
>       else if (if_unmodified && !later_than(gmtime(&mtime), if_unmodified))
>           return PRECONDITION_FAILED;
> --- 370,378 ----
>       if ((r->status < 200) || (r->status >= 300))
>           return OK;
>   
> !     if (if_modified_since && !r->header_only &&
> ! 	later_than(gmtime(&mtime), if_modified_since) &&
> ! 	!later_than(gmtime(&server_time), if_modified_since))
>           return USE_LOCAL_COPY;
>       else if (if_unmodified && !later_than(gmtime(&mtime), if_unmodified))
>           return PRECONDITION_FAILED;

Nope, -1 on this part -- later_than(x, if_modified_since) does an
alpha->date conversion, which should only be done once.  I think this
code (and later_than()) is a good candidate for rewriting.

What we need is a

   time_t parse_date(char *HTTP_date)

function that returns (time_t)0 if the date is invalid.  Then we
can just do numeric comparisons on the returned value. 

Unfortunately, I am on a trial jury Tuesday and Wednesday.  Here is
something I wrote 2.5 years ago on the same issue, just in case somebody
wants to try and make it work.  Note that some of this doesn't apply
any more, and strptime() is not portable [which is why RobM used sscanf],
but this is the general drift.

......Roy

================================================================
To: Rob McCool <robm@ncsa.uiuc.edu>
Subject: 1.21b If-modified-since Solved
Date: Sun, 24 Apr 1994 05:13:37 -0700
From: "Roy T. Fielding" <fielding@simplon.ics.uci.edu>

Ignore all the prior stuff.

I finally got it to work!  Here is what I did:

First, I tried to stay with the existing function, but for some reason
I could not get a hold of the conceptual model of what we were trying to
do with the later_than name.  So, I changed its functionality to get_gmtime
as follows:

in httpd.c replace later_than def (line 560) with:
--------------
time_t get_gmtime(char *gdstr);
--------------

in http_mime.c, replace set_last_modified() with:
--------------
void set_last_modified(time_t t, FILE *out) {
    struct tm *tms;
    char ts[MAX_STRING_LEN];

    tms = gmtime(&t);
    strftime(ts,MAX_STRING_LEN,HTTP_TIME_FORMAT,tms);
    strcpy(last_modified,ts);

    if(!ims[0])
        return;

    if(t <= get_gmtime(ims))
        die(USE_LOCAL_COPY,NULL,out);
}
--------------
Note the <= --- that's why the later_than was causing me so much trouble.

finally, in util.c replace later_than() with:
--------------
time_t get_gmtime(char *gdstr) {
    char *ip;
    struct tm gtime;

    /* Whatever format we're looking at, it will start with weekday. */
    /* Skip to first space. */
    if(!(ip = strchr(gdstr,' ')))
        return 0;
    else
        while(*ip && isspace(*ip))
            ++ip;

    if(!(*ip))
        return 0;

    if(isalpha(*ip)) {
        /* ctime  (Apr 24 02:49:37 GMT 1994) */
        strptime(ip,"%b %d %T GMT %Y",&gtime);
    }
    else if(ip[2] == '-') {
        /* RFC 850 (24-Apr-94 02:49:37 GMT) */
        strptime(ip,"%d-%b-%y %T GMT",&gtime);
    }
    else {
        /* RFC 822 (24 Apr 1994 02:49:37 GMT) */
        strptime(ip,"%d %b %Y %T GMT",&gtime);
    }
    if (!(gtime.tm_mday && gtime.tm_year))      /* Check for failed strptime */
        return 0;

    gtime.tm_isdst  = 0;                        /* Force it to be GMT */
    gtime.tm_gmtoff = 0;

    return timegm(&gtime);
}
--------------

Naturally, this is dependent on the portability of strptime() and
struct tm including tm_isdst and tm_gmtoff.  I have tested it thoroughly
on  http://simplon.ics.uci.edu/  and it works great (it even behaves
robustly if the date passed is garbage).

Whatcha think?

........Roy


Mime
View raw message