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

« back to all changes in this revision

Viewing changes to libsieve/src/lib-sieve/ext-envelope.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
/* Extension envelope 
 
5
 * ------------------
 
6
 *
 
7
 * Authors: Stephan Bosch
 
8
 * Specification: RFC5228
 
9
 * Implementation: full
 
10
 * Status: experimental, largely untested
 
11
 *
 
12
 */
 
13
 
 
14
#include "lib.h"
 
15
#include "str-sanitize.h"
 
16
#include "array.h"
 
17
 
 
18
#include "sieve-common.h"
 
19
#include "sieve-extensions.h"
 
20
#include "sieve-commands.h"
 
21
#include "sieve-code.h"
 
22
#include "sieve-address.h"
 
23
#include "sieve-comparators.h"
 
24
#include "sieve-match-types.h"
 
25
#include "sieve-address-parts.h"
 
26
#include "sieve-message.h"
 
27
 
 
28
#include "sieve-validator.h"
 
29
#include "sieve-generator.h"
 
30
#include "sieve-interpreter.h"
 
31
#include "sieve-dump.h"
 
32
#include "sieve-match.h"
 
33
 
 
34
/*
 
35
 * Forward declarations
 
36
 */
 
37
 
 
38
static const struct sieve_command envelope_test;
 
39
const struct sieve_operation envelope_operation;
 
40
const struct sieve_extension envelope_extension;
 
41
 
 
42
/* 
 
43
 * Extension 
 
44
 */
 
45
 
 
46
static bool ext_envelope_validator_load(struct sieve_validator *validator);
 
47
 
 
48
static int ext_my_id = -1;
 
49
 
 
50
const struct sieve_extension envelope_extension = { 
 
51
        "envelope", 
 
52
        &ext_my_id,
 
53
        NULL, NULL,
 
54
        ext_envelope_validator_load, 
 
55
        NULL, NULL, NULL, NULL, NULL,
 
56
        SIEVE_EXT_DEFINE_OPERATION(envelope_operation), 
 
57
        SIEVE_EXT_DEFINE_NO_OPERANDS 
 
58
};
 
59
 
 
60
static bool ext_envelope_validator_load(struct sieve_validator *validator)
 
61
{
 
62
        /* Register new test */
 
63
        sieve_validator_register_command(validator, &envelope_test);
 
64
 
 
65
        return TRUE;
 
66
}
 
67
 
 
68
/* 
 
69
 * Envelope test 
 
70
 *
 
71
 * Syntax
 
72
 *   envelope [COMPARATOR] [ADDRESS-PART] [MATCH-TYPE]
 
73
 *     <envelope-part: string-list> <key-list: string-list>   
 
74
 */
 
75
 
 
76
static bool tst_envelope_registered
 
77
        (struct sieve_validator *validator, struct sieve_command_registration *cmd_reg);
 
78
static bool tst_envelope_validate
 
79
        (struct sieve_validator *validator, struct sieve_command_context *tst);
 
80
static bool tst_envelope_generate
 
81
        (const struct sieve_codegen_env *cgenv, struct sieve_command_context *ctx);
 
82
 
 
83
static const struct sieve_command envelope_test = { 
 
84
        "envelope", 
 
85
        SCT_TEST, 
 
86
        2, 0, FALSE, FALSE,
 
87
        tst_envelope_registered, 
 
88
        NULL,
 
89
        tst_envelope_validate, 
 
90
        tst_envelope_generate, 
 
91
        NULL 
 
92
};
 
93
 
 
94
/* 
 
95
 * Envelope operation 
 
96
 */
 
97
 
 
98
static bool ext_envelope_operation_dump
 
99
        (const struct sieve_operation *op, 
 
100
                const struct sieve_dumptime_env *denv, sieve_size_t *address);
 
101
static int ext_envelope_operation_execute
 
102
        (const struct sieve_operation *op,
 
103
                const struct sieve_runtime_env *renv, sieve_size_t *address);
 
104
 
 
105
const struct sieve_operation envelope_operation = { 
 
106
        "ENVELOPE",
 
107
        &envelope_extension,
 
108
        0,
 
109
        ext_envelope_operation_dump, 
 
110
        ext_envelope_operation_execute 
 
111
};
 
