Ejemplo n.º 1
0
Archivo: db.c Proyecto: InvLim/heimdal
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;
}
Ejemplo n.º 2
0
static heim_string_t
parse_string(struct parse_ctx *ctx)
{
    const uint8_t *start;
    int quote = 0;

    heim_assert(*ctx->p == '"', "string doesnt' start with \"");
    start = ++ctx->p;

    while (ctx->p < ctx->pend) {
	if (*ctx->p == '\n') {
	    ctx->lineno++;
	} else if (*ctx->p == '\\') {
	    if (ctx->p + 1 == ctx->pend)
		goto out;
	    ctx->p += 1;
	    quote = 1;
	} else if (*ctx->p == '"') {
	    heim_object_t o;

	    if (quote) {
		char *p0, *p;
		p = p0 = malloc(ctx->p - start);
		if (p == NULL)
		    goto out;
		while (start < ctx->p) {
		    if (*start == '\\') {
			start++;
			/* XXX validate qouted char */
		    }
		    *p++ = *start++;
		}
		o = heim_string_create_with_bytes(p0, p - p0);
		free(p0);
	    } else {
		o = heim_string_create_with_bytes(start, ctx->p - start);
	    }
	    ctx->p += 1;

	    return o;
	}    
	ctx->p += 1;
    }
    out:
    ctx->error = heim_error_create(EINVAL, "ran out of string");
    return NULL;
}
Ejemplo n.º 3
0
Archivo: db.c Proyecto: InvLim/heimdal
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;
}
Ejemplo n.º 4
0
Archivo: string.c Proyecto: lha/heimdal
heim_string_t
heim_string_create(const char *string)
{
    return heim_string_create_with_bytes(string, strlen(string));
}
Ejemplo n.º 5
0
Archivo: db.c Proyecto: InvLim/heimdal
/**
 * Open a database of the given dbtype.
 *
 * Database type names can be composed of one or more pseudo-DB types
 * and one concrete DB type joined with a '+' between each.  For
 * example: "transaction+bdb" might be a Berkeley DB with a layer above
 * that provides transactions.
 *
 * Options may be provided via a dict (an associative array).  Existing
 * options include:
 *
 *  - "create", with any value (create if DB doesn't exist)
 *  - "exclusive", with any value (exclusive create)
 *  - "truncate", with any value (truncate the DB)
 *  - "read-only", with any value (disallow writes)
 *  - "sync", with any value (make transactions durable)
 *  - "journal-name", with a string value naming a journal file name
 *
 * @param dbtype  Name of DB type
 * @param dbname  Name of DB (likely a file path)
 * @param options Options dict
 * @param db      Output open DB handle
 * @param error   Output error  object
 *
 * @return a DB handle
 *
 * @addtogroup heimbase
 */
