Introduction of the notion of filter_t object takes a stream and
perform some filtering on it. All the decoding streams will move to this i.e. quoted-printable, base64 etc .. This scheme will also permit users to add to the list new filters. Still work in progress. * mailbox/Makefile.am : Add filter.c filter_rfc822.c. * mailbox/body.c ( : When creating a floating body i.e creating a temporary file, the stream was not "own" by the body_t. (_body_get_fd): Likewised. (_body_read):_ Likewised. (_body_readline): Likewised. (_body_write): Likewised. (_body_truncate): Likewised. (_body_size): Likewised. (_body_flush): Likewised. * mailbox/folder_imap.c (imap_literal_string): Check if the callback.buffer is NULL. (imap_body): Do no set the callback.type if "FIELDS" is part of the string. * mailbox/header.c: Remove the support for RFC822 it will be part of the filter_t object. * mailbox/mbx_mbox.c: Likewised. * mailbox/mailbox.c (mailbox_size): Rename to mailbox_get_size(). * mailbox/stream.c (stream_is_seekable): New function. (stream_set_property): New function. (stream_get_property): New function. * mailbox/trans_stream.c: Beautify.
Showing
22 changed files
with
606 additions
and
445 deletions
... | @@ -20,6 +20,8 @@ body.c \ | ... | @@ -20,6 +20,8 @@ body.c \ |
20 | debug.c \ | 20 | debug.c \ |
21 | envelope.c \ | 21 | envelope.c \ |
22 | file_stream.c \ | 22 | file_stream.c \ |
23 | filter.c \ | ||
24 | filter_rfc822.c \ | ||
23 | folder.c \ | 25 | folder.c \ |
24 | folder_imap.c \ | 26 | folder_imap.c \ |
25 | folder_mbox.c \ | 27 | folder_mbox.c \ | ... | ... |
... | @@ -32,6 +32,13 @@ | ... | @@ -32,6 +32,13 @@ |
32 | #include <body0.h> | 32 | #include <body0.h> |
33 | 33 | ||
34 | static int lazy_create __P ((body_t)); | 34 | static int lazy_create __P ((body_t)); |
35 | static int _body_flush __P ((stream_t)); | ||
36 | static int _body_get_fd __P ((stream_t, int *)); | ||
37 | static int _body_read __P ((stream_t, char *, size_t, off_t, size_t *)); | ||
38 | static int _body_readline __P ((stream_t, char *, size_t, off_t, size_t *)); | ||
39 | static int _body_write __P ((stream_t, const char *, size_t, off_t, size_t *)); | ||
40 | static int _body_truncate __P ((stream_t, off_t)); | ||
41 | static int _body_size __P ((stream_t, off_t *)); | ||
35 | 42 | ||
36 | int | 43 | int |
37 | body_create (body_t *pbody, void *owner) | 44 | body_create (body_t *pbody, void *owner) |
... | @@ -60,10 +67,23 @@ body_destroy (body_t *pbody, void *owner) | ... | @@ -60,10 +67,23 @@ body_destroy (body_t *pbody, void *owner) |
60 | { | 67 | { |
61 | if (body->filename) | 68 | if (body->filename) |
62 | { | 69 | { |
70 | /* FIXME: should we do this? */ | ||
63 | remove (body->filename); | 71 | remove (body->filename); |
64 | free (body->filename); | 72 | free (body->filename); |
65 | } | 73 | } |
74 | |||
75 | if (body->stream) | ||
66 | stream_destroy (&(body->stream), body); | 76 | stream_destroy (&(body->stream), body); |
77 | |||
78 | if (body->fstream) | ||
79 | { | ||
80 | stream_close (body->fstream); | ||
81 | stream_destroy (&(body->fstream), NULL); | ||
82 | } | ||
83 | |||
84 | if (body->property) | ||
85 | property_destroy (&(body->property), body); | ||
86 | |||
67 | free (body); | 87 | free (body); |
68 | } | 88 | } |
69 | *pbody = NULL; | 89 | *pbody = NULL; |
... | @@ -93,6 +113,33 @@ body_clear_modified (body_t body) | ... | @@ -93,6 +113,33 @@ body_clear_modified (body_t body) |
93 | } | 113 | } |
94 | 114 | ||
95 | int | 115 | int |
116 | body_set_property (body_t body, property_t property, void *owner) | ||
117 | { | ||
118 | if (body == NULL) | ||
119 | return EINVAL; | ||
120 | if (body->owner != owner) | ||
121 | return EACCES; | ||
122 | property_destroy (&(body->property), body); | ||
123 | body->property = property; | ||
124 | return 0; | ||
125 | } | ||
126 | |||
127 | int | ||
128 | body_get_property (body_t body, property_t *pproperty) | ||
129 | { | ||
130 | if (body == NULL || pproperty == NULL) | ||
131 | return EINVAL; | ||
132 | if (body->property == NULL) | ||
133 | { | ||
134 | int status = property_create (&(body->property), body); | ||
135 | if (status != 0) | ||
136 | return status; | ||
137 | } | ||
138 | *pproperty = body->property; | ||
139 | return 0; | ||
140 | } | ||
141 | |||
142 | int | ||
96 | body_get_filename (body_t body, char *filename, size_t len, size_t *pn) | 143 | body_get_filename (body_t body, char *filename, size_t len, size_t *pn) |
97 | { | 144 | { |
98 | int n = 0; | 145 | int n = 0; |
... | @@ -120,19 +167,27 @@ body_get_stream (body_t body, stream_t *pstream) | ... | @@ -120,19 +167,27 @@ body_get_stream (body_t body, stream_t *pstream) |
120 | 167 | ||
121 | if (body->stream == NULL) | 168 | if (body->stream == NULL) |
122 | { | 169 | { |
123 | stream_t stream; | ||
124 | int fd; | 170 | int fd; |
125 | int status = file_stream_create (&stream); | 171 | int status = stream_create (&(body->stream), MU_STREAM_RDWR, body); |
172 | if (status != 0) | ||
173 | return status; | ||
174 | status = file_stream_create (&(body->fstream)); | ||
126 | if (status != 0) | 175 | if (status != 0) |
127 | return status; | 176 | return status; |
128 | fd = lazy_create (body); | 177 | fd = lazy_create (body); |
129 | if (fd == -1) | 178 | if (fd == -1) |
130 | return errno; | 179 | return errno; |
131 | status = stream_open (stream, body->filename, 0, MU_STREAM_RDWR); | 180 | status = stream_open (body->fstream, body->filename, 0, MU_STREAM_RDWR); |
132 | close (fd); | 181 | close (fd); |
133 | if (status != 0) | 182 | if (status != 0) |
134 | return status; | 183 | return status; |
135 | body->stream = stream; | 184 | stream_set_fd (body->stream, _body_get_fd, body); |
185 | stream_set_read (body->stream, _body_read, body); | ||
186 | stream_set_readline (body->stream, _body_readline, body); | ||
187 | stream_set_write (body->stream, _body_write, body); | ||
188 | stream_set_truncate (body->stream, _body_truncate, body); | ||
189 | stream_set_size (body->stream, _body_size, body); | ||
190 | stream_set_flush (body->stream, _body_flush, body); | ||
136 | } | 191 | } |
137 | *pstream = body->stream; | 192 | *pstream = body->stream; |
138 | return 0; | 193 | return 0; |
... | @@ -223,6 +278,55 @@ body_set_size (body_t body, int (*_size)(body_t, size_t*) , void *owner) | ... | @@ -223,6 +278,55 @@ body_set_size (body_t body, int (*_size)(body_t, size_t*) , void *owner) |
223 | return 0; | 278 | return 0; |
224 | } | 279 | } |
225 | 280 | ||
281 | static int | ||
282 | _body_get_fd (stream_t stream, int *fd) | ||
283 | { | ||
284 | body_t body = stream_get_owner (stream); | ||
285 | return stream_get_fd (body->fstream, fd); | ||
286 | } | ||
287 | |||
288 | static int | ||
289 | _body_read (stream_t stream, char *buffer, size_t n, off_t off, size_t *pn) | ||
290 | { | ||
291 | body_t body = stream_get_owner (stream); | ||
292 | return stream_read (body->fstream, buffer, n, off, pn); | ||
293 | } | ||
294 | |||
295 | static int | ||
296 | _body_readline (stream_t stream, char *buffer, size_t n, off_t off, size_t *pn) | ||
297 | { | ||
298 | body_t body = stream_get_owner (stream); | ||
299 | return stream_readline (body->fstream, buffer, n, off, pn); | ||
300 | } | ||
301 | |||
302 | static int | ||
303 | _body_write (stream_t stream, const char *buf, size_t n, off_t off, size_t *pn) | ||
304 | { | ||
305 | body_t body = stream_get_owner (stream); | ||
306 | return stream_write (body->fstream, buf, n, off, pn); | ||
307 | } | ||
308 | |||
309 | static int | ||
310 | _body_truncate (stream_t stream, off_t n) | ||
311 | { | ||
312 | body_t body = stream_get_owner (stream); | ||
313 | return stream_truncate (body->fstream, n); | ||
314 | } | ||
315 | |||
316 | static int | ||
317 | _body_size (stream_t stream, off_t *size) | ||
318 | { | ||
319 | body_t body = stream_get_owner (stream); | ||
320 | return stream_size (body->fstream, size); | ||
321 | } | ||
322 | |||
323 | static int | ||
324 | _body_flush (stream_t stream) | ||
325 | { | ||
326 | body_t body = stream_get_owner (stream); | ||
327 | return stream_flush (body->fstream); | ||
328 | } | ||
329 | |||
226 | #ifndef P_tmpdir | 330 | #ifndef P_tmpdir |
227 | # define P_tmpdir "/tmp" | 331 | # define P_tmpdir "/tmp" |
228 | #endif | 332 | #endif | ... | ... |
mailbox/filter_rfc822.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 | /* First draft by Alain Magloire */ | ||
19 | |||
20 | #ifdef HAVE_CONFIG_H | ||
21 | # include <config.h> | ||
22 | #endif | ||
23 | |||
24 | #include <stdlib.h> | ||
25 | #include <errno.h> | ||
26 | #ifdef HAVE_PTHREAD_H | ||
27 | # define _XOPEN_SOURCE 500 | ||
28 | # include <pthread.h> | ||
29 | #endif | ||
30 | |||
31 | #include <mailutils/filter.h> | ||
32 | #include <mailutils/property.h> | ||
33 | |||
34 | static int rfc822_property __P ((property_t, const char *, const char *)); | ||
35 | static int rfc822_init __P ((filter_t)); | ||
36 | static void rfc822_destroy __P ((filter_t)); | ||
37 | static int rfc822_read __P ((filter_t, char *, size_t, off_t, size_t *)); | ||
38 | static int rfc822_readline __P ((filter_t, char *, size_t, off_t, size_t *)); | ||
39 | static int rfc822_read0 __P ((filter_t, char *, size_t, off_t, size_t *, int)); | ||
40 | |||
41 | struct rfc822 | ||
42 | { | ||
43 | off_t r_offset; /* rfc822 offset. */ | ||
44 | off_t s_offset; /* stream offset. */ | ||
45 | size_t lines; | ||
46 | int residue; | ||
47 | }; | ||
48 | |||
49 | static struct _filter _rfc822_filter = | ||
50 | { | ||
51 | "RFC822", | ||
52 | rfc822_init, | ||
53 | rfc822_read, | ||
54 | rfc822_readline, | ||
55 | NULL, | ||
56 | rfc822_destroy, | ||
57 | NULL, | ||
58 | NULL, | ||
59 | NULL, | ||
60 | 0, | ||
61 | NULL | ||
62 | }; | ||
63 | |||
64 | /* Exported. */ | ||
65 | filter_t rfc822_filter = &_rfc822_filter; | ||
66 | |||
67 | static int | ||
68 | rfc822_property (property_t property, const char *key, const char *value) | ||
69 | { | ||
70 | filter_t filter = property_get_owner (property); | ||
71 | struct rfc822 *rfc822 = filter->data; | ||
72 | (void)key; | ||
73 | rfc822->lines = strtoul (value, NULL, 10); | ||
74 | return 0; | ||
75 | } | ||
76 | |||
77 | static int | ||
78 | rfc822_init (filter_t filter) | ||
79 | { | ||
80 | property_t property; | ||
81 | int status; | ||
82 | filter->data = calloc (1, sizeof (struct rfc822)); | ||
83 | if (filter->data == NULL) | ||
84 | return ENOMEM; | ||
85 | /* We are interested in this property. */ | ||
86 | if ((status = stream_get_property (filter->filter_stream, &property) != 0) | ||
87 | || (status = property_add_defaults (property, "LINES", "0", | ||
88 | rfc822_property, NULL, filter)) != 0) | ||
89 | { | ||
90 | free (filter->data); | ||
91 | filter->data = NULL; | ||
92 | return status; | ||
93 | } | ||
94 | return 0; | ||
95 | } | ||
96 | |||
97 | static void | ||
98 | rfc822_destroy (filter_t filter) | ||
99 | { | ||
100 | if (filter->data) | ||
101 | free (filter->data); | ||
102 | } | ||
103 | |||
104 | static int | ||
105 | rfc822_read (filter_t filter, char *buffer, size_t buflen, | ||
106 | off_t off, size_t *pnread) | ||
107 | { | ||
108 | return rfc822_read0 (filter, buffer, buflen, off, pnread, 0); | ||
109 | } | ||
110 | |||
111 | static int | ||
112 | rfc822_readline (filter_t filter, char *buffer, size_t buflen, | ||
113 | off_t off, size_t *pnread) | ||
114 | { | ||
115 | return rfc822_read0 (filter, buffer, buflen, off, pnread, 1); | ||
116 | } | ||
117 | |||
118 | /* RFC 822 converter "\n" --> "\r\n" | ||
119 | We maintain to offset, the rfc822 offset (r_offset) and the offset of | ||
120 | the stream (s_offset). If they do not match we go back as for as possible | ||
121 | and start to read by 1 'till we reach the current offset. */ | ||
122 | |||
123 | static int | ||
124 | rfc822_read0 (filter_t filter, char *buffer, size_t buflen, | ||
125 | off_t off, size_t *pnread, int isreadline) | ||
126 | { | ||
127 | size_t total = 0; | ||
128 | int status = 0; | ||
129 | struct rfc822 *rfc822 = filter->data; | ||
130 | |||
131 | /* Catch up i.e bring us to the current offset. */ | ||
132 | if (rfc822->r_offset != off) | ||
133 | { | ||
134 | rfc822->r_offset = off - rfc822->lines; | ||
135 | rfc822->residue = 0; | ||
136 | |||
137 | if (rfc822->r_offset < 0) | ||
138 | rfc822->r_offset = 0; | ||
139 | rfc822->s_offset = rfc822->r_offset; | ||
140 | |||
141 | while (rfc822->r_offset < off) | ||
142 | { | ||
143 | char c; | ||
144 | size_t n = 0; | ||
145 | status = stream_read (filter->stream, &c, 1, rfc822->s_offset, &n); | ||
146 | if (status != 0) | ||
147 | return status; | ||
148 | if (n == 0) | ||
149 | break; | ||
150 | if (c == '\n') | ||
151 | { | ||
152 | rfc822->r_offset++; | ||
153 | if (rfc822->r_offset == off) | ||
154 | { | ||
155 | rfc822->residue = 1; | ||
156 | break; | ||
157 | } | ||
158 | } | ||
159 | rfc822->r_offset++; | ||
160 | rfc822->s_offset++; | ||
161 | } | ||
162 | } | ||
163 | |||
164 | do | ||
165 | { | ||
166 | size_t nread = 0; | ||
167 | status = stream_readline (filter->stream, buffer, buflen, | ||
168 | rfc822->s_offset, &nread); | ||
169 | if (status != 0) | ||
170 | return status; | ||
171 | if (nread == 0) | ||
172 | break; | ||
173 | rfc822->r_offset += nread; | ||
174 | rfc822->s_offset += nread; | ||
175 | total += nread; | ||
176 | buflen -= nread; | ||
177 | if (buffer[nread - 1] == '\n') | ||
178 | { | ||
179 | if (!rfc822->residue) | ||
180 | { | ||
181 | buffer[nread - 1] = '\r'; | ||
182 | if (buflen == 0) | ||
183 | { | ||
184 | rfc822->residue = 1; | ||
185 | break; | ||
186 | } | ||
187 | buffer[nread] = '\n'; | ||
188 | buflen--; | ||
189 | nread++; | ||
190 | total++; | ||
191 | rfc822->r_offset++; | ||
192 | } | ||
193 | else | ||
194 | rfc822->residue = 0; | ||
195 | } | ||
196 | buffer += nread; | ||
197 | } while (buflen > 0 || !isreadline); | ||
198 | |||
199 | if (isreadline) | ||
200 | *buffer = '\0'; | ||
201 | |||
202 | if (pnread) | ||
203 | *pnread = total; | ||
204 | return status; | ||
205 | } |
... | @@ -756,11 +756,11 @@ imap_literal_string (f_imap_t f_imap, char **ptr) | ... | @@ -756,11 +756,11 @@ imap_literal_string (f_imap_t f_imap, char **ptr) |
756 | f_imap->ptr = f_imap->buffer; | 756 | f_imap->ptr = f_imap->buffer; |
757 | 757 | ||
758 | /* How much ? */ | 758 | /* How much ? */ |
759 | len0= len = f_imap->nl - f_imap->buffer; | 759 | len0 = len = f_imap->nl - f_imap->buffer; |
760 | /* Check if the last read did not finish on a line, if yes do not copy in | 760 | /* Check if the last read did not finish on a line, if yes do not copy in |
761 | callback buffer the terminating sequence ")\r\n". We are doing this | 761 | callback buffer the terminating sequence ")\r\n". We are doing this |
762 | by checking if the amount(total) we got so far + the len of the line | 762 | by checking if the amount(total) we got so far + the len of the line |
763 | +1 (taking to account the strip '\r'). */ | 763 | +1 (taking to account the strip '\r') goes behond the request. */ |
764 | if ((total + len + 1) > f_imap->callback.nleft) | 764 | if ((total + len + 1) > f_imap->callback.nleft) |
765 | { | 765 | { |
766 | len0 = len = f_imap->callback.nleft - total; | 766 | len0 = len = f_imap->callback.nleft - total; |
... | @@ -777,6 +777,7 @@ imap_literal_string (f_imap_t f_imap, char **ptr) | ... | @@ -777,6 +777,7 @@ imap_literal_string (f_imap_t f_imap, char **ptr) |
777 | /* Check how much we can fill the callback buffer. */ | 777 | /* Check how much we can fill the callback buffer. */ |
778 | int x = (f_imap->callback.buflen - f_imap->callback.total) - len0; | 778 | int x = (f_imap->callback.buflen - f_imap->callback.total) - len0; |
779 | x = (x >= 0) ? len0 : (x + len0); | 779 | x = (x >= 0) ? len0 : (x + len0); |
780 | if (f_imap->callback.buffer) | ||
780 | memcpy (f_imap->callback.buffer + f_imap->callback.total, | 781 | memcpy (f_imap->callback.buffer + f_imap->callback.total, |
781 | f_imap->buffer, x); | 782 | f_imap->buffer, x); |
782 | f_imap->callback.total += x; | 783 | f_imap->callback.total += x; |
... | @@ -838,7 +839,8 @@ imap_quoted_string (f_imap_t f_imap, char **ptr) | ... | @@ -838,7 +839,8 @@ imap_quoted_string (f_imap_t f_imap, char **ptr) |
838 | f_imap->callback.total = *ptr - bquote; | 839 | f_imap->callback.total = *ptr - bquote; |
839 | /* Fill the call back buffer. The if is redundant there should always | 840 | /* Fill the call back buffer. The if is redundant there should always |
840 | be enough room since the request is base on the buffer size. */ | 841 | be enough room since the request is base on the buffer size. */ |
841 | if (f_imap->callback.total <= f_imap->callback.buflen) | 842 | if (f_imap->callback.total <= f_imap->callback.buflen |
843 | && f_imap->callback.buffer) | ||
842 | memcpy (f_imap->callback.buffer, bquote, f_imap->callback.total); | 844 | memcpy (f_imap->callback.buffer, bquote, f_imap->callback.total); |
843 | if (**ptr == '"') | 845 | if (**ptr == '"') |
844 | (*ptr)++; | 846 | (*ptr)++; |
... | @@ -1238,6 +1240,7 @@ imap_body (f_imap_t f_imap, char **ptr) | ... | @@ -1238,6 +1240,7 @@ imap_body (f_imap_t f_imap, char **ptr) |
1238 | if (**ptr == '[') | 1240 | if (**ptr == '[') |
1239 | { | 1241 | { |
1240 | char *sep = strchr (*ptr, ']'); | 1242 | char *sep = strchr (*ptr, ']'); |
1243 | (*ptr)++; /* Move pass the '[' */ | ||
1241 | if (sep) | 1244 | if (sep) |
1242 | { | 1245 | { |
1243 | size_t len = sep - *ptr; | 1246 | size_t len = sep - *ptr; |
... | @@ -1250,20 +1253,22 @@ imap_body (f_imap_t f_imap, char **ptr) | ... | @@ -1250,20 +1253,22 @@ imap_body (f_imap_t f_imap, char **ptr) |
1250 | if (isalpha((unsigned)*p)) | 1253 | if (isalpha((unsigned)*p)) |
1251 | *p = toupper ((unsigned)*p); | 1254 | *p = toupper ((unsigned)*p); |
1252 | /* Check to see the callback type to update the line count. */ | 1255 | /* Check to see the callback type to update the line count. */ |
1253 | if (strstr (section, "MIME") | 1256 | if (!strstr (section, "FIELD")) |
1254 | || (strstr (section, "HEADER") && ! strstr (section, "FIELD"))) | 1257 | { |
1258 | if (strstr (section, "MIME") || (strstr (section, "HEADER"))) | ||
1255 | { | 1259 | { |
1256 | f_imap->callback.type = IMAP_HEADER; | 1260 | f_imap->callback.type = IMAP_HEADER; |
1257 | } | 1261 | } |
1258 | else if (strstr (section, "TEXT")) | 1262 | else if (strstr (section, "TEXT") || len > 0) |
1259 | { | 1263 | { |
1260 | f_imap->callback.type = IMAP_BODY; | 1264 | f_imap->callback.type = IMAP_BODY; |
1261 | } | 1265 | } |
1262 | else if (len == 1) /* body[] */ | 1266 | else if (len == 0) /* body[] */ |
1263 | { | 1267 | { |
1264 | f_imap->callback.type = IMAP_MESSAGE; | 1268 | f_imap->callback.type = IMAP_MESSAGE; |
1265 | } | 1269 | } |
1266 | sep++; | 1270 | } |
1271 | sep++; /* Move pass the ']' */ | ||
1267 | *ptr = sep; | 1272 | *ptr = sep; |
1268 | } | 1273 | } |
1269 | } | 1274 | } |
... | @@ -1586,9 +1591,6 @@ imap_readline (f_imap_t f_imap) | ... | @@ -1586,9 +1591,6 @@ imap_readline (f_imap_t f_imap) |
1586 | while (f_imap->nl == NULL); | 1591 | while (f_imap->nl == NULL); |
1587 | 1592 | ||
1588 | /* Conversion \r\n --> \n\0 */ | 1593 | /* Conversion \r\n --> \n\0 */ |
1589 | /**/ | ||
1590 | if (f_imap->selected == NULL | ||
1591 | || f_imap->selected->mailbox->properties[PROP_RFC822].value == 0) | ||
1592 | if (f_imap->nl > f_imap->buffer) | 1594 | if (f_imap->nl > f_imap->buffer) |
1593 | { | 1595 | { |
1594 | *(f_imap->nl - 1) = '\n'; | 1596 | *(f_imap->nl - 1) = '\n'; | ... | ... |
... | @@ -413,7 +413,6 @@ header_get_value (header_t header, const char *name, char *buffer, | ... | @@ -413,7 +413,6 @@ header_get_value (header_t header, const char *name, char *buffer, |
413 | size_t name_len; | 413 | size_t name_len; |
414 | size_t total = 0, fn_len = 0, fv_len = 0; | 414 | size_t total = 0, fn_len = 0, fv_len = 0; |
415 | size_t threshold; | 415 | size_t threshold; |
416 | int rfc822 = 0; | ||
417 | int err = 0; | 416 | int err = 0; |
418 | 417 | ||
419 | if (header == NULL || name == NULL) | 418 | if (header == NULL || name == NULL) |
... | @@ -456,10 +455,6 @@ header_get_value (header_t header, const char *name, char *buffer, | ... | @@ -456,10 +455,6 @@ header_get_value (header_t header, const char *name, char *buffer, |
456 | return err; | 455 | return err; |
457 | } | 456 | } |
458 | 457 | ||
459 | /* Do they want rfc822 format */ | ||
460 | if (header->property) | ||
461 | rfc822 = property_is_set (header->property, "RFC822"); | ||
462 | |||
463 | /* We set the threshold to be 1 less for the null. */ | 458 | /* We set the threshold to be 1 less for the null. */ |
464 | threshold = --buflen; | 459 | threshold = --buflen; |
465 | 460 | ||
... | @@ -481,24 +476,6 @@ header_get_value (header_t header, const char *name, char *buffer, | ... | @@ -481,24 +476,6 @@ header_get_value (header_t header, const char *name, char *buffer, |
481 | if (buffer && threshold > 0) | 476 | if (buffer && threshold > 0) |
482 | { | 477 | { |
483 | buflen = (fv_len < threshold) ? fv_len : threshold; | 478 | buflen = (fv_len < threshold) ? fv_len : threshold; |
484 | if (rfc822) | ||
485 | { | ||
486 | /* Convert to \r\n */ | ||
487 | char *s = header->hdr[i].fv; | ||
488 | size_t j; | ||
489 | for (j = 0; j < buflen; s++, j++) | ||
490 | { | ||
491 | if (*s == '\n') | ||
492 | { | ||
493 | buffer[j] = '\r'; | ||
494 | /* Side effect. */ | ||
495 | if (++j >= buflen) | ||
496 | break; | ||
497 | } | ||
498 | buffer[j] = *s; | ||
499 | } | ||
500 | } | ||
501 | else | ||
502 | memcpy (buffer, header->hdr[i].fv, buflen); | 479 | memcpy (buffer, header->hdr[i].fv, buflen); |
503 | buffer += buflen; | 480 | buffer += buflen; |
504 | threshold -= buflen; | 481 | threshold -= buflen; |
... | @@ -679,15 +656,7 @@ header_size (header_t header, size_t *psize) | ... | @@ -679,15 +656,7 @@ header_size (header_t header, size_t *psize) |
679 | } | 656 | } |
680 | 657 | ||
681 | if (psize) | 658 | if (psize) |
682 | { | ||
683 | *psize = header->blurb_len; | 659 | *psize = header->blurb_len; |
684 | if (property_is_set (header->property, "RFC822")) | ||
685 | { | ||
686 | size_t lines = 0; | ||
687 | header_lines (header, &lines); | ||
688 | *psize += lines; | ||
689 | } | ||
690 | } | ||
691 | return 0; | 660 | return 0; |
692 | } | 661 | } |
693 | 662 | ||
... | @@ -708,6 +677,12 @@ header_get_property (header_t header, property_t *pp) | ... | @@ -708,6 +677,12 @@ header_get_property (header_t header, property_t *pp) |
708 | { | 677 | { |
709 | if (header == NULL || pp == NULL) | 678 | if (header == NULL || pp == NULL) |
710 | return EINVAL; | 679 | return EINVAL; |
680 | if (header->property == NULL) | ||
681 | { | ||
682 | int status = property_create (&(header->property), header); | ||
683 | if (status != 0) | ||
684 | return status; | ||
685 | } | ||
711 | *pp = header->property; | 686 | *pp = header->property; |
712 | return 0; | 687 | return 0; |
713 | } | 688 | } |
... | @@ -874,7 +849,6 @@ header_read (stream_t is, char *buf, size_t buflen, off_t off, size_t *pnread) | ... | @@ -874,7 +849,6 @@ header_read (stream_t is, char *buf, size_t buflen, off_t off, size_t *pnread) |
874 | { | 849 | { |
875 | int len; | 850 | int len; |
876 | header_t header = stream_get_owner (is); | 851 | header_t header = stream_get_owner (is); |
877 | int rfc822 = 0; | ||
878 | 852 | ||
879 | if (is == NULL || header == NULL) | 853 | if (is == NULL || header == NULL) |
880 | return EINVAL; | 854 | return EINVAL; |
... | @@ -894,44 +868,6 @@ header_read (stream_t is, char *buf, size_t buflen, off_t off, size_t *pnread) | ... | @@ -894,44 +868,6 @@ header_read (stream_t is, char *buf, size_t buflen, off_t off, size_t *pnread) |
894 | return err; | 868 | return err; |
895 | } | 869 | } |
896 | 870 | ||
897 | if (header->property) | ||
898 | rfc822 = property_is_set (header->property, "RFC822"); | ||
899 | |||
900 | if (rfc822) | ||
901 | { | ||
902 | size_t j; | ||
903 | int residue = 0; | ||
904 | char *s = header->blurb; | ||
905 | char *e = header->blurb + header->blurb_len; | ||
906 | /* Get to the offset. */ | ||
907 | for (j = 0; j < (size_t)off && s < e; j++, s++) | ||
908 | { | ||
909 | if (*s == '\n') | ||
910 | { | ||
911 | if (++j >= (size_t)off) | ||
912 | { | ||
913 | residue = 1; | ||
914 | break; | ||
915 | } | ||
916 | } | ||
917 | } | ||
918 | if (residue) | ||
919 | buf[0] = '\r'; | ||
920 | /* Copy. */ | ||
921 | for (j = residue ; j < buflen && s < e; j++, s++) | ||
922 | { | ||
923 | if (*s == '\n') | ||
924 | { | ||
925 | buf[j] = '\r'; | ||
926 | if (++j >= buflen) | ||
927 | break; | ||
928 | } | ||
929 | buf[j] = *s; | ||
930 | } | ||
931 | len = j; | ||
932 | } | ||
933 | else | ||
934 | { | ||
935 | len = header->blurb_len - off; | 871 | len = header->blurb_len - off; |
936 | if (len > 0) | 872 | if (len > 0) |
937 | { | 873 | { |
... | @@ -940,7 +876,6 @@ header_read (stream_t is, char *buf, size_t buflen, off_t off, size_t *pnread) | ... | @@ -940,7 +876,6 @@ header_read (stream_t is, char *buf, size_t buflen, off_t off, size_t *pnread) |
940 | } | 876 | } |
941 | else | 877 | else |
942 | len = 0; | 878 | len = 0; |
943 | } | ||
944 | 879 | ||
945 | if (pnread) | 880 | if (pnread) |
946 | *pnread = len; | 881 | *pnread = len; |
... | @@ -952,7 +887,6 @@ header_readline (stream_t is, char *buf, size_t buflen, off_t off, size_t *pn) | ... | @@ -952,7 +887,6 @@ header_readline (stream_t is, char *buf, size_t buflen, off_t off, size_t *pn) |
952 | { | 887 | { |
953 | int len; | 888 | int len; |
954 | header_t header = stream_get_owner (is); | 889 | header_t header = stream_get_owner (is); |
955 | int rfc822 = 0; | ||
956 | 890 | ||
957 | if (is == NULL || header == NULL) | 891 | if (is == NULL || header == NULL) |
958 | return EINVAL; | 892 | return EINVAL; |
... | @@ -972,42 +906,8 @@ header_readline (stream_t is, char *buf, size_t buflen, off_t off, size_t *pn) | ... | @@ -972,42 +906,8 @@ header_readline (stream_t is, char *buf, size_t buflen, off_t off, size_t *pn) |
972 | return err; | 906 | return err; |
973 | } | 907 | } |
974 | 908 | ||
975 | if (header->property) | ||
976 | rfc822 = property_is_set (header->property, "RFC822"); | ||
977 | |||
978 | buflen--; /* Space for the null. */ | 909 | buflen--; /* Space for the null. */ |
979 | 910 | ||
980 | if (rfc822) | ||
981 | { | ||
982 | size_t j; | ||
983 | char *s = header->blurb; | ||
984 | char *e = header->blurb + header->blurb_len; | ||
985 | char *nl; | ||
986 | /* Get to the offset. */ | ||
987 | for (j = 0; j < (size_t)off && s <= e; j++, s++) | ||
988 | { | ||
989 | if (*s == '\n') | ||
990 | { | ||
991 | if (++j >= (size_t)off) | ||
992 | break; | ||
993 | } | ||
994 | } | ||
995 | /* Copy. */ | ||
996 | e = (nl = memchr (s, '\n', e - s)) ? nl : e; | ||
997 | for (j = 0 ; j < buflen && s <= e; j++, s++) | ||
998 | { | ||
999 | if (*s == '\n') | ||
1000 | { | ||
1001 | buf[j] = '\r'; | ||
1002 | if (++j >= buflen) | ||
1003 | break; | ||
1004 | } | ||
1005 | buf[j] = *s; | ||
1006 | } | ||
1007 | len = j; | ||
1008 | } | ||
1009 | else | ||
1010 | { | ||
1011 | len = header->blurb_len - off; | 911 | len = header->blurb_len - off; |
1012 | if (len > 0) | 912 | if (len > 0) |
1013 | { | 913 | { |
... | @@ -1019,7 +919,6 @@ header_readline (stream_t is, char *buf, size_t buflen, off_t off, size_t *pn) | ... | @@ -1019,7 +919,6 @@ header_readline (stream_t is, char *buf, size_t buflen, off_t off, size_t *pn) |
1019 | } | 919 | } |
1020 | else | 920 | else |
1021 | len = 0; | 921 | len = 0; |
1022 | } | ||
1023 | if (pn) | 922 | if (pn) |
1024 | *pn = len; | 923 | *pn = len; |
1025 | buf[len] = '\0'; | 924 | buf[len] = '\0'; | ... | ... |
1 | /* GNU mailutils - a suite of utilities for electronic mail | 1 | /* GNU mailutils - a suite of utilities for electronic mail |
2 | Copyright (C) 1999, 2000 Free Software Foundation, Inc. | 2 | Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc. |
3 | 3 | ||
4 | This program is free software; you can redistribute it and/or modify | 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 | 5 | it under the terms of the GNU General Library Public License as published by |
... | @@ -43,11 +43,12 @@ extern "C" { | ... | @@ -43,11 +43,12 @@ extern "C" { |
43 | struct _body | 43 | struct _body |
44 | { | 44 | { |
45 | void *owner; | 45 | void *owner; |
46 | |||
47 | /* it's better and more portable to use stdio */ | ||
48 | FILE *file; | ||
49 | char *filename; | 46 | char *filename; |
50 | stream_t stream; | 47 | stream_t stream; |
48 | stream_t fstream; | ||
49 | property_t property; | ||
50 | int flags; | ||
51 | |||
51 | int (*_size) (body_t, size_t*); | 52 | int (*_size) (body_t, size_t*); |
52 | int (*_lines) (body_t, size_t*); | 53 | int (*_lines) (body_t, size_t*); |
53 | }; | 54 | }; | ... | ... |
... | @@ -40,6 +40,14 @@ extern "C" { | ... | @@ -40,6 +40,14 @@ extern "C" { |
40 | # endif | 40 | # endif |
41 | #endif /*__P */ | 41 | #endif /*__P */ |
42 | 42 | ||
43 | struct default_properties | ||
44 | { | ||
45 | char *key; | ||
46 | char *value; | ||
47 | int (*_set_value) __P ((property_t, const char *, const char *)); | ||
48 | int (*_get_value) __P ((property_t, const char *, char *, size_t, size_t *)); | ||
49 | }; | ||
50 | |||
43 | struct _mailbox | 51 | struct _mailbox |
44 | { | 52 | { |
45 | /* Data */ | 53 | /* Data */ |
... | @@ -48,7 +56,7 @@ struct _mailbox | ... | @@ -48,7 +56,7 @@ struct _mailbox |
48 | ticket_t ticket; | 56 | ticket_t ticket; |
49 | authority_t authority; | 57 | authority_t authority; |
50 | property_t property; | 58 | property_t property; |
51 | struct property_list *properties; | 59 | struct default_properties *properties; |
52 | size_t properties_count; | 60 | size_t properties_count; |
53 | locker_t locker; | 61 | locker_t locker; |
54 | stream_t stream; | 62 | stream_t stream; |
... | @@ -81,7 +89,7 @@ struct _mailbox | ... | @@ -81,7 +89,7 @@ struct _mailbox |
81 | int (*_scan) __P ((mailbox_t, size_t msgno, size_t *count)); | 89 | int (*_scan) __P ((mailbox_t, size_t msgno, size_t *count)); |
82 | int (*_is_updated) __P ((mailbox_t)); | 90 | int (*_is_updated) __P ((mailbox_t)); |
83 | 91 | ||
84 | int (*_size) __P ((mailbox_t, off_t *size)); | 92 | int (*_get_size) __P ((mailbox_t, off_t *size)); |
85 | 93 | ||
86 | }; | 94 | }; |
87 | 95 | ... | ... |
... | @@ -53,6 +53,14 @@ extern "C" { | ... | @@ -53,6 +53,14 @@ extern "C" { |
53 | 53 | ||
54 | #define MAILER_LINE_BUF_SIZE 1000 | 54 | #define MAILER_LINE_BUF_SIZE 1000 |
55 | 55 | ||
56 | struct default_properties | ||
57 | { | ||
58 | char *key; | ||
59 | char *value; | ||
60 | int (*_set_value) __P ((property_t, const char *, const char *)); | ||
61 | int (*_get_value) __P ((property_t, const char *, char *, size_t, size_t *)); | ||
62 | }; | ||
63 | |||
56 | struct _mailer | 64 | struct _mailer |
57 | { | 65 | { |
58 | stream_t stream; | 66 | stream_t stream; |
... | @@ -62,7 +70,7 @@ struct _mailer | ... | @@ -62,7 +70,7 @@ struct _mailer |
62 | int flags; | 70 | int flags; |
63 | monitor_t monitor; | 71 | monitor_t monitor; |
64 | property_t property; | 72 | property_t property; |
65 | struct property_list *properties; | 73 | struct default_properties *properties; |
66 | size_t properties_count; | 74 | size_t properties_count; |
67 | 75 | ||
68 | /* Pointer to the specific mailer data. */ | 76 | /* Pointer to the specific mailer data. */ | ... | ... |
... | @@ -50,7 +50,9 @@ struct _message | ... | @@ -50,7 +50,9 @@ struct _message |
50 | header_t header; | 50 | header_t header; |
51 | body_t body; | 51 | body_t body; |
52 | 52 | ||
53 | int flags; | ||
53 | stream_t stream; | 54 | stream_t stream; |
55 | property_t property; | ||
54 | attribute_t attribute; | 56 | attribute_t attribute; |
55 | monitor_t monitor; | 57 | monitor_t monitor; |
56 | mime_t mime; | 58 | mime_t mime; | ... | ... |
... | @@ -41,10 +41,13 @@ | ... | @@ -41,10 +41,13 @@ |
41 | extern "C" { | 41 | extern "C" { |
42 | #endif | 42 | #endif |
43 | 43 | ||
44 | struct property_private | 44 | struct property_data |
45 | { | 45 | { |
46 | size_t hash; | 46 | size_t hash; |
47 | int *address; | 47 | char *key; |
48 | char *value; | ||
49 | int (*_set_value) __P ((property_t, const char *, const char *)); | ||
50 | int (*_get_value) __P ((property_t, const char *, char *, size_t, size_t *)); | ||
48 | }; | 51 | }; |
49 | 52 | ||
50 | struct _property | 53 | struct _property | ... | ... |
... | @@ -274,11 +274,11 @@ mailbox_scan (mailbox_t mbox, size_t msgno, size_t *pcount) | ... | @@ -274,11 +274,11 @@ mailbox_scan (mailbox_t mbox, size_t msgno, size_t *pcount) |
274 | } | 274 | } |
275 | 275 | ||
276 | int | 276 | int |
277 | mailbox_size (mailbox_t mbox, off_t *psize) | 277 | mailbox_get_size (mailbox_t mbox, off_t *psize) |
278 | { | 278 | { |
279 | if (mbox == NULL || mbox->_size == NULL) | 279 | if (mbox == NULL || mbox->_get_size == NULL) |
280 | return ENOSYS; | 280 | return ENOSYS; |
281 | return mbox->_size (mbox, psize); | 281 | return mbox->_get_size (mbox, psize); |
282 | } | 282 | } |
283 | 283 | ||
284 | int | 284 | int |
... | @@ -426,9 +426,11 @@ mailbox_get_property (mailbox_t mbox, property_t *pproperty) | ... | @@ -426,9 +426,11 @@ mailbox_get_property (mailbox_t mbox, property_t *pproperty) |
426 | /* Add the defaults. */ | 426 | /* Add the defaults. */ |
427 | for (i = 0; i < mbox->properties_count; i++) | 427 | for (i = 0; i < mbox->properties_count; i++) |
428 | { | 428 | { |
429 | status = property_add_default (mbox->property, | 429 | status = property_add_defaults (mbox->property, |
430 | mbox->properties[i].key, | 430 | mbox->properties[i].key, |
431 | &(mbox->properties[i].value), | 431 | mbox->properties[i].value, |
432 | mbox->properties[i]._set_value, | ||
433 | mbox->properties[i]._get_value, | ||
432 | mbox); | 434 | mbox); |
433 | if (status != 0) | 435 | if (status != 0) |
434 | { | 436 | { | ... | ... |
... | @@ -145,6 +145,8 @@ mailer_destroy (mailer_t *pmailer) | ... | @@ -145,6 +145,8 @@ mailer_destroy (mailer_t *pmailer) |
145 | { | 145 | { |
146 | if (mailer->properties[i].key) | 146 | if (mailer->properties[i].key) |
147 | free (mailer->properties[i].key); | 147 | free (mailer->properties[i].key); |
148 | if (mailer->properties[i].value) | ||
149 | free (mailer->properties[i].value); | ||
148 | } | 150 | } |
149 | free (mailer->properties); | 151 | free (mailer->properties); |
150 | } | 152 | } |
... | @@ -237,9 +239,11 @@ mailer_get_property (mailer_t mailer, property_t *pproperty) | ... | @@ -237,9 +239,11 @@ mailer_get_property (mailer_t mailer, property_t *pproperty) |
237 | /* Add the defaults. */ | 239 | /* Add the defaults. */ |
238 | for (i = 0; i < mailer->properties_count; i++) | 240 | for (i = 0; i < mailer->properties_count; i++) |
239 | { | 241 | { |
240 | status = property_add_default (mailer->property, | 242 | status = property_add_defaults (mailer->property, |
241 | mailer->properties[i].key, | 243 | mailer->properties[i].key, |
242 | &(mailer->properties[i].value), | 244 | mailer->properties[i].value, |
245 | mailer->properties[i]._set_value, | ||
246 | mailer->properties[i]._get_value, | ||
243 | mailer); | 247 | mailer); |
244 | if (status != 0) | 248 | if (status != 0) |
245 | { | 249 | { | ... | ... |
... | @@ -145,14 +145,12 @@ _mailbox_imap_init (mailbox_t mailbox) | ... | @@ -145,14 +145,12 @@ _mailbox_imap_init (mailbox_t mailbox) |
145 | m_imap->mailbox = mailbox; | 145 | m_imap->mailbox = mailbox; |
146 | 146 | ||
147 | /* Set our properties. */ | 147 | /* Set our properties. */ |
148 | mailbox->properties = calloc (2, sizeof (*(mailbox->properties))); | 148 | mailbox->properties = calloc (1, sizeof (*(mailbox->properties))); |
149 | if (mailbox->properties == NULL) | 149 | if (mailbox->properties == NULL) |
150 | return ENOMEM; | 150 | return ENOMEM; |
151 | mailbox->properties_count = 2; | 151 | mailbox->properties_count = 1; |
152 | mailbox->properties[0].key = strdup ("IMAP4"); | 152 | mailbox->properties[0].key = strdup ("TYPE"); |
153 | mailbox->properties[0].value = 1; | 153 | mailbox->properties[0].value = strdup ("IMAP"); |
154 | mailbox->properties[1].key = strdup ("RFC822"); | ||
155 | mailbox->properties[1].value = 0; | ||
156 | return 0; | 154 | return 0; |
157 | } | 155 | } |
158 | 156 | ||
... | @@ -436,6 +434,7 @@ imap_get_message0 (msg_imap_t msg_imap, message_t *pmsg) | ... | @@ -436,6 +434,7 @@ imap_get_message0 (msg_imap_t msg_imap, message_t *pmsg) |
436 | 434 | ||
437 | /* Set the UID on the message. */ | 435 | /* Set the UID on the message. */ |
438 | message_set_uid (msg, imap_message_uid, msg_imap); | 436 | message_set_uid (msg, imap_message_uid, msg_imap); |
437 | message_set_mailbox (msg, mailbox, msg_imap); | ||
439 | 438 | ||
440 | *pmsg = msg; | 439 | *pmsg = msg; |
441 | return 0; | 440 | return 0; |
... | @@ -720,6 +719,7 @@ imap_submessage_size (msg_imap_t msg_imap, size_t *psize) | ... | @@ -720,6 +719,7 @@ imap_submessage_size (msg_imap_t msg_imap, size_t *psize) |
720 | { | 719 | { |
721 | if (psize) | 720 | if (psize) |
722 | { | 721 | { |
722 | *psize = 0; | ||
723 | if (msg_imap->message_size == 0) | 723 | if (msg_imap->message_size == 0) |
724 | { | 724 | { |
725 | size_t i, size; | 725 | size_t i, size; |
... | @@ -1129,13 +1129,10 @@ imap_header_get_value (header_t header, const char *field, char * buffer, | ... | @@ -1129,13 +1129,10 @@ imap_header_get_value (header_t header, const char *field, char * buffer, |
1129 | /* Hack, if buffer == NULL they want to know how big is the field value, | 1129 | /* Hack, if buffer == NULL they want to know how big is the field value, |
1130 | Unfortunately IMAP does not say, so we take a guess hoping that the | 1130 | Unfortunately IMAP does not say, so we take a guess hoping that the |
1131 | value will not be over 1024. */ | 1131 | value will not be over 1024. */ |
1132 | /* FIXME: This is stupid, find a way to fix this. */ | ||
1133 | if (buffer == NULL || buflen == 0) | 1132 | if (buffer == NULL || buflen == 0) |
1134 | len = 1024; | 1133 | len = 1024; |
1135 | else | 1134 | else |
1136 | len = strlen (field) + buflen + 4; | 1135 | len = strlen (field) + buflen + 4; |
1137 | value = alloca (len); | ||
1138 | /*memset (value, '0', len); */ | ||
1139 | 1136 | ||
1140 | if (f_imap->state == IMAP_NO_STATE) | 1137 | if (f_imap->state == IMAP_NO_STATE) |
1141 | { | 1138 | { |
... | @@ -1151,14 +1148,18 @@ imap_header_get_value (header_t header, const char *field, char * buffer, | ... | @@ -1151,14 +1148,18 @@ imap_header_get_value (header_t header, const char *field, char * buffer, |
1151 | f_imap->state = IMAP_FETCH; | 1148 | f_imap->state = IMAP_FETCH; |
1152 | 1149 | ||
1153 | } | 1150 | } |
1151 | |||
1152 | value = calloc (len, sizeof (*value)); | ||
1154 | status = message_operation (f_imap, msg_imap, value, len, &len); | 1153 | status = message_operation (f_imap, msg_imap, value, len, &len); |
1155 | if (status == 0) | 1154 | if (status == 0) |
1156 | { | 1155 | { |
1157 | char *colon; | 1156 | char *colon; |
1158 | /* The field-matching is case-insensitive but otherwise exact. In all | 1157 | /* The field-matching is case-insensitive. In all cases, the delimiting |
1159 | cases, the delimiting blank line between the header and the body is | 1158 | newline between the header and the body is always included. |
1160 | always included. */ | 1159 | Nuke it */ |
1161 | value[len - 1] = '\0'; | 1160 | value[len - 1] = '\0'; |
1161 | |||
1162 | /* Move pass the field-name. */ | ||
1162 | colon = strchr (value, ':'); | 1163 | colon = strchr (value, ':'); |
1163 | if (colon) | 1164 | if (colon) |
1164 | { | 1165 | { |
... | @@ -1183,8 +1184,8 @@ imap_header_get_value (header_t header, const char *field, char * buffer, | ... | @@ -1183,8 +1184,8 @@ imap_header_get_value (header_t header, const char *field, char * buffer, |
1183 | if (len == 0) | 1184 | if (len == 0) |
1184 | status = ENOENT; | 1185 | status = ENOENT; |
1185 | } | 1186 | } |
1187 | free (value); | ||
1186 | return status; | 1188 | return status; |
1187 | |||
1188 | } | 1189 | } |
1189 | 1190 | ||
1190 | static int | 1191 | static int | ... | ... |
... | @@ -46,11 +46,6 @@ | ... | @@ -46,11 +46,6 @@ |
46 | #include <registrar0.h> | 46 | #include <registrar0.h> |
47 | #include <mailbox0.h> | 47 | #include <mailbox0.h> |
48 | 48 | ||
49 | |||
50 | /* See porperties in _init. */ | ||
51 | #define PROP_TYPE 0 | ||
52 | #define PROP_RFC822 1 | ||
53 | |||
54 | #define ATTRIBUTE_IS_DELETED(flag) (flag & MU_ATTRIBUTE_DELETED) | 49 | #define ATTRIBUTE_IS_DELETED(flag) (flag & MU_ATTRIBUTE_DELETED) |
55 | #define ATTRIBUTE_IS_EQUAL(flag1, flag2) (flag1 == flag2) | 50 | #define ATTRIBUTE_IS_EQUAL(flag1, flag2) (flag1 == flag2) |
56 | 51 | ||
... | @@ -110,14 +105,6 @@ struct _mbox_message | ... | @@ -110,14 +105,6 @@ struct _mbox_message |
110 | off_t body; | 105 | off_t body; |
111 | off_t body_end; | 106 | off_t body_end; |
112 | 107 | ||
113 | /* Save the offset for rfc822 format. */ | ||
114 | struct _rfc822 | ||
115 | { | ||
116 | off_t r_offset; | ||
117 | off_t f_offset; | ||
118 | int residue; | ||
119 | } rfc822; | ||
120 | |||
121 | /* Fast header retrieve, we save here the most common headers. This will | 108 | /* Fast header retrieve, we save here the most common headers. This will |
122 | speed the header search. The entire headers are copied, when modified, | 109 | speed the header search. The entire headers are copied, when modified, |
123 | by the header_t object, we do not have to worry about updating them. */ | 110 | by the header_t object, we do not have to worry about updating them. */ |
... | @@ -177,7 +164,7 @@ static int mbox_uidvalidity __P ((mailbox_t, unsigned long *)); | ... | @@ -177,7 +164,7 @@ static int mbox_uidvalidity __P ((mailbox_t, unsigned long *)); |
177 | static int mbox_uidnext __P ((mailbox_t, size_t *)); | 164 | static int mbox_uidnext __P ((mailbox_t, size_t *)); |
178 | static int mbox_scan __P ((mailbox_t, size_t, size_t *)); | 165 | static int mbox_scan __P ((mailbox_t, size_t, size_t *)); |
179 | static int mbox_is_updated __P ((mailbox_t)); | 166 | static int mbox_is_updated __P ((mailbox_t)); |
180 | static int mbox_size __P ((mailbox_t, off_t *)); | 167 | static int mbox_get_size __P ((mailbox_t, off_t *)); |
181 | 168 | ||
182 | /* private stuff */ | 169 | /* private stuff */ |
183 | static int mbox_scan0 __P ((mailbox_t, size_t, size_t *, int)); | 170 | static int mbox_scan0 __P ((mailbox_t, size_t, size_t *, int)); |
... | @@ -195,9 +182,6 @@ static int mbox_body_read __P ((stream_t, char *, size_t, off_t, | ... | @@ -195,9 +182,6 @@ static int mbox_body_read __P ((stream_t, char *, size_t, off_t, |
195 | size_t *)); | 182 | size_t *)); |
196 | static int mbox_body_readline __P ((stream_t, char *, size_t, off_t, | 183 | static int mbox_body_readline __P ((stream_t, char *, size_t, off_t, |
197 | size_t *)); | 184 | size_t *)); |
198 | static int mbox_readstream_rfc822 __P ((mbox_message_t, char *, size_t, | ||
199 | off_t, size_t *, int, off_t, | ||
200 | off_t)); | ||
201 | static int mbox_readstream __P ((mbox_message_t, char *, size_t, | 185 | static int mbox_readstream __P ((mbox_message_t, char *, size_t, |
202 | off_t, size_t *, int, off_t, | 186 | off_t, size_t *, int, off_t, |
203 | off_t)); | 187 | off_t)); |
... | @@ -275,17 +259,15 @@ _mailbox_mbox_init (mailbox_t mailbox) | ... | @@ -275,17 +259,15 @@ _mailbox_mbox_init (mailbox_t mailbox) |
275 | mailbox->_scan = mbox_scan; | 259 | mailbox->_scan = mbox_scan; |
276 | mailbox->_is_updated = mbox_is_updated; | 260 | mailbox->_is_updated = mbox_is_updated; |
277 | 261 | ||
278 | mailbox->_size = mbox_size; | 262 | mailbox->_get_size = mbox_get_size; |
279 | 263 | ||
280 | /* Set our properties. */ | 264 | /* Set our properties. */ |
281 | mailbox->properties = calloc (2, sizeof (*(mailbox->properties))); | 265 | mailbox->properties = calloc (1, sizeof (*(mailbox->properties))); |
282 | if (mailbox->properties == NULL) | 266 | if (mailbox->properties == NULL) |
283 | return ENOMEM; | 267 | return ENOMEM; |
284 | mailbox->properties_count = 2; | 268 | mailbox->properties_count = 1; |
285 | mailbox->properties[0].key = strdup ("MBOX"); | 269 | mailbox->properties[0].key = strdup ("TYPE"); |
286 | mailbox->properties[0].value = 1; | 270 | mailbox->properties[0].value = strdup ("MBOX"); |
287 | mailbox->properties[1].key = strdup ("RFC822"); | ||
288 | mailbox->properties[1].value = 0; | ||
289 | 271 | ||
290 | MAILBOX_DEBUG1 (mailbox, MU_DEBUG_TRACE, "mbox_init(%s)\n", mud->name); | 272 | MAILBOX_DEBUG1 (mailbox, MU_DEBUG_TRACE, "mbox_init(%s)\n", mud->name); |
291 | return 0; /* okdoke */ | 273 | return 0; /* okdoke */ |
... | @@ -993,10 +975,6 @@ mbox_body_readline (stream_t is, char *buffer, size_t buflen, | ... | @@ -993,10 +975,6 @@ mbox_body_readline (stream_t is, char *buffer, size_t buflen, |
993 | message_t msg = body_get_owner (body); | 975 | message_t msg = body_get_owner (body); |
994 | mbox_message_t mum = message_get_owner (msg); | 976 | mbox_message_t mum = message_get_owner (msg); |
995 | 977 | ||
996 | if (mum->mud->mailbox->properties[PROP_RFC822].value) | ||
997 | return mbox_readstream_rfc822 (mum, buffer, buflen, off, pnread, 1, | ||
998 | mum->body, mum->body_end); | ||
999 | else | ||
1000 | return mbox_readstream (mum, buffer, buflen, off, pnread, 1, | 978 | return mbox_readstream (mum, buffer, buflen, off, pnread, 1, |
1001 | mum->body, mum->body_end); | 979 | mum->body, mum->body_end); |
1002 | } | 980 | } |
... | @@ -1008,101 +986,11 @@ mbox_body_read (stream_t is, char *buffer, size_t buflen, | ... | @@ -1008,101 +986,11 @@ mbox_body_read (stream_t is, char *buffer, size_t buflen, |
1008 | body_t body = stream_get_owner (is); | 986 | body_t body = stream_get_owner (is); |
1009 | message_t msg = body_get_owner (body); | 987 | message_t msg = body_get_owner (body); |
1010 | mbox_message_t mum = message_get_owner (msg); | 988 | mbox_message_t mum = message_get_owner (msg); |
1011 | if (mum->mud->mailbox->properties[PROP_RFC822].value) | ||
1012 | return mbox_readstream_rfc822 (mum, buffer, buflen, off, pnread, 0, | ||
1013 | mum->body, mum->body_end); | ||
1014 | else | ||
1015 | return mbox_readstream (mum, buffer, buflen, off, pnread, 0, | 989 | return mbox_readstream (mum, buffer, buflen, off, pnread, 0, |
1016 | mum->body, mum->body_end); | 990 | mum->body, mum->body_end); |
1017 | } | 991 | } |
1018 | 992 | ||
1019 | static int | 993 | static int |
1020 | mbox_readstream_rfc822 (mbox_message_t mum, char *buffer, size_t buflen, | ||
1021 | off_t off, size_t *pnread, int isreadline, | ||
1022 | off_t start, off_t end) | ||
1023 | { | ||
1024 | size_t total = 0; | ||
1025 | int status = 0; | ||
1026 | |||
1027 | if (isreadline) | ||
1028 | buflen--; | ||
1029 | /* Catch up i.e bring us to the current offset. */ | ||
1030 | if (mum->rfc822.r_offset != off) | ||
1031 | { | ||
1032 | mum->rfc822.r_offset = off - mum->body_lines; | ||
1033 | mum->rfc822.residue = 0; | ||
1034 | |||
1035 | if (mum->rfc822.r_offset < 0) | ||
1036 | mum->rfc822.r_offset = 0; | ||
1037 | mum->rfc822.f_offset = mum->rfc822.r_offset; | ||
1038 | while (mum->rfc822.r_offset < off) | ||
1039 | { | ||
1040 | char c; | ||
1041 | size_t n = 0; | ||
1042 | status = stream_read (mum->mud->mailbox->stream, &c, 1, | ||
1043 | mum->rfc822.f_offset, &n); | ||
1044 | if (status != 0) | ||
1045 | return status; | ||
1046 | if (n == 0) | ||
1047 | break; | ||
1048 | if (c == '\n') | ||
1049 | { | ||
1050 | mum->rfc822.r_offset++; | ||
1051 | if (mum->rfc822.r_offset == off) | ||
1052 | { | ||
1053 | mum->rfc822.residue = 1; | ||
1054 | break; | ||
1055 | } | ||
1056 | } | ||
1057 | mum->rfc822.r_offset++; | ||
1058 | mum->rfc822.f_offset++; | ||
1059 | } | ||
1060 | } | ||
1061 | |||
1062 | do | ||
1063 | { | ||
1064 | size_t nread = 0; | ||
1065 | status = mbox_readstream (mum, buffer, buflen, mum->rfc822.f_offset, | ||
1066 | &nread, 1, start, end); | ||
1067 | if (status != 0) | ||
1068 | return status; | ||
1069 | if (nread == 0) | ||
1070 | break; | ||
1071 | mum->rfc822.f_offset += nread; | ||
1072 | mum->rfc822.r_offset += nread; | ||
1073 | total += nread; | ||
1074 | buflen -= nread; | ||
1075 | if (buffer[nread - 1] == '\n') | ||
1076 | { | ||
1077 | if (!mum->rfc822.residue) | ||
1078 | { | ||
1079 | buffer[nread - 1] = '\r'; | ||
1080 | if (buflen == 0) | ||
1081 | { | ||
1082 | mum->rfc822.residue = 1; | ||
1083 | break; | ||
1084 | } | ||
1085 | buffer[nread] = '\n'; | ||
1086 | buflen--; | ||
1087 | nread++; | ||
1088 | total++; | ||
1089 | mum->rfc822.r_offset++; | ||
1090 | } | ||
1091 | else | ||
1092 | mum->rfc822.residue = 0; | ||
1093 | } | ||
1094 | buffer += nread; | ||
1095 | } while (buflen > 0 || !isreadline); | ||
1096 | |||
1097 | if (isreadline) | ||
1098 | *buffer = '\0'; | ||
1099 | |||
1100 | if (pnread) | ||
1101 | *pnread = total; | ||
1102 | return status; | ||
1103 | } | ||
1104 | |||
1105 | static int | ||
1106 | mbox_readstream (mbox_message_t mum, char *buffer, size_t buflen, | 994 | mbox_readstream (mbox_message_t mum, char *buffer, size_t buflen, |
1107 | off_t off, size_t *pnread, int isreadline, | 995 | off_t off, size_t *pnread, int isreadline, |
1108 | off_t start, off_t end) | 996 | off_t start, off_t end) |
... | @@ -1187,28 +1075,8 @@ mbox_header_get_fvalue (header_t header, const char *name, char *buffer, | ... | @@ -1187,28 +1075,8 @@ mbox_header_get_fvalue (header_t header, const char *name, char *buffer, |
1187 | { | 1075 | { |
1188 | /* For the null. */ | 1076 | /* For the null. */ |
1189 | buflen--; | 1077 | buflen--; |
1190 | /* Convert to \r\n */ | ||
1191 | if (mum->mud->mailbox->properties[PROP_RFC822].value) | ||
1192 | { | ||
1193 | char *s = mum->fhdr[i]; | ||
1194 | for (fv_len = 0; *s && fv_len < buflen; | ||
1195 | s++, fv_len++) | ||
1196 | { | ||
1197 | if (*s == '\n') | ||
1198 | { | ||
1199 | buffer[fv_len] = '\r'; | ||
1200 | /* Side effect. */ | ||
1201 | if (++fv_len >= buflen) | ||
1202 | break; | ||
1203 | } | ||
1204 | buffer[fv_len] = *s; | ||
1205 | } | ||
1206 | } | ||
1207 | else | ||
1208 | { | ||
1209 | fv_len = (fv_len < buflen) ? fv_len : buflen; | 1078 | fv_len = (fv_len < buflen) ? fv_len : buflen; |
1210 | memcpy (buffer, mum->fhdr[i], fv_len); | 1079 | memcpy (buffer, mum->fhdr[i], fv_len); |
1211 | } | ||
1212 | buffer[fv_len] = '\0'; | 1080 | buffer[fv_len] = '\0'; |
1213 | } | 1081 | } |
1214 | err = 0; | 1082 | err = 0; |
... | @@ -1232,13 +1100,7 @@ mbox_header_size (header_t header, size_t *psize) | ... | @@ -1232,13 +1100,7 @@ mbox_header_size (header_t header, size_t *psize) |
1232 | if (mum == NULL) | 1100 | if (mum == NULL) |
1233 | return EINVAL; | 1101 | return EINVAL; |
1234 | if (psize) | 1102 | if (psize) |
1235 | { | ||
1236 | *psize = mum->body - mum->header_from_end; | 1103 | *psize = mum->body - mum->header_from_end; |
1237 | #if 1 | ||
1238 | if (mum->mud->mailbox->properties[PROP_RFC822].value) | ||
1239 | *psize += mum->header_lines; | ||
1240 | #endif | ||
1241 | } | ||
1242 | return 0; | 1104 | return 0; |
1243 | } | 1105 | } |
1244 | 1106 | ||
... | @@ -1262,13 +1124,7 @@ mbox_body_size (body_t body, size_t *psize) | ... | @@ -1262,13 +1124,7 @@ mbox_body_size (body_t body, size_t *psize) |
1262 | if (mum == NULL) | 1124 | if (mum == NULL) |
1263 | return EINVAL; | 1125 | return EINVAL; |
1264 | if (psize) | 1126 | if (psize) |
1265 | { | ||
1266 | *psize = mum->body_end - mum->body + 1; | 1127 | *psize = mum->body_end - mum->body + 1; |
1267 | #if 1 | ||
1268 | if (mum->mud->mailbox->properties[PROP_RFC822].value) | ||
1269 | *psize += mum->body_lines; | ||
1270 | #endif | ||
1271 | } | ||
1272 | return 0; | 1128 | return 0; |
1273 | } | 1129 | } |
1274 | 1130 | ||
... | @@ -1421,16 +1277,12 @@ mbox_get_message (mailbox_t mailbox, size_t msgno, message_t *pmsg) | ... | @@ -1421,16 +1277,12 @@ mbox_get_message (mailbox_t mailbox, size_t msgno, message_t *pmsg) |
1421 | /* Set the header. */ | 1277 | /* Set the header. */ |
1422 | { | 1278 | { |
1423 | header_t header = NULL; | 1279 | header_t header = NULL; |
1424 | property_t property = NULL; | ||
1425 | status = header_create (&header, NULL, 0, msg); | 1280 | status = header_create (&header, NULL, 0, msg); |
1426 | if (status != 0) | 1281 | if (status != 0) |
1427 | { | 1282 | { |
1428 | message_destroy (&msg, mum); | 1283 | message_destroy (&msg, mum); |
1429 | return status; | 1284 | return status; |
1430 | } | 1285 | } |
1431 | /* Force the mailbox to register the properties. */ | ||
1432 | mailbox_get_property (mailbox, &property); | ||
1433 | header_set_property (header, property, msg); | ||
1434 | header_set_fill (header, mbox_header_fill, msg); | 1286 | header_set_fill (header, mbox_header_fill, msg); |
1435 | header_set_get_fvalue (header, mbox_header_get_fvalue, msg); | 1287 | header_set_get_fvalue (header, mbox_header_get_fvalue, msg); |
1436 | header_set_size (header, mbox_header_size, msg); | 1288 | header_set_size (header, mbox_header_size, msg); |
... | @@ -1458,7 +1310,9 @@ mbox_get_message (mailbox_t mailbox, size_t msgno, message_t *pmsg) | ... | @@ -1458,7 +1310,9 @@ mbox_get_message (mailbox_t mailbox, size_t msgno, message_t *pmsg) |
1458 | body_t body = NULL; | 1310 | body_t body = NULL; |
1459 | stream_t stream = NULL; | 1311 | stream_t stream = NULL; |
1460 | if ((status = body_create (&body, msg)) != 0 | 1312 | if ((status = body_create (&body, msg)) != 0 |
1461 | || (status = stream_create (&stream, mailbox->flags, body)) != 0) | 1313 | || (status = stream_create (&stream, |
1314 | mailbox->flags | MU_STREAM_SEEKABLE, | ||
1315 | body)) != 0) | ||
1462 | { | 1316 | { |
1463 | body_destroy (&body, msg); | 1317 | body_destroy (&body, msg); |
1464 | stream_destroy (&stream, body); | 1318 | stream_destroy (&stream, body); |
... | @@ -1493,7 +1347,7 @@ mbox_get_message (mailbox_t mailbox, size_t msgno, message_t *pmsg) | ... | @@ -1493,7 +1347,7 @@ mbox_get_message (mailbox_t mailbox, size_t msgno, message_t *pmsg) |
1493 | 1347 | ||
1494 | /* Attach the message to the mailbox mbox data. */ | 1348 | /* Attach the message to the mailbox mbox data. */ |
1495 | mum->message = msg; | 1349 | mum->message = msg; |
1496 | message_set_mailbox (msg, mailbox); | 1350 | message_set_mailbox (msg, mailbox, mum); |
1497 | 1351 | ||
1498 | *pmsg = msg; | 1352 | *pmsg = msg; |
1499 | return 0; | 1353 | return 0; |
... | @@ -1832,7 +1686,7 @@ mbox_append_message0 (mailbox_t mailbox, message_t msg, off_t *psize, | ... | @@ -1832,7 +1686,7 @@ mbox_append_message0 (mailbox_t mailbox, message_t msg, off_t *psize, |
1832 | } | 1686 | } |
1833 | 1687 | ||
1834 | static int | 1688 | static int |
1835 | mbox_size (mailbox_t mailbox, off_t *psize) | 1689 | mbox_get_size (mailbox_t mailbox, off_t *psize) |
1836 | { | 1690 | { |
1837 | off_t size; | 1691 | off_t size; |
1838 | int status; | 1692 | int status; | ... | ... |
... | @@ -87,7 +87,7 @@ static int pop_is_updated __P ((mailbox_t)); | ... | @@ -87,7 +87,7 @@ static int pop_is_updated __P ((mailbox_t)); |
87 | 87 | ||
88 | /* The implementation of message_t */ | 88 | /* The implementation of message_t */ |
89 | static int pop_user __P ((authority_t)); | 89 | static int pop_user __P ((authority_t)); |
90 | static int pop_size __P ((mailbox_t, off_t *)); | 90 | static int pop_get_size __P ((mailbox_t, off_t *)); |
91 | /* We use pop_top for retreiving headers. */ | 91 | /* We use pop_top for retreiving headers. */ |
92 | /* static int pop_header_read (header_t, char *, size_t, off_t, size_t *); */ | 92 | /* static int pop_header_read (header_t, char *, size_t, off_t, size_t *); */ |
93 | static int pop_body_fd __P ((stream_t, int *)); | 93 | static int pop_body_fd __P ((stream_t, int *)); |
... | @@ -292,17 +292,15 @@ _mailbox_pop_init (mailbox_t mbox) | ... | @@ -292,17 +292,15 @@ _mailbox_pop_init (mailbox_t mbox) |
292 | mbox->_scan = pop_scan; | 292 | mbox->_scan = pop_scan; |
293 | mbox->_is_updated = pop_is_updated; | 293 | mbox->_is_updated = pop_is_updated; |
294 | 294 | ||
295 | mbox->_size = pop_size; | 295 | mbox->_get_size = pop_get_size; |
296 | 296 | ||
297 | /* Properties. */ | 297 | /* Properties. */ |
298 | mbox->properties = calloc (2, sizeof (*(mbox->properties))); | 298 | mbox->properties = calloc (1, sizeof (*(mbox->properties))); |
299 | if (mbox->properties == NULL) | 299 | if (mbox->properties == NULL) |
300 | return ENOMEM; | 300 | return ENOMEM; |
301 | mbox->properties_count = 2; | 301 | mbox->properties_count = 1; |
302 | mbox->properties[0].key = strdup ("POP3"); | 302 | mbox->properties[0].key = strdup ("TYPE"); |
303 | mbox->properties[0].value = 1; | 303 | mbox->properties[0].value = strdup ("POP3"); |
304 | mbox->properties[1].key = strdup ("RFC822"); | ||
305 | mbox->properties[1].value = 0; | ||
306 | return 0; /* Okdoke. */ | 304 | return 0; /* Okdoke. */ |
307 | } | 305 | } |
308 | 306 | ||
... | @@ -799,7 +797,7 @@ pop_get_message (mailbox_t mbox, size_t msgno, message_t *pmsg) | ... | @@ -799,7 +797,7 @@ pop_get_message (mailbox_t mbox, size_t msgno, message_t *pmsg) |
799 | monitor_unlock (mbox->monitor); | 797 | monitor_unlock (mbox->monitor); |
800 | 798 | ||
801 | /* Save The message pointer. */ | 799 | /* Save The message pointer. */ |
802 | message_set_mailbox (msg, mbox); | 800 | message_set_mailbox (msg, mbox, mpm); |
803 | *pmsg = mpm->message = msg; | 801 | *pmsg = mpm->message = msg; |
804 | 802 | ||
805 | return 0; | 803 | return 0; |
... | @@ -1005,7 +1003,7 @@ pop_expunge (mailbox_t mbox) | ... | @@ -1005,7 +1003,7 @@ pop_expunge (mailbox_t mbox) |
1005 | 1003 | ||
1006 | /* Mailbox size ? It is part of the STAT command */ | 1004 | /* Mailbox size ? It is part of the STAT command */ |
1007 | static int | 1005 | static int |
1008 | pop_size (mailbox_t mbox, off_t *psize) | 1006 | pop_get_size (mailbox_t mbox, off_t *psize) |
1009 | { | 1007 | { |
1010 | pop_data_t mpd = mbox->data; | 1008 | pop_data_t mpd = mbox->data; |
1011 | int status = 0; | 1009 | int status = 0; |
... | @@ -1865,9 +1863,7 @@ pop_readline (pop_data_t mpd) | ... | @@ -1865,9 +1863,7 @@ pop_readline (pop_data_t mpd) |
1865 | mpd->nl = NULL; | 1863 | mpd->nl = NULL; |
1866 | } | 1864 | } |
1867 | } | 1865 | } |
1868 | /* \r\n --> \n\0, conversion, If the propety is set no conversion | 1866 | /* \r\n --> \n\0, conversion. */ |
1869 | is done. */ | ||
1870 | if (mpd->mbox->properties[PROP_RFC822].value == 0) | ||
1871 | if (mpd->nl > mpd->buffer) | 1867 | if (mpd->nl > mpd->buffer) |
1872 | { | 1868 | { |
1873 | *(mpd->nl - 1) = '\n'; | 1869 | *(mpd->nl - 1) = '\n'; | ... | ... |
... | @@ -182,10 +182,43 @@ message_clear_modified (message_t msg) | ... | @@ -182,10 +182,43 @@ message_clear_modified (message_t msg) |
182 | } | 182 | } |
183 | 183 | ||
184 | int | 184 | int |
185 | message_set_mailbox (message_t msg, mailbox_t mailbox) | 185 | message_set_property (message_t msg, property_t property, void *owner) |
186 | { | 186 | { |
187 | if (msg == NULL) | 187 | if (msg == NULL) |
188 | return EINVAL; | 188 | return EINVAL; |
189 | if (msg->owner != owner) | ||
190 | return EACCES; | ||
191 | header_set_property (msg->header, property, msg); | ||
192 | body_set_property (msg->body, property, msg); | ||
193 | property_destroy (&(msg->property), msg); | ||
194 | msg->property = property; | ||
195 | return 0; | ||
196 | } | ||
197 | |||
198 | int | ||
199 | message_get_property (message_t msg, property_t *pproperty) | ||
200 | { | ||
201 | if (msg == NULL || pproperty == NULL) | ||
202 | return EINVAL; | ||
203 | if (msg->property == NULL) | ||
204 | { | ||
205 | int status = property_create (&(msg->property), msg); | ||
206 | if (status != 0) | ||
207 | return status; | ||
208 | header_set_property (msg->header, msg->property, msg); | ||
209 | body_set_property (msg->body, msg->property, msg); | ||
210 | } | ||
211 | *pproperty = msg->property; | ||
212 | return 0; | ||
213 | } | ||
214 | |||
215 | int | ||
216 | message_set_mailbox (message_t msg, mailbox_t mailbox, void *owner) | ||
217 | { | ||
218 | if (msg == NULL) | ||
219 | return EINVAL; | ||
220 | if (msg->owner != owner) | ||
221 | return EACCES; | ||
189 | msg->mailbox = mailbox; | 222 | msg->mailbox = mailbox; |
190 | return 0; | 223 | return 0; |
191 | } | 224 | } | ... | ... |
... | @@ -21,9 +21,13 @@ | ... | @@ -21,9 +21,13 @@ |
21 | 21 | ||
22 | #include <property0.h> | 22 | #include <property0.h> |
23 | 23 | ||
24 | static int property_find __P ((list_t, const char *, struct property_list **)); | 24 | static int property_find __P ((list_t, const char *, struct property_data **)); |
25 | static int property_add __P ((property_t, const char *, int, int *)); | 25 | static int property_add __P ((property_t, const char *, const char *, |
26 | static void property_update __P ((struct property_list *)); | 26 | int (*_set_value) |
27 | __P ((property_t, const char *, const char *)), | ||
28 | int (*_get_value) | ||
29 | __P ((property_t, const char *, char *, | ||
30 | size_t, size_t *)))); | ||
27 | static size_t property_hash __P ((const char *)); | 31 | static size_t property_hash __P ((const char *)); |
28 | 32 | ||
29 | int | 33 | int |
... | @@ -51,22 +55,21 @@ property_destroy (property_t *pp, void *owner) | ... | @@ -51,22 +55,21 @@ property_destroy (property_t *pp, void *owner) |
51 | /* Destroy the list and is properties. */ | 55 | /* Destroy the list and is properties. */ |
52 | if (prop->list) | 56 | if (prop->list) |
53 | { | 57 | { |
54 | struct property_list *pl = NULL; | 58 | struct property_data *pd = NULL; |
55 | iterator_t iterator = NULL; | 59 | iterator_t iterator = NULL; |
56 | 60 | ||
57 | iterator_create (&iterator, prop->list); | 61 | iterator_create (&iterator, prop->list); |
58 | |||
59 | for (iterator_first (iterator); !iterator_is_done (iterator); | 62 | for (iterator_first (iterator); !iterator_is_done (iterator); |
60 | iterator_next (iterator)) | 63 | iterator_next (iterator)) |
61 | { | 64 | { |
62 | iterator_current (iterator, (void **)&pl); | 65 | iterator_current (iterator, (void **)&pd); |
63 | if (pl) | 66 | if (pd) |
64 | { | 67 | { |
65 | if (pl->key) | 68 | if (pd->key) |
66 | free (pl->key); | 69 | free (pd->key); |
67 | if (pl->private_) | 70 | if (pd->value) |
68 | free (pl->private_); | 71 | free (pd->value); |
69 | free (pl); | 72 | free (pd); |
70 | } | 73 | } |
71 | } | 74 | } |
72 | iterator_destroy (&iterator); | 75 | iterator_destroy (&iterator); |
... | @@ -85,98 +88,126 @@ property_get_owner (property_t prop) | ... | @@ -85,98 +88,126 @@ property_get_owner (property_t prop) |
85 | } | 88 | } |
86 | 89 | ||
87 | int | 90 | int |
88 | property_add_default (property_t prop, const char *key, int *address, | 91 | property_add_defaults (property_t prop, const char *key, const char *value, |
92 | int (*_set_value) __P ((property_t, const char *, | ||
93 | const char *)), | ||
94 | int (*_get_value) __P ((property_t, const char *, | ||
95 | char *, size_t, size_t *)), | ||
89 | void *owner) | 96 | void *owner) |
90 | { | 97 | { |
91 | if (prop == NULL) | 98 | if (prop == NULL) |
92 | return EINVAL; | 99 | return EINVAL; |
93 | if (prop->owner != owner) | 100 | if (prop->owner != owner) |
94 | return EACCES; | 101 | return EACCES; |
95 | return property_add (prop, key, 0, address); | 102 | return property_add (prop, key, value, _set_value, _get_value); |
96 | } | 103 | } |
97 | 104 | ||
98 | int | 105 | int |
99 | property_set_value (property_t prop, const char *key, int value) | 106 | property_set_value (property_t prop, const char *key, const char *value) |
100 | { | 107 | { |
101 | 108 | ||
102 | if (prop == NULL) | 109 | if (prop == NULL) |
103 | return EINVAL; | 110 | return EINVAL; |
104 | return property_add (prop, key, value, NULL); | 111 | return property_add (prop, key, value, NULL, NULL); |
105 | } | 112 | } |
106 | 113 | ||
107 | int | 114 | int |
108 | property_get_value (property_t prop, const char *key, int *pvalue) | 115 | property_get_value (property_t prop, const char *key, char *buffer, |
116 | size_t buflen, size_t *n) | ||
109 | { | 117 | { |
110 | struct property_list *pl = NULL; | 118 | struct property_data *pd = NULL; |
111 | int status; | 119 | int status; |
120 | size_t len; | ||
112 | 121 | ||
113 | if (prop == NULL) | 122 | if (prop == NULL) |
114 | return EINVAL; | 123 | return EINVAL; |
115 | 124 | ||
116 | status = property_find (prop->list, key, &pl); | 125 | status = property_find (prop->list, key, &pd); |
117 | if (status != 0) | 126 | if (status != 0) |
118 | return status; | 127 | return status; |
119 | 128 | ||
120 | if (pl == NULL) | 129 | if (pd == NULL) |
121 | return ENOENT; | 130 | return ENOENT; |
122 | 131 | ||
123 | /* Update the value. */ | 132 | if (pd->_get_value) |
124 | property_update (pl); | 133 | return pd->_get_value (prop, key, buffer, buflen, n); |
125 | if (pvalue) | 134 | |
126 | *pvalue = pl->value; | 135 | len = (pd->value) ? strlen (pd->value) : 0; |
136 | if (buffer && buflen != 0) | ||
137 | { | ||
138 | buflen--; | ||
139 | len = (buflen < len) ? buflen : len; | ||
140 | strncpy (buffer, pd->value, len)[len] = '\0'; | ||
141 | } | ||
142 | if (n) | ||
143 | *n = len; | ||
127 | return 0; | 144 | return 0; |
128 | } | 145 | } |
129 | 146 | ||
147 | #if 0 | ||
130 | int | 148 | int |
131 | property_set (property_t prop, const char *k) | 149 | property_load (property_t prop, stream_t stream) |
132 | { | 150 | { |
133 | return property_set_value (prop, k, 1); | 151 | size_t n = 0; |
152 | off_t off = 0; | ||
153 | int status; | ||
154 | int buflen = 512; | ||
155 | char *buf = calloc (buflen, sizeof (*buf)); | ||
156 | if (buf == NULL) | ||
157 | return ENOMEM; | ||
158 | |||
159 | while ((status = stream_readline (stream, buf, buflen, off, &n)) == 0 | ||
160 | && n > 0) | ||
161 | { | ||
162 | char *sep; | ||
163 | if (buf[n] != '\n') | ||
164 | { | ||
165 | char *tmp; | ||
166 | buflen *= 2; | ||
167 | tmp = realloc (buf, buflen); | ||
168 | if (tmp == NULL) | ||
169 | { | ||
170 | free (buf); | ||
171 | return ENOMEM; | ||
172 | } | ||
173 | buf = tmp; | ||
174 | continue; | ||
175 | } | ||
176 | sep = strchr (buf, '='); | ||
177 | if (sep) | ||
178 | { | ||
179 | *sep++ = '\0'; | ||
180 | property_set_value (prop, buf, sep); | ||
181 | } | ||
182 | else | ||
183 | property_set (prop, buf); | ||
184 | } | ||
185 | return 0; | ||
134 | } | 186 | } |
187 | #endif | ||
135 | 188 | ||
136 | int | 189 | int |
137 | property_unset (property_t prop, const char *k) | 190 | property_set (property_t prop, const char *k) |
138 | { | 191 | { |
139 | int v = 0; | 192 | if (!property_is_set (prop, k)) |
140 | property_get_value (prop, k, &v); | 193 | return property_set_value (prop, k, "1"); |
141 | if (v != 0) | ||
142 | return property_set_value (prop, k, 0); | ||
143 | return 0; | 194 | return 0; |
144 | } | 195 | } |
145 | 196 | ||
146 | int | 197 | int |
147 | property_is_set (property_t prop, const char *k) | 198 | property_unset (property_t prop, const char *k) |
148 | { | 199 | { |
149 | int v = 0; | 200 | if (property_is_set (prop, k)) |
150 | property_get_value (prop, k, &v); | 201 | return property_set_value (prop, k, NULL); |
151 | return (v != 0); | 202 | return 0; |
152 | } | 203 | } |
153 | 204 | ||
154 | int | 205 | int |
155 | property_get_list (property_t prop, list_t *plist) | 206 | property_is_set (property_t prop, const char *k) |
156 | { | 207 | { |
157 | struct property_list *pl = NULL; | 208 | int n = 0; |
158 | iterator_t iterator = NULL; | 209 | property_get_value (prop, k, NULL, 0, &n); |
159 | int status; | 210 | return (n != 0); |
160 | |||
161 | if (plist == NULL || prop == NULL) | ||
162 | return EINVAL; | ||
163 | |||
164 | status = iterator_create (&iterator, prop->list); | ||
165 | if (status != 0) | ||
166 | return status; | ||
167 | |||
168 | /* Make sure the values are updated before passing it outside. */ | ||
169 | for (iterator_first (iterator); !iterator_is_done (iterator); | ||
170 | iterator_next (iterator)) | ||
171 | { | ||
172 | iterator_current (iterator, (void **)&pl); | ||
173 | if (pl) | ||
174 | property_update (pl); | ||
175 | } | ||
176 | iterator_destroy (&iterator); | ||
177 | |||
178 | *plist = prop->list; | ||
179 | return 0; | ||
180 | } | 211 | } |
181 | 212 | ||
182 | /* Taking from an article in Dr Dobbs. */ | 213 | /* Taking from an article in Dr Dobbs. */ |
... | @@ -196,24 +227,12 @@ property_hash (const char *s) | ... | @@ -196,24 +227,12 @@ property_hash (const char *s) |
196 | return hashval; | 227 | return hashval; |
197 | } | 228 | } |
198 | 229 | ||
199 | static void | ||
200 | property_update (struct property_list *pl) | ||
201 | { | ||
202 | /* Update the value. */ | ||
203 | if (pl->private_) | ||
204 | { | ||
205 | struct property_private *private_ = pl->private_; | ||
206 | if (private_->address) | ||
207 | pl->value = *(private_->address); | ||
208 | } | ||
209 | } | ||
210 | |||
211 | static int | 230 | static int |
212 | property_find (list_t list, const char *key, struct property_list **p) | 231 | property_find (list_t list, const char *key, struct property_data **p) |
213 | { | 232 | { |
214 | int status; | 233 | int status; |
215 | size_t h; | 234 | size_t h; |
216 | struct property_list *pl = NULL; | 235 | struct property_data *pd = NULL; |
217 | iterator_t iterator; | 236 | iterator_t iterator; |
218 | 237 | ||
219 | status = iterator_create (&iterator, list); | 238 | status = iterator_create (&iterator, list); |
... | @@ -224,28 +243,30 @@ property_find (list_t list, const char *key, struct property_list **p) | ... | @@ -224,28 +243,30 @@ property_find (list_t list, const char *key, struct property_list **p) |
224 | for (iterator_first (iterator); !iterator_is_done (iterator); | 243 | for (iterator_first (iterator); !iterator_is_done (iterator); |
225 | iterator_next (iterator)) | 244 | iterator_next (iterator)) |
226 | { | 245 | { |
227 | iterator_current (iterator, (void **)&pl); | 246 | iterator_current (iterator, (void **)&pd); |
228 | if (pl) | 247 | if (pd) |
229 | { | 248 | { |
230 | struct property_private *private_ = pl->private_; | 249 | if (pd->hash == h) |
231 | if (private_->hash == h) | 250 | if (pd->key && strcasecmp (pd->key, key) == 0) |
232 | if (strcasecmp (pl->key, key) == 0) | ||
233 | break; | 251 | break; |
234 | } | 252 | } |
235 | pl = NULL; | 253 | pd = NULL; |
236 | } | 254 | } |
237 | iterator_destroy (&iterator); | 255 | iterator_destroy (&iterator); |
238 | *p = pl; | 256 | *p = pd; |
239 | return 0; | 257 | return 0; |
240 | } | 258 | } |
241 | 259 | ||
242 | static int | 260 | static int |
243 | property_add (property_t prop, const char *key, int value, int *address) | 261 | property_add (property_t prop, const char *key, const char *value, |
262 | int (*_set_value) __P ((property_t, const char *, const char *)), | ||
263 | int (*_get_value) __P ((property_t, const char *, char *, | ||
264 | size_t, size_t *))) | ||
244 | { | 265 | { |
245 | struct property_list *pl = NULL; | 266 | struct property_data *pd = NULL; |
246 | int status; | 267 | int status; |
247 | 268 | ||
248 | if (key == NULL) | 269 | if (key == NULL || *key == '\0') |
249 | return EINVAL; | 270 | return EINVAL; |
250 | 271 | ||
251 | if (prop->list == NULL) | 272 | if (prop->list == NULL) |
... | @@ -255,47 +276,26 @@ property_add (property_t prop, const char *key, int value, int *address) | ... | @@ -255,47 +276,26 @@ property_add (property_t prop, const char *key, int value, int *address) |
255 | return status; | 276 | return status; |
256 | } | 277 | } |
257 | 278 | ||
258 | status = property_find (prop->list, key, &pl); | 279 | status = property_find (prop->list, key, &pd); |
259 | if (status != 0) | 280 | if (status != 0) |
260 | return status; | 281 | return status; |
261 | 282 | ||
262 | /* None find create a new one. */ | 283 | /* None find create a new one. */ |
263 | if (pl == NULL) | 284 | if (pd == NULL) |
264 | { | ||
265 | struct property_private *private_; | ||
266 | pl = calloc (1, sizeof (*pl)); | ||
267 | if (pl == NULL) | ||
268 | return ENOMEM; | ||
269 | private_ = calloc (1, sizeof (*private_)); | ||
270 | if (private_ == NULL) | ||
271 | { | 285 | { |
272 | free (pl); | 286 | pd = calloc (1, sizeof (*pd)); |
287 | if (pd == NULL) | ||
273 | return ENOMEM; | 288 | return ENOMEM; |
289 | pd->hash = property_hash (key); | ||
290 | list_append (prop->list, (void *)pd); | ||
274 | } | 291 | } |
275 | pl->key = strdup (key); | 292 | |
276 | if (pl->key == NULL) | 293 | if (pd->key == NULL) |
277 | { | 294 | pd->key = strdup (key); |
278 | free (private_); | 295 | if (pd->value) |
279 | free (pl); | 296 | free (pd->value); |
280 | return ENOMEM; | 297 | pd->value = (value) ? strdup (value) : NULL; |
281 | } | 298 | pd->_set_value = _set_value; |
282 | pl->value = value; | 299 | pd->_get_value = _get_value; |
283 | private_->hash = property_hash (key); | ||
284 | private_->address = address; | ||
285 | pl->private_ = private_; | ||
286 | list_append (prop->list, (void *)pl); | ||
287 | } | ||
288 | else | ||
289 | { | ||
290 | struct property_private *private_ = pl->private_; | ||
291 | if (address) | ||
292 | private_->address = address; | ||
293 | else | ||
294 | { | ||
295 | if (private_->address) | ||
296 | *(private_->address) = value; | ||
297 | pl->value = value; | ||
298 | } | ||
299 | } | ||
300 | return 0; | 300 | return 0; |
301 | } | 301 | } | ... | ... |
... | @@ -86,8 +86,8 @@ _mailer_sendmail_init (mailer_t mailer) | ... | @@ -86,8 +86,8 @@ _mailer_sendmail_init (mailer_t mailer) |
86 | if (mailer->properties == NULL) | 86 | if (mailer->properties == NULL) |
87 | return ENOMEM; | 87 | return ENOMEM; |
88 | mailer->properties_count = 1; | 88 | mailer->properties_count = 1; |
89 | mailer->properties[0].key = strdup ("SENDMAIL"); | 89 | mailer->properties[0].key = strdup ("TYPE"); |
90 | mailer->properties[0].value = 1; | 90 | mailer->properties[0].value = strdup ("SENDMAIL"); |
91 | return 0; | 91 | return 0; |
92 | } | 92 | } |
93 | 93 | ... | ... |
... | @@ -164,8 +164,8 @@ _mailer_smtp_init (mailer_t mailer) | ... | @@ -164,8 +164,8 @@ _mailer_smtp_init (mailer_t mailer) |
164 | if (mailer->properties == NULL) | 164 | if (mailer->properties == NULL) |
165 | return ENOMEM; | 165 | return ENOMEM; |
166 | mailer->properties_count = 1; | 166 | mailer->properties_count = 1; |
167 | mailer->properties[0].key = strdup ("SMTP"); | 167 | mailer->properties[0].key = strdup ("TYPE"); |
168 | mailer->properties[0].value = 1; | 168 | mailer->properties[0].value = strdup ("SMTP"); |
169 | 169 | ||
170 | return 0; | 170 | return 0; |
171 | } | 171 | } | ... | ... |
... | @@ -41,7 +41,9 @@ static int refill (stream_t, off_t); | ... | @@ -41,7 +41,9 @@ static int refill (stream_t, off_t); |
41 | /* Stream is a way for object to do I/O, they can take over(overload) the | 41 | /* Stream is a way for object to do I/O, they can take over(overload) the |
42 | the read/write functions for there needs. We are doing some very | 42 | the read/write functions for there needs. We are doing some very |
43 | minimal buffering on the read when the stream_bufsiz is set, this | 43 | minimal buffering on the read when the stream_bufsiz is set, this |
44 | unfortunately does not take to account the offset, this buffering is more | 44 | unfortunately does not take to account the offset i.e if the offset ask |
45 | is different then the offset we maintain internally, the buffer is flushed | ||
46 | and a new buffer is use, this buffering is more | ||
45 | for networking stream (POP/IMAP). No buffering on the write. */ | 47 | for networking stream (POP/IMAP). No buffering on the write. */ |
46 | int | 48 | int |
47 | stream_create (stream_t *pstream, int flags, void *owner) | 49 | stream_create (stream_t *pstream, int flags, void *owner) |
... | @@ -116,6 +118,12 @@ stream_close (stream_t stream) | ... | @@ -116,6 +118,12 @@ stream_close (stream_t stream) |
116 | } | 118 | } |
117 | 119 | ||
118 | int | 120 | int |
121 | stream_is_seekable (stream_t stream) | ||
122 | { | ||
123 | return (stream) ? stream->flags & MU_STREAM_SEEKABLE : 0; | ||
124 | } | ||
125 | |||
126 | int | ||
119 | stream_setbufsiz (stream_t stream, size_t size) | 127 | stream_setbufsiz (stream_t stream, size_t size) |
120 | { | 128 | { |
121 | if (stream == NULL) | 129 | if (stream == NULL) |
... | @@ -396,6 +404,34 @@ stream_get_flags (stream_t stream, int *pfl) | ... | @@ -396,6 +404,34 @@ stream_get_flags (stream_t stream, int *pfl) |
396 | } | 404 | } |
397 | 405 | ||
398 | int | 406 | int |
407 | stream_set_property (stream_t stream, property_t property, void *owner) | ||
408 | { | ||
409 | if (stream == NULL) | ||
410 | return EINVAL; | ||
411 | if (stream->owner != owner) | ||
412 | return EACCES; | ||
413 | if (stream->property) | ||
414 | property_destroy (&(stream->property), stream); | ||
415 | stream->property = property; | ||
416 | return 0; | ||
417 | } | ||
418 | |||
419 | int | ||
420 | stream_get_property (stream_t stream, property_t *pp) | ||
421 | { | ||
422 | if (stream == NULL) | ||
423 | return EINVAL; | ||
424 | if (stream->property == NULL) | ||
425 | { | ||
426 | int status = property_create (&(stream->property), stream); | ||
427 | if (status != 0) | ||
428 | return status; | ||
429 | } | ||
430 | *pp = stream->property; | ||
431 | return 0; | ||
432 | } | ||
433 | |||
434 | int | ||
399 | stream_size (stream_t stream, off_t *psize) | 435 | stream_size (stream_t stream, off_t *psize) |
400 | { | 436 | { |
401 | if (stream == NULL || stream->_size == NULL) | 437 | if (stream == NULL || stream->_size == NULL) | ... | ... |
This diff is collapsed.
Click to expand it.
-
Please register or sign in to post a comment