~ubuntu-branches/ubuntu/wily/dovecot/wily

« back to all changes in this revision

Viewing changes to dovecot-sieve/src/libsieve/bc_eval.c

  • Committer: Bazaar Package Importer
  • Author(s): CHuck Short, Chuck Short
  • Date: 2009-11-06 00:47:29 UTC
  • mfrom: (4.1.9 squeeze)
  • Revision ID: james.westby@ubuntu.com-20091106004729-i39n7v9e7d4h51f6
Tags: 1:1.2.6-1ubuntu1
* 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 restrictions
    - 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 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
   + debian/patches/dovecot-postfix.conf.diff:
     + 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.
   + debian/rules:
     - Create emtpy stamp.h.in files in dovecot-sieve/ and dovecot-managesieve/
       if they're not there since empty files are not included in the diff.gz 
       file.
   + Add SMTP-AUTH support for Outlook (login auth mechanism)
   + Dropped:
     - debian/patches/security-CVE-2009-3235: Applied upstream.
     - debian/patches/fix-pop3-assertion.dpatch: Applied upstream.
     - dovecot-sieve and dovecot-managesieve: Use the debian patches instead.

  [Chuck Short]
  - Updated dovecot-sieve to 0.1.13.
  - Updated dovecot-managesieve to 0.11.9.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* bc_eval.c - evaluate the bytecode
2
 
 * $Id$
3
 
 */
4
 
/***********************************************************
5
 
        Copyright 2001 by Carnegie Mellon University
6
 
 
7
 
                      All Rights Reserved
8
 
 
9
 
Permission to use, copy, modify, and distribute this software and its
10
 
documentation for any purpose and without fee is hereby granted,
11
 
provided that the above copyright notice appear in all copies and that
12
 
both that copyright notice and this permission notice appear in
13
 
supporting documentation, and that the name of Carnegie Mellon
14
 
University not be used in advertising or publicity pertaining to
15
 
distribution of the software without specific, written prior
16
 
permission.
17
 
 
18
 
CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO
19
 
THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
20
 
FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE FOR
21
 
ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
22
 
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
23
 
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
24
 
OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
25
 
******************************************************************/
26
 
 
27
 
#ifdef HAVE_CONFIG_H
28
 
#include <config.h>
29
 
#endif
30
 
 
31
 
#include "sieve_interface.h"
32
 
#include "interp.h"
33
 
#include "message.h"
34
 
#include "script.h"
35
 
 
36
 
#include "bytecode.h"
37
 
 
38
 
#include "xmalloc.h"
39
 
 
40
 
#include <string.h>
41
 
#include <ctype.h>
42
 
 
43
 
/**************************************************************************/
44
 
/**************************************************************************/
45
 
/**************************************************************************/
46
 
/**************************EXECUTING BYTECODE******************************/
47
 
/**************************************************************************/
48
 
/**************************************************************************/
49
 
/**************************************************************************/
50
 
/**************************************************************************/
51
 
 
52
 
/* Given a bytecode_input_t at the beginning of a string (the len block),
53
 
 * return the string, the length, and the bytecode index of the NEXT
54
 
 * item */
55
 
int unwrap_string(bytecode_input_t *bc, int pos, const char **str, int *len) 
56
 
{
57
 
    int local_len = ntohl(bc[pos].value);
58
 
 
59
 
    pos++;
60
 
    
61
 
    if(local_len == -1) {
62
 
        /* -1 length indicates NULL */
63
 
        *str = NULL;
64
 
    } else {
65
 
        /* This cast is ugly, but necessary */
66
 
        *str = (const char *)&bc[pos].str;
67
 
        
68
 
        /* Compute the next index */
69
 
        pos += ((ROUNDUP(local_len+1))/sizeof(bytecode_input_t));
70
 
    }
71
 
    
72
 
    if(len) *len = local_len;
73
 
    
74
 
    return pos;
75
 
}
76
 
 
77
 
 
78
 
/* this is used by notify to pass the options list to do_notify
79
 
 * do_notify needs null-terminated (char *)[],
80
 
 *  we have a stringlist, the beginning of which is pointed at by pos */
81
 
static const char ** bc_makeArray(bytecode_input_t *bc, int *pos)
82
 
{
83
 
    int i;
84
 
    const char** array;
85
 
    int len = ntohl(bc[*pos].value);
86
 
 
87
 
    (*pos)+=2; /* Skip # Values and Total Byte Length */
88
 
  
89
 
    array=(const char **)xmalloc((len+1) * sizeof(char *));
90
 
 
91
 
    for (i=0; i<len; i++) {
92
 
        *pos = unwrap_string(bc, *pos, &(array[i]), NULL);
93
 
    }
94
 
 
95
 
    array[i] = NULL;
96
 
  
97
 
    return array;
98
 
}
99
 
 
100
 
/* Compile a regular expression for use during parsing */
101
 
static regex_t * bc_compile_regex(const char *s, int ctag,
102
 
                                  char *errmsg, size_t errsiz)
103
 
{
104
 
    int ret;
105
 
    regex_t *reg = (regex_t *) xmalloc(sizeof(regex_t));
106
 
    
107
 
    if ( (ret=regcomp(reg, s, ctag)) != 0)
108
 
    {
109
 
        (void) regerror(ret, reg, errmsg, errsiz);
110
 
        free(reg);
111
 
        return NULL;
112
 
    }
113
 
    return reg;
114
 
}
115
 
 
116
 
/* Determine if addr is a system address */
117
 
static int sysaddr(const char *addr)
118
 
{
119
 
    if (!strncasecmp(addr, "MAILER-DAEMON", 13))
120
 
        return 1;
121
 
 
122
 
    if (!strncasecmp(addr, "LISTSERV", 8))
123
 
        return 1;
124
 
 
125
 
    if (!strncasecmp(addr, "majordomo", 9))
126
 
        return 1;
127
 
 
128
 
    if (strstr(addr, "-request@"))
129
 
        return 1;
130
 
 
131
 
    if (!strncmp(addr, "owner-", 6))
132
 
        return 1;
133
 
 
134
 
    return 0;
135
 
}
136
 
 
137
 
/* look for myaddr and myaddrs in the body of a header - return the match */
138
 
static char* look_for_me(char *myaddr, int numaddresses,
139
 
                               bytecode_input_t *bc, int i, const char **body)
140
 
