View | Details | Raw Unified | Return to bug 45449
Collapse All | Expand All

(-)httpd-2.2.9-orig/modules/dav/fs/repos.c (-1 / +1 lines)
Lines 37-43 Link Here
37
37
38
38
39
/* to assist in debugging mod_dav's GET handling */
39
/* to assist in debugging mod_dav's GET handling */
40
#define DEBUG_GET_HANDLER       0
40
#define DEBUG_GET_HANDLER       1
41
41
42
#define DAV_FS_COPY_BLOCKSIZE   16384   /* copy 16k at a time */
42
#define DAV_FS_COPY_BLOCKSIZE   16384   /* copy 16k at a time */
43
43
(-)httpd-2.2.9-orig/modules/dav/main/mod_dav.c (-18 / +930 lines)
Lines 55-60 Link Here
55
#include "http_main.h"
55
#include "http_main.h"
56
#include "http_protocol.h"
56
#include "http_protocol.h"
57
#include "http_request.h"
57
#include "http_request.h"
58
#include "util_ebcdic.h"
58
#include "util_script.h"
59
#include "util_script.h"
59
60
60
#include "mod_dav.h"
61
#include "mod_dav.h"
Lines 103-108 Link Here
103
};
104
};
104
static int dav_methods[DAV_M_LAST];
105
static int dav_methods[DAV_M_LAST];
105
106
107
typedef struct
108
{
109
	char *token;
110
	char *path;
111
} dav_remote_lock_token;
106
112
107
static int dav_init_handler(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp,
113
static int dav_init_handler(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp,
108
                             server_rec *s)
114
                             server_rec *s)
Lines 2550-2555 Link Here
2550
    return dav_created(r, NULL, "Collection", 0);
2556
    return dav_created(r, NULL, "Collection", 0);
