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 / +899 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 0;
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
	if (NULL != (err = dav_remote_create_connection(r->pool, resource_uri, r->server, &conn))) {
2664
		return err;
2665
	}
2666
2667
	conn->keepalive = AP_CONN_KEEPALIVE;
2668
2669
	r->connection      = conn;
2670
	r->output_filters  = conn->output_filters;
2671
	r->input_filters   = conn->input_filters;
2672
	r->proto_output_filters  = conn->output_filters;
2673
	r->proto_input_filters   = conn->input_filters;
2674
2675
	return 0;
2676
}
2677
2678
DAV_DECLARE(dav_error *) dav_remote_send_resource_content(request_rec *r, const dav_resource *resource)
2679
{
2680
	dav_error *err;
2681
	apr_bucket_brigade *request_brigade;
2682
	apr_bucket *e;
2683
	apr_status_t rv;
2684
2685
    /* okay... time to deliver the content */
2686
    if ((err = (*resource->hooks->deliver)(resource,
2687
                                           r->output_filters)) != NULL) {
2688
        return dav_push_error(r->pool, err->status, 0,
2689
                             "Unable to deliver content.",
2690
                             err);
2691
    }
2692
2693
	request_brigade =  apr_brigade_create(r->pool, r->connection->bucket_alloc);
2694
2695
	e = apr_bucket_flush_create(r->connection->bucket_alloc);
2696
	APR_BRIGADE_INSERT_TAIL(request_brigade, e);
2697
2698
    if (APR_SUCCESS != (rv = ap_pass_brigade(r->output_filters, request_brigade)))
2699
    	return dav_new_error(r->pool, HTTP_INTERNAL_SERVER_ERROR, 0, "Sending content failed");
2700
    else
2701
    	return NULL;
2702
}
2703
2704
DAV_DECLARE(dav_error *) dav_remote_send_string(request_rec *r, const char *string)
2705
{
2706
	dav_error *err;
2707
	apr_bucket_brigade *request_brigade;
2708
	apr_bucket *e;
2709
	apr_status_t rv;
2710
2711
	request_brigade =  apr_brigade_create(r->pool, r->connection->bucket_alloc);
2712
2713
	e = apr_bucket_pool_create(string, strlen(string), r->pool, r->connection->bucket_alloc);
2714
	ap_xlate_proto_to_ascii(string, strlen(string));
2715
	APR_BRIGADE_INSERT_TAIL(request_brigade, e);
2716
2717
	e = apr_bucket_flush_create(r->connection->bucket_alloc);
2718
	APR_BRIGADE_INSERT_TAIL(request_brigade, e);
2719
2720
    if (APR_SUCCESS != (rv = ap_pass_brigade(r->output_filters, request_brigade)))
2721
    	return dav_new_error(r->pool, HTTP_INTERNAL_SERVER_ERROR, 0, "Sending content failed");
2722
    else
2723
    	return NULL;
2724
}
2725
2726
struct dav_remote_send_headers_wrapper {
2727
	apr_bucket_alloc_t *bucket_alloc;
2728
	apr_bucket_brigade *request_brigade;
2729
	apr_pool_t *p;
2730
};
2731
2732
int dav_remote_send_header(void *rec, const char *key, const char *value)
2733
{
2734
	struct dav_remote_send_headers_wrapper *wrapper = (struct dav_remote_send_headers_wrapper *)rec;
2735
2736
	apr_bucket_brigade *request_brigade = wrapper->request_brigade;
2737
	apr_bucket *e;
2738
	char *buf;
2739
2740
	buf = apr_pstrcat(wrapper->p, key, ": ", value, CRLF, NULL);
2741
	e = apr_bucket_pool_create(buf, strlen(buf), wrapper->p, wrapper->bucket_alloc);
2742
	ap_xlate_proto_to_ascii(buf, strlen(buf));
2743
	APR_BRIGADE_INSERT_TAIL(request_brigade, e);
2744
}
2745
2746
DAV_DECLARE(dav_error *) dav_remote_read_status_line(request_rec *r)
2747
{
2748
    apr_bucket_brigade *response_brigade;
2749
2750
    char buff[HUGE_STRING_LEN];
2751
	char *buff_p = buff;
2752
	char keepchar;
2753
	apr_size_t len;
2754
2755
    response_brigade = apr_brigade_create(r->pool, r->connection->bucket_alloc);
2756
    ap_rgetline(&buff_p, sizeof(buff), &len, r, 0, response_brigade);
2757
2758
    if (!apr_date_checkmask(buff, "HTTP/#.# ###*")) {
2759
    	return dav_new_error(r->pool, HTTP_BAD_GATEWAY, 0, "Invalid response status line");
2760
    }
2761
2762
    int major, minor;
2763
2764
    if (2 != sscanf(buff, "HTTP/%u.%u", &major, &minor)) {
2765
        major = 1;
2766
        minor = 1;
2767
    }
2768
    else if ((buff[5] != '1') || (len >= sizeof(buff) - 1)) {
2769
        return dav_new_error(r->pool, HTTP_BAD_GATEWAY, 0, "Invalid response status line");
2770
    }
2771
2772
    keepchar = buff[12];
2773
    buff[12] = '\0';
2774
    r->status = atoi(&buff[9]);
2775
2776
    if (keepchar != '\0') {
2777
     	buff[12] = keepchar;
2778
    } else {
2779
        /* 2616 requires the space in Status-Line; the origin
2780
         * server may have sent one but ap_rgetline_core will
2781
         * have stripped it. */
2782
    	buff[12] = ' ';
2783
        buff[13] = '\0';
2784
    }
2785
    r->status_line = apr_pstrdup(r->pool, &buff[9]);
2786
2787
    return 0;
2788
}
2789
2790
DAV_DECLARE(dav_error *) dav_remote_read_response_headers(request_rec *r)
2791
{
2792
	dav_error *err;
2793
    apr_bucket_brigade *response_brigade;
2794
	apr_size_t len;
2795
	apr_status_t rv;
2796
    char buff[HUGE_STRING_LEN];
2797
	char *buff_p = buff;
2798
	char *value, *end;
2799
2800
	apr_table_clear(r->headers_in);
2801
2802
	response_brigade = apr_brigade_create(r->pool, r->connection->bucket_alloc);
2803
    if (APR_SUCCESS != (rv = ap_rgetline(&buff_p, sizeof(buff), &len, r, 0, response_brigade))) {
2804
    	return dav_new_error(r->pool, HTTP_BAD_GATEWAY, 0, "Error reading response header");
2805
    }
2806
2807
    while (0 < len) {
2808
    	if (!(value = strchr(buff, ':'))) {
2809
    	    if (APR_SUCCESS != (rv = ap_rgetline(&buff_p, sizeof(buff), &len, r, 0, response_brigade))) {
2810
    	    	return dav_new_error(r->pool, HTTP_BAD_GATEWAY, 0, "Error reading response header");
2811
    	    }
2812
    	}
2813
2814
        *value = '\0';
2815
        ++value;
2816
        /* XXX: RFC2068 defines only SP and HT as whitespace, this test is
2817
         * wrong... and so are many others probably.
2818
         */
2819
        while (apr_isspace(*value))
2820
            ++value;            /* Skip to start of value   */
2821
2822
        /* should strip trailing whitespace as well */
2823
        for (end = &value[strlen(value)-1]; end > value && apr_isspace(*end); --end)
2824
            *end = '\0';
2825
2826
        apr_table_add(r->headers_in, buff, value);
2827
2828
	    if (APR_SUCCESS != (rv = ap_rgetline(&buff_p, sizeof(buff), &len, r, 0, response_brigade))) {
2829
	    	return dav_new_error(r->pool, HTTP_BAD_GATEWAY, 0, "Error reading response header");
2830
	    }
2831
    }
2832
2833
    return 0;
2834
}
2835
2836
typedef DAV_DECLARE(dav_error *) (* write_request_content_callback) (request_rec *, void *data);
2837
typedef DAV_DECLARE(dav_error *) (* read_reponse_content_callback) (request_rec *, void *data);
2838
2839
DAV_DECLARE(dav_error *) dav_remote_skip_response_content(request_rec *r, void *unused)
2840
{
2841
	if (APR_SUCCESS != ap_discard_request_body(r))
2842
		return dav_new_error(r->pool, HTTP_INTERNAL_SERVER_ERROR, 0, "Error during discarding response body");
2843
2844
	return NULL;
2845
}
2846
2847
DAV_DECLARE(dav_error *) dav_remote_method_request(request_rec *r, const char *method, apr_uri_t *resource_uri,
2848
		const char *resource_path, const dav_resource *resource,
2849
		write_request_content_callback write_request_content, void *write_request_content_data,
2850
		read_reponse_content_callback read_response_content, void *read_response_content_data)
