You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@httpd.apache.org by Roy Fielding <fi...@hyperreal.com> on 1996/11/06 11:30:41 UTC

cvs commit: apache/src Makefile.tmpl http_protocol.c util.c

fielding    96/11/06 02:30:40

  Modified:    src       Makefile.tmpl http_protocol.c util.c
  Log:
  Replaced existing code for If-Modified-Since, If-Unmodified-Since,
  If-Match, and If-None-Match in order to correct the order of preference
  regarding ETags and to make use of the parseHTTPdate routine.  Also
  modified the comparison for last-modification time so that it changes
  Last-Modified only if it is greater than the current time, rather than
  the request_time. We also now check to be sure that the incoming
  If-Modified-Since value is not greater than the request_time, which was
  the last non-compliant bit for HTTP/1.1.
  
  Finally, I updated the Makefile dependency list, since it was woefully
  out-of-date and hard to read in its prior form.
  
  Revision  Changes    Path
  1.32      +69 -36    apache/src/Makefile.tmpl
  
  Index: Makefile.tmpl
  ===================================================================
  RCS file: /export/home/cvs/apache/src/Makefile.tmpl,v
  retrieving revision 1.31
  retrieving revision 1.32
  diff -C3 -r1.31 -r1.32
  *** Makefile.tmpl	1996/11/03 20:56:03	1.31
  --- Makefile.tmpl	1996/11/06 10:30:37	1.32
  ***************
  *** 51,94 ****
    	$(CC) -c $(INCLUDES) $(CFLAGS) $(BROKEN_BPRINTF_FLAGS) http_bprintf.c
    
    #Dependencies
  - #Core code
  - $(OBJS): Makefile httpd.h alloc.h buff.h conf.h
    
  ! http_config.o http_core.o http_main.o util.o: http_conf_globals.h
  ! http_config.o http_core.o http_main.o: http_config.h http_log.h
  ! http_log.o http_protocol.o http_request.o modules.o: http_config.h
  ! http_config.o http_core.o http_log.o http_main.o http_protocol.o: http_core.h
  ! http_request.o: http_core.h
  ! http_protocol.o http_request.o util_script.o rfc1413.o: http_log.h
  ! http_core.o http_main.o http_protocol.o http_request.o: http_main.h
  ! http_core.o http_main.o http_protocol.o http_request.o: http_protocol.h
  ! http_config.o http_main.o http_request.o: http_request.h
  ! http_main.o: scoreboard.h
  ! http_core.o rfc1413.o: rfc1413.h
    
  ! #Modules
  ! $(MODULES): http_config.h httpd.h
  ! mod_dld.o: http_conf_globals.h
  ! mod_ai_backcompat.o mod_auth.o mod_auth_dbm.o mod_cgi.o mod_dir.o: http_core.h
  ! mod_access.o mod_imap.o mod_include.o mod_negotiation.o: http_core.h
  ! mod_asis.o mod_auth.o mod_auth_dbm.o mod_cgi.o mod_dir.o: http_core.h
  ! mod_status.o mod_cookies.o mod_log_common.o: http_core.h
  ! mod_access.o mod_imap.o mod_include.o mod_negotiation.o: http_log.h
  ! mod_asis.o mod_cgi.o mod_dir.o mod_imap.o: http_main.h
  ! mod_status.o mod_include.o: http_main.h
  ! mod_asis.o mod_auth.o mod_auth_dbm.o mod_cgi.o: http_protocol.h
  ! mod_status.o mod_dir.o: http_protocol.h
  ! mod_imap.o mod_include.o: http_protocol.h
  ! mod_cgi.o mod_dir.o mod_imap.o mod_include.o mod_negotiation.o: http_request.h
  ! mod_status.o: util_script.h
  ! mod_asis.o mod_cgi.o mod_dir.o mod_imap.o mod_include.o: util_script.h
  ! mod_digest.o: util_md5.h
  ! mod_status.o: scoreboard.h
  ! 
  ! #Utils
    md5c.o: md5.h
  ! util.o: http_conf_globals.h
  ! util_script.o: http_core.h http_main.h http_protocol.h util_script.h
  ! util_md5.o: md5.h
    util_date.o: util_date.h
    
  --- 51,127 ----
    	$(CC) -c $(INCLUDES) $(CFLAGS) $(BROKEN_BPRINTF_FLAGS) http_bprintf.c
    
    #Dependencies
    
  ! $(OBJS): Makefile
    
  ! alloc.o: conf.h alloc.h
  ! buff.o: conf.h alloc.h buff.h
  ! explain.o: explain.h
  ! http_bprintf.o: conf.h alloc.h buff.h
  ! http_config.o: httpd.h http_config.h http_core.h http_log.h http_request.h \
  !                http_conf_globals.h explain.h
  ! http_core.o: httpd.h http_config.h http_core.h http_protocol.h scoreboard.h \
  !              http_conf_globals.h http_main.h http_log.h rfc1413.h util_md5.h
  ! http_log.o: httpd.h http_config.h http_core.h http_log.h
  ! http_main.o: httpd.h http_config.h http_core.h http_log.h http_request.h \
  !              http_conf_globals.h http_protocol.h http_main.h scoreboard.h \
  !              explain.h
  ! http_protocol.o: httpd.h http_config.h http_core.h http_protocol.h \
  !                  http_main.h http_log.h util_date.h
  ! http_request.o: httpd.h http_config.h http_request.h http_core.h \
  !                 http_protocol.h http_log.h http_main.h scoreboard.h
    md5c.o: md5.h
  ! mod_access.o: httpd.h http_core.h http_config.h http_log.h
  ! mod_actions.o: httpd.h http_config.h http_request.h http_core.h \
  !                http_protocol.h http_main.h http_log.h util_script.h
  ! mod_alias.o: httpd.h http_config.h
  ! mod_asis.o: httpd.h http_config.h http_protocol.h http_log.h util_script.h \
  !             http_main.h http_request.h
  ! mod_auth.o: httpd.h http_config.h http_core.h http_log.h http_protocol.h
  ! mod_auth_anon.o: httpd.h http_config.h http_core.h http_log.h http_protocol.h
  ! mod_auth_db.o: httpd.h http_config.h http_core.h http_log.h http_protocol.h
  ! mod_auth_dbm.o: httpd.h http_config.h http_core.h http_log.h http_protocol.h
  ! mod_auth_msql.o: httpd.h http_config.h http_core.h http_log.h http_protocol.h
  ! mod_browser.o: httpd.h http_config.h
  ! mod_cern_meta.o: httpd.h http_config.h util_script.h http_log.h
  ! mod_cgi.o: httpd.h http_config.h http_request.h http_core.h http_protocol.h \
  !            http_main.h http_log.h util_script.h
  ! mod_digest.o: httpd.h http_config.h http_core.h http_log.h http_protocol.h \
  !               util_md5.h
  ! mod_dir.o: httpd.h http_config.h http_core.h http_request.h http_protocol.h \
  !            http_log.h http_main.h util_script.h
  ! mod_dld.o: httpd.h http_config.h http_conf_globals.h
  ! mod_env.o: httpd.h http_config.h
  ! mod_expires.o: httpd.h http_config.h http_log.h
  ! mod_fastcgi.o: httpd.h http_config.h http_request.h http_core.h http_log.h \
  !                http_protocol.h http_main.h util_script.h http_conf_globals.h
  ! mod_headers.o: httpd.h http_config.h
  ! mod_imap.o: httpd.h http_config.h http_request.h http_core.h http_protocol.h \
  !             http_main.h http_log.h util_script.h
  ! mod_include.o: httpd.h http_config.h http_request.h http_core.h http_log.h \
  !                http_protocol.h http_main.h util_script.h
  ! mod_info.o: httpd.h http_config.h http_core.h http_log.h http_main.h \
  !             http_protocol.h util_script.h
  ! mod_log_agent.o: httpd.h http_config.h
  ! mod_log_config.o: httpd.h http_config.h http_core.h
  ! mod_log_referer.o: httpd.h http_config.h
  ! mod_mime.o: httpd.h http_config.h
  ! mod_negotiation.o: httpd.h http_config.h http_request.h http_core.h http_log.h
  ! mod_rewrite.o: httpd.h http_config.h http_request.h http_core.h http_log.h \
  !                mod_rewrite.h
  ! mod_status.o: httpd.h http_config.h http_core.h http_protocol.h http_main.h \
  !               util_script.h scoreboard.h
  ! mod_userdir.o: httpd.h http_config.h
  ! mod_usertrack.o: httpd.h http_config.h http_core.h
  ! modules.o: httpd.h http_config.h
  ! rfc1413.o: httpd.h http_log.h rfc1413.h
  ! util.o: httpd.h http_conf_globals.h
    util_date.o: util_date.h
  + util_md5.o: httpd.h util_md5.h
  + util_script.o: httpd.h http_config.h http_conf_globals.h http_main.h \
  +                http_log.h http_protocol.h http_core.h http_request.h \
  +                util_script.h
    
  + httpd.h: conf.h alloc.h buff.h
  + mod_rewrite.h: regexp/regexp.h
  + util_md5.h: md5.h
  
  
  
  1.71      +75 -118   apache/src/http_protocol.c
  
  Index: http_protocol.c
  ===================================================================
  RCS file: /export/home/cvs/apache/src/http_protocol.c,v
  retrieving revision 1.70
  retrieving revision 1.71
  diff -C3 -r1.70 -r1.71
  *** http_protocol.c	1996/11/04 01:06:09	1.70
  --- http_protocol.c	1996/11/06 10:30:38	1.71
  ***************
  *** 1,5 ****
    /* ====================================================================
  !  * Copyright (c) 1995 The Apache Group.  All rights reserved.
     *
     * Redistribution and use in source and binary forms, with or without
     * modification, are permitted provided that the following conditions
  --- 1,5 ----
    /* ====================================================================
  !  * Copyright (c) 1995, 1996 The Apache Group.  All rights reserved.
     *
     * Redistribution and use in source and binary forms, with or without
     * modification, are permitted provided that the following conditions
  ***************
  *** 51,60 ****
     */
      
    /*
  !  * http_protocol.c --- routines which directly communicate with the
  !  * client.
     *
  !  * Code originally by Rob McCool; much redone by rst.
     */
    
    #define CORE_PRIVATE
  --- 51,60 ----
     */
      
    /*
  !  * http_protocol.c --- routines which directly communicate with the client.
     *
  !  * Code originally by Rob McCool; much redone by Robert S. Thau
  !  * and the Apache Group.
     */
    
    #define CORE_PRIVATE
  ***************
  *** 66,72 ****
    #include "http_log.h"		/* For errors detected in basic auth
    				 * common support code...
    				 */
  ! 
    #include <stdarg.h>
    
    #define SET_BYTES_SENT(r) \
  --- 66,72 ----
    #include "http_log.h"		/* For errors detected in basic auth
    				 * common support code...
    				 */
  ! #include "util_date.h"          /* For parseHTTPdate and BAD_DATE */
    #include <stdarg.h>
    
    #define SET_BYTES_SENT(r) \
  ***************
  *** 74,148 ****
    	  bgetopt (r->connection->client, BO_BYTECT, &r->bytes_sent); \
      } while (0)
    
  - /* Handling of conditional gets (if-modified-since); Roy owes Rob beer. 
  -  * This would be considerably easier if strptime or timegm were portable...
  -  */
  - 
  - const char month_snames[12][4] = {
  -     "Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"
  - };
  - 
  - int find_month(char *mon) {
  -     register int x;
  - 
  -     for(x=0;x<12;x++)
  -         if(!strcmp(month_snames[x],mon))
  -             return x;
  -     return -1;
  - }
  - 
  - int later_than(struct tm *lms, char *ims) {
  -     char *ip;
  -     char mname[MAX_STRING_LEN];
  -     int year = 0, month = 0, day = 0, hour = 0, min = 0, sec = 0, x;
  - 
  -     /* Whatever format we're looking at, it will start with weekday. */
  -     /* Skip to first space. */
  -     if(!(ip = strchr(ims,' ')))
  -         return 0;
  -     else
  -         while(isspace(*ip))
  -             ++ip;
  - 
  -     if(isalpha(*ip)) {
  -         /* ctime */
  -         sscanf(ip,"%s %d %d:%d:%d %d",mname,&day,&hour,&min,&sec,&year);
  -     }
  -     else if(ip[2] == '-') {
  -         /* RFC 850 (normal HTTP) */
  -         char t[MAX_STRING_LEN];
  -         sscanf(ip,"%s %d:%d:%d",t,&hour,&min,&sec);
  -         t[2] = '\0';
  -         day = atoi(t);
  -         t[6] = '\0';
  -         strcpy(mname,&t[3]);
  -         x = atoi(&t[7]);
  -         /* Prevent wraparound from ambiguity */
  -         if(x < 70)
  -             x += 100;
  -         year = 1900 + x;
  -     }
  -     else {
  -         /* RFC 822 */
  -         sscanf(ip,"%d %s %d %d:%d:%d",&day,mname,&year,&hour,&min,&sec);
  -     }
  -     month = find_month(mname);
  - 
  -     if((x = (1900+lms->tm_year) - year))
  -         return x < 0;
  -     if((x = lms->tm_mon - month))
  -         return x < 0;
  -     if((x = lms->tm_mday - day))
  -         return x < 0;
  -     if((x = lms->tm_hour - hour))
  -         return x < 0;
  -     if((x = lms->tm_min - min))
  -         return x < 0;
  -     if((x = lms->tm_sec - sec))
  -         return x < 0;
  - 
  -     return 1;
  - }
    
    static int parse_byterange (char *range, long clength, long *start, long *end)
    {
  --- 74,79 ----
  ***************
  *** 175,185 ****
        return 1;
    }
    
  - /* This is a string I made up. Pounded on the keyboard a couple of times.
  -  * It's a good a way as any, I suppose, if you can't parse the document
  -  * beforehand (which we can't).
  -  */
  - 
    int set_byterange (request_rec *r)
    {
        char *range = table_get (r->headers_in, "Range");
  --- 106,111 ----
  ***************
  *** 320,335 ****
    
    int set_last_modified(request_rec *r, time_t mtime)
    {
  !     char *ts, *etag, weak_etag[MAX_STRING_LEN];
  !     char *if_modified_since = table_get (r->headers_in, "If-Modified-Since");
  !     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");
    
  !     ts = gm_timestr_822(r->pool, (mtime > r->request_time) ? r->request_time : mtime);
  !     table_set (r->headers_out, "Last-Modified", ts);
    
  !     /* Make an ETag header out of various peices of information. We use
         * the last-modified date and, if we have a real file, the
         * length and inode number - note that this doesn't have to match
         * the content-length (i.e. includes), it just has to be unique
  --- 246,262 ----
    
    int set_last_modified(request_rec *r, time_t mtime)
    {
  !     char *etag, weak_etag[MAX_STRING_LEN];
  !     char *if_modified_since = table_get(r->headers_in, "If-Modified-Since");
  !     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 now = time(NULL);
    
  !     table_set(r->headers_out, "Last-Modified",
  !               gm_timestr_822(r->pool, (mtime > now) ? now : mtime));
    
  !     /* Make an ETag header out of various pieces of information. We use
         * the last-modified date and, if we have a real file, the
         * length and inode number - note that this doesn't have to match
         * the content-length (i.e. includes), it just has to be unique
  ***************
  *** 343,391 ****
    
        if (r->finfo.st_mode != 0)
            sprintf(weak_etag, "W/\"%lx-%lx-%lx\"", (unsigned long)r->finfo.st_ino,
  ! 		(unsigned long)r->finfo.st_size, mtime);
        else
  !         sprintf(weak_etag, "W/\"%lx\"", mtime);
    
        etag = weak_etag + ((r->request_time - mtime > 1) ? 2 : 0);
        table_set (r->headers_out, "ETag", etag);
    
  !     /* We now do the no_cache stuff using an Expires: header (we used to
  !      * withhold Last-modified). However, we still want to enforce this by
  !      * not allowing conditional GETs.
         */
    
  !     if (r->no_local_copy) return OK;
    
  !     /* Check for conditional GETs --- note that we only want this check
  !      * to succeed if the GET was successful; ErrorDocuments *always* get sent.
         */
  -     
  -     if (!is_HTTP_SUCCESS(r->status))
  -         return OK;
    
  !     if (if_modified_since && !r->header_only &&
  ! 	later_than(gmtime(&mtime), if_modified_since))
  !         return USE_LOCAL_COPY;
  !     else if (if_unmodified && !later_than(gmtime(&mtime), if_unmodified))
  !         return PRECONDITION_FAILED;
  !     else if (if_nonematch && ((if_nonematch[0] == '*') ||
  ! 			      find_token(r->pool, if_nonematch, etag)))
  !         return (r->method_number == M_GET) ?
  ! 	    USE_LOCAL_COPY : PRECONDITION_FAILED;
  !     else if (if_match && !((if_match[0] == '*') ||
  ! 			   find_token(r->pool, if_match, etag)))
  !         return PRECONDITION_FAILED;
  !     else
  !         return OK;
  ! }
    
  ! /*
  !  * Finally, real protocol stuff.
  !  */
    
  ! static char *
  ! getline(char *s, int n, BUFF *in)
    {
        int retval = bgets (s, n, in);
    
  --- 270,348 ----
    
        if (r->finfo.st_mode != 0)
            sprintf(weak_etag, "W/\"%lx-%lx-%lx\"", (unsigned long)r->finfo.st_ino,
  ! 		(unsigned long)r->finfo.st_size, (unsigned long)mtime);
        else
  !         sprintf(weak_etag, "W/\"%lx\"", (unsigned long)mtime);
    
        etag = weak_etag + ((r->request_time - mtime > 1) ? 2 : 0);
        table_set (r->headers_out, "ETag", etag);
    
  !     /* Check for conditional requests --- note that we only want to do
  !      * this if we are successful so far and we are not processing a
  !      * subrequest or an ErrorDocument.
  !      *
  !      * The order of the checks is important, since etag checks are supposed
  !      * to be more accurate than checks relative to the modification time.
  !      */
  !     
  !     if (!is_HTTP_SUCCESS(r->status) || r->no_local_copy)
  !         return OK;
  ! 
  !     /* If an If-Match request-header field was given and
  !      * if our ETag does not match any of the entity tags in that field
  !      * and the field value is not "*" (meaning match anything), then
  !      *    respond with a status of 412 (Precondition Failed).
         */
    
  !     if (if_match &&
  !         !((if_match[0] == '*') || find_token(r->pool, if_match, etag)))
  !         return HTTP_PRECONDITION_FAILED;
  ! 
  !     /* If an If-None-Match request-header field was given and
  !      * if our ETag matches any of the entity tags in that field or
  !      * if the field value is "*" (meaning match anything), then
  !      *    if the request method was GET or HEAD, the server SHOULD
  !      *       respond with a 304 (Not Modified) response.
  !      *    For all other request methods, the server MUST
  !      *       respond with a status of 412 (Precondition Failed).
  !      */
    
  !     if (if_nonematch &&
  !         ((if_nonematch[0] == '*') || find_token(r->pool, if_nonematch, etag)))
  !         return ((r->method_number == M_GET) || r->header_only) ?
  !                    HTTP_NOT_MODIFIED : HTTP_PRECONDITION_FAILED;
  ! 
  !     /* If a valid If-Unmodified-Since request-header field was given
  !      * and the requested resource has been modified since the time
  !      * specified in this field, then the server MUST
  !      *    respond with a status of 412 (Precondition Failed).
         */
    
  !     if (if_unmodified) {
  !         time_t ius = parseHTTPdate(if_unmodified);
    
  !         if ((ius != BAD_DATE) && (mtime > ius))
  !             return HTTP_PRECONDITION_FAILED;
  !     }
  ! 
  !     /* If a valid If-Modified-Since request-header field was given on a GET
  !      * and the requested resource has not been modified since the time
  !      * specified in this field, then the server MUST
  !      *    respond with a status of 304 (Not Modified).
  !      * A date later than the server's current request time is invalid.
  !      */
  ! 
  !     if (if_modified_since && (r->method_number == M_GET)) {
  !         time_t ims = parseHTTPdate(if_modified_since);
  ! 
  !         if ((ims >= mtime) && (ims <= r->request_time))
  !             return HTTP_NOT_MODIFIED;
  !     }
  ! 
  !     return OK;
  ! }
    
  ! static char *getline(char *s, int n, BUFF *in)
    {
        int retval = bgets (s, n, in);
    
  
  
  
  1.29      +4 -0      apache/src/util.c
  
  Index: util.c
  ===================================================================
  RCS file: /export/home/cvs/apache/src/util.c,v
  retrieving revision 1.28
  retrieving revision 1.29
  diff -C3 -r1.28 -r1.29
  *** util.c	1996/10/27 07:23:21	1.28
  --- util.c	1996/11/06 10:30:38	1.29
  ***************
  *** 61,66 ****
  --- 61,70 ----
    #include "httpd.h"
    #include "http_conf_globals.h"	/* for user_id & group_id */
    
  + const char month_snames[12][4] = {
  +     "Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"
  + };
  + 
    char *get_time() {
        time_t t;
        char *time_string;