]> granicus.if.org Git - apache/commitdiff
Add support for arbitrary extension methods for the Allow
authorKen Coar <coar@apache.org>
Thu, 10 Aug 2000 11:22:57 +0000 (11:22 +0000)
committerKen Coar <coar@apache.org>
Thu, 10 Aug 2000 11:22:57 +0000 (11:22 +0000)
response header field, and an API routine for modifying the
allowed list in a unified manner for both known and extension
methods.

git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@86043 13f79535-47bb-0310-9956-ffa450edef68

include/http_request.h
include/httpd.h
modules/http/http_protocol.c
modules/http/http_request.c

index 7d5bed28f9a8016bf79c02941f5a7d16e7e3de7e..803eb15c95b17aee29036c7b6b6d9823398d7625 100644 (file)
@@ -106,7 +106,23 @@ API_EXPORT(void) ap_internal_redirect_handler(const char *new_uri, request_rec *
 API_EXPORT(int) ap_some_auth_required(request_rec *r);
 API_EXPORT(int) ap_is_initial_req(request_rec *r);
 API_EXPORT(void) ap_update_mtime(request_rec *r, apr_time_t dependency_mtime);
-
+/**
+ * Add one or more methods to the list permitted to access the resource.
+ * Usually executed by the content handler before the response header is
+ * sent, but sometimes invoked at an earlier phase if a module knows it
+ * can set the list authoritatively.  Note that the methods are ADDED
+ * to any already permitted unless the reset flag is non-zero.  The
+ * list is used to generate the Allow response header field when it
+ * is needed.
+ * @param   r     The pointer to the request identifying the resource.
+ * @param   reset Boolean flag indicating whether this list should
+ *                completely replace any current settings.
+ * @param   ...   A NULL-terminated list of strings, each identifying a
+ *                method name to add.
+ * @return  None.
+ * @deffunc void ap_allow_methods(request_rec *r, int reset, ...)
+ */
+API_EXPORT(void) ap_allow_methods(request_rec *r, int reset, ...);
 #ifdef CORE_PRIVATE
 /* Function called by main.c to handle first-level request */
 void ap_process_request(request_rec *);
index 26d9c227a2d884a5e459e131090c27453605a5ab..b7ca03bb1dc884502012e3037bb201a9fc909d17 100644 (file)
@@ -666,6 +666,7 @@ struct request_rec {
      *  handler can't be installed by mod_actions. </PRE>
      */
     int allowed;               /* Allowed methods - for 405, OPTIONS, etc */
+    apr_array_header_t *allowed_xmethods; /* Array of extension methods */
 
     /** byte count in stream is for body */
     int sent_bodyct;
index 0cfb497b7eca0d11f48c9e00ad388acab959b735..8a687aa0b7ceff13d6461fe0327084da2741a27b 100644 (file)
@@ -1572,23 +1572,41 @@ static void terminate_header(request_rec *r)
  */
 static char *make_allow(request_rec *r)
 {
-    return 2 + 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"    : "",
-                   ", TRACE",
-                   NULL);
+    char *list;
+
+    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"    : "",
+                      ", TRACE",
+                      NULL);
+    if ((r->allowed & (1 << M_INVALID)) && (r->allowed_xmethods->nelts)) {
+       int i;
+       char **xmethod = (char **) r->allowed_xmethods->elts;
+
+       /*
+        * Append all of the elements of r->allowed_xmethods
+        */
+       for (i = 0; i < r->allowed_xmethods->nelts; ++i) {
+           list = ap_pstrcat(r->pool, list, ", ", xmethod[i], NULL);
+       }
+    }
+    /*
+     * Space past the leading ", ".  Wastes two bytes, but that's better
+     * than futzing around to find the actual length.
+     */
+    return list + 2;
 }
 
 API_EXPORT(int) ap_send_http_trace(request_rec *r)
index 2049386e2d2304ad09fc068dd25fa77072e5cd16..6fc8be11bdcc5bd8fd77b814379bfd37a7238d76 100644 (file)
@@ -79,6 +79,9 @@
 #include "apr_strings.h"
 #include "apr_file_io.h"
 #include "apr_fnmatch.h"
+#ifdef APR_HAVE_STDARG_H
+#include <stdarg.h>
+#endif
 
 AP_HOOK_STRUCT(
            AP_HOOK_LINK(translate_name)
@@ -1425,3 +1428,46 @@ API_EXPORT(void) ap_update_mtime(request_rec *r, apr_time_t dependency_mtime)
        r->mtime = dependency_mtime;
     }
 }
+
+API_EXPORT(void) ap_allow_methods(request_rec *r, int reset, ...) {
+    int mnum;
+    const char *method;
+    const char **xmethod;
+    va_list methods;
+
+    /*
+     * Get rid of any current settings if requested; not just the
+     * well-known methods but any extensions as well.
+     */
+    if (reset) {
+       r->allowed = 0;
+       if (r->allowed_xmethods != NULL) {
+           r->allowed_xmethods->nelts = 0;
+       }
+    }
+
+    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) {
+           if (r->allowed_xmethods == NULL) {
+               r->allowed_xmethods = apr_make_array(r->pool, 2,
+                                                    sizeof(char *));
+           }
+           xmethod = (const char **) apr_push_array(r->allowed_xmethods);
+           *xmethod = method;
+       }
+    }
+}