heim_db_t
heim_db_create(const char *dbtype, const char *dbname,
	       heim_dict_t options, heim_error_t *error)
{
    heim_string_t s;
    char *p;
    db_plugin plug;
    heim_db_t db;
    int ret = 0;

    if (options == NULL) {
	options = heim_dict_create(11);
	if (options == NULL) {
	    if (error)
		*error = heim_error_create_enomem();
	    return NULL;
	}
    } else {
	(void) heim_retain(options);
    }

    if (db_plugins == NULL) {
	heim_release(options);
	return NULL;
    }

    if (dbtype == NULL || *dbtype == '\0') {
	struct dbtype_iter iter_ctx = { NULL, dbname, options, error};

	/* Try all dbtypes */
	heim_dict_iterate_f(db_plugins, &iter_ctx, dbtype_iter2create_f);
	heim_release(options);
	return iter_ctx.db;
    } else if (strstr(dbtype, "json")) {
	(void) heim_db_register(dbtype, NULL, &json_dbt);
    }

    /*
     * Allow for dbtypes that are composed from pseudo-dbtypes chained
     * to a real DB type with '+'.  For example a pseudo-dbtype might
     * add locking, transactions, transcoding of values, ...
     */
    p = strchr(dbtype, '+');
    if (p != NULL)
	s = heim_string_create_with_bytes(dbtype, p - dbtype);
    else
	s = heim_string_create(dbtype);
    if (s == NULL) {
	heim_release(options);
	return NULL;
    }

    HEIMDAL_MUTEX_lock(&db_type_mutex);
    plug = heim_dict_get_value(db_plugins, s);
    HEIMDAL_MUTEX_unlock(&db_type_mutex);
    heim_release(s);
    if (plug == NULL) {
	if (error)
	    *error = heim_error_create(ENOENT,
				       N_("Heimdal DB plugin not found: %s", ""),
				       dbtype);
	heim_release(options);
	return NULL;
    }

    db = _heim_alloc_object(&db_object, sizeof(*db));
    if (db == NULL) {
	heim_release(options);
	return NULL;
    }

    db->in_transaction = 0;
    db->ro_tx = 0;
    db->set_keys = NULL;
    db->del_keys = NULL;
    db->plug = plug;
    db->options = options;

    ret = plug->openf(plug->data, dbtype, dbname, options, &db->db_data, error);
    if (ret) {
	heim_release(db);
	if (error && *error == NULL)
	    *error = heim_error_create(ENOENT,
				       N_("Heimdal DB could not be opened: %s", ""),
				       dbname);
	return NULL;
    }

    ret = db_replay_log(db, error);
    if (ret) {
	heim_release(db);
	return NULL;
    }

    if (plug->clonef == NULL) {
	db->dbtype = heim_string_create(dbtype);
	db->dbname = heim_string_create(dbname);

	if (!db->dbtype || ! db->dbname) {
	    heim_release(db);
	    if (error)
		*error = heim_error_create_enomem();
	    return NULL;
	}
    }

    return db;
}
Ejemplo n.º 6
0
Archivo: json.c Proyecto: kaduk/heimdal
static heim_string_t
parse_string(struct parse_ctx *ctx)
{
    const uint8_t *start;
    int quote = 0;

    if (ctx->flags & HEIM_JSON_F_STRICT_STRINGS) {
	ctx->error = heim_error_create(EINVAL, "Strict JSON string encoding "
				       "not yet supported");
	return NULL;
    }

    if (*ctx->p != '"') {
	ctx->error = heim_error_create(EINVAL, "Expected a JSON string but "
				       "found something else at line %lu",
				       ctx->lineno);
	return NULL;
    }
    start = ++ctx->p;

    while (ctx->p < ctx->pend) {
	if (*ctx->p == '\n') {
	    ctx->lineno++;
	} else if (*ctx->p == '\\') {
	    if (ctx->p + 1 == ctx->pend)
		goto out;
	    ctx->p++;
	    quote = 1;
	} else if (*ctx->p == '"') {
	    heim_object_t o;

	    if (quote) {
		char *p0, *p;
		p = p0 = malloc(ctx->p - start);
		if (p == NULL)
		    goto out;
		while (start < ctx->p) {
		    if (*start == '\\') {
			start++;
			/* XXX validate quoted char */
		    }
		    *p++ = *start++;
		}
		o = heim_string_create_with_bytes(p0, p - p0);
		free(p0);
	    } else {
		o = heim_string_create_with_bytes(start, ctx->p - start);
		if (o == NULL) {
		    ctx->error = heim_error_create_enomem();
		    return NULL;
		}

		/* If we can decode as base64, then let's */
		if (ctx->flags & HEIM_JSON_F_TRY_DECODE_DATA) {
		    void *buf;
		    size_t len;
		    const char *s;

		    s = heim_string_get_utf8(o);
		    len = strlen(s);

		    if (len >= 4 && strspn(s, base64_chars) >= len - 2) {
			buf = malloc(len);
			if (buf == NULL) {
			    heim_release(o);
			    ctx->error = heim_error_create_enomem();
			    return NULL;
			}
			len = base64_decode(s, buf);
			if (len == -1) {
			    free(buf);
			    return o;
			}
			heim_release(o);
			o = heim_data_ref_create(buf, len, free);
		    }
		}
	    }
	    ctx->p += 1;

	    return o;
	}
	ctx->p += 1;
    }
    out:
    ctx->error = heim_error_create(EINVAL, "ran out of string");
    return NULL;
}