~ubuntu-branches/ubuntu/quantal/dovecot/quantal

« back to all changes in this revision

Viewing changes to sieve/src/lib-sieve/ext-encoded-character.c

  • Committer: Bazaar Package Importer
  • Author(s): Chuck Short, Scott Kitterman
  • Date: 2010-06-22 10:33:51 UTC
  • mfrom: (1.13.5 upstream)
  • Revision ID: james.westby@ubuntu.com-20100622103351-ifbmnklp8kxrhb30
Tags: 1:1.2.12-0ubuntu1
* New upstream release:
  - deliver: Don't crash when a message with Auto-submitted: header gets
   rejected.
  - lib-storage: Fixed header searches to work correctly when there are
    multiple headers with same name.
  - dict client: Disconnect from dict server after 1 second of idling.
  - dict: If process crashed, it wasn't automatically restarted
  - dict file: If dict file's group permissions equal world permissions,
    don't try to change its gid.
  - maildir: Fixed a memory leak when copying with hardlinks.
  - maildir: Expunging last messages may have assert-crashed if their
    filenames had just changed.
 * Update sieve patch to 0.1.17
 * debian/dovecot-common.postinst: Add warning about expired certificate.
   (Debian Bug: #576455)
 * Silence lintian warnings.

 [Scott Kitterman]
 * Rename dovecot-postfix to mail-stack-delivery per server-maverick-mail-
   integration spec.
   - Update debian/rules
   - Convert existing package to a dummy package and add new binary in debian/control
   - Update maintainer scripts.
   - Move previously installed backups and config files to new package name
     space in preinst
   - Add new debian/mail-stack-delivery.prerm to handle downgrades
   - Rename debian/dovecot-postfix.* to debian/mail-stack-delivery.*

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/* Copyright (c) 2002-2010 Dovecot Sieve authors, see the included COPYING file
2
2
 */
3
3
 
4
 
/* Extension encoded-character
 
4
/* Extension encoded-character 
5
5
 * ---------------------------
6
6
 *
7
7
 * Authors: Stephan Bosch
8
8
 * Specification: RFC5228
9
 
 * Implementation: full
 
9
 * Implementation: full 
10
10
 * Status: experimental, largely untested
11
11
 *
12
12
 */
20
20
 
21
21
#include <ctype.h>
22
22
 
23
 
/*
 
23
/* 
24
24
 * Extension
25
25
 */
26
26
 
27
27
static bool ext_encoded_character_validator_load
28
28
        (const struct sieve_extension *ext, struct sieve_validator *valdtr);
29
 
 
30
 
struct sieve_extension_def encoded_character_extension = {
31
 
        "encoded-character",
 
29
        
 
30
struct sieve_extension_def encoded_character_extension = { 
 
31
        "encoded-character", 
32
32
        NULL, NULL,
33
 
        ext_encoded_character_validator_load,
 
33
        ext_encoded_character_validator_load, 
34
34
        NULL, NULL, NULL, NULL, NULL,
35
 
        SIEVE_EXT_DEFINE_NO_OPERATIONS,
 
35
        SIEVE_EXT_DEFINE_NO_OPERATIONS, 
36
36
        SIEVE_EXT_DEFINE_NO_OPERANDS
37
37
};
38
38
 
41
41
 */
42
42
 
43
43
bool arg_encoded_string_validate
44
 
        (struct sieve_validator *valdtr, struct sieve_ast_argument **arg,
 
44
        (struct sieve_validator *valdtr, struct sieve_ast_argument **arg, 
45
45
                struct sieve_command *context);
46
46
 
47
 
const struct sieve_argument_def encoded_string_argument = {
48
 
        "@encoded-string",
49
 
        NULL,
50
 
        arg_encoded_string_validate,
 
47
const struct sieve_argument_def encoded_string_argument = { 
 
48
        "@encoded-string", 
 
49
        NULL, 
 
50
        arg_encoded_string_validate, 
51
51
        NULL, NULL, NULL
52
52
};
53
53
 
63
63
                                return FALSE;
64
64
                        continue;
65
65
                }
66
 
 
 
66
                
67
67
                /* (Loose LF is non-standard) */
68
 
                if ( **in != ' ' && **in != '\n' && **in != '\t' )
 
68
                if ( **in != ' ' && **in != '\n' && **in != '\t' ) 
69
69
                        break;
70
 
 
 
70
                        
71
71
                (*in)++;
72
72
        }
73
 
 
 
73
        
74
74
        return TRUE;
75
75
}
76
76
 
79
79
{
80
80
        int digit = 0;
81
81
        *result = 0;
82
 
 
 
82
                
83
83
        while ( *in < inend && (max_digits == 0 || digit < max_digits) ) {
84
 
 
85
 
                if ( (**in) >= '0' && (**in) <= '9' )
 
84
        
 
85
                if ( (**in) >= '0' && (**in) <= '9' ) 
86
86
                        *result = ((*result) << 4) + (**in) - ((unsigned int) '0');
87
87
                else if ( (**in) >= 'a' && (**in) <= 'f' )
88
88
                        *result = ((*result) << 4) + (**in) - ((unsigned int) 'a') + 0x0a;
90
90
                        *result = ((*result) << 4) + (**in) - ((unsigned int) 'A') + 0x0a;
91
91
                else
92
92
                        return ( digit > 0 );
93
 
 
 
93
        
94
94
                (*in)++;
95
95
                digit++;
96
96
        }
97
 
 
 
97
        
98
98
        if ( digit == max_digits ) {
99
99
                /* Hex digit _MUST_ end here */
100
100
                if ( (**in >= '0' && **in <= '9')       || (**in >= 'a' && **in <= 'f') ||
101
101
                        (**in >= 'A' && **in <= 'F') )
102
102
                        return FALSE;
103
 
 
 
103
                        
104
104
                return TRUE;
105
105
        }
106
 
 
 
106
        
107
107
        return ( digit > 0 );
108
108
}
109
109
 
110
110
static bool _decode_hex
111
 
(const char **in, const char *inend, string_t *result)
 
111
(const char **in, const char *inend, string_t *result) 
112
112
{
113
113
        int values = 0;
114
 
 
 
114
        
115
115
        while ( *in < inend ) {
116
116
                unsigned int hexpair;
117
 
 
 
117
                
118
118
                if ( !_skip_whitespace(in, inend) ) return FALSE;
119
 
 
 
119
                
120
120
                if ( !_parse_hexint(in, inend, 2, &hexpair) ) break;
121
 
 
 
121
                
122
122
                str_append_c(result, (unsigned char) hexpair);
123
123
                values++;
124
124
        }
125
 
 
 
125
        
126
126
        return ( values > 0 );
127
127
}
128
128
 
129
129
static int _decode_unicode
130
 
(const char **in, const char *inend, string_t *result, unsigned int *error_hex)
 
130
(const char **in, const char *inend, string_t *result, unsigned int *error_hex) 
131
131
{
132
132
        int values = 0;
133
133
        bool valid = TRUE;
134
 
 
 
134
        
135
135
        while ( *in < inend ) {
136
136
                unsigned int unicode_hex;
137
 
 
 
137
                
138
138
                if ( !_skip_whitespace(in, inend) ) return FALSE;
139
 
 
 
139
                
140
140
                if ( !_parse_hexint(in, inend, 0, &unicode_hex) ) break;
141
141
 
142
 
                if ( (unicode_hex <= 0xD7FF) ||
143
 
                        (unicode_hex >= 0xE000 && unicode_hex <= 0x10FFFF)      )
 
142
                if ( (unicode_hex <= 0xD7FF) || 
 
143
                        (unicode_hex >= 0xE000 && unicode_hex <= 0x10FFFF)      ) 
144
144
                        uni_ucs4_to_utf8_c((unichar_t) unicode_hex, result);
145
145
                else {
146
146
                        if ( valid ) *error_hex = unicode_hex;
147
147
                        valid = FALSE;
148
 
                }
 
148
                }       
149
149
                values++;
150
150
        }
151
 
 
 
151
        
152
152
        return ( values > 0 );
153
153
}
154
154
 
