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 (-13 / +559 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 2550-2555 Link Here
2550
    return dav_created(r, NULL, "Collection", 0);
2551
    return dav_created(r, NULL, "Collection", 0);
2551
}
2552
}
2552
2553
2554
DAV_DECLARE(dav_error *) dav_remote_copymove_create_socket(apr_pool_t *p, apr_sockaddr_t *addr, apr_socket_t **newsock)
2555
{
2556
	apr_status_t rv;
2557
2558
	while (addr) {
2559
        if ((rv = apr_socket_create(newsock, addr->family,
2560
                                    SOCK_STREAM, 0, p)) != APR_SUCCESS) {
2561
            /*
2562
             * this could be an IPv6 address from the DNS but the
2563
             * local machine won't give us an IPv6 socket; hopefully the
2564
             * DNS returned an additional address to try
2565
             */
2566
            addr = addr->next;
2567
            continue;
2568
        }
2569
2570
        rv = apr_socket_connect(*newsock, addr);
2571
2572
        /* if an error occurred, loop round and try again */
2573
        if (rv != APR_SUCCESS) {
2574
            apr_socket_close(*newsock);
2575
            addr = addr->next;
2576
            continue;
2577
        }
2578
2579
        return 0;
2580
	}
2581
2582
	// TODO: good error code?
2583
	return dav_new_error(p, HTTP_INTERNAL_SERVER_ERROR, 0, "Socket creating failed");
2584
}
2585
2586
DAV_DECLARE(dav_error *) dav_remote_create_connection(apr_pool_t *p, apr_uri_t *uri, server_rec *s, conn_rec **conn)
2587
{
2588
	apr_status_t rv;
2589
	apr_sockaddr_t *src_addr;
2590
	apr_socket_t *socket;
2591
	dav_error *err;
2592
2593
	rv = apr_sockaddr_info_get(&src_addr, uri->hostname, APR_UNSPEC, uri->port, 0, p);
2594
    if (APR_SUCCESS != rv) {
2595
        return dav_new_error(p, HTTP_BAD_REQUEST, 0, apr_pstrcat(p, "DNS lookup failure for: ", uri->hostname, NULL));
2596
    }
2597
2598
	if (NULL != (err = dav_remote_copymove_create_socket(p, src_addr, &socket))) {
2599
		return err;
2600
	}
2601
2602
	*conn = (conn_rec *)ap_run_create_connection(p, s, socket, 0, NULL, apr_bucket_alloc_create(p));
2603
2604
	if (!*conn) {
2605
		// will it have memory to create error message? i guess not, let the caller check!
2606
		return 0;
2607
	}
2608
2609
    /* set up the connection filters */
2610
    rv = ap_run_pre_connection(*conn, socket);
2611
    if (rv != OK && rv != DONE) {
2612
        (*conn)->aborted = 1;
2613
        return dav_new_error(p, HTTP_INTERNAL_SERVER_ERROR, 0, "pre_connection setup failed");
2614
    }
2615
2616
	return 0;
2617
}
2618
2619
DAV_DECLARE(dav_error *) dav_remote_close_connection(request_rec *r)
2620
{
2621
	// TODO: find a better way to do it
2622
	r->connection = 0;
2623
}
2624
2625
DAV_DECLARE(request_rec *) dav_remote_make_fake_request(request_rec *r)
2626
{
2627
	request_rec *rp = apr_pcalloc(r->pool, sizeof(*r));
2628
2629
    rp->pool            = r->pool;
2630
    rp->status          = HTTP_OK;
2631
2632
    rp->headers_in      = apr_table_make(r->pool, 12);
2633
    rp->subprocess_env  = apr_table_make(r->pool, 12);
2634
    rp->headers_out     = apr_table_make(r->pool, 12);
2635
    rp->err_headers_out = apr_table_make(r->pool, 5);
2636
    rp->notes           = apr_table_make(r->pool, 5);
2637
2638
    rp->server = r->server;
2639
    rp->proxyreq = r->proxyreq;
2640
    rp->request_time = r->request_time;
2641
2642
    rp->connection = 0;
2643
2644
    rp->request_config = ap_create_request_config(r->pool);
2645
    rp->per_dir_config = r->per_dir_config; // hope it will not crash
2646
}
2647
2648
DAV_DECLARE(dav_error *) dav_remote_set_connection(request_rec *r, apr_uri_t *resource_uri)
2649
{
2650
	dav_error *err;
2651
	conn_rec *conn;
2652
2653
	if (r->connection) {
2654
		return 0;
2655
	}
2656
	if (NULL != (err = dav_remote_create_connection(r->pool, resource_uri, r->server, &conn))) {
2657
		return err;
2658
	}
2659
2660
	r->connection      = conn;
2661
	r->output_filters  = conn->output_filters;
2662
	r->input_filters   = conn->input_filters;
2663
	r->proto_output_filters  = conn->output_filters;
2664
	r->proto_input_filters   = conn->input_filters;
2665
2666
	return 0;
2667
}
2668
2669
DAV_DECLARE(dav_error *) dav_remote_send_resource_content(request_rec *r, dav_resource *resource)
2670
{
2671
	dav_error *err;
2672
	apr_bucket_brigade *request_brigade;
2673
	apr_bucket *e;
2674
	apr_status_t rv;
2675
2676
    /* okay... time to deliver the content */
2677
    if ((err = (*resource->hooks->deliver)(resource,
2678
                                           r->output_filters)) != NULL) {
2679
        return dav_push_error(r->pool, err->status, 0,
2680
                             "Unable to deliver content.",
2681
                             err);
2682
    }
2683
2684
	request_brigade =  apr_brigade_create(r->pool, r->connection->bucket_alloc);
2685
2686
	e = apr_bucket_flush_create(r->connection->bucket_alloc);
2687
	APR_BRIGADE_INSERT_TAIL(request_brigade, e);
2688
2689
    rv = ap_pass_brigade(r->output_filters, request_brigade);
2690
2691
    return NULL;
2692
}
2693
2694
struct dav_remote_send_headers_wrapper {
2695
	apr_bucket_alloc_t *bucket_alloc;
2696
	apr_bucket_brigade *request_brigade;
2697
	apr_pool_t *p;
2698
};
2699
2700
int dav_remote_send_headers(void *rec, const char *key, const char *value)
2701
{
2702
	struct dav_remote_send_headers_wrapper *wrapper = (struct dav_remote_send_headers_wrapper *)rec;
2703
2704
	apr_bucket_brigade *request_brigade = wrapper->request_brigade;
2705
	apr_bucket *e;
2706
	char *buf;
2707
2708
	buf = apr_pstrcat(wrapper->p, key, ": ", value, CRLF, NULL);
2709
	e = apr_bucket_pool_create(buf, strlen(buf), wrapper->p, wrapper->bucket_alloc);
2710
	ap_xlate_proto_to_ascii(buf, strlen(buf));
2711
	APR_BRIGADE_INSERT_TAIL(request_brigade, e);
2712
}
2713
2714
DAV_DECLARE(dav_error *) dav_remote_read_status_line(request_rec *r)
2715
{
2716
    apr_bucket_brigade *response_brigade;
2717
2718
    char buff[HUGE_STRING_LEN];
2719
	char *buff_p = buff;
2720
	char keepchar;
2721
	apr_size_t len;
2722
2723
    response_brigade = apr_brigade_create(r->pool, r->connection->bucket_alloc);
2724
    ap_rgetline(&buff_p, sizeof(buff), &len, r, 0, response_brigade);
2725
2726
    if (!apr_date_checkmask(buff, "HTTP/#.# ###*")) {
2727
    	return dav_new_error(r->pool, HTTP_BAD_GATEWAY, 0, "Invalid response status line");
2728
    }
2729
2730
    int major, minor;
2731
2732
    if (2 != sscanf(buff, "HTTP/%u.%u", &major, &minor)) {
2733
        major = 1;
2734
        minor = 1;
2735
    }
2736
    else if ((buff[5] != '1') || (len >= sizeof(buff) - 1)) {
2737
        return dav_new_error(r->pool, HTTP_BAD_GATEWAY, 0, "Invalid response status line");
2738
    }
2739
2740
    keepchar = buff[12];
2741
    buff[12] = '\0';
2742
    r->status = atoi(&buff[9]);
2743
2744
    if (keepchar != '\0') {
2745
     	buff[12] = keepchar;
2746
    } else {
2747
        /* 2616 requires the space in Status-Line; the origin
2748
         * server may have sent one but ap_rgetline_core will
2749
         * have stripped it. */
2750
    	buff[12] = ' ';
2751
        buff[13] = '\0';
2752
    }
2753
    r->status_line = apr_pstrdup(r->pool, &buff[9]);
2754
2755
    return 0;
2756
}
2757
2758
DAV_DECLARE(dav_error *) dav_remote_read_response_headers(request_rec *r)
2759
{
2760
	dav_error *err;
2761
    apr_bucket_brigade *response_brigade;
2762
	apr_size_t len;
2763
	apr_status_t rv;
2764
    char buff[HUGE_STRING_LEN];
2765
	char *buff_p = buff;
2766
	char *value, *end;
2767
2768
	apr_table_clear(r->headers_in);
2769
2770
	response_brigade = apr_brigade_create(r->pool, r->connection->bucket_alloc);
2771
    if (APR_SUCCESS != (rv = ap_rgetline(&buff_p, sizeof(buff), &len, r, 0, response_brigade))) {
2772
    	return dav_new_error(r->pool, HTTP_BAD_GATEWAY, 0, "Error reading response header");
2773
    }
2774
2775
    while (0 < len) {
2776
    	if (!(value = strchr(buff, ':'))) {
2777
    	    if (APR_SUCCESS != (rv = ap_rgetline(&buff_p, sizeof(buff), &len, r, 0, response_brigade))) {
2778
    	    	return dav_new_error(r->pool, HTTP_BAD_GATEWAY, 0, "Error reading response header");
2779
    	    }
2780
    	}
2781
2782
        *value = '\0';
2783
        ++value;
2784
        /* XXX: RFC2068 defines only SP and HT as whitespace, this test is
2785
         * wrong... and so are many others probably.
2786
         */
2787
        while (apr_isspace(*value))
2788
            ++value;            /* Skip to start of value   */
2789
2790
        /* should strip trailing whitespace as well */
2791
        for (end = &value[strlen(value)-1]; end > value && apr_isspace(*end); --end)
2792
            *end = '\0';
2793
2794
        apr_table_add(r->headers_in, buff, value);
2795
2796
	    if (APR_SUCCESS != (rv = ap_rgetline(&buff_p, sizeof(buff), &len, r, 0, response_brigade))) {
2797
	    	return dav_new_error(r->pool, HTTP_BAD_GATEWAY, 0, "Error reading response header");
2798
	    }
2799
    }
2800
2801
    return 0;
2802
}
2803
2804
typedef dav_error * (* write_request_content_callback) (request_rec *, void *data);
2805
typedef dav_error * (* read_reponse_content_callback) (request_rec *, void *data);
2806
2807
DAV_DECLARE(dav_error *) dav_remote_skip_response_content(request_rec *r, void *unused)
2808
{
2809
	apr_size_t content_length;
2810
	apr_size_t to_read;
2811
    apr_bucket_brigade *response_brigade;
2812
    apr_bucket *e;
2813
    int seen_eos;
2814
	const char *content_length_str;
2815
    apr_bucket_alloc_t *bucket_alloc = r->connection->bucket_alloc;
2816
	char buff[HUGE_STRING_LEN];
2817
    char *buff_p = buff;
2818
2819
	if (NULL == apr_table_get(r->headers_in, "Keep-Alive")) { // we can close the connection now
2820
		dav_remote_close_connection(r);
2821
		return 0;
2822
	}
2823
2824
	content_length_str = apr_table_get(r->headers_in, "Content-Length");
2825
	if (!content_length_str) {
2826
		return 0; // no content
2827
	}
2828
2829
	content_length = atoi(content_length_str);
2830
	if (!content_length) {
2831
		return 0; // no content
2832
	}
2833
2834
	if (content_length < 0) {
2835
		dav_remote_close_connection(r);
2836
		return dav_new_error(r->pool, HTTP_BAD_GATEWAY, 0, "Invalid Content-Length of response");
2837
	}
2838
2839
	while (0 < content_length) {
2840
		response_brigade = apr_brigade_create(r->pool, bucket_alloc);
2841
2842
        do {
2843
            apr_status_t rc;
2844
2845
            rc = ap_get_brigade(r->input_filters, response_brigade, AP_MODE_READBYTES,
2846
                                APR_BLOCK_READ, DAV_READ_BLOCKSIZE);
2847
2848
            if (rc != APR_SUCCESS) {
2849
                return dav_new_error(r->pool, HTTP_INTERNAL_SERVER_ERROR, 0,
2850
                                    "Could not get next bucket brigade");
2851
            }
2852
2853
            for (e = APR_BRIGADE_FIRST(response_brigade);
2854
                 e != APR_BRIGADE_SENTINEL(response_brigade);
2855
                 e = APR_BUCKET_NEXT(e))
2856
            {
2857
                const char *data;
2858
                apr_size_t len;
2859
2860
                if (APR_BUCKET_IS_EOS(e)) {
2861
                    seen_eos = 1;
2862
                    break;
2863
                }
2864
2865
                if (APR_BUCKET_IS_METADATA(e)) {
2866
                    continue;
2867
                }
2868
2869
                rc = apr_bucket_read(e, &data, &len, APR_BLOCK_READ);
2870
                content_length -= len;
2871
2872
                if (rc != APR_SUCCESS) {
2873
                    return dav_new_error(r->pool, HTTP_BAD_REQUEST, 0,
2874
                                        "An error occurred while reading "
2875
                                        "the request body.");
2876
                }
2877
            }
2878
2879
            apr_brigade_cleanup(response_brigade);
2880
        } while (!seen_eos);
2881
2882
2883
2884
	}
2885
2886
	return 0;
2887
}
2888
2889
DAV_DECLARE(dav_error *) dav_remote_method_request(request_rec *r, const char *method, apr_uri_t *resource_uri,
2890
		const char *resource_path, dav_resource *resource,
2891
		write_request_content_callback write_request_content, void *write_request_content_data,
2892
		read_reponse_content_callback read_response_content, void *read_response_content_data)
