~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
  • Date: 2010-06-29 09:21:32 UTC
  • mfrom: (4.1.14 sid)
  • Revision ID: james.westby@ubuntu.com-20100629092132-q4pr5lfuvmjqou19
Tags: 1:1.2.12-1ubuntu1
* Merge from Debian Unstable, remaining changes:
  + Add mail-stack-delivery as 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.*
  + 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/*.
  + Add ufw integration:
    - Created debian/dovecot-common.ufw.profile.
    - debian/rules: install profile.
    - debian/control: suggest ufw.
  + debian/{control,rules}: enable PIE hardening.
  + debian/control: Update Vcs-* headers.
  + Add SMTP-AUTH support for Outlook (login auth mechanism) 
  + debian/dovecot-common.dirs: Added usr/share/doc/dovecot-common
  + debian/patches/fix-dovecot-config-parser.patch: Fix ordering of external config 
    files. (LP: #597818)

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
}