{
141
 
    char *found = NULL;
142
 
    int l;
143
 
    int curra,x ;
144
 
 
145
 
    /* loop through each TO header */
146
 
    for (l = 0; body[l] != NULL && !found; l++) {
147
 
        void *data = NULL, *marker = NULL;
148
 
        char *addr;
149
 
        
150
 
        parse_address(body[l], &data, &marker);
151
 
 
152
 
        /* loop through each address in the header */
153
 
        while (!found &&
154
 
               ((addr = get_address(ADDRESS_ALL,&data, &marker, 1))!= NULL)) {
155
 
 
156
 
            if (!strcasecmp(addr, myaddr)) {
157
 
                found = xstrdup(myaddr);
158
 
                break;
159
 
            }
160
 
 
161
 
            curra=i;
162
 
 
163
 
            for(x=0; x<numaddresses; x++)
164
 
            {
165
 
                void *altdata = NULL, *altmarker = NULL;
166
 
                char *altaddr;
167
 
                const char *str;
168
 
 
169
 
                curra = unwrap_string(bc, curra, &str, NULL);
170
 
                
171
 
                /* is this address one of my addresses? */
172
 
                parse_address(str, &altdata, &altmarker);
173
 
 
174
 
                altaddr = get_address(ADDRESS_ALL, &altdata, &altmarker, 1);
175
 
 
176
 
                if (!strcasecmp(addr,altaddr)) {
177
 
                    found=xstrdup(str);
178
 
                    break;
179
 
                }
180
 
 
181
 
                free_address(&altdata, &altmarker);
182
 
            }
183
 
 
184
 
        }
185
 
        free_address(&data, &marker);
186
 
    }
187
 
 
188
 
    return found;
189
 
}
190
 
 
191
 
static char *list_fields[] = {
192
 
    "list-id",
193
 
    "list-help",
194
 
    "list-subscribe",
195
 
    "list-unsubscribe",
196
 
    "list-post",
197
 
    "list-owner",
198
 
    "list-archive",
199
 
    NULL
200
 
};
201
 
 
202
 
/* Determine if we should respond to a vacation message */
203
 
static int shouldRespond(void * m, sieve_interp_t *interp,
204
 
                         int numaddresses, bytecode_input_t* bc,
205
 
                         int i, char **from, char **to)
206
 
{
207
 
    const char **body;
208
 
    char buf[128];
209
 
    char *myaddr = NULL;
210
 
    int l = SIEVE_OK, j;
211
 
    void *data = NULL, *marker = NULL;
212
 
    char *tmp;
213
 
    int curra, x;
214
 
    char *found=NULL;
215
 
    char *reply_to=NULL;
216
 
  
217
 
    /* Implementations SHOULD NOT respond to any message that contains a
218
 
       "List-Id" [RFC2919], "List-Help", "List-Subscribe", "List-
219
 
       Unsubscribe", "List-Post", "List-Owner" or "List-Archive" [RFC2369]
220
 
       header field. */
221
 
    for (j = 0; list_fields[j]; j++) {
222
 
        strcpy(buf, list_fields[j]);
223
 
        if (interp->getheader(m, buf, &body) == SIEVE_OK) {
224
 
            l = SIEVE_DONE;
225
 
            break;
226
 
        }
227
 
    }
228
 
 
229
 
    /* Implementations SHOULD NOT respond to any message that has an
230
 
       "Auto-submitted" header field with a value other than "no".
231
 
       This header field is described in [RFC3834]. */
232
 
    strcpy(buf, "auto-submitted");
233
 
    if (interp->getheader(m, buf, &body) == SIEVE_OK) {
234
 
        /* we don't deal with comments, etc. here */
235
 
        /* skip leading white-space */
236
 
        while (*body[0] && isspace((int) *body[0])) body[0]++;
237
 
        if (strcasecmp(body[0], "no")) l = SIEVE_DONE;
238
 
    }
239
 
 
240
 
    /* is there a Precedence keyword of "junk | bulk | list"? */
241
 
    /* XXX  non-standard header, but worth checking */
242
 
    strcpy(buf, "precedence");
243
 
    if (interp->getheader(m, buf, &body) == SIEVE_OK) {
244
 
        /* we don't deal with comments, etc. here */
245
 
        /* skip leading white-space */
246
 
        while (*body[0] && isspace((int) *body[0])) body[0]++;
247
 
        if (!strcasecmp(body[0], "junk") ||
248
 
            !strcasecmp(body[0], "bulk") ||
249
 
            !strcasecmp(body[0], "list"))
250
 
            l = SIEVE_DONE;
251
 
    }
252
 
 
253
 
    /* Note: the domain-part of all addresses are canonicalized */
254
 
    /* grab my address from the envelope */
255
 
    if (l == SIEVE_OK) {
256
 
        strcpy(buf, "to");
257
 
        l = interp->getenvelope(m, buf, &body);
258
 
        
259
 
        if (body[0]) {  
260
 
            parse_address(body[0], &data, &marker);
261
 
            tmp = get_address(ADDRESS_ALL, &data, &marker, 1);
262
 
            myaddr = (tmp != NULL) ? xstrdup(tmp) : NULL;
263
 
            free_address(&data, &marker);
264
 
        }  
265
 
    }  
266
 
  
267
 
    if (l == SIEVE_OK) {
268
 
        strcpy(buf, "from");
269
 
        l = interp->getenvelope(m, buf, &body);
270
 
    }
271
 
    if (l == SIEVE_OK && body[0]) {
272
 
        /* we have to parse this address & decide whether we
273
 
           want to respond to it */
274
 
        parse_address(body[0], &data, &marker);
275
 
        tmp = get_address(ADDRESS_ALL, &data, &marker, 1);
276
 
        reply_to = (tmp != NULL) ? xstrdup(tmp) : NULL;
277
 
        free_address(&data, &marker);
278
 
 
279
 
        /* first, is there a reply-to address? */
280
 
        if (reply_to == NULL) {
281
 
            l = SIEVE_DONE;
282
 
        }
283
 
    
284
 
        /* first, is it from me? */
285
 
        if (l == SIEVE_OK && !strcmp(myaddr, reply_to)) {
286
 
            l = SIEVE_DONE;
287
 
        }
288
 
   
289
 
        /* ok, is it any of the other addresses i've
290
 
           specified? */
291
 
        if (l == SIEVE_OK)
292
 
        {
293
 
            curra=i;
294
 
            for(x=0; x<numaddresses; x++) {
295
 
                const char *address;
296
 
 
297
 
                curra = unwrap_string(bc, curra, &address, NULL);
298
 
                
299
 
                if (!strcmp(address, reply_to))
300
 
                    l=SIEVE_DONE;
301
 
            }
302
 
        }
303
 
   
304
 
        /* ok, is it a system address? */
305
 
        if (l == SIEVE_OK && sysaddr(reply_to)) {
306
 
            l = SIEVE_DONE;
307
 
        }
308
 
    }
309
 
    if (l == SIEVE_OK) {
310
 
        /* ok, we're willing to respond to the sender.
311
 
           but is this message to me?  that is, is my address
312
 
           in the [Resent]-To, [Resent]-Cc or [Resent]-Bcc fields? */
313
 
        if (strcpy(buf, "to"), 
314
 
            interp->getheader(m, buf, &body) == SIEVE_OK)
315
 
            found = look_for_me(myaddr, numaddresses ,bc, i, body);
316
 
        if (!found && (strcpy(buf, "cc"),
317
 
                       (interp->getheader(m, buf, &body) == SIEVE_OK)))
318
 
            found = look_for_me(myaddr, numaddresses, bc, i, body);
319
 
        if (!found && (strcpy(buf, "bcc"),
320
 
                       (interp->getheader(m, buf, &body) == SIEVE_OK)))
321
 
            found = look_for_me(myaddr, numaddresses, bc, i, body);
322
 
        if (!found && (strcpy(buf, "resent-to"),
323
 
                       (interp->getheader(m, buf, &body) == SIEVE_OK)))
324
 
            found = look_for_me(myaddr, numaddresses ,bc, i, body);
325
 
        if (!found && (strcpy(buf, "resent-cc"),
326
 
                       (interp->getheader(m, buf, &body) == SIEVE_OK)))
327
 
            found = look_for_me(myaddr, numaddresses, bc, i, body);
328
 
        if (!found && (strcpy(buf, "resent-bcc"),
329
 
                       (interp->getheader(m, buf, &body) == SIEVE_OK)))
330
 
            found = look_for_me(myaddr, numaddresses, bc, i, body);
331
 
        if (!found)
332
 
            l = SIEVE_DONE;
333
 
    }
334
 
    /* ok, ok, if we got here maybe we should reply */
335
 
    if (myaddr) free(myaddr);
336
 
    *from=found;
337
 
    *to=reply_to;
338
 
    return l;
339
 
}
340
 
 
341
 