2551
}
2557
}
2552
2558
2559
// copied from mod_proxy - maybe add to core or lib?
2560
DAV_DECLARE(dav_error *) dav_remote_copymove_create_socket(apr_pool_t *p, apr_sockaddr_t *addr, apr_socket_t **newsock)
2561
{
2562
	apr_status_t rv;
2563
2564
	while (addr) {
2565
        if ((rv = apr_socket_create(newsock, addr->family,
2566
                                    SOCK_STREAM, 0, p)) != APR_SUCCESS) {
2567
            /*
2568
             * this could be an IPv6 address from the DNS but the
2569
             * local machine won't give us an IPv6 socket; hopefully the
2570
             * DNS returned an additional address to try
2571
             */
2572
            addr = addr->next;
2573
            continue;
2574
        }
2575
2576
        rv = apr_socket_connect(*newsock, addr);
2577
2578
        /* if an error occurred, loop round and try again */
2579
        if (rv != APR_SUCCESS) {
2580
            apr_socket_close(*newsock);
2581
            addr = addr->next;
2582
            continue;
2583
        }
2584
2585
        return NULL;
2586
	}
2587
2588
	return dav_new_error(p, HTTP_INTERNAL_SERVER_ERROR, 0, "Socket creating failed");
2589
}
2590
2591
DAV_DECLARE(dav_error *) dav_remote_create_connection(apr_pool_t *p, apr_uri_t *uri, server_rec *s, conn_rec **conn)
2592
{
2593
	apr_status_t rv;
2594
	apr_sockaddr_t *src_addr;
2595
	apr_socket_t *socket;
2596
	dav_error *err;
2597
2598
	rv = apr_sockaddr_info_get(&src_addr, uri->hostname, APR_UNSPEC, uri->port, 0, p);
2599
    if (APR_SUCCESS != rv) {
2600
        return dav_new_error(p, HTTP_BAD_REQUEST, 0, apr_pstrcat(p, "DNS lookup failure for: ", uri->hostname, NULL));
2601
    }
2602
2603
	if (NULL != (err = dav_remote_copymove_create_socket(p, src_addr, &socket))) {
2604
		return err;
2605
	}
2606
2607
	*conn = (conn_rec *)ap_run_create_connection(p, s, socket, 0, NULL, apr_bucket_alloc_create(p));
2608
2609
	if (!*conn) {
2610
		// will it have memory to create error message? i guess not, let the caller check!
2611
		return 0;
2612
	}
2613
2614
    /* set up the connection filters */
2615
    rv = ap_run_pre_connection(*conn, socket);
2616
    if (rv != OK && rv != DONE) {
2617
        (*conn)->aborted = 1;
2618
        return dav_new_error(p, HTTP_INTERNAL_SERVER_ERROR, 0, "pre_connection setup failed");
2619
    }
2620
2621
	return 0;
2622
}
2623
2624
DAV_DECLARE(dav_error *) dav_remote_close_connection(request_rec *r)
2625
{
2626
	// TODO: find a better way to do it
2627
	r->connection = 0;
2628
}
2629
2630
DAV_DECLARE(request_rec *) dav_remote_make_fake_request(request_rec *r)
2631
{
2632
	request_rec *rp = apr_pcalloc(r->pool, sizeof(*r));
2633
2634
    rp->pool            = r->pool;
2635
    rp->status          = HTTP_OK;
2636
2637
    rp->headers_in      = apr_table_make(r->pool, 12);
2638
    rp->subprocess_env  = apr_table_make(r->pool, 12);
2639
    rp->headers_out     = apr_table_make(r->pool, 12);
2640
    rp->err_headers_out = apr_table_make(r->pool, 5);
2641
    rp->notes           = apr_table_make(r->pool, 5);
2642
2643
    rp->server = r->server;
2644
    rp->proxyreq = r->proxyreq;
2645
    rp->request_time = r->request_time;
2646
2647
    rp->connection = 0;
2648
2649
    // TODO: is it ok to do that?
2650
    rp->request_config = r->request_config;
2651
    rp->per_dir_config = r->per_dir_config;
2652
}
2653
2654
DAV_DECLARE(dav_error *) dav_remote_set_connection(request_rec *r, apr_uri_t *resource_uri)
2655
{
2656
	dav_error *err;
2657
	conn_rec *conn;
2658
2659
	if (r->connection && !r->connection->aborted && (r->connection->keepalive == AP_CONN_KEEPALIVE)) {
2660
		return 0;
2661
	}
2662
2663
	dav_remote_close_connection(r);
2664
2665
	if (NULL != (err = dav_remote_create_connection(r->pool, resource_uri, r->server, &conn))) {
2666
		return err;
2667
	}
2668
2669
	conn->keepalive = AP_CONN_KEEPALIVE;
2670
2671
	r->connection      = conn;
2672
	r->output_filters  = conn->output_filters;
2673
	r->input_filters   = conn->input_filters;
2674
	r->proto_output_filters  = conn->output_filters;
2675
	r->proto_input_filters   = conn->input_filters;
2676
2677
	return 0;
2678
}
2679
2680
DAV_DECLARE(dav_error *) dav_remote_send_resource_content(request_rec *r, const dav_resource *resource)
2681
{
2682
	dav_error *err;
2683
	apr_bucket_brigade *request_brigade;
2684
	apr_bucket *e;
2685
	apr_status_t rv;
2686
2687
    /* okay... time to deliver the content */
2688
    if ((err = (*resource->hooks->deliver)(resource,
2689
                                           r->output_filters)) != NULL) {
2690
        return dav_push_error(r->pool, err->status, 0,
2691
                             "Unable to deliver content.",
2692
                             err);
2693
    }
2694
2695
	request_brigade =  apr_brigade_create(r->pool, r->connection->bucket_alloc);
2696
2697
	e = apr_bucket_flush_create(r->connection->bucket_alloc);
2698
	APR_BRIGADE_INSERT_TAIL(request_brigade, e);
2699
2700
    if (APR_SUCCESS != (rv = ap_pass_brigade(r->output_filters, request_brigade)))
2701
    	return dav_new_error(r->pool, HTTP_INTERNAL_SERVER_ERROR, 0, "Sending content failed");
2702
    else
2703
    	return NULL;
2704
}
2705
2706
DAV_DECLARE(dav_error *) dav_remote_send_string(request_rec *r, const char *string)
2707
{
2708
	dav_error *err;
2709
	apr_bucket_brigade *request_brigade;
2710
	apr_bucket *e;
2711
	apr_status_t rv;
2712
2713
	request_brigade =  apr_brigade_create(r->pool, r->connection->bucket_alloc);
2714
2715
	e = apr_bucket_pool_create(string, strlen(string), r->pool, r->connection->bucket_alloc);
2716
	ap_xlate_proto_to_ascii(string, strlen(string));
2717
	APR_BRIGADE_INSERT_TAIL(request_brigade, e);
2718
2719
	e = apr_bucket_flush_create(r->connection->bucket_alloc);
2720
	APR_BRIGADE_INSERT_TAIL(request_brigade, e);
2721
2722
    if (APR_SUCCESS != (rv = ap_pass_brigade(r->output_filters, request_brigade)))
2723
    	return dav_new_error(r->pool, HTTP_INTERNAL_SERVER_ERROR, 0, "Sending content failed");
2724
    else
2725
    	return NULL;
2726
}
2727
2728
struct dav_remote_send_headers_wrapper {
2729
	apr_bucket_alloc_t *bucket_alloc;
2730
	apr_bucket_brigade *request_brigade;
2731
	apr_pool_t *p;
2732
};
2733
2734
int dav_remote_send_header(void *rec, const char *key, const char *value)
2735
{
2736
	struct dav_remote_send_headers_wrapper *wrapper = (struct dav_remote_send_headers_wrapper *)rec;
2737
2738
	apr_bucket_brigade *request_brigade = wrapper->request_brigade;
2739
	apr_bucket *e;
2740
	char *buf;
2741
2742
	buf = apr_pstrcat(wrapper->p, key, ": ", value, CRLF, NULL);
2743
	e = apr_bucket_pool_create(buf, strlen(buf), wrapper->p, wrapper->bucket_alloc);
2744
	ap_xlate_proto_to_ascii(buf, strlen(buf));
2745
	APR_BRIGADE_INSERT_TAIL(request_brigade, e);
2746
2747
	return 1;
2748
}
2749
2750
DAV_DECLARE(dav_error *) dav_remote_read_status_line(request_rec *r)
2751
{
2752
    apr_bucket_brigade *response_brigade;
2753
2754
    char buff[HUGE_STRING_LEN];
2755
	char *buff_p = buff;
2756
	char keepchar;
2757
	apr_size_t len;
2758
2759
    response_brigade = apr_brigade_create(r->pool, r->connection->bucket_alloc);
2760
    ap_rgetline(&buff_p, sizeof(buff), &len, r, 0, response_brigade);
2761
2762
    if (!apr_date_checkmask(buff, "HTTP/#.# ###*")) {
2763
    	return dav_new_error(r->pool, HTTP_BAD_GATEWAY, 0, "Invalid response status line");
2764
    }
2765
2766
    int major, minor;
2767
2768
    if (2 != sscanf(buff, "HTTP/%u.%u", &major, &minor)) {
2769
        major = 1;
2770
        minor = 1;
2771
    }
2772
    else if ((buff[5] != '1') || (len >= sizeof(buff) - 1)) {
2773
        return dav_new_error(r->pool, HTTP_BAD_GATEWAY, 0, "Invalid response status line");
2774
    }
2775
2776
    keepchar = buff[12];
2777
    buff[12] = '\0';
2778
    r->status = atoi(&buff[9]);
2779
2780
    if (keepchar != '\0') {
2781
     	buff[12] = keepchar;
2782
    } else {
2783
        /* 2616 requires the space in Status-Line; the origin
2784
         * server may have sent one but ap_rgetline_core will
2785
         * have stripped it. */
2786
    	buff[12] = ' ';
2787
        buff[13] = '\0';
2788
    }
2789
    r->status_line = apr_pstrdup(r->pool, &buff[9]);
2790
2791
    return NULL;
2792
}
2793
2794
DAV_DECLARE(dav_error *) dav_remote_read_response_headers(request_rec *r)
2795
{
2796
	dav_error *err;
2797
    apr_bucket_brigade *response_brigade;
2798
	apr_size_t len;
2799
	apr_status_t rv;
2800
    char buff[HUGE_STRING_LEN];
2801
	char *buff_p = buff;
2802
	char *value, *end;
2803
2804
	apr_table_clear(r->headers_in);
2805
2806
	response_brigade = apr_brigade_create(r->pool, r->connection->bucket_alloc);
2807
    if (APR_SUCCESS != (rv = ap_rgetline(&buff_p, sizeof(buff), &len, r, 0, response_brigade))) {
2808
    	return dav_new_error(r->pool, HTTP_BAD_GATEWAY, 0, "Error reading response header");
2809
    }
2810
2811
    while (0 < len) {
2812
    	if (!(value = strchr(buff, ':'))) {
2813
    	    if (APR_SUCCESS != (rv = ap_rgetline(&buff_p, sizeof(buff), &len, r, 0, response_brigade))) {
2814
    	    	return dav_new_error(r->pool, HTTP_BAD_GATEWAY, 0, "Error reading response header");
2815
    	    }
2816
    	}
2817
2818
        *value = '\0';
2819
        ++value;
2820
        /* XXX: RFC2068 defines only SP and HT as whitespace, this test is
2821
         * wrong... and so are many others probably.
2822
         */
2823
        while (apr_isspace(*value))
2824
            ++value;            /* Skip to start of value   */
2825
2826
        /* should strip trailing whitespace as well */
2827
        for (end = &value[strlen(value)-1]; end > value && apr_isspace(*end); --end)
2828
            *end = '\0';
2829
2830
        apr_table_add(r->headers_in, buff, value);
2831
2832
	    if (APR_SUCCESS != (rv = ap_rgetline(&buff_p, sizeof(buff), &len, r, 0, response_brigade))) {
2833
	    	return dav_new_error(r->pool, HTTP_BAD_GATEWAY, 0, "Error reading response header");
2834
	    }
2835
    }
2836
2837
    return NULL;
2838
}
2839
2840
typedef DAV_DECLARE(dav_error *) (* write_request_content_callback) (request_rec *, void *data);
2841
typedef DAV_DECLARE(dav_error *) (* read_reponse_content_callback) (request_rec *, void *data);
2842
2843
DAV_DECLARE(dav_error *) dav_remote_skip_response_content(request_rec *r, void *unused)
2844
{
2845
	if (APR_SUCCESS != ap_discard_request_body(r))
2846
		return dav_new_error(r->pool, HTTP_INTERNAL_SERVER_ERROR, 0, "Error during discarding response body");
2847
2848
	return NULL;
2849
}
2850
2851
DAV_DECLARE(dav_error *) dav_remote_method_request(request_rec *r, const char *method, apr_uri_t *resource_uri,
2852
		const char *resource_path, const dav_resource *resource,
2853
		write_request_content_callback write_request_content, void *write_request_content_data,
2854
		read_reponse_content_callback read_response_content, void *read_response_content_data)
