Commit f30fe5bf f30fe5bfa76d2631c1480ac31e487f23a03868a5 by Alain Magloire

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.
1 parent 360bc51c
...@@ -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
......
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
......
...@@ -48,6 +48,7 @@ struct rbuffer ...@@ -48,6 +48,7 @@ struct rbuffer
48 struct _stream 48 struct _stream
49 { 49 {
50 void *owner; 50 void *owner;
51 property_t property;
51 52
52 int flags; 53 int flags;
53 int state; 54 int state;
......
...@@ -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)
......