/* Evaluate a bytecode test */
342
 
static int eval_bc_test(sieve_interp_t *interp,
343
 
                        struct hash_table *body_cache, void* m,
344
 
                        bytecode_input_t * bc, int * ip)
345
 
{
346
 
    int res=0; 
347
 
    int i=*ip;
348
 
    int x,y,z;/* loop variable */
349
 
    int list_len; /* for allof/anyof/exists */
350
 
    int list_end; /* for allof/anyof/exists */
351
 
    int address=0;/*to differentiate between address and envelope*/
352
 
    comparator_t * comp=NULL;
353
 
    void * comprock=NULL;
354
 
    int op= ntohl(bc[i].op);
355
 
    
356
 
    switch(op)
357
 
    {
358
 
    case BC_FALSE:
359
 
        res=0; i++; break;
360
 
 
361
 
    case BC_TRUE:
362
 
        res=1; i++; break;
363
 
 
364
 
    case BC_NOT:/*2*/
365
 
        i+=1;
366
 
        res = eval_bc_test(interp, body_cache, m, bc, &i);
367
 
        if(res >= 0) res = !res; /* Only invert in non-error case */
368
 
        break;
369
 
 
370
 
    case BC_EXISTS:/*3*/
371
 
    {
372
 
        int headersi=i+1;
373
 
        const char** val;
374
 
        int currh;
375
 
 
376
 
        res=1;
377
 
 
378
 
        list_len=ntohl(bc[headersi].len);
379
 
        list_end=ntohl(bc[headersi+1].value)/4;
380
 
 
381
 
        currh=headersi+2;
382
 
 
383
 
        for(x=0; x<list_len && res; x++)
384
 
        {
385
 
            const char *str;
386
 
 
387
 
            currh = unwrap_string(bc, currh, &str, NULL);
388
 
            
389
 
            if(interp->getheader(m,str, &val) != SIEVE_OK)
390
 
                res = 0;
391
 
        }
392
 
 
393
 
        i=list_end; /* adjust for short-circuit */
394
 
        break;
395
 
    }
396
 
    case BC_SIZE:/*4*/
397
 
    {
398
 
        int s;
399
 
        int sizevar=ntohl(bc[i+1].value);
400
 
        int x=ntohl(bc[i+2].value);
401
 
        
402
 
        if (interp->getsize(m, &s) != SIEVE_OK)
403
 
            break;
404
 
        
405
 
        if (sizevar ==B_OVER) {
406
 
            /* over */
407
 
            res= s > x;
408
 
        } else {
409
 
            /* under */
410
 
            res= s < x;
411
 
        }
412
 
        i+=3;
413
 
        break;
414
 
    }
415
 
    case BC_ANYOF:/*5*/
416
 
        res = 0;
417
 
        list_len=ntohl(bc[i+1].len);
418
 
        list_end=ntohl(bc[i+2].len)/4;
419
 
        i+=3;
420
 
 
421
 
        /* need to process all of them, to ensure our instruction pointer stays
422
 
         * in the right place */
423
 
        for (x=0; x<list_len && !res; x++) { 
424
 
            int tmp;
425
 
            tmp = eval_bc_test(interp,body_cache,m,bc,&i);
426
 
            if(tmp < 0) {
427
 
                res = tmp;
428
 
                break;
429
 
            }
430
 
            res = res || tmp;
431
 
        }
432
 
 
433
 
        i = list_end; /* handle short-circuting */
434
 
 
435
 
        break; 
436
 
    case BC_ALLOF:/*6*/ 
437
 
        res = 1;     
438
 
        list_len=ntohl(bc[i+1].len);
439
 
        list_end=ntohl(bc[i+2].len)/4;
440
 
        i+=3;
441
 
 
442
 
        /* return 1 unless you find one that isn't true, then return 0 */
443
 
        for (x=0; x<list_len && res; x++) {
444
 
            int tmp;
445
 
            tmp = eval_bc_test(interp,body_cache,m,bc,&i);
446
 
            if(tmp < 0) {
447
 
                res = tmp;
448
 
                break;
449
 
            }
450
 
            res = res && tmp; 
451
 
        }
452
 
 
453
 
        i = list_end; /* handle short-circuiting */
454
 
        
455
 
        break;
456
 
    case BC_ADDRESS:/*7*/
457
 
        address=1;
458
 
        /* fall through */
459
 
    case BC_ENVELOPE:/*8*/
460
 
    {
461
 
        const char ** val;
462
 
        void * data=NULL;
463
 
        void * marker=NULL;
464
 
        char * addr;
465
 
        int addrpart=ADDRESS_ALL;/* XXX correct default behavior?*/
466
 
 
467
 
        int headersi=i+5;/* the i value for the begining of the headers */
468
 
        int datai=(ntohl(bc[headersi+1].value)/4);
469
 
 
470
 
        int numheaders=ntohl(bc[headersi].len);
471
 
        int numdata=ntohl(bc[datai].len);
472
 
 
473
 
        int currh, currd; /* current header, current data */
474
 
 
475
 
        int match=ntohl(bc[i+1].value);
476
 
        int relation=ntohl(bc[i+2].value);
477
 
        int comparator=ntohl(bc[i+3].value);
478
 
        int apart=ntohl(bc[i+4].value);
479
 
        int count=0;
480
 
        char scount[3];
481
 
        int isReg = (match==B_REGEX);
482
 
        int ctag = 0;
483
 
        regex_t *reg;
484
 
        char errbuf[100]; /* Basically unused, as regexps are tested at compile */
485
 
 
486
 
        /* set up variables needed for compiling regex */
487
 
        if (isReg)
488
 
        {
489
 
            if (comparator== B_ASCIICASEMAP)
490
 
            {
491
 
                ctag = REG_EXTENDED | REG_NOSUB | REG_ICASE;
492
 
            }
493
 
            else
494
 
            {
495
 
                ctag = REG_EXTENDED | REG_NOSUB;
496
 
            }
497
 
        }
498
 
 
499
 
        /*find the correct comparator fcn*/
500
 
        comp = lookup_comp(comparator, match, relation, &comprock);
501
 
 
502
 
        if(!comp) {
503
 
            res = SIEVE_RUN_ERROR;
504
 
            break;
505
 
        }
506
 
        
507
 
        /*find the part of the address that we want*/
508
 
        switch(apart)
509
 
        {
510
 
        case B_ALL:
511
 
            addrpart = ADDRESS_ALL; break;
512
 
        case B_LOCALPART:
513
 
            addrpart = ADDRESS_LOCALPART; break;
514
 
        case B_DOMAIN:
515
 
            addrpart = ADDRESS_DOMAIN; break;
516
 
        case B_USER:
517
 
            addrpart = ADDRESS_USER; break;
518
 
        case B_DETAIL:
519
 
            addrpart = ADDRESS_DETAIL; break;
520
 
        default:
521
 
            /* this shouldn't happen with correcct bytecode */
522
 
            res = SIEVE_RUN_ERROR;
523
 
        }
524
 
 
525
 
        if(res == SIEVE_RUN_ERROR) break;
526
 
 
527
 
        /*loop through all the headers*/
528
 
        currh=headersi+2;
529
 
#if VERBOSE
530
 
        printf("about to process %d headers\n", numheaders);
531
 
#endif
532
 
        for (x=0; x<numheaders && !res; x++)
533
 
        {
534
 
            const char *this_header;
535
 
 
536
 
            currh = unwrap_string(bc, currh, &this_header, NULL);
537
 
            
538
 
            /* Try the next string if we don't have this one */
539
 
            if(address) {
540
 
                /* Header */
541
 
                if(interp->getheader(m, this_header, &val) != SIEVE_OK)
542
 
                    continue;
543
 
#if VERBOSE
544
 
                printf(" [%d] header %s is %s\n", x, this_header, val[0]);
545
 
#endif
546
 
            } else {
547
 
                /* Envelope */
548
 
                if(interp->getenvelope(m, this_header, &val) != SIEVE_OK)
549
 
                    continue;
550
 
            }
551
 
        
552
 
            /*header exists, now to test it*/
553
 
            /*search through all the headers that match*/
554
 
            
555
 
            for (y=0; val[y]!=NULL && !res; y++) {
556
 
                
557
 
#if VERBOSE
558
 
                printf("about to parse %s\n", val[y]);
559
 
#endif
560
 
                    
561
 
                if (parse_address(val[y], &data, &marker)!=SIEVE_OK) 
562
 
                    return 0;
563
 
                    
564
 
                while (!res &&
565
 
                       (addr = get_address(addrpart, &data, &marker, 0))) {
566
 
#if VERBOSE
567
 
                    printf("working addr %s\n", (addr ? addr : "[nil]"));
568
 
#endif
569
 
                        
570
 
                    if (match == B_COUNT) {
571
 
                        count++;
572
 
                    } else {
573
 
                        /*search through all the data*/ 
574
 
                        currd=datai+2;
575
 
                        for (z=0; z<numdata && !res; z++)
576
 
                        {
577
 
                            const char *data_val;
578
 
                            
579
 
                            currd = unwrap_string(bc, currd, &data_val, NULL);
580
 
 
581
 
                            if (isReg) {
582
 
                                reg = bc_compile_regex(data_val, ctag,
583
 
                                                       errbuf, sizeof(errbuf));
584
 
                                if (!reg) {
585
 
                                    /* Oops */
586
 
                                    res=-1;
587
 
                                    goto alldone;
588
 
                                }
589
 
 
590
 
                                res |= comp(val[y], strlen(val[y]),
591
 
                                            (const char *)reg, comprock);
592
 
                                free(reg);
593
 
                            } else {
594
 
#if VERBOSE
595
 
                                printf("%s compared to %s(from script)\n",
596
 
                                       addr, data_val);
597
 
#endif 
598
 
                                res |= comp(addr, strlen(addr),
599
 
                                            data_val, comprock);
600
 
                            }
601
 
                        } /* For each data */
602
 
                    }
603
 
                } /* For each address */
604
 
 
605
 
                free_address(&data, &marker);
606
 
            }/* For each message header */
607
 
            
608
 
#if VERBOSE
609
 
            printf("end of loop, res is %d, x is %d (%d)\n", res, x, numheaders);
610
 
#endif      
611
 
        } /* For each script header */
612
 
     
613
 
        if  (match == B_COUNT)
614
 
        {
615
 
            sprintf(scount, "%u", count);
616
 
            /* search through all the data */ 
617
 
            currd=datai+2;
618
 
            for (z=0; z<numdata && !res; z++)
619
 
            {
620
 
                const char *data_val;
621
 
                
622
 
                currd = unwrap_string(bc, currd, &data_val, NULL);
623
 
 
624
 
                res |= comp(scount, strlen(scount), data_val, comprock);
625
 
            }
626
 
        }
627
 
 
628
 
        /* Update IP */
629
 
        i=(ntohl(bc[datai+1].value)/4);
630
 
        
631
 
        break;
632
 
    }
633
 
    case BC_HEADER:/*9*/
634
 
    {
635
 
        const char** val;
636
 
 
637
 
        int headersi=i+4;/*the i value for the begining of hte headers*/
638
 
        int datai=(ntohl(bc[headersi+1].value)/4);
639
 
 
640
 
        int numheaders=ntohl(bc[headersi].len);
641
 
        int numdata=ntohl(bc[datai].len);
642
 
 
643
 
        int currh, currd; /*current header, current data*/
644
 
 
645
 
        int match=ntohl(bc[i+1].value);
646
 
        int relation=ntohl(bc[i+2].value);
647
 
        int comparator=ntohl(bc[i+3].value);
648
 
        int count=0;    
649
 
        char scount[3];
650
 
        int isReg = (match==B_REGEX);
651
 
        int ctag = 0;
652
 
        regex_t *reg;
653
 
        char errbuf[100]; /* Basically unused, regexps tested at compile */ 
654
 
 
655
 
        /* set up variables needed for compiling regex */
656
 
        if (isReg)
657
 
        {
658
 
            if (comparator== B_ASCIICASEMAP)
659
 
            {
660
 
                ctag= REG_EXTENDED | REG_NOSUB | REG_ICASE;
661
 
            }
662
 
            else
663
 
            {
664
 
                ctag= REG_EXTENDED | REG_NOSUB;
665
 
            }
666
 
     
667
 
        }
668
 
        
669
 
        /*find the correct comparator fcn*/
670
 
        comp=lookup_comp(comparator, match, relation, &comprock);
671
 
 
672
 
        if(!comp) {
673
 
            res = SIEVE_RUN_ERROR;
674
 
            break;
675
 
        }
676
 
 
677
 
        /*search through all the flags for the header*/
678
 
        currh=headersi+2;
679
 
        for(x=0; x<numheaders && !res; x++)
680
 
        {
681
 
            const char *this_header;
682
 
            
683
 
            currh = unwrap_string(bc, currh, &this_header, NULL);
684
 
           
685
 
            if(interp->getheader(m, this_header, &val) != SIEVE_OK) {
686
 
                continue; /*this header does not exist, search the next*/ 
687
 
            }
688
 
#if VERBOSE
689
 
            printf ("val %s %s %s\n", val[0], val[1], val[2]);
690
 
#endif
691
 
            
692
 
            /* search through all the headers that match */
693
 
            
694
 
            for (y=0; val[y]!=NULL && !res; y++)
695
 
            {
696
 
                if  (match == B_COUNT) {
697
 
                    count++;
698
 
                } else {
699
 
                    /*search through all the data*/ 
700
 
                    currd=datai+2;
701
 
                    for (z=0; z<numdata && !res; z++)
702
 
                    {
703
 
                        const char *data_val;
704
 
                        
705
 
                        currd = unwrap_string(bc, currd, &data_val, NULL);
706
 
                        
707
 
                        if (isReg) {
708
 
                            reg= bc_compile_regex(data_val, ctag, errbuf,
709
 
                                                  sizeof(errbuf));
710
 
                            if (!reg)
711
 
                            {
712
 
                                /* Oops */
713
 
                                res=-1;
714
 
                                goto alldone;
715
 
                            }
716
 
                            
717
 
                            res |= comp(val[y], strlen(val[y]),
718
 
                                        (const char *)reg, comprock);
719
 
                            free(reg);
720
 
                        } else {
721
 
                            res |= comp(val[y], strlen(val[y]),
722
 
                                        data_val, comprock);
723
 
                        }
724
 
                    }
725
 
                }
726
 
            }
727
 
        }
728
 
        
729
 
        if  (match == B_COUNT )
730
 
        {
731
 
            sprintf(scount, "%u", count);
732
 
            /*search through all the data*/ 
733
 
            currd=datai+2;
734
 
            for (z=0; z<numdata && !res; z++)
735
 
            {   
736
 
                const char *data_val;
737
 
                        
738
 
                currd = unwrap_string(bc, currd, &data_val, NULL);
739
 
#if VERBOSE
740
 
                printf("%d, %s \n", count, data_val);
741
 
#endif
742
 
                res |= comp(scount, strlen(scount), data_val, comprock);
743
 
            }
744
 
              
745
 
        }
746
 
 
747
 
        /* Update IP */
748
 
        i=(ntohl(bc[datai+1].value)/4);
749
 
        
750
 
        break;
751
 
    }
752
 
    case BC_BODY:/*10*/
753
 
    {
754
 
        sieve_bodypart_t *val;
755
 
        const char **content_types = NULL;
756
 
 
757
 
        int typesi=i+6;/* the i value for the begining of the content-types */
758
 
        int datai=(ntohl(bc[typesi+1].value)/4);
759
 
 
760
 
        int numdata=ntohl(bc[datai].len);
761
 
 
762
 
        int currd; /* current data */
763
 
 
764
 
        int match=ntohl(bc[i+1].value);
765
 
        int relation=ntohl(bc[i+2].value);
766
 
        int comparator=ntohl(bc[i+3].value);
767
 
        int transform=ntohl(bc[i+4].value);
768
 
        /*int offset=ntohl(bc[i+5].value);*/
769
 
        int count=0;
770
 
        char scount[3];
771
 
        int isReg = (match==B_REGEX);
772
 
        int ctag = 0;
773
 
        regex_t *reg;
774
 
        char errbuf[100]; /* Basically unused, as regexps are tested at compile */
775
 
 
776
 
        /* set up variables needed for compiling regex */
777
 
        if (isReg)
778
 
        {
779
 
            if (comparator== B_ASCIICASEMAP)
780
 
            {
781
 
                ctag = REG_EXTENDED | REG_NOSUB | REG_ICASE;
782
 
            }
783
 
            else
784
 
            {
785
 
                ctag = REG_EXTENDED | REG_NOSUB;
786
 
            }
787
 
        }
788
 
 
789
 
        /*find the correct comparator fcn*/
790
 
        comp = lookup_comp(comparator, match, relation, &comprock);
791
 
 
792
 
        if(!comp) {
793
 
            res = SIEVE_RUN_ERROR;
794
 
            break;
795
 
        }
796
 
        
797
 
        /*find the part(s) of the body that we want*/
798
 
        content_types = bc_makeArray(bc, &typesi);
799
 
        if(interp->getbody(m, content_types, transform != B_RAW, &val) != SIEVE_OK) {
800
 
            res = SIEVE_RUN_ERROR;
801
 
            break;
802
 
        }
803
 
        free(content_types);
804
 
        
805
 
        /* bodypart(s) exist, now to test them */
806
 
            
807
 
        for (y=0; val[y].content!=NULL && !res; y++) {
808
 
 
809
 
            if (match == B_COUNT) {
810
 
                count++;
811
 
            } else {
812
 
                const char *content = val[y].content;
813
 
                size_t size = val[y].size;
814
 
 
815
 
                /* search through all the data */ 
816
 
                currd=datai+2;
817
 
                for (z=0; z<numdata && !res; z++)
818
 
                {
819
 
                    const char *data_val;
820
 
                            
821
 
                    currd = unwrap_string(bc, currd, &data_val, NULL);
822
 
 
823
 
                    if (isReg) {
824
 
                        reg = bc_compile_regex(data_val, ctag,
825
 
                                               errbuf, sizeof(errbuf));
826
 
                        if (!reg) {
827
 
                            /* Oops */
828
 
                            res=-1;
829
 
                            goto alldone;
830
 
                        }
831
 
 
832
 
                        res |= comp(content, size, (const char *)reg, comprock);
833
 
                        free(reg);
834
 
                    } else {
835
 
                        res |= comp(content, size, data_val, comprock);
836
 
                    }
837
 
                } /* For each data */
838
 
            }
839
 
 
840
 
        } /* For each body part */
841
 
 
842
 
        if  (match == B_COUNT)
843
 
        {
844
 
            sprintf(scount, "%u", count);
845
 
            /* search through all the data */ 
846
 
            currd=datai+2;
847
 
            for (z=0; z<numdata && !res; z++)
848
 
            {
849
 
                const char *data_val;
850
 
                
851
 
                currd = unwrap_string(bc, currd, &data_val, NULL);
852
 
 
853
 
                res |= comp(scount, strlen(scount), data_val, comprock);
854
 
            }
855
 
        }
856
 
 
857
 
        /* Update IP */
858
 
        i=(ntohl(bc[datai+1].value)/4);
859
 
        
860
 
        break;
861
 
    }
862
 
    default:
863
 
#if VERBOSE
864
 
        printf("WERT, can't evaluate if statement. %d is not a valid command",
865
 
               op);
866
 
#endif     
867
 
        return SIEVE_RUN_ERROR;
868
 
    }
869
 
    
870
 
  
871
 
 alldone:
872
 
    
873
 
    *ip=i;
874
 
    return res;
875
 
}
876
 
 
877
 
