string source_zone;
string client_id;
string op_id;
- string etag;
+ ceph::buffer::list etag;
off_t last_ofs;
real_time delete_at,
string *version_id,
string *ptag,
- string *petag,
+ ceph::buffer::list *petag,
struct rgw_err *err,
void (*progress_cb)(off_t, void *),
void *progress_data)
}
if (petag) {
- map<string, bufferlist>::iterator iter = src_attrs.find(RGW_ATTR_ETAG);
+ const auto iter = src_attrs.find(RGW_ATTR_ETAG);
if (iter != src_attrs.end()) {
- bufferlist& etagbl = iter->second;
- *petag = string(etagbl.c_str(), etagbl.length());
+ *petag = iter->second;
}
}
real_time delete_at,
string *version_id,
string *ptag,
- string *petag,
+ ceph::buffer::list *petag,
struct rgw_err *err,
void (*progress_cb)(off_t, void *),
void *progress_data)
}
if (petag) {
- map<string, bufferlist>::iterator iter = attrs.find(RGW_ATTR_ETAG);
+ const auto iter = attrs.find(RGW_ATTR_ETAG);
if (iter != attrs.end()) {
- bufferlist& etagbl = iter->second;
- *petag = string(etagbl.c_str(), etagbl.length());
+ *petag = iter->second;
}
}
real_time delete_at,
string *version_id,
string *ptag,
- string *petag,
+ ceph::buffer::list *petag,
struct rgw_err *err)
{
bufferlist first_chunk;
} while (ofs <= end);
string etag;
- map<string, bufferlist>::iterator iter = attrs.find(RGW_ATTR_ETAG);
+ auto iter = attrs.find(RGW_ATTR_ETAG);
if (iter != attrs.end()) {
bufferlist& bl = iter->second;
etag = string(bl.c_str(), bl.length());
if (petag) {
- *petag = etag;
+ *petag = bl;
}
}
ceph::real_time delete_at,
string *version_id,
string *ptag,
- string *petag,
+ ceph::buffer::list *petag,
struct rgw_err *err,
void (*progress_cb)(off_t, void *),
void *progress_data);
ceph::real_time delete_at,
string *version_id,
string *ptag,
- string *petag,
+ ceph::buffer::list *petag,
struct rgw_err *err,
void (*progress_cb)(off_t, void *),
void *progress_data);
ceph::real_time delete_at,
string *version_id,
string *ptag,
- string *petag,
+ ceph::buffer::list *petag,
struct rgw_err *err);
/**
}
}
+static inline boost::string_ref get_sanitized_hdrval(ceph::buffer::list& raw)
+{
+ /* std::string and thus boost::string_ref ARE OBLIGED to carry multiple
+ * 0x00 and count them to the length of a string. We need to take that
+ * into consideration and sanitize the size of a ceph::buffer::list used
+ * to store metadata values (x-amz-meta-*, X-Container-Meta-*, etags).
+ * Otherwise we might send 0x00 to clients. */
+ const char* const data = raw.c_str();
+ size_t len = raw.length();
+
+ if (len && data[len - 1] == '\0') {
+ /* That's the case - the null byte has been included at the last position
+ * of the bufferlist. We need to restore the proper string length we'll
+ * pass to string_ref. */
+ len--;
+ }
+
+ return boost::string_ref(data, len);
+}
+
void dump_header(struct req_state* const s,
const boost::string_ref& name,
ceph::buffer::list& bl)
{
- return dump_header(s, name, boost::string_ref(bl.c_str(), bl.length()));
+ return dump_header(s, name, get_sanitized_hdrval(bl));
}
void dump_header(struct req_state* const s,
ceph::buffer::list& bl_etag,
const bool quoted)
{
- return dump_etag(s, boost::string_ref(bl_etag.c_str(), bl_etag.length()),
- quoted);
+ return dump_etag(s, get_sanitized_hdrval(bl_etag), quoted);
}
void dump_bucket_from_state(struct req_state *s)
if (op_ret == 0) {
dump_time(s, "LastModified", &mtime);
- if (!etag.empty()) {
- s->formatter->dump_string("ETag", etag);
+ std::string etag_str = etag.to_str();
+ if (! etag_str.empty()) {
+ s->formatter->dump_string("ETag", std::move(etag_str));
}
s->formatter->close_section();
rgw_flush_formatter_and_reset(s, s->formatter);