summaryrefslogtreecommitdiffstats
path: root/src/lib-storage/mailbox-attribute-lua.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/lib-storage/mailbox-attribute-lua.c163
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;
+}