/* The entrypoint for bytecode evaluation */
878
 
int sieve_eval_bc(sieve_execute_t *exe, int is_incl, sieve_interp_t *i,
879
 
                  struct hash_table *body_cache, void *sc, void *m,
880
 
                  sieve_imapflags_t * imapflags, action_list_t *actions,
881
 
                  notify_list_t *notify_list, const char **errmsg) 
882
 
{
883
 
    const char *data;
884
 
    int res=0;
885
 
    int op;
886
 
    int version;
887
 
  
888
 
    sieve_bytecode_t *bc_cur = exe->bc_cur;
889
 
    bytecode_input_t *bc = (bytecode_input_t *) bc_cur->data;
890
 
    int ip = 0, ip_max = (bc_cur->len/sizeof(bytecode_input_t));
891
 
 
892
 
    if (bc_cur->is_executing) {
893
 
        *errmsg = "Recursive Include";
894
 
        return SIEVE_RUN_ERROR;
895
 
    }
896
 
    bc_cur->is_executing = 1;
897
 
    
898
 
    /* Check that we
899
 
     * a) have bytecode
900
 
     * b) it is atleast long enough for the magic number, the version
901
 
     *    and one opcode */
902
 
    if(!bc) return SIEVE_FAIL;
903
 
    if(bc_cur->len < (BYTECODE_MAGIC_LEN + 2*sizeof(bytecode_input_t)))
904
 
       return SIEVE_FAIL;
905
 
 
906
 
    if(memcmp(bc, BYTECODE_MAGIC, BYTECODE_MAGIC_LEN)) {
907
 
        *errmsg = "Not a bytecode file";
908
 
        return SIEVE_FAIL;
909
 
    }
910
 
 
911
 
    ip = BYTECODE_MAGIC_LEN / sizeof(bytecode_input_t);
912
 
 
913
 
    version= ntohl(bc[ip].op);
914
 
 
915
 
    /* this is because there was a time where integers were not network byte
916
 
       order.  all the scripts written then would have version 0x01 written
917
 
       in host byte order.*/
918
 
 
919
 
     if(version == (int)ntohl(1)) {
920
 
        if(errmsg) {
921
 
            *errmsg =
922
 
                "Incorrect Bytecode Version, please recompile (use sievec)";
923
 
            
924
 
        }
925
 
        return SIEVE_FAIL;
926
 
    }
927
 
    
928
 
    if((version < BYTECODE_MIN_VERSION) || (version > BYTECODE_VERSION)) {
929
 
        if(errmsg) {
930
 
            *errmsg =
931
 
                "Incorrect Bytecode Version, please recompile (use sievec)";
932
 
        }
933
 
        return SIEVE_FAIL;
934
 
    }
935
 
 
936
 
#if VERBOSE
937
 
    printf("version number %d\n",version); 
938
 
#endif
939
 
 
940
 
    for(ip++; ip<ip_max; ) { 
941
 
        int copy = 0;
942
 
 
943
 
        op=ntohl(bc[ip].op);
944
 
        switch(op) {
945
 
        case B_STOP:/*0*/
946
 
            res=1;
947
 
            break;
948
 
 
949
 
        case B_KEEP:/*1*/
950
 
            res = do_keep(actions, imapflags);
951
 
            if (res == SIEVE_RUN_ERROR)
952
 
                *errmsg = "Keep can not be used with Reject";
953
 
            ip++;
954
 
            break;
955
 
 
956
 
        case B_DISCARD:/*2*/
957
 
            res=do_discard(actions);
958
 
            ip++;
959
 
            break;
960
 
 
961
 
        case B_REJECT:/*3*/
962
 
            ip = unwrap_string(bc, ip+1, &data, NULL);
963
 
            
964
 
            res = do_reject(actions, data);
965
 
        
966
 
            if (res == SIEVE_RUN_ERROR)
967
 
                *errmsg = "Reject can not be used with any other action";  
968
 
 
969
 
            break;
970
 
 
971
 
        case B_FILEINTO:/*19*/
972
 
            copy = ntohl(bc[ip+1].value);
973
 
            ip+=1;
974
 
 
975
 
        case B_FILEINTO_ORIG:/*4*/
976
 
        {
977
 
            ip = unwrap_string(bc, ip+1, &data, NULL);
978
 
 
979
 
            res = do_fileinto(actions, data, !copy, imapflags);
980
 
 
981
 
            if (res == SIEVE_RUN_ERROR)
982
 
                *errmsg = "Fileinto can not be used with Reject";
983
 
 
984
 
            break;
985
 
        }
986
 
 
987
 
        case B_REDIRECT:/*20*/
988
 
            copy = ntohl(bc[ip+1].value);
989
 
            ip+=1;
990
 
 
991
 
        case B_REDIRECT_ORIG:/*5*/
992
 
        {
993
 
            ip = unwrap_string(bc, ip+1, &data, NULL);
994
 
 
995
 
            res = do_redirect(actions, data, !copy);
996
 
 
997
 
            if (res == SIEVE_RUN_ERROR)
998
 
                *errmsg = "Redirect can not be used with Reject";
999
 
 
1000
 
            break;
1001
 
        }
1002
 
 
1003
 
        case B_IF:/*6*/
1004
 
        {
1005
 
            int testend=ntohl(bc[ip+1].value);
1006
 
            int result;
1007
 
           
1008
 
            ip+=2;
1009
 
            result=eval_bc_test(i, body_cache, m, bc, &ip);
1010
 
            
1011
 
            if (result<0) {
1012
 
                *errmsg = "Invalid test";
1013
 
                return SIEVE_FAIL;
1014
 
            } else if (result) {
1015
 
                /*skip over jump instruction*/
1016
 
                testend+=2;
1017
 
            }
1018
 
            ip=testend;
1019
 
            
1020
 
            break;
1021
 
        }
1022
 
 
1023
 
        case B_MARK:/*8*/
1024
 
            res = do_mark(actions);
1025
 
            ip++;
1026
 
            break;
1027
 
 
1028
 
        case B_UNMARK:/*9*/
1029
 
            res = do_unmark(actions);
1030
 
            ip++;
1031
 
            break;
1032
 
 
1033
 
        case B_ADDFLAG:/*10*/ 
1034
 
        {
1035
 
            int x;
1036
 
            int list_len=ntohl(bc[ip+1].len);
1037
 
 
1038
 
            ip+=3; /* skip opcode, list_len, and list data len */
1039
 
 
1040
 
            for (x=0; x<list_len; x++) {
1041
 
                ip = unwrap_string(bc, ip, &data, NULL);
1042
 
                
1043
 
                res = do_addflag(actions, data);
1044
 
 
1045
 
                if (res == SIEVE_RUN_ERROR)
1046
 
                    *errmsg = "addflag can not be used with Reject";
1047
 
            } 
1048
 
            break;
1049
 
        }
1050
 
 
1051
 
        case B_SETFLAG:
1052
 
        {
1053
 
            int x;
1054
 
            int list_len=ntohl(bc[ip+1].len);
1055
 
 
1056
 
            ip+=3; /* skip opcode, list_len, and list data len */
1057
 
 
1058
 
            ip = unwrap_string(bc, ip, &data, NULL);
1059
 
 
1060
 
            res = do_setflag(actions, data);
1061
 
 
1062
 
            if (res == SIEVE_RUN_ERROR) {
1063
 
                *errmsg = "setflag can not be used with Reject";
1064
 
            } else {
1065
 
                for (x=1; x<list_len; x++) {
1066
 
                    ip = unwrap_string(bc, ip, &data, NULL);
1067
 
 
1068
 
                    res = do_addflag(actions, data);
1069
 
 
1070
 
                    if (res == SIEVE_RUN_ERROR)
1071
 
                        *errmsg = "setflag can not be used with Reject";
1072
 
                } 
1073
 
            }
1074
 
            
1075
 
            break;
1076
 
        }
1077
 
 
1078
 
        case B_REMOVEFLAG:
1079
 
        {
1080
 
            int x;
1081
 
            int list_len=ntohl(bc[ip+1].len);
1082
 
 
1083
 
            ip+=3; /* skip opcode, list_len, and list data len */
1084
 
 
1085
 
            for (x=0; x<list_len; x++) {
1086
 
                ip = unwrap_string(bc, ip, &data, NULL);
1087
 
 
1088
 
                res = do_removeflag(actions, data);
1089
 
 
1090
 
                if (res == SIEVE_RUN_ERROR)
1091
 
                    *errmsg = "removeflag can not be used with Reject";
1092
 
            } 
1093
 
            break;
1094
 
        }
1095
 
 
1096
 
        case B_NOTIFY:
1097
 
        {
1098
 
            const char * id;
1099
 
            const char * method;
1100
 
            const char **options = NULL;
1101
 
            const char *priority = NULL;
1102
 
            const char * message;
1103
 
            int pri;
1104
 
            
1105
 
            ip++;
1106
 
 
1107
 
            /* method */
1108
 
            ip = unwrap_string(bc, ip, &method, NULL);
1109
 
 
1110
 
            /* id */
1111
 
            ip = unwrap_string(bc, ip, &id, NULL);
1112
 
 
1113
 
            /*options*/
1114
 
            options=bc_makeArray(bc, &ip); 
1115
 
 
1116
 
            /* priority */
1117
 
            pri=ntohl(bc[ip].value);
1118
 
            ip++;
1119
 
            
1120
 
            switch (pri)
1121
 
            {
1122
 
            case B_LOW:
1123
 
                priority="low";
1124
 
            case B_NORMAL:
1125
 
                priority="normal";
1126
 
                break;
1127
 
            case B_HIGH: 
1128
 
                priority="high";
1129
 
                break; 
1130
 
            case B_ANY:
1131
 
                priority="any";
1132
 
                break;
1133
 
            default:
1134
 
                res=SIEVE_RUN_ERROR;
1135
 
            }
1136
 
 
1137
 
            /* message */
1138
 
            ip = unwrap_string(bc, ip, &message, NULL);
1139
 
          
1140
 
            res = do_notify(notify_list, id, method, options,
1141
 
                            priority, message);
1142
 
 
1143
 
            break;
1144
 
        }
1145
 
        case B_DENOTIFY:
1146
 
        {
1147
 
         /*
1148
 
          * i really have no idea what the count matchtype should do here.
1149
 
          * the sanest thing would be to use 1.
1150
 
          * however that would require passing on the match type to do_notify.
1151
 
          *  -jsmith2
1152
 
          */
1153
 
 
1154
 
            comparator_t *comp = NULL;
1155
 
            
1156
 
            const char *pattern;
1157
 
            regex_t *reg;
1158
 
            
1159
 
            const char *priority = NULL;
1160
 
            void *comprock = NULL;
1161
 
            
1162
 
            int comparator;
1163
 
            int pri;
1164
 
            
1165
 
            ip++;
1166
 
            pri=ntohl(bc[ip].value);
1167
 
            ip++;
1168
 
            
1169
 
            switch (pri)
1170
 
            {
1171
 
            case B_LOW:
1172
 
                priority="low";         
1173
 
            case B_NORMAL:
1174
 
                priority="normal";
1175
 
                break;
1176
 
            case B_HIGH: 
1177
 
                priority="high";
1178
 
                break; 
1179
 
            case B_ANY:
1180
 
                priority="any";
1181
 
                break;
1182
 
            default:
1183
 
                res=SIEVE_RUN_ERROR;
1184
 
            }
1185
 
 
1186
 
            if(res == SIEVE_RUN_ERROR)
1187
 
                break;
1188
 
           
1189
 
            comparator =ntohl( bc[ip].value);
1190
 
            ip++;
1191
 
            
1192
 
            if (comparator == B_ANY)
1193
 
            { 
1194
 
                ip++;/* skip placeholder this has no comparator function */
1195
 
                comp=NULL;
1196
 
            } else {
1197
 
                int x= ntohl(bc[ip].value);
1198
 
                ip++;
1199
 
                
1200
 
                comp=lookup_comp(B_ASCIICASEMAP,comparator,
1201
 
                                 x, &comprock);
1202
 
            }
1203
 
            
1204
 
            ip = unwrap_string(bc, ip, &pattern, NULL);
1205
 
          
1206
 
            if (comparator == B_REGEX)
1207
 
            {   
1208
 
                char errmsg[1024]; /* Basically unused */
1209
 
                
1210
 
                reg=bc_compile_regex(pattern,
1211
 
                                     REG_EXTENDED | REG_NOSUB | REG_ICASE,
1212
 
                                     errmsg, sizeof(errmsg));
1213
 
                if (!reg) {
1214
 
                    res = SIEVE_RUN_ERROR;
1215
 
                } else {
1216
 
                    res = do_denotify(notify_list, comp, reg,
1217
 
                                      comprock, priority);
1218
 
                    free(reg);
1219
 
                }
1220
 
            } else {
1221
 
                res = do_denotify(notify_list, comp, pattern,
1222
 
                                  comprock, priority);
1223
 
            }
1224
 
            
1225
 
            break;
1226
 
        }
1227
 
        case B_VACATION:
1228
 
        {
1229
 
            int respond;
1230
 
            char *fromaddr = NULL; /* relative to message we send */
1231
 
            char *toaddr = NULL; /* relative to message we send */
1232
 
            const char *handle = NULL;
1233
 
            const char *message = NULL;
1234
 
            int days, mime;
1235
 
            char buf[128];
1236
 
            char subject[1024];
1237
 
            int x;
1238
 
            
1239
 
            ip++;
1240
 
 
1241
 
            x=ntohl( bc[ip].len);
1242
 
            
1243
 
            respond=shouldRespond(m, i, x, bc, ip+2,
1244
 
                                  &fromaddr, &toaddr);
1245
 
            
1246
 
            ip=(ntohl(bc[ip+1].value)/4);       
1247
 
            if (respond==SIEVE_OK)
1248
 
            {    
1249
 
                ip = unwrap_string(bc, ip, &data, NULL);
1250
 
                
1251
 
                if (!data) 
1252
 
                {
1253
 
                    /* we have to generate a subject */
1254
 
                    const char **s;         
1255
 
                    strlcpy(buf, "subject", sizeof(buf));
1256
 
                    if (i->getheader(m, buf, &s) != SIEVE_OK ||
1257
 
                        s[0] == NULL) {
1258
 
                        strlcpy(subject, "Automated reply", sizeof(subject));
1259
 
                    } else {
1260
 
                        /* s[0] contains the original subject */
1261
 
                        const char *origsubj = s[0];
1262
 
 
1263
 
                        snprintf(subject, sizeof(subject), "Auto: %s", origsubj);
1264
 
                    }
1265
 
                } else {
1266
 
                    /* user specified subject */
1267
 
                    strlcpy(subject, data, sizeof(subject));
1268
 
                }
1269
 
                
1270
 
                ip = unwrap_string(bc, ip, &message, NULL);
1271
 
 
1272
 
                days = ntohl(bc[ip].value);
1273
 
                mime = ntohl(bc[ip+1].value);
1274
 
 
1275
 
                ip+=2;  
1276
 
 
1277
 
                if (version >= 0x05) {
1278
 
                    ip = unwrap_string(bc, ip, &data, NULL);
1279
 
 
1280
 
                    if (data) {
1281
 
                        /* user specified from address */
1282
 
                        free(fromaddr);
1283
 
                        fromaddr = xstrdup(data);
1284
 
                    }
1285
 
 
1286
 
                    ip = unwrap_string(bc, ip, &data, NULL);
1287
 
 
1288
 
                    if (data) {
1289
 
                        /* user specified handle */
1290
 
                        handle = data;
1291
 
                    }
1292
 
                }
1293
 
 
1294
 
                res = do_vacation(actions, toaddr, fromaddr, xstrdup(subject),
1295
 
                                  message, days, mime, handle);
1296
 
 
1297
 
                if (res == SIEVE_RUN_ERROR)
1298
 
                    *errmsg = "Vacation can not be used with Reject or Vacation";
1299
 
            } else if (respond == SIEVE_DONE) {
1300
 
                /* skip subject and message */
1301
 
 
1302
 
                ip = unwrap_string(bc, ip, &data, NULL);
1303
 
                ip = unwrap_string(bc, ip, &data, NULL);
1304
 
 
1305
 
                ip+=2;/*skip days and mime flag*/
1306
 
 
1307
 
                if (version >= 0x05) {
1308
 
                    /* skip from and handle */
1309
 
                    ip = unwrap_string(bc, ip, &data, NULL);
1310
 
                    ip = unwrap_string(bc, ip, &data, NULL);
1311
 
                }
1312
 
            } else {
1313
 
                res = SIEVE_RUN_ERROR; /* something is bad */ 
1314
 
            }
1315
 
 
1316
 
            break;
1317
 
        }
1318
 
        case B_NULL:/*15*/
1319
 
            ip++;
1320
 
            break;
1321
 
 
1322
 
        case B_JUMP:/*16*/
1323
 
            ip= ntohl(bc[ip+1].jump);
1324
 
            break;
1325
 
            
1326
 
        case B_INCLUDE:/*17*/
1327
 
        {
1328
 
            int isglobal = (ntohl(bc[ip+1].value) == B_GLOBAL);
1329
 
            char fpath[4096];
1330
 
 
1331
 
            ip = unwrap_string(bc, ip+2, &data, NULL);
1332
 
 
1333
 
            res = i->getinclude(sc, data, isglobal, fpath, sizeof(fpath));
1334
 
            if (res != SIEVE_OK)
1335
 
                *errmsg = "Include can not find script";
1336
 
 
1337
 
            if (!res) {
1338
 
                res = sieve_script_load(fpath, &exe);
1339
 
                if (res != SIEVE_OK)
1340
 
                *errmsg = "Include can not load script";
1341
 
            }
1342
 
 
1343
 
            if (!res)
1344
 
                res = sieve_eval_bc(exe, 1, i, body_cache,
1345
 
                                    sc, m, imapflags, actions,
1346
 
                                    notify_list, errmsg);
1347
 
 
1348
 
            break;
1349
 
        }
1350
 
 
1351
 
        case B_RETURN:/*18*/
1352
 
            if (is_incl)
1353
 
                goto done;
1354
 
            else
1355
 
                res=1;
1356
 
            break;
1357
 
 
1358
 
        default:
1359
 
            if(errmsg) *errmsg = "Invalid sieve bytecode";
1360
 
            return SIEVE_FAIL;
1361
 
        }
1362
 
      
1363
 
        if (res) /* we've either encountered an error or a stop */
1364
 
            break;
1365
 
    }
1366
 
 
1367
 
  done:
1368
 
    bc_cur->is_executing = 0;
1369
 
 
1370
 
    return res;      
1371
 
}