2851
{
2852
    apr_status_t rv;
2853
    dav_error *err;
2854
    apr_bucket_alloc_t *bucket_alloc = r->connection->bucket_alloc;
2855
    apr_bucket_brigade *request_brigade;
2856
    apr_bucket *e;
2857
    ap_filter_t *http_in_filter;
2858
	char *buf;
2859
2860
	// as I see nobody in httpd check for NULL results of malloc/apr_palloc, so why I should?
2861
    request_brigade = apr_brigade_create(r->pool, bucket_alloc);
2862
2863
    // request line
2864
	buf = apr_pstrcat(r->pool, method, " ", resource_uri->path, " HTTP/1.1", CRLF, NULL);
2865
	e = apr_bucket_pool_create(buf, strlen(buf), r->pool, bucket_alloc);
2866
	ap_xlate_proto_to_ascii(buf, strlen(buf));
2867
	APR_BRIGADE_INSERT_TAIL(request_brigade, e);
2868
2869
	// headers
2870
	struct dav_remote_send_headers_wrapper wrapper;
2871
	wrapper.bucket_alloc = bucket_alloc;
2872
	wrapper.request_brigade = request_brigade;
2873
	wrapper.p = r->pool;
2874
2875
	apr_table_do(dav_remote_send_header, &wrapper, r->headers_out, 0);
2876
2877
	// empty line after headers
2878
	buf = apr_pstrcat(r->pool, CRLF, NULL);
2879
	e = apr_bucket_pool_create(buf, strlen(buf), r->pool, bucket_alloc);
2880
	ap_xlate_proto_to_ascii(buf, strlen(buf));
2881
	APR_BRIGADE_INSERT_TAIL(request_brigade, e);
2882
2883
	e = apr_bucket_flush_create(bucket_alloc);
2884
	APR_BRIGADE_INSERT_TAIL(request_brigade, e);
2885
2886
	// send it now
2887
    rv = ap_pass_brigade(r->output_filters, request_brigade);
2888
2889
	if (rv != APR_SUCCESS) {
2890
		return dav_new_error(r->pool, HTTP_INTERNAL_SERVER_ERROR, 0, "Sending request failed");
2891
	}
2892
2893
    // for PUT requests
2894
    if (NULL != write_request_content) {
2895
    	if (NULL != (err = write_request_content(r, write_request_content_data))) {
2896
    		return dav_push_error(r->pool, err->status, 0,
2897
    				apr_pstrcat(r->pool, "Could not write request for ", method, " for ", resource_path, NULL), err);
2898
    	}
2899
    }
2900
2901
	if (NULL != (err = dav_remote_read_status_line(r))) {
2902
		return dav_push_error(r->pool, err->status, 0,
2903
				apr_pstrcat(r->pool, "Could not read status for ", method, " for ", resource_path, NULL), err);
2904
	}
2905
2906
	if (NULL != (err = dav_remote_read_response_headers(r))) {
2907
		return dav_push_error(r->pool, err->status, 0,
2908
				apr_pstrcat(r->pool, "Could not read response headers for ", method, " for ", resource_path, NULL), err);
2909
	}
2910
2911
	http_in_filter = ap_add_input_filter("HTTP_IN", NULL, r, r->connection);
2912
2913
	if (NULL == read_response_content) {
2914
		read_response_content = dav_remote_skip_response_content;
2915
	}
2916
2917
	if (NULL != (err = read_response_content(r, read_response_content_data))) {
2918
		return dav_push_error(r->pool, err->status, 0,
2919
				apr_pstrcat(r->pool, "Could not read response content for ", method, " for ", resource_path, NULL), err);
2920
	}
2921
2922
	ap_remove_input_filter(http_in_filter);
2923
2924
	// MOVED PERMANENTLY - check with '/' at the end
2925
	if ((r->status == HTTP_MOVED_PERMANENTLY) && (resource_uri->path[strlen(resource_uri->path) - 1] != '/')) {
2926
		apr_uri_t *resource_with_slash_uri = apr_palloc(r->pool, sizeof(apr_uri_t));
2927
2928
		resource_path = apr_pstrcat(r->pool, resource_path, "/", NULL);
2929
		// TODO: do something with it
2930
		if (strcmp(resource_path, apr_table_get(r->headers_in, "Location")) != 0) {
2931
			return dav_new_error(r->pool, HTTP_INTERNAL_SERVER_ERROR, 0, "No idea what to do...");
2932
		}
2933
2934
		*resource_with_slash_uri = *resource_uri;
2935
		resource_with_slash_uri->path = apr_pstrcat(r->pool, resource_uri->path, "/", NULL);
2936
2937
		return dav_remote_method_request(r, method, resource_with_slash_uri, resource_path, resource, NULL, NULL, NULL, NULL);
2938
	}
2939
2940
	return NULL;
2941
}
2942
2943
DAV_DECLARE(dav_error *) dav_remote_resource_exists(request_rec *r, apr_uri_t *resource_uri,
2944
		const char *resource_path, const dav_resource *resource, int *exists)