2855
{
2856
    apr_status_t rv;
2857
    dav_error *err;
2858
    apr_bucket_alloc_t *bucket_alloc = r->connection->bucket_alloc;
2859
    apr_bucket_brigade *request_brigade;
2860
    apr_bucket *e;
2861
    ap_filter_t *http_in_filter;
2862
	char *buf;
2863
2864
	// as I see nobody in httpd check for NULL results of malloc/apr_palloc, so why I should?
2865
    request_brigade = apr_brigade_create(r->pool, bucket_alloc);
2866
2867
    // request line
2868
	buf = apr_pstrcat(r->pool, method, " ", resource_uri->path, " HTTP/1.1", CRLF, NULL);
2869
	e = apr_bucket_pool_create(buf, strlen(buf), r->pool, bucket_alloc);
2870
	ap_xlate_proto_to_ascii(buf, strlen(buf));
2871
	APR_BRIGADE_INSERT_TAIL(request_brigade, e);
2872
2873
	// headers
2874
	struct dav_remote_send_headers_wrapper wrapper;
2875
	wrapper.bucket_alloc = bucket_alloc;
2876
	wrapper.request_brigade = request_brigade;
2877
	wrapper.p = r->pool;
2878
2879
	apr_table_do(dav_remote_send_header, &wrapper, r->headers_out, NULL);
2880
2881
	// empty line after headers
2882
	buf = apr_pstrcat(r->pool, CRLF, NULL);
2883
	e = apr_bucket_pool_create(buf, strlen(buf), r->pool, bucket_alloc);
2884
	ap_xlate_proto_to_ascii(buf, strlen(buf));
2885
	APR_BRIGADE_INSERT_TAIL(request_brigade, e);
2886
2887
	e = apr_bucket_flush_create(bucket_alloc);
2888
	APR_BRIGADE_INSERT_TAIL(request_brigade, e);
2889
2890
	// send it now
2891
    rv = ap_pass_brigade(r->output_filters, request_brigade);
2892
2893
	if (rv != APR_SUCCESS) {
2894
		return dav_new_error(r->pool, HTTP_INTERNAL_SERVER_ERROR, 0, "Sending request failed");
2895
	}
2896
2897
    // for PUT requests
2898
    if (NULL != write_request_content) {
2899
    	if (NULL != (err = write_request_content(r, write_request_content_data))) {
2900
    		return dav_push_error(r->pool, err->status, 0,
2901
    				apr_pstrcat(r->pool, "Could not write request for ", method, " for ", resource_path, NULL), err);
2902
    	}
2903
    }
2904
2905
	if (NULL != (err = dav_remote_read_status_line(r))) {
2906
		return dav_push_error(r->pool, err->status, 0,
2907
				apr_pstrcat(r->pool, "Could not read status for ", method, " for ", resource_path, NULL), err);
2908
	}
2909
2910
	if (NULL != (err = dav_remote_read_response_headers(r))) {
2911
		return dav_push_error(r->pool, err->status, 0,
2912
				apr_pstrcat(r->pool, "Could not read response headers for ", method, " for ", resource_path, NULL), err);
2913
	}
2914
2915
	http_in_filter = ap_add_input_filter("HTTP_IN", NULL, r, r->connection);
2916
2917
	if (NULL == read_response_content) {
2918
		read_response_content = dav_remote_skip_response_content;
2919
	}
2920
2921
	if (NULL != (err = read_response_content(r, read_response_content_data))) {
2922
		return dav_push_error(r->pool, err->status, 0,
2923
				apr_pstrcat(r->pool, "Could not read response content for ", method, " for ", resource_path, NULL), err);
2924
	}
2925
2926
	ap_remove_input_filter(http_in_filter);
2927
2928
	// MOVED PERMANENTLY - check with '/' at the end
2929
	if ((r->status == HTTP_MOVED_PERMANENTLY) && (resource_uri->path[strlen(resource_uri->path) - 1] != '/')) {
2930
		apr_uri_t *resource_with_slash_uri = apr_palloc(r->pool, sizeof(apr_uri_t));
2931
2932
		resource_path = apr_pstrcat(r->pool, resource_path, "/", NULL);
2933
		// TODO: do something with it
2934
		if (strcmp(resource_path, apr_table_get(r->headers_in, "Location")) != 0) {
2935
			return dav_new_error(r->pool, HTTP_INTERNAL_SERVER_ERROR, 0, "No idea what to do...");
2936
		}
2937
2938
		*resource_with_slash_uri = *resource_uri;
2939
		resource_with_slash_uri->path = apr_pstrcat(r->pool, resource_uri->path, "/", NULL);
2940
2941
		return dav_remote_method_request(r, method, resource_with_slash_uri, resource_path, resource, NULL, NULL, NULL, NULL);
2942
	}
2943
2944
	return NULL;
2945
}
2946
2947
DAV_DECLARE(dav_error *) dav_remote_resource_exists(request_rec *r, apr_uri_t *resource_uri,
2948
		const char *resource_path, const dav_resource *resource, int *exists)