112
 
 
113
/*
 
114
 * Envelope parts
 
115
 *
 
116
 * FIXME: not available to extensions
 
117
 */
 
118
 
 
119
struct sieve_envelope_part {
 
120
        const char *identifier;
 
121
 
 
122
        const struct sieve_address *const *(*get_addresses)
 
123
                (const struct sieve_runtime_env *renv);
 
124
        const char * const *(*get_values)
 
125
                (const struct sieve_runtime_env *renv);
 
126
};
 
127
 
 
128
static const struct sieve_address *const *_from_part_get_addresses
 
129
        (const struct sieve_runtime_env *renv);
 
130
static const char *const *_from_part_get_values
 
131
        (const struct sieve_runtime_env *renv);
 
132
static const struct sieve_address *const *_to_part_get_addresses
 
133
        (const struct sieve_runtime_env *renv);
 
134
static const char *const *_to_part_get_values
 
135
        (const struct sieve_runtime_env *renv);
 
136
static const char *const *_auth_part_get_values
 
137
        (const struct sieve_runtime_env *renv);
 
138
 
 
139
static const struct sieve_envelope_part _from_part = {
 
140
        "from",
 
141
        _from_part_get_addresses,
 
142
        _from_part_get_values,
 
143
};
 
144
 
 
145
static const struct sieve_envelope_part _to_part = {
 
146
        "to",
 
147
        _to_part_get_addresses,
 
148
        _to_part_get_values,
 
149
};      
 
150
 
 
151
static const struct sieve_envelope_part _auth_part = {
 
152
        "auth",
 
153
        NULL,
 
154
        _auth_part_get_values,
 
155
};      
 
156
 
 
157
static const struct sieve_envelope_part *_envelope_parts[] = {
 
158
        /* Required */
 
159
        &_from_part, &_to_part, 
 
160
 
 
161
        /* Non-standard */
 
162
        &_auth_part
 
163
};
 
164
 
 
165
static unsigned int _envelope_part_count = N_ELEMENTS(_envelope_parts);
 
166
 
 
167
static const struct sieve_envelope_part *_envelope_part_find
 
168
(const char *identifier)
 
169
{
 
170
        unsigned int i;
 
171
 
 
172
        for ( i = 0; i < _envelope_part_count; i++ ) {
 
173
                if ( strcasecmp( _envelope_parts[i]->identifier, identifier ) == 0 ) {
 
174
                        return _envelope_parts[i];
 
175
        }
 
176
        }
 
177
        
 
178
        return NULL;
 
179
}
 
180
 
 
181
 
 
182
/* 
 
183
 * Command Registration 
 
184
 */
 
185
 
 
186
static bool tst_envelope_registered
 
187
(struct sieve_validator *validator, struct sieve_command_registration *cmd_reg) 
 
188
{
 
189
        /* The order of these is not significant */
 
190
        sieve_comparators_link_tag(validator, cmd_reg, SIEVE_AM_OPT_COMPARATOR);
 
191
        sieve_address_parts_link_tags(validator, cmd_reg, SIEVE_AM_OPT_ADDRESS_PART);
 
192
        sieve_match_types_link_tags(validator, cmd_reg, SIEVE_AM_OPT_MATCH_TYPE);
 
193
        
 
194
        return TRUE;
 
195
}
 
196
 
 
197
/* 
 
198
 * Validation 
 
199
 */
 
200
 
 
201
static int _envelope_part_is_supported
 
202
(void *context, struct sieve_ast_argument *arg)
 
203
{
 
204
        const struct sieve_envelope_part **not_address =
 
205
                (const struct sieve_envelope_part **) context;
 
206
 
 
207
        if ( sieve_argument_is_string_literal(arg) ) {
 
208
                const struct sieve_envelope_part *epart;
 
209
 
 
210
                if ( (epart=_envelope_part_find(sieve_ast_strlist_strc(arg))) != NULL ) {
 
211
                        if ( epart->get_addresses == NULL ) {
 
212
                                if ( *not_address == NULL )
 
213
                                        *not_address = epart;
 
214
                        }
 
215
                                        
 
216
                        return TRUE;
 
217
                }
 
218
                
 
219
                return FALSE;
 
220
        } 
 
221
        
 
222
        return TRUE; /* Can't check at compile time */
 
223
}
 