2945
{
2946
	dav_error *err;
2947
2948
	*exists = 0;
2949
2950
	if (NULL != (err = dav_remote_set_connection(r, resource_uri))) {
2951
		return dav_push_error(r->pool, err->status, 0, "Unable to create connection in dav_remote_resource_exists.", err);
2952
	}
2953
2954
	apr_table_clear(r->headers_out);
2955
	apr_table_add(r->headers_out, "Host", resource_uri->hostname);
2956
	apr_table_add(r->headers_out, "Content-Length", "0");
2957
	apr_table_add(r->headers_out, "Depth", "0");
2958
	apr_table_add(r->headers_out, "Connection", "Keep-Alive");
2959
2960
	if (NULL != (err = dav_remote_method_request(r, "HEAD", resource_uri, resource_path,
2961
			resource,
2962
			NULL, NULL,
2963
			NULL, NULL))) {
2964
		return dav_push_error(r->pool, err->status, 0, "HEAD in dav_remote_resource_exists failed.", err);
2965
	}
2966
2967
	*exists = r->status != HTTP_NOT_FOUND;
2968
	return NULL;
2969
}
2970
2971
DAV_DECLARE(dav_error *) dav_remote_resource_delete(request_rec *r, apr_uri_t *resource_uri,
2972
		const char *resource_path, const dav_resource *resource)
2973
{
2974
	dav_error *err;
2975
2976
	if (NULL != (err = dav_remote_set_connection(r, resource_uri))) {
2977
		return dav_push_error(r->pool, err->status, 0, "Unable to create connection in dav_remote_resource_delete.", err);
2978
	}
2979
2980
	apr_table_clear(r->headers_out);
2981
	apr_table_add(r->headers_out, "Host", resource_uri->hostname);
2982
	apr_table_add(r->headers_out, "Content-Length", "0");
2983
	apr_table_add(r->headers_out, "Connection", "Keep-Alive");
2984
2985
	if (NULL != (err = dav_remote_method_request(r, "DELETE", resource_uri, resource_path, resource, NULL, NULL, NULL, NULL))) {
2986
		return dav_push_error(r->pool, err->status, 0, "DELETE in dav_remote_resource_delete failed.", err);
2987
	}
2988
2989
	if (r->status == HTTP_OK || r->status == HTTP_NO_CONTENT || r->status == HTTP_NOT_FOUND)
2990
		return NULL;
2991
	else
2992
		return dav_new_error(r->pool, r->status, 0, "DELETE refused by remote server");
2993
}
2994
2995
DAV_DECLARE(dav_error *) dav_remote_resource_mkcol(request_rec *r, apr_uri_t *resource_uri,
2996
		const char *resource_path, const dav_resource *resource, int overwrite, dav_remote_lock_token token)
2997
{
2998
	dav_error *err;
2999
3000
	if (NULL != (err = dav_remote_set_connection(r, resource_uri))) {
3001
		return dav_push_error(r->pool, err->status, 0, "Unable to create connection in dav_remote_resource_delete.", err);
3002
	}
3003
3004
	apr_table_clear(r->headers_out);
3005
	apr_table_add(r->headers_out, "Host", resource_uri->hostname);
3006
	apr_table_add(r->headers_out, "Content-Length", "0");
3007
	apr_table_add(r->headers_out, "Connection", "Keep-Alive");
3008
3009
	if (!overwrite) {
3010
		apr_table_add(r->headers_out, "If-None-Match", "*");
3011
	}
3012
3013
	if (token.token && token.path) {
3014
		apr_table_add(r->headers_out, "If", apr_pstrcat(r->pool, "<", token.path, "> (", token.token, ")", NULL));
3015
	}
3016
3017
	if (NULL != (err = dav_remote_method_request(r, "MKCOL", resource_uri, resource_path, resource, NULL, NULL, NULL, NULL))) {
3018
		return dav_push_error(r->pool, err->status, 0, "MKCOL failed.", err);
3019
	}
3020
3021
	if (r->status != HTTP_CREATED)
3022
		return dav_new_error(r->pool, r->status, 0, "Remote server refused to make collection");
3023
	else
3024
		return NULL;
3025
}
3026
3027
DAV_DECLARE(dav_error *) dav_remote_resource_put(request_rec *r, apr_uri_t *resource_uri,
3028
		const char *resource_path, const dav_resource *resource, int overwrite, dav_remote_lock_token token)
3029
{
3030
	dav_error *err;
3031
3032
	if (NULL != (err = dav_remote_set_connection(r, resource_uri))) {
3033
		return dav_push_error(r->pool, err->status, 0, "Unable to create connection in dav_remote_resource_delete.", err);
3034
	}
3035
3036
	apr_table_clear(r->headers_out);
3037
	apr_table_add(r->headers_out, "Host", resource_uri->hostname);
3038
	apr_table_add(r->headers_out, "Connection", "Keep-Alive");
3039
3040
	if (!overwrite) {
3041
		apr_table_add(r->headers_out, "If-None-Match", "*");
3042
	}
3043
3044
	if (token.token && token.path) {
3045
		apr_table_add(r->headers_out, "If", apr_pstrcat(r->pool, "<", token.path, "> (", token.token, ")", NULL));
3046
	}
3047
3048
    if ((err = (*resource->hooks->set_headers)(r, resource)) != NULL) {
3049
        return dav_push_error(r->pool, err->status, 0,
3050
                             "Unable to set up HTTP headers.",
3051
                             err);
3052
    }
3053
3054
    apr_table_unset(r->headers_out, "Accept-Ranges");
3055
    apr_table_unset(r->headers_out, "ETag");
3056
3057
	if (NULL != (err = dav_remote_method_request(r, "PUT", resource_uri, resource_path, resource,
3058
			dav_remote_send_resource_content, (void *)resource,
3059
			NULL, NULL))) {
3060
		return dav_push_error(r->pool, err->status, 0, "PUT failed.", err);
3061
	}
3062
3063
	if (r->status != HTTP_CREATED && r->status != HTTP_NO_CONTENT)
3064
		return dav_new_error(r->pool, r->status, 0, "Remote server does not accept resource");
3065
	else
3066
		return NULL;
3067
}
3068
3069
DAV_DECLARE(dav_error *) dav_remote_resource_lock(request_rec *r, apr_uri_t *resource_uri,
3070
		const char *resource_path, const dav_resource *resource, const char *owner, dav_remote_lock_token *token)
3071
{
3072
	dav_error *err;
3073
	char *content;
3074
	apr_xml_doc *xmlDoc;
3075
3076
	token->token = NULL;
3077
	token->path = NULL;
3078
3079
	if (NULL != (err = dav_remote_set_connection(r, resource_uri))) {
3080
		return dav_push_error(r->pool, err->status, 0, "Unable to create connection in dav_remote_resource_delete.", err);
3081
	}
3082
3083
	// create LOCK request
3084
	content = apr_pstrcat(r->pool,
3085
			"<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n"
3086
			"<D:lockinfo xmlns:D='DAV:'>\n"
3087
			"  <D:lockscope><D:exclusive/></D:lockscope>\n"
3088
			"  <D:locktype><D:write/></D:locktype>\n"
3089
			"  <D:owner>\n"
3090
			"       <D:href>", owner, "</D:href>\n"
3091
			"  </D:owner>\n"
3092
			"</D:lockinfo>",
3093
			NULL
3094
	);
3095
3096
	apr_table_clear(r->headers_out);
3097
	apr_table_add(r->headers_out, "Host", resource_uri->hostname);
3098
	apr_table_add(r->headers_out, "Content-Type", "text/xml; charset=\"utf-8\"");
3099
	apr_table_add(r->headers_out, "Content-Length", apr_itoa(r->pool, strlen(content)));
3100
	apr_table_add(r->headers_out, "Connection", "Keep-Alive");
3101
	apr_table_add(r->headers_out, "Depth", "Infinity");
3102
	// only LOCK null resources
3103
	apr_table_add(r->headers_out, "If-None-Match", "*");
3104
3105
	if (NULL != (err = dav_remote_method_request(r, "LOCK", resource_uri, resource_path, resource,
3106
			dav_remote_send_string, content,
3107
			NULL, NULL))) {
3108
		return dav_push_error(r->pool, err->status, 0, "LOCK failed.", err);
3109
	}
3110
3111
	if (r->status == HTTP_OK) {
3112
		token->token = apr_table_get(r->headers_in, "Lock-Token");
3113
		token->path = apr_pstrdup(r->pool, resource_uri->path);
3114
		return NULL;
3115
	}
3116
3117
	if (r->status == HTTP_PRECONDITION_FAILED) {
3118
		return dav_new_error(r->pool, r->status, 0, "Resource already locked");
3119
	}
3120
3121
	return NULL;
3122
}
3123
3124
DAV_DECLARE(dav_error *) dav_remote_resource_unlock(request_rec *r, apr_uri_t *resource_uri,
3125
		const char *resource_path, const dav_resource *resource, dav_remote_lock_token *token)
