~ubuntu-dev/ubuntu/lucid/dovecot/lucid-201002101901

« back to all changes in this revision

Viewing changes to libsieve/src/lib-sieve/plugins/imap4flags/ext-imap4flags-common.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
#include "str.h"
 
6
#include "str-sanitize.h"
 
7
 
 
8
#include "sieve-common.h"
 
9
#include "sieve-commands.h"
 
10
#include "sieve-code.h"
 
11
#include "sieve-actions.h"
 
12
#include "sieve-validator.h" 
 
13
#include "sieve-generator.h"
 
14
#include "sieve-interpreter.h"
 
15
#include "sieve-result.h"
 
16
#include "sieve-dump.h"
 
17
 
 
18
#include "sieve-ext-variables.h"
 
19
 
 
20
#include "ext-imap4flags-common.h"
 
21
 
 
22
/*
 
23
 * Forward declarations
 
24
 */
 
25
 
 
26
static bool flag_is_valid(const char *flag);
 
27
 
 
28
/* 
 
29
 * Tagged arguments 
 
30
 */
 
31
 
 
32
extern const struct sieve_argument tag_flags;
 
33
extern const struct sieve_argument tag_flags_implicit;
 
34
 
 
35
/* 
 
36
 * Common command functions 
 
37
 */
 
38
 
 
39
bool ext_imap4flags_command_validate
 
40
(struct sieve_validator *validator, struct sieve_command_context *cmd)
 
41
{
 
42
        struct sieve_ast_argument *arg = cmd->first_positional;
 
43
        struct sieve_ast_argument *arg2;
 
44
        
 
45
        /* Check arguments */
 
46
        
 
47
        if ( arg == NULL ) {
 
48
                sieve_command_validate_error(validator, cmd, 
 
49
                        "the %s %s expects at least one argument, but none was found", 
 
50
                        cmd->command->identifier, sieve_command_type_name(cmd->command));
 
51
                return FALSE;
 
52
        }
 
53
        
 
54
        if ( sieve_ast_argument_type(arg) != SAAT_STRING && 
 
55
                sieve_ast_argument_type(arg) != SAAT_STRING_LIST ) 
 
56
        {
 
57
                sieve_argument_validate_error(validator, arg, 
 
58
                        "the %s %s expects either a string (variable name) or "
 
59
                        "a string-list (list of flags) as first argument, but %s was found", 
 
60
                        cmd->command->identifier, sieve_command_type_name(cmd->command),
 
61
                        sieve_ast_argument_name(arg));
 
62
                return FALSE; 
 
63
        }
 
64
 
 
65
        arg2 = sieve_ast_argument_next(arg);
 
66
        if ( arg2 != NULL ) {           
 
67
                /* First, check syntax sanity */
 
68
                                
 
69
                if ( sieve_ast_argument_type(arg) != SAAT_STRING ) 
 
70
                {
 
71
                        if ( cmd->command == &tst_hasflag ) {
 
72
                                if ( sieve_ast_argument_type(arg) != SAAT_STRING_LIST ) {
 
73
                                        sieve_argument_validate_error(validator, arg, 
 
74
                                                "if a second argument is specified for the hasflag, the first "
 
75
                                                "must be a string-list (variable-list), but %s was found",
 
76
                                                sieve_ast_argument_name(arg));
 
77
                                        return FALSE;
 
78
                                }
 
79
                        } else {
 
80
                                sieve_argument_validate_error(validator, arg, 
 
81
                                        "if a second argument is specified for the %s %s, the first "
 
82
                                        "must be a string (variable name), but %s was found",
 
83
                                        cmd->command->identifier, sieve_command_type_name(cmd->command), 
 
84
                                        sieve_ast_argument_name(arg));
 
85
                                return FALSE; 
 
86
                        }
 
87
                }
 
88
                
 
89
                /* Then, check whether the second argument is permitted */
 
90
                
 
91
                if ( !sieve_ext_variables_is_active(validator) )        {
 
92
                        sieve_argument_validate_error(validator,arg, 
 
93
                                "the %s %s only allows for the specification of a "
 
94
                                "variable name when the variables extension is active",
 
95
                                cmd->command->identifier, sieve_command_type_name(cmd->command));
 
96
                        return FALSE;
 
97
                }               
 
98
                
 
99
                if ( !sieve_variable_argument_activate(validator, cmd, arg, 
 
100
                        cmd->command != &tst_hasflag ) )
 
101
                        return FALSE;
 
102
                
 
103
                if ( sieve_ast_argument_type(arg2) != SAAT_STRING && 
 
104
                        sieve_ast_argument_type(arg2) != SAAT_STRING_LIST ) 
 
105
                {
 
106
                        sieve_argument_validate_error(validator, arg2, 
 
107
                                "the %s %s expects a string list (list of flags) as "
 
108
                                "second argument when two arguments are specified, "
 
109
                                "but %s was found",
 
110
                                cmd->command->identifier, sieve_command_type_name(cmd->command),
 
111
                                sieve_ast_argument_name(arg2));
 
112
                        return FALSE; 
 
113
                }
 
114
        } else
 
115
                arg2 = arg;
 
116
 
 
117
        if ( !sieve_validator_argument_activate(validator, cmd, arg2, FALSE) )
 
118
                return FALSE;
 
119
 
 
120
        if ( cmd->command != &tst_hasflag && sieve_argument_is_string_literal(arg2) ) {
 
121
                struct ext_imap4flags_iter fiter;
 
122
                const char *flag;
 
123
                
 
124
                /* Warn the user about validity of verifiable flags */
 
125
                ext_imap4flags_iter_init(&fiter, sieve_ast_argument_str(arg));
 
126
 
 
127
                while ( (flag=ext_imap4flags_iter_get_flag(&fiter)) != NULL ) {
 
128
                        if ( !flag_is_valid(flag) ) {
 
129
                                sieve_argument_validate_warning(validator, arg,
 
130
                        "IMAP flag '%s' specified for the %s command is invalid "
 
131
                                        "and will be ignored (only first invalid is reported)",                                 
 
132
                                        str_sanitize(flag, 64), cmd->command->identifier);
 
133
                                break;
 
134
                        }
 
135
                }
 
136
        }
 
137
 
 
138
        return TRUE;
 
139
}
 
