summaryrefslogtreecommitdiffstats
path: root/pigeonhole/src/lib-sieve/sieve-code.h
blob: 00bf68bdd28fe4b9e701aadf6053c281bc160d81 (plain)
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
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
#ifndef SIEVE_CODE_H
#define SIEVE_CODE_H

#include "lib.h"
#include "buffer.h"
#include "mempool.h"
#include "array.h"

#include "sieve-common.h"
#include "sieve-runtime.h"
#include "sieve-runtime-trace.h"
#include "sieve-dump.h"

/*
 * Operand object
 */

struct sieve_operand_class {
	const char *name;
};

struct sieve_operand_def {
	const char *name;

	const struct sieve_extension_def *ext_def;
	unsigned int code;

	const struct sieve_operand_class *class;
	const void *interface;
};

struct sieve_operand {
	const struct sieve_operand_def *def;
	const struct sieve_extension *ext;
	sieve_size_t address;
	const char *field_name;
};

#define sieve_operand_name(opr) \
	( (opr)->def == NULL ? "(NULL)" : (opr)->def->name )
#define sieve_operand_is(opr, definition) \
	( (opr)->def == &(definition) )

sieve_size_t sieve_operand_emit
	(struct sieve_binary_block *sblock, const struct sieve_extension *ext,
		const struct sieve_operand_def *oprnd);
bool sieve_operand_read
	(struct sieve_binary_block *sblock, sieve_size_t *address,
		const char *field_name, struct sieve_operand *oprnd);

static inline int sieve_operand_runtime_read
(const struct sieve_runtime_env *renv, sieve_size_t *address,
	const char *field_name, struct sieve_operand *operand)
{
	if ( !sieve_operand_read(renv->sblock, address, field_name, operand) ) {
		sieve_runtime_trace_operand_error(renv, operand, "invalid operand");
		return SIEVE_EXEC_BIN_CORRUPT;
	}

	return SIEVE_EXEC_OK;
}

/*
 * Optional operands
 */

int sieve_opr_optional_next
(struct sieve_binary_block *sblock, sieve_size_t *address,
	signed int *opt_code);

static inline int sieve_opr_optional_dump
(const struct sieve_dumptime_env *denv, sieve_size_t *address,
	signed int *opt_code)
{
	sieve_size_t pc = *address;
	int ret;

	if ( (ret=sieve_opr_optional_next(denv->sblock, address, opt_code)) <= 0 )
		return ret;

	sieve_code_mark_specific(denv, pc);
	return ret;
}

static inline int sieve_opr_optional_read
(const struct sieve_runtime_env *renv, sieve_size_t *address,
	signed int *opt_code)
{
	int ret;

	if ( (ret=sieve_opr_optional_next(renv->sblock, address, opt_code)) < 0 )
		sieve_runtime_trace_error(renv, "invalid optional operand code");

	return ret;
}

/*
 * Core operands
 */

/* Operand codes */

enum sieve_core_operand {
	SIEVE_OPERAND_OPTIONAL = 0x00,
	SIEVE_OPERAND_NUMBER,
	SIEVE_OPERAND_STRING,
	SIEVE_OPERAND_STRING_LIST,
	SIEVE_OPERAND_COMPARATOR,
	SIEVE_OPERAND_MATCH_TYPE,
	SIEVE_OPERAND_ADDRESS_PART,
	SIEVE_OPERAND_CATENATED_STRING,

	SIEVE_OPERAND_CUSTOM
};

/* Operand classes */

extern const struct sieve_operand_class number_class;
extern const struct sieve_operand_class string_class;
extern const struct sieve_operand_class stringlist_class;

/* Operand objects */

extern const struct sieve_operand_def omitted_operand;
extern const struct sieve_operand_def number_operand;
extern const struct sieve_operand_def string_operand;
extern const struct sieve_operand_def stringlist_operand;
extern const struct sieve_operand_def catenated_string_operand;

extern const struct sieve_operand_def *sieve_operands[];
extern const unsigned int sieve_operand_count;

