~ubuntu-branches/debian/sid/openchange/sid

« back to all changes in this revision

Viewing changes to mapiproxy/services/plugins/dovecot/ocsmanager-plugin.c

  • Committer: Package Import Robot
  • Author(s): Jelmer Vernooij
  • Date: 2012-04-12 20:07:57 UTC
  • mfrom: (11 sid)
  • mto: This revision was merged to the branch mainline in revision 12.
  • Revision ID: package-import@ubuntu.com-20120412200757-k933d9trljmxj1l4
Tags: 1:1.0-4
* openchangeserver: Add dependency on openchangeproxy.
* Rebuild against newer version of Samba 4.
* Use dpkg-buildflags.
* Migrate to Git, update Vcs-Git header.
* Switch to debhelper 9.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
   OpenChange Service Manager Plugin for Dovecot
 
3
 
 
4
   OpenChange Project
 
5
 
 
6
   Copyright (C) Julien Kerihuel 2011.
 
7
 
 
8
   This program is free software; you can redistribute it and/or modify
 
9
   it under the terms of the GNU General Public License as published by
 
10
   the Free Software Foundation; either version 3 of the License, or
 
11
   (at your option) any later version.
 
12
   
 
13
   This program is distributed in the hope that it will be useful,
 
14
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
15
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
16
   GNU General Public License for more details.
 
17
   
 
18
   You should have received a copy of the GNU General Public License
 
19
   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
20
 */
 
21
 
 
22
/*
 
23
  Step 1. Compile the plugin
 
24
  gcc  -fPIC -shared -DHAVE_CONFIG_H `echo $DOVECOT_CFLAGS $LIBDOVECOT_INCLUDE $LIBDOVECOT_STORAGE_INCLUDE` ocsmanager-plugin.c -L/usr/lib/dovecot/modules/ -l15_notify_plugin -o ocsmanager_plugin.so
 
25
 
 
26
  Step 2: Install the plugin
 
27
  sudo cp ocsmanager_plugin.so /usr/lib/dovecot/modules/ocsmanager_plugin.so
 
28
 
 
29
  Step 3: Configure ocsmanager plugin options in dovecot.conf
 
30
  plugin {
 
31
  ocsmanager_backend = SOGo
 
32
  ocsmanager_newmail = /home/openchange/openchange/sogo-good/mapiproxy/services/client/newmail.py
 
33
  ocsmanager_config = /home/openchange/openchange/sogo-good/mapiproxy/services/client/ocsmanager.cfg
 
34
}
 
35
 
 
36
 Step 4: Restart dovecot
 
37
 */
 
38
 
 
39
#include "ocsmanager-plugin.h"
 
40
 
 
41
#define OCSMANAGER_USER_CONTEXT(obj) \
 
42
        MODULE_CONTEXT(obj, ocsmanager_user_module)
 
43
 
 
44
enum ocsmanager_field {
 
45
        OCSMANAGER_FIELD_UID            = 0x1,
 
46
        OCSMANAGER_FIELD_BOX            = 0x2,
 
47
        OCSMANAGER_FIELD_MSGID          = 0x4,
 
48
        OCSMANAGER_FIELD_PSIZE          = 0x8,
 
49
        OCSMANAGER_FIELD_VSIZE          = 0x10,
 
50
        OCSMANAGER_FIELD_FLAGS          = 0x20,
 
51
        OCSMANAGER_FIELD_FROM           = 0x40,
 
52
        OCSMANAGER_FIELD_SUBJECT        = 0x80
 
53
};
 
54
 
 
55
#define OCSMANAGER_DEFAULT_FIELDS \
 
56
        (OCSMANAGER_FIELD_UID | OCSMANAGER_FIELD_BOX | \
 
57
         OCSMANAGER_FIELD_MSGID | OCSMANAGER_FIELD_PSIZE)
 
58
 
 
59
enum ocsmanager_event {
 
60
        OCSMANAGER_EVENT_DELETE         = 0x1,
 
61
        OCSMANAGER_EVENT_UNDELETE       = 0x2,
 
62
        OCSMANAGER_EVENT_EXPUNGE        = 0x4,
 
63
        OCSMANAGER_EVENT_SAVE           = 0x8,
 
64
        OCSMANAGER_EVENT_COPY           = 0x10,
 
65
        OCSMANAGER_EVENT_MAILBOX_CREATE = 0x20,
 
66
        OCSMANAGER_EVENT_MAILBOX_DELETE = 0x40,
 
67
        OCSMANAGER_EVENT_MAILBOX_RENAME = 0x80,
 
68
        OCSMANAGER_EVENT_FLAG_CHANGE    = 0x100
 
69
};
 
