File: ext-subaddress.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 (189 lines) | stat: -rw-r--r-- 4,457 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
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
/* Copyright (c) 2002-2013 Pigeonhole authors, see the included COPYING file
 */

/* Extension subaddress
 * --------------------
 *
 * Author: Stephan Bosch
 * Specification: RFC 3598
 * Implementation: full
 * Status: testing
 *
 */

#include "sieve-common.h"

#include "sieve-settings.h"
#include "sieve-code.h"
#include "sieve-address.h"
#include "sieve-extensions.h"
#include "sieve-commands.h"
#include "sieve-address-parts.h"
#include "sieve-validator.h"
#include "sieve-generator.h"
#include "sieve-interpreter.h"

#include <stdlib.h>
#include <string.h>

/*
 * Configuration
 */

#define SUBADDRESS_DEFAULT_DELIM "+"

struct ext_subaddress_config {
	char *delimiter;
};

/*
 * Forward declarations
 */

const struct sieve_address_part_def user_address_part;
const struct sieve_address_part_def detail_address_part;

static struct sieve_operand_def subaddress_operand;

/*
 * Extension
 */

static bool ext_subaddress_load
	(const struct sieve_extension *ext, void **context);
static void ext_subaddress_unload
	(const struct sieve_extension *ext);
static bool ext_subaddress_validator_load
	(const struct sieve_extension *ext, struct sieve_validator *validator);

const struct sieve_extension_def subaddress_extension = {
	.name = "subaddress",
	.load = ext_subaddress_load,
	.unload = ext_subaddress_unload,
	.validator_load = ext_subaddress_validator_load,
	SIEVE_EXT_DEFINE_OPERAND(subaddress_operand)
};

static bool ext_subaddress_load
(const struct sieve_extension *ext, void **context)
{
	struct ext_subaddress_config *config;
	const char *delim;

	if ( *context != NULL ) {
		ext_subaddress_unload(ext);
	}

	delim = sieve_setting_get(ext->svinst, "recipient_delimiter");

	if ( delim == NULL )
		delim = SUBADDRESS_DEFAULT_DELIM;

	config = i_new(struct ext_subaddress_config, 1);
	config->delimiter = i_strdup(delim);

	*context = (void *) config;

	return TRUE;
}

static void ext_subaddress_unload
(const struct sieve_extension *ext)
{
	struct ext_subaddress_config *config =
		(struct ext_subaddress_config *) ext->context;

	i_free(config->delimiter);
	i_free(config);
}

static bool ext_subaddress_validator_load
(const struct sieve_extension *ext, struct sieve_validator *validator)
{
	sieve_address_part_register(validator, ext, &user_address_part);
	sieve_address_part_register(validator, ext, &detail_address_part);

	return TRUE;
}

/*
 * Address parts
 */

enum ext_subaddress_address_part {
  SUBADDRESS_USER,
  SUBADDRESS_DETAIL
};

/* Forward declarations */

static const char *subaddress_user_extract_from
	(const struct sieve_address_part *addrp, const struct sieve_address *address);
static const char *subaddress_detail_extract_from
	(const struct sieve_address_part *addrp, const struct sieve_address *address);

/* Address part objects */

const struct sieve_address_part_def user_address_part = {
	SIEVE_OBJECT("user", &subaddress_operand, SUBADDRESS_USER),
	subaddress_user_extract_from
};

const struct sieve_address_part_def detail_address_part = {
	SIEVE_OBJECT("detail", &subaddress_operand, SUBADDRESS_DETAIL),
	subaddress_detail_extract_from
};

/* Address part implementation */

static const char *subaddress_user_extract_from
(const struct sieve_address_part *addrp, const struct sieve_address *address)
{
	struct ext_subaddress_config *config =
		(struct ext_subaddress_config *) addrp->object.ext->context;
	const char *delim;

	delim = strstr(address->local_part, config->delimiter);

	if ( delim == NULL ) return address->local_part;

	return t_strdup_until(address->local_part, delim);
}

static const char *subaddress_detail_extract_from
(const struct sieve_address_part *addrp, const struct sieve_address *address)
{
	struct ext_subaddress_config *config =
		(struct ext_subaddress_config *) addrp->object.ext->context;
	const char *delim;

	if ( (delim=strstr(address->local_part, config->delimiter)) == NULL )
		return NULL;

	delim += strlen(config->delimiter);

	/* Just to be sure */
	if ( delim > (address->local_part + strlen(address->local_part)) )
		return NULL;

	return delim;
}

/*
 * Operand
 */

const struct sieve_address_part_def *ext_subaddress_parts[] = {
	&user_address_part, &detail_address_part
};

static const struct sieve_extension_objects ext_address_parts =
	SIEVE_EXT_DEFINE_ADDRESS_PARTS(ext_subaddress_parts);

static struct sieve_operand_def subaddress_operand = {
	"address-part",
	&subaddress_extension, 0,
	&sieve_address_part_operand_class,
	&ext_address_parts
};