/* Operand object interfaces */

struct sieve_opr_number_interface {
	bool (*dump)
		(const struct sieve_dumptime_env *denv, const struct sieve_operand *oprnd,
			sieve_size_t *address);
	int (*read)
	  (const struct sieve_runtime_env *renv, const struct sieve_operand *oprnd,
			sieve_size_t *address, sieve_number_t *number_r);
};

struct sieve_opr_string_interface {
	bool (*dump)
		(const struct sieve_dumptime_env *denv, const struct sieve_operand *oprnd,
			sieve_size_t *address);
	int (*read)
		(const struct sieve_runtime_env *renv, const struct sieve_operand *oprnd,
		 	sieve_size_t *address, string_t **str_r);
};

struct sieve_opr_stringlist_interface {
	bool (*dump)
		(const struct sieve_dumptime_env *denv, const struct sieve_operand *oprnd,
			sieve_size_t *address);
	int (*read)
		(const struct sieve_runtime_env *renv, const struct sieve_operand *oprnd,
			sieve_size_t *address, struct sieve_stringlist **strlist_r);
};

/*
 * Core operand functions
 */

/* Omitted */

void sieve_opr_omitted_emit(struct sieve_binary_block *sblock);

static inline bool sieve_operand_is_omitted
(const struct sieve_operand *operand)
{
	return ( operand != NULL && operand->def != NULL &&
		operand->def == &omitted_operand );
}

/* Number */

void sieve_opr_number_emit
	(struct sieve_binary_block *sblock, sieve_number_t number);
bool sieve_opr_number_dump_data
	(const struct sieve_dumptime_env *denv, struct sieve_operand *operand,
		sieve_size_t *address, const char *field_name);
bool sieve_opr_number_dump
	(const struct sieve_dumptime_env *denv, sieve_size_t *address,
		const char *field_name);
int sieve_opr_number_read_data
	(const struct sieve_runtime_env *renv, struct sieve_operand *operand,
		sieve_size_t *address, const char *field_name, sieve_number_t *number_r);
int sieve_opr_number_read
	(const struct sieve_runtime_env *renv, sieve_size_t *address,
		const char *field_name, sieve_number_t *number_r);

static inline bool sieve_operand_is_number
(const struct sieve_operand *operand)
{
	return ( operand != NULL && operand->def != NULL &&
		operand->def->class == &number_class );
}

/* String */

void sieve_opr_string_emit
	(struct sieve_binary_block *sblock, string_t *str);
bool sieve_opr_string_dump_data
	(const struct sieve_dumptime_env *denv, struct sieve_operand *operand,
		sieve_size_t *address, const char *field_name);
bool sieve_opr_string_dump
	(const struct sieve_dumptime_env *denv, sieve_size_t *address,
		const char *field_name);
bool sieve_opr_string_dump_ex
	(const struct sieve_dumptime_env *denv, sieve_size_t *address,
		const char *field_name, const char *omitted_value);
int sieve_opr_string_read_data
	(const struct sieve_runtime_env *renv, struct sieve_operand *operand,
		sieve_size_t *address, const char *field_name, string_t **str_r);
int sieve_opr_string_read
	(const struct sieve_runtime_env *renv, sieve_size_t *address,
		const char *field_name, string_t **str_r);
int sieve_opr_string_read_ex
	(const struct sieve_runtime_env *renv, sieve_size_t *address,
		const char *field_name, bool optional, string_t **str_r, bool *literal_r);

static inline bool sieve_operand_is_string
(const struct sieve_operand *operand)
{
	return ( operand != NULL && operand->def != NULL &&
		operand->def->class == &string_class );
}

static inline bool sieve_operand_is_string_literal
(const struct sieve_operand *operand)
{
	return ( operand != NULL && sieve_operand_is(operand, string_operand) );
}

/* String list */

void sieve_opr_stringlist_emit_start
	(struct sieve_binary_block *sblock, unsigned int listlen, void **context);
