~james-page/ubuntu/raring/dovecot/autopkgtest

« back to all changes in this revision

Viewing changes to src/dsync/dsync-proxy-server-cmd.c

  • Committer: Package Import Robot
  • Author(s): James Page
  • Date: 2012-06-11 11:11:54 UTC
  • mfrom: (1.15.2) (4.1.27 sid)
  • Revision ID: package-import@ubuntu.com-20120611111154-678cwbdj6ktgsv1h
Tags: 1:2.1.7-1ubuntu1
* Merge from Debian unstable, remaining changes:
  + Add mail-stack-delivery package:
    - Update d/rules
    - d/control: convert existing dovecot-postfix package to a dummy
      package and add new mail-stack-delivery package.
    - Update maintainer scripts.
    - Rename d/dovecot-postfix.* to debian/mail-stack-delivery.*
    - d/mail-stack-delivery.preinst: Move previously installed backups and
      config files to a new package namespace.
    - d/mail-stack-delivery.prerm: Added to handle downgrades.
  + Use Snakeoil SSL certificates by default:
    - d/control: Depend on ssl-cert.
    - d/dovecot-core.postinst: Relax grep for SSL_* a bit.
  + Add autopkgtest to debian/tests/*.
  + Add ufw integration:
    - d/dovecot-core.ufw.profile: new ufw profile.
    - d/rules: install profile in dovecot-core.
    - d/control: dovecot-core - suggest ufw.
  + d/{control,rules}: enable PIE hardening.
  + d/dovecot-core.dirs: Added usr/share/doc/dovecot-core
  + Add apport hook:
    - d/rules, d/source_dovecot.py
  + Add upstart job:
    - d/rules, d/dovecot-core.dovecot.upstart, d/control,
      d/dovecot-core.dirs, dovecot-imapd.{postrm, postinst, prerm},
      d/dovecot-pop3d.{postinst, postrm, prerm}.
      d/mail-stack-deliver.postinst: Convert init script to upstart.
  + d/control: Added Pre-Depends: dpkg (>= 1.15.6) to dovecot-dbg to support
    xz compression in Ubuntu.
  + d/control: Demote dovecot-common Recommends: to Suggests: to prevent
    install of extra packages on upgrade.
  + d/patches/dovecot-drac.patch: Updated with version for dovecot >= 2.0.0.
  + d/control: Drop B-D on systemd.
* Dropped changes:
  + d/patches/fix-racey-restart.patch: part of 2.1.x, no longer required.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* Copyright (c) 2009-2011 Dovecot authors, see the included COPYING file */
2
 
 
3
 
#include "lib.h"
4
 
#include "array.h"
5
 
#include "str.h"
6
 
#include "strescape.h"
7
 
#include "network.h"
8
 
#include "istream.h"
9
 
#include "istream-dot.h"
10
 
#include "ostream.h"
11
 
#include "imap-util.h"
12
 
#include "master-service.h"
13
 
#include "dsync-worker.h"
14
 
#include "dsync-proxy.h"
15
 
#include "dsync-proxy-server.h"
16
 
 
17
 
#include <stdlib.h>
18
 
 
19
 
#define OUTBUF_THROTTLE_SIZE (1024*64)
20
 
 
21
 
static bool
22
 
proxy_server_is_output_full(struct dsync_proxy_server *server)
23
 
{
24
 
        return o_stream_get_buffer_used_size(server->output) >=
25
 
                OUTBUF_THROTTLE_SIZE;
26
 
}
27
 
 
28
 
static int
29
 
cmd_box_list(struct dsync_proxy_server *server,
30
 
             const char *const *args ATTR_UNUSED)
31
 