224
 
 
225
static bool tst_envelope_validate
 
226
(struct sieve_validator *validator, struct sieve_command_context *tst) 
 
227
{               
 
228
        struct sieve_ast_argument *arg = tst->first_positional;
 
229
        struct sieve_ast_argument *epart;
 
230
        const struct sieve_envelope_part *not_address = NULL;
 
231
                                
 
232
        if ( !sieve_validate_positional_argument
 
233
                (validator, tst, arg, "envelope part", 1, SAAT_STRING_LIST) ) {
 
234
                return FALSE;
 
235
        }
 
236
        
 
237
        if ( !sieve_validator_argument_activate(validator, tst, arg, FALSE) )
 
238
                return FALSE;
 
239
                
 
240
        /* Check whether supplied envelope parts are supported
 
241
         *   FIXME: verify dynamic envelope parts at runtime 
 
242
         */
 
243
        epart = arg;
 
244
        if ( !sieve_ast_stringlist_map(&epart, (void *) &not_address, 
 
245
                _envelope_part_is_supported) ) {                
 
246
                
 
247
                sieve_argument_validate_error(validator, epart, 
 
248
                        "specified envelope part '%s' is not supported by the envelope test", 
 
249
                                str_sanitize(sieve_ast_strlist_strc(epart), 64));
 
250
                return FALSE;
 
251
        }
 
252
 
 
253
        if ( not_address != NULL ) {
 
254
                struct sieve_ast_argument *addrp_arg = 
 
255
                        sieve_command_find_argument(tst, &address_part_tag);
 
256
 
 
257
                if ( addrp_arg != NULL ) {
 
258
                        sieve_argument_validate_error(validator, addrp_arg,
 
259
                                "address part ':%s' specified while non-address envelope part '%s' "
 
260
                                "is tested with the envelope test",
 
261
                sieve_ast_argument_tag(addrp_arg), not_address->identifier);
 
262
                return FALSE;
 
263
                }
 
264
        }
 
265
        
 
266
        arg = sieve_ast_argument_next(arg);
 
267
        
 
268
        if ( !sieve_validate_positional_argument
 
269
                (validator, tst, arg, "key list", 2, SAAT_STRING_LIST) ) {
 
270
                return FALSE;
 
271
        }
 
272
        
 
273
        if ( !sieve_validator_argument_activate(validator, tst, arg, FALSE) )
 
274
                return FALSE;
 
275
 
 
276
        /* Validate the key argument to a specified match type */
 
277
        return sieve_match_type_validate
 
278
                (validator, tst, arg, &is_match_type, &i_ascii_casemap_comparator);
 
279
}
 
280
 
 
281
/*
 
282
 * Code generation
 
283
 */
 
284
 
 
285
static bool tst_envelope_generate
 
286
(const struct sieve_codegen_env *cgenv, struct sieve_command_context *ctx) 
 
287
{
 
288
        (void)sieve_operation_emit_code(cgenv->sbin, &envelope_operation);
 
289
 
 
290
        /* Generate arguments */
 
291
        if ( !sieve_generate_arguments(cgenv, ctx, NULL) )
 
292
                return FALSE;
 
293
 
 
294
        return TRUE;
 
295
}
 
296
 
 
297
/* 
 
298
 * Code dump 
 
299
 */
 
300
 
 
301
static bool ext_envelope_operation_dump
 
302
(const struct sieve_operation *op ATTR_UNUSED, 
 
303
        const struct sieve_dumptime_env *denv, sieve_size_t *address)
 
304
{
 
305
        sieve_code_dumpf(denv, "ENVELOPE");
 
306
        sieve_code_descend(denv);
 
307
 
 
308
        /* Handle any optional arguments */
 
309
        if ( !sieve_addrmatch_default_dump_optionals(denv, address) )
 
310
                return FALSE;
 
311
 
 
312
        return
 
313
                sieve_opr_stringlist_dump(denv, address, "envelope part") &&
 
314
                sieve_opr_stringlist_dump(denv, address, "key list");
 
315
}
 
316
 
 
317
/*
 
318
 * Interpretation
 
319
 */
 
320
 
 
321
static const struct sieve_address *const *_from_part_get_addresses
 