2893
{
2894
    apr_status_t rv;
2895
    dav_error *err;
2896
    apr_bucket_alloc_t *bucket_alloc = r->connection->bucket_alloc;
2897
    apr_bucket_brigade *request_brigade;
2898
    apr_bucket *e;
2899
	char *buf;
2900
2901
	// as I see nobody in httpd check for NULL results of malloc/apr_palloc, so why I should?
2902
    request_brigade = apr_brigade_create(r->pool, bucket_alloc);
2903
2904
	buf = apr_pstrcat(r->pool, method, " ", resource_uri->path, " HTTP/1.1", CRLF, NULL);
2905
	e = apr_bucket_pool_create(buf, strlen(buf), r->pool, bucket_alloc);
2906
	ap_xlate_proto_to_ascii(buf, strlen(buf));
2907
	APR_BRIGADE_INSERT_TAIL(request_brigade, e);
2908
2909
	struct dav_remote_send_headers_wrapper wrapper;
2910
	wrapper.bucket_alloc = bucket_alloc;
2911
	wrapper.request_brigade = request_brigade;
2912
	wrapper.p = r->pool;
2913
2914
	apr_table_do(dav_remote_send_headers, &wrapper, r->headers_out, 0);
2915
2916
	buf = apr_pstrcat(r->pool, CRLF, NULL);
2917
	e = apr_bucket_pool_create(buf, strlen(buf), r->pool, bucket_alloc);
2918
	ap_xlate_proto_to_ascii(buf, strlen(buf));
2919
	APR_BRIGADE_INSERT_TAIL(request_brigade, e);
2920
2921
	e = apr_bucket_flush_create(bucket_alloc);
2922
	APR_BRIGADE_INSERT_TAIL(request_brigade, e);
2923
2924
    rv = ap_pass_brigade(r->output_filters, request_brigade);
2925
2926
    if (NULL != write_request_content) {
2927
    	write_request_content(r, write_request_content_data);
2928
    }
2929
2930
	if (rv != APR_SUCCESS) {
2931
		return dav_new_error(r->pool, HTTP_INTERNAL_SERVER_ERROR, 0, "Sending request failed");
2932
	}
2933
2934
	if (NULL != (err = dav_remote_read_status_line(r))) {
2935
		return dav_push_error(r->pool, err->status, 0, "read_status in dav_remote_method_request failed.", err);
2936
	}
2937
2938
	if (NULL != (err = dav_remote_read_response_headers(r))) {
2939
		return dav_push_error(r->pool, err->status, 0, "read_response_headers in dav_remote_method_request failed.", err);
2940
	}
2941
2942
	if (NULL == read_response_content) {
2943
		read_response_content = dav_remote_skip_response_content;
2944
	}
2945
2946
	if (NULL != (err = read_response_content(r, read_response_content_data))) {
2947
		return dav_push_error(r->pool, err->status, 0, "read_reponse_content_callback in dav_remote_method_request failed.", err);
2948
	}
2949
2950
	// MOVED PERMANENTLY - check with '/' at the end
2951
	if ((r->status == HTTP_MOVED_PERMANENTLY) && (resource_uri->path[strlen(resource_uri->path) - 1] != '/')) {
2952
		resource_path = apr_pstrcat(r->pool, resource_path, "/", NULL);
2953
		if (strcmp(resource_path, apr_table_get(r->headers_in, "Location")) != 0) {
2954
			return dav_new_error(r->pool, HTTP_INTERNAL_SERVER_ERROR, 0, "No idea what to do...");
2955
		}
2956
2957
		resource_uri->path = apr_pstrcat(r->pool, resource_uri->path, "/", NULL);
2958
2959
		return dav_remote_method_request(r, method, resource_uri, resource_path, resource, NULL, NULL, NULL, NULL);
2960
	}
2961
2962
	return NULL;
2963
}
2964
2965
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)
2966
{
2967
	dav_error *err;
2968
	conn_rec *conn;
2969
2970
	*exists = 0;
2971
2972
	if (NULL != (err = dav_remote_set_connection(r, resource_uri))) {
2973
		return dav_push_error(r->pool, err->status, 0, "Unable to create connection in dav_remote_resource_exists.", err);
2974
	}
2975
2976
	apr_table_clear(r->headers_out);
2977
	apr_table_add(r->headers_out, "Host", resource_uri->hostname);
2978
	apr_table_add(r->headers_out, "Content-Length", "0");
2979
	apr_table_add(r->headers_out, "Depth", "0");
2980
	apr_table_add(r->headers_out, "Connection", "Keep-Alive");
2981
2982
	if (NULL != (err = dav_remote_method_request(r, "HEAD", resource_uri, resource_path, resource, NULL, NULL, NULL, NULL))) {
2983
		return dav_push_error(r->pool, err->status, 0, "HEAD in dav_remote_resource_exists failed.", err);
2984
	}
2985
2986
	*exists = r->status != 404;
2987
	return 0;
2988
}
2989
2990
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)
2991
{
2992
	dav_error *err;
2993
	conn_rec *conn;
2994
2995
	if (NULL != (err = dav_remote_set_connection(r, resource_uri))) {
2996
		return dav_push_error(r->pool, err->status, 0, "Unable to create connection in dav_remote_resource_delete.", err);
2997
	}
2998
2999
	apr_table_clear(r->headers_out);
3000
	apr_table_add(r->headers_out, "Host", resource_uri->hostname);
3001
	apr_table_add(r->headers_out, "Content-Length", "0");
3002
	apr_table_add(r->headers_out, "Connection", "Keep-Alive");
3003
3004
	if (NULL != (err = dav_remote_method_request(r, "DELETE", resource_uri, resource_path, resource, NULL, NULL, NULL, NULL))) {
3005
		return dav_push_error(r->pool, err->status, 0, "DELETE in dav_remote_resource_delete failed.", err);
3006
	}
3007
3008
	*deleted = r->status == 200 || r->status == 202 || r->status == 204 || r->status == 404;
3009
3010
	return 0;
3011
}
3012
3013
DAV_DECLARE(dav_error *) dav_remote_resource_put(request_rec *r, apr_uri_t *resource_uri, const char *resource_path, dav_resource *resource)
3014
{
3015
	dav_error *err;
3016
	conn_rec *conn;
3017
3018
	if (NULL != (err = dav_remote_set_connection(r, resource_uri))) {
3019
		return dav_push_error(r->pool, err->status, 0, "Unable to create connection in dav_remote_resource_delete.", err);
3020
	}
3021
3022
	apr_table_clear(r->headers_out);
3023
	apr_table_add(r->headers_out, "Host", resource_uri->hostname);
3024
	apr_table_add(r->headers_out, "Connection", "Keep-Alive");
3025
3026
    if ((err = (*resource->hooks->set_headers)(r, resource)) != NULL) {
3027
        return dav_push_error(r->pool, err->status, 0,
3028
                             "Unable to set up HTTP headers.",
3029
                             err);
3030
    }
3031
3032
	if (NULL != (err = dav_remote_method_request(r, "PUT", resource_uri, resource_path, resource,
3033
			dav_remote_send_resource_content, resource,
3034
			NULL, NULL))) {
3035
		return dav_push_error(r->pool, err->status, 0, "DELETE in dav_remote_resource_delete failed.", err);
3036
	}
3037
3038
	if (r->status != 201 && r->status != 204) {
3039
		return dav_new_error(r->pool, r->status, 0, "Remote server does not accept resource");
3040
	}
3041
3042
	return 0;
3043
}
3044
3045
static int dav_remote_copymove(request_rec *r, dav_resource *resource, const char *dest, int is_move, int overwrite)
3046
{
3047
	dav_error *err;
3048
	apr_uri_t dest_uri;
3049
	conn_rec *conn;
3050
    request_rec *rp;
3051
    int exists;
3052
	int deleted;
3053
3054
    if (APR_SUCCESS != apr_uri_parse(r->pool, dest, &dest_uri)) {
3055
        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
3056
                      "Destination URI cannot be parsed.", NULL);
3057
    	return HTTP_BAD_REQUEST;
3058
    }