{
32
 
        struct dsync_mailbox dsync_box;
33
 
        string_t *str;
34
 
        int ret;
35
 
 
36
 
        if (server->mailbox_iter == NULL) {
37
 
                server->mailbox_iter =
38
 
                        dsync_worker_mailbox_iter_init(server->worker);
39
 
        }
40
 
 
41
 
        str = t_str_new(256);
42
 
        while ((ret = dsync_worker_mailbox_iter_next(server->mailbox_iter,
43
 
                                                     &dsync_box)) > 0) {
44
 
                str_truncate(str, 0);
45
 
                dsync_proxy_mailbox_export(str, &dsync_box);
46
 
                str_append_c(str, '\n');
47
 
                o_stream_send(server->output, str_data(str), str_len(str));
48
 
                if (proxy_server_is_output_full(server))
49
 
                        break;
50
 
        }
51
 
        if (ret >= 0) {
52
 
                /* continue later */
53
 
                o_stream_set_flush_pending(server->output, TRUE);
54
 
                return 0;
55
 
        }
56
 
        if (dsync_worker_mailbox_iter_deinit(&server->mailbox_iter) < 0) {
57
 
                o_stream_send(server->output, "-\n", 2);
58
 
                return -1;
59
 
        } else {
60
 
                o_stream_send(server->output, "+\n", 2);
61
 
                return 1;
62
 
        }
63
 
}
64
 
 
65
 
static bool cmd_subs_list_subscriptions(struct dsync_proxy_server *server)
66
 
{
67
 
        struct dsync_worker_subscription rec;
68
 
        string_t *str;
69
 
        int ret;
70
 
 
71
 
        str = t_str_new(256);
72
 
        while ((ret = dsync_worker_subs_iter_next(server->subs_iter,
73
 
                                                  &rec)) > 0) {
74
 
                str_truncate(str, 0);
75
 
                str_tabescape_write(str, rec.vname);
76
 
                str_append_c(str, '\t');
77
 
                str_tabescape_write(str, rec.storage_name);
78
 
                str_append_c(str, '\t');
79
 
                str_tabescape_write(str, rec.ns_prefix);
80
 
                str_printfa(str, "\t%ld\n", (long)rec.last_change);
81
 
                o_stream_send(server->output, str_data(str), str_len(str));
82
 
                if (proxy_server_is_output_full(server))
83
 
                        break;
84
 
        }
85
 
        if (ret >= 0) {
86
 
                /* continue later */
87
 
                o_stream_set_flush_pending(server->output, TRUE);
88
 
                return FALSE;
89
 
        }
90
 
        return TRUE;
91
 
}
92
 
 
93
 
static bool cmd_subs_list_unsubscriptions(struct dsync_proxy_server *server)
94
 
{
95
 
        struct dsync_worker_unsubscription rec;
96
 
        string_t *str;
97
 
        int ret;
98
 
 
99
 
        str = t_str_new(256);
100
 
        while ((ret = dsync_worker_subs_iter_next_un(server->subs_iter,
101
 
                                                     &rec)) > 0) {
102
 
                str_truncate(str, 0);
103
 
                dsync_proxy_mailbox_guid_export(str, &rec.name_sha1);
104
 
                str_append_c(str, '\t');
105
 
                str_tabescape_write(str, rec.ns_prefix);
106
 
                str_printfa(str, "\t%ld\n", (long)rec.last_change);
107
 
                o_stream_send(server->output, str_data(str), str_len(str));
108
 
                if (proxy_server_is_output_full(server))
109
 
                        break;
110
 
        }
111
 
        if (ret >= 0) {
112
 
                /* continue later */
113
 
                o_stream_set_flush_pending(server->output, TRUE);
114
 
                return FALSE;
115
 
        }
116
 
        return TRUE;
117
 
}
118
 
 
119
 
static int
120
 
cmd_subs_list(struct dsync_proxy_server *server,
121
 
              const char *const *args ATTR_UNUSED)
122
 
