static int json_db_del_key(void *db, heim_string_t table, heim_data_t key, heim_error_t *error) { json_db_t jsondb = db; heim_string_t key_string; const heim_octet_string *key_data = heim_data_get_data(key); if (error) *error = NULL; if (strnlen(key_data->data, key_data->length) != key_data->length) return HEIM_ERROR(error, EINVAL, (EINVAL, N_("JSON DB requires keys that are actually strings", ""))); key_string = heim_string_create_with_bytes(key_data->data, key_data->length); if (key_string == NULL) return HEIM_ENOMEM(error); if (table == NULL) table = HSTR(""); heim_path_delete(jsondb->dict, error, table, key_string, NULL); heim_release(key_string); return 0; }
static heim_data_t json_db_copy_value(void *db, heim_string_t table, heim_data_t key, heim_error_t *error) { json_db_t jsondb = db; heim_string_t key_string; const heim_octet_string *key_data = heim_data_get_data(key); struct stat st; heim_data_t result; if (error) *error = NULL; if (strnlen(key_data->data, key_data->length) != key_data->length) { HEIM_ERROR(error, EINVAL, (EINVAL, N_("JSON DB requires keys that are actually " "strings", ""))); return NULL; } if (stat(heim_string_get_utf8(jsondb->dbname), &st) == -1) { HEIM_ERROR(error, errno, (errno, N_("Could not stat JSON DB file", ""))); return NULL; } if (st.st_mtime > jsondb->last_read_time || st.st_ctime > jsondb->last_read_time) { heim_dict_t contents = NULL; int ret; /* Ignore file is gone (ENOENT) */ ret = read_json(heim_string_get_utf8(jsondb->dbname), (heim_object_t *)&contents, error); if (ret) return NULL; if (contents == NULL) contents = heim_dict_create(29); heim_release(jsondb->dict); jsondb->dict = contents; jsondb->last_read_time = time(NULL); } key_string = heim_string_create_with_bytes(key_data->data, key_data->length); if (key_string == NULL) { (void) HEIM_ENOMEM(error); return NULL; } result = heim_path_copy(jsondb->dict, error, table, key_string, NULL); heim_release(key_string); return result; }
static heim_string_t to_base64(heim_data_t data, heim_error_t *error) { char *b64 = NULL; heim_string_t s = NULL; const heim_octet_string *d; int ret; d = heim_data_get_data(data); ret = rk_base64_encode(d->data, d->length, &b64); if (ret < 0 || b64 == NULL) goto enomem; s = heim_string_ref_create(b64, free); if (s == NULL) goto enomem; return s; enomem: free(b64); if (error) *error = heim_error_create_enomem(); return NULL; }
static int base2json(heim_object_t obj, struct twojson *j) { heim_tid_t type; int first = 0; if (obj == NULL) { if (j->flags & HEIM_JSON_F_CNULL2JSNULL) { obj = heim_null_create(); } else if (j->flags & HEIM_JSON_F_NO_C_NULL) { return EINVAL; } else { indent(j); j->out(j->ctx, "<NULL>\n"); /* This is NOT valid JSON! */ return 0; } } type = heim_get_tid(obj); switch (type) { case HEIM_TID_ARRAY: indent(j); j->out(j->ctx, "[\n"); j->indent++; first = j->first; j->first = 1; heim_array_iterate_f(obj, j, array2json); j->indent--; if (!j->first) j->out(j->ctx, "\n"); indent(j); j->out(j->ctx, "]\n"); j->first = first; break; case HEIM_TID_DICT: indent(j); j->out(j->ctx, "{\n"); j->indent++; first = j->first; j->first = 1; heim_dict_iterate_f(obj, j, dict2json); j->indent--; if (!j->first) j->out(j->ctx, "\n"); indent(j); j->out(j->ctx, "}\n"); j->first = first; break; case HEIM_TID_STRING: indent(j); j->out(j->ctx, "\""); j->out(j->ctx, heim_string_get_utf8(obj)); j->out(j->ctx, "\""); break; case HEIM_TID_DATA: { heim_dict_t d; heim_string_t v; const heim_octet_string *data; char *b64 = NULL; int ret; if (j->flags & HEIM_JSON_F_NO_DATA) return EINVAL; /* JSON doesn't do binary */ data = heim_data_get_data(obj); ret = base64_encode(data->data, data->length, &b64); if (ret < 0 || b64 == NULL) return ENOMEM; if (j->flags & HEIM_JSON_F_NO_DATA_DICT) { indent(j); j->out(j->ctx, "\""); j->out(j->ctx, b64); /* base64-encode; hope there's no aliasing */ j->out(j->ctx, "\""); free(b64); } else { /* * JSON has no way to represent binary data, therefore the * following is a Heimdal-specific convention. * * We encode binary data as a dict with a single very magic * key with a base64-encoded value. The magic key includes * a uuid, so we're not likely to alias accidentally. */ d = heim_dict_create(2); if (d == NULL) { free(b64); return ENOMEM; } v = heim_string_ref_create(b64, free); if (v == NULL) { free(b64); heim_release(d); return ENOMEM; } ret = heim_dict_set_value(d, heim_tid_data_uuid_key, v); heim_release(v); if (ret) { heim_release(d); return ENOMEM; } ret = base2json(d, j); heim_release(d); if (ret) return ret; } break; } case HEIM_TID_NUMBER: { char num[32]; indent(j); snprintf(num, sizeof (num), "%d", heim_number_get_int(obj)); j->out(j->ctx, num); break; } case HEIM_TID_NULL: indent(j); j->out(j->ctx, "null"); break; case HEIM_TID_BOOL: indent(j); j->out(j->ctx, heim_bool_val(obj) ? "true" : "false"); break; default: return 1; } return 0; }