3059
3060
    if (!dest_uri.port) {
3061
    	dest_uri.port = apr_uri_port_of_scheme(dest_uri.scheme);
3062
    }
3063
3064
    // 1. create request
3065
    rp = dav_remote_make_fake_request(r);
3066
3067
3068
   	if (!overwrite) {
3069
   	    // 2. check if exists
3070
   	   	if (NULL != (err = dav_remote_resource_exists(rp, &dest_uri, dest, resource, &exists))) {
3071
   	   		return dav_handle_err(r, err, NULL);
3072
   	   	}
3073
3074
   	   	if (exists)
3075
			return HTTP_PRECONDITION_FAILED;
3076
    }
3077
   	else {
3078
   		// 2. delete old resource
3079
   		if (NULL != (err = dav_remote_resource_delete(rp, &dest_uri, dest, resource, &deleted))) {
3080
   			return dav_handle_err(r, err, NULL);
3081
   		}
3082
3083
   		if (!deleted)
3084
   			return HTTP_FORBIDDEN;
3085
   	}
3086
3087
    // 3. send content
3088
    if ((err = dav_remote_resource_put(rp, &dest_uri, dest, resource)) != NULL) {
3089
        return dav_handle_err(r, err, NULL);
3090
    }
3091
3092
	return HTTP_NO_CONTENT;