{
123
 
        if (server->subs_iter == NULL) {
124
 
                server->subs_iter =
125
 
                        dsync_worker_subs_iter_init(server->worker);
126
 
        }
127
 
 
128
 
        if (!server->subs_sending_unsubscriptions) {
129
 
                if (!cmd_subs_list_subscriptions(server))
130
 
                        return 0;
131
 
                /* a bit hacky way to handle this. this assumes that caller
132
 
                   goes through all subscriptions first, and next starts
133
 
                   going through unsubscriptions */
134
 
                o_stream_send(server->output, "+\n", 2);
135
 
                server->subs_sending_unsubscriptions = TRUE;
136
 
        }
137
 
        if (!cmd_subs_list_unsubscriptions(server))
138
 
                return 0;
139
 
 
140
 
        server->subs_sending_unsubscriptions = FALSE;
141
 
        if (dsync_worker_subs_iter_deinit(&server->subs_iter) < 0) {
142
 
                o_stream_send(server->output, "-\n", 2);
143
 
                return -1;
144
 
        } else {
145
 
                o_stream_send(server->output, "+\n", 2);
146
 
                return 1;
147
 
        }
148
 
}
149
 
 
150
 
static int
151
 
cmd_subs_set(struct dsync_proxy_server *server, const char *const *args)
152
 
{
153
 
        if (str_array_length(args) < 3) {
154
 
                i_error("subs-set: Missing parameters");
155
 
                return -1;
156
 
        }
157
 
 
158
 
        dsync_worker_set_subscribed(server->worker, args[0],
159
 
                                    strtoul(args[1], NULL, 10),
160
 
                                    strcmp(args[2], "1") == 0);
161
 
        return 1;
162
 
}
163
 
 
164
 
static int
165
 
cmd_msg_list_init(struct dsync_proxy_server *server, const char *const *args)
166
 
{
167
 
        mailbox_guid_t *mailboxes;
168
 
        unsigned int i, count;
169
 
        int ret;
170
 
 
171
 
        count = str_array_length(args);
172
 
        mailboxes = count == 0 ? NULL : t_new(mailbox_guid_t, count);
173
 
        for (i = 0; i < count; i++) {
174
 
                T_BEGIN {
175
 
                        ret = dsync_proxy_mailbox_guid_import(args[i],
176
 
                                                              &mailboxes[i]);
177
 
                } T_END;
178
 
 
179
 
                if (ret < 0) {
180
 
                        i_error("msg-list: Invalid mailbox GUID '%s'", args[i]);
181
 
                        return -1;
182
 
                }
183
 
        }
184
 
        server->msg_iter = dsync_worker_msg_iter_init(server->worker,
185
 
                                                      mailboxes, count);
186
 
        return 0;
187
 
}
188
 
 
189
 
static int
190
 
cmd_msg_list(struct dsync_proxy_server *server, const char *const *args)
191
 
{
192
 
        unsigned int mailbox_idx;
193
 
        struct dsync_message msg;
194
 
        string_t *str;
195
 
        int ret;
196
 
 
197
 
        if (server->msg_iter == NULL) {
198
 
                if (cmd_msg_list_init(server, args) < 0)
199
 
                        return -1;
200
 
        }
201
 
 
202
 
        str = t_str_new(256);
203
 
        while ((ret = dsync_worker_msg_iter_next(server->msg_iter,
204
 
                                                 &mailbox_idx, &msg)) > 0) {
205
 
                str_truncate(str, 0);
206
 
                str_printfa(str, "%u\t", mailbox_idx);
207
 
                dsync_proxy_msg_export(str, &msg);
208
 
                str_append_c(str, '\n');
209
 
                o_stream_send(server->output, str_data(str), str_len(str));
210
 
                if (proxy_server_is_output_full(server))
211
 
                        break;
212
 
        }
213
 
        if (ret >= 0) {
214
 
                /* continue later */
215
 
                o_stream_set_flush_pending(server->output, TRUE);
216
 
                return 0;
217
 
        }
218
 
        if (dsync_worker_msg_iter_deinit(&server->msg_iter) < 0) {
219
 
                o_stream_send(server->output, "-\n", 2);
220
 
                return -1;
221
 
        } else {
222
 
                o_stream_send(server->output, "+\n", 2);
223
 
                return 1;
224
 
        }
225
 
}
226
 
 
227
 
static int
228
 
cmd_box_create(struct dsync_proxy_server *server, const char *const *args)
229
 
