summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/apr_json.h20
-rw-r--r--jose/apr_jose_encode.c102
-rw-r--r--json/apr_json.c52
-rw-r--r--json/apr_json_decode.c2
4 files changed, 109 insertions, 67 deletions
diff --git a/include/apr_json.h b/include/apr_json.h
index c05f6704c..55c4806b5 100644
--- a/include/apr_json.h
+++ b/include/apr_json.h
@@ -271,6 +271,22 @@ APR_DECLARE(apr_json_value_t *)
/**
* Associate a value with a key in a JSON object.
* @param obj The JSON object.
+ * @param key Pointer to the key string.
+ * @param klen Length of the key, or APR_JSON_VALUE_STRING if NUL
+ * terminated.
+ * @param val Value to associate with the key.
+ * @param pool Pool to use.
+ * @return APR_SUCCESS on success, APR_EINVAL if the key is
+ * NULL or not a string, or the object is not an APR_JSON_OBJECT.
+ * @remark If the value is NULL the key value pair is deleted.
+ */
+APR_DECLARE(apr_status_t) apr_json_object_set(apr_json_value_t *obj,
+ const char *key, apr_ssize_t klen, apr_json_value_t *val,
+ apr_pool_t *pool) __attribute__((nonnull(1, 2, 5)));
+
+/**
+ * Associate a value with a key in a JSON object, preserving whitespace.
+ * @param obj The JSON object.
* @param key Pointer to the key string, including any whitespace
* required.
* @param val Value to associate with the key.
@@ -279,9 +295,9 @@ APR_DECLARE(apr_json_value_t *)
* NULL or not a string, or the object is not an APR_JSON_OBJECT.
* @remark If the value is NULL the key value pair is deleted.
*/
-APR_DECLARE(apr_status_t) apr_json_object_set(apr_json_value_t *obj,
+APR_DECLARE(apr_status_t) apr_json_object_set_ex(apr_json_value_t *obj,
apr_json_value_t *key, apr_json_value_t *val,
- apr_pool_t *pool) __attribute__((nonnull(1, 4)));
+ apr_pool_t *pool) __attribute__((nonnull(1, 2, 4)));
/**
* Look up the value associated with a key in a JSON object.
diff --git a/jose/apr_jose_encode.c b/jose/apr_jose_encode.c
index 43a4adc8b..71088b8ca 100644
--- a/jose/apr_jose_encode.c
+++ b/jose/apr_jose_encode.c
@@ -263,7 +263,7 @@ static apr_status_t apr_jose_encode_json_jwe(apr_bucket_brigade *brigade,
apr_pool_t *p)
{
- apr_json_value_t *json, *key, *val;
+ apr_json_value_t *json;
char *buf;
const char *buf64;
apr_size_t len;
@@ -300,10 +300,9 @@ static apr_status_t apr_jose_encode_json_jwe(apr_bucket_brigade *brigade,
apr_brigade_cleanup(bb);
- key = apr_json_string_create(p, "protected",
- APR_JSON_VALUE_STRING);
- val = apr_json_string_create(p, buf, len);
- apr_json_object_set(json, key, val, p);
+ apr_json_object_set(json, "protected",
+ APR_JSON_VALUE_STRING,
+ apr_json_string_create(p, buf, len), p);
}
@@ -311,9 +310,8 @@ static apr_status_t apr_jose_encode_json_jwe(apr_bucket_brigade *brigade,
if (e->unprotected) {
- key = apr_json_string_create(p, "unprotected",
- APR_JSON_VALUE_STRING);
- apr_json_object_set(json, key, e->unprotected, p);
+ apr_json_object_set(json, "unprotected",
+ APR_JSON_VALUE_STRING, e->unprotected, p);
}
@@ -341,9 +339,8 @@ static apr_status_t apr_jose_encode_json_jwe(apr_bucket_brigade *brigade,
/* create header */
- key = apr_json_string_create(p, "header",
- APR_JSON_VALUE_STRING);
- apr_json_object_set(json, key, recip->header, p);
+ apr_json_object_set(json, "header",
+ APR_JSON_VALUE_STRING, recip->header, p);
apr_brigade_cleanup(bb);
@@ -353,10 +350,9 @@ static apr_status_t apr_jose_encode_json_jwe(apr_bucket_brigade *brigade,
recip->ekey.len,
APR_ENCODE_BASE64URL, &len64);
- key = apr_json_string_create(p, "encrypted_key",
- APR_JSON_VALUE_STRING);
- val = apr_json_string_create(p, buf64, len64);
- apr_json_object_set(json, key, val, p);
+ apr_json_object_set(json, "encrypted_key",
+ APR_JSON_VALUE_STRING,
+ apr_json_string_create(p, buf64, len64), p);
}
@@ -368,10 +364,9 @@ static apr_status_t apr_jose_encode_json_jwe(apr_bucket_brigade *brigade,
/* create recipients element */
- key = apr_json_string_create(p, "recipients",
- APR_JSON_VALUE_STRING);
recips = apr_json_array_create(p, jwe->recipients->nelts);
- apr_json_object_set(json, key, recips, p);
+ apr_json_object_set(json, "recipients",
+ APR_JSON_VALUE_STRING, recips, p);
/* populate each recipient */
@@ -405,9 +400,8 @@ static apr_status_t apr_jose_encode_json_jwe(apr_bucket_brigade *brigade,
/* create header */
- key = apr_json_string_create(p, "header",
- APR_JSON_VALUE_STRING);
- apr_json_object_set(r, key, recip->header, p);
+ apr_json_object_set(r, "header",
+ APR_JSON_VALUE_STRING, recip->header, p);
apr_brigade_cleanup(bb);
@@ -417,10 +411,9 @@ static apr_status_t apr_jose_encode_json_jwe(apr_bucket_brigade *brigade,
recip->ekey.len,
APR_ENCODE_BASE64URL, &len64);
- key = apr_json_string_create(p, "encrypted_key",
- APR_JSON_VALUE_STRING);
- val = apr_json_string_create(p, buf64, len64);
- apr_json_object_set(r, key, val, p);
+ apr_json_object_set(r, "encrypted_key",
+ APR_JSON_VALUE_STRING,
+ apr_json_string_create(p, buf64, len64), p);
}
if (APR_SUCCESS != status) {
@@ -436,9 +429,8 @@ static apr_status_t apr_jose_encode_json_jwe(apr_bucket_brigade *brigade,
buf64 = apr_pencode_base64_binary(p, e->iv.data, e->iv.len,
APR_ENCODE_BASE64URL, &len64);
- key = apr_json_string_create(p, "iv", APR_JSON_VALUE_STRING);
- val = apr_json_string_create(p, buf64, len64);
- apr_json_object_set(json, key, val, p);
+ apr_json_object_set(json, "iv", APR_JSON_VALUE_STRING,
+ apr_json_string_create(p, buf64, len64), p);
}
/* create aad */
@@ -448,9 +440,8 @@ static apr_status_t apr_jose_encode_json_jwe(apr_bucket_brigade *brigade,
buf64 = apr_pencode_base64_binary(p, e->aad.data, e->aad.len,
APR_ENCODE_BASE64URL, &len64);
- key = apr_json_string_create(p, "aad", APR_JSON_VALUE_STRING);
- val = apr_json_string_create(p, buf64, len64);
- apr_json_object_set(json, key, val, p);
+ apr_json_object_set(json, "aad", APR_JSON_VALUE_STRING,
+ apr_json_string_create(p, buf64, len64), p);
}
/* create ciphertext */
@@ -460,9 +451,8 @@ static apr_status_t apr_jose_encode_json_jwe(apr_bucket_brigade *brigade,
buf64 = apr_pencode_base64_binary(p, e->cipher.data, e->cipher.len,
APR_ENCODE_BASE64URL, &len64);
- key = apr_json_string_create(p, "ciphertext", APR_JSON_VALUE_STRING);
- val = apr_json_string_create(p, buf64, len64);
- apr_json_object_set(json, key, val, p);
+ apr_json_object_set(json, "ciphertext", APR_JSON_VALUE_STRING,
+ apr_json_string_create(p, buf64, len64), p);
}
/* create tag */
@@ -472,9 +462,8 @@ static apr_status_t apr_jose_encode_json_jwe(apr_bucket_brigade *brigade,
buf64 = apr_pencode_base64_binary(p, e->tag.data, e->tag.len,
APR_ENCODE_BASE64URL, &len64);
- key = apr_json_string_create(p, "tag", APR_JSON_VALUE_STRING);
- val = apr_json_string_create(p, buf64, len64);
- apr_json_object_set(json, key, val, p);
+ apr_json_object_set(json, "tag", APR_JSON_VALUE_STRING,
+ apr_json_string_create(p, buf64, len64), p);
}
}
@@ -493,7 +482,7 @@ static apr_status_t apr_jose_encode_json_jws(apr_bucket_brigade *brigade,
apr_brigade_flush flush, void *ctx, apr_jose_t *jose, apr_jose_cb_t *cb,
apr_pool_t *p)
{
- apr_json_value_t *json, *key, *val;
+ apr_json_value_t *json;
char *buf;
const char *buf64;
apr_size_t len;
@@ -530,9 +519,8 @@ static apr_status_t apr_jose_encode_json_jws(apr_bucket_brigade *brigade,
/* add the payload to our json */
- key = apr_json_string_create(p, "payload", APR_JSON_VALUE_STRING);
- val = apr_json_string_create(p, buf64, len64);
- apr_json_object_set(json, key, val, p);
+ apr_json_object_set(json, "payload", APR_JSON_VALUE_STRING,
+ apr_json_string_create(p, buf64, len64), p);
/* calculate the flattened signature */
@@ -551,9 +539,8 @@ static apr_status_t apr_jose_encode_json_jws(apr_bucket_brigade *brigade,
return status;
}
- key = apr_json_string_create(p, "protected", APR_JSON_VALUE_STRING);
- val = apr_json_string_create(p, buf, len);
- apr_json_object_set(json, key, val, p);
+ apr_json_object_set(json, "protected", APR_JSON_VALUE_STRING,
+ apr_json_string_create(p, buf, len), p);
status = apr_brigade_write(bb, flush, ctx, ".", 1);
if (APR_SUCCESS != status) {
@@ -576,8 +563,8 @@ static apr_status_t apr_jose_encode_json_jws(apr_bucket_brigade *brigade,
/* create header */
- key = apr_json_string_create(p, "header", APR_JSON_VALUE_STRING);
- apr_json_object_set(json, key, jws->signature->header, p);
+ apr_json_object_set(json, "header", APR_JSON_VALUE_STRING,
+ jws->signature->header, p);
apr_brigade_cleanup(bb);
@@ -587,9 +574,8 @@ static apr_status_t apr_jose_encode_json_jws(apr_bucket_brigade *brigade,
jws->signature->sig.data, jws->signature->sig.len,
APR_ENCODE_BASE64URL, &len64);
- key = apr_json_string_create(p, "signature", APR_JSON_VALUE_STRING);
- val = apr_json_string_create(p, buf64, len64);
- apr_json_object_set(json, key, val, p);
+ apr_json_object_set(json, "signature", APR_JSON_VALUE_STRING,
+ apr_json_string_create(p, buf64, len64), p);
}
@@ -602,9 +588,9 @@ static apr_status_t apr_jose_encode_json_jws(apr_bucket_brigade *brigade,
/* create signatures element */
- key = apr_json_string_create(p, "signatures", APR_JSON_VALUE_STRING);
sigs = apr_json_array_create(p, jws->signatures->nelts);
- apr_json_object_set(json, key, sigs, p);
+ apr_json_object_set(json, "signatures", APR_JSON_VALUE_STRING,
+ sigs, p);
/* populate each signature */
@@ -630,9 +616,8 @@ static apr_status_t apr_jose_encode_json_jws(apr_bucket_brigade *brigade,
/* add protected header to array */
- key = apr_json_string_create(p, "protected", APR_JSON_VALUE_STRING);
- val = apr_json_string_create(p, buf, len);
- apr_json_object_set(s, key, val, p);
+ apr_json_object_set(s, "protected", APR_JSON_VALUE_STRING,
+ apr_json_string_create(p, buf, len), p);
status = apr_brigade_write(bb, flush, ctx, ".", 1);
if (APR_SUCCESS != status) {
@@ -655,8 +640,8 @@ static apr_status_t apr_jose_encode_json_jws(apr_bucket_brigade *brigade,
/* create header */
- key = apr_json_string_create(p, "header", APR_JSON_VALUE_STRING);
- apr_json_object_set(s, key, sig->header, p);
+ apr_json_object_set(s, "header", APR_JSON_VALUE_STRING,
+ sig->header, p);
apr_brigade_cleanup(bb);
@@ -666,9 +651,8 @@ static apr_status_t apr_jose_encode_json_jws(apr_bucket_brigade *brigade,
sig->sig.len,
APR_ENCODE_BASE64URL, &len64);
- key = apr_json_string_create(p, "signature", APR_JSON_VALUE_STRING);
- val = apr_json_string_create(p, buf64, len64);
- apr_json_object_set(s, key, val, p);
+ apr_json_object_set(s, "signature", APR_JSON_VALUE_STRING,
+ apr_json_string_create(p, buf64, len64), p);
}
if (APR_SUCCESS != status) {
diff --git a/json/apr_json.c b/json/apr_json.c
index ad4281cc2..4b5867fc0 100644
--- a/json/apr_json.c
+++ b/json/apr_json.c
@@ -129,13 +129,55 @@ apr_json_value_t *apr_json_null_create(apr_pool_t *pool)
return json;
}
-apr_status_t apr_json_object_set(apr_json_value_t *object, apr_json_value_t *key,
- apr_json_value_t *val, apr_pool_t *pool)
+apr_status_t apr_json_object_set(apr_json_value_t *object,
+ const char *key, apr_ssize_t klen, apr_json_value_t *val,
+ apr_pool_t *pool)
{
apr_json_kv_t *kv;
apr_hash_t *hash;
- if (object->type != APR_JSON_OBJECT || !key
+ if (object->type != APR_JSON_OBJECT) {
+ return APR_EINVAL;
+ }
+
+ if (klen == APR_JSON_VALUE_STRING) {
+ klen = strlen(key);
+ }
+
+ hash = object->value.object->hash;
+
+ kv = apr_hash_get(hash, key, klen);
+
+ if (!val) {
+ if (kv) {
+ apr_hash_set(hash, key, klen, NULL);
+ APR_RING_REMOVE((kv), link);
+ }
+ return APR_SUCCESS;
+ }
+
+ if (!kv) {
+ kv = apr_palloc(pool, sizeof(apr_json_kv_t));
+ APR_RING_ELEM_INIT(kv, link);
+ APR_JSON_OBJECT_INSERT_TAIL(object->value.object, kv);
+ apr_hash_set(hash, key, klen,
+ kv);
+ }
+
+ kv->k = apr_json_string_create(pool, key, klen);
+ kv->v = val;
+
+ return APR_SUCCESS;
+}
+
+apr_status_t apr_json_object_set_ex(apr_json_value_t *object,
+ apr_json_value_t *key, apr_json_value_t *val,
+ apr_pool_t *pool)
+{
+ apr_json_kv_t *kv;
+ apr_hash_t *hash;
+
+ if (object->type != APR_JSON_OBJECT
|| key->type != APR_JSON_STRING) {
return APR_EINVAL;
}
@@ -316,7 +358,7 @@ apr_json_value_t *apr_json_overlay(apr_pool_t *p,
if (!apr_hash_get(overlay->value.object->hash, kv->k->value.string.p,
kv->k->value.string.len)) {
- apr_json_object_set(res, kv->k, kv->v, p);
+ apr_json_object_set_ex(res, kv->k, kv->v, p);
}
else if (APR_JSON_FLAGS_STRICT & flags) {
@@ -329,7 +371,7 @@ apr_json_value_t *apr_json_overlay(apr_pool_t *p,
kv != APR_RING_SENTINEL(&(overlay->value.object)->list, apr_json_kv_t, link);
kv = APR_RING_NEXT((kv), link)) {
- apr_json_object_set(res, kv->k, kv->v, p);
+ apr_json_object_set_ex(res, kv->k, kv->v, p);
}
diff --git a/json/apr_json_decode.c b/json/apr_json_decode.c
index c790d6fdc..5ef2cb854 100644
--- a/json/apr_json_decode.c
+++ b/json/apr_json_decode.c
@@ -501,7 +501,7 @@ static apr_status_t apr_json_decode_object(apr_json_scanner_t * self,
if ((status = apr_json_decode_value(self, &value)))
goto out;
- apr_json_object_set(json, key, value, self->pool);
+ apr_json_object_set_ex(json, key, value, self->pool);
if (self->p == self->e) {
status = APR_EOF;