3093
}
3094
2553
/* handle the COPY and MOVE methods */
3095
/* handle the COPY and MOVE methods */
2554
static int dav_method_copymove(request_rec *r, int is_move)
3096
static int dav_method_copymove(request_rec *r, int is_move)
2555
{
3097
{
Lines 2609-2614 Link Here
2609
        return HTTP_BAD_REQUEST;
3151
        return HTTP_BAD_REQUEST;
2610
    }
3152
    }
2611
3153
3154
    /* get and parse the overwrite header value */
3155
    if ((overwrite = dav_get_overwrite(r)) < 0) {
3156
        /* dav_get_overwrite() supplies additional information for the
3157
         * default message. */
3158
        return HTTP_BAD_REQUEST;
3159
    }
3160
2612
    lookup = dav_lookup_uri(dest, r, 1 /* must_be_absolute */);
3161
    lookup = dav_lookup_uri(dest, r, 1 /* must_be_absolute */);
2613
    if (lookup.rnew == NULL) {
3162
    if (lookup.rnew == NULL) {
2614
        if (lookup.err.status == HTTP_BAD_REQUEST) {
3163
        if (lookup.err.status == HTTP_BAD_REQUEST) {
Lines 2618-2623 Link Here
2618
            return HTTP_BAD_REQUEST;
3167
            return HTTP_BAD_REQUEST;
2619
        }
3168
        }
2620
3169
3170
        if (!is_move && lookup.err.status == HTTP_BAD_GATEWAY) {
3171
            err = dav_get_resource(r, 1 /* label_allowed */, 0 /* use_checked_in */,
3172
                                   &resource);
3173
        	return dav_remote_copymove(r, resource, dest, is_move, overwrite);
3174
        }
3175
2621
        /* ### this assumes that dav_lookup_uri() only generates a status
3176
        /* ### this assumes that dav_lookup_uri() only generates a status
2622
         * ### that Apache can provide a status line for!! */
3177
         * ### that Apache can provide a status line for!! */
2623
3178
Lines 2650-2669 Link Here
2650
        return dav_handle_err(r, err, NULL);
3206
        return dav_handle_err(r, err, NULL);
2651
3207
2652
    /* are the two resources handled by the same repository? */
3208
    /* are the two resources handled by the same repository? */
2653
    if (resource->hooks != resnew->hooks) {
3209
    if (!is_move && resource->hooks != resnew->hooks) {
3210
        err = dav_get_resource(r, 1 /* label_allowed */, 0 /* use_checked_in */,
3211
                               &resource);
2654
        /* ### this message exposes some backend config, but screw it... */
3212
        /* ### this message exposes some backend config, but screw it... */
2655
        return dav_error_response(r, HTTP_BAD_GATEWAY,
3213
    	return dav_remote_copymove(r, resource, dest, is_move, overwrite);
2656
                                  "Destination URI is handled by a "
2657
                                  "different repository than the source URI. "
2658
                                  "MOVE or COPY between repositories is "
2659
                                  "not possible.");
2660
    }
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
    }
3214
    }
2668
3215
2669
    /* quick failure test: if dest exists and overwrite is false. */
3216
    /* quick failure test: if dest exists and overwrite is false. */
(-)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,

Return to bug 45449