{
230
 
        struct dsync_mailbox dsync_box;
231
 
        const char *error;
232
 
 
233
 
        if (dsync_proxy_mailbox_import_unescaped(pool_datastack_create(),
234
 
                                                 args, &dsync_box,
235
 
                                                 &error) < 0) {
236
 
                i_error("Invalid mailbox input: %s", error);
237
 
                return -1;
238
 
        }
239
 
        dsync_worker_create_mailbox(server->worker, &dsync_box);
240
 
        return 1;
241
 
}
242
 
 
243
 
static int
244
 
cmd_box_delete(struct dsync_proxy_server *server, const char *const *args)
245
 
{
246
 
        mailbox_guid_t guid;
247
 
        struct dsync_mailbox dsync_box;
248
 
 
249
 
        if (str_array_length(args) < 2)
250
 
                return -1;
251
 
        if (dsync_proxy_mailbox_guid_import(args[0], &guid) < 0) {
252
 
                i_error("box-delete: Invalid mailbox GUID '%s'", args[0]);
253
 
                return -1;
254
 
        }
255
 
 
256
 
        memset(&dsync_box, 0, sizeof(dsync_box));
257
 
        dsync_box.mailbox_guid = guid;
258
 
        dsync_box.last_change = strtoul(args[1], NULL, 10);
259
 
        dsync_worker_delete_mailbox(server->worker, &dsync_box);
260
 
        return 1;
261
 
}
262
 
 
263
 
static int
264
 
cmd_dir_delete(struct dsync_proxy_server *server, const char *const *args)
265
 
{
266
 
        struct dsync_mailbox dsync_box;
267
 
 
268
 
        if (str_array_length(args) < 2)
269
 
                return -1;
270
 
 
271
 
        memset(&dsync_box, 0, sizeof(dsync_box));
272
 
        dsync_box.name = str_tabunescape(t_strdup_noconst(args[0]));
273
 
        dsync_box.last_change = strtoul(args[1], NULL, 10);
274
 
        dsync_worker_delete_dir(server->worker, &dsync_box);
275
 
        return 1;
276
 
}
277
 
 
278
 
static int
279
 
cmd_box_rename(struct dsync_proxy_server *server, const char *const *args)
280
 
{
281
 
        mailbox_guid_t guid;
282
 
        struct dsync_mailbox dsync_box;
283
 
 
284
 
        if (str_array_length(args) < 3)
285
 
                return -1;
286
 
        if (dsync_proxy_mailbox_guid_import(args[0], &guid) < 0) {
287
 
                i_error("box-delete: Invalid mailbox GUID '%s'", args[0]);
288
 
                return -1;
289
 
        }
290
 
 
291
 
        memset(&dsync_box, 0, sizeof(dsync_box));
292
 
        dsync_box.name = args[1];
293
 
        dsync_box.name_sep = args[2][0];
294
 
        dsync_worker_rename_mailbox(server->worker, &guid, &dsync_box);
295
 
        return 1;
296
 
}
297
 
 
298
 
static int
299
 
cmd_box_update(struct dsync_proxy_server *server, const char *const *args)
300
 
{
301
 
        struct dsync_mailbox dsync_box;
302
 
        const char *error;
303
 
 
304
 
        if (dsync_proxy_mailbox_import_unescaped(pool_datastack_create(),
305
 
                                                 args, &dsync_box,
306
 
                                                 &error) < 0) {
307
 
                i_error("Invalid mailbox input: %s", error);
308
 
                return -1;
309
 
        }
310
 
        dsync_worker_update_mailbox(server->worker, &dsync_box);
311
 
        return 1;
312
 
}
313
 
 
314
 
static int
315
 
cmd_box_select(struct dsync_proxy_server *server, const char *const *args)
316
 
{
317
 
        struct dsync_mailbox box;
318
 
        unsigned int i, count;
319
 
 
320
 
        memset(&box, 0, sizeof(box));
321
 
        if (args[0] == NULL ||
322
 
            dsync_proxy_mailbox_guid_import(args[0], &box.mailbox_guid) < 0) {
323
 
                i_error("box-select: Invalid mailbox GUID '%s'", args[0]);
324
 
                return -1;
325
 
        }
326
 
        args++;
327
 
 
328
 
        count = str_array_length(args);
329
 
        t_array_init(&box.cache_fields, count + 1);
330
 
        for (i = 0; i < count; i++)
331
 
                array_append(&box.cache_fields, &args[i], 1);
332
 
        dsync_worker_select_mailbox(server->worker, &box);
333
 
        return 1;
334
 
}
335
 
 
336
 
static int
337
 
cmd_msg_update(struct dsync_proxy_server *server, const char *const *args)
338
 
{
339
 
        struct dsync_message msg;
340
 
 
341
 
        /* uid modseq flags */
342
 
        if (str_array_length(args) < 3)
343
 
                return -1;
344
 
 
345
 
        memset(&msg, 0, sizeof(msg));
346
 
        msg.uid = strtoul(args[0], NULL, 10);
347
 
        msg.modseq = strtoull(args[1], NULL, 10);
348
 
        if (dsync_proxy_msg_parse_flags(pool_datastack_create(),
349
 
                                        args[2], &msg) < 0)
350
 
                return -1;
351
 
 
352
 
        dsync_worker_msg_update_metadata(server->worker, &msg);
353
 
        return 1;
354
 
}
355
 
 
356
 
static int
357
 
cmd_msg_uid_change(struct dsync_proxy_server *server, const char *const *args)
358
 
{
359
 
        if (args[0] == NULL || args[1] == NULL)
360
 
                return -1;
361
 
 
362
 
        dsync_worker_msg_update_uid(server->worker,
363
 
                                    strtoul(args[0], NULL, 10),
364
 
                                    strtoul(args[1], NULL, 10));
365
 
        return 1;
366
 
}
367
 
 
368
 
static int
369
 
cmd_msg_expunge(struct dsync_proxy_server *server, const char *const *args)
370
 
{
371
 
        if (args[0] == NULL)
372
 
                return -1;
373
 
 
374
 
        dsync_worker_msg_expunge(server->worker, strtoul(args[0], NULL, 10));
375
 
        return 1;
376
 
}
377
 
 
378
 
static void copy_callback(bool success, void *context)
379
 
{
380
 
        struct dsync_proxy_server *server = context;
381
 
        const char *reply;
382
 
 
383
 
        i_assert(server->copy_uid != 0);
384
 
 
385
 
        reply = t_strdup_printf("%d\t%u\n", success ? 1 : 0, server->copy_uid);
386
 
        o_stream_send_str(server->output, reply);
387
 
}
388
 
 
389
 
static int
390
 
cmd_msg_copy(struct dsync_proxy_server *server, const char *const *args)
391
 
{
392
 
        mailbox_guid_t src_mailbox_guid;
393
 
        uint32_t src_uid;
394
 
        struct dsync_message msg;
395
 
        const char *error;
396
 
 
397
 
        /* src_mailbox_guid src_uid <message> */
398
 
        if (str_array_length(args) < 3)
399
 
                return -1;
400
 
 
401
 
        if (dsync_proxy_mailbox_guid_import(args[0], &src_mailbox_guid) < 0) {
402
 
                i_error("msg-copy: Invalid mailbox GUID '%s'", args[0]);
403
 
                return -1;
404
 
        }
405
 
        src_uid = strtoul(args[1], NULL, 10);
406
 
 
407
 
        if (dsync_proxy_msg_import_unescaped(pool_datastack_create(),
408
 
                                             args + 2, &msg, &error) < 0)
409
 
                i_error("Invalid message input: %s", error);
410
 
 
411
 
        server->copy_uid = src_uid;
412
 
        dsync_worker_msg_copy(server->worker, &src_mailbox_guid, src_uid, &msg,
413
 
                              copy_callback, server);
414
 
        server->copy_uid = 0;
415
 
        return 1;
416
 
}
417
 
 
418
 
static void cmd_msg_save_callback(void *context)
419
 