3126
{
3127
	dav_error *err;
3128
	apr_xml_doc *xmlDoc;
3129
	char *content;
3130
3131
	if (NULL == token->token || NULL == token->path)
3132
		return 0; // no need
3133
3134
	if (NULL != (err = dav_remote_set_connection(r, resource_uri))) {
3135
		return dav_push_error(r->pool, err->status, 0, "Unable to create connection in dav_remote_resource_delete.", err);
3136
	}
3137
3138
	apr_table_clear(r->headers_out);
3139
	apr_table_add(r->headers_out, "Host", resource_uri->hostname);
3140
	apr_table_add(r->headers_out, "Connection", "Keep-Alive");
3141
	apr_table_add(r->headers_out, "Depth", "Infinity");
3142
	apr_table_add(r->headers_out, "Lock-Token", token->token);
3143
3144
	if (NULL != (err = dav_remote_method_request(r, "UNLOCK", resource_uri, resource_path, resource,
3145
			NULL, NULL,
3146
			NULL, NULL))) {
3147
		return dav_push_error(r->pool, err->status, 0, "UNLOCK failed.", err);
3148
	}
3149
3150
	if (r->status != HTTP_NO_CONTENT) {
3151
		return dav_new_error(r->pool, r->status, 0, "Unable to unlock resource");
3152
	}
3153
3154
	return NULL;
3155
}
3156
3157
DAV_DECLARE(dav_error *) dav_remote_resource_proppatch(request_rec *source_r, request_rec *r, apr_uri_t *resource_uri,
3158
		const char *resource_path, const dav_resource *resource, dav_remote_lock_token token, dav_lockdb *lockdb)
3159
{
3160
	dav_error *err;
3161
    const dav_hooks_db *prop_db_hooks;
3162
    const dav_db *prop_db;
3163
    dav_prop_name name;
3164
	char *content;
3165
	apr_text_header hdr = { 0 };
3166
    apr_text_header hdr_ns = { 0 };
3167
3168
	prop_db_hooks = DAV_GET_HOOKS_PROPDB(r);
3169
	if (NULL == prop_db_hooks) {
3170
		return NULL; // nothing to do
3171
	}
3172
3173
	if (NULL != (err = prop_db_hooks->open(r->pool, resource, 1, &prop_db))) {
3174
		return err;
3175
	}
3176
3177
	if (NULL == prop_db)
3178
		return NULL; // nothing to do
3179
3180
	if (NULL != (err = prop_db_hooks->first_name(prop_db, &name))) {
3181
		prop_db_hooks->close(prop_db);
3182
		return err;
3183
	}
3184
3185
	dav_xmlns_info *xi = dav_xmlns_create(r->pool);
3186
3187
	if (NULL != (err = (*prop_db_hooks->define_namespaces)(prop_db, xi))) {
3188
		prop_db_hooks->close(prop_db);
3189
		return err;
3190
	}
3191
3192
	while (NULL != name.ns) {
3193
        int found;
3194
3195
        if (NULL != (err = (*prop_db_hooks->output_value)(prop_db, &name,
3196
        		xi, &hdr, &found))) {
3197
    		prop_db_hooks->close(prop_db);
3198
        	return err;
3199
        }
3200
3201
		if (NULL != (err = prop_db_hooks->next_name(prop_db, &name))) {
3202
			prop_db_hooks->close(prop_db);
3203
			return err;
3204
		}
3205
	}
3206
3207
    dav_xmlns_generate(xi, &hdr_ns);
3208
3209
3210
	// create LOCK request
3211
	content = apr_pstrcat(r->pool,
3212
			"<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n"
3213
			"<D:propertyupdate xmlns:D=\"DAV:\"", NULL);
3214
3215
    apr_text *text = hdr_ns.first;
3216
    while (text) {
3217
    	content = apr_pstrcat(r->pool, content, text->text, NULL);
3218
    	text = text->next;
3219
    }
3220
3221
	content = apr_pstrcat(r->pool, content, ">\n"
3222
			"  <D:set>\n"
3223
			"    <D:prop>\n",
3224
			NULL
3225
	);
3226
3227
    text = hdr.first;
3228
    while (text) {
3229
    	content = apr_pstrcat(r->pool, content, "      ", text->text, NULL);
3230
    	text = text->next;
3231
    }
3232
3233
    content = apr_pstrcat(r->pool, content,
3234
			"    </D:prop>\n"
3235
			"  </D:set>\n"
3236
			"</D:propertyupdate>\n",
3237
			NULL
3238
	);
3239
3240
	apr_table_clear(r->headers_out);
3241
	apr_table_add(r->headers_out, "Host", resource_uri->hostname);
3242
	apr_table_add(r->headers_out, "Connection", "Keep-Alive");
3243
	apr_table_add(r->headers_out, "Content-Length", apr_itoa(r->pool, strlen(content)));
3244
	apr_table_add(r->headers_out, "Content-Type", "text/xml; charset=\"utf-8\"");
3245
3246
	if (token.token && token.path) {
3247
		apr_table_add(r->headers_out, "If", apr_pstrcat(r->pool, "<", token.path, "> (", token.token, ")", NULL));
3248
	}
3249
3250
	if (NULL != (err = dav_remote_method_request(r, "PROPPATCH", resource_uri, resource_path, resource,
3251
			dav_remote_send_string, content,
3252
			NULL, NULL))) {
3253
		return dav_push_error(r->pool, err->status, 0, "PROPATCH failed.", err);
3254
	}
3255
3256
	if (r->status != HTTP_NO_CONTENT && r->status != HTTP_MULTI_STATUS) {
3257
		return dav_new_error(r->pool, r->status, 0, "Unable to unlock resource");
3258
	}
3259
3260
	return NULL;
3261
}
3262
3263
struct dav_remote_copymove_copy_walk_ctx
3264
{
3265
	request_rec *source_r;
3266
	request_rec *r;
3267
	const char *base_uri;
3268
	apr_uri_t *dest_uri;
3269
	const char *dest;
3270
	dav_remote_lock_token token;
3271
	int overwrite;
3272
	dav_lockdb *lockdb;
3273
};
3274
3275
DAV_DECLARE(dav_error *) dav_remote_copymove_walk(dav_walk_resource *wres, int calltype)
3276
{
3277
	struct dav_remote_copymove_copy_walk_ctx *ctx = (struct dav_remote_copymove_copy_walk_ctx *)wres->walk_ctx;
3278
	char *new_resource_path;
3279
	apr_uri_t new_resource_uri;
3280
	dav_error *err;
3281
	int remove_length;
3282
3283
	if (strncmp(wres->resource->uri, ctx->base_uri, strlen(ctx->base_uri)) != 0) {
3284
		return dav_new_error(wres->pool, HTTP_INTERNAL_SERVER_ERROR, 0, "Invalid uri of subresource");
3285
	}
3286
3287
	remove_length = strlen(ctx->base_uri);
3288
	if (wres->resource->collection) {
3289
		remove_length++;
3290
	}
3291
3292
	new_resource_path = apr_pstrcat(wres->pool, ctx->dest, &(wres->resource->uri[remove_length]), NULL);
3293
	printf("from %s and %s on base %s done: %s\n", ctx->dest, wres->resource->uri, ctx->base_uri, new_resource_path);
3294
3295
	// shallow copy, only cange the path
3296
	new_resource_uri = *ctx->dest_uri;
3297
	new_resource_uri.path = apr_pstrcat(wres->pool, ctx->dest_uri->path, &(wres->resource->uri[remove_length]), NULL);
3298
3299
	if (wres->resource->collection) {
3300
		// for lock-token...
3301
		new_resource_path[strlen(new_resource_path) - 1] = '\0';
3302
		new_resource_uri.path[strlen(new_resource_uri.path) - 1] = '\0';
3303
3304
		if (NULL != (err = dav_remote_resource_mkcol(ctx->r, &new_resource_uri, new_resource_path, wres->resource, ctx->overwrite, ctx->token)))
3305
			return err;
3306
	} else {
3307
		if (NULL != (err = dav_remote_resource_put(ctx->r, &new_resource_uri, new_resource_path, wres->resource, ctx->overwrite, ctx->token)))
3308
			return err;
3309
	}
3310
3311
	if (NULL != (err = dav_remote_resource_proppatch(ctx->source_r, ctx->r, ctx->dest_uri,
3312
			ctx->dest, wres->resource, ctx->token, ctx->lockdb))) {
3313
		return err;
3314
	}
3315
3316
	return NULL;
3317
}
3318
3319
DAV_DECLARE(dav_error *) dav_remote_copymove(request_rec *r, dav_resource *resource,
3320
		const char *dest, int overwrite, int depth, dav_lockdb *lockdb)