140
 
 
141
/* 
 
142
 * Flags tag registration 
 
143
 */
 
144
 
 
145
void ext_imap4flags_attach_flags_tag
 
146
(struct sieve_validator *valdtr, const char *command)
 
147
{
 
148
        /* Register :flags tag with the command and we don't care whether it is 
 
149
         * registered or even whether it will be registered at all. The validator 
 
150
         * handles either situation gracefully 
 
151
         */
 
152
         
 
153
        /* Tag specified by user */
 
154
        sieve_validator_register_external_tag
 
155
                (valdtr, &tag_flags, command, SIEVE_OPT_SIDE_EFFECT);
 
156
 
 
157
    /* Implicit tag if none is specified */
 
158
        sieve_validator_register_persistent_tag
 
159
                (valdtr, &tag_flags_implicit, command);
 
160
}
 
161
 
 
162
/* 
 
163
 * Result context 
 
164
 */
 
165
 
 
166
struct ext_imap4flags_result_context {
 
167
    string_t *internal_flags;
 
168
};
 
169
 
 
170
static void _get_initial_flags
 
171
(struct sieve_result *result, string_t *flags)
 
172
{
 
173
        const struct sieve_message_data *msgdata = 
 
174
                sieve_result_get_message_data(result);
 
175
        enum mail_flags mail_flags;
 
176
        const char *const *mail_keywords;
 
177
 
 
178
        mail_flags = mail_get_flags(msgdata->mail);
 
179
        mail_keywords = mail_get_keywords(msgdata->mail);       
 
180
 
 
181
        if ( (mail_flags & MAIL_FLAGGED) > 0 )
 
182
                str_printfa(flags, " \\flagged");
 
183
 
 
184
        if ( (mail_flags & MAIL_ANSWERED) > 0 )
 
185
                str_printfa(flags, " \\answered");
 
186
 
 
187
        if ( (mail_flags & MAIL_DELETED) > 0 )
 
188
                str_printfa(flags, " \\deleted");
 
189
 
 
190
        if ( (mail_flags & MAIL_SEEN) > 0 )
 
191
                str_printfa(flags, " \\seen");
 
192
 
 
193
        if ( (mail_flags & MAIL_DRAFT) > 0 )
 
194
                str_printfa(flags, " \\draft");
 
195
 
 
196
        while ( *mail_keywords != NULL ) {
 
197
                str_printfa(flags, " %s", *mail_keywords);
 
198
                mail_keywords++;
 
199
        }       
 
200
}
 
201
 
 
202
static inline struct ext_imap4flags_result_context *_get_result_context
 
203
(struct sieve_result *result)
 
204
{
 
205
        struct ext_imap4flags_result_context *rctx =
 
206
                (struct ext_imap4flags_result_context *) 
 
207
                sieve_result_extension_get_context(result, &imap4flags_extension);
 
208
 
 
209
        if ( rctx == NULL ) {
 
210
                pool_t pool = sieve_result_pool(result);
 
211
 
 
212
                rctx =p_new(pool, struct ext_imap4flags_result_context, 1);
 
213
                rctx->internal_flags = str_new(pool, 32);
 
214
                _get_initial_flags(result, rctx->internal_flags);
 
215
 
 
216
                sieve_result_extension_set_context
 
217
                        (result, &imap4flags_extension, rctx);
 
218
        }
 
219
 
 
220
        return rctx;
 
221
}
 
222
 
 
223
static string_t *_get_flags_string
 
224
(struct sieve_result *result)
 
225
{
 
226
        struct ext_imap4flags_result_context *ctx = 
 
227
                _get_result_context(result);
 
228
                
 
229
        return ctx->internal_flags;
 
230
}
 
231
 
 
232
/* 
 
233
 * Runtime initialization 
 
234
 */
 
235
 
 
236
static void ext_imap4flags_runtime_init
 
237
(const struct sieve_runtime_env *renv, void *context ATTR_UNUSED)
 
238
{       
 
239
        sieve_result_add_implicit_side_effect
 
240
                (renv->result, NULL, TRUE, &flags_side_effect, NULL);
 
241
}
 
242
 
 
243
const struct sieve_interpreter_extension imap4flags_interpreter_extension = {
 
244
        &imap4flags_extension,
 
245
        ext_imap4flags_runtime_init,
 
246
        NULL,
 
247
};
 
248
 
 
249
/* 
 
250
 * Flag operations 
 
251
 */
 
252
 
 
253
/* FIXME: This currently accepts a potentially unlimited number of 
 
254
 * flags, making the internal or variable flag list indefinitely long
 
255
 */
 
256
static bool flag_is_valid(const char *flag)
 
257
{       
 
258
        if (*flag == '\\') {
 
259
                /* System flag */
 
260
                const char *atom = t_str_ucase(flag); 
 
261
        
 
262
                if (
 
263
                        (strcmp(atom, "\\ANSWERED") != 0) &&
 
264
                        (strcmp(atom, "\\FLAGGED") != 0) &&
 
265
                        (strcmp(atom, "\\DELETED") != 0) &&
 
266
                        (strcmp(atom, "\\SEEN") != 0) &&
 
267
                        (strcmp(atom, "\\DRAFT") != 0) )  
 
268
                {           
 
269
                        return FALSE;
 
270
                }
 
271
        } else {
 
272
                /* Custom keyword:
 
273
                 *
 
274
                 * The validity of the keyword cannot be validated until the 
 
275
                 * target mailbox for the message is known. Meaning that the 
 
276
                 * verfication of keyword can only be performed when the
 
277
                 * action side effect is about to be executed.
 
278
                 *
 
279
                 * FIXME: technically this is nonsense, since we can simply parse
 
280
                 * using the flag-keyword grammar provided by imap.
 
281
                 */                                     
 
282
        }
 
283
 
 
284
        return TRUE;  
 
285
}
 
286
 
 
287
void ext_imap4flags_iter_init
 
288
(struct ext_imap4flags_iter *iter, string_t *flags_list) 
 
289
{
 
290
        iter->flags_list = flags_list;
 
291
        iter->offset = 0;
 
292
        iter->last = 0;
 
293
}
 
294
 
 
295
const char *ext_imap4flags_iter_get_flag
 
296
(struct ext_imap4flags_iter *iter) 
 
