1
1
/* Copyright (c) 2002-2010 Dovecot Sieve authors, see the included COPYING file
4
/* Extension encoded-character
4
/* Extension encoded-character
5
5
* ---------------------------
7
7
* Authors: Stephan Bosch
8
8
* Specification: RFC5228
10
10
* Status: experimental, largely untested
27
27
static bool ext_encoded_character_validator_load
28
28
(const struct sieve_extension *ext, struct sieve_validator *valdtr);
30
struct sieve_extension_def encoded_character_extension = {
30
struct sieve_extension_def encoded_character_extension = {
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
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);
47
const struct sieve_argument_def encoded_string_argument = {
50
arg_encoded_string_validate,
47
const struct sieve_argument_def encoded_string_argument = {
50
arg_encoded_string_validate,
83
83
while ( *in < inend && (max_digits == 0 || digit < max_digits) ) {
85
if ( (**in) >= '0' && (**in) <= '9' )
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;
92
92
return ( digit > 0 );
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') )
107
107
return ( digit > 0 );
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)
115
115
while ( *in < inend ) {
116
116
unsigned int hexpair;
118
118
if ( !_skip_whitespace(in, inend) ) return FALSE;
120
120
if ( !_parse_hexint(in, inend, 2, &hexpair) ) break;
122
122
str_append_c(result, (unsigned char) hexpair);
126
126
return ( values > 0 );
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)
133
133
bool valid = TRUE;
135
135
while ( *in < inend ) {
136
136
unsigned int unicode_hex;
138
138
if ( !_skip_whitespace(in, inend) ) return FALSE;
140
140
if ( !_parse_hexint(in, inend, 0, &unicode_hex) ) break;
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);
146
146
if ( valid ) *error_hex = unicode_hex;
152
152
return ( values > 0 );
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)
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 }
162
162
string_t *str = sieve_ast_argument_str(*arg);
163
163
string_t *tmpstr, *newstr = NULL;
214
214
if ( !_decode_unicode(&p, strend, tmpstr, &error_hex) )
217
217
/* Invalid encoding */
224
/* We now know that the substitution is valid */
224
/* We now know that the substitution is valid */
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",
234
234
if ( newstr == NULL ) {
235
235
newstr = str_new(sieve_ast_pool((*arg)->ast), str_len(str)*2);
238
238
str_append_n(newstr, strstart, substart-strstart);
239
239
str_append_str(newstr, tmpstr);
241
241
strstart = p + 1;
242
242
substart = strstart;
251
251
if ( !result ) return FALSE;
253
253
if ( newstr != NULL ) {
254
254
if ( strstart != strend )
255
str_append_n(newstr, strstart, strend-strstart);
255
str_append_n(newstr, strstart, strend-strstart);
257
257
sieve_ast_argument_string_set(*arg, newstr);
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);
266
266
* Extension implementation
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);
274
(valdtr, SAT_CONST_STRING, ext, &encoded_string_argument);