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);
}
}