You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@httpd.apache.org by co...@locus.apache.org on 2000/09/13 03:58:17 UTC

cvs commit: apache-2.0/src/main http_core.c http_protocol.c http_request.c

coar        00/09/12 18:58:16

  Modified:    src/include http_config.h http_protocol.h httpd.h
               src/main http_core.c http_protocol.c http_request.c
  Log:
  	Start introducing the extension-method elements so we're not
  	bound to hard-coded names and a bitmask.  We still use the
  	bitmask for known methods, but we also have an array for
  	extension method named.  Wherever we used the M_* constants
  	we need to use a routine that knows about the new structure instead.
  
  	This is far from complete, but AFAIK this interim work doesn't
  	break anything -- especially the compile.  The rest of the
  	work will be added in segments; this is just a checkpoint.
  
  Revision  Changes    Path
  1.49      +1 -0      apache-2.0/src/include/http_config.h
  
  Index: http_config.h
  ===================================================================
  RCS file: /home/cvs/apache-2.0/src/include/http_config.h,v
  retrieving revision 1.48
  retrieving revision 1.49
  diff -u -u -r1.48 -r1.49
  --- http_config.h	2000/08/11 23:41:51	1.48
  +++ http_config.h	2000/09/13 01:58:13	1.49
  @@ -287,6 +287,7 @@
       /** Which methods are <Limit>ed */
       int limited;
       apr_array_header_t *limited_xmethods;
  +    ap_method_list_t *xlimited;
   
       /** Config file structure. */
       configfile_t *config_file;
  
  
  
  1.24      +63 -0     apache-2.0/src/include/http_protocol.h
  
  Index: http_protocol.h
  ===================================================================
  RCS file: /home/cvs/apache-2.0/src/include/http_protocol.h,v
  retrieving revision 1.23
  retrieving revision 1.24
  diff -u -u -r1.23 -r1.24
  --- http_protocol.h	2000/08/12 18:45:32	1.23
  +++ http_protocol.h	2000/09/13 01:58:13	1.24
  @@ -252,6 +252,69 @@
   API_EXPORT(size_t) ap_send_mmap(apr_mmap_t *mm, request_rec *r, size_t offset,
                                size_t length);
   
  +/**
  + * Create a new method list with the specified number of preallocated
  + * slots for extension methods.
  + *
  + * @param   p       Pointer to a pool in which the structure should be
  + *                  allocated.
  + * @param   nelts   Number of preallocated extension slots
  + * @return  Pointer to the newly created structure.
  + * @deffunc ap_method_list_t ap_make_method_list(apr_pool_t *p, int nelts)
  + */
  +API_EXPORT(ap_method_list_t *) ap_make_method_list(apr_pool_t *p, int nelts);
  +API_EXPORT(void) ap_copy_method_list(ap_method_list_t *dest,
  +				     ap_method_list_t *src);
  +API_EXPORT(void) ap_method_list_do(int (*comp) (void *urec, const char *mname,
  +						int mnum),
  +				   void *rec,
  +				   const ap_method_list_t *ml, ...);
  +API_EXPORT(void) ap_method_list_vdo(int (*comp) (void *urec, const char *mname,
  +						 int mnum),
  +				    void *rec, const ap_method_list_t *ml,
  +				    va_list vp);
  +/**
  + * Search for an HTTP method name in an ap_method_list_t structure, and
  + * return true if found.
  + *
  + * @param   method  String containing the name of the method to check.
  + * @param   l       Pointer to a method list, such as cmd->methods_limited.
  + * @return  1 if method is in the list, otherwise 0
  + * @deffunc int ap_method_in_list(const char *method, ap_method_list_t *l)
  + */
  +API_EXPORT(int) ap_method_in_list(ap_method_list_t *l, const char *method);
  +
  +/**
  + * Add an HTTP method name to an ap_method_list_t structure if it isn't
  + * already listed.
  + *
  + * @param   method  String containing the name of the method to check.
  + * @param   l       Pointer to a method list, such as cmd->methods_limited.
  + * @return  None.
  + * @deffunc void ap_method_in_list(ap_method_list_t *l, const char *method)
  + */
  +API_EXPORT(void) ap_method_list_add(ap_method_list_t *l, const char *method);
  +    
  +/**
  + * Remove an HTTP method name from an ap_method_list_t structure.
  + *
  + * @param   l       Pointer to a method list, such as cmd->methods_limited.
  + * @param   method  String containing the name of the method to remove.
  + * @return  None.
  + * @deffunc void ap_method_list_remove(ap_method_list_t *l, const char *method)
  + */
  +API_EXPORT(void) ap_method_list_remove(ap_method_list_t *l,
  +				       const char *method);
  +
  +/**
  + * Reset a method list to be completely empty.
  + *
  + * @param   l       Pointer to a method list, such as cmd->methods_limited.
  + * @return  None.
  + * @deffunc void ap_clear_method_list(ap_method_list_t *l)
  + */
  +API_EXPORT(void) ap_clear_method_list(ap_method_list_t *l);
  +    
   /* Hmmm... could macrofy these for now, and maybe forever, though the
    * definitions of the macros would get a whole lot hairier.
    */
  
  
  
  1.85      +11 -0     apache-2.0/src/include/httpd.h
  
  Index: httpd.h
  ===================================================================
  RCS file: /home/cvs/apache-2.0/src/include/httpd.h,v
  retrieving revision 1.84
  retrieving revision 1.85
  diff -u -u -r1.84 -r1.85
  --- httpd.h	2000/09/12 03:40:15	1.84
  +++ httpd.h	2000/09/13 01:58:13	1.85
  @@ -484,6 +484,16 @@
   
   #define METHODS     16
   
  +/*
  + * Structure for handling HTTP methods.  Methods known to the server are
  + * accessed via a bitmask shortcut; extension methods are handled by
  + * an array.
  + */
  +typedef struct {
  +    int method_mask;
  +    apr_array_header_t *method_list;
  +} ap_method_list_t;
  +
   #define CGI_MAGIC_TYPE "application/x-httpd-cgi"
   #define INCLUDES_MAGIC_TYPE "text/x-server-parsed-html"
   #define INCLUDES_MAGIC_TYPE3 "text/x-server-parsed-html3"
  @@ -668,6 +678,7 @@
        */
       int allowed;		/* Allowed methods - for 405, OPTIONS, etc */
       apr_array_header_t *allowed_xmethods; /* Array of extension methods */
  +    ap_method_list_t *allowed_methods; /* List of allowed methods */
   
       /** byte count in stream is for body */
       int sent_bodyct;
  
  
  
  1.118     +1 -3      apache-2.0/src/main/http_core.c
  
  Index: http_core.c
  ===================================================================
  RCS file: /home/cvs/apache-2.0/src/main/http_core.c,v
  retrieving revision 1.117
  retrieving revision 1.118
  diff -u -u -r1.117 -r1.118
  --- http_core.c	2000/09/10 05:00:03	1.117
  +++ http_core.c	2000/09/13 01:58:14	1.118
  @@ -1497,9 +1497,7 @@
   		}
   	    }
           }
  -        else {
  -            limited |= (1 << methnum);
  -        }
  +	limited |= (1 << methnum);
       }
   
       /* Killing two features with one function,
  
  
  
  1.123     +192 -20   apache-2.0/src/main/http_protocol.c
  
  Index: http_protocol.c
  ===================================================================
  RCS file: /home/cvs/apache-2.0/src/main/http_protocol.c,v
  retrieving revision 1.122
  retrieving revision 1.123
  diff -u -u -r1.122 -r1.123
  --- http_protocol.c	2000/09/13 01:36:01	1.122
  +++ http_protocol.c	2000/09/13 01:58:15	1.123
  @@ -1181,6 +1181,8 @@
       r->user            = NULL;
       r->ap_auth_type    = NULL;
   
  +    r->allowed_methods = ap_make_method_list(p, 2);
  +
       r->headers_in      = apr_make_table(r->pool, 50);
       r->subprocess_env  = apr_make_table(r->pool, 50);
       r->headers_out     = apr_make_table(r->pool, 12);
  @@ -1645,40 +1647,210 @@
       (void) checked_bputs(CRLF, r);  /* Send the terminating empty line */
   }
   
  +/*
  + * Create a new method list with the specified number of preallocated
  + * extension slots.
  + */
  +API_EXPORT(ap_method_list_t *) ap_make_method_list(apr_pool_t *p, int nelts)
  +{
  +    ap_method_list_t *ml;
  +
  +    ml = (ap_method_list_t *) apr_palloc(p, sizeof(ap_method_list_t));
  +    ml->method_mask = 0;
  +    ml->method_list = apr_make_array(p, sizeof(char *), nelts);
  +    return ml;
  +}
  +
  +/*
  + * Make a copy of a method list (primarily for subrequests that may
  + * subsequently change it; don't want them changing the parent's, too!).
  + */
  +API_EXPORT(void) ap_copy_method_list(ap_method_list_t *dest,
  +				     ap_method_list_t *src)
  +{
  +    int i;
  +    char **imethods;
  +    char **omethods;
  +
  +    dest->method_mask = src->method_mask;
  +    imethods = (char **) src->method_list->elts;
  +    for (i = 0; i < src->method_list->nelts; ++i) {
  +	omethods = (char **) apr_push_array(dest->method_list);
  +	*omethods = apr_pstrdup(dest->method_list->cont, imethods[i]);
  +    }
  +}
  +
  +/*
  + * Invoke a callback routine for each method in the specified list.
  + */
  +API_EXPORT(void) ap_method_list_do(int (*comp) (void *urec, const char *mname,
  +						int mnum),
  +				   void *rec,
  +				   const ap_method_list_t *ml, ...)
  +{
  +    va_list vp;
  +    va_start(vp, ml);
  +    ap_method_list_vdo(comp, rec, ml, vp);
  +    va_end(vp);  
  +}
  +
  +API_EXPORT(void) ap_method_list_vdo(int (*comp) (void *mrec,
  +						 const char *mname,
  +						 int mnum),
  +				    void *rec, const ap_method_list_t *ml,
  +				    va_list vp)
  +{
  +    
  +}
  +
  +/*
  + * Return true if the specified HTTP method is in the provided
  + * method list.
  + */
  +API_EXPORT(int) ap_method_in_list(ap_method_list_t *l, const char *method)
  +{
  +    int methnum;
  +    int i;
  +    char **methods;
  +
  +    /*
  +     * If it's one of our known methods, use the shortcut and check the
  +     * bitmask.
  +     */
  +    methnum = ap_method_number_of(method);
  +    if (methnum != M_INVALID) {
  +	return (l->method_mask & (1 << methnum));
  +    }
  +    /*
  +     * Otherwise, see if the method name is in the array or string names
  +     */
  +    if ((l->method_list = NULL) || (l->method_list->nelts == 0)) {
  +	return 0;
  +    }
  +    for (i = 0; i < l->method_list->nelts; ++i) {
  +	if (strcmp(method, methods[i]) == 0) {
  +	    return 1;
  +	}
  +    }
  +    return 0;
  +}
  +    
  +/*
  + * Add the specified method to a method list (if it isn't already there).
  + */
  +API_EXPORT(void) ap_method_list_add(ap_method_list_t *l, const char *method)
  +{
  +    int methnum;
  +    int i;
  +    const char **xmethod;
  +    char **methods;
  +
  +    /*
  +     * If it's one of our known methods, use the shortcut and use the
  +     * bitmask.
  +     */
  +    methnum = ap_method_number_of(method);
  +    l->method_mask |= (1 << methnum);
  +    if (methnum != M_INVALID) {
  +	return;
  +    }
  +    /*
  +     * Otherwise, see if the method name is in the array of string names.
  +     */
  +    if (l->method_list->nelts != 0) {
  +	for (i = 0; i < l->method_list->nelts; ++i) {
  +	    if (strcmp(method, methods[i]) == 0) {
  +		return;
  +	    }
  +	}
  +    }
  +    xmethod = (const char **) apr_push_array(l->method_list);
  +    *xmethod = method;
  +}
  +    
  +/*
  + * Remove the specified method from a method list.
  + */
  +API_EXPORT(void) ap_method_list_remove(ap_method_list_t *l,
  +				       const char *method)
  +{
  +    int methnum;
  +    const char **xmethod;
  +    char **methods;
  +
  +    /*
  +     * If it's one of our known methods, use the shortcut and use the
  +     * bitmask.
  +     */
  +    methnum = ap_method_number_of(method);
  +    l->method_mask |= ~(1 << methnum);
  +    if (methnum != M_INVALID) {
  +	return;
  +    }
  +    /*
  +     * Otherwise, see if the method name is in the array of string names.
  +     */
  +    if (l->method_list->nelts != 0) {
  +	register int i, j, k;
  +	for (i = 0; i < l->method_list->nelts; ) {
  +	    if (strcmp(method, methods[i]) == 0) {
  +		for (j = i, k = i + 1; k < l->method_list->nelts; ++j, ++k) {
  +		    methods[j] = methods[k];
  +		}
  +		--l->method_list->nelts;
  +	    }
  +	    else {
  +		++i;
  +	    }
  +	}
  +    }
  +}
  +
  +/*
  + * Reset a method list to be completely empty.
  + */
  +API_EXPORT(void) ap_clear_method_list(ap_method_list_t *l)
  +{
  +    l->method_mask = 0;
  +    l->method_list->nelts = 0;
  +}
  +
   /* Build the Allow field-value from the request handler method mask.
    * Note that we always allow TRACE, since it is handled below.
    */
   static char *make_allow(request_rec *r)
   {
       char *list;
  +    int mask;
   
  +    mask = r->allowed_methods->method_mask;
       list = apr_pstrcat(r->pool,
  -		       (r->allowed & (1 << M_GET))       ? ", GET, HEAD" : "",
  -		       (r->allowed & (1 << M_POST))      ? ", POST"      : "",
  -		       (r->allowed & (1 << M_PUT))       ? ", PUT"       : "",
  -		       (r->allowed & (1 << M_DELETE))    ? ", DELETE"    : "",
  -		       (r->allowed & (1 << M_CONNECT))   ? ", CONNECT"   : "",
  -		       (r->allowed & (1 << M_OPTIONS))   ? ", OPTIONS"   : "",
  -		       (r->allowed & (1 << M_PATCH))     ? ", PATCH"     : "",
  -		       (r->allowed & (1 << M_PROPFIND))  ? ", PROPFIND"  : "",
  -		       (r->allowed & (1 << M_PROPPATCH)) ? ", PROPPATCH" : "",
  -		       (r->allowed & (1 << M_MKCOL))     ? ", MKCOL"     : "",
  -		       (r->allowed & (1 << M_COPY))      ? ", COPY"      : "",
  -		       (r->allowed & (1 << M_MOVE))      ? ", MOVE"      : "",
  -		       (r->allowed & (1 << M_LOCK))      ? ", LOCK"      : "",
  -		       (r->allowed & (1 << M_UNLOCK))    ? ", UNLOCK"    : "",
  +		       (mask & (1 << M_GET))	   ? ", GET, HEAD" : "",
  +		       (mask & (1 << M_POST))	   ? ", POST"      : "",
  +		       (mask & (1 << M_PUT))	   ? ", PUT"       : "",
  +		       (mask & (1 << M_DELETE))	   ? ", DELETE"    : "",
  +		       (mask & (1 << M_CONNECT))   ? ", CONNECT"   : "",
  +		       (mask & (1 << M_OPTIONS))   ? ", OPTIONS"   : "",
  +		       (mask & (1 << M_PATCH))	   ? ", PATCH"     : "",
  +		       (mask & (1 << M_PROPFIND))  ? ", PROPFIND"  : "",
  +		       (mask & (1 << M_PROPPATCH)) ? ", PROPPATCH" : "",
  +		       (mask & (1 << M_MKCOL))	   ? ", MKCOL"     : "",
  +		       (mask & (1 << M_COPY))	   ? ", COPY"      : "",
  +		       (mask & (1 << M_MOVE))	   ? ", MOVE"      : "",
  +		       (mask & (1 << M_LOCK))	   ? ", LOCK"      : "",
  +		       (mask & (1 << M_UNLOCK))	   ? ", UNLOCK"    : "",
   		       ", TRACE",
   		       NULL);
  -    if ((r->allowed & (1 << M_INVALID))
  -	&& (r->allowed_xmethods != NULL)
  -	&& (r->allowed_xmethods->nelts != 0)) {
  +    if ((mask & (1 << M_INVALID))
  +	&& (r->allowed_methods->method_list != NULL)
  +	&& (r->allowed_methods->method_list->nelts != 0)) {
   	int i;
  -	char **xmethod = (char **) r->allowed_xmethods->elts;
  +	char **xmethod = (char **) r->allowed_methods->method_list->elts;
   
   	/*
  -	 * Append all of the elements of r->allowed_xmethods
  +	 * Append all of the elements of r->allowed_methods->method_list
   	 */
  -	for (i = 0; i < r->allowed_xmethods->nelts; ++i) {
  +	for (i = 0; i < r->allowed_methods->method_list->nelts; ++i) {
   	    list = apr_pstrcat(r->pool, list, ", ", xmethod[i], NULL);
   	}
       }
  
  
  
  1.45      +11 -45    apache-2.0/src/main/http_request.c
  
  Index: http_request.c
  ===================================================================
  RCS file: /home/cvs/apache-2.0/src/main/http_request.c,v
  retrieving revision 1.44
  retrieving revision 1.45
  diff -u -u -r1.44 -r1.45
  --- http_request.c	2000/08/22 18:01:47	1.44
  +++ http_request.c	2000/09/13 01:58:15	1.45
  @@ -864,6 +864,9 @@
       rnew->htaccess       = r->htaccess;
       rnew->chunked        = r->chunked;
   
  +    /* make a copy of the allowed-methods list */
  +    ap_copy_method_list(rnew->allowed_methods, r->allowed_methods);
  +
       /* start with the same set of output filters */
       rnew->filters = r->filters;
   
  @@ -1321,10 +1324,11 @@
       return new;
   }
   
  -static request_rec *internal_internal_redirect(const char *new_uri, request_rec *r)
  -{
  +static request_rec *internal_internal_redirect(const char *new_uri,
  +					       request_rec *r) {
       int access_status;
  -    request_rec *new = (request_rec *) apr_pcalloc(r->pool, sizeof(request_rec));
  +    request_rec *new = (request_rec *) apr_pcalloc(r->pool,
  +						   sizeof(request_rec));
   
       new->connection = r->connection;
       new->server     = r->server;
  @@ -1338,6 +1342,7 @@
   
       new->method          = r->method;
       new->method_number   = r->method_number;
  +    new->allowed_methods = ap_make_method_list(new->pool, 2);
       ap_parse_uri(new, new_uri);
       new->request_config = ap_create_request_config(r->pool);
       new->per_dir_config = r->server->lookup_defaults;
  @@ -1365,6 +1370,7 @@
       new->err_headers_out = r->err_headers_out;
       new->subprocess_env  = rename_original_env(r->pool, r->subprocess_env);
       new->notes           = apr_make_table(r->pool, 5);
  +    new->allowed_methods = ap_make_method_list(new->pool, 2);
   
       new->htaccess        = r->htaccess;
       new->no_cache        = r->no_cache;
  @@ -1445,51 +1451,11 @@
        * well-known methods but any extensions as well.
        */
       if (reset) {
  -	r->allowed = 0;
  -	if (r->allowed_xmethods != NULL) {
  -	    r->allowed_xmethods->nelts = 0;
  -	}
  +	ap_clear_method_list(r->allowed_methods);
       }
   
       va_start(methods, reset);
       while ((method = va_arg(methods, const char *)) != NULL) {
  -	/*
  -	 * Look up our internal number for this particular method.
  -	 * Even if it isn't one of the ones we know about, the return
  -	 * value is used in the same way.
  -	 */
  -	mnum = ap_method_number_of(method);
  -	r->allowed |= (1 << mnum);
  -	/*
  -	 * Now, if we don't know about it, we regard it as an
  -	 * extension method.  Add it to our array of such.  This means
  -	 * that anything that checks for M_INVALID needs to make an
  -	 * additional check of this array if it *is* invalid.
  -	 */
  -	if (mnum == M_INVALID) {
  -	    int i;
  -	    int found;
  -	    char **xmethods;
  -
  -	    if (r->allowed_xmethods == NULL) {
  -		r->allowed_xmethods = apr_make_array(r->pool, 2,
  -						     sizeof(char *));
  -	    }
  -	    /*
  -	     * Don't add it to the array if it's already listed.
  -	     */
  -	    xmethods = (char **) r->allowed_xmethods->elts;
  -	    found = 0;
  -	    for (i = 0; i < r->allowed_xmethods->nelts; ++i) {
  -		if (strcmp(method, xmethods[i]) == 0) {
  -		    found++;
  -		    break;
  -		}
  -	    }
  -	    if (!found) {
  -		xmethod = (const char **) apr_push_array(r->allowed_xmethods);
  -		*xmethod = method;
  -	    }
  -	}
  +	ap_method_list_add(r->allowed_methods, method);
       }
   }