bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2013-2018 Dovecot authors, see the included COPYING file */
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch#include "lib.h"
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch#include "mail-storage.h"
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch#include "imap-metadata.h"
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Boschstruct imap_metadata_transaction {
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch struct mailbox *box;
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch struct mailbox_transaction_context *trans;
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch enum mail_error error;
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch char *error_string;
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen bool server:1;
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch};
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Boschbool imap_metadata_verify_entry_name(const char *name, const char **error_r)
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch{
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch unsigned int i;
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch bool ok;
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch if (name[0] != '/') {
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch *error_r = "Entry name must begin with '/'";
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch return FALSE;
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch }
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch for (i = 0; name[i] != '\0'; i++) {
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch switch (name[i]) {
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch case '/':
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch if (i > 0 && name[i-1] == '/') {
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch *error_r = "Entry name can't contain consecutive '/'";
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch return FALSE;
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch }
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch if (name[i+1] == '\0') {
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch *error_r = "Entry name can't end with '/'";
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch return FALSE;
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch }
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch break;
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch case '*':
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch *error_r = "Entry name can't contain '*'";
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch return FALSE;
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch case '%':
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch *error_r = "Entry name can't contain '%'";
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch return FALSE;
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch default:
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch if (name[i] <= 0x19) {
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch *error_r = "Entry name can't contain control chars";
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch return FALSE;
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch }
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch break;
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch }
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch }
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch T_BEGIN {
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch const char *prefix, *p = strchr(name+1, '/');
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch prefix = p == NULL ? name : t_strdup_until(name, p);
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch ok = strcasecmp(prefix, IMAP_METADATA_PRIVATE_PREFIX) == 0 ||
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch strcasecmp(prefix, IMAP_METADATA_SHARED_PREFIX) == 0;
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch } T_END;
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch if (!ok) {
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch *error_r = "Entry name must begin with /private or /shared";
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch return FALSE;
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch }
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch return TRUE;
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch}
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Boschstatic void
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Boschimap_metadata_transaction_set_error(struct imap_metadata_transaction *imtrans,
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch enum mail_error error, const char *string)
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch{
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch i_free(imtrans->error_string);
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch imtrans->error_string = i_strdup(string);
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch imtrans->error = error;
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch}
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Boschstatic bool
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Boschimap_metadata_entry2key(struct imap_metadata_transaction *imtrans,
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch const char *entry, enum mail_attribute_type *type_r,
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch const char **key_r)
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch{
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch const char *key_prefix = (imtrans->server ?
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch MAILBOX_ATTRIBUTE_PREFIX_DOVECOT_PVT_SERVER : NULL);
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch /* names are case-insensitive so we'll always lowercase them */
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch entry = t_str_lcase(entry);
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch if (strncmp(entry, IMAP_METADATA_PRIVATE_PREFIX,
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch strlen(IMAP_METADATA_PRIVATE_PREFIX)) == 0) {
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch *key_r = entry + strlen(IMAP_METADATA_PRIVATE_PREFIX);
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch *type_r = MAIL_ATTRIBUTE_TYPE_PRIVATE;
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch } else {
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch i_assert(strncmp(entry, IMAP_METADATA_SHARED_PREFIX,
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch strlen(IMAP_METADATA_SHARED_PREFIX)) == 0);
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch *key_r = entry + strlen(IMAP_METADATA_SHARED_PREFIX);
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch *type_r = MAIL_ATTRIBUTE_TYPE_SHARED;
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch }
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch if ((*key_r)[0] == '\0') {
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch /* /private or /shared prefix has no value itself */
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch } else {
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch i_assert((*key_r)[0] == '/');
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch *key_r += 1;
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch }
c07fb2247951f6bc9421d816bb7599efcd84da2eTimo Sirainen if (strncmp(*key_r, MAILBOX_ATTRIBUTE_PREFIX_DOVECOT_PVT,
c07fb2247951f6bc9421d816bb7599efcd84da2eTimo Sirainen strlen(MAILBOX_ATTRIBUTE_PREFIX_DOVECOT_PVT)) == 0) {
c07fb2247951f6bc9421d816bb7599efcd84da2eTimo Sirainen /* Dovecot's internal attribute (mailbox or server).
c07fb2247951f6bc9421d816bb7599efcd84da2eTimo Sirainen don't allow accessing this. */
c07fb2247951f6bc9421d816bb7599efcd84da2eTimo Sirainen return FALSE;
c07fb2247951f6bc9421d816bb7599efcd84da2eTimo Sirainen }
c07fb2247951f6bc9421d816bb7599efcd84da2eTimo Sirainen /* Add the server-prefix (after checking for the above internal
c07fb2247951f6bc9421d816bb7599efcd84da2eTimo Sirainen attribute). */
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch if (key_prefix != NULL)
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch *key_r = t_strconcat(key_prefix, *key_r, NULL);
c07fb2247951f6bc9421d816bb7599efcd84da2eTimo Sirainen return TRUE;
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch}
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Boschstatic int
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Boschimap_metadata_get_mailbox_transaction(struct imap_metadata_transaction *imtrans)
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch{
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch if (imtrans->trans != NULL)
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch return 0;
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch if (imtrans->box == NULL || mailbox_open(imtrans->box) < 0)
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch return -1;
0dab9cb35a976c49b28a11e28d5570f5191f1a7aMartti Rannanjärvi imtrans->trans = mailbox_transaction_begin(imtrans->box,
0dab9cb35a976c49b28a11e28d5570f5191f1a7aMartti Rannanjärvi MAILBOX_TRANSACTION_FLAG_EXTERNAL, __func__);
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch return 0;
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch}
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Boschint imap_metadata_set(struct imap_metadata_transaction *imtrans,
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch const char *entry, const struct mail_attribute_value *value)
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch{
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch enum mail_attribute_type type;
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch const char *key;
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch if (!imap_metadata_entry2key(imtrans, entry, &type, &key)) {
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch imap_metadata_transaction_set_error(imtrans, MAIL_ERROR_PARAMS,
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch "Internal mailbox attributes cannot be accessed");
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch return -1;
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch }
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch if (imap_metadata_get_mailbox_transaction(imtrans) < 0)
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch return -1;
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch return (value->value == NULL ?
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch mailbox_attribute_unset(imtrans->trans, type, key) :
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch mailbox_attribute_set(imtrans->trans, type, key, value));
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch}
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Boschint imap_metadata_unset(struct imap_metadata_transaction *imtrans,
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch const char *entry)
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch{
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch struct mail_attribute_value value;
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch
efe78d3ba24fc866af1c79b9223dc0809ba26cadStephan Bosch i_zero(&value);
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch return imap_metadata_set(imtrans, entry, &value);
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch}
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Boschint imap_metadata_get(struct imap_metadata_transaction *imtrans,
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch const char *entry, struct mail_attribute_value *value_r)
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch{
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch enum mail_attribute_type type;
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch const char *key;
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch
efe78d3ba24fc866af1c79b9223dc0809ba26cadStephan Bosch i_zero(value_r);
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch if (!imap_metadata_entry2key(imtrans, entry, &type, &key))
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch return 0;
66c87722e0fd2a85cd59797326bad3d1c409dc3aAki Tuomi return mailbox_attribute_get(imtrans->box, type, key, value_r);
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch}
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Boschint imap_metadata_get_stream(struct imap_metadata_transaction *imtrans,
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch const char *entry, struct mail_attribute_value *value_r)
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch{
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch enum mail_attribute_type type;
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch const char *key;
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch
efe78d3ba24fc866af1c79b9223dc0809ba26cadStephan Bosch i_zero(value_r);
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch if (!imap_metadata_entry2key(imtrans, entry, &type, &key))
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch return 0;
66c87722e0fd2a85cd59797326bad3d1c409dc3aAki Tuomi return mailbox_attribute_get_stream(imtrans->box, type, key, value_r);
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch}
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Boschstruct imap_metadata_iter {
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch struct mailbox_attribute_iter *iter;
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch};
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Boschstruct imap_metadata_iter *
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Boschimap_metadata_iter_init(struct imap_metadata_transaction *imtrans,
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch const char *entry)
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch{
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch struct imap_metadata_iter *iter;
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch enum mail_attribute_type type;
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch const char *key;
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch iter = i_new(struct imap_metadata_iter, 1);
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch if (imap_metadata_entry2key(imtrans, entry, &type, &key)) {
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch const char *prefix =
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch key[0] == '\0' ? "" : t_strconcat(key, "/", NULL);
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch iter->iter = mailbox_attribute_iter_init(imtrans->box, type,
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch prefix);
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch }
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch return iter;
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch}
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Boschconst char *imap_metadata_iter_next(struct imap_metadata_iter *iter)
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch{
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch if (iter->iter == NULL)
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch return NULL;
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch return mailbox_attribute_iter_next(iter->iter);
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch}
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Boschint imap_metadata_iter_deinit(struct imap_metadata_iter **_iter)
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch{
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch struct imap_metadata_iter *iter = *_iter;
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch int ret;
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch *_iter = NULL;
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch if (iter->iter == NULL)
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch ret = 0;
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch else
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch ret = mailbox_attribute_iter_deinit(&iter->iter);
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch i_free(iter);
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch return ret;
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch}
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Boschstruct imap_metadata_transaction *
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Boschimap_metadata_transaction_begin(struct mailbox *box)
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch{
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch struct imap_metadata_transaction *imtrans;
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch imtrans = i_new(struct imap_metadata_transaction, 1);
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch imtrans->box = box;
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch return imtrans;
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch}
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Boschstruct imap_metadata_transaction *
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Boschimap_metadata_transaction_begin_server(struct mail_user *user)
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch{
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch struct mail_namespace *ns;
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch struct mailbox *box;
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch struct imap_metadata_transaction *imtrans;
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch ns = mail_namespace_find_inbox(user->namespaces);
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch box = mailbox_alloc(ns->list, "INBOX", 0);
61cf001f1944d92eb25f113ba4c08985d6e30d53Timo Sirainen mailbox_set_reason(box, "Server METADATA");
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch imtrans = imap_metadata_transaction_begin(box);
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch imtrans->server = TRUE;
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch return imtrans;
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch}
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Boschstatic void
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Boschimap_metadata_transaction_finish(struct imap_metadata_transaction **_imtrans)
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch{
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch struct imap_metadata_transaction *imtrans = *_imtrans;
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch if (imtrans->server)
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch mailbox_free(&imtrans->box);
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch i_free(imtrans->error_string);
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch i_free(imtrans);
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch *_imtrans = NULL;
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch}
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Boschint imap_metadata_transaction_commit(
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch struct imap_metadata_transaction **_imtrans,
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch enum mail_error *error_code_r, const char **error_r)
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch{
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch struct imap_metadata_transaction *imtrans = *_imtrans;
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch int ret = 0;
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch if (imtrans->trans != NULL) {
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch const char *error = NULL;
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch ret = mailbox_transaction_commit(&imtrans->trans);
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch if (ret < 0)
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch error = mailbox_get_last_error(imtrans->box, error_code_r);
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch if (error_r != NULL)
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch *error_r = error;
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch }
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch imap_metadata_transaction_finish(_imtrans);
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch return ret;
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch}
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Boschvoid imap_metadata_transaction_rollback(
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch struct imap_metadata_transaction **_imtrans)
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch{
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch struct imap_metadata_transaction *imtrans = *_imtrans;
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch if (imtrans->trans != NULL)
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch mailbox_transaction_rollback(&imtrans->trans);
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch imap_metadata_transaction_finish(_imtrans);
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch}
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Boschconst char *
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Boschimap_metadata_transaction_get_last_error(
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch struct imap_metadata_transaction *imtrans,
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch enum mail_error *error_code_r)
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch{
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch if (imtrans->error != MAIL_ERROR_NONE) {
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch if (error_code_r != NULL)
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch *error_code_r = imtrans->error;
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch return imtrans->error_string;
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch }
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch i_assert(imtrans->box != NULL);
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch return mailbox_get_last_error(imtrans->box, error_code_r);
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch}