~ubuntu-dev/ubuntu/lucid/dovecot/lucid-201002110912

« back to all changes in this revision

Viewing changes to libsieve/src/lib-sieve/plugins/enotify/cmd-notify.c

  • Committer: Chuck Short
  • Date: 2010-01-21 20:21:25 UTC
  • mfrom: (4.1.11 squeeze)
  • Revision ID: zulcss@ubuntu.com-20100121202125-pme73o491kfwj5nc
* Merge from debian testing, remaining changes:
  + Add new binary pkg dovecot-postfix that integrates postfix and dovecot
    automatically: (LP: #164837)
  + debian/control:
    - add new binary with short description
    - set Architecture all for dovecot-postfix (LP: #329878)
  + debian/dovecot-postfix.postinst:
    - create initial certificate symlinks to snakeoil.
    - set up postfix with postconf to:
      - use Maildir/ as the default mailbox.
      - use dovecot as the sasl authentication server.
      - use dovecot LDA (deliver).
      - use tls for smtp{d} services.
    - fix certificates paths in postfix' main.cf
    - add reject_unauth_destination to postfix' recipient restrictions
    - add reject_unknown_sender_domain to postfix' sender restriction
    - rename configuration name on remove, delete on purge
    - restart dovecot after linking certificates
    - handle use case when postfix is unconfigurated
  + debian/dovecot-postfix.dirs: create backup directory for postfix's config
    configuration
  + restart postfix and dovecot.
  + debian/dovecot-postfix.postrm:
    - remove all dovecot related configuration from postfix.
    - restart postfix and dovecot.
  + debian/dovecot-common.init:
    - check if /etc/dovecot/dovecot-postfix.conf exists and use it
      as the configuration file if so.
  + debian/patches/warning-ubuntu-postfix.dpatch
    - add warning about dovecot-postfix.conf in dovecot default
      configuration file
  + debian/patches/dovecot-postfix.conf.diff:
    - Ubuntu server custom changes to the default dovecot configuration for
      better interfation with postfix.
    - enable sieve plugin.
    - Ubuntu server custom changes to the default dovecot configuration for
      better integration with postfix:
      - enable imap, pop3, imaps, pop3s and managesieve by default.
      - enable dovecot LDA (deliver).
      - enable SASL auth socket in postfix private directory
   + debian/rules:
     - copy, patch and install dovecot-postfix.conf in /etc/dovecot/.
     - build architecure independent packages too
   + Use Snakeoil SSL certificates by default.
     - debian/control: Depend on ssl-cert.
     - debian/patches/ssl-cert-snakeoil.dpatch: Change default SSL cert
       paths to snakeoil.
     - debian/dovecot-common.postinst: Relax grep for SSL_* a bit.
   + Add autopkgtest to debian/tests/*.
   + Fast TearDown: Update the lsb init header to not stop in level 6.
   + Add ufw integration:
     - Created debian/dovecot-common.ufw.profile.
     - debian/rules: install profile.
     - debian/control: suggest ufw.
   + debian/{control,rules}: enable PIE hardening.
   + dovecot-imapd, dovecot-pop3: Replaces dovecot-common (<< 1:1.1). (LP: #254721)
   + debian/control: Update Vcs-* headers.
   + Add SMTP-AUTH support for Outlook (login auth mechanism)
* New upstream release.
* debian/patches/gold-fix.patch: Removed. Fixed upstream.
* Moved libexec to lib corrections in dovecot-managesieve.patch and
  dovecot-managesieve-dist.patch to dovecot-example.patch
* debian/patches/dovecot-mboxlocking.patch: Regenerated to avoid FTBFS
  when quilt isn't installed.
* debian/patches/quota-mountpoint.patch: Removed. Not needed anymore.
* debian/patches/dovecot-quota.patch: Removed. Quotas aren't properly
  enabled unless mail_plugins = quota imap_quota.
* debian/patches/gold-fix.patch: Fixed configure script to build even
  with binutils-gold or --no-add-needed linker flag (Closes: #554306)
* debian/dovecot-common.init: fixed LSB headers. Thanks to Pascal Volk.
  (Closes: #558040)
* debian/changelog: added CVE references to previous changelog entry.
* debian/rules: checked up the build system. It's not fragile anymore.
  (Closes: 493803)
* debian/dovecot-common.postinst: Now invoking dpkg-reconfigure
  on dovecot-common is enough to generate new certificates
  if the previous ones were removed. (Closes: #545582)
* debian/rules: No longer install convert-tool in /usr/bin.
  It isn't an user utility and it should stay in /usr/lib/dovecot
  like all other similar tool.
* New upstream release. (Closes: #557601)
* [SECURITY] Fixes local information disclosure and denial of service.
  (see: http://www.dovecot.org/list/dovecot-news/2009-November/000143.html
  and CVE-2009-3897)
* Added myself to uploaders.
* Switched to the new source format "3.0 (quilt)":
  - removed dpatch from build-depends
  - removed debian/README.source because now we use only standard
    dpkg features
  - regenerated all patches
* Prepared to switch to multi-origin source:
  - recreated dovecot-libsieve.patch and dovecot-managesieve-dist.patch
    starting from the upstream tarball
  - removed all autotools related build-depends and build-conflict
  - renamed dovecot-libsieve and dovecot-managesieve directories
    to libsieve and managesieve.
* debian/rules: Moved the configuration of libsieve and managesieve from
  the build phase to the configuration phase
* Added dovecot-dbg package  with debugging symbols.  Thanks Stephan Bosch.
  (Closes: #554710)
* Fixed some stray libexec'isms in the default configuration.
* New upstream release.
* debian/dovecot-common.init:
  - use $CONF when starting the daemon. (Closes: #549944)
  - always output start/stop messages. (Closes: #523810)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Copyright (c) 2002-2009 Dovecot Sieve authors, see the included COPYING file
 
2
 */
 
3
 
 
4
#include "lib.h"
 
5
 
 
6
#include "sieve-common.h"
 
7
#include "sieve-code.h"
 
8
#include "sieve-extensions.h"
 
9
#include "sieve-commands.h"
 
10
#include "sieve-actions.h"
 
11
#include "sieve-validator.h"
 
12
#include "sieve-generator.h"
 
13
#include "sieve-interpreter.h"
 
14
#include "sieve-dump.h"
 
15
#include "sieve-result.h"
 
16
 
 
17
#include "ext-enotify-common.h"
 
18
 
 
19
/* 
 
20
 * Forward declarations 
 
21
 */
 
22
 
 
23
static const struct sieve_argument notify_importance_tag;
 
24
static const struct sieve_argument notify_from_tag;
 
25
static const struct sieve_argument notify_options_tag;
 
26
static const struct sieve_argument notify_message_tag;
 
27
 
 
28
/* 
 
29
 * Notify command 
 
30
 *      
 
31
 * Syntax: 
 
32
 *    notify [":from" string]
 
33
 *           [":importance" <"1" / "2" / "3">]
 
34
 *           [":options" string-list]
 
35
 *           [":message" string]
 
36
 *           <method: string>
 
37
 */
 
38
 
 
39
static bool cmd_notify_registered
 
40
        (struct sieve_validator *valdtr, 
 
41
                struct sieve_command_registration *cmd_reg);
 
42
static bool cmd_notify_pre_validate
 
43
        (struct sieve_validator *validator, struct sieve_command_context *cmd);
 
44
static bool cmd_notify_validate
 
45
        (struct sieve_validator *valdtr, struct sieve_command_context *cmd);
 
46
static bool cmd_notify_generate
 
47
        (const struct sieve_codegen_env *cgenv, struct sieve_command_context *ctx);
 
48
 
 
49
const struct sieve_command notify_command = { 
 
50
        "notify",
 
51
        SCT_COMMAND, 
 
52
        1, 0, FALSE, FALSE, 
 
53
        cmd_notify_registered,
 
54
        cmd_notify_pre_validate,
 
55
        cmd_notify_validate, 
 
56
        cmd_notify_generate, 
 
57
        NULL 
 
58
};
 
59
 
 
60
/*
 
61
 * Notify command tags
 
62
 */
 
63
 
 
64
/* Forward declarations */
 
65
 
 
66
static bool cmd_notify_validate_string_tag
 
67
        (struct sieve_validator *valdtr, struct sieve_ast_argument **arg, 
 
68
                struct sieve_command_context *cmd);
 
69
static bool cmd_notify_validate_stringlist_tag
 
70
        (struct sieve_validator *valdtr, struct sieve_ast_argument **arg, 
 
71
                struct sieve_command_context *cmd);
 
72
static bool cmd_notify_validate_importance_tag
 
73
        (struct sieve_validator *valdtr, struct sieve_ast_argument **arg, 
 
74
                struct sieve_command_context *cmd);
 
75
 
 
76
/* Argument objects */
 
77
 
 
78
static const struct sieve_argument notify_from_tag = { 
 
79
        "from", 
 
80
        NULL, NULL,
 
81
        cmd_notify_validate_string_tag, 
 
82
        NULL, NULL 
 
83
};
 
84
 
 
85
static const struct sieve_argument notify_options_tag = { 
 
86
        "options", 
 
87
        NULL, NULL,
 
88
        cmd_notify_validate_stringlist_tag, 
 
89
        NULL, NULL 
 
90
};
 
91
 
 
92
static const struct sieve_argument notify_message_tag = { 
 
93
        "message", 
 
94
        NULL, NULL, 
 
95
        cmd_notify_validate_string_tag, 
 
96
        NULL, NULL 
 
97
};
 
98
 
 
99
static const struct sieve_argument notify_importance_tag = { 
 
100
        "importance", 
 
101
        NULL, NULL,
 
102
        cmd_notify_validate_importance_tag, 
 
103
        NULL, NULL 
 
104
};
 
105
 
 
106
/* 
 
107
 * Notify operation 
 
108
 */
 
109
 
 
110
static bool cmd_notify_operation_dump
 
111
        (const struct sieve_operation *op,      
 
112
                const struct sieve_dumptime_env *denv, sieve_size_t *address);
 
113
static int cmd_notify_operation_execute
 
114
        (const struct sieve_operation *op, 
 
115
                const struct sieve_runtime_env *renv, sieve_size_t *address);
 
116
 
 
117
const struct sieve_operation notify_operation = { 
 
118
        "NOTIFY",
 
119
        &enotify_extension,
 
120
        EXT_ENOTIFY_OPERATION_NOTIFY,
 
121
        cmd_notify_operation_dump, 
 
122
        cmd_notify_operation_execute
 
123
};
 
124
 
 
125
/* 
 
126
 * Notify action 
 
127
 */
 
128
 
 
129
/* Forward declarations */
 
130
 
 
131
static int act_notify_check_duplicate
 
132
        (const struct sieve_runtime_env *renv, 
 
133
                const struct sieve_action_data *act,
 
134
                const struct sieve_action_data *act_other);
 
135
static void act_notify_print
 
136
        (const struct sieve_action *action, const struct sieve_result_print_env *rpenv,
 
137
                void *context, bool *keep);     
 
138
static bool act_notify_commit
 
139
        (const struct sieve_action *action,     const struct sieve_action_exec_env *aenv, 
 
140
                void *tr_context, bool *keep);
 
141
 
 
142
/* Action object */
 
143
 
 
144
const struct sieve_action act_notify = {
 
145
        "notify",
 
146
        0,
 
147
        NULL,
 
148
        act_notify_check_duplicate, 
 
149
        NULL,
 
150
        act_notify_print,
 
151
        NULL, NULL,
 
152
        act_notify_commit,
 
153
        NULL
 
154
};
 
155
 
 
156
/*
 
157
 * Command validation context
 
158
 */
 
159
 
 
160
struct cmd_notify_context_data {
 
161
        struct sieve_ast_argument *from;
 
162
        struct sieve_ast_argument *message;
 
163
        struct sieve_ast_argument *options;
 
164
};
 
165
 
 
166
/* 
 
167
 * Tag validation 
 
168
 */
 
169
 
 
170
static bool cmd_notify_validate_string_tag
 
171
(struct sieve_validator *valdtr, struct sieve_ast_argument **arg, 
 
172
        struct sieve_command_context *cmd)
 
173
{
 
174
        struct sieve_ast_argument *tag = *arg;
 
175
        struct cmd_notify_context_data *ctx_data = 
 
176
                (struct cmd_notify_context_data *) cmd->data; 
 
177
 
 
178
        /* Detach the tag itself */
 
179
        *arg = sieve_ast_arguments_detach(*arg,1);
 
180
        
 
181
        /* Check syntax:
 
182
         *   :from <string>
 
183
         *   :message <string>
 
184
         */
 
185
        if ( !sieve_validate_tag_parameter(valdtr, cmd, tag, *arg, SAAT_STRING) )
 
186
                return FALSE;
 
187
 
 
188
        if ( tag->argument == &notify_from_tag ) {
 
189
                ctx_data->from = *arg;
 
190
                
 
191
                /* Skip parameter */
 
192
                *arg = sieve_ast_argument_next(*arg);
 
193
                
 
194
        } else if ( tag->argument == &notify_message_tag ) {
 
195
                ctx_data->message = *arg;
 
196
 
 
197
                /* Skip parameter */
 
198
                *arg = sieve_ast_argument_next(*arg);   
 
199
        }
 
200
                        
 
201
        return TRUE;
 
202
}
 
203
 
 
204
static bool cmd_notify_validate_stringlist_tag
 
205
(struct sieve_validator *valdtr, struct sieve_ast_argument **arg, 
 
206
        struct sieve_command_context *cmd)
 
207
{
 
208
        struct sieve_ast_argument *tag = *arg;
 
209
        struct cmd_notify_context_data *ctx_data = 
 
210
                (struct cmd_notify_context_data *) cmd->data; 
 
211
 
 
212
        /* Detach the tag itself */
 
213
        *arg = sieve_ast_arguments_detach(*arg,1);
 
214
        
 
215
        /* Check syntax:
 
216
         *   :options string-list
 
217
         */
 
218
        if ( !sieve_validate_tag_parameter(valdtr, cmd, tag, *arg, SAAT_STRING_LIST) ) 
 
219
                return FALSE;
 
220
                
 
221
        /* Assign context */
 
222
        ctx_data->options = *arg;       
 
223
        
 
224
        /* Skip parameter */
 
225
        *arg = sieve_ast_argument_next(*arg);
 
226
 
 
227
        return TRUE;
 
228
}
 
229
 
 
230
static bool cmd_notify_validate_importance_tag
 
231
(struct sieve_validator *valdtr, struct sieve_ast_argument **arg, 
 
232
        struct sieve_command_context *cmd ATTR_UNUSED)
 
233
{
 
234
        const struct sieve_ast_argument *tag = *arg;
 
235
        const char *impstr;
 
236
 
 
237
        /* Detach the tag itself */
 
238
        *arg = sieve_ast_arguments_detach(*arg,1);
 
239
 
 
240
        /* Check syntax: 
 
241
         *   :importance <"1" / "2" / "3">
 
242
         */
 
243
 
 
244
        if ( sieve_ast_argument_type(*arg) != SAAT_STRING ) {
 
245
                /* Not a string */
 
246
                sieve_argument_validate_error(valdtr, *arg, 
 
247
                        "the :importance tag for the notify command requires a string parameter, "
 
248
                        "but %s was found", sieve_ast_argument_name(*arg));
 
249
                return FALSE;
 
250
        }
 
251
 
 
252
        impstr = sieve_ast_argument_strc(*arg);
 
253
 
 
254
        if ( impstr[0] < '1' || impstr[0]  > '3' || impstr[1] != '\0' ) {
 
255
                /* Invalid importance */
 
256
                sieve_argument_validate_error(valdtr, *arg, 
 
257
                        "invalid :importance value for notify command: %s", impstr);
 
258
                return FALSE;
 
259
        } 
 
260
 
 
261
        sieve_ast_argument_number_substitute(*arg, impstr[0] - '0');
 
262
        (*arg)->arg_id_code = tag->arg_id_code;
 
263
        (*arg)->argument = &number_argument;
 
264
 
 
265
        /* Skip parameter */
 
266
        *arg = sieve_ast_argument_next(*arg);
 
267
                        
 
268
        return TRUE;
 
269
}
 
270
 
 
271
 
 
272
/* 
 
273
 * Command registration 
 
274
 */
 
275
 
 
276
static bool cmd_notify_registered
 
277
(struct sieve_validator *valdtr, struct sieve_command_registration *cmd_reg) 
 
278
{
 
279
        sieve_validator_register_tag
 
280
                (valdtr, cmd_reg, &notify_importance_tag, CMD_NOTIFY_OPT_IMPORTANCE);   
 
281
        sieve_validator_register_tag
 
282
                (valdtr, cmd_reg, &notify_from_tag, CMD_NOTIFY_OPT_FROM);       
 
283
        sieve_validator_register_tag
 
284
                (valdtr, cmd_reg, &notify_options_tag, CMD_NOTIFY_OPT_OPTIONS);         
 
285
        sieve_validator_register_tag
 
286
                (valdtr, cmd_reg, &notify_message_tag, CMD_NOTIFY_OPT_MESSAGE);         
 
287
 
 
288
        return TRUE;
 
289
}
 
290
 
 
291
/* 
 
292
 * Command validation 
 
293
 */
 
294
 
 
295
static bool cmd_notify_pre_validate
 
296
(struct sieve_validator *validator ATTR_UNUSED, 
 
297
        struct sieve_command_context *cmd) 
 
298
{
 
299
        struct cmd_notify_context_data *ctx_data;
 
300
        
 
301
        /* Assign context */
 
302
        ctx_data = p_new(sieve_command_pool(cmd), 
 
303
                struct cmd_notify_context_data, 1);
 
304
        cmd->data = ctx_data;
 
305
 
 
306
        return TRUE;
 
307
}
 
308
 
 
309
static bool cmd_notify_validate
 
310
(struct sieve_validator *valdtr, struct sieve_command_context *cmd) 
 
311
{       
 
312
        struct sieve_ast_argument *arg = cmd->first_positional;
 
313
        struct cmd_notify_context_data *ctx_data = 
 
314
                (struct cmd_notify_context_data *) cmd->data; 
 
315
 
 
316
        if ( !sieve_validate_positional_argument
 
317
                (valdtr, cmd, arg, "method", 1, SAAT_STRING) ) {
 
318
                return FALSE;
 
319
        }
 
320
        
 
321
        if ( !sieve_validator_argument_activate(valdtr, cmd, arg, FALSE) )
 
322
                return FALSE;
 
323
                
 
324
        return ext_enotify_compile_check_arguments
 
325
                (valdtr, arg, ctx_data->message, ctx_data->from, ctx_data->options);
 
326
}
 
327
 
 
328
/*
 
329
 * Code generation
 
330
 */
 
331
 
 
332
static bool cmd_notify_generate
 
333
(const struct sieve_codegen_env *cgenv, struct sieve_command_context *ctx) 
 
334
{                
 
335
        sieve_operation_emit_code(cgenv->sbin, &notify_operation);
 
336
 
 
337
        /* Emit source line */
 
338
        sieve_code_source_line_emit(cgenv->sbin, sieve_command_source_line(ctx));
 
339
 
 
340
        /* Generate arguments */
 
341
        return sieve_generate_arguments(cgenv, ctx, NULL);
 
342
}
 
343
 
 
344
/* 
 
345
 * Code dump
 
346
 */
 
347
 
 
348
static bool cmd_notify_operation_dump
 
349
(const struct sieve_operation *op ATTR_UNUSED,
 
350
        const struct sieve_dumptime_env *denv, sieve_size_t *address)
 
351
{       
 
352
        int opt_code = 1;
 
353
        
 
354
        sieve_code_dumpf(denv, "NOTIFY");
 
355
        sieve_code_descend(denv);       
 
356
 
 
357
        /* Source line */
 
358
        if ( !sieve_code_source_line_dump(denv, address) )
 
359
                return FALSE;
 
360
 
 
361
        /* Dump optional operands */
 
362
        if ( sieve_operand_optional_present(denv->sbin, address) ) {
 
363
                while ( opt_code != 0 ) {
 
364
                        sieve_code_mark(denv);
 
365
                        
 
366
                        if ( !sieve_operand_optional_read(denv->sbin, address, &opt_code) ) 
 
367
                                return FALSE;
 
368
 
 
369
                        switch ( opt_code ) {
 
370
                        case 0:
 
371
                                break;
 
372
                        case CMD_NOTIFY_OPT_IMPORTANCE:
 
373
                                if ( !sieve_opr_number_dump(denv, address, "importance") )
 
374
                                        return FALSE;
 
375
                                break;
 
376
                        case CMD_NOTIFY_OPT_FROM:
 
377
                                if ( !sieve_opr_string_dump(denv, address, "from") )
 
378
                                        return FALSE;
 
379
                                break;
 
380
                        case CMD_NOTIFY_OPT_OPTIONS:
 
381
                                if ( !sieve_opr_stringlist_dump(denv, address, "options") )
 
382
                                        return FALSE;
 
383
                                break;
 
384
                        case CMD_NOTIFY_OPT_MESSAGE:
 
385
                                if ( !sieve_opr_string_dump(denv, address, "message") )
 
386
                                        return FALSE;
 
387
                                break;
 
388
                        default:
 
389
                                return FALSE;
 
390
                        }
 
391
                }
 
392
        }
 
393
        
 
394
        /* Dump reason and handle operands */
 
395
        return 
 
396
                sieve_opr_string_dump(denv, address, "method");
 
397
}
 
398
 
 
399
/* 
 
400
 * Code execution
 
401
 */
 
402
 
 
403
static int cmd_notify_operation_execute
 
404
(const struct sieve_operation *op ATTR_UNUSED,
 
405
        const struct sieve_runtime_env *renv, sieve_size_t *address)
 
406
{       
 
407
        struct sieve_side_effects_list *slist = NULL;
 
408
        struct sieve_enotify_action *act;
 
409
        void *method_context;
 
410
        pool_t pool;
 
411
        int opt_code = 1, result = SIEVE_EXEC_OK;
 
412
        sieve_number_t importance = 1;
 
413
        struct sieve_coded_stringlist *options = NULL;
 
414
        const struct sieve_enotify_method *method;
 
415
        string_t *method_uri, *message = NULL, *from = NULL; 
 
416
        unsigned int source_line;
 
417
 
 
418
        /*
 
419
         * Read operands
 
420
         */
 
421
                
 
422
        /* Source line */
 
423
        if ( !sieve_code_source_line_read(renv, address, &source_line) ) {
 
424
                sieve_runtime_trace_error(renv, "invalid source line");
 
425
                return SIEVE_EXEC_BIN_CORRUPT;
 
426
        }
 
427
        
 
428
        /* Optional operands */ 
 
429
        if ( sieve_operand_optional_present(renv->sbin, address) ) {
 
430
                while ( opt_code != 0 ) {
 
431
                        if ( !sieve_operand_optional_read(renv->sbin, address, &opt_code) ) {
 
432
                                sieve_runtime_trace_error(renv, "invalid optional operand");
 
433
                                return SIEVE_EXEC_BIN_CORRUPT;
 
434
                        }
 
435
 
 
436
                        switch ( opt_code ) {
 
437
                        case 0:
 
438
                                break;
 
439
                        case CMD_NOTIFY_OPT_IMPORTANCE:
 
440
                                if ( !sieve_opr_number_read(renv, address, &importance) ) {
 
441
                                        sieve_runtime_trace_error(renv, "invalid importance operand");
 
442
                                        return SIEVE_EXEC_BIN_CORRUPT;
 
443
                                }
 
444
        
 
445
                                /* Enforce 0 < importance < 4 (just to be sure) */
 
446
                                if ( importance < 1 ) 
 
447
                                        importance = 1;
 
448
                                else if ( importance > 3 )
 
449
                                        importance = 3;
 
450
                                break;
 
451
                        case CMD_NOTIFY_OPT_FROM:
 
452
                                if ( !sieve_opr_string_read(renv, address, &from) ) {
 
453
                                        sieve_runtime_trace_error(renv, "invalid from operand");
 
454
                                        return SIEVE_EXEC_BIN_CORRUPT;
 
455
                                }
 
456
                                break;
 
457
                        case CMD_NOTIFY_OPT_MESSAGE:
 
458
                                if ( !sieve_opr_string_read(renv, address, &message) ) {
 
459
                                        sieve_runtime_trace_error(renv, "invalid from operand");
 
460
                                        return SIEVE_EXEC_BIN_CORRUPT;
 
461
                                }
 
462
                                break;
 
463
                        case CMD_NOTIFY_OPT_OPTIONS:
 
464
                                if ( (options=sieve_opr_stringlist_read(renv, address)) == NULL ) {
 
465
                                        sieve_runtime_trace_error(renv, "invalid options operand");
 
466
                                        return SIEVE_EXEC_BIN_CORRUPT;
 
467
                                }
 
468
                                break;
 
469
                        default:
 
470
                                sieve_runtime_trace_error(renv, "unknown optional operand: %d", 
 
471
                                        opt_code);
 
472
                                return SIEVE_EXEC_BIN_CORRUPT;
 
473
                        }
 
474
                }
 
475
        }
 
476
        
 
477
        /* Reason operand */
 
478
        if ( !sieve_opr_string_read(renv, address, &method_uri) ) {
 
479
                sieve_runtime_trace_error(renv, "invalid method operand");
 
480
                return SIEVE_EXEC_BIN_CORRUPT;
 
481
        }
 
482
                
 
483
        /*
 
484
         * Perform operation
 
485
         */
 
486
 
 
487
        sieve_runtime_trace(renv, "NOTIFY action");     
 
488
 
 
489
        /* Check operands */
 
490
 
 
491
        if ( (result=ext_enotify_runtime_check_operands
 
492
                (renv, source_line, method_uri, message, from, options, &method, 
 
493
                        &method_context)) ) 
 
494
        {
 
495
                /* Add notify action to the result */
 
496
 
 
497
                pool = sieve_result_pool(renv->result);
 
498
                act = p_new(pool, struct sieve_enotify_action, 1);
 
499
                act->method = method;
 
500
                act->method_context = method_context;
 
501
                act->importance = importance;
 
502
                if ( message != NULL )
 
503
                        act->message = p_strdup(pool, str_c(message));
 
504
                if ( from != NULL )
 
505
                        act->from = p_strdup(pool, str_c(from));
 
506
                
 
507
                return ( sieve_result_add_action
 
508
                        (renv, &act_notify, slist, source_line, (void *) act, 0) >= 0 );
 
509
        }
 
510
        
 
511
        return result;
 
512
}
 
513
 
 
514
/*
 
515
 * Action
 
516
 */
 
517
 
 
518
/* Runtime verification */
 
519
 
 
520
static int act_notify_check_duplicate
 
521
(const struct sieve_runtime_env *renv ATTR_UNUSED, 
 
522
        const struct sieve_action_data *act ATTR_UNUSED,
 
523
        const struct sieve_action_data *act_other ATTR_UNUSED)
 
524
{
 
525
        const struct sieve_enotify_action *nact1, *nact2;
 
526
        struct sieve_enotify_log nlog;
 
527
                
 
528
        if ( act->context == NULL || act_other->context == NULL )
 
529
                return 0;
 
530
 
 
531
        nact1 = (const struct sieve_enotify_action *) act->context;
 
532
        nact2 = (const struct sieve_enotify_action *) act_other->context;
 
533
 
 
534
        if ( nact1->method == NULL || nact1->method->action_check_duplicates == NULL )
 
535
                return 0;
 
536
 
 
537
        memset(&nlog, 0, sizeof(nlog));
 
538
        nlog.location = act->location;
 
539
        nlog.ehandler = sieve_result_get_error_handler(renv->result);
 
540
 
 
541
        return nact1->method->action_check_duplicates
 
542
                (&nlog, nact1->method_context, nact2->method_context, act_other->location);
 
543
}
 
544
 
 
545
/* Result printing */
 
546
 
 
547
static void act_notify_print
 
548
(const struct sieve_action *action ATTR_UNUSED, 
 
549
        const struct sieve_result_print_env *rpenv, void *context, 
 
550
        bool *keep ATTR_UNUSED) 
 
551
{
 
552
        const struct sieve_enotify_action *act = 
 
553
                (const struct sieve_enotify_action *) context;
 
554
 
 
555
        sieve_result_action_printf
 
556
                ( rpenv, "send notification with method '%s:':", act->method->identifier);
 
557
                
 
558
        if ( act->method->action_print != NULL ) {
 
559
                struct sieve_enotify_print_env penv;
 
560
 
 
561
                memset(&penv, 0, sizeof(penv));
 
562
                penv.result_penv = rpenv;
 
563
 
 
564
                act->method->action_print(&penv, act);
 
565
        }
 
566
}
 
567
 
 
568
/* Result execution */
 
569
 
 
570
static bool act_notify_commit
 
571
(const struct sieve_action *action ATTR_UNUSED, 
 
572
        const struct sieve_action_exec_env *aenv, void *tr_context, 
 
573
        bool *keep ATTR_UNUSED)
 
574
{
 
575
        const struct sieve_enotify_action *act = 
 
576
                (const struct sieve_enotify_action *) tr_context;
 
577
        struct sieve_enotify_exec_env nenv;
 
578
        struct sieve_enotify_log nlog;
 
579
                
 
580
        memset(&nlog, 0, sizeof(nlog));
 
581
        nlog.location = sieve_action_get_location(aenv);
 
582
        nlog.ehandler = sieve_result_get_error_handler(aenv->result);
 
583
 
 
584
        nenv.scriptenv = aenv->scriptenv;
 
585
        nenv.msgdata = aenv->msgdata;
 
586
        nenv.msgctx = aenv->msgctx;
 
587
        nenv.notify_log = &nlog;
 
588
 
 
589
        if ( act->method->action_execute != NULL )
 
590
                return act->method->action_execute(&nenv, act);
 
591
                        
 
592
        return TRUE;
 
593
}
 
594
 
 
595
 
 
596
 
 
597