297
{
 
298
        unsigned int len = str_len(iter->flags_list);
 
299
        const unsigned char *fp;
 
300
        const unsigned char *fbegin;
 
301
        const unsigned char *fstart;
 
302
        const unsigned char *fend;
 
303
        
 
304
        if ( iter->offset >= len ) return NULL;
 
305
        
 
306
        fbegin = str_data(iter->flags_list);
 
307
        fp = fbegin + iter->offset;
 
308
        fstart = fp;
 
309
        fend = fbegin + len;
 
310
        for (;;) {
 
311
                if ( fp >= fend || *fp == ' ' ) { 
 
312
                        if ( fp > fstart ) {
 
313
                                const char *flag = t_strdup_until(fstart, fp);
 
314
                                
 
315
                                iter->last = fstart - fbegin;
 
316
                                iter->offset = fp - fbegin;
 
317
                                return flag;
 
318
                        }       
 
319
                        
 
320
                        fstart = fp+1;
 
321
                }
 
322
                
 
323
                if ( fp >= fend ) break;
 
324
                                
 
325
                fp++;
 
326
        }
 
327
        
 
328
        iter->last = fstart - fbegin;
 
329
        iter->offset = fp - fbegin;
 
330
        return NULL;
 
331
}
 
332
 
 
333
static void ext_imap4flags_iter_delete_last
 
334
(struct ext_imap4flags_iter *iter) 
 
335
{
 
336
        iter->offset++;
 
337
        if ( iter->offset > str_len(iter->flags_list) )
 
338
                iter->offset = str_len(iter->flags_list);
 
339
        if ( iter->offset == str_len(iter->flags_list) )
 
340
                iter->last--;
 
341
 
 
342
        str_delete(iter->flags_list, iter->last, iter->offset - iter->last);    
 
343
        
 
344
        iter->offset = iter->last;
 
345
}
 
346
 
 
347
static bool flags_list_flag_exists
 
348
(string_t *flags_list, const char *flag)
 
349
{
 
350
        const char *flg;
 
351
        struct ext_imap4flags_iter flit;
 
352
                
 
353
        ext_imap4flags_iter_init(&flit, flags_list);
 
354
        
 
355
        while ( (flg=ext_imap4flags_iter_get_flag(&flit)) != NULL ) {
 
356
                if ( strcasecmp(flg, flag) == 0 ) 
 
357
                        return TRUE;    
 
358
        }
 
359
        
 
360
        return FALSE;
 
361
}
 
362
 
 
363
static void flags_list_flag_delete
 
364
(string_t *flags_list, const char *flag)
 
365
{
 
366
        const char *flg;
 
367
        struct ext_imap4flags_iter flit;
 
368
                
 
369
        ext_imap4flags_iter_init(&flit, flags_list);
 
370
        
 
371
        while ( (flg=ext_imap4flags_iter_get_flag(&flit)) != NULL ) {
 
372
                if ( strcasecmp(flg, flag) == 0 ) {
 
373
                        ext_imap4flags_iter_delete_last(&flit);
 
374
                }       
 
375
        }
 
376
}
 
377
                        
 
378
static void flags_list_add_flags
 
379
(string_t *flags_list, string_t *flags)
 
380
{       
 
381
        const char *flg;
 
382
        struct ext_imap4flags_iter flit;
 
383
                
 
384
        ext_imap4flags_iter_init(&flit, flags);
 
385
        
 
386
        while ( (flg=ext_imap4flags_iter_get_flag(&flit)) != NULL ) {
 
387
                if ( flag_is_valid(flg) && !flags_list_flag_exists(flags_list, flg) ) {
 
388
                        if ( str_len(flags_list) != 0 ) 
 
389
                                str_append_c(flags_list, ' '); 
 
390
                        str_append(flags_list, flg);
 
391
                }       
 
392
        }
 
393
}
 
394
 
 
395
static void flags_list_remove_flags
 
396
(string_t *flags_list, string_t *flags)
 
397
{       
 
398
        const char *flg;
 
399
        struct ext_imap4flags_iter flit;
 
400
                
 
401
        ext_imap4flags_iter_init(&flit, flags);
 
402
        
 
403
        while ( (flg=ext_imap4flags_iter_get_flag(&flit)) != NULL ) {
 
404
                flags_list_flag_delete(flags_list, flg);        
 
405
        }
 
406
}
 
407
 
 
408
static void flags_list_set_flags
 
409
(string_t *flags_list, string_t *flags)
 
410
{
 
411
        str_truncate(flags_list, 0);
 
412
        flags_list_add_flags(flags_list, flags);
 
413
}
 
414
 
 
415
/* 
 
416
 * Flag registration 
 
417
 */
 