3321
{
3322
	dav_error *err = NULL;
3323
	dav_error *lock_err = NULL;
3324
	apr_uri_t dest_uri;
3325
	conn_rec *conn;
3326
    request_rec *rp;
3327
    int exists;
3328
	int deleted;
3329
	dav_walk_params walk_params = { 0 };
3330
	dav_response *response;
3331
	const char *lock_owner;
3332
	dav_remote_lock_token token;
3333
3334
    if (APR_SUCCESS != apr_uri_parse(r->pool, dest, &dest_uri)) {
3335
        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
3336
                      "Destination URI cannot be parsed.", NULL);
3337
        return dav_new_error(r->pool, HTTP_BAD_REQUEST, 0, "Destination URI cannot be parsed.");
3338
    }
3339
3340
    if (!dest_uri.port) {
3341
    	dest_uri.port = apr_uri_port_of_scheme(dest_uri.scheme);
3342
    }
3343
3344
    // 1. create request
3345
    rp = dav_remote_make_fake_request(r);
3346
3347
   	if (!overwrite) {
3348
   	    // 2. check if exists
3349
   	   	if (NULL != (err = dav_remote_resource_exists(rp, &dest_uri, dest, resource, &exists))) {
3350
   	   		return err;
3351
   	   	}
3352
3353
   	   	if (exists) {
3354
   	        return dav_new_error(r->pool, HTTP_PRECONDITION_FAILED, 0, "Destination resource already exists.");
3355
   	   	}
3356
    }
3357
   	else {
3358
   		// 2. delete old resource
3359
   		if (NULL != (err = dav_remote_resource_delete(rp, &dest_uri, dest, resource))) {
3360
   			return err;
3361
   		}
3362
   	}
3363
3364
   	// 3. gain lock on NULL resource
3365
   	lock_owner = r->unparsed_uri;
3366
   	if (NULL != (err = dav_remote_resource_lock(rp, &dest_uri, dest, resource, lock_owner, &token))) {
3367
   		return err;
3368
	}
3369
3370
   	struct dav_remote_copymove_copy_walk_ctx ctx;
3371
	ctx.source_r = r;
3372
	ctx.r = rp;
3373
	ctx.base_uri = resource->uri;
