New file.
Showing
1 changed file
with
273 additions
and
0 deletions
mailbox/filter.c
0 → 100644
1 | /* GNU mailutils - a suite of utilities for electronic mail | ||
2 | Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc. | ||
3 | |||
4 | This program is free software; you can redistribute it and/or modify | ||
5 | it under the terms of the GNU General Library Public License as published by | ||
6 | the Free Software Foundation; either version 2, or (at your option) | ||
7 | any later version. | ||
8 | |||
9 | This program is distributed in the hope that it will be useful, | ||
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | GNU Library General Public License for more details. | ||
13 | |||
14 | You should have received a copy of the GNU Library General Public License | ||
15 | along with this program; if not, write to the Free Software | ||
16 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ | ||
17 | |||
18 | /* Notes: | ||
19 | First draft: Alain Magloire. | ||
20 | |||
21 | */ | ||
22 | |||
23 | #ifdef HAVE_CONFIG_H | ||
24 | # include <config.h> | ||
25 | #endif | ||
26 | |||
27 | #include <errno.h> | ||
28 | #include <string.h> | ||
29 | #include <stdlib.h> | ||
30 | |||
31 | #include <filter0.h> | ||
32 | #include <mailutils/iterator.h> | ||
33 | |||
34 | static void | ||
35 | filter_destroy (stream_t stream) | ||
36 | { | ||
37 | filter_t filter = stream_get_owner (stream); | ||
38 | if (filter->_destroy) | ||
39 | filter->_destroy (filter); | ||
40 | if (filter->property) | ||
41 | property_destroy (&(filter->property), filter); | ||
42 | free (filter); | ||
43 | } | ||
44 | |||
45 | static int | ||
46 | filter_read (stream_t stream, char *buffer, size_t buflen, off_t offset, | ||
47 | size_t *nbytes) | ||
48 | { | ||
49 | filter_t filter = stream_get_owner (stream); | ||
50 | if (filter->_read && (filter->direction & MU_STREAM_READ | ||
51 | || filter->direction & MU_STREAM_RDWR)) | ||
52 | return filter->_read (filter, buffer, buflen, offset, nbytes); | ||
53 | return stream_read (filter->stream, buffer, buflen, offset, nbytes); | ||
54 | } | ||
55 | |||
56 | static int | ||
57 | filter_readline (stream_t stream, char *buffer, size_t buflen, | ||
58 | off_t offset, size_t *nbytes) | ||
59 | { | ||
60 | filter_t filter = stream_get_owner (stream); | ||
61 | if (filter->_readline && (filter->direction & MU_STREAM_READ | ||
62 | || filter->direction & MU_STREAM_RDWR)) | ||
63 | return filter->_readline (filter, buffer, buflen, offset, nbytes); | ||
64 | return stream_readline (filter->stream, buffer, buflen, offset, nbytes); | ||
65 | } | ||
66 | |||
67 | static int | ||
68 | filter_write (stream_t stream, const char *buffer, size_t buflen, | ||
69 | off_t offset, size_t *nbytes) | ||
70 | { | ||
71 | filter_t filter = stream_get_owner (stream); | ||
72 | if (filter->_write && (filter->direction & MU_STREAM_WRITE | ||
73 | || filter->direction & MU_STREAM_RDWR)) | ||
74 | return filter->_write (filter, buffer, buflen, offset, nbytes); | ||
75 | return stream_write (filter->stream, buffer, buflen, offset, nbytes); | ||
76 | } | ||
77 | |||
78 | static int | ||
79 | filter_open (stream_t stream, const char *filename, int port, int flags) | ||
80 | { | ||
81 | filter_t filter = stream_get_owner (stream); | ||
82 | stream_set_flags (stream, flags); | ||
83 | return stream_open (filter->stream, filename, port, flags); | ||
84 | } | ||
85 | |||
86 | static int | ||
87 | filter_truncate (stream_t stream, off_t len) | ||
88 | { | ||
89 | filter_t filter = stream_get_owner (stream); | ||
90 | return stream_truncate (filter->stream, len); | ||
91 | } | ||
92 | |||
93 | static int | ||
94 | filter_size (stream_t stream, off_t *psize) | ||
95 | { | ||
96 | filter_t filter = stream_get_owner (stream); | ||
97 | return stream_size (filter->stream, psize); | ||
98 | } | ||
99 | |||
100 | static int | ||
101 | filter_flush (stream_t stream) | ||
102 | { | ||
103 | filter_t filter = stream_get_owner(stream); | ||
104 | return stream_flush (filter->stream); | ||
105 | } | ||
106 | |||
107 | static int | ||
108 | filter_get_fd (stream_t stream, int *pfd) | ||
109 | { | ||
110 | filter_t filter = stream_get_owner (stream); | ||
111 | return stream_get_fd (filter->stream, pfd); | ||
112 | } | ||
113 | |||
114 | static int | ||
115 | filter_close (stream_t stream) | ||
116 | { | ||
117 | filter_t filter = stream_get_owner (stream); | ||
118 | return stream_close (filter->stream); | ||
119 | } | ||
120 | |||
121 | static int | ||
122 | filter_property (property_t property, const char *key, const char *value) | ||
123 | { | ||
124 | filter_t filter = property_get_owner (property); | ||
125 | (void)key; | ||
126 | if (value) | ||
127 | { | ||
128 | if (strcasecmp (value, "READ") == 0) | ||
129 | { | ||
130 | filter->direction = MU_STREAM_READ; | ||
131 | } | ||
132 | else if (strcasecmp (value, "WRITE") == 0) | ||
133 | { | ||
134 | filter->direction = MU_STREAM_WRITE; | ||
135 | } | ||
136 | else if (strcasecmp (value, "RDWR") == 0) | ||
137 | { | ||
138 | filter->direction = MU_STREAM_RDWR; | ||
139 | } | ||
140 | } | ||
141 | return 0; | ||
142 | } | ||
143 | |||
144 | /* NOTE: We will leak here since the monitor of the filter will never | ||
145 | be release. That's ok we can leave with this, it's only done once. */ | ||
146 | static list_t filter_list; | ||
147 | struct _monitor filter_monitor = MU_MONITOR_INITIALIZER; | ||
148 | |||
149 | int | ||
150 | filter_get_list (list_t *plist) | ||
151 | { | ||
152 | if (plist == NULL) | ||
153 | return EINVAL; | ||
154 | monitor_wrlock (&filter_monitor); | ||
155 | if (filter_list == NULL) | ||
156 | { | ||
157 | int status = list_create (&filter_list); | ||
158 | if (status != 0) | ||
159 | return status; | ||
160 | /* Default filters. */ | ||
161 | list_append (filter_list, base64_filter); | ||
162 | list_append (filter_list, qp_filter); | ||
163 | list_append (filter_list, binary_filter); | ||
164 | list_append (filter_list, bit8_filter); | ||
165 | list_append (filter_list, bit7_filter); | ||
166 | list_append (filter_list, rfc822_filter); | ||
167 | /* FIXME: add the default encodings? */ | ||
168 | } | ||
169 | *plist = filter_list; | ||
170 | monitor_unlock (&filter_monitor); | ||
171 | return 0; | ||
172 | } | ||
173 | |||
174 | int | ||
175 | filter_create (stream_t *pstream, stream_t stream, const char *name, | ||
176 | int type, int direction) | ||
177 | { | ||
178 | iterator_t iterator = NULL; | ||
179 | filter_record_t filter_record = NULL; | ||
180 | int (*f_init) __P ((filter_t)) = NULL; | ||
181 | int found = 0; | ||
182 | int status; | ||
183 | list_t list = NULL; | ||
184 | |||
185 | if (pstream == NULL || stream == NULL || name == NULL) | ||
186 | return EINVAL; | ||
187 | |||
188 | filter_get_list (&list); | ||
189 | status = iterator_create (&iterator, list); | ||
190 | if (status != 0) | ||
191 | return status; | ||
192 | |||
193 | for (iterator_first (iterator); !iterator_is_done (iterator); | ||
194 | iterator_next (iterator)) | ||
195 | { | ||
196 | iterator_current (iterator, (void **)&filter_record); | ||
197 | if ((filter_record->_is_filter | ||
198 | && filter_record->_is_filter (filter_record, name)) | ||
199 | || (strcasecmp (filter_record->name, name) == 0)) | ||
200 | { | ||
201 | found = 1; | ||
202 | if (filter_record->_get_filter) | ||
203 | filter_record->_get_filter (filter_record, &f_init); | ||
204 | else | ||
205 | f_init = filter_record->_filter; | ||
206 | break; | ||
207 | } | ||
208 | } | ||
209 | iterator_destroy (&iterator); | ||
210 | |||
211 | if (found) | ||
212 | { | ||
213 | int flags = 0; | ||
214 | filter_t filter; | ||
215 | |||
216 | filter = calloc (1, sizeof (*filter)); | ||
217 | if (filter == NULL) | ||
218 | return ENOMEM; | ||
219 | |||
220 | stream_get_flags (stream, &flags); | ||
221 | status = stream_create (pstream, flags | MU_STREAM_NO_CHECK, filter); | ||
222 | if (status != 0) | ||
223 | { | ||
224 | free (filter); | ||
225 | return status; | ||
226 | } | ||
227 | |||
228 | filter->stream = stream; | ||
229 | filter->filter_stream = *pstream; | ||
230 | filter->direction = (direction == 0) ? MU_STREAM_READ : direction; | ||
231 | filter->type = type; | ||
232 | |||
233 | status = property_create (&(filter->property), filter); | ||
234 | if (status != 0) | ||
235 | { | ||
236 | stream_destroy (pstream, filter); | ||
237 | free (filter); | ||
238 | return status; | ||
239 | } | ||
240 | property_add_defaults (filter->property, "DIRECTION", | ||
241 | ((filter->direction == MU_STREAM_WRITE) ? "WRITE": | ||
242 | (filter->direction == MU_STREAM_RDWR) ? "RDWR" : | ||
243 | "READ"), filter_property, NULL, filter); | ||
244 | property_add_defaults (filter->property, "NAME", filter_record->name, | ||
245 | NULL, NULL, filter); | ||
246 | stream_set_property (*pstream, filter->property, filter); | ||
247 | |||
248 | if (f_init != NULL) | ||
249 | { | ||
250 | status = f_init (filter); | ||
251 | if (status != 0) | ||
252 | { | ||
253 | stream_destroy (pstream, filter); | ||
254 | free (filter); | ||
255 | return status; | ||
256 | } | ||
257 | } | ||
258 | |||
259 | stream_set_open (*pstream, filter_open, filter ); | ||
260 | stream_set_close (*pstream, filter_close, filter ); | ||
261 | stream_set_read (*pstream, filter_read, filter); | ||
262 | stream_set_readline (*pstream, filter_readline, filter); | ||
263 | stream_set_write (*pstream, filter_write, filter); | ||
264 | stream_set_fd (*pstream, filter_get_fd, filter ); | ||
265 | stream_set_truncate (*pstream, filter_truncate, filter ); | ||
266 | stream_set_size (*pstream, filter_size, filter ); | ||
267 | stream_set_flush (*pstream, filter_flush, filter ); | ||
268 | stream_set_destroy (*pstream, filter_destroy, filter); | ||
269 | } | ||
270 | else | ||
271 | status = ENOENT; | ||
272 | return status; | ||
273 | } |
-
Please register or sign in to post a comment