155
155
bool arg_encoded_string_validate
156
 
(struct sieve_validator *valdtr, struct sieve_ast_argument **arg,
 
156
(struct sieve_validator *valdtr, struct sieve_ast_argument **arg, 
157
157
                struct sieve_command *cmd)
158
158
{
159
159
        bool result = TRUE;
160
 
        enum { ST_NONE, ST_OPEN, ST_TYPE, ST_CLOSE }
 
160
        enum { ST_NONE, ST_OPEN, ST_TYPE, ST_CLOSE } 
161
161
                state = ST_NONE;
162
162
        string_t *str = sieve_ast_argument_str(*arg);
163
163
        string_t *tmpstr, *newstr = NULL;
166
166
        const char *strend = strval + str_len(str);
167
167
        unsigned int error_hex = 0;
168
168
 
169
 
        T_BEGIN {
170
 
                tmpstr = t_str_new(32);
171
 
 
 
169
        T_BEGIN {               
 
170
                tmpstr = t_str_new(32); 
 
171
                        
172
172
                p = strval;
173
173
                strstart = p;
174
174
                while ( result && p < strend ) {
186
186
                                if ( *p == '{' ) {
187
187
                                        state = ST_TYPE;
188
188
                                        p++;
189
 
                                } else
 
189
                                } else 
190
190
                                        state = ST_NONE;
191
191
                                break;
192
192
                        /* Parsed '${' */
194
194
                                mark = p;
195
195
                                /* Scan for 'hex' or 'unicode' */
196
196
                                while ( p < strend && i_isalpha(*p) ) p++;
197
 
 
 
197
                                        
198
198
                                if ( *p != ':' ) {
199
199
                                        state = ST_NONE;
200
200
                                        break;
201
201
                                }
202
 
 
 
202
                                
203
203
                                state = ST_CLOSE;
204
 
 
 
204
                                
205
205
                                str_truncate(tmpstr, 0);
206
206
                                if ( strncasecmp(mark, "hex", p - mark) == 0 ) {
207
207
                                        /* Hexadecimal */
213
213
                                        p++;
214
214
                                        if ( !_decode_unicode(&p, strend, tmpstr, &error_hex) )
215
215
                                                state = ST_NONE;
216
 
                                } else {
 
216
                                } else {        
217
217
                                        /* Invalid encoding */
218
218
                                        p++;
219
219
                                        state = ST_NONE;
220
220
                                }
221
221
                                break;
222
222
                        case ST_CLOSE:
223
 
                                if ( *p == '}' ) {
224
 
                                        /* We now know that the substitution is valid */
 
223
                                if ( *p == '}' ) {                              
 
224
                                        /* We now know that the substitution is valid */        
225
225
 
226
226
                                        if ( error_hex != 0 ) {
227
 
                                                sieve_argument_validate_error(valdtr, *arg,
 
227
                                                sieve_argument_validate_error(valdtr, *arg, 
228
228
                                                        "invalid unicode character 0x%08x in encoded character substitution",
229
229
                                                        error_hex);
230
230
                                                result = FALSE;
231
231
                                                break;
232
232
                                        }
233
 
 
 
233
                                        
234
234
                                        if ( newstr == NULL ) {
235
235
                                                newstr = str_new(sieve_ast_pool((*arg)->ast), str_len(str)*2);
236
236
                                        }
237
 
 
 
237
                                        
238
238
                                        str_append_n(newstr, strstart, substart-strstart);
239
239
                                        str_append_str(newstr, tmpstr);
240
 
 
 
240
                                        
241
241
                                        strstart = p + 1;
242
242
                                        substart = strstart;
243
 
 
244
 
                                        p++;
245
 
                                }
 
243
                                        
 
244
                                        p++;    
 
245
                                } 
246
246
                                state = ST_NONE;
247
247
                        }
248
248
                }
249
249
        } T_END;
250
250
 
251
251
        if ( !result ) return FALSE;
252
 
 
 
252
        
253
253
        if ( newstr != NULL ) {
254
254
                if ( strstart != strend )
255
 
                        str_append_n(newstr, strstart, strend-strstart);
256
 
 
 
255
                        str_append_n(newstr, strstart, strend-strstart);        
 
256
        
257
257
                sieve_ast_argument_string_set(*arg, newstr);
258
258
        }
259
 
 
 
259
        
260
260
        /* Pass the processed string to a (possible) next layer of processing */
261
261
        return sieve_validator_argument_activate_super
262
262
                (valdtr, cmd, *arg, TRUE);
263
263
}
264
264
 
265
 
/*
 
265
/* 
266
266
 * Extension implementation
267
267
 */
268
268
 
271
271
{
272
272
        /* Override the constant string argument with our own */
273
273
        sieve_validator_argument_override
274
 
                (valdtr, SAT_CONST_STRING, ext, &encoded_string_argument);
275
 
 
 
274
                (valdtr, SAT_CONST_STRING, ext, &encoded_string_argument); 
 
275
        
276
276
        return TRUE;
277
277
}