2949
{
2950
	dav_error *err;
2951
2952
	*exists = 0;
2953
2954
	if (NULL != (err = dav_remote_set_connection(r, resource_uri))) {
2955
		return dav_push_error(r->pool, err->status, 0, "Unable to create connection in dav_remote_resource_exists.", err);
2956
	}
2957
2958
	apr_table_clear(r->headers_out);
2959
	apr_table_add(r->headers_out, "Host", resource_uri->hostname);
2960
	apr_table_add(r->headers_out, "Content-Length", "0");
2961
	apr_table_add(r->headers_out, "Depth", "0");
2962
	apr_table_add(r->headers_out, "Connection", "Keep-Alive");
2963
2964
	if (NULL != (err = dav_remote_method_request(r, "HEAD", resource_uri, resource_path,
2965
			resource,
2966
			NULL, NULL,
2967
			NULL, NULL))) {
2968
		return dav_push_error(r->pool, err->status, 0, "HEAD in dav_remote_resource_exists failed.", err);
2969
	}
2970
2971
	*exists = r->status != HTTP_NOT_FOUND;
2972
	return NULL;
2973
}
2974
2975
DAV_DECLARE(dav_error *) dav_remote_resource_delete(request_rec *r, apr_uri_t *resource_uri,
2976
		const char *resource_path, const dav_resource *resource)
2977
{
2978
	dav_error *err;
2979
2980
	if (NULL != (err = dav_remote_set_connection(r, resource_uri))) {
2981
		return dav_push_error(r->pool, err->status, 0, "Unable to create connection in dav_remote_resource_delete.", err);
2982
	}
2983
2984
	apr_table_clear(r->headers_out);
2985
	apr_table_add(r->headers_out, "Host", resource_uri->hostname);
2986
	apr_table_add(r->headers_out, "Content-Length", "0");
2987
	apr_table_add(r->headers_out, "Connection", "Keep-Alive");
2988
2989
	if (NULL != (err = dav_remote_method_request(r, "DELETE", resource_uri, resource_path, resource, NULL, NULL, NULL, NULL))) {
2990
		return dav_push_error(r->pool, err->status, 0, "DELETE in dav_remote_resource_delete failed.", err);
2991
	}
2992
2993
	if (r->status == HTTP_OK || r->status == HTTP_NO_CONTENT || r->status == HTTP_NOT_FOUND)
2994
		return NULL;
2995
	else
2996
		return dav_new_error(r->pool, r->status, 0, "DELETE refused by remote server");
2997
}
2998
2999
DAV_DECLARE(dav_error *) dav_remote_resource_mkcol(request_rec *r, apr_uri_t *resource_uri,
3000
		const char *resource_path, const dav_resource *resource, int overwrite, dav_remote_lock_token token)
3001
{
3002
	dav_error *err;
3003
3004
	if (NULL != (err = dav_remote_set_connection(r, resource_uri))) {
3005
		return dav_push_error(r->pool, err->status, 0, "Unable to create connection in dav_remote_resource_delete.", err);
3006
	}
3007
3008
	apr_table_clear(r->headers_out);
3009
	apr_table_add(r->headers_out, "Host", resource_uri->hostname);
3010
	apr_table_add(r->headers_out, "Content-Length", "0");
3011
	apr_table_add(r->headers_out, "Connection", "Keep-Alive");
3012
3013
	if (!overwrite) {
3014
		apr_table_add(r->headers_out, "If-None-Match", "*");
3015
	}
3016
3017
	if (token.token && token.path) {
3018
		apr_table_add(r->headers_out, "If", apr_pstrcat(r->pool, "<", token.path, "> (", token.token, ")", NULL));
3019
	}
3020
3021
	if (NULL != (err = dav_remote_method_request(r, "MKCOL", resource_uri, resource_path, resource, NULL, NULL, NULL, NULL))) {
3022
		return dav_push_error(r->pool, err->status, 0, "MKCOL failed.", err);
3023
	}
3024
3025
	if (r->status != HTTP_CREATED)
3026
		return dav_new_error(r->pool, r->status, 0, "Remote server refused to make collection");
3027
	else
3028
		return NULL;
3029
}
3030
3031
DAV_DECLARE(dav_error *) dav_remote_resource_put(request_rec *r, apr_uri_t *resource_uri,
3032
		const char *resource_path, const dav_resource *resource, int overwrite, dav_remote_lock_token token)
3033
{
3034
	dav_error *err;
3035
3036
	if (NULL != (err = dav_remote_set_connection(r, resource_uri))) {
3037
		return dav_push_error(r->pool, err->status, 0, "Unable to create connection in dav_remote_resource_delete.", err);
3038
	}
3039
3040
	apr_table_clear(r->headers_out);
3041
	apr_table_add(r->headers_out, "Host", resource_uri->hostname);
3042
	apr_table_add(r->headers_out, "Connection", "Keep-Alive");
3043
3044
	if (!overwrite) {
3045
		apr_table_add(r->headers_out, "If-None-Match", "*");
3046
	}
3047
3048
	if (token.token && token.path) {
3049
		apr_table_add(r->headers_out, "If", apr_pstrcat(r->pool, "<", token.path, "> (", token.token, ")", NULL));
3050
	}
3051
3052
    if ((err = (*resource->hooks->set_headers)(r, resource)) != NULL) {
3053
        return dav_push_error(r->pool, err->status, 0,
3054
                             "Unable to set up HTTP headers.",
3055
                             err);
3056
    }
3057
3058
    apr_table_unset(r->headers_out, "Accept-Ranges");
3059
    apr_table_unset(r->headers_out, "ETag");
3060
3061
	if (NULL != (err = dav_remote_method_request(r, "PUT", resource_uri, resource_path, resource,
3062
			dav_remote_send_resource_content, (void *)resource,
3063
			NULL, NULL))) {
3064
		return dav_push_error(r->pool, err->status, 0, "PUT failed.", err);
3065
	}
3066
3067
	if (r->status != HTTP_CREATED && r->status != HTTP_NO_CONTENT)
3068
		return dav_new_error(r->pool, r->status, 0, "Remote server does not accept resource");
3069
	else
3070
		return NULL;
3071
}
3072
3073
DAV_DECLARE(dav_error *) dav_remote_resource_lock(request_rec *r, apr_uri_t *resource_uri,
3074
		const char *resource_path, const dav_resource *resource, const char *owner, dav_remote_lock_token *token)