3374
	ctx.dest_uri = &dest_uri;
3375
	ctx.dest = dest;
3376
	ctx.overwrite = overwrite;
3377
	ctx.token = token;
3378
	ctx.lockdb = lockdb;
3379
3380
   	walk_params.walk_type = DAV_WALKTYPE_AUTH | DAV_WALKTYPE_NORMAL;
3381
   	walk_params.func = dav_remote_copymove_walk;
3382
   	walk_params.walk_ctx = &ctx;
3383
   	walk_params.pool = r->pool;
3384
   	walk_params.root = resource;
3385
3386
   	// 4. copy resources/collections
3387
   	err = (*resource->hooks->walk)(&walk_params, depth, &response);
3388
3389
   	// 5. release lock
3390
   	if (NULL != (err = dav_remote_resource_unlock(rp, &dest_uri, dest, resource, &token))) {
3391
   		return err;
3392
	}
3393
3394
	return NULL;
3395
}
3396
2553
/* handle the COPY and MOVE methods */
3397
/* handle the COPY and MOVE methods */
2554
static int dav_method_copymove(request_rec *r, int is_move)
3398
static int dav_method_copymove(request_rec *r, int is_move)
2555
{
3399
{
Lines 2559-2567 Link Here
2559
    dav_auto_version_info dst_av_info = { 0 };
3403
    dav_auto_version_info dst_av_info = { 0 };
2560
    const char *body;
3404
    const char *body;
2561
    const char *dest;
3405
    const char *dest;
2562
    dav_error *err;
3406
    dav_error *err = NULL;
2563
    dav_error *err2;
3407
    dav_error *err2 = NULL;
2564
    dav_error *err3;
3408
    dav_error *err3 = NULL;
2565
    dav_response *multi_response;
3409
    dav_response *multi_response;
2566
    dav_lookup_result lookup;
3410
    dav_lookup_result lookup;
2567
    int is_dir;
3411
    int is_dir;
Lines 2571-2576 Link Here
2571
    dav_lockdb *lockdb;
3415
    dav_lockdb *lockdb;
2572
    int replace_dest;
3416
    int replace_dest;
2573
    int resnew_state;
3417
    int resnew_state;
3418
    int remote = 0;
2574
3419
2575
    /* Ask repository module to resolve the resource */
3420
    /* Ask repository module to resolve the resource */
2576
    err = dav_get_resource(r, !is_move /* label_allowed */,
3421
    err = dav_get_resource(r, !is_move /* label_allowed */,
Lines 2609-2614 Link Here
2609
        return HTTP_BAD_REQUEST;
3454
        return HTTP_BAD_REQUEST;
2610
    }
3455
    }
2611
3456
3457
    /* get and parse the overwrite header value */
3458
    if ((overwrite = dav_get_overwrite(r)) < 0) {
3459
        /* dav_get_overwrite() supplies additional information for the
3460
         * default message. */
3461
        return HTTP_BAD_REQUEST;
3462
    }
3463
2612
    lookup = dav_lookup_uri(dest, r, 1 /* must_be_absolute */);
3464
    lookup = dav_lookup_uri(dest, r, 1 /* must_be_absolute */);
2613
    if (lookup.rnew == NULL) {
3465
    if (lookup.rnew == NULL) {
2614
        if (lookup.err.status == HTTP_BAD_REQUEST) {
3466
        if (lookup.err.status == HTTP_BAD_REQUEST) {
Lines 2618-2628 Link Here
2618
            return HTTP_BAD_REQUEST;
3470
            return HTTP_BAD_REQUEST;
2619
        }
3471
        }
2620
3472
3473
        if (lookup.err.status == HTTP_BAD_GATEWAY) {
3474
            err = dav_get_resource(r, 1 /* label_allowed */, 0 /* use_checked_in */,
3475
                                   &resource);
3476
            remote = 1;
3477
        }
3478
3479
        if (!remote) {
2621
        /* ### this assumes that dav_lookup_uri() only generates a status
3480
        /* ### this assumes that dav_lookup_uri() only generates a status
2622
         * ### that Apache can provide a status line for!! */
3481
         * ### that Apache can provide a status line for!! */
2623
3482
2624
        return dav_error_response(r, lookup.err.status, lookup.err.desc);
3483
        return dav_error_response(r, lookup.err.status, lookup.err.desc);
2625
    }
3484
    }
3485
    }
3486
3487
    if (!remote) {
2626
    if (lookup.rnew->status != HTTP_OK) {
3488
    if (lookup.rnew->status != HTTP_OK) {
2627
        const char *auth = apr_table_get(lookup.rnew->err_headers_out,
3489
        const char *auth = apr_table_get(lookup.rnew->err_headers_out,
2628
                                        "WWW-Authenticate");
3490
                                        "WWW-Authenticate");
Lines 2651-2671 Link Here
2651
3513
2652
    /* are the two resources handled by the same repository? */
3514
    /* are the two resources handled by the same repository? */
2653
    if (resource->hooks != resnew->hooks) {
3515
    if (resource->hooks != resnew->hooks) {
2654
        /* ### this message exposes some backend config, but screw it... */
3516
    		err = dav_get_resource(r, 1 /* label_allowed */, 0 /* use_checked_in */,
2655
        return dav_error_response(r, HTTP_BAD_GATEWAY,
3517
                               &resource);
2656
                                  "Destination URI is handled by a "
3518
    		remote = 1;
2657
                                  "different repository than the source URI. "
2658
                                  "MOVE or COPY between repositories is "
2659
                                  "not possible.");
2660
    }
3519
    }
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
    }
3520
    }
2668
3521
3522
    // recheck remote, maybe it changed
3523
    if (!remote) {
2669
    /* quick failure test: if dest exists and overwrite is false. */
3524
    /* quick failure test: if dest exists and overwrite is false. */
2670
    if (resnew->exists && !overwrite) {
3525
    if (resnew->exists && !overwrite) {
2671
        /* Supply some text for the error response body. */
3526
        /* Supply some text for the error response body. */
Lines 2679-2685 Link Here
2679
        /* Supply some text for the error response body. */
3534
        /* Supply some text for the error response body. */
2680
        return dav_error_response(r, HTTP_FORBIDDEN,
3535
        return dav_error_response(r, HTTP_FORBIDDEN,
2681
                                  "Source and Destination URIs are the same.");
3536
                                  "Source and Destination URIs are the same.");
2682
3537
    	}
2683
    }
3538
    }
2684
3539
2685
    is_dir = resource->collection;
3540
    is_dir = resource->collection;
Lines 2732-2737 Link Here
2732
        return dav_handle_err(r, err, multi_response);
3587
        return dav_handle_err(r, err, multi_response);
2733
    }
3588
    }
2734
3589
3590
    if (!remote)
3591
    {
2735
    /*
3592
    /*
2736
     * Check If-Headers and existing locks for destination. Note that we
3593
     * Check If-Headers and existing locks for destination. Note that we
2737
     * use depth==infinity since the target (hierarchy) will be deleted
3594
     * use depth==infinity since the target (hierarchy) will be deleted
Lines 2778-2783 Link Here
2778
                                  "Destination collection contains the Source "
3635
                                  "Destination collection contains the Source "
2779
                                  "and Overwrite has been specified.");
3636
                                  "and Overwrite has been specified.");
2780
    }
3637
    }
3638
    }
2781
3639
2782
    /* ### for now, we don't need anything in the body */
3640
    /* ### for now, we don't need anything in the body */
2783
    if ((result = ap_discard_request_body(r)) != OK) {
3641
    if ((result = ap_discard_request_body(r)) != OK) {
Lines 2818-2823 Link Here
2818
        }
3676
        }
2819
    }
3677
    }
