This version of path support COPY resources to remote servers with
respect to Overwrite header.
TODO: support MOVE
TODO: support collections
----------------------------------------------------
Tysiące pomysłów na urządzanie domu, mieszkania,
ogrodu w jednym miejscu!
Zobacz jak mógłbyś zamieszkać.
Kliknij: http://klik.wp.pl/?adr=www.dom.wp.pl&sid=419
diff -urbB httpd-2.2.9-orig/modules/dav/fs/repos.c httpd-2.2.9/modules/dav/fs/repos.c
--- httpd-2.2.9-orig/modules/dav/fs/repos.c 2008-01-02 10:41:46.000000000 +0100
+++ httpd-2.2.9/modules/dav/fs/repos.c 2008-07-22 05:24:07.000000000 +0200
@@ -37,7 +37,7 @@
/* to assist in debugging mod_dav's GET handling */
-#define DEBUG_GET_HANDLER 0
+#define DEBUG_GET_HANDLER 1
#define DAV_FS_COPY_BLOCKSIZE 16384 /* copy 16k at a time */
diff -urbB httpd-2.2.9-orig/modules/dav/main/mod_dav.c httpd-2.2.9/modules/dav/main/mod_dav.c
--- httpd-2.2.9-orig/modules/dav/main/mod_dav.c 2008-05-27 17:57:23.000000000 +0200
+++ httpd-2.2.9/modules/dav/main/mod_dav.c 2008-07-22 05:32:44.000000000 +0200
@@ -55,6 +55,7 @@
#include "http_main.h"
#include "http_protocol.h"
#include "http_request.h"
+#include "util_ebcdic.h"
#include "util_script.h"
#include "mod_dav.h"
@@ -2550,6 +2551,547 @@
return dav_created(r, NULL, "Collection", 0);
}
+DAV_DECLARE(dav_error *) dav_remote_copymove_create_socket(apr_pool_t *p, apr_sockaddr_t *addr, apr_socket_t **newsock)
+{
+ apr_status_t rv;
+
+ while (addr) {
+ if ((rv = apr_socket_create(newsock, addr->family,
+ SOCK_STREAM, 0, p)) != APR_SUCCESS) {
+ /*
+ * this could be an IPv6 address from the DNS but the
+ * local machine won't give us an IPv6 socket; hopefully the
+ * DNS returned an additional address to try
+ */
+ addr = addr->next;
+ continue;
+ }
+
+ rv = apr_socket_connect(*newsock, addr);
+
+ /* if an error occurred, loop round and try again */
+ if (rv != APR_SUCCESS) {
+ apr_socket_close(*newsock);
+ addr = addr->next;
+ continue;
+ }
+
+ return 0;
+ }
+
+ // TODO: good error code?
+ return dav_new_error(p, HTTP_INTERNAL_SERVER_ERROR, 0, "Socket creating failed");
+}
+
+DAV_DECLARE(dav_error *) dav_remote_create_connection(apr_pool_t *p, apr_uri_t *uri, server_rec *s, conn_rec **conn)
+{
+ apr_status_t rv;
+ apr_sockaddr_t *src_addr;
+ apr_socket_t *socket;
+ dav_error *err;
+
+ rv = apr_sockaddr_info_get(&src_addr, uri->hostname, APR_UNSPEC, uri->port, 0, p);
+ if (APR_SUCCESS != rv) {
+ return dav_new_error(p, HTTP_BAD_REQUEST, 0, apr_pstrcat(p, "DNS lookup failure for: ", uri->hostname, NULL));
+ }
+
+ if (NULL != (err = dav_remote_copymove_create_socket(p, src_addr, &socket))) {
+ return err;
+ }
+
+ *conn = (conn_rec *)ap_run_create_connection(p, s, socket, 0, NULL, apr_bucket_alloc_create(p));
+
+ if (!*conn) {
+ // will it have memory to create error message? i guess not, let the caller check!
+ return 0;
+ }
+
+ /* set up the connection filters */
+ rv = ap_run_pre_connection(*conn, socket);
+ if (rv != OK && rv != DONE) {
+ (*conn)->aborted = 1;
+ return dav_new_error(p, HTTP_INTERNAL_SERVER_ERROR, 0, "pre_connection setup failed");
+ }
+
+ return 0;
+}
+
+DAV_DECLARE(dav_error *) dav_remote_close_connection(request_rec *r)
+{
+ // TODO: find a better way to do it
+ r->connection = 0;
+}
+
+DAV_DECLARE(request_rec *) dav_remote_make_fake_request(request_rec *r)
+{
+ request_rec *rp = apr_pcalloc(r->pool, sizeof(*r));
+
+ rp->pool = r->pool;
+ rp->status = HTTP_OK;
+
+ rp->headers_in = apr_table_make(r->pool, 12);
+ rp->subprocess_env = apr_table_make(r->pool, 12);
+ rp->headers_out = apr_table_make(r->pool, 12);
+ rp->err_headers_out = apr_table_make(r->pool, 5);
+ rp->notes = apr_table_make(r->pool, 5);
+
+ rp->server = r->server;
+ rp->proxyreq = r->proxyreq;
+ rp->request_time = r->request_time;
+
+ rp->connection = 0;
+
+ rp->request_config = ap_create_request_config(r->pool);
+ rp->per_dir_config = r->per_dir_config; // hope it will not crash
+}
+
+DAV_DECLARE(dav_error *) dav_remote_set_connection(request_rec *r, apr_uri_t *resource_uri)
+{
+ dav_error *err;
+ conn_rec *conn;
+
+ if (r->connection) {
+ return 0;
+ }
+ if (NULL != (err = dav_remote_create_connection(r->pool, resource_uri, r->server, &conn))) {
+ return err;
+ }
+
+ r->connection = conn;
+ r->output_filters = conn->output_filters;
+ r->input_filters = conn->input_filters;
+ r->proto_output_filters = conn->output_filters;
+ r->proto_input_filters = conn->input_filters;
+
+ return 0;
+}
+
+DAV_DECLARE(dav_error *) dav_remote_send_resource_content(request_rec *r, dav_resource *resource)
+{
+ dav_error *err;
+ apr_bucket_brigade *request_brigade;
+ apr_bucket *e;
+ apr_status_t rv;
+
+ /* okay... time to deliver the content */
+ if ((err = (*resource->hooks->deliver)(resource,
+ r->output_filters)) != NULL) {
+ return dav_push_error(r->pool, err->status, 0,
+ "Unable to deliver content.",
+ err);
+ }
+
+ request_brigade = apr_brigade_create(r->pool, r->connection->bucket_alloc);
+
+ e = apr_bucket_flush_create(r->connection->bucket_alloc);
+ APR_BRIGADE_INSERT_TAIL(request_brigade, e);
+
+ rv = ap_pass_brigade(r->output_filters, request_brigade);
+
+ return NULL;
+}
+
+struct dav_remote_send_headers_wrapper {
+ apr_bucket_alloc_t *bucket_alloc;
+ apr_bucket_brigade *request_brigade;
+ apr_pool_t *p;
+};
+
+int dav_remote_send_headers(void *rec, const char *key, const char *value)
+{
+ struct dav_remote_send_headers_wrapper *wrapper = (struct dav_remote_send_headers_wrapper *)rec;
+
+ apr_bucket_brigade *request_brigade = wrapper->request_brigade;
+ apr_bucket *e;
+ char *buf;
+
+ buf = apr_pstrcat(wrapper->p, key, ": ", value, CRLF, NULL);
+ e = apr_bucket_pool_create(buf, strlen(buf), wrapper->p, wrapper->bucket_alloc);
+ ap_xlate_proto_to_ascii(buf, strlen(buf));
+ APR_BRIGADE_INSERT_TAIL(request_brigade, e);
+}
+
+DAV_DECLARE(dav_error *) dav_remote_read_status_line(request_rec *r)
+{
+ apr_bucket_brigade *response_brigade;
+
+ char buff[HUGE_STRING_LEN];
+ char *buff_p = buff;
+ char keepchar;
+ apr_size_t len;
+
+ response_brigade = apr_brigade_create(r->pool, r->connection->bucket_alloc);
+ ap_rgetline(&buff_p, sizeof(buff), &len, r, 0, response_brigade);
+
+ if (!apr_date_checkmask(buff, "HTTP/#.# ###*")) {
+ return dav_new_error(r->pool, HTTP_BAD_GATEWAY, 0, "Invalid response status line");
+ }
+
+ int major, minor;
+
+ if (2 != sscanf(buff, "HTTP/%u.%u", &major, &minor)) {
+ major = 1;
+ minor = 1;
+ }
+ else if ((buff[5] != '1') || (len >= sizeof(buff) - 1)) {
+ return dav_new_error(r->pool, HTTP_BAD_GATEWAY, 0, "Invalid response status line");
+ }
+
+ keepchar = buff[12];
+ buff[12] = '\0';
+ r->status = atoi(&buff[9]);
+
+ if (keepchar != '\0') {
+ buff[12] = keepchar;
+ } else {
+ /* 2616 requires the space in Status-Line; the origin
+ * server may have sent one but ap_rgetline_core will
+ * have stripped it. */
+ buff[12] = ' ';
+ buff[13] = '\0';
+ }
+ r->status_line = apr_pstrdup(r->pool, &buff[9]);
+
+ return 0;
+}
+
+DAV_DECLARE(dav_error *) dav_remote_read_response_headers(request_rec *r)
+{
+ dav_error *err;
+ apr_bucket_brigade *response_brigade;
+ apr_size_t len;
+ apr_status_t rv;
+ char buff[HUGE_STRING_LEN];
+ char *buff_p = buff;
+ char *value, *end;
+
+ apr_table_clear(r->headers_in);
+
+ response_brigade = apr_brigade_create(r->pool, r->connection->bucket_alloc);
+ if (APR_SUCCESS != (rv = ap_rgetline(&buff_p, sizeof(buff), &len, r, 0, response_brigade))) {
+ return dav_new_error(r->pool, HTTP_BAD_GATEWAY, 0, "Error reading response header");
+ }
+
+ while (0 < len) {
+ if (!(value = strchr(buff, ':'))) {
+ if (APR_SUCCESS != (rv = ap_rgetline(&buff_p, sizeof(buff), &len, r, 0, response_brigade))) {
+ return dav_new_error(r->pool, HTTP_BAD_GATEWAY, 0, "Error reading response header");
+ }
+ }
+
+ *value = '\0';
+ ++value;
+ /* XXX: RFC2068 defines only SP and HT as whitespace, this test is
+ * wrong... and so are many others probably.
+ */
+ while (apr_isspace(*value))
+ ++value; /* Skip to start of value */
+
+ /* should strip trailing whitespace as well */
+ for (end = &value[strlen(value)-1]; end > value && apr_isspace(*end); --end)
+ *end = '\0';
+
+ apr_table_add(r->headers_in, buff, value);
+
+ if (APR_SUCCESS != (rv = ap_rgetline(&buff_p, sizeof(buff), &len, r, 0, response_brigade))) {
+ return dav_new_error(r->pool, HTTP_BAD_GATEWAY, 0, "Error reading response header");
+ }
+ }
+
+ return 0;
+}
+
+typedef dav_error * (* write_request_content_callback) (request_rec *, void *data);
+typedef dav_error * (* read_reponse_content_callback) (request_rec *, void *data);
+
+DAV_DECLARE(dav_error *) dav_remote_skip_response_content(request_rec *r, void *unused)
+{
+ apr_size_t content_length;
+ apr_size_t to_read;
+ apr_bucket_brigade *response_brigade;
+ apr_bucket *e;
+ int seen_eos;
+ const char *content_length_str;
+ apr_bucket_alloc_t *bucket_alloc = r->connection->bucket_alloc;
+ char buff[HUGE_STRING_LEN];
+ char *buff_p = buff;
+
+ if (NULL == apr_table_get(r->headers_in, "Keep-Alive")) { // we can close the connection now
+ dav_remote_close_connection(r);
+ return 0;
+ }
+
+ content_length_str = apr_table_get(r->headers_in, "Content-Length");
+ if (!content_length_str) {
+ return 0; // no content
+ }
+
+ content_length = atoi(content_length_str);
+ if (!content_length) {
+ return 0; // no content
+ }
+
+ if (content_length < 0) {
+ dav_remote_close_connection(r);
+ return dav_new_error(r->pool, HTTP_BAD_GATEWAY, 0, "Invalid Content-Length of response");
+ }
+
+ while (0 < content_length) {
+ response_brigade = apr_brigade_create(r->pool, bucket_alloc);
+
+ do {
+ apr_status_t rc;
+
+ rc = ap_get_brigade(r->input_filters, response_brigade, AP_MODE_READBYTES,
+ APR_BLOCK_READ, DAV_READ_BLOCKSIZE);
+
+ if (rc != APR_SUCCESS) {
+ return dav_new_error(r->pool, HTTP_INTERNAL_SERVER_ERROR, 0,
+ "Could not get next bucket brigade");
+ }
+
+ for (e = APR_BRIGADE_FIRST(response_brigade);
+ e != APR_BRIGADE_SENTINEL(response_brigade);
+ e = APR_BUCKET_NEXT(e))
+ {
+ const char *data;
+ apr_size_t len;
+
+ if (APR_BUCKET_IS_EOS(e)) {
+ seen_eos = 1;
+ break;
+ }
+
+ if (APR_BUCKET_IS_METADATA(e)) {
+ continue;
+ }
+
+ rc = apr_bucket_read(e, &data, &len, APR_BLOCK_READ);
+ content_length -= len;
+
+ if (rc != APR_SUCCESS) {
+ return dav_new_error(r->pool, HTTP_BAD_REQUEST, 0,
+ "An error occurred while reading "
+ "the request body.");
+ }
+ }
+
+ apr_brigade_cleanup(response_brigade);
+ } while (!seen_eos);
+
+
+
+ }
+
+ return 0;
+}
+
+DAV_DECLARE(dav_error *) dav_remote_method_request(request_rec *r, const char *method, apr_uri_t *resource_uri,
+ const char *resource_path, dav_resource *resource,
+ write_request_content_callback write_request_content, void *write_request_content_data,
+ read_reponse_content_callback read_response_content, void *read_response_content_data)
+{
+ apr_status_t rv;
+ dav_error *err;
+ apr_bucket_alloc_t *bucket_alloc = r->connection->bucket_alloc;
+ apr_bucket_brigade *request_brigade;
+ apr_bucket *e;
+ char *buf;
+
+ // as I see nobody in httpd check for NULL results of malloc/apr_palloc, so why I should?
+ request_brigade = apr_brigade_create(r->pool, bucket_alloc);
+
+ buf = apr_pstrcat(r->pool, method, " ", resource_uri->path, " HTTP/1.1", CRLF, NULL);
+ e = apr_bucket_pool_create(buf, strlen(buf), r->pool, bucket_alloc);
+ ap_xlate_proto_to_ascii(buf, strlen(buf));
+ APR_BRIGADE_INSERT_TAIL(request_brigade, e);
+
+ struct dav_remote_send_headers_wrapper wrapper;
+ wrapper.bucket_alloc = bucket_alloc;
+ wrapper.request_brigade = request_brigade;
+ wrapper.p = r->pool;
+
+ apr_table_do(dav_remote_send_headers, &wrapper, r->headers_out, 0);
+
+ buf = apr_pstrcat(r->pool, CRLF, NULL);
+ e = apr_bucket_pool_create(buf, strlen(buf), r->pool, bucket_alloc);
+ ap_xlate_proto_to_ascii(buf, strlen(buf));
+ APR_BRIGADE_INSERT_TAIL(request_brigade, e);
+
+ e = apr_bucket_flush_create(bucket_alloc);
+ APR_BRIGADE_INSERT_TAIL(request_brigade, e);
+
+ rv = ap_pass_brigade(r->output_filters, request_brigade);
+
+ if (NULL != write_request_content) {
+ write_request_content(r, write_request_content_data);
+ }
+
+ if (rv != APR_SUCCESS) {
+ return dav_new_error(r->pool, HTTP_INTERNAL_SERVER_ERROR, 0, "Sending request failed");
+ }
+
+ if (NULL != (err = dav_remote_read_status_line(r))) {
+ return dav_push_error(r->pool, err->status, 0, "read_status in dav_remote_method_request failed.", err);
+ }
+
+ if (NULL != (err = dav_remote_read_response_headers(r))) {
+ return dav_push_error(r->pool, err->status, 0, "read_response_headers in dav_remote_method_request failed.", err);
+ }
+
+ if (NULL == read_response_content) {
+ read_response_content = dav_remote_skip_response_content;
+ }
+
+ if (NULL != (err = read_response_content(r, read_response_content_data))) {
+ return dav_push_error(r->pool, err->status, 0, "read_reponse_content_callback in dav_remote_method_request failed.", err);
+ }
+
+ // MOVED PERMANENTLY - check with '/' at the end
+ if ((r->status == HTTP_MOVED_PERMANENTLY) && (resource_uri->path[strlen(resource_uri->path) - 1] != '/')) {
+ resource_path = apr_pstrcat(r->pool, resource_path, "/", NULL);
+ if (strcmp(resource_path, apr_table_get(r->headers_in, "Location")) != 0) {
+ return dav_new_error(r->pool, HTTP_INTERNAL_SERVER_ERROR, 0, "No idea what to do...");
+ }
+
+ resource_uri->path = apr_pstrcat(r->pool, resource_uri->path, "/", NULL);
+
+ return dav_remote_method_request(r, method, resource_uri, resource_path, resource, NULL, NULL, NULL, NULL);
+ }
+
+ return NULL;
+}
+
+DAV_DECLARE(dav_error *) dav_remote_resource_exists(request_rec *r, apr_uri_t *resource_uri, const char *resource_path, dav_resource *resource, int *exists)
+{
+ dav_error *err;
+ conn_rec *conn;
+
+ *exists = 0;
+
+ if (NULL != (err = dav_remote_set_connection(r, resource_uri))) {
+ return dav_push_error(r->pool, err->status, 0, "Unable to create connection in dav_remote_resource_exists.", err);
+ }
+
+ apr_table_clear(r->headers_out);
+ apr_table_add(r->headers_out, "Host", resource_uri->hostname);
+ apr_table_add(r->headers_out, "Content-Length", "0");
+ apr_table_add(r->headers_out, "Depth", "0");
+ apr_table_add(r->headers_out, "Connection", "Keep-Alive");
+
+ if (NULL != (err = dav_remote_method_request(r, "HEAD", resource_uri, resource_path, resource, NULL, NULL, NULL, NULL))) {
+ return dav_push_error(r->pool, err->status, 0, "HEAD in dav_remote_resource_exists failed.", err);
+ }
+
+ *exists = r->status != 404;
+ return 0;
+}
+
+DAV_DECLARE(dav_error *) dav_remote_resource_delete(request_rec *r, apr_uri_t *resource_uri, const char *resource_path, dav_resource *resource, int *deleted)
+{
+ dav_error *err;
+ conn_rec *conn;
+
+ if (NULL != (err = dav_remote_set_connection(r, resource_uri))) {
+ return dav_push_error(r->pool, err->status, 0, "Unable to create connection in dav_remote_resource_delete.", err);
+ }
+
+ apr_table_clear(r->headers_out);
+ apr_table_add(r->headers_out, "Host", resource_uri->hostname);
+ apr_table_add(r->headers_out, "Content-Length", "0");
+ apr_table_add(r->headers_out, "Connection", "Keep-Alive");
+
+ if (NULL != (err = dav_remote_method_request(r, "DELETE", resource_uri, resource_path, resource, NULL, NULL, NULL, NULL))) {
+ return dav_push_error(r->pool, err->status, 0, "DELETE in dav_remote_resource_delete failed.", err);
+ }
+
+ *deleted = r->status == 200 || r->status == 202 || r->status == 204 || r->status == 404;
+
+ return 0;
+}
+
+DAV_DECLARE(dav_error *) dav_remote_resource_put(request_rec *r, apr_uri_t *resource_uri, const char *resource_path, dav_resource *resource)
+{
+ dav_error *err;
+ conn_rec *conn;
+
+ if (NULL != (err = dav_remote_set_connection(r, resource_uri))) {
+ return dav_push_error(r->pool, err->status, 0, "Unable to create connection in dav_remote_resource_delete.", err);
+ }
+
+ apr_table_clear(r->headers_out);
+ apr_table_add(r->headers_out, "Host", resource_uri->hostname);
+ apr_table_add(r->headers_out, "Connection", "Keep-Alive");
+
+ if ((err = (*resource->hooks->set_headers)(r, resource)) != NULL) {
+ return dav_push_error(r->pool, err->status, 0,
+ "Unable to set up HTTP headers.",
+ err);
+ }
+
+ if (NULL != (err = dav_remote_method_request(r, "PUT", resource_uri, resource_path, resource,
+ dav_remote_send_resource_content, resource,
+ NULL, NULL))) {
+ return dav_push_error(r->pool, err->status, 0, "DELETE in dav_remote_resource_delete failed.", err);
+ }
+
+ if (r->status != 201 && r->status != 204) {
+ return dav_new_error(r->pool, r->status, 0, "Remote server does not accept resource");
+ }
+
+ return 0;
+}
+
+static int dav_remote_copymove(request_rec *r, dav_resource *resource, const char *dest, int is_move, int overwrite)
+{
+ dav_error *err;
+ apr_uri_t dest_uri;
+ conn_rec *conn;
+ request_rec *rp;
+ int exists;
+ int deleted;
+
+ if (APR_SUCCESS != apr_uri_parse(r->pool, dest, &dest_uri)) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
+ "Destination URI cannot be parsed.", NULL);
+ return HTTP_BAD_REQUEST;
+ }
+
+ if (!dest_uri.port) {
+ dest_uri.port = apr_uri_port_of_scheme(dest_uri.scheme);
+ }
+
+ // 1. create request
+ rp = dav_remote_make_fake_request(r);
+
+
+ if (!overwrite) {
+ // 2. check if exists
+ if (NULL != (err = dav_remote_resource_exists(rp, &dest_uri, dest, resource, &exists))) {
+ return dav_handle_err(r, err, NULL);
+ }
+
+ if (exists)
+ return HTTP_PRECONDITION_FAILED;
+ }
+ else {
+ // 2. delete old resource
+ if (NULL != (err = dav_remote_resource_delete(rp, &dest_uri, dest, resource, &deleted))) {
+ return dav_handle_err(r, err, NULL);
+ }
+
+ if (!deleted)
+ return HTTP_FORBIDDEN;
+ }
+
+ // 3. send content
+ if ((err = dav_remote_resource_put(rp, &dest_uri, dest, resource)) != NULL) {
+ return dav_handle_err(r, err, NULL);
+ }
+
+ return HTTP_NO_CONTENT;
+}
+
/* handle the COPY and MOVE methods */
static int dav_method_copymove(request_rec *r, int is_move)
{
@@ -2609,6 +3151,13 @@
return HTTP_BAD_REQUEST;
}
+ /* get and parse the overwrite header value */
+ if ((overwrite = dav_get_overwrite(r)) < 0) {
+ /* dav_get_overwrite() supplies additional information for the
+ * default message. */
+ return HTTP_BAD_REQUEST;
+ }
+
lookup = dav_lookup_uri(dest, r, 1 /* must_be_absolute */);
if (lookup.rnew == NULL) {
if (lookup.err.status == HTTP_BAD_REQUEST) {
@@ -2618,6 +3167,12 @@
return HTTP_BAD_REQUEST;
}
+ if (!is_move && lookup.err.status == HTTP_BAD_GATEWAY) {
+ err = dav_get_resource(r, 1 /* label_allowed */, 0 /* use_checked_in */,
+ &resource);
+ return dav_remote_copymove(r, resource, dest, is_move, overwrite);
+ }
+
/* ### this assumes that dav_lookup_uri() only generates a status
* ### that Apache can provide a status line for!! */
@@ -2650,20 +3206,11 @@
return dav_handle_err(r, err, NULL);
/* are the two resources handled by the same repository? */
- if (resource->hooks != resnew->hooks) {
+ if (!is_move && resource->hooks != resnew->hooks) {
+ err = dav_get_resource(r, 1 /* label_allowed */, 0 /* use_checked_in */,
+ &resource);
/* ### this message exposes some backend config, but screw it... */
- return dav_error_response(r, HTTP_BAD_GATEWAY,
- "Destination URI is handled by a "
- "different repository than the source URI. "
- "MOVE or COPY between repositories is "
- "not possible.");
- }
-
- /* get and parse the overwrite header value */
- if ((overwrite = dav_get_overwrite(r)) < 0) {
- /* dav_get_overwrite() supplies additional information for the
- * default message. */
- return HTTP_BAD_REQUEST;
+ return dav_remote_copymove(r, resource, dest, is_move, overwrite);
}
/* quick failure test: if dest exists and overwrite is false. */
diff -urbB httpd-2.2.9-orig/modules/dav/main/util.c httpd-2.2.9/modules/dav/main/util.c
--- httpd-2.2.9-orig/modules/dav/main/util.c 2008-01-05 10:45:07.000000000 +0100
+++ httpd-2.2.9/modules/dav/main/util.c 2008-07-17 19:19:19.000000000 +0200
@@ -216,10 +216,9 @@
request. the port must match our port.
*/
port = r->connection->local_addr->port;
+
if (strcasecmp(comp.scheme, scheme) != 0
-#ifdef APACHE_PORT_HANDLING_IS_BUSTED
|| comp.port != port
-#endif
) {
result.err.status = HTTP_BAD_GATEWAY;
result.err.desc = apr_psprintf(r->pool,