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 |