static void dyn_array_free(struct dynbuf *db, size_t num_elements);
static void pair_array_free(struct pair *pair_array, size_t num_elements);
-static CURLcode split_to_dyn_array(const char *source, char split_by,
- struct dynbuf db[MAX_QUERY_COMPONENTS], size_t *num_splits);
+static CURLcode split_to_dyn_array(const char *source,
+ struct dynbuf db[MAX_QUERY_COMPONENTS],
+ size_t *num_splits);
static bool is_reserved_char(const char c);
static CURLcode uri_encode_path(struct Curl_str *original_path,
- struct dynbuf *new_path);
+ struct dynbuf *new_path);
static CURLcode encode_query_component(char *component, size_t len,
- struct dynbuf *db);
+ struct dynbuf *db);
static CURLcode http_aws_decode_encode(const char *in, size_t in_len,
- struct dynbuf *out);
+ struct dynbuf *out);
static bool should_urlencode(struct Curl_str *service_name);
static void sha256_to_hex(char *dst, unsigned char *sha)
size_t num_query_components;
size_t counted_query_components = 0;
size_t index;
- size_t in_key_len;
- size_t in_value_len;
- size_t query_part_len;
- const char *in_key;
- char *in_value;
- char *offset;
- char *key_ptr;
- char *value_ptr;
- const char *query_part;
if(!query)
return result;
- result = split_to_dyn_array(query, '&', &query_array[0],
- &num_query_components);
+ result = split_to_dyn_array(query, &query_array[0],
+ &num_query_components);
if(result) {
goto fail;
}
/* Create list of pairs, each pair containing an encoded query
* component */
- for(index = 0; index < num_query_components;
- index++) {
-
- query_part_len = curlx_dyn_len(&query_array[index]);
- query_part = curlx_dyn_ptr(&query_array[index]);
+ for(index = 0; index < num_query_components; index++) {
+ const char *in_key;
+ size_t in_key_len;
+ char *offset;
+ size_t query_part_len = curlx_dyn_len(&query_array[index]);
+ char *query_part = curlx_dyn_ptr(&query_array[index]);
in_key = query_part;
/* Decode/encode the key */
result = http_aws_decode_encode(in_key, in_key_len,
- &encoded_query_array[index].key);
+ &encoded_query_array[index].key);
if(result) {
goto fail;
}
/* Decode/encode the value if it exists */
if(offset && offset != (query_part + query_part_len - 1)) {
- in_value = offset + 1;
+ size_t in_value_len;
+ const char *in_value = offset + 1;
in_value_len = query_part + query_part_len - (offset + 1);
result = http_aws_decode_encode(in_value, in_value_len,
- &encoded_query_array[index].value);
+ &encoded_query_array[index].value);
if(result) {
goto fail;
}
/* Sort the encoded query components by key and value */
qsort(&encoded_query_array, num_query_components,
- sizeof(struct pair), compare_func);
+ sizeof(struct pair), compare_func);
/* Append the query components together to make a full query string */
for(index = 0; index < num_query_components; index++) {
- key_ptr = curlx_dyn_ptr(&encoded_query_array[index].key);
- value_ptr = curlx_dyn_ptr(&encoded_query_array[index].value);
-
- if(value_ptr && strlen(value_ptr)) {
- result = curlx_dyn_addf(dq, "%s=%s&", key_ptr, value_ptr);
- }
- else {
- /* Empty value is always encoded to key= */
- result = curlx_dyn_addf(dq, "%s=&", key_ptr);
- }
- if(result) {
- goto fail;
+ if(index)
+ result = curlx_dyn_addn(dq, "&", 1);
+ if(!result) {
+ char *key_ptr = curlx_dyn_ptr(&encoded_query_array[index].key);
+ char *value_ptr = curlx_dyn_ptr(&encoded_query_array[index].value);
+ size_t vlen = curlx_dyn_len(&encoded_query_array[index].value);
+ if(value_ptr && vlen) {
+ result = curlx_dyn_addf(dq, "%s=%s", key_ptr, value_ptr);
+ }
+ else {
+ /* Empty value is always encoded to key= */
+ result = curlx_dyn_addf(dq, "%s=", key_ptr);
+ }
}
+ if(result)
+ break;
}
- /* Remove trailing & */
- result = curlx_dyn_setlen(dq, curlx_dyn_len(dq)-1);
fail:
- pair_array_free(&encoded_query_array[0], counted_query_components);
+ if(counted_query_components)
+ /* the encoded_query_array might not be initialized yet */
+ pair_array_free(&encoded_query_array[0], counted_query_components);
dyn_array_free(&query_array[0], num_query_components);
return result;
}
{
size_t index;
- for(index = 0; index < num_elements; index++) {
+ for(index = 0; index < num_elements; index++)
curlx_dyn_free((&db[index]));
- }
-
}
/*
-* Splits source string by split_by, and creates an array of dynbuf in db
-* db is initialized by this function
+* Splits source string by SPLIT_BY, and creates an array of dynbuf in db.
+* db is initialized by this function.
* Caller is responsible for freeing the array elements with dyn_array_free
*/
-static CURLcode split_to_dyn_array(const char *source, char split_by,
- struct dynbuf db[MAX_QUERY_COMPONENTS], size_t *num_splits_out)
-{
+#define SPLIT_BY '&'
+static CURLcode split_to_dyn_array(const char *source,
+ struct dynbuf db[MAX_QUERY_COMPONENTS],
+ size_t *num_splits_out)
+{
CURLcode result = CURLE_OK;
-
size_t len = strlen(source);
-
size_t pos = 0; /* Position in result buffer */
size_t start = 0; /* Start of current segment */
size_t segment_length = 0;
size_t index = 0;
- size_t num_splits;
+ size_t num_splits = 0;
- /* Split source_ptr on split_by and store the segment offsets and
- * length in array */
- num_splits = 0;
+ /* Split source_ptr on SPLIT_BY and store the segment offsets and length in
+ * array */
for(pos = 0; pos < len; pos++) {
- if(source[pos] == split_by) {
+ if(source[pos] == SPLIT_BY) {
if(segment_length) {
curlx_dyn_init(&db[index], segment_length + 1);
result = curlx_dyn_addn(&db[index], &source[start],
- segment_length);
+ segment_length);
if(result) {
goto fail;
}
if(segment_length) {
curlx_dyn_init(&db[index], segment_length + 1);
result = curlx_dyn_addn(&db[index], &source[start],
- segment_length);
+ segment_length);
if(result) {
goto fail;
}
if(++num_splits == MAX_QUERY_COMPONENTS) {
goto fail;
}
-}
+ }
fail:
*num_splits_out = num_splits;
return result;
}
static CURLcode uri_encode_path(struct Curl_str *original_path,
-struct dynbuf *new_path)
+ struct dynbuf *new_path)
{
-
const char *p = curlx_str(original_path);
CURLcode result = CURLE_OK;
size_t index;
static CURLcode encode_query_component(char *component, size_t len,
- struct dynbuf *db)
+ struct dynbuf *db)
{
-
size_t index;
CURLcode result = CURLE_OK;
unsigned char this_char;
*/
static CURLcode http_aws_decode_encode(const char *in, size_t in_len,
-struct dynbuf *out)
+ struct dynbuf *out)
{
- CURLcode result = CURLE_OK;
char *out_s;
size_t out_s_len;
+ CURLcode result =
+ Curl_urldecode(in, in_len, &out_s, &out_s_len, REJECT_NADA);
- result = Curl_urldecode(in, in_len, &out_s, &out_s_len, REJECT_NADA);
-
- if(result) {
+ if(result)
goto fail;
- }
+
result = encode_query_component(out_s, out_s_len, out);
Curl_safefree(out_s);
fail: