/** * common routine for x-object-meta-* and x-container-meta-* * * @param string * @param value * @param metadatum_func * @param cb_arg * @param metadata * @param sysmdp * * @return */ dpl_status_t dpl_cdmi_get_metadatum_from_string(const char *key, const char *value, dpl_metadatum_func_t metadatum_func, void *cb_arg, dpl_dict_t *metadata, dpl_sysmd_t *sysmdp) { dpl_status_t ret, ret2; dpl_value_t *val = NULL; //XXX convert ret2 = dpl_cdmi_get_metadatum_from_value(key, val, metadatum_func, cb_arg, metadata, sysmdp); if (DPL_SUCCESS != ret2) { ret = ret2; goto end; } ret = DPL_SUCCESS; end: if (NULL != val) dpl_value_free(val); return ret; }
static dpl_status_t insert_query_params_in_vec(dpl_vec_t *params, const dpl_dict_t *query_params, unsigned char encode_url) { int bucket; for (bucket = 0; bucket < query_params->n_buckets; bucket++) { dpl_dict_var_t *param = query_params->buckets[bucket]; while (param != NULL) { size_t new_size; dpl_dict_var_t *new_param; dpl_status_t ret; new_param = (dpl_dict_var_t *) malloc (sizeof (dpl_dict_var_t)); if (new_param == NULL) return DPL_FAILURE; if (encode_url) new_size = DPL_URL_LENGTH(strlen(param->key)) + 1; else new_size = strlen(param->key) + 1; new_param->key = (char *) malloc(new_size); if (new_param->key == NULL) { free(new_param); return DPL_FAILURE; } if (encode_url) dpl_url_encode(param->key, new_param->key); else strcpy(new_param->key, param->key); new_param->val = dpl_value_dup(param->val); if (new_param->val == NULL) { free(new_param->key); free(new_param); return DPL_FAILURE; } if (encode_url) { ret = dpl_sbuf_url_encode(new_param->val->string); if (ret != DPL_SUCCESS) { dpl_value_free(new_param->val); free(new_param->key); free(new_param); return DPL_FAILURE; } } dpl_vec_add(params, new_param); param = param->prev; } } return DPL_SUCCESS; }
/** * parse a JSON buffer into a value * * @param ctx * @param buf * @param len * @param valp * * @return */ dpl_status_t dpl_cdmi_parse_json_buffer(dpl_ctx_t *ctx, const char *buf, int len, dpl_value_t **valp) { int ret, ret2; json_tokener *tok = NULL; json_object *obj = NULL; dpl_value_t *val = NULL; // write(1, buf, len); tok = json_tokener_new(); if (NULL == tok) { ret = DPL_ENOMEM; goto end; } obj = json_tokener_parse_ex(tok, buf, len); if (NULL == obj) { ret = DPL_FAILURE; goto end; } ret2 = convert_obj_to_value(ctx, obj, 0, &val); if (DPL_SUCCESS != ret2) { ret = ret2; goto end; } if (NULL != valp) { *valp = val; val = NULL; } ret = DPL_SUCCESS; end: if (NULL != val) dpl_value_free(val); if (NULL != obj) json_object_put(obj); if (NULL != tok) json_tokener_free(tok); return ret; }
static dpl_status_t convert_obj_to_value(dpl_ctx_t *ctx, struct json_object *obj, int level, dpl_value_t **valp) { int ret, ret2; dpl_value_t *val = NULL; char *key; struct lh_entry *entry; json_object *child; dpl_dict_t *subdict = NULL; dpl_vec_t *vector = NULL; DPRINTF("convert_obj_to_value level=%d type=%d\n", level, json_object_get_type(obj)); val = malloc(sizeof (*val)); if (NULL == val) { ret = DPL_ENOMEM; goto end; } memset(val, 0, sizeof (*val)); switch (json_object_get_type(obj)) { case json_type_null: return DPL_ENOTSUPP; case json_type_array: { int n_items = json_object_array_length(obj); int i; vector = dpl_vec_new(2, 2); if (NULL == vector) { ret = DPL_ENOMEM; goto end; } for (i = 0;i < n_items;i++) { child = json_object_array_get_idx(obj, i); dpl_value_t *subval; ret2 = convert_obj_to_value(ctx, child, level+1, &subval); if (DPL_SUCCESS != ret2) { ret = ret2; goto end; } ret2 = dpl_vec_add_value(vector, subval); dpl_value_free(subval); if (DPL_SUCCESS != ret2) { ret = ret2; goto end; } } val->type = DPL_VALUE_VECTOR; val->vector = vector; vector = NULL; break ; } case json_type_object: { subdict = dpl_dict_new(13); if (NULL == subdict) { ret = DPL_ENOMEM; goto end; } for (entry = json_object_get_object(obj)->head; (entry ? (key = (char*)entry->k, child = (struct json_object*)entry->v, entry) : 0); entry = entry->next) { dpl_value_t *subval; DPRINTF("key='%s'\n", key); ret2 = convert_obj_to_value(ctx, child, level+1, &subval); if (DPL_SUCCESS != ret2) { ret = ret2; goto end; } ret2 = dpl_dict_add_value(subdict, key, subval, 0); dpl_value_free(subval); if (DPL_SUCCESS != ret2) { ret = ret2; goto end; } } val->type = DPL_VALUE_SUBDICT; val->subdict = subdict; subdict = NULL; break ; } case json_type_boolean: case json_type_double: case json_type_int: case json_type_string: { pthread_mutex_lock(&ctx->lock); //lock for objects other than string val->string = strdup((char *) json_object_get_string(obj)); pthread_mutex_unlock(&ctx->lock); if (NULL == val->string) { ret = DPL_ENOMEM; goto end; } val->type = DPL_VALUE_STRING; break ; } } if (NULL != valp) { *valp = val; val = NULL; } ret = DPL_SUCCESS; end: if (NULL != vector) dpl_vec_free(vector); if (NULL != subdict) dpl_dict_free(subdict); if (NULL != val) dpl_value_free(val); DPRINTF("level=%d ret=%d\n", level, ret); return ret; }
dpl_status_t dpl_cdmi_head_raw(dpl_ctx_t *ctx, const char *bucket, const char *resource, const char *subresource, const dpl_option_t *option, dpl_ftype_t object_type, const dpl_condition_t *condition, dpl_dict_t **metadatap, char **locationp) { int ret, ret2; char *md_buf = NULL; u_int md_len; dpl_value_t *val = NULL; dpl_option_t option2; DPL_TRACE(ctx, DPL_TRACE_BACKEND, ""); //fetch metadata from JSON content memset(&option2, 0, sizeof (option2)); option2.mask |= DPL_OPTION_RAW; ret2 = dpl_cdmi_get(ctx, bucket, resource, NULL != subresource ? subresource : "metadata;objectID;parentID;objectType", &option2, object_type, condition, NULL, &md_buf, &md_len, NULL, NULL, locationp); if (DPL_SUCCESS != ret2) { ret = ret2; goto end; } ret2 = dpl_cdmi_parse_json_buffer(ctx, md_buf, md_len, &val); if (DPL_SUCCESS != ret2) { ret = ret2; goto end; } if (DPL_VALUE_SUBDICT != val->type) { ret = DPL_EINVAL; goto end; } if (NULL != metadatap) { *metadatap = val->subdict; val->subdict = NULL; } ret = DPL_SUCCESS; end: if (NULL != val) dpl_value_free(val); if (NULL != md_buf) free(md_buf); DPL_TRACE(ctx, DPL_TRACE_BACKEND, "ret=%d", ret); return ret; }
dpl_status_t dpl_cdmi_get(dpl_ctx_t *ctx, const char *bucket, const char *resource, const char *subresource, const dpl_option_t *option, dpl_ftype_t object_type, const dpl_condition_t *condition, const dpl_range_t *range, char **data_bufp, unsigned int *data_lenp, dpl_dict_t **metadatap, dpl_sysmd_t *sysmdp, char **locationp) { int ret, ret2; dpl_conn_t *conn = NULL; char header[dpl_header_size]; u_int header_len; struct iovec iov[10]; int n_iov = 0; int connection_close = 0; char *data_buf = NULL; u_int data_len; dpl_dict_t *headers_request = NULL; dpl_dict_t *headers_reply = NULL; dpl_req_t *req = NULL; int raw = 0; dpl_value_t *val = NULL; dpl_dict_var_t *var = NULL; dpl_dict_var_t *encoding = NULL; int value_len; int orig_len; char *orig_buf = NULL; dpl_cdmi_req_mask_t req_mask = 0u; char *location; DPL_TRACE(ctx, DPL_TRACE_BACKEND, ""); if (option) { if (option->mask & DPL_OPTION_HTTP_COMPAT) req_mask |= DPL_CDMI_REQ_HTTP_COMPAT; if (option->mask & DPL_OPTION_RAW) raw = 1; } req = dpl_req_new(ctx); if (NULL == req) { ret = DPL_ENOMEM; goto end; } dpl_req_set_method(req, DPL_METHOD_GET); if (NULL != bucket) { ret2 = dpl_req_set_bucket(req, bucket); if (DPL_SUCCESS != ret2) { ret = ret2; goto end; } } ret2 = dpl_cdmi_req_set_resource(req, resource); if (DPL_SUCCESS != ret2) { ret = ret2; goto end; } if (NULL == subresource) { if (DPL_FTYPE_REG == object_type) { subresource = "valuetransferencoding"; } } if (NULL != subresource) { ret2 = dpl_req_set_subresource(req, subresource); if (DPL_SUCCESS != ret2) { ret = ret2; goto end; } } if (NULL != condition) { dpl_req_set_condition(req, condition); } if (range) { ret2 = dpl_cdmi_req_add_range(req, req_mask, range); if (DPL_SUCCESS != ret2) { ret = ret2; goto end; } } dpl_req_set_object_type(req, object_type); //build request ret2 = dpl_cdmi_req_build(req, 0, &headers_request, NULL, NULL); if (DPL_SUCCESS != ret2) { ret = ret2; goto end; } //contact default host dpl_req_rm_behavior(req, DPL_BEHAVIOR_VIRTUAL_HOSTING); ret2 = dpl_try_connect(ctx, req, &conn); if (DPL_SUCCESS != ret2) { ret = ret2; goto end; } ret2 = dpl_add_host_to_headers(req, headers_request); if (DPL_SUCCESS != ret2) { ret = ret2; goto end; } ret2 = dpl_req_gen_http_request(ctx, req, headers_request, NULL, header, sizeof (header), &header_len); if (DPL_SUCCESS != ret2) { ret = ret2; goto end; } iov[n_iov].iov_base = header; iov[n_iov].iov_len = header_len; n_iov++; //final crlf iov[n_iov].iov_base = "\r\n"; iov[n_iov].iov_len = 2; n_iov++; ret2 = dpl_conn_writev_all(conn, iov, n_iov, conn->ctx->write_timeout); if (DPL_SUCCESS != ret2) { DPL_TRACE(conn->ctx, DPL_TRACE_ERR, "writev failed"); connection_close = 1; ret = ret2; goto end; } if (option && option->mask & DPL_OPTION_NOALLOC) { data_buf = *data_bufp; data_len = *data_lenp; } ret2 = dpl_read_http_reply_ext(conn, 1, (option && option->mask & DPL_OPTION_NOALLOC) ? 1 : 0, &data_buf, &data_len, &headers_reply, &connection_close); if (DPL_SUCCESS != ret2) { if (DPL_EREDIRECT == ret2) { if (NULL != locationp) { location = dpl_location(headers_reply); if (NULL == location) { DPL_TRACE(conn->ctx, DPL_TRACE_ERR, "missing \"Location\" header in redirect HTTP response"); connection_close = 1; ret = DPL_FAILURE; goto end; } *locationp = strdup(location); } } ret = ret2; goto end; } if (req_mask & DPL_CDMI_REQ_HTTP_COMPAT) { //metadata are in headers ret2 = dpl_cdmi_get_metadata_from_headers(headers_reply, metadatap, sysmdp); if (DPL_SUCCESS != ret2) { ret = ret2; goto end; } } else { if (!raw) { char *tmp; //extract data+metadata from json ret2 = dpl_cdmi_parse_json_buffer(ctx, data_buf, data_len, &val); if (DPL_SUCCESS != ret2) { ret = ret2; goto end; } if (DPL_VALUE_SUBDICT != val->type) { ret = DPL_EINVAL; goto end; } ret2 = dpl_cdmi_get_metadata_from_values(val->subdict, metadatap, sysmdp); if (DPL_SUCCESS != ret2) { ret = ret2; goto end; } //find the value object ret2 = dpl_dict_get_lowered(val->subdict, "value", &var); if (DPL_SUCCESS != ret2) { ret = ret2; goto end; } if (DPL_VALUE_STRING != var->val->type) { ret = DPL_EINVAL; goto end; } ret2 = dpl_dict_get_lowered(val->subdict, "valuetransferencoding", &encoding); if (DPL_SUCCESS != ret2) { ret = ret2; goto end; } if (DPL_VALUE_STRING != encoding->val->type) { ret = DPL_EINVAL; goto end; } value_len = var->val->string->len; if (0 == strcmp(dpl_sbuf_get_str(encoding->val->string), "base64")) { orig_len = DPL_BASE64_ORIG_LENGTH(value_len); orig_buf = malloc(orig_len); if (NULL == orig_buf) { ret = DPL_ENOMEM; goto end; } orig_len = dpl_base64_decode((u_char *) dpl_sbuf_get_str(var->val->string), value_len, (u_char *) orig_buf); //swap pointers tmp = data_buf; data_buf = orig_buf; orig_buf = tmp; data_len = orig_len; } else if (0 == strcmp(dpl_sbuf_get_str(encoding->val->string), "utf-8")) { orig_buf = data_buf; orig_len = data_len; data_buf = malloc(value_len + 1); if (NULL == data_buf) { ret = DPL_ENOMEM; goto end; } memcpy(data_buf, dpl_sbuf_get_str(var->val->string), value_len); data_buf[value_len] = '\0'; data_len = value_len; } else { DPL_TRACE(conn->ctx, DPL_TRACE_ERR, "unknown \"valuetransferencoding\" received: \"%s\"", encoding->val->string); ret = DPL_EINVAL; goto end; } } } if (NULL != data_bufp) { *data_bufp = data_buf; data_buf = NULL; //consume it } if (NULL != data_lenp) *data_lenp = data_len; ret = DPL_SUCCESS; end: if (NULL != orig_buf) free(orig_buf); if (NULL != val) dpl_value_free(val); if ((option && !(option->mask & DPL_OPTION_NOALLOC)) && NULL != data_buf) free(data_buf); if (NULL != conn) { if (1 == connection_close) dpl_conn_terminate(conn); else dpl_conn_release(conn); } if (NULL != headers_reply) dpl_dict_free(headers_reply); if (NULL != headers_request) dpl_dict_free(headers_request); if (NULL != req) dpl_req_free(req); DPL_TRACE(ctx, DPL_TRACE_BACKEND, "ret=%d", ret); return ret; }
dpl_status_t dpl_cdmi_put_internal(dpl_ctx_t *ctx, int post, const char *bucket, const char *resource, const char *subresource, const dpl_option_t *option, dpl_ftype_t object_type, const dpl_condition_t *condition, const dpl_range_t *range, const dpl_dict_t *metadata, const dpl_sysmd_t *sysmd, const char *data_buf, unsigned int data_len, const dpl_dict_t *query_params, dpl_sysmd_t *returned_sysmdp, char **locationp) { int ret, ret2; dpl_conn_t *conn = NULL; char header[dpl_header_size]; u_int header_len; struct iovec iov[10]; int n_iov = 0; int connection_close = 0; dpl_dict_t *headers_request = NULL; dpl_dict_t *headers_reply = NULL; dpl_req_t *req = NULL; char *body_str = NULL; int body_len = 0; char *data_buf_returned = NULL; u_int data_len_returned; dpl_value_t *val = NULL; dpl_cdmi_req_mask_t req_mask = 0u; DPL_TRACE(ctx, DPL_TRACE_BACKEND, ""); if (option) { if (option->mask & DPL_OPTION_HTTP_COMPAT) req_mask |= DPL_CDMI_REQ_HTTP_COMPAT; } req = dpl_req_new(ctx); if (NULL == req) { ret = DPL_ENOMEM; goto end; } if (post) dpl_req_set_method(req, DPL_METHOD_POST); else dpl_req_set_method(req, DPL_METHOD_PUT); ret2 = dpl_cdmi_req_set_resource(req, resource); if (DPL_SUCCESS != ret2) { ret = ret2; goto end; } if (NULL != subresource) { ret2 = dpl_req_set_subresource(req, subresource); if (DPL_SUCCESS != ret2) { ret = ret2; goto end; } } if (NULL != condition) { dpl_req_set_condition(req, condition); } if (range) { ret2 = dpl_cdmi_req_add_range(req, req_mask, range); if (DPL_SUCCESS != ret2) { ret = ret2; goto end; } } dpl_req_set_object_type(req, object_type); dpl_req_set_data(req, data_buf, data_len); dpl_req_add_behavior(req, DPL_BEHAVIOR_MD5); if (NULL != sysmd) { ret2 = dpl_cdmi_add_sysmd_to_req(sysmd, req); if (DPL_SUCCESS != ret2) { ret = ret2; goto end; } } if (NULL != metadata) { ret2 = dpl_cdmi_req_add_metadata(req, metadata, option ? option->mask & DPL_OPTION_APPEND_METADATA : 0); if (DPL_SUCCESS != ret2) { ret = ret2; goto end; } } //build request ret2 = dpl_cdmi_req_build(req, 0, &headers_request, &body_str, &body_len); if (DPL_SUCCESS != ret2) { ret = ret2; goto end; } //contact default host dpl_req_rm_behavior(req, DPL_BEHAVIOR_VIRTUAL_HOSTING); ret2 = dpl_try_connect(ctx, req, &conn); if (DPL_SUCCESS != ret2) { ret = ret2; goto end; } ret2 = dpl_add_host_to_headers(req, headers_request); if (DPL_SUCCESS != ret2) { ret = ret2; goto end; } ret2 = dpl_req_gen_http_request(ctx, req, headers_request, NULL, header, sizeof (header), &header_len); if (DPL_SUCCESS != ret2) { ret = ret2; goto end; } iov[n_iov].iov_base = header; iov[n_iov].iov_len = header_len; n_iov++; //final crlf iov[n_iov].iov_base = "\r\n"; iov[n_iov].iov_len = 2; n_iov++; //buffer iov[n_iov].iov_base = body_str; iov[n_iov].iov_len = body_len; n_iov++; ret2 = dpl_conn_writev_all(conn, iov, n_iov, conn->ctx->write_timeout); if (DPL_SUCCESS != ret2) { DPL_TRACE(conn->ctx, DPL_TRACE_ERR, "writev failed"); connection_close = 1; ret = ret2; goto end; } ret2 = dpl_read_http_reply(conn, 1, &data_buf_returned, &data_len_returned, &headers_reply, &connection_close); if (DPL_SUCCESS != ret2) { ret = ret2; goto end; } if (post) { if (req_mask & DPL_CDMI_REQ_HTTP_COMPAT) { ret2 = dpl_cdmi_get_metadata_from_headers(headers_reply, NULL, returned_sysmdp); if (DPL_SUCCESS != ret2) { ret = ret2; goto end; } } else { ret2 = dpl_cdmi_parse_json_buffer(ctx, data_buf_returned, data_len_returned, &val); if (DPL_SUCCESS != ret2) { ret = ret2; goto end; } if (DPL_VALUE_SUBDICT != val->type) { ret = DPL_EINVAL; goto end; } ret2 = dpl_cdmi_get_metadata_from_values(val->subdict, NULL, returned_sysmdp); if (DPL_SUCCESS != ret2) { ret = ret2; goto end; } } if (NULL != returned_sysmdp) { dpl_dict_var_t *var; int base_path_len = strlen(ctx->base_path); //location contains the path to new location ret2 = dpl_dict_get_lowered(headers_reply, "location", &var); if (DPL_SUCCESS != ret2) { ret = ret2; goto end; } if (DPL_VALUE_STRING != var->val->type) { ret = DPL_EINVAL; goto end; } //remove the base_path from the answer if (strncmp(dpl_sbuf_get_str(var->val->string), ctx->base_path, base_path_len)) { ret = DPL_EINVAL; goto end; } returned_sysmdp->mask |= DPL_SYSMD_MASK_PATH; strncpy(returned_sysmdp->path, dpl_sbuf_get_str(var->val->string) + base_path_len, DPL_MAXPATHLEN); } } ret = DPL_SUCCESS; end: if (NULL != val) dpl_value_free(val); if (NULL != data_buf_returned) free(data_buf_returned); if (NULL != body_str) free(body_str); if (NULL != conn) { if (1 == connection_close) dpl_conn_terminate(conn); else dpl_conn_release(conn); } if (NULL != headers_reply) dpl_dict_free(headers_reply); if (NULL != headers_request) dpl_dict_free(headers_request); if (NULL != req) dpl_req_free(req); DPL_TRACE(ctx, DPL_TRACE_BACKEND, "ret=%d", ret); return ret; }