322
(const struct sieve_runtime_env *renv)
 
323
{
 
324
        ARRAY_DEFINE(envelope_values, const struct sieve_address *);
 
325
        const struct sieve_address *address =
 
326
                sieve_message_get_sender_address(renv->msgctx);
 
327
        
 
328
        if ( address != NULL ) {
 
329
                t_array_init(&envelope_values, 2);
 
330
 
 
331
        array_append(&envelope_values, &address, 1);
 
332
 
 
333
            (void)array_append_space(&envelope_values);
 
334
        return array_idx(&envelope_values, 0);
 
335
        } 
 
336
 
 
337
        return NULL;
 
338
}
 
339
 
 
340
static const char *const *_from_part_get_values
 
341
(const struct sieve_runtime_env *renv)
 
342
{
 
343
        ARRAY_DEFINE(envelope_values, const char *);
 
344
 
 
345
        t_array_init(&envelope_values, 2);
 
346
 
 
347
        if ( renv->msgdata->return_path != NULL ) {
 
348
        array_append(&envelope_values, &renv->msgdata->return_path, 1);
 
349
        }
 
350
 
 
351
        (void)array_append_space(&envelope_values);
 
352
 
 
353
        return array_idx(&envelope_values, 0);
 
354
}
 
355
 
 
356
static const struct sieve_address *const *_to_part_get_addresses
 
357
(const struct sieve_runtime_env *renv)
 
358
{
 
359
        ARRAY_DEFINE(envelope_values, const struct sieve_address *);
 
360
        const struct sieve_address *address = 
 
361
                sieve_message_get_recipient_address(renv->msgctx);      
 
362
 
 
363
        if ( address != NULL && address->local_part != NULL ) {
 
364
                t_array_init(&envelope_values, 2);
 
365
 
 
366
        array_append(&envelope_values, &address, 1);
 
367
 
 
368
            (void)array_append_space(&envelope_values);
 
369
        return array_idx(&envelope_values, 0);
 
370
        }
 
371
 
 
372
        return NULL;
 
373
}
 
374
 
 
375
static const char *const *_to_part_get_values
 
376
(const struct sieve_runtime_env *renv)
 
377
{
 
378
        ARRAY_DEFINE(envelope_values, const char *);
 
379
 
 
380
        t_array_init(&envelope_values, 2);
 
381
 
 
382
        if ( renv->msgdata->to_address != NULL ) {
 
383
        array_append(&envelope_values, &renv->msgdata->to_address, 1);
 
384
        }
 
385
 
 
386
        (void)array_append_space(&envelope_values);
 
387
 
 
388
        return array_idx(&envelope_values, 0);
 
389
}
 
390
 
 
391
 
 
392
static const char *const *_auth_part_get_values
 
393
(const struct sieve_runtime_env *renv)
 
394
{
 
395
        ARRAY_DEFINE(envelope_values, const char *);
 
396
 
 
397
        t_array_init(&envelope_values, 2);
 
398
 
 
399
        if ( renv->msgdata->auth_user != NULL )
 
400
        array_append(&envelope_values, &renv->msgdata->auth_user, 1);
 
401
 
 
402
        (void)array_append_space(&envelope_values);
 
403
 
 
404
        return array_idx(&envelope_values, 0);
 
405
}
 
406
 
 
407
static int ext_envelope_operation_execute
 
408
(const struct sieve_operation *op ATTR_UNUSED,
 
409
        const struct sieve_runtime_env *renv, sieve_size_t *address)
 
