Coverage Report

Created: 2026-10-17 06:32

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/pigeonhole/src/lib-sieve/sieve-storage-sync.c
Line
Count
Source
1
/* Copyright (c) Pigeonhole authors, see top-level COPYING file */
2
3
#include "lib.h"
4
#include "array.h"
5
#include "str-sanitize.h"
6
#include "home-expand.h"
7
#include "eacces-error.h"
8
#include "mkdir-parents.h"
9
#include "ioloop.h"
10
#include "mail-storage-private.h"
11
12
#include "sieve-common.h"
13
#include "sieve-error-private.h"
14
15
#include "sieve-script-private.h"
16
#include "sieve-storage-private.h"
17
18
/*
19
 * Synchronization
20
 */
21
22
int sieve_storage_sync_init(struct sieve_storage *storage,
23
          struct mail_user *user)
24
0
{
25
0
  enum sieve_storage_flags sflags = storage->flags;
26
27
0
  if ((sflags & SIEVE_STORAGE_FLAG_SYNCHRONIZING) == 0 &&
28
0
      (sflags & SIEVE_STORAGE_FLAG_READWRITE) == 0)
29
0
    return 0;
30
31
0
  if (!storage->allows_synchronization) {
32
0
    if ((sflags & SIEVE_STORAGE_FLAG_SYNCHRONIZING) != 0)
33
0
      return -1;
34
0
    return 0;
35
0
  }
36
37
0
  e_debug(storage->event, "sync: Synchronization active");
38
39
0
  storage->sync_inbox_ns = mail_namespace_find_inbox(user->namespaces);
40
0
  return 0;
41
0
}
42
43
void sieve_storage_sync_deinit(struct sieve_storage *storage ATTR_UNUSED)
44
0
{
45
  /* nothing */
46
0
}
47
48
/*
49
 * Sync attributes
50
 */
51
52
static int
53
sieve_storage_sync_transaction_begin(
54
  struct sieve_storage *storage,
55
  struct mailbox_transaction_context **trans_r)
56
0
{
57
0
  enum mailbox_flags mflags = MAILBOX_FLAG_IGNORE_ACLS;
58
0
  struct mail_namespace *ns = storage->sync_inbox_ns;
59
0
  struct mailbox *inbox;
60
0
  enum mail_error error;
61
62
0
  if (ns == NULL)
63
0
    return 0;
64
65
0
  inbox = mailbox_alloc(ns->list, "INBOX", mflags);
66
0
  if (mailbox_open(inbox) < 0) {
67
0
    e_warning(storage->event, "sync: "
68
0
        "Failed to open user INBOX for attribute modifications: %s",
69
0
        mailbox_get_last_internal_error(inbox, &error));
70
0
    mailbox_free(&inbox);
71
0
    return -1;
72
0
  }
73
74
0
  *trans_r = mailbox_transaction_begin(inbox,
75
0
               MAILBOX_TRANSACTION_FLAG_EXTERNAL,
76
0
               __func__);
77
0
  return 1;
78
0
}
79
80
static int
81
sieve_storage_sync_transaction_finish(
82
  struct sieve_storage *storage,
83
  struct mailbox_transaction_context **trans)
84
0
{
85
0
  struct mailbox *inbox;
86
0
  int ret;
87
88
0
  inbox = mailbox_transaction_get_mailbox(*trans);
89
90
0
  if ((ret = mailbox_transaction_commit(trans)) < 0) {
91
0
    enum mail_error error;
92
93
0
    e_warning(storage->event, "sync: "
94
0
        "Failed to update INBOX attributes: %s",
95
0
         mail_storage_get_last_error(
96
0
        mailbox_get_storage(inbox), &error));
97
0
  }
98
99
0
  mailbox_free(&inbox);
100
0
  return ret;
101
0
}
102
103
int sieve_storage_sync_script_save(struct sieve_storage *storage,
104
           const char *name)
105
0
{
106
0
  struct mailbox_transaction_context *trans;
107
0
  const char *key;
108
0
  int ret;
109
110
0
  if ((ret = sieve_storage_sync_transaction_begin(storage, &trans)) <= 0)
111
0
    return ret;
112
113
0
  key = t_strconcat(MAILBOX_ATTRIBUTE_PREFIX_SIEVE_FILES, name, NULL);
114
115
0
  mail_index_attribute_set(trans->itrans, TRUE, key, ioloop_time, 0);
116
117
0
  return sieve_storage_sync_transaction_finish(storage, &trans);
118
0
}
119
120
int sieve_storage_sync_script_rename(struct sieve_storage *storage,
121
             const char *oldname, const char *newname)
122
0
{
123
0
  struct mailbox_transaction_context *trans;
124
0
  const char *oldkey, *newkey;
125
0
  int ret;
126
127
0
  if ((ret = sieve_storage_sync_transaction_begin(storage, &trans)) <= 0)
128
0
    return ret;
129
130
0
  oldkey = t_strconcat(MAILBOX_ATTRIBUTE_PREFIX_SIEVE_FILES,
131
0
           oldname, NULL);
132
0
  newkey = t_strconcat(MAILBOX_ATTRIBUTE_PREFIX_SIEVE_FILES,
133
0
           newname, NULL);
134
135
0
  mail_index_attribute_unset(trans->itrans, TRUE, oldkey, ioloop_time);
136
0
  mail_index_attribute_set(trans->itrans, TRUE, newkey, ioloop_time, 0);
137
138
0
  return sieve_storage_sync_transaction_finish(storage, &trans);
139
0
}
140
141
int sieve_storage_sync_script_delete(struct sieve_storage *storage,
142
             const char *name)
143
0
{
144
0
  struct mailbox_transaction_context *trans;
145
0
  const char *key;
146
0
  int ret;
147
148
0
  if ((ret = sieve_storage_sync_transaction_begin(storage, &trans)) <= 0)
149
0
    return ret;
150
151
0
  key = t_strconcat(MAILBOX_ATTRIBUTE_PREFIX_SIEVE_FILES, name, NULL);
152
153
0
  mail_index_attribute_unset(trans->itrans, TRUE, key, ioloop_time);
154
155
0
  return sieve_storage_sync_transaction_finish(storage, &trans);
156
0
}
157
158
int sieve_storage_sync_script_activate(struct sieve_storage *storage)
159
0
{
160
0
  struct mailbox_transaction_context *trans;
161
0
  int ret;
162
163
0
  if ((ret = sieve_storage_sync_transaction_begin(storage, &trans)) <= 0)
164
0
    return ret;
165
166
0
  mail_index_attribute_set(trans->itrans, TRUE,
167
0
         MAILBOX_ATTRIBUTE_SIEVE_DEFAULT,
168
0
         ioloop_time, 0);
169
170
0
  return sieve_storage_sync_transaction_finish(storage, &trans);
171
0
}
172
173
int sieve_storage_sync_deactivate(struct sieve_storage *storage)
174
0
{
175
0
  struct mailbox_transaction_context *trans;
176
0
  int ret;
177
178
0
  if ((ret = sieve_storage_sync_transaction_begin(storage, &trans)) <= 0)
179
0
    return ret;
180
181
0
  mail_index_attribute_unset(trans->itrans, TRUE,
182
0
           MAILBOX_ATTRIBUTE_SIEVE_DEFAULT,
183
0
           ioloop_time);
184
185
0
  return sieve_storage_sync_transaction_finish(storage, &trans);
186
0
}