diff options
Diffstat (limited to 'src/lib-storage/mailbox-attribute-lua.c')
-rw-r--r-- | src/lib-storage/mailbox-attribute-lua.c | 163 |
1 files changed, 163 insertions, 0 deletions
diff --git a/src/lib-storage/mailbox-attribute-lua.c b/src/lib-storage/mailbox-attribute-lua.c new file mode 100644 index 0000000..8d615a0 --- /dev/null +++ b/src/lib-storage/mailbox-attribute-lua.c @@ -0,0 +1,163 @@ +/* Copyright (c) 2018 Dovecot authors, see the included COPYING file */ + +#include "lib.h" +#include "str.h" +#include "istream.h" +#include "array.h" +#include "var-expand.h" +#include "dlua-script.h" +#include "dlua-script-private.h" +#include "mail-storage.h" +#include "mailbox-attribute.h" +#include "mail-storage-lua.h" +#include "mail-storage-lua-private.h" +#include "mail-user.h" + +/* lookup mailbox attribute */ +int lua_storage_mailbox_attribute_get(struct mailbox *box, const char *key, + const char **value_r, size_t *value_len_r, + const char **error_r) +{ + struct mail_attribute_value value; + enum mail_attribute_type attr_type; + int ret; + + if (str_begins(key, "/private/")) { + attr_type = MAIL_ATTRIBUTE_TYPE_PRIVATE; + key += 9; + } else if (str_begins(key, "/shared/")) { + attr_type = MAIL_ATTRIBUTE_TYPE_SHARED; + key += 8; + } else { + *error_r = "Invalid key prefix, must be /private/ or /shared/"; + return -1; + } + + /* get the attribute */ + if ((ret = mailbox_attribute_get_stream(box, attr_type, key, &value)) < 0) { + *error_r = mailbox_get_last_error(box, NULL); + return ret; + } else if (ret == 0) { + /* was not found */ + *value_r = NULL; + *value_len_r = 0; + return 0; + } + + if (value.value_stream != NULL) { + string_t *str = t_str_new(128); + const unsigned char *data; + size_t siz; + while((ret = i_stream_read_more(value.value_stream, &data, &siz))>0) { + str_append_data(str, data, siz); + i_stream_skip(value.value_stream, siz); + } + i_assert(ret != 0); + if (ret == -1 && !value.value_stream->eof) { + /* we could not read the stream */ + *error_r = i_stream_get_error(value.value_stream); + ret = -1; + } else { + *value_r = str->data; + *value_len_r = str->used; + ret = 1; + } + i_stream_unref(&value.value_stream); + return ret; + } + + *value_r = value.value; + if (value.value != NULL) + *value_len_r = strlen(value.value); + else + *value_len_r = 0; + return 1; +} + +int lua_storage_mailbox_attribute_set(struct mailbox *box, const char *key, + const char *value, size_t value_len, + const char **error_r) +{ + struct mail_attribute_value attr_value; + enum mail_attribute_type attr_type; + int ret; + + i_assert(value != NULL || value_len == 0); + + if (str_begins(key, "/private/")) { + attr_type = MAIL_ATTRIBUTE_TYPE_PRIVATE; + key += 9; + } else if (str_begins(key, "/shared/")) { + attr_type = MAIL_ATTRIBUTE_TYPE_SHARED; + key += 8; + } else { + *error_r = "Invalid key prefix, must be /private/ or /shared/"; + return -1; + } + + struct mailbox_transaction_context *t = + mailbox_transaction_begin(box, MAILBOX_TRANSACTION_FLAG_NO_NOTIFY, __func__); + i_zero(&attr_value); + + if (value != NULL) { + /* use stream API to allow NULs in data */ + attr_value.value_stream = i_stream_create_from_data(value, value_len); + } + + ret = mailbox_attribute_set(t, attr_type, key, &attr_value); + + if (ret < 0) { + *error_r = mailbox_get_last_error(box, NULL); + mailbox_transaction_rollback(&t); + } else if ((ret = mailbox_transaction_commit(&t)) < 0) { + *error_r = mailbox_get_last_error(box, NULL); + } + + if (attr_value.value_stream != NULL) + i_stream_unref(&attr_value.value_stream); + + return ret; +} + +int lua_storage_mailbox_attribute_list(struct mailbox *box, const char *prefix, + ARRAY_TYPE(lua_storage_keyvalue) *items_r, + const char **error_r) +{ + const char *key, *orig_prefix = prefix; + enum mail_attribute_type attr_type; + int ret; + + if (str_begins(prefix, "/private/")) { + attr_type = MAIL_ATTRIBUTE_TYPE_PRIVATE; + prefix += 9; + } else if (str_begins(prefix, "/shared/")) { + attr_type = MAIL_ATTRIBUTE_TYPE_SHARED; + prefix += 8; + } else { + *error_r = "Invalid key prefix, must be /private/ or /shared/"; + return -1; + } + + struct mailbox_attribute_iter *iter = + mailbox_attribute_iter_init(box, attr_type, prefix); + + ret = 0; + *error_r = NULL; + while((key = mailbox_attribute_iter_next(iter)) != NULL) { + struct lua_storage_keyvalue *item = array_append_space(items_r); + item->key = t_strdup_printf("%s%s", orig_prefix, key); + if (lua_storage_mailbox_attribute_get(box, item->key, &item->value, + &item->value_len, error_r) < 0) { + ret = -1; + break; + } + } + + if (mailbox_attribute_iter_deinit(&iter) < 0 || ret == -1) { + if (*error_r == NULL) + *error_r = mailbox_get_last_error(box, NULL); + return -1; + } + + return 0; +} |