void sieve_opr_stringlist_emit_item
	(struct sieve_binary_block *sblock, void *context ATTR_UNUSED,
		string_t *item);
void sieve_opr_stringlist_emit_end
	(struct sieve_binary_block *sblock, void *context);
bool sieve_opr_stringlist_dump_data
	(const struct sieve_dumptime_env *denv, struct sieve_operand *operand,
		sieve_size_t *address, const char *field_name);
bool sieve_opr_stringlist_dump
	(const struct sieve_dumptime_env *denv, sieve_size_t *address,
		const char *field_name);
bool sieve_opr_stringlist_dump_ex
	(const struct sieve_dumptime_env *denv, sieve_size_t *address,
		const char *field_name, const char *omitted_value);
int sieve_opr_stringlist_read_data
	(const struct sieve_runtime_env *renv, struct sieve_operand *operand,
		sieve_size_t *address, const char *field_name,
		struct sieve_stringlist **strlist_r);
int sieve_opr_stringlist_read
	(const struct sieve_runtime_env *renv, sieve_size_t *address,
		const char *field_name, struct sieve_stringlist **strlist_r);
int sieve_opr_stringlist_read_ex
	(const struct sieve_runtime_env *renv, sieve_size_t *address,
		const char *field_name, bool optional, struct sieve_stringlist **strlist_r);

static inline bool sieve_operand_is_stringlist
(const struct sieve_operand *operand)
{
	return ( operand != NULL && operand->def != NULL &&
		(operand->def->class == &stringlist_class ||
			operand->def->class == &string_class) );
}

/* Catenated string */

void sieve_opr_catenated_string_emit
	(struct sieve_binary_block *sblock, unsigned int elements);

/*
 * Operation object
 */

struct sieve_operation_def {
	const char *mnemonic;

	const struct sieve_extension_def *ext_def;
	unsigned int code;

	bool (*dump)
		(const struct sieve_dumptime_env *denv, sieve_size_t *address);
	int (*execute)
		(const struct sieve_runtime_env *renv, sieve_size_t *address);
};

struct sieve_operation {
	const struct sieve_operation_def *def;
	const struct sieve_extension *ext;

	sieve_size_t address;
};

#define sieve_operation_is(oprtn, definition) \
	( (oprtn)->def == &(definition) )
#define sieve_operation_mnemonic(oprtn) \
	( (oprtn)->def == NULL ? "(NULL)" : (oprtn)->def->mnemonic )

sieve_size_t sieve_operation_emit
	(struct sieve_binary_block *sblock, const struct sieve_extension *ext,
		const struct sieve_operation_def *op_def);
bool sieve_operation_read
	(struct sieve_binary_block *sblock, sieve_size_t *address,
		struct sieve_operation *oprtn);
const char *sieve_operation_read_string
	(struct sieve_binary_block *sblock, sieve_size_t *address);

/*
 * Core operations
 */

/* Opcodes */

enum sieve_operation_code {
	SIEVE_OPERATION_INVALID,
	SIEVE_OPERATION_JMP,
	SIEVE_OPERATION_JMPTRUE,
	SIEVE_OPERATION_JMPFALSE,

	SIEVE_OPERATION_STOP,
	SIEVE_OPERATION_KEEP,
	SIEVE_OPERATION_DISCARD,
	SIEVE_OPERATION_REDIRECT,

	SIEVE_OPERATION_ADDRESS,
	SIEVE_OPERATION_HEADER,
	SIEVE_OPERATION_EXISTS,
	SIEVE_OPERATION_SIZE_OVER,
	SIEVE_OPERATION_SIZE_UNDER,

	SIEVE_OPERATION_CUSTOM
};

/* Operation objects */

extern const struct sieve_operation_def sieve_jmp_operation;
extern const struct sieve_operation_def sieve_jmptrue_operation;
extern const struct sieve_operation_def sieve_jmpfalse_operation;

extern const struct sieve_operation_def *sieve_operations[];
extern const unsigned int sieve_operations_count;

#endif