418
 
 
419
int ext_imap4flags_set_flags
 
420
(const struct sieve_runtime_env *renv, struct sieve_variable_storage *storage,
 
421
        unsigned int var_index, string_t *flags)
 
422
{
 
423
        string_t *cur_flags;
 
424
        
 
425
        if ( storage != NULL ) {
 
426
                if ( !sieve_variable_get_modifiable(storage, var_index, &cur_flags) )
 
427
                        return SIEVE_EXEC_BIN_CORRUPT;
 
428
        } else
 
429
                cur_flags = _get_flags_string(renv->result);
 
430
 
 
431
        if ( cur_flags != NULL )
 
432
                flags_list_set_flags(cur_flags, flags);         
 
433
 
 
434
        return SIEVE_EXEC_OK;
 
435
}
 
436
 
 
437
int ext_imap4flags_add_flags
 
438
(const struct sieve_runtime_env *renv, struct sieve_variable_storage *storage,
 
439
        unsigned int var_index, string_t *flags)
 
440
{
 
441
        string_t *cur_flags;
 
442
        
 
443
        if ( storage != NULL ) {
 
444
                if ( !sieve_variable_get_modifiable(storage, var_index, &cur_flags) )
 
445
                        return SIEVE_EXEC_BIN_CORRUPT;
 
446
        } else
 
447
                cur_flags = _get_flags_string(renv->result);
 
448
        
 
449
        if ( cur_flags != NULL )
 
450
                flags_list_add_flags(cur_flags, flags);
 
451
        
 
452
        return SIEVE_EXEC_OK;   
 
453
}
 
454
 
 
455
int ext_imap4flags_remove_flags
 
456
(const struct sieve_runtime_env *renv, struct sieve_variable_storage *storage,
 
457
        unsigned int var_index, string_t *flags)
 
458
{
 
459
        string_t *cur_flags;
 
460
        
 
461
        if ( storage != NULL ) {
 
462
                if ( !sieve_variable_get_modifiable(storage, var_index, &cur_flags) )
 
463
                        return SIEVE_EXEC_BIN_CORRUPT;
 
464
        } else
 
465
                cur_flags = _get_flags_string(renv->result);
 
466
        
 
467
        if ( cur_flags != NULL )
 
468
                flags_list_remove_flags(cur_flags, flags);              
 
469
 
 
470
        return SIEVE_EXEC_OK;
 
471
}
 
472
 
 
473
int ext_imap4flags_get_flags_string
 
474
(const struct sieve_runtime_env *renv, struct sieve_variable_storage *storage, 
 
475
        unsigned int var_index, const char **flags)
 
476
{
 
477
        string_t *cur_flags;
 
478
        
 
479
        if ( storage != NULL ) {
 
480
                if ( !sieve_variable_get_modifiable(storage, var_index, &cur_flags) )
 
481
                        return SIEVE_EXEC_BIN_CORRUPT;
 
482
        } else
 
483
                cur_flags = _get_flags_string(renv->result);
 
484
        
 
485
        if ( cur_flags == NULL )
 
486
                *flags = "";
 
487
        else 
 
488
                *flags = str_c(cur_flags);
 
489
 
 
490
        return SIEVE_EXEC_OK;
 
491
}
 
492
 
 
493
void ext_imap4flags_get_flags_init
 
494
(struct ext_imap4flags_iter *iter, const struct sieve_runtime_env *renv,
 
495
        string_t *flags_list)
 
496
{
 
497
        string_t *cur_flags;
 
498
        
 
499
        if ( flags_list != NULL ) {
 
500
                cur_flags = t_str_new(256);
 
501
                
 
502
                flags_list_set_flags(cur_flags, flags_list);
 
503
        }
 
504
        else
 
505
                cur_flags = _get_flags_string(renv->result);
 
506
        
 
507
        ext_imap4flags_iter_init(iter, cur_flags);              
 
508
}
 
509
 
 
510
void ext_imap4flags_get_implicit_flags_init
 
511
(struct ext_imap4flags_iter *iter, struct sieve_result *result)
 
512
{
 
513
        string_t *cur_flags = _get_flags_string(result);
 
514
        
 
515
        ext_imap4flags_iter_init(iter, cur_flags);              
 
516
}
 
517
 
 
518
 
 
519
        
 
520
        
 
521