{
420
 
        struct dsync_proxy_server *server = context;
421
 
 
422
 
        server->save_finished = TRUE;
423
 
}
424
 
 
425
 
static int
426
 
cmd_msg_save(struct dsync_proxy_server *server, const char *const *args)
427
 
{
428
 
        struct dsync_message msg;
429
 
        struct dsync_msg_static_data data;
430
 
        const char *error;
431
 
        int ret;
432
 
 
433
 
        if (dsync_proxy_msg_static_import_unescaped(pool_datastack_create(),
434
 
                                                    args, &data, &error) < 0) {
435
 
                i_error("Invalid message input: %s", error);
436
 
                return -1;
437
 
        }
438
 
        data.input = i_stream_create_dot(server->input, FALSE);
439
 
 
440
 
        if (dsync_proxy_msg_import_unescaped(pool_datastack_create(),
441
 
                                             args + 2, &msg, &error) < 0) {
442
 
                i_error("Invalid message input: %s", error);
443
 
                return -1;
444
 
        }
445
 
 
446
 
        /* we rely on save reading the entire input */
447
 
        server->save_finished = FALSE;
448
 
        net_set_nonblock(server->fd_in, FALSE);
449
 
        dsync_worker_msg_save(server->worker, &msg, &data,
450
 
                              cmd_msg_save_callback, server);
451
 
        net_set_nonblock(server->fd_in, TRUE);
452
 
        ret = dsync_worker_has_failed(server->worker) ? -1 : 1;
453
 
        i_assert(server->save_finished);
454
 
        i_assert(data.input->eof || ret < 0);
455
 
        i_stream_destroy(&data.input);
456
 
        return ret;
457
 
}
458
 
 
459
 
static void cmd_msg_get_send_more(struct dsync_proxy_server *server)
460
 
{
461
 
        const unsigned char *data;
462
 
        size_t size;
463
 
        int ret;
464
 
 
465
 
        while (!proxy_server_is_output_full(server)) {
466
 
                ret = i_stream_read_data(server->get_input, &data, &size, 0);
467
 
                if (ret == -1) {
468
 
                        /* done */
469
 
                        o_stream_send(server->output, "\n.\n", 3);
470
 
                        i_stream_unref(&server->get_input);
471
 
                        return;
472
 
                } else {
473
 
                        /* for now we assume input is blocking */
474
 
                        i_assert(ret != 0);
475
 
                }
476
 
 
477
 
                dsync_proxy_send_dot_output(server->output,
478
 
                                            &server->get_input_last_lf,
479
 
                                            data, size);
480
 
                i_stream_skip(server->get_input, size);
481
 
        }
482
 
        o_stream_set_flush_pending(server->output, TRUE);
483
 
}
484
 
 
485
 
static void
486
 
cmd_msg_get_callback(enum dsync_msg_get_result result,
487
 
                     const struct dsync_msg_static_data *data, void *context)
488
 
{
489
 
        struct dsync_proxy_server *server = context;
490
 
        string_t *str;
491
 
 
492
 
        i_assert(server->get_uid != 0);
493
 
 
494
 
        switch (result) {
495
 
        case DSYNC_MSG_GET_RESULT_SUCCESS:
496
 
                break;
497
 
        case DSYNC_MSG_GET_RESULT_EXPUNGED:
498
 
                o_stream_send(server->output, "0\n", 3);
499
 
                return;
500
 
        case DSYNC_MSG_GET_RESULT_FAILED:
501
 
                o_stream_send(server->output, "-\n", 3);
502
 
                return;
503
 
        }
504
 
 
505
 
        str = t_str_new(128);
506
 
        str_printfa(str, "1\t%u\t", server->get_uid);
507
 
        dsync_proxy_msg_static_export(str, data);
508
 
        str_append_c(str, '\n');
509
 
        o_stream_send(server->output, str_data(str), str_len(str));
510
 
 
511
 
        /* then we'll still have to send the message body. */
512
 
        server->get_input = data->input;
513
 
        cmd_msg_get_send_more(server);
514
 
        if (server->get_input == NULL) {
515
 
                /* if we came here from ioloop, make sure the command gets
516
 
                   freed in the output flush callback */
517
 
                o_stream_set_flush_pending(server->output, TRUE);
518
 
        }
519
 
}
520
 
 
521
 