3075
{
3076
	dav_error *err;
3077
	char *content;
3078
	apr_xml_doc *xmlDoc;
3079
3080
	token->token = NULL;
3081
	token->path = NULL;
3082
3083
	if (NULL != (err = dav_remote_set_connection(r, resource_uri))) {
3084
		return dav_push_error(r->pool, err->status, 0, "Unable to create connection in dav_remote_resource_delete.", err);
3085
	}
3086
3087
	// create LOCK request
3088
	content = apr_pstrcat(r->pool,
3089
			"<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n"
3090
			"<D:lockinfo xmlns:D='DAV:'>\n"
3091
			"  <D:lockscope><D:exclusive/></D:lockscope>\n"
3092
			"  <D:locktype><D:write/></D:locktype>\n"
3093
			"  <D:owner>\n"
3094
			"       <D:href>", dav_xml_escape_uri(r->pool, owner), "</D:href>\n"
3095
			"  </D:owner>\n"
3096
			"</D:lockinfo>",
3097
			NULL
3098
	);
3099
3100
	apr_table_clear(r->headers_out);
3101
	apr_table_add(r->headers_out, "Host", resource_uri->hostname);
3102
	apr_table_add(r->headers_out, "Content-Type", "text/xml; charset=\"utf-8\"");
3103
	apr_table_add(r->headers_out, "Content-Length", apr_itoa(r->pool, strlen(content)));
3104
	apr_table_add(r->headers_out, "Connection", "Keep-Alive");
3105
	apr_table_add(r->headers_out, "Depth", "Infinity");
3106
	// only LOCK null resources
3107
	apr_table_add(r->headers_out, "If-None-Match", "*");
3108
3109
	if (NULL != (err = dav_remote_method_request(r, "LOCK", resource_uri, resource_path, resource,
3110
			dav_remote_send_string, content,
3111
			NULL, NULL))) {
3112
		return dav_push_error(r->pool, err->status, 0, "LOCK failed.", err);
3113
	}
3114
3115
	if (r->status == HTTP_OK) {
3116
		token->token = apr_table_get(r->headers_in, "Lock-Token");
3117
		token->path = apr_pstrdup(r->pool, resource_uri->path);
3118
		return NULL;
3119
	}
3120
3121
	if (r->status == HTTP_PRECONDITION_FAILED) {
3122
		return dav_new_error(r->pool, r->status, 0, "Resource already locked");
3123
	}
3124
3125
	// unable to lock, ignore it
3126
	return NULL;
3127
}
3128
3129
DAV_DECLARE(dav_error *) dav_remote_resource_unlock(request_rec *r, apr_uri_t *resource_uri,
3130
		const char *resource_path, const dav_resource *resource, dav_remote_lock_token *token)
3131
{
3132
	dav_error *err;
3133
	apr_xml_doc *xmlDoc;
3134
	char *content;
3135
3136
	if (NULL == token->token || NULL == token->path)
3137
		return 0; // no need
3138
3139
	if (NULL != (err = dav_remote_set_connection(r, resource_uri))) {
3140
		return dav_push_error(r->pool, err->status, 0, "Unable to create connection in dav_remote_resource_delete.", err);
3141
	}
3142
3143
	apr_table_clear(r->headers_out);
3144
	apr_table_add(r->headers_out, "Host", resource_uri->hostname);
3145
	apr_table_add(r->headers_out, "Connection", "Keep-Alive");
3146
	apr_table_add(r->headers_out, "Depth", "Infinity");
3147
	apr_table_add(r->headers_out, "Lock-Token", token->token);
3148
3149
	if (NULL != (err = dav_remote_method_request(r, "UNLOCK", resource_uri, resource_path, resource,
3150
			NULL, NULL,
3151
			NULL, NULL))) {
3152
		return dav_push_error(r->pool, err->status, 0, "UNLOCK failed.", err);
3153
	}
3154
3155
	if (r->status != HTTP_NO_CONTENT) {
3156
		return dav_new_error(r->pool, r->status, 0, "Unable to unlock resource");
3157
	}
3158
3159
	return NULL;
3160
}
3161
3162
DAV_DECLARE(dav_error *) dav_remote_resource_proppatch(request_rec *source_r, request_rec *r, apr_uri_t *resource_uri,
3163
		const char *resource_path, const dav_resource *resource, dav_remote_lock_token token, dav_lockdb *lockdb)