70
 
 
71
#define OCSMANAGER_DEFAULT_EVENTS       (OCSMANAGER_EVENT_SAVE)
 
72
 
 
73
struct ocsmanager_user {
 
74
        union mail_user_module_context  module_ctx;
 
75
        enum ocsmanager_field           fields;
 
76
        enum ocsmanager_event           events;
 
77
        char                            *username;
 
78
        const char                      *backend;
 
79
        const char                      *bin;
 
80
        const char                      *config;
 
81
};
 
82
 
 
83
struct ocsmanager_message {
 
84
        struct ocsmanager_message       *prev;
 
85
        struct ocsmanager_message       *next;
 
86
        enum ocsmanager_event           event;
 
87
        bool                            ignore;
 
88
        uint32_t                        uid;
 
89
        char                            *destination_folder;
 
90
        char                            *username;
 
91
        const char                      *backend;
 
92
        char                            *bin;
 
93
        char                            *config;
 
94
};
 
95
 
 
96
struct ocsmanager_mail_txn_context {
 
97
        pool_t                          pool;
 
98
        struct ocsmanager_message       *messages;
 
99
        struct ocsmanager_message       *messages_tail;
 
100
};
 
101
 
 
102
static MODULE_CONTEXT_DEFINE_INIT(ocsmanager_user_module,
 
103
                                  &mail_user_module_register);
 
104
 
 
105
static void ocsmanager_mail_user_created(struct mail_user *user)
 
106
{
 
107
        struct ocsmanager_user  *ocsuser;
 
108
        const char              *str;
 
109
 
 
110
        i_debug("ocsmanager_mail_user_created");
 
111
        i_debug("username = %s", user->username);
 
112
 
 
113
        ocsuser = p_new(user->pool, struct ocsmanager_user, 1);
 
114
        MODULE_CONTEXT_SET(user, ocsmanager_user_module, ocsuser);
 
115
 
 
116
        ocsuser->fields = OCSMANAGER_DEFAULT_FIELDS;
 
117
        ocsuser->events = OCSMANAGER_DEFAULT_EVENTS;
 
118
        ocsuser->username = p_strdup(user->pool, user->username);
 
119
        str = mail_user_plugin_getenv(user, "ocsmanager_backend");
 
120
        if (!str) {
 
121
                i_fatal("Missing ocsmanager_backend parameter in dovecot.conf");
 
122
        }
 
123
        ocsuser->backend = str;
 
124
 
 
125
        str = mail_user_plugin_getenv(user, "ocsmanager_newmail");
 
126
        if (!str) {
 
127
                i_fatal("Missing ocsmanager_newmail parameter in dovecot.conf");
 
128
        }
 
129
        ocsuser->bin = str;
 
130
        
 
131
        str = mail_user_plugin_getenv(user, "ocsmanager_config");
 
132
        if (!str) {
 
133
                i_fatal("Missing ocsmanager_config parameter in dovecot.conf");
 
134
        }
 
135
        ocsuser->config = str;
 
136
}
 
137
 
 
138
static void ocsmanager_mail_save(void *txn, struct mail *mail)
 
139
{
 
140
        i_debug("ocsmanager_mail_save");
 
141
        i_debug("message UID = %d\n", mail->uid);
 
142
}
 
143
 
 
144
static void ocsmanager_mail_copy(void *txn, struct mail *src, struct mail *dst)
 
145
{
 
146
        struct ocsmanager_mail_txn_context      *ctx = (struct ocsmanager_mail_txn_context *) txn;
 
147
        struct ocsmanager_user                  *mctx = OCSMANAGER_USER_CONTEXT(dst->box->storage->user);
 
148
        struct ocsmanager_message               *msg;
 
149
        int                                     i;
 
150
 
 
151
        if (strcmp(src->box->storage->name, "raw") == 0) {
 
152
                /* special case: lda/lmtp is saving a mail */
 
153
                msg = p_new(ctx->pool, struct ocsmanager_message, 1);
 
154
                msg->event = OCSMANAGER_EVENT_COPY;
 
155
                msg->ignore = FALSE;
 
156
                msg->username = p_strdup(ctx->pool, mctx->username);
 
157
                msg->backend = p_strdup(ctx->pool, mctx->backend);
 
158
                msg->destination_folder = p_strdup(ctx->pool, mailbox_get_name(dst->box));
 
159
                msg->bin = p_strdup(ctx->pool, mctx->bin);
 
160
                msg->config = p_strdup(ctx->pool, mctx->config);
 
161
 
 
162
                /* FIXME: Quick hack of the night */
 
163
                msg->username[0] = toupper(msg->username[0]);
 
164
                for (i = 0; i < strlen(msg->destination_folder); i++) {
 
165
                        msg->destination_folder[i] = tolower(msg->destination_folder[i]);
 
166
                }
 
167
 
 
168
                DLLIST2_APPEND(&ctx->messages, &ctx->messages_tail, msg);               
 
169
        }
 
170
}
 
