return oss;
}
+static bool check_str_end(const char *s)
+{
+ if (!s)
+ return false;
+
+ while (*s) {
+ if (!isspace(*s))
+ return false;
+ s++;
+ }
+ return true;
+}
+
+static bool parse_rfc850(const char *s, struct tm *t)
+{
+ return check_str_end(strptime(s, "%A, %d-%b-%y %H:%M:%S GMT", t));
+}
+
+static bool parse_asctime(const char *s, struct tm *t)
+{
+ return check_str_end(strptime(s, "%a %b %d %H:%M:%S %Y", t));
+}
+
+static bool parse_rfc1123(const char *s, struct tm *t)
+{
+ return check_str_end(strptime(s, "%a, %d %b %Y %H:%M:%S GMT", t));
+}
+
+bool parse_rfc2616(const char *s, struct tm *t)
+{
+ return parse_rfc850(s, t) || parse_asctime(s, t) || parse_rfc1123(s, t);
+}
+
int parse_time(const char *time_str, time_t *time)
{
struct tm tm;
- memset(&tm, 0, sizeof(struct tm));
- if (!strptime(time_str, "%a, %d %b %Y %H:%M:%S %Z", &tm))
+
+ if (!parse_rfc2616(time_str, &tm))
return -EINVAL;
- *time = mktime(&tm);
+ *time = timegm(&tm);
return 0;
}
state->bytes_received += olen; \
} while (0)
+#define STATUS_CREATED 1900
+#define STATUS_ACCEPTED 1901
+#define STATUS_NO_CONTENT 1902
+#define STATUS_PARTIAL_CONTENT 1903
+
#define ERR_INVALID_BUCKET_NAME 2000
#define ERR_INVALID_OBJECT_NAME 2001
#define ERR_NO_SUCH_BUCKET 2002
#define ERR_LENGTH_REQUIRED 2011
#define ERR_REQUEST_TIME_SKEWED 2012
#define ERR_BUCKET_EXISTS 2013
+#define ERR_BAD_URL 2014
+#define ERR_PRECONDITION_FAILED 2015
+#define ERR_NOT_MODIFIED 2016
#define ERR_USER_SUSPENDED 2100
#define ERR_INTERNAL_ERROR 2200
return "unknown";
}
-/** */
+/** time parsing */
extern int parse_time(const char *time_str, time_t *time);
+extern bool parse_rfc2616(const char *s, struct tm *t);
+
/** Check if a user has a permission on that ACL */
extern bool verify_permission(RGWAccessControlPolicy *policy, string& uid, int user_perm_mask, int perm);
/** Check if the req_state's user has the necessary permissions
{
char buf[LARGE_SIZE];
va_list ap;
+ const char *format;
struct plain_stack_entry& entry = stack.back();
va_start(ap, fmt);
vsnprintf(buf, LARGE_SIZE, fmt, ap);
va_end(ap);
- write_data("%s\n", buf);
+ if (len)
+ format = "\n%s";
+ else
+ format = "%s";
+
+ write_data(format, buf);
}
int RGWFormatter_Plain::get_len() const
if (ret < 0)
goto done;
- init_common();
+ ret = init_common();
+ if (ret < 0)
+ goto done;
+dout(0) << __FILE__ << ":" << __LINE__ << " unmod_ptr=" << (void *)unmod_ptr << dendl;
obj.init(s->bucket, s->object_str);
rgwstore->set_atomic(s->obj_ctx, obj);
mod_ptr = &mod_time;
}
+dout(0) << __FILE__ << ":" << __LINE__ << " if_unmod=" << (void *)if_unmod << dendl;
if (if_unmod) {
if (parse_time(if_unmod, &unmod_time) < 0)
return -EINVAL;
unmod_ptr = &unmod_time;
+dout(0) << __FILE__ << ":" << __LINE__ << " unmod_ptr=" << (void *)unmod_ptr << dendl;
}
return 0;
goto done_err;
}
+ dout(0) << __FILE__ << ":" << __LINE__ << " mod_ptr=" << (void *)mod_ptr << " unmod_ptr=" << (void *)unmod_ptr << dendl;
+
/* Convert all times go GMT to make them compatible */
if (mod_ptr || unmod_ptr) {
struct tm mtm;
}
ctime = mktime(gmtm);
- r = -ECANCELED;
if (mod_ptr) {
dout(10) << "If-Modified-Since: " << *mod_ptr << " Last-Modified: " << ctime << dendl;
if (ctime < *mod_ptr) {
- err->http_ret = 304;
- err->s3_code = "NotModified";
-
+ r = -ERR_NOT_MODIFIED;
goto done_err;
}
}
if (unmod_ptr) {
dout(10) << "If-UnModified-Since: " << *unmod_ptr << " Last-Modified: " << ctime << dendl;
if (ctime > *unmod_ptr) {
- err->http_ret = 412;
- err->s3_code = "PreconditionFailed";
+ r = -ERR_PRECONDITION_FAILED;
goto done_err;
}
}
if (r < 0)
goto done_err;
- r = -ECANCELED;
if (if_match) {
dout(10) << "ETag: " << etag.c_str() << " " << " If-Match: " << if_match << dendl;
if (strcmp(if_match, etag.c_str())) {
- err->http_ret = 412;
- err->s3_code = "PreconditionFailed";
+ r = -ERR_PRECONDITION_FAILED;
goto done_err;
}
}
if (if_nomatch) {
dout(10) << "ETag: " << etag.c_str() << " " << " If-NoMatch: " << if_nomatch << dendl;
if (strcmp(if_nomatch, etag.c_str()) == 0) {
- err->http_ret = 304;
- err->s3_code = "NotModified";
+ r = -ERR_NOT_MODIFIED;
goto done_err;
}
}
const static struct rgw_html_errors RGW_HTML_ERRORS[] = {
{ 0, 200, "" },
- { 201, 201, "Created" },
- { 202, 202, "Accepted" },
- { 204, 204, "NoContent" },
- { 206, 206, "" },
+ { STATUS_CREATED, 201, "Created" },
+ { STATUS_ACCEPTED, 202, "Accepted" },
+ { STATUS_NO_CONTENT, 204, "NoContent" },
+ { STATUS_PARTIAL_CONTENT, 206, "" },
+ { ERR_NOT_MODIFIED, 304, "NotModified" },
{ EINVAL, 400, "InvalidArgument" },
{ ERR_INVALID_DIGEST, 400, "InvalidDigest" },
{ ERR_BAD_DIGEST, 400, "BadDigest" },
{ ETIMEDOUT, 408, "RequestTimeout" },
{ EEXIST, 409, "BucketAlreadyExists" },
{ ENOTEMPTY, 409, "BucketNotEmpty" },
+ { ERR_PRECONDITION_FAILED, 412, "PreconditionFailed" },
{ ERANGE, 416, "InvalidRange" },
{ ERR_INTERNAL_ERROR, 500, "InternalError" },
};
{ EACCES, 401, "AccessDenied" },
{ EPERM, 401, "AccessDenied" },
{ ERR_USER_SUSPENDED, 401, "UserSuspended" },
+ { ERR_BAD_URL, 412, "Bad URL" },
};
#define ARRAY_LEN(arr) (sizeof(arr) / sizeof(arr[0]))
dump_start(s);
s->formatter->open_object_section("Error");
if (!s->err.s3_code.empty())
- s->formatter->dump_format("Code", "%s", s->err.s3_code.c_str());
+ s->formatter->dump_string("Code", s->err.s3_code.c_str());
if (!s->err.message.empty())
s->formatter->dump_format("Message", s->err.message.c_str());
s->formatter->close_section();
range_str = s->env->get("HTTP_RANGE");
if_mod = s->env->get("HTTP_IF_MODIFIED_SINCE");
if_unmod = s->env->get("HTTP_IF_UNMODIFIED_SINCE");
+dout(0) << __FILE__ << ":" << __LINE__ << " if_unmod=" << (void *)if_unmod << dendl;
if_match = s->env->get("HTTP_IF_MATCH");
if_nomatch = s->env->get("HTTP_IF_NONE_MATCH");
}
}
-void init_entities_from_header(struct req_state *s)
+static int init_entities_from_header(struct req_state *s)
{
string req;
string first;
} else {
s->host_bucket = NULL;
}
- } else s->host_bucket = NULL;
+ } else
+ s->host_bucket = NULL;
const char *req_name = s->path_name;
const char *p;
}
}
} else {
+ if (req.compare(g_conf->rgw_swift_url_prefix) == 0) {
+ s->prot_flags |= RGW_REST_SWIFT;
+ delete s->formatter;
+ s->format = 0;
+ s->formatter = new RGWFormatter_Plain;
+ return -ERR_BAD_URL;
+ }
first = req;
}
if (s->prot_flags & RGW_REST_SWIFT) {
+ /* verify that the request_uri conforms with what's expected */
+ char buf[g_conf->rgw_swift_url_prefix.length() + 16];
+ int blen = sprintf(buf, "/%s/v1", g_conf->rgw_swift_url_prefix.c_str());
+ if (s->path_name_url[0] != '/' ||
+ s->path_name_url.compare(0, blen, buf) != 0) {
+ return -ENOENT;
+ }
+
s->format = 0;
delete s->formatter;
s->formatter = new RGWFormatter_Plain;
}
done:
s->formatter->reset();
+ return 0;
}
static void line_unfold(const char *line, string& sdest)
else
s->op = OP_UNKNOWN;
- init_entities_from_header(s);
+ ret = init_entities_from_header(s);
+ if (ret)
+ return ret;
+
switch (s->op) {
case OP_PUT:
if (s->object && !s->args.sub_resource_exists("acl")) {
break;
}
- if (s->prot_flags & RGW_REST_SWIFT) {
- char buf[g_conf->rgw_swift_url_prefix.length() + 16];
- int blen = sprintf(buf, "/%s/v1", g_conf->rgw_swift_url_prefix.c_str());
- if (s->path_name_url[0] != '/' ||
- s->path_name_url.compare(0, blen, buf) != 0)
- ret = -ENOENT;
- }
-
if (ret)
return ret;
}
if (range_str && !ret)
- ret = 206; /* partial content */
+ ret = STATUS_PARTIAL_CONTENT;
done:
set_req_state_err(s, ret);
{
int r = ret;
if (!r)
- r = 204;
+ r = STATUS_NO_CONTENT;
set_req_state_err(s, r);
dump_errno(s);
{
int r = ret;
if (!r)
- r = 204;
+ r = STATUS_NO_CONTENT;
set_req_state_err(s, r);
dump_errno(s);
{
int r = ret;
if (!r)
- r = 204;
+ r = STATUS_NO_CONTENT;
set_req_state_err(s, r);
dump_errno(s);
dout(10) << "get_canon_resource(): dest=" << dest << dendl;
}
-static bool check_str_end(const char *s)
-{
- if (!s)
- return false;
-
- while (*s) {
- if (!isspace(*s))
- return false;
- s++;
- }
- return true;
-}
-
-static bool parse_rfc850(const char *s, struct tm *t)
-{
- return check_str_end(strptime(s, "%A, %d-%b-%y %H:%M:%S GMT", t));
-}
-
-static bool parse_asctime(const char *s, struct tm *t)
-{
- return check_str_end(strptime(s, "%a %b %d %H:%M:%S %Y", t));
-}
-
-static bool parse_rfc1123(const char *s, struct tm *t)
-{
- return check_str_end(strptime(s, "%a, %d %b %Y %H:%M:%S GMT", t));
-}
-
-static bool parse_rfc2616(const char *s, struct tm *t)
-{
- return parse_rfc850(s, t) || parse_asctime(s, t) || parse_rfc1123(s, t);
-}
-
static inline bool is_base64_for_content_md5(unsigned char c) {
return (isalnum(c) || isspace(c) || (c == '+') || (c == '/') || (c == '='));
}
s->formatter->close_section();
if (!ret && s->formatter->get_len() == 0)
- ret = 204;
+ ret = STATUS_NO_CONTENT;
set_req_state_err(s, ret);
dump_errno(s);
s->formatter->close_section();
if (!ret && s->formatter->get_len() == 0)
- ret = 204;
+ ret = STATUS_NO_CONTENT;
else if (ret > 0)
ret = 0;
void RGWStatAccount_REST_SWIFT::send_response()
{
if (ret >= 0) {
- ret = 204;
+ ret = STATUS_NO_CONTENT;
dump_account_metadata(s, buckets_count, buckets_objcount, buckets_size);
}
void RGWStatBucket_REST_SWIFT::send_response()
{
if (ret >= 0) {
- ret = 204;
+ ret = STATUS_NO_CONTENT;
dump_container_metadata(s, bucket);
}
void RGWCreateBucket_REST_SWIFT::send_response()
{
if (!ret)
- ret = 201; // "created"
+ ret = STATUS_CREATED;
else if (ret == -ERR_BUCKET_EXISTS)
- ret = 202;
+ ret = STATUS_ACCEPTED;
set_req_state_err(s, ret);
dump_errno(s);
end_header(s);
{
int r = ret;
if (!r)
- r = 204;
+ r = STATUS_NO_CONTENT;
set_req_state_err(s, r);
dump_errno(s);
void RGWPutObj_REST_SWIFT::send_response()
{
if (!ret)
- ret = 201; // "created"
+ ret = STATUS_CREATED;
dump_etag(s, etag.c_str());
set_req_state_err(s, ret);
dump_errno(s);
{
int r = ret;
if (!r)
- r = 204;
+ r = STATUS_NO_CONTENT;
set_req_state_err(s, r);
dump_errno(s);
}
if (range_str && !ret)
- ret = 206; /* partial content */
+ ret = -STATUS_PARTIAL_CONTENT;
if (ret)
set_req_state_err(s, ret);
CGI_PRINTF(s, "X-Storage-Token: AUTH_rgwtk%s\n", buf);
}
- ret = 204;
+ ret = STATUS_NO_CONTENT;
done:
set_req_state_err(s, ret);