You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@httpd.apache.org by Cody Sherr <cs...@covalent.net> on 2001/08/01 07:13:41 UTC
directive extended to arbitrary methods
The purpose of this patch is to allow modules to register request methods,
and have those methods <limit>able in the httpd.conf. It uses the same bit
mask/shifted offset as the original HTTP methods such as M_GET or M_POST,
but expands the total bits from an int to an ap_int64_t to handle more
bits for new request methods than an int provides.
regards,
--
Cody Sherr
Engineer
Covalent Technologies
phone: (415)536-5292
email: csherr@covalent.net
Index: include/http_config.h
===================================================================
RCS file: /home/cvspublic/httpd-2.0/include/http_config.h,v
retrieving revision 1.82
diff -u -r1.82 http_config.h
--- include/http_config.h 2001/05/28 15:32:50 1.82
+++ include/http_config.h 2001/08/01 05:02:51
@@ -260,7 +260,7 @@
/** Which allow-override bits are set */
int override;
/** Which methods are <Limit>ed */
- int limited;
+ apr_int64_t limited;
apr_array_header_t *limited_xmethods;
ap_method_list_t *xlimited;
Index: include/http_core.h
===================================================================
RCS file: /home/cvspublic/httpd-2.0/include/http_core.h,v
retrieving revision 1.46
diff -u -r1.46 http_core.h
--- include/http_core.h 2001/07/30 18:51:57 1.46
+++ include/http_core.h 2001/08/01 05:02:51
@@ -277,7 +277,7 @@
/** A structure to keep track of authorization requirements */
struct require_line {
/** Where the require line is in the config file. */
- int method_mask;
+ apr_int64_t method_mask;
/** The complete string from the command line */
char *requirement;
};
Index: include/http_protocol.h
===================================================================
RCS file: /home/cvspublic/httpd-2.0/include/http_protocol.h,v
retrieving revision 1.60
diff -u -r1.60 http_protocol.h
--- include/http_protocol.h 2001/07/27 21:01:16 1.60
+++ include/http_protocol.h 2001/08/01 05:02:51
@@ -227,6 +227,34 @@
size_t length);
#endif
+/* The index of the first bit field that is used to index into a limit
+ * bitmask. M_INVALID + 1 to METHOD_NUMBER_LAST.
+ */
+#define METHOD_NUMBER_FIRST M_INVALID + 1
+
+/* The max method number. Method numbers are used to shift bitmasks,
+ * so this cannot exceed 63, and all bits high is equal to -1, which is a
+ * special flag, so the last bit used has index 62.
+ */
+#define METHOD_NUMBER_LAST 62
+
+/**
+ * Register a new request method, and return the offset that will be
+ * associated with that method.
+ *
+ * @param p The pool to create registered method numbers from.
+ * @param methname The name of the new method to register.
+ * @return Ab int value representing an offset into a bitmask.
+ */
+AP_DECLARE(int) ap_method_register(apr_pool_t *p, char *methname);
+
+/**
+ * Initialize the method_registry and allocate memory for it.
+ *
+ * @param p Pool to allocate memory for the registry from.
+ */
+AP_DECLARE(void) ap_method_registry_init(apr_pool_t *p);
+
/**
* Create a new method list with the specified number of preallocated
* slots for extension methods.
Index: include/httpd.h
===================================================================
RCS file: /home/cvspublic/httpd-2.0/include/httpd.h,v
retrieving revision 1.156
diff -u -r1.156 httpd.h
--- include/httpd.h 2001/07/26 15:53:15 1.156
+++ include/httpd.h 2001/08/01 05:02:51
@@ -478,8 +478,6 @@
/* Methods recognized (but not necessarily handled) by the server.
* These constants are used in bit shifting masks of size int, so it is
* unsafe to have more methods than bits in an int. HEAD == M_GET.
- * This list must be tracked by the list in http_protocol.c in routine
- * ap_method_name_of().
*/
#define M_GET 0
#define M_PUT 1
@@ -498,7 +496,10 @@
#define M_UNLOCK 14
#define M_INVALID 15
-#define METHODS 16
+/* METHODS needs to be equal to the number of bits
+ * we are using for limit masks.
+ */
+#define METHODS 64
typedef struct ap_method_list_t ap_method_list_t;
/**
@@ -508,8 +509,8 @@
*/
struct ap_method_list_t {
/* The bitmask used for known methods */
- int method_mask;
- /* The array used for extension methods */
+ apr_int64_t method_mask;
+ /* the array used for extension methods */
apr_array_header_t *method_list;
};
@@ -679,7 +680,7 @@
* HTTP_METHOD_NOT_ALLOWED. Unfortunately this means that a Script GET
* handler can't be installed by mod_actions.
*/
- int allowed;
+ apr_int64_t allowed;
/** Array of extension methods */
apr_array_header_t *allowed_xmethods;
/** List of allowed methods */
Index: modules/aaa/mod_access.c
===================================================================
RCS file: /home/cvspublic/httpd-2.0/modules/aaa/mod_access.c,v
retrieving revision 1.32
diff -u -r1.32 mod_access.c
--- modules/aaa/mod_access.c 2001/04/12 13:35:39 1.32
+++ modules/aaa/mod_access.c 2001/08/01 05:02:51
@@ -91,7 +91,7 @@
};
typedef struct {
- int limited;
+ apr_int64_t limited;
union {
char *from;
apr_ipsubnet_t *ip;
@@ -237,8 +237,9 @@
static int find_allowdeny(request_rec *r, apr_array_header_t *a, int method)
{
+
allowdeny *ap = (allowdeny *) a->elts;
- int mmask = (1 << method);
+ apr_int64_t mmask = (1 << method);
int i;
int gothost = 0;
const char *remotehost = NULL;
Index: modules/http/http_protocol.c
===================================================================
RCS file: /home/cvspublic/httpd-2.0/modules/http/http_protocol.c,v
retrieving revision 1.339
diff -u -r1.339 http_protocol.c
--- modules/http/http_protocol.c 2001/08/01 04:08:36 1.339
+++ modules/http/http_protocol.c 2001/08/01 05:02:52
@@ -299,6 +299,83 @@
return OK;
}
+/**
+ * Singleton registry of additional methods. This maps new method names
+ * such as "MYGET" to methnums, which are int offsets into bitmasks.
+ *
+ * This follows the same technique as standard M_GET, M_POST, etc. These
+ * are dynamically assigned when modules are loaded and <Limit GET MYGET>
+ * directives are processed.
+ */
+static apr_hash_t *methods_registry=NULL;
+
+/**
+ * This keeps track of the currently available method number.
+ */
+static int cur_method_number = METHOD_NUMBER_FIRST;
+
+/* This internal function is used to clear the method registry
+ * and reset the cur_method_number counter.
+ */
+static apr_status_t ap_method_registry_destroy(void *notused)
+{
+ methods_registry = NULL;
+ cur_method_number = METHOD_NUMBER_FIRST;
+ return APR_SUCCESS;
+}
+
+/**
+ * Initialize the method_registry and allocate memory for it.
+ *
+ * @param p Pool to allocate memory for the registry from.
+ */
+AP_DECLARE(void) ap_method_registry_init(apr_pool_t *p)
+{
+ methods_registry = apr_hash_make(p);
+ apr_pool_cleanup_register(p, NULL,
+ ap_method_registry_destroy,
+ apr_pool_cleanup_null);
+}
+
+/**
+ * Register a new request method, and return the offset that will be
+ * associated with that method.
+ *
+ * @param p The pool to create registered method numbers from.
+ * @param methname The name of the new method to register.
+ * @return An int value representing an offset into a bitmask.
+ * M_INVALID is return if methname is NULL or we
+ * have run out of space in the allowed mask.
+ */
+AP_DECLARE(int) ap_method_register(apr_pool_t *p, char *methname)
+{
+ int *newmethnum;
+
+ if (methods_registry == NULL) {
+ ap_method_registry_init(p);
+ }
+
+ if (methname == NULL) {
+ return M_INVALID;
+ }
+
+ if (cur_method_number > METHOD_NUMBER_LAST) {
+ /* The method registry has run out of dynamically
+ * assignable method numbers. Log this and return M_INVALID.
+ */
+ ap_log_perror(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, 0, p,
+ "Maximum new request methods %d reached while registering method %s.",
+ METHOD_NUMBER_LAST, methname);
+ return M_INVALID;
+ }
+
+ newmethnum = (int*)apr_palloc(p,sizeof(int));
+ *newmethnum = cur_method_number++;
+ apr_hash_set(methods_registry, methname, APR_HASH_KEY_STRING, newmethnum);
+
+ return *newmethnum;
+}
+
/* Get the method number associated with the given string, assumed to
* contain an HTTP method. Returns M_INVALID if not recognized.
*
@@ -308,11 +385,13 @@
*/
AP_DECLARE(int) ap_method_number_of(const char *method)
{
+ int *methnum = NULL;
+
switch (*method) {
case 'H':
if (strcmp(method, "HEAD") == 0)
return M_GET; /* see header_only in request_rec */
- break;
+ break;
case 'G':
if (strcmp(method, "GET") == 0)
return M_GET;
@@ -361,7 +440,17 @@
if (strcmp(method, "UNLOCK") == 0)
return M_UNLOCK;
break;
+ }
+
+ /* check if the method has been dynamically registered */
+ if (methods_registry != NULL) {
+ methnum = (int*)apr_hash_get(methods_registry,
+ method,
+ APR_HASH_KEY_STRING);
+ if (methnum != NULL)
+ return *methnum;
}
+
return M_INVALID;
}
@@ -904,7 +993,7 @@
static char *make_allow(request_rec *r)
{
char *list;
- int mask;
+ apr_int64_t mask;
mask = r->allowed_methods->method_mask;
list = apr_pstrcat(r->pool,
@@ -2073,8 +2162,8 @@
char **methods;
/*
- * If it's one of our known methods, use the shortcut and use the
- * bitmask.
+ * If it's a known methods, either builtin or registered
+ * by a module, use the bitmask.
*/
methnum = ap_method_number_of(method);
l->method_mask |= ~(1 << methnum);
Index: server/config.c
===================================================================
RCS file: /home/cvspublic/httpd-2.0/server/config.c,v
retrieving revision 1.130
diff -u -r1.130 config.c
--- server/config.c 2001/07/04 03:16:33 1.130
+++ server/config.c 2001/08/01 05:02:52
@@ -354,30 +354,18 @@
AP_DECLARE(int) ap_method_is_limited(cmd_parms *cmd, const char *method) {
int methnum;
- int i;
- char **xmethod;
methnum = ap_method_number_of(method);
+
/*
- * The simple case: a method hard-coded into Apache.
+ * A method number either hardcoded into apache or
+ * added by a module and registered.
*/
if (methnum != M_INVALID) {
- return (methnum & cmd->limited);
- }
- /*
- * Some extension method we don't know implicitly.
- */
- if ((cmd->limited_xmethods == NULL)
- || (cmd->limited_xmethods->nelts == 0)) {
- return 0;
- }
- xmethod = (char **) cmd->limited_xmethods->elts;
- for (i = 0; i < cmd->limited_xmethods->nelts; ++i) {
- if (strcmp(method, xmethod[i]) == 0) {
- return 1;
- }
+ return (cmd->limited & (1<<methnum));
}
- return 0;
+
+ return 0; /* not found */
}
AP_DECLARE(void) ap_register_hooks(module *m, apr_pool_t *p)
Index: server/core.c
===================================================================
RCS file: /home/cvspublic/httpd-2.0/server/core.c,v
retrieving revision 1.31
diff -u -r1.31 core.c
--- server/core.c 2001/07/30 18:51:57 1.31
+++ server/core.c 2001/08/01 05:02:53
@@ -1466,55 +1466,31 @@
const char *arg) {
const char *limited_methods = ap_getword(cmd->pool, &arg, '>');
void *tog = cmd->cmd->cmd_data;
- int limited = 0;
+ apr_int64_t limited = 0;
const char *errmsg;
-
+ int i = 0;
const char *err = ap_check_cmd_context(cmd, NOT_IN_LIMIT);
+
if (err != NULL) {
return err;
}
while (limited_methods[0]) {
char *method = ap_getword_conf(cmd->pool, &limited_methods);
- int methnum = ap_method_number_of(method);
+ int methnum;
+
+ /* check for builtin or module registered method number */
+ methnum = ap_method_number_of(method);
if (methnum == M_TRACE && !tog) {
return "TRACE cannot be controlled by <Limit>";
}
- else if (methnum == M_INVALID) {
- char **xmethod;
- register int i, j, k;
-
- /*
- * Deal with <Limit> by adding the method to the list.
+ else if (methnum == M_INVALID) {
+ /* method has not been registered yet, but resorce restriction
+ * is always checked before method handling, so register it.
*/
- if (!tog) {
- if (cmd->limited_xmethods == NULL) {
- cmd->limited_xmethods = apr_array_make(cmd->pool, 2,
- sizeof(char *));
- }
- xmethod = (char **) apr_array_push(cmd->limited_xmethods);
- *xmethod = apr_pstrdup(cmd->pool, method);
- }
- /*
- * <LimitExcept>, so remove any/all occurrences of the method
- * in the extension array.
- */
- else if ((cmd->limited_xmethods != NULL)
- && (cmd->limited_xmethods->nelts != 0)) {
- xmethod = (char **) cmd->limited_xmethods->elts;
- for (i = 0; i < cmd->limited_xmethods->nelts; i++) {
- if (strcmp(xmethod[i], method) == 0) {
- for (j = i, k = i + 1;
- k < cmd->limited_xmethods->nelts;
- ++j, ++k) {
- xmethod[j] = xmethod[k];
- }
- cmd->limited_xmethods->nelts--;
- }
- }
- }
- }
+ methnum = ap_method_register(cmd->pool, method);
+ }
limited |= (1 << methnum);
}