3164
{
3165
	dav_error *err;
3166
    const dav_hooks_db *prop_db_hooks;
3167
    const dav_db *prop_db;
3168
    dav_prop_name name;
3169
	char *content;
3170
	apr_text_header hdr = { 0 };
3171
    apr_text_header hdr_ns = { 0 };
3172
3173
	prop_db_hooks = DAV_GET_HOOKS_PROPDB(r);
3174
	if (NULL == prop_db_hooks) {
3175
		return NULL; // nothing to do
3176
	}
3177
3178
	if (NULL != (err = prop_db_hooks->open(r->pool, resource, 1, &prop_db))) {
3179
		return err;
3180
	}
3181
3182
	if (NULL == prop_db) {
3183
		return NULL; // nothing to do
3184
	}
3185
3186
	if (NULL != (err = prop_db_hooks->first_name(prop_db, &name))) {
3187
		prop_db_hooks->close(prop_db);
3188
		return err;
3189
	}
3190
3191
	dav_xmlns_info *xi = dav_xmlns_create(r->pool);
3192
3193
	if (NULL != (err = (*prop_db_hooks->define_namespaces)(prop_db, xi))) {
3194
		prop_db_hooks->close(prop_db);
3195
		return err;
3196
	}
3197
3198
	while (NULL != name.ns) {
3199
        int found;
3200
3201
        if (NULL != (err = (*prop_db_hooks->output_value)(prop_db, &name,
3202
        		xi, &hdr, &found))) {
3203
    		prop_db_hooks->close(prop_db);
3204
        	return err;
3205
        }
3206
3207
		if (NULL != (err = prop_db_hooks->next_name(prop_db, &name))) {
3208
			prop_db_hooks->close(prop_db);
3209
			return err;
3210
		}
3211
	}
3212
3213
    dav_xmlns_generate(xi, &hdr_ns);
3214
3215
	// create LOCK request
3216
	content = apr_pstrcat(r->pool,
3217
			"<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n"
3218
			"<D:propertyupdate xmlns:D=\"DAV:\"", NULL);
3219
3220
	// add namespace content
3221
    apr_text *text = hdr_ns.first;
3222
    while (text) {
3223
    	content = apr_pstrcat(r->pool, content, text->text, NULL);
3224
    	text = text->next;
3225
    }
3226
3227
	content = apr_pstrcat(r->pool, content, ">\n"
3228
			"  <D:set>\n"
3229
			"    <D:prop>\n",
3230
			NULL
3231
	);
3232
3233
	// add properties
3234
    text = hdr.first;
3235
    while (text) {
3236
    	content = apr_pstrcat(r->pool, content, "      ", text->text, NULL);
3237
    	text = text->next;
3238
    }
3239
3240
    content = apr_pstrcat(r->pool, content,
3241
			"    </D:prop>\n"
3242
			"  </D:set>\n"
3243
			"</D:propertyupdate>\n",
3244
			NULL
3245
	);
3246
3247
	apr_table_clear(r->headers_out);
3248
	apr_table_add(r->headers_out, "Host", resource_uri->hostname);
3249
	apr_table_add(r->headers_out, "Connection", "Keep-Alive");
3250
	apr_table_add(r->headers_out, "Content-Length", apr_itoa(r->pool, strlen(content)));
3251
	apr_table_add(r->headers_out, "Content-Type", "text/xml; charset=\"utf-8\"");
3252
3253
	if (token.token && token.path) {
3254
		apr_table_add(r->headers_out, "If", apr_pstrcat(r->pool, "<", token.path, "> (", token.token, ")", NULL));
3255
	}
3256
3257
	if (NULL != (err = dav_remote_method_request(r, "PROPPATCH", resource_uri, resource_path, resource,
3258
			dav_remote_send_string, content,
3259
			NULL, NULL))) {
3260
		return dav_push_error(r->pool, err->status, 0, "PROPATCH failed.", err);
3261
	}
3262
3263
	if (r->status != HTTP_NO_CONTENT && r->status != HTTP_MULTI_STATUS) {
3264
		return dav_new_error(r->pool, r->status, 0, "Unable to unlock resource");
3265
	}
3266
3267
	return NULL;
3268
}
3269
3270
struct dav_remote_copymove_copy_walk_ctx
3271
{
3272
	request_rec *source_r;
3273
	request_rec *r;
3274
	const char *base_uri;
3275
	apr_uri_t *dest_uri;
3276
	const char *dest;
3277
	dav_remote_lock_token token;
3278
	int overwrite;
3279
	dav_lockdb *lockdb;
3280
};
3281
3282
DAV_DECLARE(dav_response *) dav_push_response(apr_pool_t *p, char *href, int status, dav_response *next)
3283
{
3284
	dav_response *response;
3285
3286
	response = apr_palloc(p, sizeof(*response));
3287
	response->href = href;
3288
	response->desc = NULL;
3289
	response->propresult.propstats = NULL;
3290
	response->status = status;
3291
	response->next = next;
3292
3293
	return response;
3294
}
3295
3296
DAV_DECLARE(dav_error *) dav_remote_copymove_walk(dav_walk_resource *wres, int calltype)
3297
{
3298
	struct dav_remote_copymove_copy_walk_ctx *ctx = (struct dav_remote_copymove_copy_walk_ctx *)wres->walk_ctx;
3299
	char *new_resource_path;
3300
	apr_uri_t new_resource_uri;
3301
	dav_error *err;
3302
	int remove_length;
3303
3304
	if (strncmp(wres->resource->uri, ctx->base_uri, strlen(ctx->base_uri)) != 0) {
3305
		wres->response = dav_push_response(wres->pool, wres->resource->uri, HTTP_INTERNAL_SERVER_ERROR, wres->response);
3306
		return dav_new_error(wres->pool, HTTP_INTERNAL_SERVER_ERROR, 0, "Invalid uri of subresource");
3307
	}
3308
3309
	remove_length = strlen(ctx->base_uri);
3310
	if (wres->resource->collection) {
3311
		remove_length++;
3312
	}
3313
3314
	new_resource_path = apr_pstrcat(wres->pool, ctx->dest, &(wres->resource->uri[remove_length]), NULL);
3315
3316
	// shallow copy, only change the path
3317
	new_resource_uri = *ctx->dest_uri;
3318
	new_resource_uri.path = apr_pstrcat(wres->pool, ctx->dest_uri->path, &(wres->resource->uri[remove_length]), NULL);
3319
3320
	if (wres->resource->collection) {
3321
		// for lock-token...
3322
		new_resource_path[strlen(new_resource_path) - 1] = '\0';
3323
		new_resource_uri.path[strlen(new_resource_uri.path) - 1] = '\0';
3324
3325
		if (NULL != (err = dav_remote_resource_mkcol(ctx->r, &new_resource_uri, new_resource_path, wres->resource, ctx->overwrite, ctx->token))) {
3326
			wres->response = dav_push_response(wres->pool, wres->resource->uri, err->status, wres->response);
3327
			return err;
3328
		}
3329
	} else {
3330
		if (NULL != (err = dav_remote_resource_put(ctx->r, &new_resource_uri, new_resource_path, wres->resource, ctx->overwrite, ctx->token))) {
3331
			wres->response = dav_push_response(wres->pool, wres->resource->uri, err->status, wres->response);
3332
			return err;
3333
		}
3334
	}
3335
3336
	if (NULL != (err = dav_remote_resource_proppatch(ctx->source_r, ctx->r, ctx->dest_uri,
3337
			ctx->dest, wres->resource, ctx->token, ctx->lockdb))) {
3338
		wres->response = dav_push_response(wres->pool, wres->resource->uri, err->status, wres->response);
3339
		return err;
3340
	}
3341
3342
	return NULL;
3343
}
3344
3345
DAV_DECLARE(dav_error *) dav_remote_copymove(request_rec *r, dav_resource *resource,
3346
		const char *dest, int overwrite, int depth, dav_lockdb *lockdb, dav_response **response)
3347
{
3348
	dav_error *err = NULL;
3349
	dav_error *lock_err = NULL;
3350
	apr_uri_t dest_uri;
3351
	conn_rec *conn;
3352
    request_rec *rp;
3353
    int exists;
3354
	int deleted;
3355
	dav_walk_params walk_params = { 0 };
3356
	const char *lock_owner;
3357
	dav_remote_lock_token token;
3358
3359
	*response = 0;
3360
3361
    if (APR_SUCCESS != apr_uri_parse(r->pool, dest, &dest_uri)) {
3362
        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
3363
                      "Destination URI cannot be parsed.", NULL);
3364
        return dav_new_error(r->pool, HTTP_BAD_REQUEST, 0, "Destination URI cannot be parsed.");
3365
    }
3366
3367
    if (!dest_uri.port) {
3368
    	dest_uri.port = apr_uri_port_of_scheme(dest_uri.scheme);
3369
    }
3370
3371
    // 1. create request
3372
    rp = dav_remote_make_fake_request(r);
3373
3374
   	if (!overwrite) {
3375
   	    // 2. check if exists
3376
   	   	if (NULL != (err = dav_remote_resource_exists(rp, &dest_uri, dest, resource, &exists))) {
3377
   	   		return err;
3378
   	   	}
3379
3380
   	   	if (exists) {
3381
   	        return dav_new_error(r->pool, HTTP_PRECONDITION_FAILED, 0, "Destination resource already exists.");
3382
   	   	}
3383
    }
3384
   	else {
3385
   		// 2. delete old resource
3386
   		if (NULL != (err = dav_remote_resource_delete(rp, &dest_uri, dest, resource))) {
3387
   			return err;
3388
   		}
3389
   	}
3390
3391
   	// 3. gain lock on NULL resource
