Mercurial > dovecot > original-hg > dovecot-1.2
changeset 3967:6fabe878c46d HEAD
Dictionary takes now a username parameter, which is used for private
queries. Made dict-sql use "insert .. on duplicate key update" syntax, which
unfortunately doesn't work with PostgreSQL yet.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Tue, 31 Jan 2006 08:05:21 +0200 |
parents | 19dcfd289610 |
children | 93449dc37434 |
files | src/dict/Makefile.am src/dict/dict-cache.c src/dict/dict-cache.h src/dict/dict-server.c src/dict/main.c src/lib-dict/dict-client.c src/lib-dict/dict-private.h src/lib-dict/dict-sql.c src/lib-dict/dict.c src/lib-dict/dict.h src/plugins/quota/quota-dict.c src/plugins/quota/quota.c |
diffstat | 12 files changed, 155 insertions(+), 51 deletions(-) [+] |
line wrap: on
line diff
--- a/src/dict/Makefile.am Tue Jan 31 08:02:35 2006 +0200 +++ b/src/dict/Makefile.am Tue Jan 31 08:05:21 2006 +0200 @@ -5,6 +5,7 @@ AM_CPPFLAGS = \ -I$(top_srcdir)/src/lib \ -I$(top_srcdir)/src/lib-dict \ + -I$(top_srcdir)/src/lib-sql \ -DPKG_RUNDIR=\""$(rundir)"\" libs = \
--- a/src/dict/dict-cache.c Tue Jan 31 08:02:35 2006 +0200 +++ b/src/dict/dict-cache.c Tue Jan 31 08:05:21 2006 +0200 @@ -31,14 +31,15 @@ i_free(cache); } -struct dict *dict_cache_get(struct dict_cache *cache, const char *uri) +struct dict *dict_cache_get(struct dict_cache *cache, const char *uri, + const char *username) { struct dict_entry *entry; entry = hash_lookup(cache->dicts, uri); if (entry == NULL) { entry = i_new(struct dict_entry, 1); - entry->dict = dict_init(uri); + entry->dict = dict_init(uri, username); entry->uri = i_strdup(uri); hash_insert(cache->dicts, entry->uri, entry); }
--- a/src/dict/dict-cache.h Tue Jan 31 08:02:35 2006 +0200 +++ b/src/dict/dict-cache.h Tue Jan 31 08:05:21 2006 +0200 @@ -4,7 +4,8 @@ struct dict_cache *dict_cache_init(void); void dict_cache_deinit(struct dict_cache *cache); -struct dict *dict_cache_get(struct dict_cache *cache, const char *uri); +struct dict *dict_cache_get(struct dict_cache *cache, const char *uri, + const char *username); void dict_cache_unref(struct dict_cache *cache, const char *uri); #endif
--- a/src/dict/dict-server.c Tue Jan 31 08:02:35 2006 +0200 +++ b/src/dict/dict-server.c Tue Jan 31 08:05:21 2006 +0200 @@ -294,11 +294,12 @@ if (*line++ != '\t') return -1; - conn->username = i_strdup(username); + conn->username = i_strdup_until(username, line - 1); /* the rest is dict URI */ conn->uri = i_strdup(line); - conn->dict = dict_cache_get(conn->server->cache, conn->uri); + conn->dict = dict_cache_get(conn->server->cache, conn->uri, + conn->username); if (conn->dict == NULL) return -1;
--- a/src/dict/main.c Tue Jan 31 08:02:35 2006 +0200 +++ b/src/dict/main.c Tue Jan 31 08:05:21 2006 +0200 @@ -6,6 +6,7 @@ #include "fd-close-on-exec.h" #include "restrict-access.h" #include "randgen.h" +#include "sql-api.h" #include "dict-sql.h" #include "dict-client.h" #include "dict-server.h" @@ -39,6 +40,10 @@ chrooting. */ random_init(); + /* Load built-in SQL drivers (if any) */ + sql_drivers_init(); + sql_drivers_register_all(); + restrict_access_by_env(FALSE); } @@ -76,6 +81,7 @@ dict_sql_unregister(); dict_client_unregister(); + sql_drivers_deinit(); random_deinit(); lib_signals_deinit(); closelog();
--- a/src/lib-dict/dict-client.c Tue Jan 31 08:02:35 2006 +0200 +++ b/src/lib-dict/dict-client.c Tue Jan 31 08:05:21 2006 +0200 @@ -220,13 +220,14 @@ } } -static struct dict *client_dict_init(struct dict *dict_class, const char *uri) +static struct dict *client_dict_init(struct dict *dict_class, const char *uri, + const char *username) { struct client_dict *dict; - const char *path, *dest_uri; + const char *dest_uri; pool_t pool; - /* uri = <username> [" " <path>] ":" <uri> */ + /* uri = [<path>] ":" <uri> */ dest_uri = strchr(uri, ':'); if (dest_uri == NULL) { i_error("dict-client: Invalid URI: %s", uri); @@ -237,17 +238,15 @@ dict = p_new(pool, struct client_dict, 1); dict->pool = pool; dict->dict = *dict_class; + dict->username = p_strdup(pool, username); dict->fd = -1; - path = strchr(uri, ' '); - if (path != NULL && path < dest_uri) { + if (*uri != ':') { /* path given */ - dict->path = p_strdup_until(pool, path + 1, dest_uri); - dict->username = p_strdup_until(pool, uri, path); + dict->path = p_strdup_until(pool, uri, dest_uri); } else { dict->path = DEFAULT_DICT_SERVER_SOCKET_PATH; - dict->username = p_strdup_until(pool, uri, dest_uri); } dict->uri = p_strdup(pool, dest_uri + 1);
--- a/src/lib-dict/dict-private.h Tue Jan 31 08:02:35 2006 +0200 +++ b/src/lib-dict/dict-private.h Tue Jan 31 08:05:21 2006 +0200 @@ -4,7 +4,8 @@ #include "dict.h" struct dict_vfuncs { - struct dict *(*init)(struct dict *dict_class, const char *uri); + struct dict *(*init)(struct dict *dict_class, const char *uri, + const char *username); void (*deinit)(struct dict *dict); int (*lookup)(struct dict *dict, pool_t pool,
--- a/src/lib-dict/dict-sql.c Tue Jan 31 08:02:35 2006 +0200 +++ b/src/lib-dict/dict-sql.c Tue Jan 31 08:05:21 2006 +0200 @@ -18,8 +18,8 @@ pool_t pool; struct sql_db *db; - const char *connect_string; - const char *table, *select_field, *where_field; + const char *connect_string, *username; + const char *table, *select_field, *where_field, *username_field; }; struct sql_dict_iterate_context { @@ -67,6 +67,8 @@ dict->select_field = p_strdup(dict->pool, value); else if (strcmp(line, "where_field") == 0) dict->where_field = p_strdup(dict->pool, value); + else if (strcmp(line, "username_field") == 0) + dict->username_field = p_strdup(dict->pool, value); t_pop(); } @@ -89,11 +91,16 @@ i_error("%s: 'where_field' missing", path); return -1; } + if (dict->username_field == NULL) { + i_error("%s: 'username_field' missing", path); + return -1; + } return 0; } -static struct dict *sql_dict_init(struct dict *dict_class, const char *uri) +static struct dict *sql_dict_init(struct dict *dict_class, const char *uri, + const char *username) { struct sql_dict *dict; pool_t pool; @@ -102,6 +109,7 @@ dict = p_new(pool, struct sql_dict, 1); dict->pool = pool; dict->dict = *dict_class; + dict->username = p_strdup(pool, username); if (sql_dict_read_config(dict, uri) < 0) { pool_unref(pool); @@ -122,19 +130,51 @@ pool_unref(dict->pool); } +static int sql_path_fix(const char **path, bool *private_r) +{ + const char *p; + size_t len; + + p = strchr(*path, '/'); + if (p == NULL) + return -1; + len = p - *path; + + if (strncmp(*path, DICT_PATH_PRIVATE, len) == 0) + *private_r = TRUE; + else if (strncmp(*path, DICT_PATH_SHARED, len) == 0) + *private_r = FALSE; + else + return -1; + + *path += len + 1; + return 0; +} + static int sql_dict_lookup(struct dict *_dict, pool_t pool, const char *key, const char **value_r) { struct sql_dict *dict = (struct sql_dict *)_dict; struct sql_result *result; - const char *query; + string_t *query; int ret; + bool priv; + + if (sql_path_fix(&key, &priv) < 0) { + *value_r = NULL; + return -1; + } t_push(); - query = t_strdup_printf("SELECT %s FROM %s WHERE %s = '%s'", - dict->select_field, dict->table, - dict->where_field, str_escape(key)); - result = sql_query_s(dict->db, query); + query = t_str_new(256); + str_printfa(query, "SELECT %s FROM %s WHERE %s = '%s'", + dict->select_field, dict->table, + dict->where_field, str_escape(key)); + if (priv) { + str_printfa(query, " AND %s = '%s'", + dict->username_field, str_escape(dict->username)); + } + result = sql_query_s(dict->db, str_c(query)); t_pop(); ret = sql_result_next_row(result); @@ -155,21 +195,32 @@ struct sql_dict *dict = (struct sql_dict *)_dict; struct sql_dict_iterate_context *ctx; string_t *query; + bool priv; ctx = i_new(struct sql_dict_iterate_context, 1); ctx->ctx.dict = _dict; - t_push(); - query = t_str_new(256); - str_printfa(query, "SELECT %s, %s FROM %s WHERE %s LIKE '%s/%%'", - dict->where_field, dict->select_field, - dict->table, dict->where_field, str_escape(path)); - if (!recurse) { - str_printfa(query, " AND %s NOT LIKE '%s/%%/%%'", - dict->where_field, str_escape(path)); + if (sql_path_fix(&path, &priv) < 0) + ctx->result = NULL; + else { + t_push(); + query = t_str_new(256); + str_printfa(query, "SELECT %s, %s FROM %s " + "WHERE %s LIKE '%s/%%'", + dict->where_field, dict->select_field, + dict->table, dict->where_field, str_escape(path)); + if (priv) { + str_printfa(query, " AND %s = '%s'", + dict->username_field, + str_escape(dict->username)); + } + if (!recurse) { + str_printfa(query, " AND %s NOT LIKE '%s/%%/%%'", + dict->where_field, str_escape(path)); + } + ctx->result = sql_query_s(dict->db, str_c(query)); + t_pop(); } - ctx->result = sql_query_s(dict->db, str_c(query)); - t_pop(); return &ctx->ctx; } @@ -181,6 +232,9 @@ (struct sql_dict_iterate_context *)_ctx; int ret; + if (ctx->result == NULL) + return -1; + if ((ret = sql_result_next_row(ctx->result)) <= 0) return ret; @@ -241,11 +295,29 @@ (struct sql_dict_transaction_context *)_ctx; struct sql_dict *dict = (struct sql_dict *)_ctx->dict; const char *query; + bool priv; + + if (sql_path_fix(&key, &priv) < 0) + return; t_push(); - query = t_strdup_printf("UPDATE %s SET %s = '%s' WHERE %s = '%s'", - dict->table, dict->select_field, str_escape(value), - dict->where_field, str_escape(key)); + if (priv) { + query = t_strdup_printf( + "INSERT INTO %s (%s, %s, %s) VALUES (%s, %s, %s) " + "ON DUPLICATE KEY UPDATE %s = '%s'", + dict->table, dict->select_field, dict->where_field, + dict->username_field, + str_escape(key), str_escape(value), + str_escape(dict->username), + str_escape(key), str_escape(value)); + } else { + query = t_strdup_printf( + "INSERT INTO %s (%s, %s) VALUES (%s, %s) " + "ON DUPLICATE KEY UPDATE %s = '%s'", + dict->table, dict->select_field, dict->where_field, + str_escape(key), str_escape(value), + str_escape(key), str_escape(value)); + } sql_update(ctx->sql_ctx, query); t_pop(); } @@ -257,12 +329,28 @@ (struct sql_dict_transaction_context *)_ctx; struct sql_dict *dict = (struct sql_dict *)_ctx->dict; const char *query; + bool priv; + + if (sql_path_fix(&key, &priv) < 0) + return; t_push(); - query = t_strdup_printf("UPDATE %s SET %s = %s + %lld WHERE %s = '%s'", - dict->table, dict->select_field, - dict->select_field, diff, - dict->where_field, str_escape(key)); + if (priv) { + query = t_strdup_printf( + "INSERT INTO %s (%s, %s, %s) VALUES (%s, %lld, %s) " + "ON DUPLICATE KEY UPDATE %s = %s + %lld", + dict->table, dict->select_field, dict->where_field, + dict->username_field, + str_escape(key), diff, str_escape(dict->username), + str_escape(key), str_escape(key), diff); + } else { + query = t_strdup_printf( + "INSERT INTO %s (%s, %s) VALUES (%s, %lld) " + "ON DUPLICATE KEY UPDATE %s = %s + %lld", + dict->table, dict->select_field, dict->where_field, + str_escape(key), diff, + str_escape(key), str_escape(key), diff); + } sql_update(ctx->sql_ctx, query); t_pop(); }
--- a/src/lib-dict/dict.c Tue Jan 31 08:02:35 2006 +0200 +++ b/src/lib-dict/dict.c Tue Jan 31 08:05:21 2006 +0200 @@ -51,10 +51,10 @@ array_free(&dict_classes); } -struct dict *dict_init(const char *uri) +struct dict *dict_init(const char *uri, const char *username) { struct dict *dict; - const char *p; + const char *p, *name; p = strchr(uri, ':'); if (p == NULL) { @@ -63,12 +63,16 @@ } t_push(); - dict = dict_class_lookup(t_strdup_until(uri, p)); + name = t_strdup_until(uri, p); + dict = dict_class_lookup(name); + if (dict == NULL) { + i_error("Unknown dict module: %s", name); + t_pop(); + return NULL; + } t_pop(); - if (dict == NULL) - return NULL; - return dict->v.init(dict, p+1); + return dict->v.init(dict, p+1, username); } void dict_deinit(struct dict **_dict)
--- a/src/lib-dict/dict.h Tue Jan 31 08:02:35 2006 +0200 +++ b/src/lib-dict/dict.h Tue Jan 31 08:05:21 2006 +0200 @@ -11,7 +11,7 @@ /* Open dictionary with given URI (type:data). If URI is invalid, returns NULL. */ -struct dict *dict_init(const char *uri); +struct dict *dict_init(const char *uri, const char *username); /* Close dictionary. */ void dict_deinit(struct dict **dict);
--- a/src/plugins/quota/quota-dict.c Tue Jan 31 08:02:35 2006 +0200 +++ b/src/plugins/quota/quota-dict.c Tue Jan 31 08:05:21 2006 +0200 @@ -37,7 +37,7 @@ if (getenv("DEBUG") != NULL) i_info("dict quota uri = %s", data); - dict = dict_init(data); + dict = dict_init(data, getenv("USER")); if (dict == NULL) return NULL;
--- a/src/plugins/quota/quota.c Tue Jan 31 08:02:35 2006 +0200 +++ b/src/plugins/quota/quota.c Tue Jan 31 08:05:21 2006 +0200 @@ -39,14 +39,16 @@ if (strcmp(quota_classes[i]->name, name) == 0) break; } - t_pop(); - quota = i == QUOTA_CLASS_COUNT ? NULL : - quota_classes[i]->init(data); - if (quota != NULL) { + if (i == QUOTA_CLASS_COUNT) { + i_error("Unknown quota module: %s", name); + quota = NULL; + } else { + quota = quota_classes[i]->init(data); array_create("a->quota_module_contexts, default_pool, sizeof(void *), 5); } + t_pop(); return quota; }