2820
3678
3679
    if (!remote)
3680
    {
2821
    /*
3681
    /*
2822
     * Remember the initial state of the destination, so the lock system
3682
     * Remember the initial state of the destination, so the lock system
2823
     * can be notified as to how it changed.
3683
     * can be notified as to how it changed.
Lines 2894-2906 Link Here
2894
    /* perform any auto-versioning cleanup */
3754
    /* perform any auto-versioning cleanup */
2895
    err2 = dav_auto_checkin(r, NULL, err != NULL /* undo if error */,
3755
    err2 = dav_auto_checkin(r, NULL, err != NULL /* undo if error */,
2896
                            0 /*unlock*/, &dst_av_info);
3756
                            0 /*unlock*/, &dst_av_info);
3757
    }
2897
3758
2898
    if (is_move) {
3759
    if (is_move) {
2899
        err3 = dav_auto_checkin(r, NULL, err != NULL /* undo if error */,
3760
        err3 = dav_auto_checkin(r, NULL, err != NULL /* undo if error */,
2900
                                0 /*unlock*/, &src_av_info);
3761
                                0 /*unlock*/, &src_av_info);
2901
    }
3762
    }
2902
    else
2903
        err3 = NULL;
2904
3763
2905
    /* check for error from remove/copy/move operations */
3764
    /* check for error from remove/copy/move operations */
2906
    if (err != NULL) {
3765
    if (err != NULL) {
Lines 2935-2940 Link Here
2935
        dav_log_err(r, err, APLOG_WARNING);
3794
        dav_log_err(r, err, APLOG_WARNING);
2936
    }
3795
    }
2937
3796
3797
    if (!remote) {
2938
    /* propagate any indirect locks at the target */
3798
    /* propagate any indirect locks at the target */
2939
    if (lockdb != NULL) {
3799
    if (lockdb != NULL) {
2940
3800
Lines 2953-2962 Link Here
2953
            return dav_handle_err(r, err, NULL);
3813
            return dav_handle_err(r, err, NULL);
2954
        }
3814
        }
2955
    }
3815
    }
3816
    }
3817
3818
    if (remote) {
3819
    	if (NULL != (err = dav_remote_copymove(r, resource, dest, overwrite, depth, lockdb))) {
3820
    		return dav_handle_err(r, err, NULL);
3821
    	}
3822
3823
    	if (is_move) {
3824
    		if (NULL != (err = (*resource->hooks->remove_resource)(resource, &multi_response))) {
3825
    			return dav_handle_err(r, err, NULL);
3826
    		}
3827
    	}
3828
3829
    	if (lockdb != NULL) {
3830
    		(*lockdb->hooks->close_lockdb)(lockdb);
3831
    	}
2956
3832
2957
    /* return an appropriate response (HTTP_CREATED or HTTP_NO_CONTENT) */
3833
    /* return an appropriate response (HTTP_CREATED or HTTP_NO_CONTENT) */
3834
    	return dav_created(r, dest, "Destination", 0);
3835
    }
3836
    if (!remote) {
3837
    	/* return an appropriate response (HTTP_CREATED or HTTP_NO_CONTENT) */
2958
    return dav_created(r, lookup.rnew->uri, "Destination",
3838
    return dav_created(r, lookup.rnew->uri, "Destination",
2959
                       resnew_state == DAV_RESOURCE_EXISTS);
3839
                       resnew_state == DAV_RESOURCE_EXISTS);
3840
    }
2960
}
3841
}
2961
3842
2962
/* dav_method_lock:  Handler to implement the DAV LOCK method
3843
/* 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