3392
   	lock_owner = r->unparsed_uri;
3393
   	if (NULL != (err = dav_remote_resource_lock(rp, &dest_uri, dest, resource, lock_owner, &token))) {
3394
   		return err;
3395
	}
3396
3397
   	struct dav_remote_copymove_copy_walk_ctx ctx;
3398
	ctx.source_r = r;
3399
	ctx.r = rp;
3400
	ctx.base_uri = resource->uri;
3401
	ctx.dest_uri = &dest_uri;
3402
	ctx.dest = dest;
3403
	ctx.overwrite = overwrite;
3404
	ctx.token = token;
3405
	ctx.lockdb = lockdb;
3406
3407
   	walk_params.walk_type = DAV_WALKTYPE_AUTH | DAV_WALKTYPE_NORMAL;
3408
   	walk_params.func = dav_remote_copymove_walk;
3409
   	walk_params.walk_ctx = &ctx;
3410
   	walk_params.pool = r->pool;
3411
   	walk_params.root = resource;
3412
3413
   	// 4. copy resources/collections
3414
   	err = (*resource->hooks->walk)(&walk_params, depth, response);
3415
3416
   	// 5. release lock
3417
   	if (NULL != (err = dav_remote_resource_unlock(rp, &dest_uri, dest, resource, &token))) {
3418
   		return err;
3419
	}
3420
3421
   	if (NULL != *response) {
3422
   		return dav_new_error(r->pool, HTTP_MULTI_STATUS, 0, "");
3423
   	}
3424
3425
	return NULL;
3426
}
3427
2553
/* handle the COPY and MOVE methods */
3428
/* handle the COPY and MOVE methods */
2554
static int dav_method_copymove(request_rec *r, int is_move)
3429
static int dav_method_copymove(request_rec *r, int is_move)
2555
{
3430
{
Lines 2559-2567 Link Here
2559
    dav_auto_version_info dst_av_info = { 0 };
3434
    dav_auto_version_info dst_av_info = { 0 };
2560
    const char *body;
3435
    const char *body;
2561
    const char *dest;
3436
    const char *dest;
2562
    dav_error *err;
3437
    dav_error *err = NULL;
2563
    dav_error *err2;
3438
    dav_error *err2 = NULL;
2564
    dav_error *err3;
3439
    dav_error *err3 = NULL;
2565
    dav_response *multi_response;
3440
    dav_response *multi_response;
2566
    dav_lookup_result lookup;
3441
    dav_lookup_result lookup;
2567
    int is_dir;
3442
    int is_dir;
Lines 2571-2576 Link Here
2571
    dav_lockdb *lockdb;
3446
    dav_lockdb *lockdb;
2572
    int replace_dest;
3447
    int replace_dest;
2573
    int resnew_state;
3448
    int resnew_state;
3449
    int remote = 0;
2574
3450
2575
    /* Ask repository module to resolve the resource */
3451
    /* Ask repository module to resolve the resource */
2576
    err = dav_get_resource(r, !is_move /* label_allowed */,
3452
    err = dav_get_resource(r, !is_move /* label_allowed */,
Lines 2609-2614 Link Here
2609
        return HTTP_BAD_REQUEST;
3485
        return HTTP_BAD_REQUEST;
2610
    }
3486
    }
2611
3487
3488
    /* get and parse the overwrite header value */
3489
    if ((overwrite = dav_get_overwrite(r)) < 0) {
3490
        /* dav_get_overwrite() supplies additional information for the
3491
         * default message. */
3492
        return HTTP_BAD_REQUEST;
3493
    }
3494
2612
    lookup = dav_lookup_uri(dest, r, 1 /* must_be_absolute */);
3495
    lookup = dav_lookup_uri(dest, r, 1 /* must_be_absolute */);
2613
    if (lookup.rnew == NULL) {
3496
    if (lookup.rnew == NULL) {
2614
        if (lookup.err.status == HTTP_BAD_REQUEST) {
3497
        if (lookup.err.status == HTTP_BAD_REQUEST) {
Lines 2618-2628 Link Here
2618
            return HTTP_BAD_REQUEST;
3501
            return HTTP_BAD_REQUEST;
2619
        }
3502
        }
2620
3503
3504
        if (lookup.err.status == HTTP_BAD_GATEWAY) {
3505
            err = dav_get_resource(r, 1 /* label_allowed */, 0 /* use_checked_in */,
3506
                                   &resource);
3507
            remote = 1;
3508
        }
3509
3510
        if (!remote) {
2621
        /* ### this assumes that dav_lookup_uri() only generates a status
3511
        /* ### this assumes that dav_lookup_uri() only generates a status
2622
         * ### that Apache can provide a status line for!! */
3512
         * ### that Apache can provide a status line for!! */
2623
3513
2624
        return dav_error_response(r, lookup.err.status, lookup.err.desc);
3514
        return dav_error_response(r, lookup.err.status, lookup.err.desc);
2625
    }
3515
    }
3516
    }
3517
3518
    if (!remote) {
2626
    if (lookup.rnew->status != HTTP_OK) {
3519
    if (lookup.rnew->status != HTTP_OK) {
2627
        const char *auth = apr_table_get(lookup.rnew->err_headers_out,
3520
        const char *auth = apr_table_get(lookup.rnew->err_headers_out,
2628
                                        "WWW-Authenticate");
3521
                                        "WWW-Authenticate");
Lines 2651-2671 Link Here
2651
3544
2652
    /* are the two resources handled by the same repository? */
3545
    /* are the two resources handled by the same repository? */
2653
    if (resource->hooks != resnew->hooks) {
3546
    if (resource->hooks != resnew->hooks) {
2654
        /* ### this message exposes some backend config, but screw it... */
3547
    		err = dav_get_resource(r, 1 /* label_allowed */, 0 /* use_checked_in */,
2655
        return dav_error_response(r, HTTP_BAD_GATEWAY,
3548
                               &resource);
2656
                                  "Destination URI is handled by a "
3549
    		remote = 1;
2657
                                  "different repository than the source URI. "
2658
                                  "MOVE or COPY between repositories is "
2659
                                  "not possible.");
2660
    }
3550
    }
2661
2662
    /* get and parse the overwrite header value */
2663
    if ((overwrite = dav_get_overwrite(r)) < 0) {
2664
        /* dav_get_overwrite() supplies additional information for the
2665
         * default message. */
2666
        return HTTP_BAD_REQUEST;
2667
    }
3551
    }
2668
3552
3553
    // recheck remote, maybe it changed
3554
    if (!remote) {
2669
    /* quick failure test: if dest exists and overwrite is false. */
3555
    /* quick failure test: if dest exists and overwrite is false. */
2670
    if (resnew->exists && !overwrite) {
3556
    if (resnew->exists && !overwrite) {
2671
        /* Supply some text for the error response body. */
3557
        /* Supply some text for the error response body. */
Lines 2679-2685 Link Here
2679
        /* Supply some text for the error response body. */
3565
        /* Supply some text for the error response body. */
2680
        return dav_error_response(r, HTTP_FORBIDDEN,
3566
        return dav_error_response(r, HTTP_FORBIDDEN,
2681
                                  "Source and Destination URIs are the same.");
3567
                                  "Source and Destination URIs are the same.");
2682
3568
    	}
2683
    }
3569
    }
2684
3570
2685
    is_dir = resource->collection;
3571
    is_dir = resource->collection;
Lines 2732-2737 Link Here
2732
        return dav_handle_err(r, err, multi_response);
3618
        return dav_handle_err(r, err, multi_response);
2733
    }
3619
    }
2734
3620
3621
    if (!remote)
3622
    {
2735
    /*
3623
    /*
2736
     * Check If-Headers and existing locks for destination. Note that we
3624
     * Check If-Headers and existing locks for destination. Note that we
2737
     * use depth==infinity since the target (hierarchy) will be deleted
3625
     * use depth==infinity since the target (hierarchy) will be deleted
Lines 2778-2783 Link Here
2778
                                  "Destination collection contains the Source "
3666
                                  "Destination collection contains the Source "
2779
                                  "and Overwrite has been specified.");
3667
                                  "and Overwrite has been specified.");
2780
    }
3668
    }
3669
    }
2781
3670
2782
    /* ### for now, we don't need anything in the body */
3671
    /* ### for now, we don't need anything in the body */
2783
    if ((result = ap_discard_request_body(r)) != OK) {
3672
    if ((result = ap_discard_request_body(r)) != OK) {
Lines 2818-2823 Link Here
2818
        }
3707
        }
2819
    }
3708
    }
2820
3709
3710
    if (!remote)
3711
    {
2821
    /*
3712
    /*
2822
     * Remember the initial state of the destination, so the lock system
3713
     * Remember the initial state of the destination, so the lock system
2823
     * can be notified as to how it changed.
3714
     * can be notified as to how it changed.
Lines 2894-2906 Link Here
2894
    /* perform any auto-versioning cleanup */
3785
    /* perform any auto-versioning cleanup */
2895
    err2 = dav_auto_checkin(r, NULL, err != NULL /* undo if error */,
3786
    err2 = dav_auto_checkin(r, NULL, err != NULL /* undo if error */,
2896
                            0 /*unlock*/, &dst_av_info);
3787
                            0 /*unlock*/, &dst_av_info);
3788
    }
2897
3789
2898
    if (is_move) {
3790
    if (is_move) {
2899
        err3 = dav_auto_checkin(r, NULL, err != NULL /* undo if error */,
3791
        err3 = dav_auto_checkin(r, NULL, err != NULL /* undo if error */,
2900
                                0 /*unlock*/, &src_av_info);
3792
                                0 /*unlock*/, &src_av_info);
2901
    }
3793
    }
2902
    else
2903
        err3 = NULL;
2904
3794
2905
    /* check for error from remove/copy/move operations */
3795
    /* check for error from remove/copy/move operations */
2906
    if (err != NULL) {
3796
    if (err != NULL) {
Lines 2935-2940 Link Here
2935
        dav_log_err(r, err, APLOG_WARNING);
3825
        dav_log_err(r, err, APLOG_WARNING);
2936
    }
3826
    }
2937
3827
3828
    if (!remote) {
2938
    /* propagate any indirect locks at the target */
3829
    /* propagate any indirect locks at the target */
2939
    if (lockdb != NULL) {
3830
    if (lockdb != NULL) {
2940
3831
Lines 2953-2962 Link Here
2953
            return dav_handle_err(r, err, NULL);
3844
            return dav_handle_err(r, err, NULL);
2954
        }
3845
        }
2955
    }
3846
    }
