OP_DELETE,
OP_HEAD,
OP_POST,
+ OP_COPY,
OP_UNKNOWN,
};
send_response();
}
-static bool parse_copy_source(const char *src, string& bucket_name, string& object)
+bool RGWCopyObj::parse_copy_location(const char *src, string& bucket_name, string& object)
{
string url_src(src);
string dec_src;
url_decode(url_src, dec_src);
src = dec_src.c_str();
- dout(15) << "decoded src=" << src << dendl;
+ dout(15) << "decoded obj=" << src << dendl;
if (*src == '/') ++src;
{
string empty_str;
RGWAccessControlPolicy src_policy;
- RGWAccessControlPolicy dest_policy;
+ ret = get_params();
+ if (ret < 0)
+ return ret;
- if (!::verify_permission(s, RGW_PERM_WRITE))
- return -EACCES;
+ RGWBucketInfo src_bucket_info, dest_bucket_info;
- ret = dest_policy.create_canned(s->user.user_id, s->user.display_name, s->canned_acl);
- if (!ret)
- return -EINVAL;
+ /* get buckets info (source and dest) */
- string src_bucket_name;
+ ret = rgwstore->get_bucket_info(s->obj_ctx, src_bucket_name, src_bucket_info);
+ if (ret < 0)
+ return ret;
- ret = parse_copy_source(s->copy_source, src_bucket_name, src_object);
- if (!ret)
- return -EINVAL;
+ src_bucket = src_bucket_info.bucket;
- RGWBucketInfo bucket_info;
+ if (src_bucket_name.compare(dest_bucket_name) == 0) {
+ dest_bucket_info = src_bucket_info;
+ } else {
+ ret = rgwstore->get_bucket_info(s->obj_ctx, dest_bucket_name, dest_bucket_info);
+ if (ret < 0)
+ return ret;
+ }
+
+ dest_bucket = dest_bucket_info.bucket;
- ret = rgwstore->get_bucket_info(s->obj_ctx, src_bucket_name, bucket_info);
+ /* check source object permissions */
+ ret = read_acls(s, src_bucket_info, &src_policy, src_bucket, src_object);
if (ret < 0)
return ret;
- src_bucket = bucket_info.bucket;
+ if (!::verify_permission(&src_policy, s->user.user_id, s->perm_mask, RGW_PERM_READ))
+ return -EACCES;
+
+ RGWAccessControlPolicy dest_bucket_policy;
- /* just checking the bucket's permission */
- ret = read_acls(s, bucket_info, &src_policy, src_bucket, empty_str);
+ /* check dest bucket permissions */
+ ret = read_acls(s, dest_bucket_info, &dest_bucket_policy, dest_bucket, empty_str);
if (ret < 0)
return ret;
- if (!::verify_permission(&src_policy, s->user.user_id, s->perm_mask, RGW_PERM_READ))
+ if (!::verify_permission(&dest_bucket_policy, s->user.user_id, s->perm_mask, RGW_PERM_WRITE))
return -EACCES;
+ /* build a polict for the target object */
+ RGWAccessControlPolicy dest_policy;
+
+ ret = dest_policy.create_canned(s->user.user_id, s->user.display_name, s->canned_acl);
+ if (!ret)
+ return -EINVAL;
+
dest_policy.encode(aclbl);
return 0;
time_t unmod_time;
time_t *mod_ptr = NULL;
time_t *unmod_ptr = NULL;
-
if (if_mod) {
if (parse_time(if_mod, &mod_time) < 0) {
ret = -EINVAL;
{
rgw_obj src_obj, dst_obj;
- ret = get_params();
- if (ret < 0)
- goto done;
-
if (init_common() < 0)
goto done;
src_obj.init(src_bucket, src_object);
- dst_obj.init(s->bucket, s->object_str);
+ dst_obj.init(dest_bucket, dest_object);
rgwstore->set_atomic(s->obj_ctx, src_obj);
rgwstore->set_atomic(s->obj_ctx, dst_obj);
time_t *unmod_ptr;
int ret;
map<string, bufferlist> attrs;
+ string src_bucket_name;
rgw_bucket src_bucket;
string src_object;
+ string dest_bucket_name;
+ rgw_bucket dest_bucket;
+ string dest_object;
time_t mtime;
int init_common();
+
+protected:
+ bool parse_copy_location(const char *src, string& bucket_name, string& object);
+
public:
RGWCopyObj() {}
return len;
}
-int RGWCopyObj_REST::get_params()
-{
- if_mod = s->env->get("HTTP_X_AMZ_COPY_IF_MODIFIED_SINCE");
- if_unmod = s->env->get("HTTP_X_AMZ_COPY_IF_UNMODIFIED_SINCE");
- if_match = s->env->get("HTTP_X_AMZ_COPY_IF_MATCH");
- if_nomatch = s->env->get("HTTP_X_AMZ_COPY_IF_NONE_MATCH");
-
- return 0;
-}
-
int RGWPutACLs_REST::get_params()
{
size_t cl = 0;
s->op = OP_HEAD;
else if (strcmp(s->method, "POST") == 0)
s->op = OP_POST;
+ else if (strcmp(s->method, "COPY") == 0)
+ s->op = OP_COPY;
else
s->op = OP_UNKNOWN;
init_auth_info(s);
- const char *cacl = s->env->get("HTTP_X_AMZ_ACL");
- if (cacl)
- s->canned_acl = cacl;
-
- s->copy_source = s->env->get("HTTP_X_AMZ_COPY_SOURCE");
s->http_auth = s->env->get("HTTP_AUTHORIZATION");
if (g_conf->rgw_print_continue) {
case OP_DELETE:
only_bucket = true;
break;
+ case OP_COPY: // op itself will read and verify the permissions
+ return 0;
default:
return -EINVAL;
}
case OP_POST:
op = get_post_op();
break;
+ case OP_COPY:
+ op = get_copy_op();
+ break;
default:
return NULL;
}
public:
RGWCopyObj_REST() {}
~RGWCopyObj_REST() {}
-
- int get_params();
};
class RGWGetACLs_REST : public RGWGetACLs {
virtual RGWOp *get_create_op() = 0;
virtual RGWOp *get_delete_op() = 0;
virtual RGWOp *get_post_op() = 0;
+ virtual RGWOp *get_copy_op() = 0;
public:
int read_permissions();
end_header(s);
}
+int RGWCopyObj_REST_S3::get_params()
+{
+ if_mod = s->env->get("HTTP_X_AMZ_COPY_IF_MODIFIED_SINCE");
+ if_unmod = s->env->get("HTTP_X_AMZ_COPY_IF_UNMODIFIED_SINCE");
+ if_match = s->env->get("HTTP_X_AMZ_COPY_IF_MATCH");
+ if_nomatch = s->env->get("HTTP_X_AMZ_COPY_IF_NONE_MATCH");
+
+ const char *req_src = s->copy_source;
+ const char *req_dest = s->object;
+ if (!req_src || !req_src)
+ return -EINVAL;
+
+ ret = parse_copy_location(req_src, src_bucket_name, src_object);
+ if (!ret)
+ return -EINVAL;
+
+ dest_bucket_name = s->bucket.name;
+ dest_object = s->object_str;
+
+ return 0;
+}
+
void RGWCopyObj_REST_S3::send_response()
{
if (ret)
return NULL;
}
+int RGWHandler_REST_S3::init(struct req_state *state, FCGX_Request *fcgx)
+{
+ const char *cacl = state->env->get("HTTP_X_AMZ_ACL");
+ if (cacl)
+ state->canned_acl = cacl;
+
+ state->copy_source = state->env->get("HTTP_X_AMZ_COPY_SOURCE");
+
+ return RGWHandler_REST::init(state, fcgx);
+}
+
/*
* ?get the canonical amazon-style header for something?
*/
RGWCopyObj_REST_S3() {}
~RGWCopyObj_REST_S3() {}
+ int get_params();
void send_response();
};
RGWOp *get_create_op();
RGWOp *get_delete_op();
RGWOp *get_post_op();
+ RGWOp *get_copy_op() { return NULL; }
public:
RGWHandler_REST_S3() : RGWHandler_REST() {}
virtual ~RGWHandler_REST_S3() {}
+ virtual int init(struct req_state *state, FCGX_Request *fcgx);
int authorize();
};
flush_formatter_to_req_state(s, s->formatter);
}
+int RGWCopyObj_REST_SWIFT::get_params()
+{
+ if_mod = s->env->get("HTTP_IF_MODIFIED_SINCE");
+ if_unmod = s->env->get("HTTP_IF_UNMODIFIED_SINCE");
+ if_match = s->env->get("HTTP_COPY_IF_MATCH");
+ if_nomatch = s->env->get("HTTP_COPY_IF_NONE_MATCH");
+
+ if (s->op == OP_COPY) {
+ const char *req_dest = s->env->get("HTTP_DESTINATION");
+ if (!req_dest)
+ return -EINVAL;
+
+ ret = parse_copy_location(req_dest, dest_bucket_name, dest_object);
+ if (!ret)
+ return -EINVAL;
+ src_bucket_name = s->bucket_name;
+ src_object = s->object_str;
+ } else {
+ const char *req_src = s->copy_source;
+ if (!req_src)
+ return -EINVAL;
+
+ ret = parse_copy_location(req_src, src_bucket_name, src_object);
+ if (!ret)
+ return -EINVAL;
+
+ dest_bucket_name = s->bucket_name;
+ dest_object = s->object_str;
+ }
+
+ return 0;
+}
+
+void RGWCopyObj_REST_SWIFT::send_response()
+{
+ if (!ret)
+ ret = STATUS_CREATED;
+ set_req_state_err(s, ret);
+ dump_errno(s);
+ end_header(s);
+}
+
int RGWGetObj_REST_SWIFT::send_response(void *handle)
{
const char *content_type = NULL;
return NULL;
}
+RGWOp *RGWHandler_REST_SWIFT::get_copy_op()
+{
+ if (s->object)
+ return new RGWCopyObj_REST_SWIFT;
+
+ return NULL;
+}
+
int RGWHandler_REST_SWIFT::authorize()
{
bool authorized = rgw_verify_os_token(s);
return 0;
}
+
+int RGWHandler_REST_SWIFT::init(struct req_state *state, FCGX_Request *fcgx)
+{
+ state->copy_source = state->env->get("HTTP_X_COPY_FROM");
+
+ return RGWHandler_REST::init(state, fcgx);
+}
RGWCopyObj_REST_SWIFT() {}
~RGWCopyObj_REST_SWIFT() {}
- void send_response() {}
+ int get_params();
+ void send_response();
};
class RGWGetACLs_REST_SWIFT : public RGWGetACLs_REST {
RGWOp *get_create_op();
RGWOp *get_delete_op();
RGWOp *get_post_op();
+ RGWOp *get_copy_op();
public:
RGWHandler_REST_SWIFT() : RGWHandler_REST() {}
virtual ~RGWHandler_REST_SWIFT() {}
+ int init(struct req_state *state, FCGX_Request *fcgx);
int authorize();
};