mirror of
https://github.com/apache/httpd.git
synced 2025-08-08 15:02:10 +03:00
Add support for arbitrary extension methods for the Allow
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
This commit is contained in:
@@ -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_some_auth_required(request_rec *r);
|
||||||
API_EXPORT(int) ap_is_initial_req(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);
|
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
|
#ifdef CORE_PRIVATE
|
||||||
/* Function called by main.c to handle first-level request */
|
/* Function called by main.c to handle first-level request */
|
||||||
void ap_process_request(request_rec *);
|
void ap_process_request(request_rec *);
|
||||||
|
@@ -666,6 +666,7 @@ struct request_rec {
|
|||||||
* handler can't be installed by mod_actions. </PRE>
|
* handler can't be installed by mod_actions. </PRE>
|
||||||
*/
|
*/
|
||||||
int allowed; /* Allowed methods - for 405, OPTIONS, etc */
|
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 */
|
/** byte count in stream is for body */
|
||||||
int sent_bodyct;
|
int sent_bodyct;
|
||||||
|
@@ -1572,23 +1572,41 @@ static void terminate_header(request_rec *r)
|
|||||||
*/
|
*/
|
||||||
static char *make_allow(request_rec *r)
|
static char *make_allow(request_rec *r)
|
||||||
{
|
{
|
||||||
return 2 + apr_pstrcat(r->pool,
|
char *list;
|
||||||
(r->allowed & (1 << M_GET)) ? ", GET, HEAD" : "",
|
|
||||||
(r->allowed & (1 << M_POST)) ? ", POST" : "",
|
list = apr_pstrcat(r->pool,
|
||||||
(r->allowed & (1 << M_PUT)) ? ", PUT" : "",
|
(r->allowed & (1 << M_GET)) ? ", GET, HEAD" : "",
|
||||||
(r->allowed & (1 << M_DELETE)) ? ", DELETE" : "",
|
(r->allowed & (1 << M_POST)) ? ", POST" : "",
|
||||||
(r->allowed & (1 << M_CONNECT)) ? ", CONNECT" : "",
|
(r->allowed & (1 << M_PUT)) ? ", PUT" : "",
|
||||||
(r->allowed & (1 << M_OPTIONS)) ? ", OPTIONS" : "",
|
(r->allowed & (1 << M_DELETE)) ? ", DELETE" : "",
|
||||||
(r->allowed & (1 << M_PATCH)) ? ", PATCH" : "",
|
(r->allowed & (1 << M_CONNECT)) ? ", CONNECT" : "",
|
||||||
(r->allowed & (1 << M_PROPFIND)) ? ", PROPFIND" : "",
|
(r->allowed & (1 << M_OPTIONS)) ? ", OPTIONS" : "",
|
||||||
(r->allowed & (1 << M_PROPPATCH)) ? ", PROPPATCH" : "",
|
(r->allowed & (1 << M_PATCH)) ? ", PATCH" : "",
|
||||||
(r->allowed & (1 << M_MKCOL)) ? ", MKCOL" : "",
|
(r->allowed & (1 << M_PROPFIND)) ? ", PROPFIND" : "",
|
||||||
(r->allowed & (1 << M_COPY)) ? ", COPY" : "",
|
(r->allowed & (1 << M_PROPPATCH)) ? ", PROPPATCH" : "",
|
||||||
(r->allowed & (1 << M_MOVE)) ? ", MOVE" : "",
|
(r->allowed & (1 << M_MKCOL)) ? ", MKCOL" : "",
|
||||||
(r->allowed & (1 << M_LOCK)) ? ", LOCK" : "",
|
(r->allowed & (1 << M_COPY)) ? ", COPY" : "",
|
||||||
(r->allowed & (1 << M_UNLOCK)) ? ", UNLOCK" : "",
|
(r->allowed & (1 << M_MOVE)) ? ", MOVE" : "",
|
||||||
", TRACE",
|
(r->allowed & (1 << M_LOCK)) ? ", LOCK" : "",
|
||||||
NULL);
|
(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)
|
API_EXPORT(int) ap_send_http_trace(request_rec *r)
|
||||||
|
@@ -79,6 +79,9 @@
|
|||||||
#include "apr_strings.h"
|
#include "apr_strings.h"
|
||||||
#include "apr_file_io.h"
|
#include "apr_file_io.h"
|
||||||
#include "apr_fnmatch.h"
|
#include "apr_fnmatch.h"
|
||||||
|
#ifdef APR_HAVE_STDARG_H
|
||||||
|
#include <stdarg.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
AP_HOOK_STRUCT(
|
AP_HOOK_STRUCT(
|
||||||
AP_HOOK_LINK(translate_name)
|
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;
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user