static int
522
 
cmd_msg_get(struct dsync_proxy_server *server, const char *const *args)
523
 
{
524
 
        mailbox_guid_t mailbox_guid;
525
 
        uint32_t uid;
526
 
 
527
 
        if (str_array_length(args) < 2)
528
 
                return -1;
529
 
 
530
 
        if (dsync_proxy_mailbox_guid_import(args[0], &mailbox_guid) < 0) {
531
 
                i_error("msg-get: Invalid mailbox GUID '%s'", args[0]);
532
 
                return -1;
533
 
        }
534
 
 
535
 
        uid = strtoul(args[1], NULL, 10);
536
 
        if (uid == 0)
537
 
                return -1;
538
 
 
539
 
        if (server->get_input != NULL) {
540
 
                i_assert(server->get_uid == uid);
541
 
                cmd_msg_get_send_more(server);
542
 
        } else {
543
 
                server->get_uid = uid;
544
 
                dsync_worker_msg_get(server->worker, &mailbox_guid, uid,
545
 
                                     cmd_msg_get_callback, server);
546
 
        }
547
 
        if (server->get_input != NULL)
548
 
                return 0;
549
 
        server->get_uid = 0;
550
 
        return 1;
551
 
}
552
 
 
553
 
static void cmd_finish_callback(bool success, void *context)
554
 
{
555
 
        struct dsync_proxy_server *server = context;
556
 
        const char *reply;
557
 
 
558
 
        if (!success)
559
 
                reply = "fail\n";
560
 
        else if (dsync_worker_has_unexpected_changes(server->worker))
561
 
                reply = "changes\n";
562
 
        else
563
 
                reply = "ok\n";
564
 
 
565
 
        server->finished = TRUE;
566
 
        o_stream_send_str(server->output, reply);
567
 
}
568
 
 
569
 
static int
570
 
cmd_finish(struct dsync_proxy_server *server,
571
 
           const char *const *args ATTR_UNUSED)
572
 
{
573
 
        dsync_worker_finish(server->worker, cmd_finish_callback, server);
574
 
        return 1;
575
 
}
576
 
 
577
 
static struct dsync_proxy_server_command commands[] = {
578
 
        { "BOX-LIST", cmd_box_list },
579
 
        { "SUBS-LIST", cmd_subs_list },
580
 
        { "SUBS-SET", cmd_subs_set },
581
 
        { "MSG-LIST", cmd_msg_list },
582
 
        { "BOX-CREATE", cmd_box_create },
583
 
        { "BOX-DELETE", cmd_box_delete },
584
 
        { "DIR-DELETE", cmd_dir_delete },
585
 
        { "BOX-RENAME", cmd_box_rename },
586
 
        { "BOX-UPDATE", cmd_box_update },
587
 
        { "BOX-SELECT", cmd_box_select },
588
 
        { "MSG-UPDATE", cmd_msg_update },
589
 
        { "MSG-UID-CHANGE", cmd_msg_uid_change },
590
 
        { "MSG-EXPUNGE", cmd_msg_expunge },
591
 
        { "MSG-COPY", cmd_msg_copy },
592
 
        { "MSG-SAVE", cmd_msg_save },
593
 
        { "MSG-GET", cmd_msg_get },
594
 
        { "FINISH", cmd_finish },
595
 
        { NULL, NULL }
596
 
};
597
 
 
598
 
struct dsync_proxy_server_command *
599
 
dsync_proxy_server_command_find(const char *name)
600
 
{
601
 
        unsigned int i;
602
 
 
603
 
        for (i = 0; commands[i].name != NULL; i++) {
604
 
                if (strcasecmp(commands[i].name, name) == 0)
605
 
                        return &commands[i];
606
 
        }
607
 
        return NULL;
608
 
}