File: tst-ihave.c

package info (click to toggle)
dovecot 1:2.2.13-12~deb8u4
  • links: PTS, VCS
  • area: main
  • in suites: jessie
  • size: 38,792 kB
  • sloc: ansic: 341,472; sh: 16,920; makefile: 5,393; cpp: 1,474; perl: 265; xml: 44; python: 34; pascal: 27
file content (158 lines) | stat: -rw-r--r-- 4,084 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
/* Copyright (c) 2002-2013 Pigeonhole authors, see the included COPYING file
 */

#include "lib.h"
#include "array.h"

#include "sieve-common.h"
#include "sieve-extensions.h"
#include "sieve-commands.h"
#include "sieve-validator.h"
#include "sieve-generator.h"

#include "ext-ihave-common.h"

/*
 * Ihave test
 *
 * Syntax:
 *   ihave <capabilities: string-list>
 */

static bool tst_ihave_validate
	(struct sieve_validator *valdtr, struct sieve_command *tst);
static bool tst_ihave_validate_const
	(struct sieve_validator *valdtr, struct sieve_command *tst,
		int *const_current, int const_next);

const struct sieve_command_def ihave_test = {
	"ihave",
	SCT_TEST,
	1, 0, FALSE, FALSE,
	NULL, NULL,
	tst_ihave_validate,
	tst_ihave_validate_const,
	NULL, NULL
};

/*
 * Code validation
 */

static bool tst_ihave_validate
(struct sieve_validator *valdtr, struct sieve_command *tst)
{
	struct _capability {
		const struct sieve_extension *ext;
		struct sieve_ast_argument *arg;
	};

	struct sieve_ast_argument *arg = tst->first_positional;
	struct sieve_ast_argument *stritem;
	enum sieve_compile_flags cpflags = sieve_validator_compile_flags(valdtr);
	bool no_global = ( (cpflags & SIEVE_COMPILE_FLAG_NOGLOBAL) != 0 );
	ARRAY(struct _capability) capabilities;
	struct _capability capability;
	const struct _capability *caps;
	unsigned int i, count;
	bool all_known = TRUE;

	t_array_init(&capabilities, 64);

	tst->data = (void *) FALSE;

	/* Check stringlist argument */
	if ( !sieve_validate_positional_argument
		(valdtr, tst, arg, "capabilities", 1, SAAT_STRING_LIST) ) {
		return FALSE;
	}

	switch ( sieve_ast_argument_type(arg) ) {
	case SAAT_STRING:
		/* Single string */
		capability.arg = arg;
		capability.ext = sieve_extension_get_by_name
			(tst->ext->svinst, sieve_ast_argument_strc(arg));

		if ( capability.ext == NULL || (no_global && capability.ext->global)) {
			all_known = FALSE;

			ext_ihave_ast_add_missing_extension
				(tst->ext, tst->ast_node->ast, sieve_ast_argument_strc(arg));
		} else {
			array_append(&capabilities, &capability, 1);
		}

		break;

	case SAAT_STRING_LIST:
		/* String list */
		stritem = sieve_ast_strlist_first(arg);

		while ( stritem != NULL ) {
			capability.arg = stritem;
			capability.ext = sieve_extension_get_by_name
				(tst->ext->svinst, sieve_ast_argument_strc(stritem));

			if ( capability.ext == NULL || (no_global && capability.ext->global)) {
				all_known = FALSE;

				ext_ihave_ast_add_missing_extension
					(tst->ext, tst->ast_node->ast, sieve_ast_argument_strc(stritem));
			} else {
				array_append(&capabilities, &capability, 1);
			}

			stritem = sieve_ast_strlist_next(stritem);
		}

		break;
	default:
		i_unreached();
	}

	if ( !all_known )
		return TRUE;

	/* RFC 5463, Section 4, page 4:
	 *
	 * The "ihave" extension is designed to be used with other extensions
	 * that add tests, actions, comparators, or arguments.  Implementations
	 * MUST NOT allow it to be used with extensions that change the
	 * underlying Sieve grammar, or extensions like encoded-character
	 * [RFC5228], or variables [RFC5229] that change how the content of
	 * Sieve scripts are interpreted.  The test MUST fail and the extension
	 * MUST NOT be enabled if such usage is attempted.
	 *
	 * FIXME: current implementation of this restriction is hardcoded and
	 * therefore highly inflexible
	 */
	caps = array_get(&capabilities, &count);
	for ( i = 0; i < count; i++ ) {
		if ( sieve_extension_name_is(caps[i].ext, "variables") ||
			sieve_extension_name_is(caps[i].ext, "encoded-character") )
			return TRUE;
	}

	/* Load all extensions */
	caps = array_get(&capabilities, &count);
	for ( i = 0; i < count; i++ ) {
		if ( !sieve_validator_extension_load
			(valdtr, tst, caps[i].arg, caps[i].ext) )
			return FALSE;
	}

	tst->data = (void *) TRUE;
	return TRUE;
}

static bool tst_ihave_validate_const
(struct sieve_validator *valdtr ATTR_UNUSED, struct sieve_command *tst,
	int *const_current, int const_next ATTR_UNUSED)
{
	if ( (bool)tst->data == TRUE )
		*const_current = 1;
	else
		*const_current = 0;
	return TRUE;
}