171
 
 
172
static void *ocsmanager_mail_transaction_begin(struct mailbox_transaction_context *t ATTR_UNUSED)
 
173
{
 
174
        pool_t                                  pool;
 
175
        struct ocsmanager_mail_txn_context      *ctx;
 
176
 
 
177
        pool = pool_alloconly_create("ocsmanager", 2048);
 
178
        ctx = p_new(pool, struct ocsmanager_mail_txn_context, 1);
 
179
        ctx->pool = pool;
 
180
 
 
181
        return ctx;
 
182
}
 
183
 
 
184
static void ocsmanager_mail_transaction_commit(void *txn, 
 
185
                                               struct mail_transaction_commit_changes *changes)
 
186
{
 
187
        struct ocsmanager_mail_txn_context      *ctx = (struct ocsmanager_mail_txn_context *)txn;
 
188
        uint32_t                                uid;
 
189
        struct ocsmanager_message               *msg;
 
190
        unsigned int                            n = 0;
 
191
        struct seq_range_iter                   iter;
 
192
        char                                    *command;
 
193
 
 
194
        seq_range_array_iter_init(&iter, &changes->saved_uids);
 
195
        for (msg = ctx->messages; msg != NULL; msg = msg->next) {
 
196
                if (msg->event == OCSMANAGER_EVENT_COPY) {
 
197
                        if (!seq_range_array_iter_nth(&iter, n++, &uid)) uid = 0;
 
198
                        msg->uid = uid;
 
199
                        
 
200
                        i_debug("# uid = %d", msg->uid);
 
201
                        i_debug("# folder = %s", msg->destination_folder);
 
202
                        i_debug("# username = %s", msg->username);
 
203
                        i_debug("# backend = %s", msg->backend);
 
204
 
 
205
                        /* FIXME: I'm ashamed but I'm tired */
 
206
                        command = p_strdup_printf(ctx->pool, "python %s --config %s --backend %s --user %s --folder %s --msgid %d", msg->bin, msg->config, msg->backend, msg->username, msg->destination_folder, msg->uid);
 
207
                        system(command);
 
208
                }
 
209
        }
 
210
        i_assert(!seq_range_array_iter_nth(&iter, n, &uid));
 
211
 
 
212
        pool_unref(&ctx->pool);
 
213
}
 
214
 
 
215
static void ocsmanager_mail_transaction_rollback(void *txn)
 
216
{
 
217
        struct ocsmanager_mail_txn_context      *ctx = (struct ocsmanager_mail_txn_context *) txn;
 
218
 
 
219
        pool_unref(&ctx->pool);
 
220
}
 
221
 
 
222
static const struct notify_vfuncs ocsmanager_vfuncs = {
 
223
        .mail_transaction_begin = ocsmanager_mail_transaction_begin,
 
224
        .mail_save = ocsmanager_mail_save,
 
225
        .mail_copy = ocsmanager_mail_copy,
 
226
        .mail_transaction_commit = ocsmanager_mail_transaction_commit,
 
227
        .mail_transaction_rollback = ocsmanager_mail_transaction_rollback,
 
228
};
 
229
 
 
230
static struct notify_context *ocsmanager_ctx;
 
231
 
 
232
static struct mail_storage_hooks ocsmanager_mail_storage_hooks = {
 
233
        .mail_user_created = ocsmanager_mail_user_created
 
234
};
 
235
 
 
236
void ocsmanager_plugin_init(struct module *module)
 
237
{
 
238
        i_debug("oscmanager_plugin_init");
 
239
        ocsmanager_ctx = notify_register(&ocsmanager_vfuncs);
 
240
        mail_storage_hooks_add(module, &ocsmanager_mail_storage_hooks);
 
241
}
 
242
 
 
243
void ocsmanager_plugin_deinit(void)
 
244
{  
 
245
        i_debug("oscmanager_plugin_deinit");
 
246
        mail_storage_hooks_remove(&ocsmanager_mail_storage_hooks);
 
247
        notify_unregister(ocsmanager_ctx);
 
248
}
 
249
 
 
250
const char *ocsmanager_plugin_dependencies[] = { "notify", NULL };