410
{
 
411
        bool result = TRUE;
 
412
        const struct sieve_comparator *cmp = &i_ascii_casemap_comparator;
 
413
        const struct sieve_match_type *mtch = &is_match_type;
 
414
        const struct sieve_address_part *addrp = &all_address_part;
 
415
        struct sieve_match_context *mctx;
 
416
        struct sieve_coded_stringlist *envp_list;
 
417
        struct sieve_coded_stringlist *key_list;
 
418
        string_t *envp_item;
 
419
        bool matched;
 
420
        int ret;
 
421
 
 
422
        /*
 
423
         * Read operands
 
424
         */
 
425
        
 
426
        sieve_runtime_trace(renv, "ENVELOPE test");
 
427
 
 
428
        if ( (ret=sieve_addrmatch_default_get_optionals
 
429
                (renv, address, &addrp, &mtch, &cmp)) <= 0 )
 
430
                return ret; 
 
431
 
 
432
        /* Read envelope-part */
 
433
        if ( (envp_list=sieve_opr_stringlist_read(renv, address)) == NULL ) {
 
434
                sieve_runtime_trace_error(renv, "invalid envelope-part operand");
 
435
                return SIEVE_EXEC_BIN_CORRUPT;
 
436
        }
 
437
 
 
438
        /* Read key-list */
 
439
        if ( (key_list=sieve_opr_stringlist_read(renv, address)) == NULL ) {
 
440
                sieve_runtime_trace_error(renv, "invalid key-list operand");
 
441
                return SIEVE_EXEC_BIN_CORRUPT;
 
442
        }
 
443
        
 
444
        /* Initialize match */
 
445
        mctx = sieve_match_begin(renv->interp, mtch, cmp, NULL, key_list);
 
446
        
 
447
        /* Iterate through all requested headers to match */
 
448
        envp_item = NULL;
 
449
        matched = FALSE;
 
450
        while ( result && !matched && 
 
451
                (result=sieve_coded_stringlist_next_item(envp_list, &envp_item)) 
 
452
                && envp_item != NULL ) {
 
453
                const struct sieve_envelope_part *epart;
 
454
                        
 
455
                if ( (epart=_envelope_part_find(str_c(envp_item))) != NULL ) {
 
456
                        const struct sieve_address * const *addresses = NULL;
 
457
                        int i;
 
458
 
 
459
                        if ( epart->get_addresses != NULL ) {
 
460
                                /* Field contains addresses */
 
461
                                addresses = epart->get_addresses(renv);
 
462
 
 
463
                                if ( addresses != NULL ) {
 
464
                                        for ( i = 0; !matched && addresses[i] != NULL; i++ ) {
 
465
                                                if ( addresses[i]->local_part == NULL ) {
 
466
                                                        /* Null path <> */
 
467
                                                        ret = sieve_match_value(mctx, "", 0);
 
468
                                                } else {
 
469
                                                        const char *part = addrp->extract_from(addresses[i]);
 
470
 
 
471
                                                        if ( part != NULL ) 
 
472
                                                                ret = sieve_match_value(mctx, part, strlen(part));
 
473
                                                        else
 
474
                                                                ret = 0;
 
475
                                                }
 
476
 
 
477
                                                if ( ret < 0 ) {
 
478
                                                        result = FALSE;
 
479
                                                        break;
 
480
                                                }
 
481
 
 
482
                                matched = ret > 0;
 
483
                                        }
 
484
                                }
 
485
                        } 
 
486
 
 
487
                        if ( epart->get_values != NULL && addresses == NULL && 
 
488
                                addrp == &all_address_part ) {
 
489
                                /* Field contains something else */
 
490
                                const char *const *values = epart->get_values(renv);
 
491
 
 
492
                                if ( values == NULL ) continue;
 
493
        
 
494
                                for ( i = 0; !matched && values[i] != NULL; i++ ) {                             
 
495
 
 
496
                                        if ( (ret=sieve_match_value
 
497
                                                (mctx, values[i], strlen(values[i]))) < 0 ) {
 
498
                            result = FALSE;
 
499
                        break;
 
500
                        }
 
501
                        
 
502
                                        matched = ret > 0;                              
 
503
                                }
 
504
                        }
 
505
                }
 
506
        }
 
507
        
 
508
        /* Finish match */
 
509
        if ( (ret=sieve_match_end(&mctx)) < 0 ) 
 
510
                result = FALSE;
 
511
        else
 
512
                matched = ( ret > 0 || matched );
 
513
 
 
514
        if ( result ) {
 
515
                /* Set test result for subsequent conditional jump */
 
516
                sieve_interpreter_set_test_result(renv->interp, matched);
 
517
                return SIEVE_EXEC_OK;
 
518
        }
 
519
        
 
520
        sieve_runtime_trace_error(renv, "invalid string-list item");    
 
521
        return SIEVE_EXEC_BIN_CORRUPT;
 
522
}
 
523