static oss_object_metadata_t *
construct_head_object_group_response(curl_request_param_t *user_data)
{

	oss_object_metadata_t *result = object_metadata_initialize();
	const char *key, *value;
	int flag = 1;
	char *ptr = user_data->header_buffer->ptr;
	while(*ptr != '\0') {
		char *tmp = strchr(ptr, '#');
		*tmp = '\0';
		if(flag % 2) {
			key = ptr;
		} else {
			value = ptr;
			//if(!strcmp(key, "Content-Length")) {
			//	long length = atol(value);
			//	result->set_content_length(result, length);
			//}
			result->add_default_metadata(result, key, value);
		}
		ptr = tmp + 1;
		flag ++;
	}
	oss_free_user_data(user_data);
	return result;
	
}
static oss_post_object_group_result_t *
construct_post_object_group_response(curl_request_param_t *user_data)
{
	const char *response = user_data->recv_buffer->ptr;
	assert(response != NULL);
	XmlNode *xml, *bucket_tag, *key_tag, *etag_tag, *size_tag;
	unsigned int response_len = strlen(response); 
	xml = xml_load_buffer(response, response_len);

	oss_post_object_group_result_t *result = post_object_group_result_initialize();
	bucket_tag = xml_find(xml, "Bucket");
	result->set_bucket_name(result, *bucket_tag->child->attrib);
	key_tag = xml_find(xml, "Key");
	result->set_key(result, *key_tag->child->attrib);
 	etag_tag = xml_find(xml, "ETag");
	result->set_etag(result, *etag_tag->child->attrib);
	size_tag = xml_find(xml,"Size");
	unsigned int size = (unsigned int)atoi(*size_tag->child->attrib);
	result->set_size(result, size);
 
	oss_free_user_data(user_data);
 	xml_free(xml);

	return result;
	
}
static oss_access_control_list_t *
construct_get_bucket_acl_response(
    curl_request_param_t *user_data)
{
    const char *response = user_data->recv_buffer->ptr;
    assert(response != NULL);
    XmlNode *xml, *grant_tag, *owner_tag;
    unsigned int response_len = strlen(response);
    xml = xml_load_buffer(response, response_len);

    owner_tag = xml_find(xml, "Owner");
    oss_owner_t *owner = owner_initialize_with_id(*owner_tag->child->child->attrib,
                         *owner_tag->child->next->child->attrib);

    grant_tag = xml_find(xml, "Grant");

    oss_access_control_list_t *acl = access_control_list_initialize();
    acl->set_grant(acl, *grant_tag->child->attrib);
    acl->set_owner(acl, owner);

    oss_free_user_data(user_data);
    xml_free(xml);

    return acl;

}
static oss_get_object_group_index_result_t *
construct_get_object_group_index_response(curl_request_param_t *user_data)
{
	const char *response = user_data->recv_buffer->ptr;
	assert(response != NULL);
	int i;
	XmlNode *xml, *bucket_tag, *key_tag, *etag_tag, *length_tag, *file_part_tag, *part_tag, *part_tmp;
	unsigned int response_len = strlen(response); 
	xml = xml_load_buffer(response, response_len);

	oss_get_object_group_index_result_t *result = get_object_group_index_result_initialize();
	bucket_tag = xml_find(xml, "Bucket");
	result->set_bucket_name(result, *bucket_tag->child->attrib);
	key_tag = xml_find(xml, "Key");
	result->set_key(result, *key_tag->child->attrib);
	etag_tag = xml_find(xml, "ETag");
	result->set_etag(result, *etag_tag->child->attrib);
	length_tag = xml_find(xml, "FileLength");
	unsigned int file_length = (unsigned int)atoi(*length_tag->child->attrib);
	result->set_file_length(result, file_length);
	
	file_part_tag = xml_find(xml, "FilePart");
	if(file_part_tag != NULL) {
		part_tag = file_part_tag->child;
	} else {
		part_tag = NULL;
	}
	if(part_tag != NULL) {
		part_tmp = part_tag;
		for(; part_tmp != NULL; part_tmp = part_tmp->next) {
			(result->part_number)++;
		}
		oss_multipart_object_group_t **group = (oss_multipart_object_group_t **)malloc(sizeof(oss_multipart_object_group_t *) * (result->part_number));
		for(i = 0; part_tag != NULL; i++, part_tag = part_tag->next) {
			group[i] = multipart_object_group_initialize();
			group[i]->set_etag(group[i], *part_tag->child->child->attrib);
			group[i]->set_part_name(group[i], *part_tag->child->next->child->attrib);
			int part_number = atoi(*part_tag->child->next->next->child->attrib);
			group[i]->set_part_number(group[i], part_number);
			unsigned int part_size = (unsigned int)(atoi(*part_tag->child->next->next->next->child->attrib));
			group[i]->set_part_size(group[i], part_size);
		}
		result->group = group;
	}
	
	oss_free_user_data(user_data);
 	xml_free(xml);

	return result;
	
}
static oss_object_metadata_t *
construct_get_object_metadata_response_on_success(
		curl_request_param_t *user_data)
{
	char *headers = user_data->header_buffer->ptr;
	oss_object_metadata_t *metadata = object_metadata_initialize();
	char tmpbuf[64] = {0};
	char *iter = NULL;
	iter = strtok(headers, "#");
	int flag = 0;
	while (iter != NULL) {
		if (flag % 2 == 0) {
			memset(tmpbuf, 0, 64);
			strncpy(tmpbuf, iter, 64);
		} else {
			metadata->add_default_metadata(metadata, tmpbuf, iter);
		}
		iter = strtok(NULL, "#");
		flag++;
	}
	oss_free_user_data(user_data);
	return metadata;
}
oss_object_metadata_t *
client_head_object_group(oss_client_t *client,
		oss_get_object_group_request_t *request,
		unsigned short *retcode)
{
	assert(client != NULL);
	assert(request != NULL);

	curl_request_param_t *user_data = (curl_request_param_t *)malloc(sizeof(curl_request_param_t));
	user_data->send_buffer = NULL;

	user_data->recv_buffer = (param_buffer_t *)malloc(sizeof(param_buffer_t));
	user_data->recv_buffer->ptr = (char *)malloc(sizeof(char) * 128 * 1024);
	user_data->recv_buffer->fp = NULL;
	user_data->recv_buffer->left = 128 * 1024;
	user_data->recv_buffer->allocated = 128 * 1024;

	user_data->header_buffer = (param_buffer_t *)malloc(sizeof(param_buffer_t));
	user_data->header_buffer->ptr = (char *)malloc(sizeof(char) * 4 * 1024);
	user_data->header_buffer->fp = NULL;
	user_data->header_buffer->left = 4 * 1024;
	user_data->header_buffer->allocated = 4 * 1024;

	unsigned int bucket_name_len = strlen(request->bucket_name);
	unsigned int key_len = strlen(request->key);

	char *resource = (char *)malloc(sizeof(char) * (bucket_name_len + key_len) + 16);

	char *url = (char *)malloc(sizeof(char) * 
			(bucket_name_len + key_len + strlen(client->endpoint) + 8));
	char header_host[256]  = {0};
	char header_date[48]  = {0};
	char header_auth[128] = {0};
	char *now;
	char header_if_modified_since[64] = {0};
	char header_if_unmodified_since[64] = {0};

	unsigned int sign_len = 0;
	oss_map_t *default_headers = oss_map_new(16);

	/**
	 * 构造参数,resource,url 赋值,
	 * */
	sprintf(resource, "/%s/%s", request->get_bucket_name(request),
			request->get_key(request));
	sprintf(url, "%s/%s/%s", client->endpoint, request->get_bucket_name(request),
			request->get_key(request));
	sprintf(header_host, "Host: %s", client->endpoint);
	now = (char *)oss_get_gmt_time();
	sprintf(header_date, "Date: %s", now);

	/**
	 * 请求头部构造
	 */
	oss_map_put(default_headers, OSS_DATE, now);
	
	/**
	 * 生成签名值
	 */
	char *sign = (char *)generate_authentication(client->access_key, OSS_HTTP_HEAD,
			default_headers, NULL, resource, &sign_len);

	sprintf(header_auth, "Authorization: OSS %s:%s", client->access_id, sign);

	/**
	 * 自定义 HTTP 请求头部
	 */
	struct curl_slist *http_headers = NULL;

	http_headers = curl_slist_append(http_headers, header_host);
	http_headers = curl_slist_append(http_headers, header_date);
	http_headers = curl_slist_append(http_headers, header_auth);
	if (request->get_modified_since_constraint(request) != NULL) {
		sprintf(header_if_modified_since, "If-Modified-Since: %s", request->get_modified_since_constraint(request));
		http_headers = curl_slist_append(http_headers, header_if_modified_since);
	}
	if (request->get_unmodified_since_constraint(request) != NULL) {
		sprintf(header_if_unmodified_since, "If-Unmodified-Since: %s", request->get_unmodified_since_constraint(request));
		http_headers = curl_slist_append(http_headers, header_if_unmodified_since);
	}

	/**
	 * 发送请求
	 */
	object_group_curl_operation(OSS_HTTP_HEAD, resource, url, http_headers, user_data);

	/**
	 * 释放 http_headers资源
	 */
	curl_slist_free_all(http_headers);

	oss_map_delete(default_headers);
	if(now != NULL) {
		free(now);
		now = NULL;
	}
	if(sign != NULL) {
		free(sign);
		sign = NULL;
	}
	if(resource != NULL) {
		free(resource);
		resource = NULL;
	}
	if(url != NULL) {
		free(url);
		url = NULL;
	}
	if (user_data->header_buffer->code != 200) {
		unsigned short tmp = user_data->header_buffer->code;
		if (retcode != NULL) {
			if(tmp == 404) {
				*retcode = FILE_NOT_FOUND;
			} else if(tmp == 304) {
				*retcode = NOT_MODIFIED;
			} else if(tmp == 412) {
				*retcode = PRECONDITION_FAILED;
			} else if(tmp == 403) {
				*retcode = ACCESS_DENIED;
			} else {
				*retcode = 1000;
			}
		}
		//*retcode = oss_get_retcode_from_response(user_data->recv_buffer->ptr);
		oss_free_user_data(user_data);
		return NULL;
	} else {
		if (retcode != NULL) *retcode = 0;
		return construct_head_object_group_response(user_data);
	}
}
void 
client_delete_object_group(oss_client_t *client,
		const char *bucket_name,
		const char *key,
		unsigned short *retcode)
{
	assert(client != NULL);
	assert(bucket_name != NULL);
	assert(key != NULL);

	curl_request_param_t *user_data = (curl_request_param_t *)malloc(sizeof(curl_request_param_t));
	user_data->send_buffer = NULL;


	user_data->recv_buffer = (param_buffer_t *)malloc(sizeof(param_buffer_t));
	user_data->recv_buffer->ptr = (char *)malloc(sizeof(char) * 128 * 1024);
	user_data->recv_buffer->fp = NULL;
	user_data->recv_buffer->left = 128 * 1024;
	user_data->recv_buffer->allocated = 128 * 1024;

	user_data->header_buffer = (param_buffer_t *)malloc(sizeof(param_buffer_t));
	user_data->header_buffer->ptr = (char *)malloc(sizeof(char) * 4 * 1024);
	user_data->header_buffer->fp = NULL;
	user_data->header_buffer->left = 4 * 1024;
	user_data->header_buffer->allocated = 4 * 1024;

	unsigned int bucket_name_len = strlen(bucket_name);
	unsigned int key_len = strlen(key);
	char *resource = (char *)malloc(
			sizeof(char) * (bucket_name_len + key_len) + 16);
	char *url = (char *)malloc(sizeof(char) *
			(bucket_name_len + key_len + strlen(client->endpoint) + 64));
	char header_host[256]  = {0};
	char header_date[48]  = {0};
	char header_auth[128] = {0};
	char *now;
	unsigned int sign_len = 0;
	oss_map_t *default_headers = oss_map_new(16);

	/**
	 * 构造参数,resource,url 赋值,
	 * */
	sprintf(resource, "/%s/%s", bucket_name, key);
	sprintf(url, "%s/%s/%s", client->endpoint, bucket_name, key);
	sprintf(header_host, "Host: %s", client->endpoint);
	now = (char *)oss_get_gmt_time();
	sprintf(header_date, "Date: %s", now);

	/**
	 * 请求头部构造
	 */
	oss_map_put(default_headers, OSS_DATE, now);
	
	/**
	 * 生成签名值
	 */
	char *sign = (char *)generate_authentication(client->access_key, OSS_HTTP_DELETE,
			default_headers, NULL, resource, &sign_len);
	sprintf(header_auth, "Authorization: OSS %s:%s", client->access_id, sign);
	/**
	 * 自定义 HTTP 请求头部
	 */
	struct curl_slist *http_headers = NULL;

	http_headers = curl_slist_append(http_headers, header_host);
	http_headers = curl_slist_append(http_headers, header_date);
	http_headers = curl_slist_append(http_headers, header_auth);

	/**
	 * 发送请求
	 */
	object_group_curl_operation(OSS_HTTP_DELETE, resource, url, http_headers, user_data);

	/**
	 * 释放 http_headers资源
	 */
	curl_slist_free_all(http_headers);

	oss_map_delete(default_headers);
	if(now != NULL) {
		free(now);
		now = NULL;
	}
	if(sign != NULL) {
		free(sign);
		sign = NULL;
	}
	if(resource != NULL) {
		free(resource);
		resource = NULL;
	}
	if(url != NULL) {
		free(url);
		url = NULL;
	}
	if (user_data->header_buffer->code != 204) {
		if (retcode != NULL)
			*retcode = oss_get_retcode_from_response(user_data->recv_buffer->ptr);
	} else {
		if (retcode != NULL) *retcode = NO_CONTENT;
	}
	oss_free_user_data(user_data);
}
oss_object_metadata_t *
client_get_object_group_to_file(oss_client_t *client,
		oss_get_object_group_request_t *request,
		FILE *file,
		unsigned short *retcode)
{

	assert(client != NULL);
	assert(request != NULL);
	assert(file != NULL);

	curl_request_param_t *user_data = 
		(curl_request_param_t *)malloc(sizeof(curl_request_param_t));

	user_data->send_buffer = NULL; /** 发送缓冲区设置为NULL*/

	user_data->recv_buffer = (param_buffer_t *)malloc(sizeof(param_buffer_t));
	user_data->recv_buffer->ptr = NULL;
	user_data->recv_buffer->fp = file;
	user_data->recv_buffer->left = 0;
	user_data->recv_buffer->allocated = 0;

	user_data->header_buffer = (param_buffer_t *)malloc(sizeof(param_buffer_t));
	user_data->header_buffer->ptr = (char *)malloc(sizeof(char) * MAX_HEADER_BUFFER_SIZE);
	user_data->header_buffer->fp = NULL;
	user_data->header_buffer->left = MAX_HEADER_BUFFER_SIZE;
	user_data->header_buffer->allocated = MAX_HEADER_BUFFER_SIZE;

	unsigned int bucket_name_len = strlen(request->get_bucket_name(request));
	unsigned int key_len = strlen(request->get_key(request));
	unsigned int sign_len = 0;
	char *resource = (char *)malloc(sizeof(char) * (bucket_name_len + key_len + 16));
	char *url = (char *)malloc(sizeof(char) *
			(bucket_name_len + key_len + strlen(client->endpoint) + 8));
	char header_host[256]  = {0};
	char header_date[48]  = {0};
	char *now; /**< Fri, 24 Feb 2012 02:58:28 GMT */
	char header_auth[128] = {0};
	char header_if_modified_since[64] = {0};
	char header_if_unmodified_since[64] = {0};
	char header_range[64] = {0};
	long start = 0; /**< Range 起始字节位置*/
	long length = 0; /**< Range 长度*/
	oss_map_t *default_headers = oss_map_new(16);

	/**
	 * 构造参数,resource,url 赋值
	 * */
	sprintf(resource, "/%s/%s", request->get_bucket_name(request),
			request->get_key(request));
	sprintf(url, "%s/%s/%s", client->endpoint, request->get_bucket_name(request),
			request->get_key(request));
	now = (char *)oss_get_gmt_time();

	/** 构造请求头部 */
	sprintf(header_host, "Host: %s", client->endpoint);
	sprintf(header_date, "Date: %s", now);
	oss_map_put(default_headers, OSS_DATE, now);

	/**
	 * 生成签名值
	 */
	char *sign = (char *)generate_authentication(client->access_key, OSS_HTTP_GET,
			default_headers, NULL, resource, &sign_len);
	sprintf(header_auth, "Authorization: OSS %s:%s", client->access_id, sign);

	/**
	 * 自定义 HTTP 请求头部,
	 * TODO:后续版本应支持If-Matching,If-None-Matching
	 */
	struct curl_slist *http_headers = NULL;
	
	if (request->get_modified_since_constraint(request) != NULL) {
		sprintf(header_if_modified_since, "If-Modified-Since: %s", request->get_modified_since_constraint(request));
		http_headers = curl_slist_append(http_headers, header_if_modified_since);
	}
	if (request->get_unmodified_since_constraint(request) != NULL) {
		sprintf(header_if_unmodified_since, "If-Unmodified-Since: %s", request->get_unmodified_since_constraint(request));
		http_headers = curl_slist_append(http_headers, header_if_unmodified_since);
	}
	request->get_range(request, &start, &length);
	if (start > 0 && length > 0) {
		sprintf(header_range, "Range: %ld-%ld", start, start + length);
		http_headers = curl_slist_append(http_headers, header_range);
	}

	http_headers = curl_slist_append(http_headers, header_host);
	http_headers = curl_slist_append(http_headers, header_date);
	http_headers = curl_slist_append(http_headers, header_auth);

	/**
	 * 发送请求
	 */
	object_group_curl_operation_2nd(OSS_HTTP_GET, resource, url, http_headers, user_data);

	/**
	 * 释放 http_headers资源
	 */
	curl_slist_free_all(http_headers);

	oss_map_delete(default_headers);
	if(now != NULL) {
		free(now);
		now = NULL;
	}
	if(sign != NULL) {
		free(sign);
		sign = NULL;
	}
	if(resource != NULL) {
		free(resource);
		resource = NULL;
	}
	if(url != NULL) {
		free(url);
		url = NULL;
	}
	if (user_data->header_buffer->code == 200) {
		if (retcode != NULL) *retcode = 0;
		return construct_get_object_metadata_response_on_success(user_data);
	} else {
		if (retcode != NULL) {
			if (user_data->header_buffer->code == 403) {
				*retcode = ACCESS_DENIED;
			} else if (user_data->header_buffer->code == 412) {
				*retcode = PRECONDITION_FAILED;
			} else if (user_data->header_buffer->code == 304) {
				*retcode = NOT_MODIFIED;
			} else if (user_data->header_buffer->code == 404) {
				*retcode = FILE_NOT_FOUND;
			} else {
				*retcode = 1000;
			}
		}
		oss_free_user_data(user_data);
	}

	return NULL;
}
oss_post_object_group_result_t *
client_post_object_group(oss_client_t *client,
		oss_post_object_group_request_t *request,
		unsigned short *retcode)
{
	assert(client != NULL);
	assert(request != NULL);

	curl_request_param_t *user_data = (curl_request_param_t *)malloc(sizeof(curl_request_param_t));
	user_data->send_buffer = (param_buffer_t *)malloc(sizeof(param_buffer_t));
	//user_data->send_buffer->ptr = (char *)malloc(sizeof(char) * 128 * 1024);
	user_data->send_buffer->fp = NULL;


	user_data->recv_buffer = (param_buffer_t *)malloc(sizeof(param_buffer_t));
	user_data->recv_buffer->ptr = (char *)malloc(sizeof(char) * MAX_RECV_BUFFER_SIZE);
	user_data->recv_buffer->fp = NULL;
	user_data->recv_buffer->left = MAX_RECV_BUFFER_SIZE;
	user_data->recv_buffer->allocated = MAX_RECV_BUFFER_SIZE;

	user_data->header_buffer = (param_buffer_t *)malloc(sizeof(param_buffer_t));
	user_data->header_buffer->ptr = (char *)malloc(sizeof(char) * MAX_HEADER_BUFFER_SIZE);
	user_data->header_buffer->fp = NULL;
	user_data->header_buffer->left = MAX_HEADER_BUFFER_SIZE;
	user_data->header_buffer->allocated = MAX_HEADER_BUFFER_SIZE;

	unsigned int bucket_name_len = strlen(request->bucket_name);
	unsigned int key_len = strlen(request->key);
	char *resource = (char *)malloc(sizeof(char) * (bucket_name_len + key_len) + 16);
	char *url = (char *)malloc(sizeof(char) *
			(bucket_name_len + key_len + strlen(client->endpoint) + 32));

	char header_host[256]  = {0};
	char header_date[48]  = {0};
	char header_auth[128] = {0};
	char *now;
	char part[256] = {0};
	unsigned int sign_len = 0;
	int parts = 0;
	unsigned int i = 0;

	oss_map_t *default_headers = oss_map_new(16);
	/**
	 * 构造参数,resource,url 赋值,
	 * */
	sprintf(resource, "/%s/%s?group", request->get_bucket_name(request),
			request->get_key(request));
	sprintf(url, "%s/%s/%s?group", client->endpoint, request->get_bucket_name(request),
			request->get_key(request));
	sprintf(header_host, "Host: %s", client->endpoint);
	now = (char *)oss_get_gmt_time();
	sprintf(header_date, "Date: %s", now);

	/**
	 * 请求头部构造
	 */
	oss_map_put(default_headers, OSS_DATE, now);
	oss_map_put(default_headers, OSS_CONTENT_TYPE, "application/x-www-form-urlencoded");
	
	/**
	 * 生成签名值
	 */
	char *sign = (char *)generate_authentication(client->access_key, OSS_HTTP_POST,
			default_headers, NULL, resource, &sign_len);

	sprintf(header_auth, "Authorization: OSS %s:%s", client->access_id, sign);

	oss_object_group_item_t **part_item = request->get_items(request, &parts);
	tstring_t *tstr_part_item = 
		tstring_new("<CreateFileGroup>");
	for (; i < parts; i++) {
		sprintf(part, "<Part><PartNumber>%d</PartNumber><PartName>%s</PartName><ETag>%s</ETag></Part>",
				(*(part_item + i))->get_part_number(*(part_item + i)),
				(*(part_item + i))->get_part_name(*(part_item + i)),
				(*(part_item + i))->get_etag(*(part_item + i)));
		tstring_append(tstr_part_item, part);
	}
	tstring_append(tstr_part_item, "</CreateFileGroup>\n");
	unsigned int tmp_len = strlen(tstring_data(tstr_part_item));
	char *tmp = (char *)malloc(sizeof(char) * (tmp_len + 1));
	strncpy(tmp, tstring_data(tstr_part_item), tmp_len);
	tmp[tmp_len] = '\0';

	user_data->send_buffer->ptr = tmp;
	//user_data->send_buffer->ptr = (char *)(tstring_data(tstr_part_item));
	user_data->send_buffer->left = tstring_size(tstr_part_item);
	user_data->send_buffer->allocated = tstring_size(tstr_part_item);
	/**
	 * 自定义 HTTP 请求头部
	 */
	struct curl_slist *http_headers = NULL;

	http_headers = curl_slist_append(http_headers, header_host);
	http_headers = curl_slist_append(http_headers, header_date);
	http_headers = curl_slist_append(http_headers, header_auth);

	/**
	 * 发送请求
	 */
	object_group_curl_operation(OSS_HTTP_POST, resource, url, http_headers, user_data);

	/**
	 * 释放 http_headers资源
	 */
	curl_slist_free_all(http_headers);
	tstring_free(tstr_part_item);
	oss_map_delete(default_headers);
	if(now != NULL) {
		free(now);
		now = NULL;
	}
	if(sign != NULL) {
		free(sign);
		sign = NULL;
	}
	if(resource != NULL) {
		free(resource);
		resource = NULL;
	}
	if(url != NULL) {
		free(url);
		url = NULL;
	}
	if (user_data->header_buffer->code != 200) {
		if (retcode != NULL)
			*retcode = oss_get_retcode_from_response(user_data->recv_buffer->ptr);
		oss_free_user_data(user_data);
		return NULL;
	} else {
		if (retcode != NULL) *retcode = 0;
		return construct_post_object_group_response(user_data);
	}
}
oss_access_control_list_t *
client_get_bucket_acl(oss_client_t *client,
                      const char *bucket_name,
                      unsigned short *retcode)
{
    assert(client != NULL);
    assert(bucket_name != NULL);

    curl_request_param_t *user_data =
        (curl_request_param_t *)malloc(sizeof(curl_request_param_t));

    user_data->send_buffer = NULL;

    user_data->recv_buffer = (param_buffer_t *)malloc(sizeof(param_buffer_t));
    user_data->recv_buffer->ptr = (char *)malloc(sizeof(char) * MAX_RECV_BUFFER_SIZE);
    user_data->recv_buffer->fp = NULL;
    user_data->recv_buffer->left = MAX_RECV_BUFFER_SIZE;
    user_data->recv_buffer->allocated = MAX_RECV_BUFFER_SIZE;
    memset(user_data->recv_buffer->ptr, 0, MAX_RECV_BUFFER_SIZE);

    user_data->header_buffer = (param_buffer_t *)malloc(sizeof(param_buffer_t));
    user_data->header_buffer->ptr = (char *)malloc(sizeof(char) * MAX_HEADER_BUFFER_SIZE);
    user_data->header_buffer->fp = NULL;
    user_data->header_buffer->left = MAX_HEADER_BUFFER_SIZE;
    user_data->header_buffer->allocated = MAX_HEADER_BUFFER_SIZE;
    memset(user_data->header_buffer->ptr, 0, MAX_HEADER_BUFFER_SIZE);

    unsigned int bucket_name_len = strlen(bucket_name);
    char *resource = (char *)malloc(sizeof(char) * bucket_name_len + 16);
    char *url = (char *)malloc(
                    sizeof(char) * (bucket_name_len + strlen(client->endpoint) + 8));

    char header_host[256]  = {0};
    char header_date[48]  = {0};
    char header_auth[128] = {0};
    char *now;
    unsigned int sign_len = 0;

    oss_map_t *default_headers = oss_map_new(16);

    /**
     * 构造参数,resource,url 赋值,
     * */
    sprintf(resource, "/%s?acl", bucket_name);
    sprintf(url, "%s/%s?acl", client->endpoint, bucket_name);
    sprintf(header_host,"Host: %s", client->endpoint);
    now = (char *)oss_get_gmt_time();
    sprintf(header_date, "Date: %s", now);

    /**
     * 请求头部构造
     */
    oss_map_put(default_headers, OSS_DATE, now);

    /**
     * 生成签名值
     */
    char *sign = (char *)generate_authentication(client->access_key, OSS_HTTP_GET,
                 default_headers, NULL, resource, &sign_len);

    sprintf(header_auth, "Authorization: OSS %s:%s", client->access_id, sign);

    /**
     * 自定义 HTTP 请求头部
     */
    struct curl_slist *http_headers = NULL;

    http_headers = curl_slist_append(http_headers, header_host);
    http_headers = curl_slist_append(http_headers, header_date);
    http_headers = curl_slist_append(http_headers, header_auth);

    /**
     * 发送请求
     */
    bucket_curl_operation(OSS_HTTP_GET, resource, url, http_headers, user_data);

    /**
     * 释放 http_headers资源
     */
    curl_slist_free_all(http_headers);
    oss_map_delete(default_headers);
    if(now != NULL) {
        free(now);
        now = NULL;
    }
    if(sign != NULL) {
        free(sign);
        sign = NULL;
    }
    if(resource != NULL) {
        free(resource);
        resource = NULL;
    }
    if(url != NULL) {
        free(url);
        url = NULL;
    }
    if (user_data->header_buffer->code != 200) {
        if (retcode != NULL)
            *retcode = oss_get_retcode_from_response(user_data->recv_buffer->ptr);
        oss_free_user_data(user_data);
        return NULL;
    } else {
        if (retcode != NULL) *retcode = 0;
        return construct_get_bucket_acl_response(user_data);
    }
}
static oss_object_listing_t *
construct_list_objects_response(
    curl_request_param_t *user_data)
{
    assert(user_data != NULL);

    const char *response = user_data->recv_buffer->ptr;
    int i;
    XmlNode *xml = NULL;
    XmlNode *name_tag, *prefix_tag, *marker_tag, *max_keys_tag;
    XmlNode *delimiter_tag, *is_truncated_tag, *next_marker_tag;
    XmlNode *contents_tag, *common_prefixes_tag, *contents_tmp;
    XmlNode *common_prefixes_tmp = NULL;

    unsigned int response_len = strlen(response);
    xml = xml_load_buffer(response, response_len);
    oss_object_listing_t *object_listing = object_listing_initialize();

    name_tag = xml_find(xml, "Name");
    object_listing->set_bucket_name(object_listing, *name_tag->child->attrib);

    prefix_tag = xml_find(xml, "Prefix");
    if(prefix_tag->child == NULL) {
        object_listing->set_prefix(object_listing, "");
    } else {
        object_listing->set_prefix(object_listing, *prefix_tag->child->attrib);
    }

    marker_tag = xml_find(xml, "Marker");
    if(marker_tag->child == NULL) {
        object_listing->set_marker(object_listing, "");
    } else {
        object_listing->set_marker(object_listing, *marker_tag->child->attrib);
    }

    next_marker_tag = xml_find(xml, "NextMarker");
    if(next_marker_tag == NULL) {
        object_listing->set_next_marker(object_listing, "");
    } else {
        if(next_marker_tag->child == NULL) {
            object_listing->set_next_marker(object_listing, "");
        } else {
            object_listing->set_next_marker(object_listing,
                                            *next_marker_tag->child->attrib);
        }
    }

    max_keys_tag = xml_find(xml, "MaxKeys");
    if(max_keys_tag->child == NULL)
    {
        object_listing->set_max_keys(object_listing, 0);
    } else {
        //经过分析, 此处atoi是OK的
        int max_keys = atoi(*max_keys_tag->child->attrib);
        object_listing->set_max_keys(object_listing, max_keys);
    }

    delimiter_tag = xml_find(xml, "Delimiter");
    if(delimiter_tag->child == NULL) {
        object_listing->set_delimiter(object_listing, "");
    } else {
        object_listing->set_delimiter(object_listing, *delimiter_tag->child->attrib);
    }

    is_truncated_tag = xml_find(xml, "IsTruncated");
    if(is_truncated_tag->child == NULL) {
        object_listing->set_is_truncated(object_listing, false);
    } else {
        if(strcmp(*is_truncated_tag->child->attrib, "false") == 0) {
            object_listing->set_is_truncated(object_listing, false);
        } else {
            object_listing->set_is_truncated(object_listing, true);
        }
    }

    contents_tag = xml_find(xml, "Contents");
    if(contents_tag != NULL) {
        contents_tmp = contents_tag;
        for(; contents_tmp != NULL; contents_tmp = contents_tmp->next) {
            if(strcmp(contents_tmp->name, "Contents") == 0)
                (object_listing->_counts_summaries)++;
            else break;
        }
        oss_object_summary_t **summaries = (oss_object_summary_t **)malloc(
                                               sizeof(oss_object_summary_t *) * (object_listing->_counts_summaries));

        for(i = 0; i < object_listing->_counts_summaries; i++, contents_tag = contents_tag->next) {
            summaries[i] = object_summary_initialize();
            summaries[i]->set_key(summaries[i],
                                  *contents_tag->child->child->attrib);
            summaries[i]->set_last_modified(summaries[i],
                                            *contents_tag->child->next->child->attrib);
            summaries[i]->set_etag(summaries[i],
                                   *contents_tag->child->next->next->child->attrib);
            summaries[i]->set_type(summaries[i],
                                   *contents_tag->child->next->next->next->child->attrib);
            long size = atol(*contents_tag->child->next->next->next->next->child->attrib);
            summaries[i]->set_size(summaries[i], size);
            summaries[i]->set_storage_class(summaries[i],
                                            *contents_tag->child->next->next->next->next->next->child->attrib);
            summaries[i]->owner = owner_initialize_with_id(
                                      *contents_tag->child->next->next->next->next->next->next->child->child->attrib,
                                      *contents_tag->child->next->next->next->next->next->next->child->next->child->attrib);
        }
        object_listing->summaries = summaries;
    }

    common_prefixes_tag = xml_find(xml, "CommonPrefixes");
    if(common_prefixes_tag != NULL) {
        common_prefixes_tmp = common_prefixes_tag;
        for(; common_prefixes_tmp != NULL;
                common_prefixes_tmp = common_prefixes_tmp->next) {
            (object_listing->_counts_common_prefixes)++;
        }
        char **common_prefixes = (char **)malloc(
                                     sizeof(char *) * (object_listing->_counts_common_prefixes));
        for(i = 0; common_prefixes_tag != NULL;
                i++, common_prefixes_tag = common_prefixes_tag->next) {
            const char *tmp = *common_prefixes_tag->child->child->attrib;
            unsigned int common_prefixes_len = strlen(tmp);
            common_prefixes[i] = (char *)malloc(
                                     sizeof(char) * (common_prefixes_len + 1));
            strncpy(common_prefixes[i], tmp, common_prefixes_len);
            common_prefixes[i][common_prefixes_len] = '\0';
        }
        object_listing->common_prefixes = common_prefixes;
    }

    oss_free_user_data(user_data);
    xml_free(xml);

    return object_listing;

}