3847
    }
3848
3849
    if (remote) {
3850
    	if (NULL != (err = dav_remote_copymove(r, resource, dest, overwrite, depth, lockdb, &multi_response))) {
3851
    		return dav_handle_err(r, err, multi_response);
3852
    	}
3853
3854
    	if (is_move) {
3855
    		if (NULL != (err = (*resource->hooks->remove_resource)(resource, &multi_response))) {
3856
    			return dav_handle_err(r, err, multi_response);
3857
    		}
3858
    	}
3859
3860
    	if (lockdb != NULL) {
3861
    		(*lockdb->hooks->close_lockdb)(lockdb);
3862
    	}
2956
3863
2957
    /* return an appropriate response (HTTP_CREATED or HTTP_NO_CONTENT) */
3864
    /* return an appropriate response (HTTP_CREATED or HTTP_NO_CONTENT) */
3865
    	return dav_created(r, dest, "Destination", 0);
3866
    }
3867
    if (!remote) {
3868
    	/* return an appropriate response (HTTP_CREATED or HTTP_NO_CONTENT) */
2958
    return dav_created(r, lookup.rnew->uri, "Destination",
3869
    return dav_created(r, lookup.rnew->uri, "Destination",
2959
                       resnew_state == DAV_RESOURCE_EXISTS);
3870
                       resnew_state == DAV_RESOURCE_EXISTS);
3871
    }
2960
}
3872
}
2961
3873
2962
/* dav_method_lock:  Handler to implement the DAV LOCK method
3874
/* dav_method_lock:  Handler to implement the DAV LOCK method
(-)httpd-2.2.9-orig/modules/dav/main/util.c (-2 / +1 lines)
Lines 216-225 Link Here
216
           request. the port must match our port.
216
           request. the port must match our port.
217
        */
217
        */
218
        port = r->connection->local_addr->port;
218
        port = r->connection->local_addr->port;
219
219
        if (strcasecmp(comp.scheme, scheme) != 0
220
        if (strcasecmp(comp.scheme, scheme) != 0
220
#ifdef APACHE_PORT_HANDLING_IS_BUSTED
221
            || comp.port != port
221
            || comp.port != port
222
#endif
223
            ) {
222
            ) {
224
            result.err.status = HTTP_BAD_GATEWAY;
223
            result.err.status = HTTP_BAD_GATEWAY;
225
            result.err.desc = apr_psprintf(r->pool,
224
            result.err.desc = apr_psprintf(r->pool,
(-)httpd-2.2.9-orig/modules/http/http_filters.c (-1 / +1 lines)
Lines 1372-1378 Link Here
1372
            }
1372
            }
1373
1373
1374
            /* These are metadata buckets. */
1374
            /* These are metadata buckets. */
1375
            if (bucket->length == 0) {
1375
            if (APR_BUCKET_IS_METADATA(bucket)) {
1376
                continue;
1376
                continue;
1377
            }
1377
            }
1378
1378

Return to bug 45449