fielding 98/11/08 01:51:12
Modified: src CHANGES
src/include ap_mmn.h http_protocol.h httpd.h
src/main http_core.c http_protocol.c
src/modules/standard mod_actions.c
Log:
Enabled all of the WebDAV method names for use by third-party
modules, Limit, and Script directives. That includes PATCH,
PROPFIND, PROPPATCH, MKCOL, COPY, MOVE, LOCK, and UNLOCK.
Improved mod_actions.c so that it can use any of the methods
defined in httpd.h. Added ap_method_number_of(method) for
getting the internal method number.
I would have preferred to use a configurable table for new methods,
but the current API is too dependent on methods being represented as
a bitmask. We need to rethink this in the next major server version.
Revision Changes Path
1.1140 +7 -0 apache-1.3/src/CHANGES
Index: CHANGES
===================================================================
RCS file: /home/cvs/apache-1.3/src/CHANGES,v
retrieving revision 1.1139
retrieving revision 1.1140
diff -u -r1.1139 -r1.1140
--- CHANGES 1998/11/07 14:31:21 1.1139
+++ CHANGES 1998/11/08 09:51:07 1.1140
@@ -1,5 +1,12 @@
Changes with Apache 1.3.4
+ *) Enabled all of the WebDAV method names for use by third-party
+ modules, Limit, and Script directives. That includes PATCH,
+ PROPFIND, PROPPATCH, MKCOL, COPY, MOVE, LOCK, and UNLOCK.
+ Improved mod_actions.c so that it can use any of the methods
+ defined in httpd.h. Added ap_method_number_of(method) for
+ getting the internal method number. [Roy Fielding]
+
*) PORT: Add a port to the TPF OS. [Joe Moenich <[EMAIL PROTECTED]> and
others at IBM]
1.10 +3 -1 apache-1.3/src/include/ap_mmn.h
Index: ap_mmn.h
===================================================================
RCS file: /home/cvs/apache-1.3/src/include/ap_mmn.h,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -r1.9 -r1.10
--- ap_mmn.h 1998/10/03 18:46:01 1.9
+++ ap_mmn.h 1998/11/08 09:51:09 1.10
@@ -181,10 +181,12 @@
* (for implementing better error reporting).
* 19980906 (1.3.2-dev) - added ap_md5_binary()
* 19980917 (1.3.2-dev) - bs2000: changed os_set_authfile() to
os_set_account()
+ * 19981108 (1.3.4-dev) - added ap_method_number_of()
+ * - changed value of M_INVALID and added WebDAV methods
*/
#ifndef MODULE_MAGIC_NUMBER_MAJOR
-#define MODULE_MAGIC_NUMBER_MAJOR 19980917
+#define MODULE_MAGIC_NUMBER_MAJOR 19981108
#endif
#define MODULE_MAGIC_NUMBER_MINOR 0 /* 0...n */
#define MODULE_MAGIC_NUMBER MODULE_MAGIC_NUMBER_MAJOR /* backward
compat */
1.46 +5 -0 apache-1.3/src/include/http_protocol.h
Index: http_protocol.h
===================================================================
RCS file: /home/cvs/apache-1.3/src/include/http_protocol.h,v
retrieving revision 1.45
retrieving revision 1.46
diff -u -r1.45 -r1.46
--- http_protocol.h 1998/08/09 14:33:10 1.45
+++ http_protocol.h 1998/11/08 09:51:09 1.46
@@ -209,6 +209,11 @@
CORE_EXPORT(void) ap_parse_uri(request_rec *r, const char *uri);
+/* Get the method number associated with the given string, assumed to
+ * contain an HTTP method. Returns M_INVALID if not recognized.
+ */
+API_EXPORT(int) ap_method_number_of(const char *method);
+
#ifdef __cplusplus
}
#endif
1.251 +21 -9 apache-1.3/src/include/httpd.h
Index: httpd.h
===================================================================
RCS file: /home/cvs/apache-1.3/src/include/httpd.h,v
retrieving revision 1.250
retrieving revision 1.251
diff -u -r1.250 -r1.251
--- httpd.h 1998/11/05 20:07:51 1.250
+++ httpd.h 1998/11/08 09:51:09 1.251
@@ -531,16 +531,28 @@
((x) == HTTP_SERVICE_UNAVAILABLE) || \
((x) == HTTP_NOT_IMPLEMENTED))
+/* 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.
+ */
+#define M_GET 0
+#define M_PUT 1
+#define M_POST 2
+#define M_DELETE 3
+#define M_CONNECT 4
+#define M_OPTIONS 5
+#define M_TRACE 6
+#define M_PATCH 7
+#define M_PROPFIND 8
+#define M_PROPPATCH 9
+#define M_MKCOL 10
+#define M_COPY 11
+#define M_MOVE 12
+#define M_LOCK 13
+#define M_UNLOCK 14
-#define METHODS 8
-#define M_GET 0
-#define M_PUT 1
-#define M_POST 2
-#define M_DELETE 3
-#define M_CONNECT 4
-#define M_OPTIONS 5
-#define M_TRACE 6
-#define M_INVALID 7
+#define METHODS 15
+#define M_INVALID 31
#define CGI_MAGIC_TYPE "application/x-httpd-cgi"
#define INCLUDES_MAGIC_TYPE "text/x-server-parsed-html"
1.239 +12 -22 apache-1.3/src/main/http_core.c
Index: http_core.c
===================================================================
RCS file: /home/cvs/apache-1.3/src/main/http_core.c,v
retrieving revision 1.238
retrieving revision 1.239
diff -u -r1.238 -r1.239
--- http_core.c 1998/10/30 03:08:55 1.238
+++ http_core.c 1998/11/08 09:51:10 1.239
@@ -1068,28 +1068,18 @@
while (limited_methods[0]) {
char *method = ap_getword_conf(cmd->pool, &limited_methods);
- if (!strcmp(method, "GET")) {
- limited |= (1 << M_GET);
- }
- else if (!strcmp(method, "PUT")) {
- limited |= (1 << M_PUT);
- }
- else if (!strcmp(method, "POST")) {
- limited |= (1 << M_POST);
- }
- else if (!strcmp(method, "DELETE")) {
- limited |= (1 << M_DELETE);
- }
- else if (!strcmp(method, "CONNECT")) {
- limited |= (1 << M_CONNECT);
- }
- else if (!strcmp(method, "OPTIONS")) {
- limited |= (1 << M_OPTIONS);
- }
- else {
- return ap_pstrcat(cmd->pool, "unknown method \"",
- method, "\" in <Limit>", NULL);
- }
+ int methnum = ap_method_number_of(method);
+
+ if (methnum == M_TRACE) {
+ return "TRACE cannot be controlled by <Limit>";
+ }
+ else if (methnum == M_INVALID) {
+ return ap_pstrcat(cmd->pool, "unknown method \"",
+ method, "\" in <Limit>", NULL);
+ }
+ else {
+ limited |= (1 << methnum);
+ }
}
cmd->limited = limited;
1.248 +85 -25 apache-1.3/src/main/http_protocol.c
Index: http_protocol.c
===================================================================
RCS file: /home/cvs/apache-1.3/src/main/http_protocol.c,v
retrieving revision 1.247
retrieving revision 1.248
diff -u -r1.247 -r1.248
--- http_protocol.c 1998/10/30 22:41:24 1.247
+++ http_protocol.c 1998/11/08 09:51:11 1.248
@@ -517,6 +517,72 @@
ap_gm_timestr_822(r->pool, mod_time));
}
+/* Get the method number associated with the given string, assumed to
+ * contain an HTTP method. Returns M_INVALID if not recognized.
+ *
+ * This is the first step toward placing method names in a configurable
+ * list. Hopefully it (and other routines) can eventually be moved to
+ * something like a mod_http_methods.c, complete with config stuff.
+ */
+API_EXPORT(int) ap_method_number_of(const char *method)
+{
+ switch (*method) {
+ case 'H':
+ if (strcmp(method, "HEAD") == 0)
+ return M_GET; /* see header_only in request_rec */
+ break;
+ case 'G':
+ if (strcmp(method, "GET") == 0)
+ return M_GET;
+ break;
+ case 'P':
+ if (strcmp(method, "POST") == 0)
+ return M_POST;
+ if (strcmp(method, "PUT") == 0)
+ return M_PUT;
+ if (strcmp(method, "PATCH") == 0)
+ return M_PATCH;
+ if (strcmp(method, "PROPFIND") == 0)
+ return M_PROPFIND;
+ if (strcmp(method, "PROPPATCH") == 0)
+ return M_PROPPATCH;
+ break;
+ case 'D':
+ if (strcmp(method, "DELETE") == 0)
+ return M_DELETE;
+ break;
+ case 'C':
+ if (strcmp(method, "CONNECT") == 0)
+ return M_CONNECT;
+ if (strcmp(method, "COPY") == 0)
+ return M_COPY;
+ break;
+ case 'M':
+ if (strcmp(method, "MKCOL") == 0)
+ return M_MKCOL;
+ if (strcmp(method, "MOVE") == 0)
+ return M_MOVE;
+ break;
+ case 'O':
+ if (strcmp(method, "OPTIONS") == 0)
+ return M_OPTIONS;
+ break;
+ case 'T':
+ if (strcmp(method, "TRACE") == 0)
+ return M_TRACE;
+ break;
+ case 'L':
+ if (strcmp(method, "LOCK") == 0)
+ return M_LOCK;
+ break;
+ case 'U':
+ if (strcmp(method, "UNLOCK") == 0)
+ return M_UNLOCK;
+ break;
+ }
+ return M_INVALID;
+}
+
/* Get a line of protocol input, including any continuation lines
* caused by MIME folding (or broken clients) if fold != 0, and place it
* in the buffer s, of size n bytes, without the ending newline.
@@ -678,26 +744,11 @@
uri = ap_getword_white(r->pool, &ll);
/* Provide quick information about the request method as soon as known */
- if (!strcmp(r->method, "HEAD")) {
+
+ r->method_number = ap_method_number_of(r->method);
+ if (r->method_number == M_GET && r->method[0] == 'H') {
r->header_only = 1;
- r->method_number = M_GET;
}
- else if (!strcmp(r->method, "GET"))
- r->method_number = M_GET;
- else if (!strcmp(r->method, "POST"))
- r->method_number = M_POST;
- else if (!strcmp(r->method, "PUT"))
- r->method_number = M_PUT;
- else if (!strcmp(r->method, "DELETE"))
- r->method_number = M_DELETE;
- else if (!strcmp(r->method, "CONNECT"))
- r->method_number = M_CONNECT;
- else if (!strcmp(r->method, "OPTIONS"))
- r->method_number = M_OPTIONS;
- else if (!strcmp(r->method, "TRACE"))
- r->method_number = M_TRACE;
- else
- r->method_number = M_INVALID; /* Will eventually croak. */
ap_parse_uri(r, uri);
@@ -1237,13 +1288,22 @@
static char *make_allow(request_rec *r)
{
return 2 + ap_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_OPTIONS)) ? ", OPTIONS" : "",
- ", TRACE",
- NULL);
+ (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" : "",
+ ", TRACE",
+ NULL);
}
API_EXPORT(int) ap_send_http_trace(request_rec *r)
1.29 +44 -47 apache-1.3/src/modules/standard/mod_actions.c
Index: mod_actions.c
===================================================================
RCS file: /home/cvs/apache-1.3/src/modules/standard/mod_actions.c,v
retrieving revision 1.28
retrieving revision 1.29
diff -u -r1.28 -r1.29
--- mod_actions.c 1998/08/06 17:30:53 1.28
+++ mod_actions.c 1998/11/08 09:51:12 1.29
@@ -56,7 +56,7 @@
*/
/*
- * mod_actions.c: executes scripts based on MIME type
+ * mod_actions.c: executes scripts based on MIME type or HTTP method
*
* by Alexei Kosut; based on mod_cgi.c, mod_mime.c and mod_includes.c,
* adapted by rst from original NCSA code by Rob McCool
@@ -69,6 +69,12 @@
* requested. It sends the URL and file path of the requested document using
* the standard CGI PATH_INFO and PATH_TRANSLATED environment variables.
*
+ * Script PUT /cgi-bin/script
+ *
+ * will activate /cgi-bin/script when a request is received with the
+ * HTTP method "PUT". The available method names are defined in httpd.h.
+ * If the method is GET, the script will only be activated if the requested
+ * URI includes query information (stuff after a ?-mark).
*/
#include "httpd.h"
@@ -81,11 +87,8 @@
#include "util_script.h"
typedef struct {
- table *action_types; /* Added with Action... */
- char *get; /* Added with Script GET */
- char *post; /* Added with Script POST */
- char *put; /* Added with Script PUT */
- char *delete; /* Added with Script DELETE */
+ table *action_types; /* Added with Action... */
+ char *scripted[METHODS]; /* Added with Script... */
} action_dir_config;
module action_module;
@@ -96,10 +99,7 @@
(action_dir_config *) ap_palloc(p, sizeof(action_dir_config));
new->action_types = ap_make_table(p, 4);
- new->get = NULL;
- new->post = NULL;
- new->put = NULL;
- new->delete = NULL;
+ memset(new->scripted, 0, sizeof(new->scripted));
return new;
}
@@ -108,17 +108,17 @@
{
action_dir_config *base = (action_dir_config *) basev;
action_dir_config *add = (action_dir_config *) addv;
- action_dir_config *new =
- (action_dir_config *) ap_palloc(p, sizeof(action_dir_config));
+ action_dir_config *new = (action_dir_config *) ap_palloc(p,
+ sizeof(action_dir_config));
+ int i;
new->action_types = ap_overlay_tables(p, add->action_types,
base->action_types);
- new->get = add->get ? add->get : base->get;
- new->post = add->post ? add->post : base->post;
- new->put = add->put ? add->put : base->put;
- new->delete = add->delete ? add->delete : base->delete;
-
+ for (i = 0; i < METHODS; ++i) {
+ new->scripted[i] = add->scripted[i] ? add->scripted[i]
+ : base->scripted[i];
+ }
return new;
}
@@ -129,19 +129,18 @@
return NULL;
}
-static const char *set_script(cmd_parms *cmd, action_dir_config * m, char
*method,
- char *script)
+static const char *set_script(cmd_parms *cmd, action_dir_config * m,
+ char *method, char *script)
{
- if (!strcmp(method, "GET"))
- m->get = script;
- else if (!strcmp(method, "POST"))
- m->post = script;
- else if (!strcmp(method, "PUT"))
- m->put = script;
- else if (!strcmp(method, "DELETE"))
- m->delete = script;
+ int methnum;
+
+ methnum = ap_method_number_of(method);
+ if (methnum == M_TRACE)
+ return "TRACE not allowed for Script";
+ else if (methnum == M_INVALID)
+ return "Unknown method type for Script";
else
- return "Unknown method type for Script";
+ m->scripted[methnum] = script;
return NULL;
}
@@ -157,30 +156,28 @@
static int action_handler(request_rec *r)
{
- action_dir_config *conf =
- (action_dir_config *) ap_get_module_config(r->per_dir_config,
&action_module);
+ action_dir_config *conf = (action_dir_config *)
+ ap_get_module_config(r->per_dir_config, &action_module);
const char *t, *action = r->handler ? r->handler : r->content_type;
- const char *script = NULL;
+ const char *script;
+ int i;
/* Set allowed stuff */
- if (conf->get)
- r->allowed |= (1 << M_GET);
- if (conf->post)
- r->allowed |= (1 << M_POST);
- if (conf->put)
- r->allowed |= (1 << M_PUT);
- if (conf->delete)
- r->allowed |= (1 << M_DELETE);
+ for (i = 0; i < METHODS; ++i) {
+ if (conf->scripted[i])
+ r->allowed |= (1 << i);
+ }
/* First, check for the method-handling scripts */
- if ((r->method_number == M_GET) && r->args && conf->get)
- script = conf->get;
- else if ((r->method_number == M_POST) && conf->post)
- script = conf->post;
- else if ((r->method_number == M_PUT) && conf->put)
- script = conf->put;
- else if ((r->method_number == M_DELETE) && conf->delete)
- script = conf->delete;
+ if (r->method_number == M_GET) {
+ if (r->args)
+ script = conf->scripted[M_GET];
+ else
+ script = NULL;
+ }
+ else {
+ script = conf->scripted[r->method_number];
+ }
/* Check for looping, which can happen if the CGI script isn't */
if (script && r->prev && r->prev->prev)