attribute.c attribute.h attribute0.h header.c header.h
header0.h mailbox.c mailbox.h mailbox0.h mbx_mbox.c mbx_unix.c message.c registrar.c registrar.h registrar0.h rfc822.c url.c more cleanups.
Showing
17 changed files
with
692 additions
and
227 deletions
... | @@ -62,7 +62,6 @@ attribute_set_answered (attribute_t attr) | ... | @@ -62,7 +62,6 @@ attribute_set_answered (attribute_t attr) |
62 | if (attr == NULL) | 62 | if (attr == NULL) |
63 | return EINVAL; | 63 | return EINVAL; |
64 | attr->flag|= MU_ATTRIBUTE_ANSWERED; | 64 | attr->flag|= MU_ATTRIBUTE_ANSWERED; |
65 | attr->flag |= MU_ATTRIBUTE_SEEN; | ||
66 | return 0; | 65 | return 0; |
67 | } | 66 | } |
68 | 67 | ||
... | @@ -72,7 +71,6 @@ attribute_set_flagged (attribute_t attr) | ... | @@ -72,7 +71,6 @@ attribute_set_flagged (attribute_t attr) |
72 | if (attr == NULL) | 71 | if (attr == NULL) |
73 | return EINVAL; | 72 | return EINVAL; |
74 | attr->flag |= MU_ATTRIBUTE_FLAGGED; | 73 | attr->flag |= MU_ATTRIBUTE_FLAGGED; |
75 | attr->flag |= MU_ATTRIBUTE_SEEN; | ||
76 | return 0; | 74 | return 0; |
77 | } | 75 | } |
78 | 76 | ||
... | @@ -82,7 +80,6 @@ attribute_set_read (attribute_t attr) | ... | @@ -82,7 +80,6 @@ attribute_set_read (attribute_t attr) |
82 | if (attr == NULL) | 80 | if (attr == NULL) |
83 | return EINVAL; | 81 | return EINVAL; |
84 | attr->flag |= MU_ATTRIBUTE_READ; | 82 | attr->flag |= MU_ATTRIBUTE_READ; |
85 | attr->flag |= MU_ATTRIBUTE_SEEN; | ||
86 | return 0; | 83 | return 0; |
87 | } | 84 | } |
88 | 85 | ||
... | @@ -175,9 +172,6 @@ attribute_unset_seen (attribute_t attr) | ... | @@ -175,9 +172,6 @@ attribute_unset_seen (attribute_t attr) |
175 | if (attr == NULL) | 172 | if (attr == NULL) |
176 | return 0; | 173 | return 0; |
177 | attr->flag ^= MU_ATTRIBUTE_SEEN; | 174 | attr->flag ^= MU_ATTRIBUTE_SEEN; |
178 | attr->flag ^= MU_ATTRIBUTE_ANSWERED; | ||
179 | attr->flag ^= MU_ATTRIBUTE_FLAGGED; | ||
180 | attr->flag ^= MU_ATTRIBUTE_READ; | ||
181 | return 0; | 175 | return 0; |
182 | } | 176 | } |
183 | 177 | ||
... | @@ -235,3 +229,38 @@ attribute_unset_recent (attribute_t attr) | ... | @@ -235,3 +229,38 @@ attribute_unset_recent (attribute_t attr) |
235 | return 0; | 229 | return 0; |
236 | } | 230 | } |
237 | 231 | ||
232 | int | ||
233 | attribute_is_equal (attribute_t attr, attribute_t attr2) | ||
234 | { | ||
235 | if (attr == NULL || attr2 == NULL) | ||
236 | return 0; | ||
237 | return attr->flag == attr2->flag; | ||
238 | } | ||
239 | |||
240 | int | ||
241 | attribute_copy (attribute_t dest, attribute_t src) | ||
242 | { | ||
243 | if (dest == NULL || src == NULL) | ||
244 | return EINVAL; | ||
245 | memcpy (dest, src, sizeof (*dest)); | ||
246 | return 0; | ||
247 | } | ||
248 | |||
249 | int | ||
250 | attribute_set_owner (attribute_t attr, message_t *msg) | ||
251 | { | ||
252 | if (attr == NULL) | ||
253 | return EINVAL; | ||
254 | attr->message = msg; | ||
255 | return 0; | ||
256 | } | ||
257 | |||
258 | int | ||
259 | attribute_get_owner (attribute_t attr, message_t *msg) | ||
260 | { | ||
261 | if (attr == NULL) | ||
262 | return EINVAL; | ||
263 | if (msg) | ||
264 | *msg = attr->message; | ||
265 | return 0; | ||
266 | } | ... | ... |
... | @@ -60,6 +60,8 @@ extern int attribute_unset_draft __P ((attribute_t)); | ... | @@ -60,6 +60,8 @@ extern int attribute_unset_draft __P ((attribute_t)); |
60 | extern int attribute_unset_recent __P ((attribute_t)); | 60 | extern int attribute_unset_recent __P ((attribute_t)); |
61 | extern int attribute_unset_read __P ((attribute_t)); | 61 | extern int attribute_unset_read __P ((attribute_t)); |
62 | 62 | ||
63 | extern int attribute_is_equal __P ((attribute_t att1, attribute_t att2)); | ||
64 | |||
63 | #ifdef __cplusplus | 65 | #ifdef __cplusplus |
64 | } | 66 | } |
65 | #endif | 67 | #endif | ... | ... |
... | @@ -18,6 +18,7 @@ | ... | @@ -18,6 +18,7 @@ |
18 | #ifndef _ATTRIBUTE0_H | 18 | #ifndef _ATTRIBUTE0_H |
19 | #define _ATTRIBUTE0_H | 19 | #define _ATTRIBUTE0_H |
20 | 20 | ||
21 | #include <message.h> | ||
21 | #include <attribute.h> | 22 | #include <attribute.h> |
22 | 23 | ||
23 | #include <sys/types.h> | 24 | #include <sys/types.h> |
... | @@ -48,6 +49,11 @@ struct _attribute | ... | @@ -48,6 +49,11 @@ struct _attribute |
48 | void *message; | 49 | void *message; |
49 | }; | 50 | }; |
50 | 51 | ||
52 | /* not user visible ?? */ | ||
53 | extern int attribute_copy __P ((attribute_t dst, attribute_t src)); | ||
54 | extern int attribute_set_owner __P ((attribute_t attr, message_t *msg)); | ||
55 | extern int attribute_get_owner __P ((attribute_t attr, message_t *msg)); | ||
56 | |||
51 | #ifdef __cplusplus | 57 | #ifdef __cplusplus |
52 | } | 58 | } |
53 | #endif | 59 | #endif | ... | ... |
... | @@ -45,7 +45,7 @@ int | ... | @@ -45,7 +45,7 @@ int |
45 | header_set_value (header_t h, const char *fn, const char *fb, size_t n, | 45 | header_set_value (header_t h, const char *fn, const char *fb, size_t n, |
46 | int replace) | 46 | int replace) |
47 | { | 47 | { |
48 | if (h == NULL) | 48 | if (h == NULL || h->_set_value == NULL) |
49 | return EINVAL; | 49 | return EINVAL; |
50 | return h->_set_value (h, fn, fb, n, replace); | 50 | return h->_set_value (h, fn, fb, n, replace); |
51 | } | 51 | } |
... | @@ -54,15 +54,41 @@ int | ... | @@ -54,15 +54,41 @@ int |
54 | header_get_value (header_t h, const char *fn, char *fb, | 54 | header_get_value (header_t h, const char *fn, char *fb, |
55 | size_t len, size_t *n) | 55 | size_t len, size_t *n) |
56 | { | 56 | { |
57 | if (h == NULL) | 57 | if (h == NULL || h->_get_value == NULL ) |
58 | return EINVAL; | 58 | return EINVAL; |
59 | return h->_get_value (h, fn, fb, len, n); | 59 | return h->_get_value (h, fn, fb, len, n); |
60 | } | 60 | } |
61 | 61 | ||
62 | int | ||
63 | header_entry_name (header_t h, size_t num, char *buf, size_t len, size_t *n) | ||
64 | { | ||
65 | if (h == NULL || h->_entry_name == NULL) | ||
66 | return EINVAL; | ||
67 | |||
68 | return h->_entry_name (h, num, buf, len, n); | ||
69 | } | ||
70 | |||
71 | int | ||
72 | header_entry_value (header_t h, size_t num, char *buf, size_t len, size_t *n) | ||
73 | { | ||
74 | if (h == NULL || h->_entry_value == NULL) | ||
75 | return EINVAL; | ||
76 | |||
77 | return h->_entry_value (h, num, buf, len, n); | ||
78 | } | ||
79 | |||
80 | int | ||
81 | header_entry_count (header_t h, size_t *num) | ||
82 | { | ||
83 | if (h == NULL || h->_entry_count) | ||
84 | return EINVAL; | ||
85 | return h->_entry_count (h, num); | ||
86 | } | ||
87 | |||
62 | ssize_t | 88 | ssize_t |
63 | header_get_data (header_t h, char *data, size_t len, off_t off, int *err) | 89 | header_get_data (header_t h, char *data, size_t len, off_t off, int *err) |
64 | { | 90 | { |
65 | if (h == NULL) | 91 | if (h == NULL || h->_get_data) |
66 | return EINVAL; | 92 | return EINVAL; |
67 | return h->_get_data (h, data, len, off, err); | 93 | return h->_get_data (h, data, len, off, err); |
68 | } | 94 | } | ... | ... |
... | @@ -67,16 +67,19 @@ extern "C" { | ... | @@ -67,16 +67,19 @@ extern "C" { |
67 | struct _header; | 67 | struct _header; |
68 | typedef struct _header * header_t; | 68 | typedef struct _header * header_t; |
69 | 69 | ||
70 | extern int header_init __P ((header_t *, const char *blurb, | 70 | extern int header_init __P ((header_t *, const char *blurb, |
71 | size_t ln, int flag)); | 71 | size_t ln, int flag)); |
72 | extern void header_destroy __P ((header_t *)); | 72 | extern void header_destroy __P ((header_t *)); |
73 | 73 | ||
74 | extern int header_set_value __P ((header_t, const char *fn, | 74 | extern int header_set_value __P ((header_t, const char *fn, |
75 | const char *fv, size_t n, int replace)); | 75 | const char *fv, size_t n, int replace)); |
76 | extern int header_get_value __P ((header_t, const char *fn, char *fv, | 76 | extern int header_get_value __P ((header_t, const char *fn, char *fv, |
77 | size_t len, size_t *n)); | 77 | size_t len, size_t *nwritten)); |
78 | extern ssize_t header_get_data __P ((header_t h, char *data, | 78 | extern int header_entry_count __P ((header_t, size_t *num)); |
79 | size_t len, off_t off, int *err)); | 79 | extern int header_entry_name __P ((header_t, size_t num, char *buf, |
80 | size_t buflen, size_t *total)); | ||
81 | extern int header_entry_value __P ((header_t, size_t num, char *buf, | ||
82 | size_t buflen, size_t *total)); | ||
80 | #ifdef _cpluscplus | 83 | #ifdef _cpluscplus |
81 | } | 84 | } |
82 | #endif | 85 | #endif | ... | ... |
... | @@ -44,6 +44,7 @@ typedef struct _hdr *hdr_t; | ... | @@ -44,6 +44,7 @@ typedef struct _hdr *hdr_t; |
44 | 44 | ||
45 | struct _header | 45 | struct _header |
46 | { | 46 | { |
47 | size_t num; | ||
47 | /* Data */ | 48 | /* Data */ |
48 | void *data; | 49 | void *data; |
49 | /* owner ? */ | 50 | /* owner ? */ |
... | @@ -56,13 +57,23 @@ struct _header | ... | @@ -56,13 +57,23 @@ struct _header |
56 | size_t n, int replace)); | 57 | size_t n, int replace)); |
57 | int (*_get_value) __P ((header_t, const char *fn, char *fv, | 58 | int (*_get_value) __P ((header_t, const char *fn, char *fv, |
58 | size_t len, size_t *n)); | 59 | size_t len, size_t *n)); |
59 | ssize_t (*_get_data) __P ((header_t h, char *data, | 60 | int (*_entry_count) __P ((header_t, size_t *)); |
60 | size_t len, off_t off, int *err)); | 61 | int (*_entry_name) __P ((header_t, size_t num, char *buf, |
62 | size_t buflen, size_t *nwritten)); | ||
63 | int (*_entry_value) __P ((header_t, size_t num, char *buf, | ||
64 | size_t buflen, size_t *nwritten)); | ||
65 | ssize_t (*_get_data) __P ((header_t h, char *data, size_t len, | ||
66 | off_t off, int *err)); | ||
61 | int (*_parse) __P ((header_t, const char *blurb, size_t len)); | 67 | int (*_parse) __P ((header_t, const char *blurb, size_t len)); |
62 | } ; | 68 | }; |
69 | |||
70 | extern ssize_t header_get_data __P ((header_t h, char *data, | ||
71 | size_t len, off_t off, int *err)); | ||
63 | 72 | ||
73 | /* rfc822 */ | ||
64 | extern int rfc822_init __P ((header_t *ph, const char *blurb, size_t len)); | 74 | extern int rfc822_init __P ((header_t *ph, const char *blurb, size_t len)); |
65 | extern void rfc822_destroy __P ((header_t *ph)); | 75 | extern void rfc822_destroy __P ((header_t *ph)); |
76 | |||
66 | #ifdef _cpluscplus | 77 | #ifdef _cpluscplus |
67 | } | 78 | } |
68 | #endif | 79 | #endif | ... | ... |
... | @@ -61,11 +61,7 @@ mailbox_init (mailbox_t *pmbox, const char *name, int id) | ... | @@ -61,11 +61,7 @@ mailbox_init (mailbox_t *pmbox, const char *name, int id) |
61 | 61 | ||
62 | /* if things went ok set mreg for mailbox_destroy and the URL */ | 62 | /* if things went ok set mreg for mailbox_destroy and the URL */ |
63 | if (status == 0) | 63 | if (status == 0) |
64 | { | 64 | (*pmbox)->url = url; |
65 | (*pmbox)->url = url; | ||
66 | (*pmbox)->_init = mreg->_init; | ||
67 | (*pmbox)->_destroy = mreg->_destroy; | ||
68 | } | ||
69 | return status; | 65 | return status; |
70 | } | 66 | } |
71 | 67 | ||
... | @@ -245,10 +241,26 @@ mailbox_set_auth (mailbox_t mbox, auth_t auth) | ... | @@ -245,10 +241,26 @@ mailbox_set_auth (mailbox_t mbox, auth_t auth) |
245 | } | 241 | } |
246 | 242 | ||
247 | int | 243 | int |
248 | mailbox_get_auth (mailbox_t mbox, auth_t *auth) | 244 | mailbox_get_auth (mailbox_t mbox, auth_t *pauth) |
249 | { | 245 | { |
250 | if (mbox == NULL || auth == NULL) | 246 | if (mbox == NULL || pauth == NULL) |
251 | return EINVAL; | 247 | return EINVAL; |
252 | *auth = mbox->auth; | 248 | *pauth = mbox->auth; |
253 | return 0; | 249 | return 0; |
254 | } | 250 | } |
251 | |||
252 | int | ||
253 | mailbox_get_attribute (mailbox_t mbox, size_t msgno, attribute_t *pattr) | ||
254 | { | ||
255 | if (mbox == NULL || mbox->_get_attribute == NULL) | ||
256 | return ENOSYS; | ||
257 | return mbox->_get_attribute (mbox, msgno, pattr); | ||
258 | } | ||
259 | |||
260 | int | ||
261 | mailbox_set_attribute (mailbox_t mbox, size_t msgno, attribute_t attr) | ||
262 | { | ||
263 | if (mbox == NULL || mbox->_set_attribute == NULL) | ||
264 | return ENOSYS; | ||
265 | return mbox->_set_attribute (mbox, msgno, attr); | ||
266 | } | ... | ... |
... | @@ -81,10 +81,14 @@ struct _mailbox | ... | @@ -81,10 +81,14 @@ struct _mailbox |
81 | int (*_get_size) __P ((mailbox_t, size_t msgno, | 81 | int (*_get_size) __P ((mailbox_t, size_t msgno, |
82 | size_t *h, size_t *b)); | 82 | size_t *h, size_t *b)); |
83 | 83 | ||
84 | ssize_t (*_get_header) __P ((mailbox_t, size_t msgno, char *h, | 84 | ssize_t (*_get_header) __P ((mailbox_t, size_t msgno, char *h, |
85 | size_t len, off_t off, int *err)); | 85 | size_t len, off_t off, int *err)); |
86 | ssize_t (*_get_body) __P ((mailbox_t, size_t msgno, char *b, | 86 | ssize_t (*_get_body) __P ((mailbox_t, size_t msgno, char *b, |
87 | size_t len, off_t off, int *err)); | 87 | size_t len, off_t off, int *err)); |
88 | int (*_get_attribute) __P ((mailbox_t mbox, size_t msgno, | ||
89 | attribute_t *attr)); | ||
90 | int (*_set_attribute) __P ((mailbox_t mbox, size_t msgno, | ||
91 | attribute_t attr)); | ||
88 | }; | 92 | }; |
89 | 93 | ||
90 | /* private */ | 94 | /* private */ |
... | @@ -103,6 +107,10 @@ extern int mailbox_get_auth __P ((mailbox_t mbox, auth_t *auth)); | ... | @@ -103,6 +107,10 @@ extern int mailbox_get_auth __P ((mailbox_t mbox, auth_t *auth)); |
103 | extern int mailbox_set_auth __P ((mailbox_t mbox, auth_t auth)); | 107 | extern int mailbox_set_auth __P ((mailbox_t mbox, auth_t auth)); |
104 | extern int mailbox_get_locker __P ((mailbox_t mbox, locker_t *locker)); | 108 | extern int mailbox_get_locker __P ((mailbox_t mbox, locker_t *locker)); |
105 | extern int mailbox_set_locker __P ((mailbox_t mbox, locker_t locker)); | 109 | extern int mailbox_set_locker __P ((mailbox_t mbox, locker_t locker)); |
110 | extern int mailbox_get_attribute __P ((mailbox_t mbox, size_t msgno, | ||
111 | attribute_t *attr)); | ||
112 | extern int mailbox_set_attribute __P ((mailbox_t mbox, size_t msgno, | ||
113 | attribute_t attr)); | ||
106 | extern int mailbox_progress __P ((mailbox_t mbox, | 114 | extern int mailbox_progress __P ((mailbox_t mbox, |
107 | int (*progress) (int, void *arg), | 115 | int (*progress) (int, void *arg), |
108 | void *arg)); | 116 | void *arg)); | ... | ... |
... | @@ -32,33 +32,42 @@ struct mailbox_registrar _mailbox_mbox_registrar = | ... | @@ -32,33 +32,42 @@ struct mailbox_registrar _mailbox_mbox_registrar = |
32 | }; | 32 | }; |
33 | 33 | ||
34 | /* | 34 | /* |
35 | if there is no specific URL for file mailbox, | 35 | Caveat there is no specific URL for file mailbox or simple path name, |
36 | file://<path_name> | 36 | <path_name> |
37 | file:<path_name> | ||
37 | 38 | ||
38 | It would be preferrable to use : | 39 | It would be preferrable to use : |
39 | maildir://<path> | 40 | maildir:<path> |
40 | unix://<path> | 41 | unix:<path> |
41 | mmdf://<path> | 42 | mmdf:<path> |
42 | This would eliminate heuristic discovery that would turn | 43 | This would eliminate heuristic discovery that would turn |
43 | out to be wrong. Caveat, there is no std URL for those | 44 | out to be wrong. |
44 | mailbox. | ||
45 | */ | 45 | */ |
46 | 46 | ||
47 | static int | 47 | static int |
48 | mailbox_mbox_init (mailbox_t *mbox, const char *name) | 48 | mailbox_mbox_init (mailbox_t *mbox, const char *name) |
49 | { | 49 | { |
50 | struct stat st; | 50 | struct stat st; |
51 | char *scheme = strstr (name, "://"); | 51 | size_t len; |
52 | 52 | ||
53 | if (scheme) | 53 | if (name == NULL || mbox == NULL) |
54 | return EINVAL; | ||
55 | |||
56 | len = strlen (name); | ||
57 | if (len >= 5 && | ||
58 | (name[0] == 'f' || name[0] == 'F') && | ||
59 | (name[1] == 'i' || name[1] == 'I') && | ||
60 | (name[2] == 'l' || name[2] == 'L') && | ||
61 | (name[3] == 'e' || name[3] == 'E') && | ||
62 | name[4] == ':') | ||
54 | { | 63 | { |
55 | scheme += 3; | 64 | name += 5; |
56 | name = scheme; | ||
57 | } | 65 | } |
58 | /* | 66 | /* |
59 | If they want to creat ?? should they know the type ??? | 67 | * If they want to creat ?? should they know the type ??? |
60 | What is the best course of action ?? | 68 | * What is the best course of action ?? |
61 | */ | 69 | * For the default is unix if the file does not exist. |
70 | */ | ||
62 | if (stat (name, &st) < 0) | 71 | if (stat (name, &st) < 0) |
63 | return _mailbox_unix_registrar._init (mbox, name); | 72 | return _mailbox_unix_registrar._init (mbox, name); |
64 | 73 | ||
... | @@ -99,7 +108,7 @@ mailbox_mbox_init (mailbox_t *mbox, const char *name) | ... | @@ -99,7 +108,7 @@ mailbox_mbox_init (mailbox_t *mbox, const char *name) |
99 | { | 108 | { |
100 | if (strncmp (head, "From ", 5) == 0) | 109 | if (strncmp (head, "From ", 5) == 0) |
101 | { | 110 | { |
102 | /* This is Unix Mbox */ | 111 | /* This is a Unix Mbox */ |
103 | close (fd); | 112 | close (fd); |
104 | return _mailbox_unix_registrar._init (mbox, name); | 113 | return _mailbox_unix_registrar._init (mbox, name); |
105 | } | 114 | } | ... | ... |
... | @@ -15,6 +15,8 @@ | ... | @@ -15,6 +15,8 @@ |
15 | along with this program; if not, write to the Free Software | 15 | along with this program; if not, write to the Free Software |
16 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ | 16 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ |
17 | 17 | ||
18 | /* First draft by Alain Magloire */ | ||
19 | |||
18 | #include <mailbox0.h> | 20 | #include <mailbox0.h> |
19 | #include <registrar0.h> | 21 | #include <registrar0.h> |
20 | #include <message0.h> | 22 | #include <message0.h> |
... | @@ -40,6 +42,7 @@ | ... | @@ -40,6 +42,7 @@ |
40 | #endif | 42 | #endif |
41 | #include <string.h> | 43 | #include <string.h> |
42 | #include <ctype.h> | 44 | #include <ctype.h> |
45 | #include <limits.h> | ||
43 | 46 | ||
44 | static int mailbox_unix_init (mailbox_t *pmbox, const char *name); | 47 | static int mailbox_unix_init (mailbox_t *pmbox, const char *name); |
45 | static void mailbox_unix_destroy (mailbox_t *pmbox); | 48 | static void mailbox_unix_destroy (mailbox_t *pmbox); |
... | @@ -51,23 +54,28 @@ struct mailbox_registrar _mailbox_unix_registrar = | ... | @@ -51,23 +54,28 @@ struct mailbox_registrar _mailbox_unix_registrar = |
51 | }; | 54 | }; |
52 | 55 | ||
53 | /* | 56 | /* |
54 | * Keep a reference of where the header and body starts | 57 | * Keep the position of where the header and body starts |
55 | * and end. | 58 | * and ends. old_attr is the one that is part of the "Status:" message. |
56 | */ | 59 | */ |
57 | typedef struct _mailbox_unix_message | 60 | typedef struct _mailbox_unix_message |
58 | { | 61 | { |
59 | off_t header; | 62 | off_t header; |
60 | off_t header_end; | 63 | off_t header_end; |
64 | /* little hack to make things easier | ||
65 | * when updating the attribute | ||
66 | */ | ||
67 | off_t status; | ||
68 | off_t status_end; | ||
61 | off_t body; | 69 | off_t body; |
62 | off_t body_end; | 70 | off_t body_end; |
63 | attribute_t attribute; | 71 | attribute_t old_attr; |
72 | attribute_t new_attr; | ||
64 | } *mailbox_unix_message_t; | 73 | } *mailbox_unix_message_t; |
65 | 74 | ||
66 | typedef struct _mailbox_unix_data | 75 | typedef struct _mailbox_unix_data |
67 | { | 76 | { |
68 | mailbox_unix_message_t messages; | 77 | mailbox_unix_message_t messages; |
69 | size_t messages_count; | 78 | size_t messages_count; |
70 | size_t num_deleted; | ||
71 | FILE *file; | 79 | FILE *file; |
72 | char *dirname; | 80 | char *dirname; |
73 | char *basename; | 81 | char *basename; |
... | @@ -92,11 +100,16 @@ static int mailbox_unix_num_deleted (mailbox_t, size_t *); | ... | @@ -92,11 +100,16 @@ static int mailbox_unix_num_deleted (mailbox_t, size_t *); |
92 | static int mailbox_unix_get_size (mailbox_t, size_t msgno, size_t *header, | 100 | static int mailbox_unix_get_size (mailbox_t, size_t msgno, size_t *header, |
93 | size_t *body); | 101 | size_t *body); |
94 | 102 | ||
95 | static int mailbox_unix_scan (mailbox_t, size_t *msgs); | 103 | static int mailbox_unix_parse (mailbox_t, size_t *msgs); |
96 | static int mailbox_unix_is_updated (mailbox_t); | 104 | static int mailbox_unix_is_updated (mailbox_t); |
97 | 105 | ||
98 | static int mailbox_unix_size (mailbox_t, off_t *size); | 106 | static int mailbox_unix_size (mailbox_t, off_t *size); |
99 | 107 | ||
108 | static int mailbox_unix_get_attribute (mailbox_t mbox, size_t msgno, | ||
109 | attribute_t *pattribute); | ||
110 | static int mailbox_unix_set_attribute (mailbox_t mbox, size_t msgno, | ||
111 | attribute_t attribute); | ||
112 | |||
100 | static ssize_t mailbox_unix_get_header (mailbox_t, size_t msgno, char *h, | 113 | static ssize_t mailbox_unix_get_header (mailbox_t, size_t msgno, char *h, |
101 | size_t len, off_t off, int *err); | 114 | size_t len, off_t off, int *err); |
102 | static ssize_t mailbox_unix_get_body (mailbox_t, size_t msgno, char *b, | 115 | static ssize_t mailbox_unix_get_body (mailbox_t, size_t msgno, char *b, |
... | @@ -106,12 +119,19 @@ static ssize_t mailbox_unix_get_body (mailbox_t, size_t msgno, char *b, | ... | @@ -106,12 +119,19 @@ static ssize_t mailbox_unix_get_body (mailbox_t, size_t msgno, char *b, |
106 | /* private stuff */ | 119 | /* private stuff */ |
107 | static int mailbox_unix_is_from (const char *); | 120 | static int mailbox_unix_is_from (const char *); |
108 | static int mailbox_unix_readhdr (mailbox_t mbox, char *buf, size_t len, | 121 | static int mailbox_unix_readhdr (mailbox_t mbox, char *buf, size_t len, |
109 | off_t *content_length, attribute_t attr); | 122 | off_t *content_length, size_t msgno); |
110 | static int mailbox_unix_lock (mailbox_t mbox, int flag); | 123 | static int mailbox_unix_lock (mailbox_t mbox, int flag); |
111 | static int mailbox_unix_unlock (mailbox_t mbox); | 124 | static int mailbox_unix_unlock (mailbox_t mbox); |
112 | static int mailbox_unix_ilock (mailbox_t mbox, int flag); | 125 | static int mailbox_unix_ilock (mailbox_t mbox, int flag); |
113 | static int mailbox_unix_iunlock (mailbox_t mbox); | 126 | static int mailbox_unix_iunlock (mailbox_t mbox); |
114 | 127 | ||
128 | /* We allocate the mailbox_t struct, but don't do any | ||
129 | * parsing on the name or even thest for existence. | ||
130 | * However we do strip any leading "unix:" part of | ||
131 | * our name, this is suppose to be the protocol/scheme name. | ||
132 | * Hopefully there will not be a mailbox name "unix:" | ||
133 | */ | ||
134 | |||
115 | static int | 135 | static int |
116 | mailbox_unix_init (mailbox_t *pmbox, const char *name) | 136 | mailbox_unix_init (mailbox_t *pmbox, const char *name) |
117 | { | 137 | { |
... | @@ -131,10 +151,12 @@ mailbox_unix_init (mailbox_t *pmbox, const char *name) | ... | @@ -131,10 +151,12 @@ mailbox_unix_init (mailbox_t *pmbox, const char *name) |
131 | #define UNIX_SCHEME_LEN 5 | 151 | #define UNIX_SCHEME_LEN 5 |
132 | #define SEPARATOR '/' | 152 | #define SEPARATOR '/' |
133 | 153 | ||
134 | /* pass the url */ | 154 | /* sskip the url scheme */ |
135 | if (name_len > UNIX_SCHEME_LEN && | 155 | if (name_len > UNIX_SCHEME_LEN && |
136 | name[0] == 'u' && name[1] == 'n' && | 156 | (name[0] == 'u' || name[0] == 'U') && |
137 | name[2] == 'i' && name[3] == 'x' && | 157 | (name[1] == 'n' || name[1] == 'N') && |
158 | (name[2] == 'i' || name[2] == 'i') && | ||
159 | (name[3] == 'x' || name[3] == 'x' ) && | ||
138 | name[4] == ':') | 160 | name[4] == ':') |
139 | { | 161 | { |
140 | name += UNIX_SCHEME_LEN; | 162 | name += UNIX_SCHEME_LEN; |
... | @@ -164,6 +186,11 @@ mailbox_unix_init (mailbox_t *pmbox, const char *name) | ... | @@ -164,6 +186,11 @@ mailbox_unix_init (mailbox_t *pmbox, const char *name) |
164 | memcpy (mbox->name, name, name_len); | 186 | memcpy (mbox->name, name, name_len); |
165 | 187 | ||
166 | /* save the basename and dirname */ | 188 | /* save the basename and dirname */ |
189 | /* FIXME: We may have to support imap "SELECT" | ||
190 | * So we split the name. But this should probably be | ||
191 | * supported via "maildir:" | ||
192 | */ | ||
193 | /* equivalent to strrchr (name, '/'); */ | ||
167 | for (i = name_len, sep = NULL; i >= 0; i--) | 194 | for (i = name_len, sep = NULL; i >= 0; i--) |
168 | { | 195 | { |
169 | /* break on the first separator */ | 196 | /* break on the first separator */ |
... | @@ -215,9 +242,9 @@ mailbox_unix_init (mailbox_t *pmbox, const char *name) | ... | @@ -215,9 +242,9 @@ mailbox_unix_init (mailbox_t *pmbox, const char *name) |
215 | memcpy (mud->basename, name, name_len); | 242 | memcpy (mud->basename, name, name_len); |
216 | } | 243 | } |
217 | 244 | ||
245 | #ifdef HAVE_PHTREAD_H | ||
218 | /* mutex when accessing the structure fields */ | 246 | /* mutex when accessing the structure fields */ |
219 | /* FIXME: should we use rdwr locks instead ?? */ | 247 | /* FIXME: should we use rdwr locks instead ?? */ |
220 | #ifdef HAVE_PHTREAD_H | ||
221 | pthread_mutex_init (&(mud->mutex), NULL); | 248 | pthread_mutex_init (&(mud->mutex), NULL); |
222 | #endif | 249 | #endif |
223 | 250 | ||
... | @@ -241,6 +268,9 @@ mailbox_unix_init (mailbox_t *pmbox, const char *name) | ... | @@ -241,6 +268,9 @@ mailbox_unix_init (mailbox_t *pmbox, const char *name) |
241 | 268 | ||
242 | mbox->_size = mailbox_unix_size; | 269 | mbox->_size = mailbox_unix_size; |
243 | 270 | ||
271 | mbox->_get_attribute = mailbox_unix_get_attribute; | ||
272 | mbox->_set_attribute = mailbox_unix_set_attribute; | ||
273 | |||
244 | mbox->_get_header = mailbox_unix_get_header; | 274 | mbox->_get_header = mailbox_unix_get_header; |
245 | mbox->_get_body = mailbox_unix_get_body; | 275 | mbox->_get_body = mailbox_unix_get_body; |
246 | 276 | ||
... | @@ -265,8 +295,10 @@ mailbox_unix_destroy (mailbox_t *pmbox) | ... | @@ -265,8 +295,10 @@ mailbox_unix_destroy (mailbox_t *pmbox) |
265 | for (i = 0; i < mud->messages_count; i++) | 295 | for (i = 0; i < mud->messages_count; i++) |
266 | { | 296 | { |
267 | /* orphan the message */ | 297 | /* orphan the message */ |
268 | mud->messages[i].attribute->message = NULL; | 298 | mud->messages[i].old_attr->message = NULL; |
269 | attribute_destroy (&(mud->messages[i].attribute)); | 299 | mud->messages[i].new_attr->message = NULL; |
300 | attribute_destroy (&(mud->messages[i].old_attr)); | ||
301 | attribute_destroy (&(mud->messages[i].new_attr)); | ||
270 | } | 302 | } |
271 | free (mud->messages); | 303 | free (mud->messages); |
272 | free (mbox->data); | 304 | free (mbox->data); |
... | @@ -331,15 +363,14 @@ mailbox_unix_open (mailbox_t mbox, int flags) | ... | @@ -331,15 +363,14 @@ mailbox_unix_open (mailbox_t mbox, int flags) |
331 | /* oops bail out */ | 363 | /* oops bail out */ |
332 | if (errno != ENOENT) | 364 | if (errno != ENOENT) |
333 | return errno; | 365 | return errno; |
334 | /* Create the file */ | 366 | /* Race condition here when creating the file ?? */ |
335 | fd = open(mbox->name, flg|O_CREAT|O_EXCL, 0600); | 367 | fd = open(mbox->name, flg|O_CREAT|O_EXCL, 0600); |
336 | if (fd < 0) | 368 | if (fd < 0) |
337 | return errno; | 369 | return errno; |
338 | } | 370 | } |
339 | /* | 371 | /* |
340 | FIXME: How about owner(uid), to whom we set it to ? | 372 | * Set the owner ship, but should we return the errno |
341 | do We need a _set_owner(uid) to mailbox_t | 373 | */ |
342 | */ | ||
343 | if (mbox->auth) | 374 | if (mbox->auth) |
344 | { | 375 | { |
345 | auth_t auth = mbox->auth; | 376 | auth_t auth = mbox->auth; |
... | @@ -365,10 +396,8 @@ mailbox_unix_open (mailbox_t mbox, int flags) | ... | @@ -365,10 +396,8 @@ mailbox_unix_open (mailbox_t mbox, int flags) |
365 | /* we use FILE * object */ | 396 | /* we use FILE * object */ |
366 | if (flags & MU_MAILBOX_APPEND) | 397 | if (flags & MU_MAILBOX_APPEND) |
367 | mode = "a"; | 398 | mode = "a"; |
368 | else if (flags & MU_MAILBOX_RDWR) | 399 | else if (flags & MU_MAILBOX_RDWR || flags & MU_MAILBOX_WRONLY) |
369 | mode = "r+"; | 400 | mode = "r+"; |
370 | else if (flags & MU_MAILBOX_WRONLY) | ||
371 | mode = "w"; | ||
372 | else /* default readonly*/ | 401 | else /* default readonly*/ |
373 | mode = "r"; | 402 | mode = "r"; |
374 | 403 | ||
... | @@ -388,7 +417,7 @@ mailbox_unix_open (mailbox_t mbox, int flags) | ... | @@ -388,7 +417,7 @@ mailbox_unix_open (mailbox_t mbox, int flags) |
388 | /* Check to make sure this is indeed a Unix Mail format */ | 417 | /* Check to make sure this is indeed a Unix Mail format */ |
389 | flockfile (mud->file); | 418 | flockfile (mud->file); |
390 | { | 419 | { |
391 | char buf [BUFSIZ]; | 420 | char buf [6]; |
392 | if (fgets (buf, sizeof (buf), mud->file) == NULL) | 421 | if (fgets (buf, sizeof (buf), mud->file) == NULL) |
393 | { | 422 | { |
394 | if (feof (mud->file)) | 423 | if (feof (mud->file)) |
... | @@ -408,14 +437,13 @@ mailbox_unix_open (mailbox_t mbox, int flags) | ... | @@ -408,14 +437,13 @@ mailbox_unix_open (mailbox_t mbox, int flags) |
408 | mailbox_unix_iunlock (mbox); | 437 | mailbox_unix_iunlock (mbox); |
409 | return EIO; | 438 | return EIO; |
410 | } | 439 | } |
411 | else | ||
412 | rewind (mud->file); | ||
413 | } | 440 | } |
441 | rewind (mud->file); | ||
414 | } | 442 | } |
415 | funlockfile (mud->file); | 443 | funlockfile (mud->file); |
444 | mud->flags = flags; | ||
416 | } | 445 | } |
417 | mailbox_unix_iunlock (mbox); | 446 | mailbox_unix_iunlock (mbox); |
418 | mud->flags = flags; | ||
419 | return 0; | 447 | return 0; |
420 | } | 448 | } |
421 | 449 | ||
... | @@ -502,14 +530,15 @@ mailbox_unix_is_from (const char *from) | ... | @@ -502,14 +530,15 @@ mailbox_unix_is_from (const char *from) |
502 | 530 | ||
503 | /* | 531 | /* |
504 | * We skip over the rest of the header. Scan for | 532 | * We skip over the rest of the header. Scan for |
505 | * Status: to set the attribute. Hopfully the Content-Length | 533 | * Status: to set the attribute. Hopefully the Content-Length |
506 | * in there too. | 534 | * in there too. |
507 | */ | 535 | */ |
508 | static int | 536 | static int |
509 | mailbox_unix_readhdr (mailbox_t mbox, char *buf, size_t len, | 537 | mailbox_unix_readhdr (mailbox_t mbox, char *buf, size_t len, |
510 | off_t *content_length, attribute_t attribute) | 538 | off_t *content_length, size_t msgno) |
511 | { | 539 | { |
512 | mailbox_unix_data_t mud = (mailbox_unix_data_t)mbox->data; | 540 | mailbox_unix_data_t mud = (mailbox_unix_data_t)mbox->data; |
541 | mailbox_unix_message_t mum = &mud->messages[msgno]; | ||
513 | char *sep; | 542 | char *sep; |
514 | 543 | ||
515 | /* skip over the remaining header */ | 544 | /* skip over the remaining header */ |
... | @@ -524,24 +553,40 @@ mailbox_unix_readhdr (mailbox_t mbox, char *buf, size_t len, | ... | @@ -524,24 +553,40 @@ mailbox_unix_readhdr (mailbox_t mbox, char *buf, size_t len, |
524 | || (isalpha (buf[0]) && (sep = strchr (buf, ':')) == NULL)) | 553 | || (isalpha (buf[0]) && (sep = strchr (buf, ':')) == NULL)) |
525 | break; | 554 | break; |
526 | /* get the the Content lenght of the body if possible */ | 555 | /* get the the Content lenght of the body if possible */ |
527 | if (strncmp (buf, "Content-Length:", 15) == 0) | 556 | else if (strncmp (buf, "Content-Length:", 15) == 0) |
528 | { | 557 | { |
529 | sep = strchr(buf, ':'); /* pass the ':' */ | 558 | sep = strchr(buf, ':'); /* pass the ':' */ |
530 | sep[strlen (sep) - 1] = '\0'; /* chop the newline */ | 559 | sep[strlen (sep) - 1] = '\0'; /* chop the newline */ |
560 | /* FIXME: use xstrtol() if strtol() is not on the platform */ | ||
561 | /* FIXME: what an awkward way of handling error | ||
562 | Some damage control can be done here. | ||
563 | for example just set content_length = -1; | ||
564 | and rely above to discover the body part */ | ||
565 | errno = 0; | ||
531 | *content_length = strtol (sep + 1, NULL, 10); | 566 | *content_length = strtol (sep + 1, NULL, 10); |
567 | if (*content_length == 0 || | ||
568 | *content_length == LONG_MIN || | ||
569 | *content_length == LONG_MAX) | ||
570 | { | ||
571 | if (errno != 0) | ||
572 | return errno; | ||
573 | } | ||
532 | } | 574 | } |
533 | /* Set the attribute */ | 575 | /* Set the attribute */ |
534 | if (strncmp (buf, "Status:", 7) == 0) | 576 | else if (strncmp (buf, "Status:", 7) == 0) |
535 | { | 577 | { |
578 | mum->status = ftell (mud->file); | ||
579 | mum->status_end = mum->status + strlen (buf); | ||
536 | sep = strchr(buf, ':'); /* pass the ':' */ | 580 | sep = strchr(buf, ':'); /* pass the ':' */ |
537 | if (strchr (sep, 'R') != NULL) | 581 | if (strchr (sep, 'R') != NULL) |
538 | attribute_set_read (attribute); | 582 | attribute_set_read (mum->old_attr); |
539 | if (strchr (sep, 'O') != NULL) | 583 | if (strchr (sep, 'O') != NULL) |
540 | attribute_set_seen (attribute); | 584 | attribute_set_seen (mum->old_attr); |
541 | if (strchr (sep, 'A') != NULL) | 585 | if (strchr (sep, 'A') != NULL) |
542 | attribute_set_answered (attribute); | 586 | attribute_set_answered (mum->old_attr); |
543 | if (strchr (sep, 'F') != NULL) | 587 | if (strchr (sep, 'F') != NULL) |
544 | attribute_set_flagged (attribute); | 588 | attribute_set_flagged (mum->old_attr); |
589 | attribute_copy (mum->new_attr, mum->old_attr); | ||
545 | } | 590 | } |
546 | } | 591 | } |
547 | /* check for any dubious conditions */ | 592 | /* check for any dubious conditions */ |
... | @@ -553,13 +598,13 @@ mailbox_unix_readhdr (mailbox_t mbox, char *buf, size_t len, | ... | @@ -553,13 +598,13 @@ mailbox_unix_readhdr (mailbox_t mbox, char *buf, size_t len, |
553 | /* Parsing. | 598 | /* Parsing. |
554 | * This a bit fragile, I need to secure this. | 599 | * This a bit fragile, I need to secure this. |
555 | * The approach is to detect the "From " as start of a | 600 | * The approach is to detect the "From " as start of a |
556 | * new message give the position of the header and scan | 601 | * new message, give the position of the header and scan |
557 | * until "\n" set header_end, set body position, we have | 602 | * until "\n" then set header_end, set body position, if we have |
558 | * a Content-Length header jump to the point if not | 603 | * a Content-Length field jump to the point if not |
559 | * scan until we it another "From " and set body_end. | 604 | * scan until we it another "From " and set body_end. |
560 | */ | 605 | */ |
561 | static int | 606 | static int |
562 | mailbox_unix_scan (mailbox_t mbox, size_t *msgs) | 607 | mailbox_unix_parse (mailbox_t mbox, size_t *msgs) |
563 | { | 608 | { |
564 | char buf[BUFSIZ]; | 609 | char buf[BUFSIZ]; |
565 | int header = 1; | 610 | int header = 1; |
... | @@ -570,6 +615,7 @@ mailbox_unix_scan (mailbox_t mbox, size_t *msgs) | ... | @@ -570,6 +615,7 @@ mailbox_unix_scan (mailbox_t mbox, size_t *msgs) |
570 | mailbox_unix_message_t mum; | 615 | mailbox_unix_message_t mum; |
571 | struct stat st; | 616 | struct stat st; |
572 | 617 | ||
618 | /* sanity */ | ||
573 | if (mbox == NULL || | 619 | if (mbox == NULL || |
574 | (mud = (mailbox_unix_data_t)mbox->data) == NULL) | 620 | (mud = (mailbox_unix_data_t)mbox->data) == NULL) |
575 | return EINVAL; | 621 | return EINVAL; |
... | @@ -615,7 +661,7 @@ mailbox_unix_scan (mailbox_t mbox, size_t *msgs) | ... | @@ -615,7 +661,7 @@ mailbox_unix_scan (mailbox_t mbox, size_t *msgs) |
615 | 661 | ||
616 | count++; | 662 | count++; |
617 | /* FIXME: This is a bad idea, we should not be allowed to | 663 | /* FIXME: This is a bad idea, we should not be allowed to |
618 | * jump out from the scanning this way. We sit at the mercy | 664 | * jump out from the parsing this way. We sit at the mercy |
619 | * of this function(_progress) waiting for disaster. | 665 | * of this function(_progress) waiting for disaster. |
620 | */ | 666 | */ |
621 | if (mbox->_progress) | 667 | if (mbox->_progress) |
... | @@ -629,6 +675,7 @@ mailbox_unix_scan (mailbox_t mbox, size_t *msgs) | ... | @@ -629,6 +675,7 @@ mailbox_unix_scan (mailbox_t mbox, size_t *msgs) |
629 | return EINTR; | 675 | return EINTR; |
630 | } | 676 | } |
631 | } | 677 | } |
678 | /* allocate space for the new message */ | ||
632 | if (count > mud->messages_count) | 679 | if (count > mud->messages_count) |
633 | { | 680 | { |
634 | mum = realloc (mud->messages, count * sizeof (*mum)); | 681 | mum = realloc (mud->messages, count * sizeof (*mum)); |
... | @@ -641,15 +688,17 @@ mailbox_unix_scan (mailbox_t mbox, size_t *msgs) | ... | @@ -641,15 +688,17 @@ mailbox_unix_scan (mailbox_t mbox, size_t *msgs) |
641 | } | 688 | } |
642 | mud->messages_count++; | 689 | mud->messages_count++; |
643 | memset (&mum[count - 1], 0, sizeof (*mum)); | 690 | memset (&mum[count - 1], 0, sizeof (*mum)); |
644 | attribute_init (&(mum[count - 1].attribute)); | 691 | attribute_init (&(mum[count - 1].old_attr)); |
692 | attribute_init (&(mum[count - 1].new_attr)); | ||
645 | } | 693 | } |
646 | mud->messages = mum; | 694 | mud->messages = mum; |
647 | mum[count - 1].header = ftell (mud->file); | 695 | mum[count - 1].header = ftell (mud->file); |
696 | /* substract the overrun */ | ||
648 | mum[count - 1].header -= over; | 697 | mum[count - 1].header -= over; |
649 | 698 | ||
650 | /* skip over the remaining header */ | 699 | /* skip the remaining header and set the attributes */ |
651 | if (mailbox_unix_readhdr (mbox, buf, sizeof (buf), &content_length, | 700 | if (mailbox_unix_readhdr (mbox, buf, sizeof (buf), |
652 | mum[count - 1].attribute) != 0) | 701 | &content_length, count - 1) != 0) |
653 | { | 702 | { |
654 | funlockfile (mud->file); | 703 | funlockfile (mud->file); |
655 | mailbox_unix_iunlock (mbox); | 704 | mailbox_unix_iunlock (mbox); |
... | @@ -664,12 +713,13 @@ mailbox_unix_scan (mailbox_t mbox, size_t *msgs) | ... | @@ -664,12 +713,13 @@ mailbox_unix_scan (mailbox_t mbox, size_t *msgs) |
664 | /* body */ | 713 | /* body */ |
665 | if (body) | 714 | if (body) |
666 | { | 715 | { |
716 | /* set the body position */ | ||
667 | if (mum[count - 1].body == 0) | 717 | if (mum[count - 1].body == 0) |
668 | mum[count - 1].body = ftell (mud->file); | 718 | mum[count - 1].body = ftell (mud->file); |
669 | 719 | ||
670 | if (content_length >= 0) | 720 | if (content_length >= 0) |
671 | { | 721 | { |
672 | /* ouf ! we got the size */ | 722 | /* ouf ! we got the lenght, jump */ |
673 | mum[count - 1].body_end = mum[count -1].body + content_length; | 723 | mum[count - 1].body_end = mum[count -1].body + content_length; |
674 | fseek (mud->file, content_length, SEEK_CUR); | 724 | fseek (mud->file, content_length, SEEK_CUR); |
675 | content_length = -1; | 725 | content_length = -1; |
... | @@ -678,6 +728,7 @@ mailbox_unix_scan (mailbox_t mbox, size_t *msgs) | ... | @@ -678,6 +728,7 @@ mailbox_unix_scan (mailbox_t mbox, size_t *msgs) |
678 | } | 728 | } |
679 | } /* while */ | 729 | } /* while */ |
680 | mum[count - 1].body_end = ftell (mud->file); | 730 | mum[count - 1].body_end = ftell (mud->file); |
731 | |||
681 | if (feof (mud->file)) | 732 | if (feof (mud->file)) |
682 | clearerr (mud->file); | 733 | clearerr (mud->file); |
683 | else if (ferror (mud->file)) | 734 | else if (ferror (mud->file)) |
... | @@ -696,6 +747,11 @@ mailbox_unix_scan (mailbox_t mbox, size_t *msgs) | ... | @@ -696,6 +747,11 @@ mailbox_unix_scan (mailbox_t mbox, size_t *msgs) |
696 | return 0; | 747 | return 0; |
697 | } | 748 | } |
698 | 749 | ||
750 | /* FIXME: How to handle a shrink ? meaning, the &^$^@%#@^& user | ||
751 | * start two browsers and delete files in one. My views | ||
752 | * is that we should scream bloody murder and hunt them with | ||
753 | * a machette. | ||
754 | */ | ||
699 | static int | 755 | static int |
700 | mailbox_unix_is_updated (mailbox_t mbox) | 756 | mailbox_unix_is_updated (mailbox_t mbox) |
701 | { | 757 | { |
... | @@ -712,7 +768,8 @@ static int | ... | @@ -712,7 +768,8 @@ static int |
712 | mailbox_unix_is_valid (mailbox_t mbox, size_t msgno) | 768 | mailbox_unix_is_valid (mailbox_t mbox, size_t msgno) |
713 | { | 769 | { |
714 | mailbox_unix_data_t mud; | 770 | mailbox_unix_data_t mud; |
715 | if (mbox == NULL || (mud = (mailbox_unix_data_t) mbox->data) == NULL) | 771 | if (mbox == NULL || |
772 | (mud = (mailbox_unix_data_t) mbox->data) == NULL) | ||
716 | return 0; | 773 | return 0; |
717 | /* valid ? */ | 774 | /* valid ? */ |
718 | return (mud->messages_count > 0 && msgno <= mud->messages_count); | 775 | return (mud->messages_count > 0 && msgno <= mud->messages_count); |
... | @@ -723,12 +780,11 @@ mailbox_unix_is_deleted (mailbox_t mbox, size_t msgno) | ... | @@ -723,12 +780,11 @@ mailbox_unix_is_deleted (mailbox_t mbox, size_t msgno) |
723 | { | 780 | { |
724 | mailbox_unix_data_t mud; | 781 | mailbox_unix_data_t mud; |
725 | 782 | ||
726 | /* Do we have a consistent view of the mbox ? */ | ||
727 | if (mbox == NULL || | 783 | if (mbox == NULL || |
728 | (mud = (mailbox_unix_data_t)mbox->data) == NULL || | 784 | (mud = (mailbox_unix_data_t)mbox->data) == NULL || |
729 | ! mailbox_unix_is_valid (mbox, msgno)) | 785 | ! mailbox_unix_is_valid (mbox, msgno)) |
730 | return 0; | 786 | return 0; |
731 | return attribute_is_deleted (mud->messages[msgno].attribute); | 787 | return attribute_is_deleted (mud->messages[msgno].new_attr); |
732 | } | 788 | } |
733 | 789 | ||
734 | static int | 790 | static int |
... | @@ -747,8 +803,7 @@ mailbox_unix_delete (mailbox_t mbox, size_t msgno) | ... | @@ -747,8 +803,7 @@ mailbox_unix_delete (mailbox_t mbox, size_t msgno) |
747 | return 0; | 803 | return 0; |
748 | 804 | ||
749 | /* Mark for deletion */ | 805 | /* Mark for deletion */ |
750 | attribute_set_deleted (mud->messages[msgno].attribute); | 806 | attribute_set_deleted (mud->messages[msgno].new_attr); |
751 | mud->num_deleted++; | ||
752 | return 0; | 807 | return 0; |
753 | } | 808 | } |
754 | 809 | ||
... | @@ -756,11 +811,20 @@ static int | ... | @@ -756,11 +811,20 @@ static int |
756 | mailbox_unix_num_deleted (mailbox_t mbox, size_t *num) | 811 | mailbox_unix_num_deleted (mailbox_t mbox, size_t *num) |
757 | { | 812 | { |
758 | mailbox_unix_data_t mud; | 813 | mailbox_unix_data_t mud; |
814 | mailbox_unix_message_t mum; | ||
815 | size_t i, total; | ||
759 | if (mbox == NULL || | 816 | if (mbox == NULL || |
760 | (mud = (mailbox_unix_data_t) mbox->data) == NULL) | 817 | (mud = (mailbox_unix_data_t) mbox->data) == NULL) |
761 | return EINVAL; | 818 | return EINVAL; |
819 | for (i = total = 0; i < mud->messages_count; i++) | ||
820 | { | ||
821 | mum = &mud->messages[i]; | ||
822 | if (attribute_is_deleted (mum->new_attr)) | ||
823 | total++; | ||
824 | } | ||
825 | |||
762 | if (num) | 826 | if (num) |
763 | *num = mud->num_deleted; | 827 | *num = total; |
764 | return 0; | 828 | return 0; |
765 | } | 829 | } |
766 | 830 | ||
... | @@ -779,8 +843,7 @@ mailbox_unix_undelete (mailbox_t mbox, size_t msgno) | ... | @@ -779,8 +843,7 @@ mailbox_unix_undelete (mailbox_t mbox, size_t msgno) |
779 | return 0; | 843 | return 0; |
780 | 844 | ||
781 | /* Mark undeletion */ | 845 | /* Mark undeletion */ |
782 | attribute_unset_deleted (mud->messages[msgno].attribute); | 846 | attribute_unset_deleted (mud->messages[msgno].new_attr); |
783 | mud->num_deleted--; | ||
784 | return 0; | 847 | return 0; |
785 | } | 848 | } |
786 | 849 | ||
... | @@ -795,7 +858,7 @@ mailbox_unix_tmpfile () | ... | @@ -795,7 +858,7 @@ mailbox_unix_tmpfile () |
795 | { | 858 | { |
796 | /*FIXME: racing conditions, to correct, .i.e don;t use tmpfile*/ | 859 | /*FIXME: racing conditions, to correct, .i.e don;t use tmpfile*/ |
797 | //return tmpfile (); | 860 | //return tmpfile (); |
798 | return fopen ("/tmp/mymail", "w"); | 861 | return fopen ("/tmp/mymail", "w+"); |
799 | } | 862 | } |
800 | 863 | ||
801 | static int | 864 | static int |
... | @@ -803,9 +866,12 @@ mailbox_unix_expunge (mailbox_t mbox) | ... | @@ -803,9 +866,12 @@ mailbox_unix_expunge (mailbox_t mbox) |
803 | { | 866 | { |
804 | mailbox_unix_data_t mud; | 867 | mailbox_unix_data_t mud; |
805 | mailbox_unix_message_t mum; | 868 | mailbox_unix_message_t mum; |
869 | int status = 0; | ||
806 | sigset_t sigset; | 870 | sigset_t sigset; |
807 | FILE *tmpfile; | 871 | FILE *tmpfile; |
808 | size_t i; | 872 | size_t nread; |
873 | size_t i, j, first; | ||
874 | off_t marker = 0; | ||
809 | off_t total = 0; | 875 | off_t total = 0; |
810 | char buffer [BUFSIZ]; | 876 | char buffer [BUFSIZ]; |
811 | 877 | ||
... | @@ -814,144 +880,208 @@ mailbox_unix_expunge (mailbox_t mbox) | ... | @@ -814,144 +880,208 @@ mailbox_unix_expunge (mailbox_t mbox) |
814 | return EINVAL; | 880 | return EINVAL; |
815 | 881 | ||
816 | /* noop */ | 882 | /* noop */ |
817 | if (mud->messages_count == 0 || mud->num_deleted <= 0) | 883 | if (mud->messages_count == 0) |
818 | return 0; | 884 | return 0; |
819 | 885 | ||
820 | tmpfile = mailbox_unix_tmpfile (); | 886 | tmpfile = mailbox_unix_tmpfile (); |
821 | if (tmpfile == NULL) | 887 | if (tmpfile == NULL) |
822 | return errno; | 888 | return errno; |
823 | 889 | ||
890 | /* Critical section, we can not allowed signal here */ | ||
891 | /* FIXME: If NONBLOCKING is set we should unset reset to | ||
892 | * later, we can not afford to luxury here | ||
893 | */ | ||
894 | sigemptyset (&sigset); | ||
895 | sigaddset (&sigset, SIGTERM); | ||
896 | sigaddset (&sigset, SIGHUP); | ||
897 | sigaddset (&sigset, SIGTSTP); | ||
898 | sigaddset (&sigset, SIGINT); | ||
899 | sigaddset (&sigset, SIGWINCH); | ||
900 | sigprocmask (SIG_BLOCK, &sigset, 0); | ||
901 | |||
824 | /* Get the lock */ | 902 | /* Get the lock */ |
825 | mailbox_unix_ilock (mbox, MU_LOCKER_RDLOCK); | ||
826 | flockfile (mud->file); | ||
827 | if (mailbox_unix_lock (mbox, MU_LOCKER_WRLOCK) < 0) | 903 | if (mailbox_unix_lock (mbox, MU_LOCKER_WRLOCK) < 0) |
828 | { | 904 | { |
829 | funlockfile (mud->file); | 905 | status = EIO; |
830 | mailbox_unix_iunlock (mbox); | 906 | goto bailout; |
831 | fclose (tmpfile); | ||
832 | return EINVAL; | ||
833 | } | 907 | } |
908 | mailbox_unix_ilock (mbox, MU_LOCKER_RDLOCK); | ||
909 | flockfile (mud->file); | ||
834 | 910 | ||
835 | /* Do we have a consistent view of the mbox */ | 911 | /* Do we have a consistent view of the mailbox */ |
912 | /* FIXME: this is not enough we can do better | ||
913 | * - by checking the file size and scream bloody murder | ||
914 | * if it has shrink. | ||
915 | * - if its bigger we should be able to handle it | ||
916 | * before the ftruncate() by copying back the new messages. | ||
917 | */ | ||
836 | if (! mailbox_unix_is_updated (mbox)) | 918 | if (! mailbox_unix_is_updated (mbox)) |
837 | { | 919 | { |
838 | /* things change, flag an error */ | 920 | status = EAGAIN; |
839 | mailbox_unix_unlock (mbox); | 921 | goto bailout; |
840 | funlockfile (mud->file); | ||
841 | mailbox_unix_iunlock (mbox); | ||
842 | fclose (tmpfile); | ||
843 | return EAGAIN; | ||
844 | } | 922 | } |
845 | 923 | ||
846 | rewind (mud->file); | 924 | rewind (mud->file); |
847 | /* copy to temp file emails not mark deleted emails */ | 925 | |
848 | for (i = 1; i <= mud->messages_count; i++) | 926 | /* Go to the first mail with an attribute change */ |
927 | for (j = 0; j < mud->messages_count; j++) | ||
928 | { | ||
929 | mum = &mud->messages[j]; | ||
930 | if (! attribute_is_equal (mum->old_attr, mum->new_attr)) | ||
931 | break; | ||
932 | } | ||
933 | |||
934 | /* did something change ? */ | ||
935 | if ((j + 1) == mud->messages_count) | ||
849 | { | 936 | { |
937 | /* nothing change, bail out */ | ||
938 | status = 0; | ||
939 | goto bailout; | ||
940 | } | ||
941 | |||
942 | /* set the marker position */ | ||
943 | total = marker = mud->messages[j].header; | ||
944 | |||
945 | /* copy to tempfile emails not mark changed */ | ||
946 | for (first = 1, i = j; i < mud->messages_count; i++) | ||
947 | { | ||
948 | size_t len; | ||
949 | off_t current; | ||
850 | mum = &mud->messages[i]; | 950 | mum = &mud->messages[i]; |
851 | if ( ! attribute_is_deleted (mum->attribute)) | 951 | |
952 | /* skip it, if mark for deletion */ | ||
953 | if (attribute_is_deleted (mum->new_attr)) | ||
954 | continue; | ||
955 | |||
956 | /* add a NL separtor between messages */ | ||
957 | if (first) | ||
958 | first = 0; | ||
959 | else | ||
852 | { | 960 | { |
853 | size_t len = mum->body - mum->header; | 961 | fputc ('\n', tmpfile); |
854 | size_t nread; | 962 | total++; |
855 | /* copy the header */ | 963 | } |
856 | if (fseek (mud->file, mum->header, SEEK_SET) == -1) | 964 | /* copy the header */ |
857 | { | 965 | if (fseek (mud->file, mum->header, SEEK_SET) == -1) |
858 | mailbox_unix_unlock (mbox); | 966 | { |
859 | funlockfile (mud->file); | 967 | status = EIO; |
860 | mailbox_unix_iunlock (mbox); | 968 | goto bailout; |
861 | fclose (tmpfile); | 969 | } |
862 | return EIO; | 970 | /* attribute change ? */ |
863 | } | 971 | if (! attribute_is_equal (mum->old_attr, mum->new_attr) && |
972 | mum->status > mum->header) | ||
973 | { | ||
974 | len = mum->status - mum->header; | ||
975 | current = mum->status_end; | ||
864 | while (len > 0) | 976 | while (len > 0) |
865 | { | 977 | { |
866 | nread = (len < sizeof (buffer)) ? len : sizeof (buffer); | 978 | nread = (len < sizeof (buffer)) ? len : sizeof (buffer); |
867 | if (fread (buffer, sizeof (*buffer), nread, mud->file) != nread | 979 | if (fread (buffer, sizeof (*buffer), nread, mud->file) != nread |
868 | || fwrite(buffer, sizeof(*buffer), nread, tmpfile) != nread) | 980 | || fwrite(buffer, sizeof(*buffer), nread, tmpfile) != nread) |
869 | { | 981 | { |
870 | mailbox_unix_unlock (mbox); | 982 | status = EIO; |
871 | funlockfile (mud->file); | 983 | goto bailout; |
872 | mailbox_unix_iunlock (mbox); | ||
873 | fclose (tmpfile); | ||
874 | return EIO; | ||
875 | } | 984 | } |
876 | len -= nread; | 985 | len -= nread; |
877 | total += nread; | 986 | total += nread; |
878 | } | 987 | } |
879 | 988 | /* put the new attributes */ | |
880 | /* copy the body */ | 989 | { |
881 | len = mum->body_end - mum->body; | 990 | attribute_t attr = mum->new_attr; |
882 | if (fseek (mud->file, mum->body, SEEK_SET) < 0) | 991 | fputs ("Status: ", tmpfile); |
992 | total += 8; | ||
993 | if (attribute_is_seen (attr)) | ||
994 | { | ||
995 | fputc ('R', tmpfile); | ||
996 | total++; | ||
997 | } | ||
998 | if (attribute_is_answered (attr)) | ||
999 | { | ||
1000 | fputc ('A', tmpfile); | ||
1001 | total++; | ||
1002 | } | ||
1003 | if (attribute_is_flagged (attr)) | ||
1004 | { | ||
1005 | fputc ('F', tmpfile); | ||
1006 | total++; | ||
1007 | } | ||
1008 | if (attribute_is_read (attr)) | ||
1009 | { | ||
1010 | fputc ('O', tmpfile); | ||
1011 | total++; | ||
1012 | } | ||
1013 | fputc ('\n', tmpfile); | ||
1014 | total++; | ||
1015 | } | ||
1016 | } | ||
1017 | else /* attribute did not change */ | ||
1018 | { | ||
1019 | current = mum->header; | ||
1020 | } | ||
1021 | len = mum->header_end - current; | ||
1022 | while (len > 0) | ||
1023 | { | ||
1024 | nread = (len < sizeof (buffer)) ? len : sizeof (buffer); | ||
1025 | if (fread (buffer, sizeof (*buffer), nread, mud->file) != nread | ||
1026 | || fwrite(buffer, sizeof(*buffer), nread, tmpfile) != nread) | ||
883 | { | 1027 | { |
884 | mailbox_unix_unlock (mbox); | 1028 | status = EIO; |
885 | funlockfile (mud->file); | 1029 | goto bailout; |
886 | mailbox_unix_iunlock (mbox); | ||
887 | fclose (tmpfile); | ||
888 | return EIO; | ||
889 | } | 1030 | } |
890 | while (len > 0) | 1031 | len -= nread; |
1032 | total += nread; | ||
1033 | } | ||
1034 | |||
1035 | /* Separate the header from body */ | ||
1036 | fputc ('\n', tmpfile); | ||
1037 | total++; | ||
1038 | |||
1039 | /* copy the body */ | ||
1040 | if (fseek (mud->file, mum->body, SEEK_SET) < 0) | ||
1041 | { | ||
1042 | status = EIO; | ||
1043 | goto bailout; | ||
1044 | } | ||
1045 | len = mum->body_end - mum->body; | ||
1046 | while (len > 0) | ||
1047 | { | ||
1048 | nread = (len < sizeof (buffer)) ? len : sizeof (buffer); | ||
1049 | if (fread (buffer, sizeof (*buffer), nread, mud->file) != nread | ||
1050 | || fwrite(buffer, sizeof(*buffer), nread, tmpfile) != nread) | ||
891 | { | 1051 | { |
892 | nread = (len < sizeof (buffer)) ? len : sizeof (buffer); | 1052 | status = EIO; |
893 | if (fread (buffer, sizeof (*buffer), nread, mud->file) != nread | 1053 | goto bailout; |
894 | || fwrite(buffer, sizeof(*buffer), nread, tmpfile) != nread) | ||
895 | { | ||
896 | mailbox_unix_unlock (mbox); | ||
897 | fclose (tmpfile); | ||
898 | mailbox_unix_iunlock (mbox); | ||
899 | funlockfile (mud->file); | ||
900 | return EIO; | ||
901 | } | ||
902 | len -= nread; | ||
903 | total += nread; | ||
904 | } | 1054 | } |
1055 | len -= nread; | ||
1056 | total += nread; | ||
905 | } | 1057 | } |
906 | } | 1058 | } |
907 | 1059 | ||
908 | /* Critical section, we can not allowed signal here */ | ||
909 | sigemptyset (&sigset); | ||
910 | sigaddset (&sigset, SIGTERM); | ||
911 | sigaddset (&sigset, SIGHUP); | ||
912 | sigaddset (&sigset, SIGTSTP); | ||
913 | sigaddset (&sigset, SIGINT); | ||
914 | sigaddset (&sigset, SIGWINCH); | ||
915 | sigprocmask (SIG_BLOCK, &sigset, 0); | ||
916 | |||
917 | /* truncate the mailbox and rewrite it */ | 1060 | /* truncate the mailbox and rewrite it */ |
918 | rewind (mud->file); | 1061 | if (total <= 0 || fseek (mud->file, marker, SEEK_SET) < 0 || |
919 | rewind (tmpfile); | 1062 | ftruncate (fileno(mud->file), total) < 0) |
920 | if (ftruncate (fileno(mud->file), total) < 0) | ||
921 | { | 1063 | { |
922 | mailbox_unix_unlock (mbox); | 1064 | status = EIO; |
923 | funlockfile (mud->file); | 1065 | goto bailout; |
924 | mailbox_unix_iunlock (mbox); | ||
925 | fclose (tmpfile); | ||
926 | sigprocmask (SIG_UNBLOCK, &sigset, 0); | ||
927 | return EIO; | ||
928 | } | 1066 | } |
1067 | rewind (tmpfile); | ||
929 | 1068 | ||
930 | while (total > 0) | 1069 | while ((nread = fread (buffer, sizeof (*buffer), sizeof (buffer), tmpfile)) != 0) |
931 | { | 1070 | fwrite (buffer, sizeof (*buffer), nread, mud->file); |
932 | size_t nread = ((unsigned)total < sizeof (buffer)) ? total : sizeof (buffer); | ||
933 | if (fread (buffer, sizeof (*buffer), nread, mud->file) != nread | ||
934 | || fwrite (buffer, sizeof (*buffer), nread, tmpfile) != nread) | ||
935 | { | ||
936 | mailbox_unix_unlock (mbox); | ||
937 | funlockfile (mud->file); | ||
938 | mailbox_unix_iunlock (mbox); | ||
939 | fclose (tmpfile); | ||
940 | sigprocmask (SIG_UNBLOCK, &sigset, 0); | ||
941 | return EIO; | ||
942 | } | ||
943 | total -= nread; | ||
944 | } | ||
945 | 1071 | ||
1072 | /* how can I handle error here ?? */ | ||
1073 | clearerr (tmpfile); | ||
1074 | clearerr (mud->file); | ||
946 | fflush (mud->file); | 1075 | fflush (mud->file); |
947 | 1076 | ||
1077 | bailout: | ||
948 | /* Release the lock */ | 1078 | /* Release the lock */ |
949 | mailbox_unix_unlock (mbox); | 1079 | mailbox_unix_unlock (mbox); |
950 | funlockfile (mud->file); | 1080 | funlockfile (mud->file); |
951 | mailbox_unix_iunlock (mbox); | 1081 | mailbox_unix_iunlock (mbox); |
952 | fclose (tmpfile); | 1082 | fclose (tmpfile); |
953 | sigprocmask (SIG_UNBLOCK, &sigset, 0); | 1083 | sigprocmask (SIG_UNBLOCK, &sigset, 0); |
954 | return 0; | 1084 | return status; |
955 | } | 1085 | } |
956 | 1086 | ||
957 | /* reading */ | 1087 | /* reading */ |
... | @@ -1160,11 +1290,10 @@ mailbox_unix_get_size (mailbox_t mbox, size_t msgno, size_t *h, size_t *b) | ... | @@ -1160,11 +1290,10 @@ mailbox_unix_get_size (mailbox_t mbox, size_t msgno, size_t *h, size_t *b) |
1160 | mailbox_unix_message_t mum; | 1290 | mailbox_unix_message_t mum; |
1161 | 1291 | ||
1162 | if (mbox == NULL || | 1292 | if (mbox == NULL || |
1163 | (mud = (mailbox_unix_data_t)mbox->data) == NULL) | 1293 | (mud = (mailbox_unix_data_t)mbox->data) == NULL || |
1294 | !mailbox_unix_is_valid (mbox, msgno)) | ||
1164 | return EINVAL; | 1295 | return EINVAL; |
1165 | 1296 | ||
1166 | if (mailbox_unix_is_valid (mbox, msgno)) | ||
1167 | return EINVAL; | ||
1168 | mum = &(mud->messages[msgno]); | 1297 | mum = &(mud->messages[msgno]); |
1169 | if (h) | 1298 | if (h) |
1170 | *h = mum->header_end - mum->header; | 1299 | *h = mum->header_end - mum->header; |
... | @@ -1173,21 +1302,50 @@ mailbox_unix_get_size (mailbox_t mbox, size_t msgno, size_t *h, size_t *b) | ... | @@ -1173,21 +1302,50 @@ mailbox_unix_get_size (mailbox_t mbox, size_t msgno, size_t *h, size_t *b) |
1173 | return 0; | 1302 | return 0; |
1174 | } | 1303 | } |
1175 | 1304 | ||
1176 | static int mailbox_unix_messages_count (mailbox_t mbox, size_t *count) | 1305 | static int |
1306 | mailbox_unix_messages_count (mailbox_t mbox, size_t *count) | ||
1177 | { | 1307 | { |
1178 | mailbox_unix_data_t mud; | 1308 | mailbox_unix_data_t mud; |
1179 | if (mbox == NULL || (mud = (mailbox_unix_data_t) mbox->data) == NULL) | 1309 | if (mbox == NULL || (mud = (mailbox_unix_data_t) mbox->data) == NULL) |
1180 | return EINVAL; | 1310 | return EINVAL; |
1181 | 1311 | ||
1182 | if (! mailbox_is_updated (mbox)) | 1312 | if (! mailbox_unix_is_updated (mbox)) |
1183 | return mailbox_unix_scan (mbox, count); | 1313 | return mailbox_unix_parse (mbox, count); |
1184 | 1314 | ||
1185 | if (count) | 1315 | if (count) |
1186 | *count = mud->messages_count; | 1316 | *count = mud->messages_count; |
1187 | 1317 | ||
1188 | return 0; | 1318 | return 0; |
1189 | } | 1319 | } |
1190 | 1320 | ||
1321 | static int | ||
1322 | mailbox_unix_get_attribute (mailbox_t mbox, size_t msgno, | ||
1323 | attribute_t *pattribute) | ||
1324 | { | ||
1325 | mailbox_unix_data_t mud; | ||
1326 | |||
1327 | if (mbox == NULL || pattribute == NULL || | ||
1328 | (mud = (mailbox_unix_data_t)mbox->data) == NULL || | ||
1329 | ! mailbox_unix_is_valid (mbox, msgno)) | ||
1330 | return EINVAL; | ||
1331 | |||
1332 | *pattribute = mud->messages[msgno].new_attr; | ||
1333 | return 0; | ||
1334 | } | ||
1335 | |||
1336 | static int | ||
1337 | mailbox_unix_set_attribute (mailbox_t mbox, size_t msgno, | ||
1338 | attribute_t attribute) | ||
1339 | { | ||
1340 | mailbox_unix_data_t mud; | ||
1341 | if (mbox == NULL || | ||
1342 | (mud = (mailbox_unix_data_t)mbox->data) == NULL || | ||
1343 | ! mailbox_unix_is_valid (mbox, msgno)) | ||
1344 | return EINVAL; | ||
1345 | attribute_copy (mud->messages[msgno].new_attr, attribute); | ||
1346 | return 0; | ||
1347 | } | ||
1348 | |||
1191 | /* locking */ | 1349 | /* locking */ |
1192 | static int | 1350 | static int |
1193 | mailbox_unix_lock (mailbox_t mbox, int flag) | 1351 | mailbox_unix_lock (mailbox_t mbox, int flag) | ... | ... |
... | @@ -183,12 +183,37 @@ message_size (message_t msg, size_t *size) | ... | @@ -183,12 +183,37 @@ message_size (message_t msg, size_t *size) |
183 | size_t hs, bs; | 183 | size_t hs, bs; |
184 | int status; | 184 | int status; |
185 | status = mailbox_get_size (msg->mailbox, msg->num, &hs, &bs); | 185 | status = mailbox_get_size (msg->mailbox, msg->num, &hs, &bs); |
186 | if (status == 0) | 186 | if (status != 0) |
187 | { | 187 | return status; |
188 | if (size) | 188 | *size = hs + bs; |
189 | *size = hs + bs; | 189 | return 0; |
190 | } | ||
191 | return status; | ||
192 | } | 190 | } |
193 | return ENOSYS; | 191 | return ENOSYS; |
194 | } | 192 | } |
193 | |||
194 | int | ||
195 | message_get_attribute (message_t msg, attribute_t *pattribute) | ||
196 | { | ||
197 | if (msg == NULL || pattribute == NULL) | ||
198 | return EINVAL; | ||
199 | if (msg->attribute) | ||
200 | *pattribute = msg->attribute; | ||
201 | if (msg->mailbox) | ||
202 | { | ||
203 | int status; | ||
204 | status = mailbox_get_attribute (msg->mailbox, msg->num, pattribute); | ||
205 | if (status != 0) | ||
206 | return status; | ||
207 | msg->attribute = *pattribute; | ||
208 | (*pattribute)->message = msg; | ||
209 | return 0; | ||
210 | } | ||
211 | return ENOSYS; | ||
212 | } | ||
213 | |||
214 | int | ||
215 | message_set_attribute (message_t msg, attribute_t attribute) | ||
216 | { | ||
217 | (void)msg; (void)attribute; | ||
218 | return ENOSYS; | ||
219 | } | ... | ... |
... | @@ -33,11 +33,12 @@ | ... | @@ -33,11 +33,12 @@ |
33 | 33 | ||
34 | static struct _registrar registrar [] = { | 34 | static struct _registrar registrar [] = { |
35 | { NULL, NULL, 0, ®istrar[1] }, /* sentinel, head list */ | 35 | { NULL, NULL, 0, ®istrar[1] }, /* sentinel, head list */ |
36 | { &_url_mbox_registrar, &_mailbox_mbox_registrar, 0, ®istrar[2] }, | 36 | { &_url_file_registrar, &_mailbox_mbox_registrar, 0, ®istrar[2] }, |
37 | { &_url_unix_registrar, &_mailbox_unix_registrar, 0, ®istrar[3] }, | 37 | { &_url_mbox_registrar, &_mailbox_mbox_registrar, 0, ®istrar[3] }, |
38 | { &_url_maildir_registrar, &_mailbox_maildir_registrar, 0, ®istrar[4] }, | 38 | { &_url_unix_registrar, &_mailbox_unix_registrar, 0, ®istrar[4] }, |
39 | { &_url_mmdf_registrar, &_mailbox_mmdf_registrar, 0, ®istrar[5] }, | 39 | { &_url_maildir_registrar, &_mailbox_maildir_registrar, 0, ®istrar[5] }, |
40 | { &_url_pop_registrar, &_mailbox_pop_registrar, 0, ®istrar[6] }, | 40 | { &_url_mmdf_registrar, &_mailbox_mmdf_registrar, 0, ®istrar[6] }, |
41 | { &_url_pop_registrar, &_mailbox_pop_registrar, 0, ®istrar[7] }, | ||
41 | { &_url_imap_registrar, &_mailbox_imap_registrar, 0, ®istrar[0] }, | 42 | { &_url_imap_registrar, &_mailbox_imap_registrar, 0, ®istrar[0] }, |
42 | }; | 43 | }; |
43 | 44 | ||
... | @@ -175,6 +176,43 @@ registrar_get (int id, | ... | @@ -175,6 +176,43 @@ registrar_get (int id, |
175 | } | 176 | } |
176 | 177 | ||
177 | int | 178 | int |
179 | registrar_entry_count (size_t *num) | ||
180 | { | ||
181 | struct _registrar *current; | ||
182 | size_t count; | ||
183 | for (count = 0, current = registrar->next; current != registrar; | ||
184 | current = current->next, count++) | ||
185 | ; | ||
186 | if (num) | ||
187 | *num = count; | ||
188 | return 0; | ||
189 | } | ||
190 | |||
191 | int | ||
192 | registrar_entry (size_t num, struct url_registrar **ureg, | ||
193 | struct mailbox_registrar **mreg, int *id) | ||
194 | { | ||
195 | struct _registrar *current; | ||
196 | size_t count, status; | ||
197 | for (status = ENOENT, count = 0, current = registrar->next; | ||
198 | current != registrar; current = current->next, count++) | ||
199 | { | ||
200 | if (num == count) | ||
201 | { | ||
202 | if (ureg) | ||
203 | *ureg = current->ureg; | ||
204 | if (mreg) | ||
205 | *mreg = current->mreg; | ||
206 | if (id) | ||
207 | *id = (int)current; | ||
208 | status = 0; | ||
209 | break; | ||
210 | } | ||
211 | } | ||
212 | return status; | ||
213 | } | ||
214 | |||
215 | int | ||
178 | registrar_list (struct url_registrar **ureg, struct mailbox_registrar **mreg, | 216 | registrar_list (struct url_registrar **ureg, struct mailbox_registrar **mreg, |
179 | int *id, registrar_t *reg) | 217 | int *id, registrar_t *reg) |
180 | { | 218 | { | ... | ... |
... | @@ -59,6 +59,10 @@ extern int registrar_add __P ((struct url_registrar *ureg, | ... | @@ -59,6 +59,10 @@ extern int registrar_add __P ((struct url_registrar *ureg, |
59 | extern int registrar_remove __P ((int id)); | 59 | extern int registrar_remove __P ((int id)); |
60 | extern int registrar_get __P ((int id, struct url_registrar **ureg, | 60 | extern int registrar_get __P ((int id, struct url_registrar **ureg, |
61 | struct mailbox_registrar **mreg)); | 61 | struct mailbox_registrar **mreg)); |
62 | extern int registrar_num __P ((size_t *num)); | ||
63 | extern int registrar_get_entry __P ((size_t num, struct url_registrar **ureg, | ||
64 | struct mailbox_registrar **mreg, | ||
65 | int *id)); | ||
62 | extern int registrar_list __P ((struct url_registrar **ureg, | 66 | extern int registrar_list __P ((struct url_registrar **ureg, |
63 | struct mailbox_registrar **mreg, | 67 | struct mailbox_registrar **mreg, |
64 | int *id, registrar_t *reg)); | 68 | int *id, registrar_t *reg)); | ... | ... |
... | @@ -46,10 +46,21 @@ struct _registrar | ... | @@ -46,10 +46,21 @@ struct _registrar |
46 | struct _registrar *next; | 46 | struct _registrar *next; |
47 | }; | 47 | }; |
48 | 48 | ||
49 | |||
50 | /* This is function is obsolete use the registrar_entry_*() ones */ | ||
51 | extern int registrar_list __P ((struct url_registrar **ureg, | ||
52 | struct mailbox_registrar **mreg, | ||
53 | int *id, registrar_t *reg)); | ||
54 | extern int registrar_entry_count __P ((size_t *num)); | ||
55 | extern int registrar_entry __P ((size_t num, struct url_registrar **ureg, | ||
56 | struct mailbox_registrar **mreg, | ||
57 | int *id)); | ||
49 | /* IMAP */ | 58 | /* IMAP */ |
50 | extern struct mailbox_registrar _mailbox_imap_registrar; | 59 | extern struct mailbox_registrar _mailbox_imap_registrar; |
51 | extern struct url_registrar _url_imap_registrar; | 60 | extern struct url_registrar _url_imap_registrar; |
52 | 61 | ||
62 | /* FILE */ | ||
63 | extern struct url_registrar _url_file_registrar; | ||
53 | /* MBOX */ | 64 | /* MBOX */ |
54 | extern struct mailbox_registrar _mailbox_mbox_registrar; | 65 | extern struct mailbox_registrar _mailbox_mbox_registrar; |
55 | extern struct url_registrar _url_mbox_registrar; | 66 | extern struct url_registrar _url_mbox_registrar; | ... | ... |
... | @@ -28,10 +28,15 @@ | ... | @@ -28,10 +28,15 @@ |
28 | static int rfc822_parse (header_t h, const char *blurb, size_t len); | 28 | static int rfc822_parse (header_t h, const char *blurb, size_t len); |
29 | static int rfc822_set_value (header_t h, const char *fn, const char *fb, | 29 | static int rfc822_set_value (header_t h, const char *fn, const char *fb, |
30 | size_t n, int replace); | 30 | size_t n, int replace); |
31 | ssize_t rfc822_get_data (header_t h, char *buf, size_t buflen, | 31 | static int rfc822_get_value (header_t h, const char *fn, char *fb, |
32 | off_t off, int *err); | 32 | size_t len, size_t *n); |
33 | static int rfc822_get_value (header_t h, const char *fn, | 33 | static int rfc822_entry_count (header_t, size_t *num); |
34 | char *fb, size_t len, size_t *n); | 34 | static int rfc822_entry_name (header_t h, size_t num, char *buf, |
35 | size_t buflen, size_t *total); | ||
36 | static int rfc822_entry_value (header_t h, size_t num, char *buf, | ||
37 | size_t buflen, size_t *total); | ||
38 | static ssize_t rfc822_get_data (header_t h, char *buf, size_t buflen, | ||
39 | off_t off, int *err); | ||
35 | 40 | ||
36 | struct _rfc822 | 41 | struct _rfc822 |
37 | { | 42 | { |
... | @@ -57,6 +62,9 @@ rfc822_init (header_t *ph, const char *blurb, size_t len) | ... | @@ -57,6 +62,9 @@ rfc822_init (header_t *ph, const char *blurb, size_t len) |
57 | h->_parse = rfc822_parse; | 62 | h->_parse = rfc822_parse; |
58 | h->_get_value = rfc822_get_value; | 63 | h->_get_value = rfc822_get_value; |
59 | h->_set_value = rfc822_set_value; | 64 | h->_set_value = rfc822_set_value; |
65 | h->_entry_count = rfc822_entry_count; | ||
66 | h->_entry_name = rfc822_entry_name; | ||
67 | h->_entry_value = rfc822_entry_value; | ||
60 | h->_get_data = rfc822_get_data; | 68 | h->_get_data = rfc822_get_data; |
61 | 69 | ||
62 | status = h->_parse (h, blurb, len); | 70 | status = h->_parse (h, blurb, len); |
... | @@ -90,6 +98,14 @@ rfc822_destroy (header_t *ph) | ... | @@ -90,6 +98,14 @@ rfc822_destroy (header_t *ph) |
90 | } | 98 | } |
91 | } | 99 | } |
92 | 100 | ||
101 | /* | ||
102 | * Parsing is done in a rather simple fashion. | ||
103 | * meaning we just consider an entry to be | ||
104 | * a field-name an a field-value. So they | ||
105 | * maybe duplicate of field-name like "Received" | ||
106 | * they are just put in the array, see _get_value() | ||
107 | * on how to handle the case. | ||
108 | */ | ||
93 | static int | 109 | static int |
94 | rfc822_parse (header_t h, const char *blurb, size_t len) | 110 | rfc822_parse (header_t h, const char *blurb, size_t len) |
95 | { | 111 | { |
... | @@ -118,9 +134,9 @@ rfc822_parse (header_t h, const char *blurb, size_t len) | ... | @@ -118,9 +134,9 @@ rfc822_parse (header_t h, const char *blurb, size_t len) |
118 | for (header_start = rfc->blurb;; header_start = ++header_end) | 134 | for (header_start = rfc->blurb;; header_start = ++header_end) |
119 | { | 135 | { |
120 | /* get a header, a header is : | 136 | /* get a header, a header is : |
121 | field-name ':' field-body1 | 137 | * field-name ':' ' ' field-value '\r' '\n' |
122 | [ ' ' '\t' field-body2 ] '\r' '\n' | 138 | * [ (' ' | '\t') field-value '\r' '\n' ] |
123 | */ | 139 | */ |
124 | for (header_start2 = header_start;;header_start2 = ++header_end) | 140 | for (header_start2 = header_start;;header_start2 = ++header_end) |
125 | { | 141 | { |
126 | header_end = memchr (header_start2, '\n', len); | 142 | header_end = memchr (header_start2, '\n', len); |
... | @@ -195,36 +211,124 @@ rfc822_set_value (header_t h, const char *fn, const char *fv, | ... | @@ -195,36 +211,124 @@ rfc822_set_value (header_t h, const char *fn, const char *fv, |
195 | } | 211 | } |
196 | 212 | ||
197 | static int | 213 | static int |
198 | rfc822_get_value (header_t h, const char *fn, char *fv, size_t len, size_t *n) | 214 | rfc822_get_value (header_t h, const char *name, char *buffer, |
215 | size_t buflen, size_t *n) | ||
199 | { | 216 | { |
200 | size_t i = 0; | 217 | size_t i = 0; |
201 | size_t j = 0; | 218 | size_t name_len; |
202 | size_t name_len, fn_len, fv_len; | 219 | size_t total = 0, fn_len = 0, fv_len = 0; |
220 | int threshold; | ||
203 | rfc822_t rfc; | 221 | rfc822_t rfc; |
204 | 222 | ||
205 | if (h == NULL || fn == NULL || (rfc = (rfc822_t)h->data) == NULL) | 223 | if (h == NULL || name == NULL || |
224 | (rfc = (rfc822_t)h->data) == NULL) | ||
206 | return EINVAL; | 225 | return EINVAL; |
207 | 226 | ||
208 | for (name_len = strlen (fn), i = 0; i < rfc->hdr_count; i++) | 227 | /* we set the threshold to be 1 less for the null */ |
228 | threshold = --buflen; | ||
229 | |||
230 | /* | ||
231 | * Caution: We may have more then one value for a field | ||
232 | * name, for example a "Received" field-name is added by | ||
233 | * each passing MTA. The way that the parsing (_parse()) | ||
234 | * is done it's not take to account. So we just stuff in | ||
235 | * the buffer all the field-values to a corresponding field-name. | ||
236 | * FIXME: Should we kosher the output ? meaning replace | ||
237 | * occurences of " \t\r\n" for spaces ? for now we don't. | ||
238 | */ | ||
239 | for (name_len = strlen (name), i = 0; i < rfc->hdr_count; i++) | ||
209 | { | 240 | { |
210 | fn_len = rfc->hdr[i].fn_end - rfc->hdr[i].fn; | 241 | fn_len = rfc->hdr[i].fn_end - rfc->hdr[i].fn; |
211 | if (fn_len == name_len && memcmp (rfc->hdr[i].fn, fn, fn_len) == 0) | 242 | if (fn_len == name_len && memcmp (rfc->hdr[i].fn, name, fn_len) == 0) |
212 | { | 243 | { |
213 | fv_len = rfc->hdr[i].fv_end - rfc->hdr[i].fv; | 244 | fv_len = (rfc->hdr[i].fv_end - rfc->hdr[i].fv); |
214 | j = (len < fv_len) ? len : fv_len; | 245 | total += fv_len; |
215 | if (fv) | 246 | /* can everything fit in the buffer */ |
216 | memcpy (fv, rfc->hdr[i].fv, j); | 247 | if (buffer && threshold > 0) |
217 | break; | 248 | { |
249 | threshold -= fv_len; | ||
250 | if (threshold > 0) | ||
251 | { | ||
252 | memcpy (buffer, rfc->hdr[i].fv, fv_len); | ||
253 | buffer += fv_len; | ||
254 | } | ||
255 | else if (threshold < 0) | ||
256 | { | ||
257 | threshold += fv_len; | ||
258 | memcpy (buffer, rfc->hdr[i].fv, threshold); | ||
259 | buffer += threshold; | ||
260 | threshold = 0; | ||
261 | } | ||
262 | } | ||
218 | } | 263 | } |
219 | } | 264 | } |
220 | if (fv) | 265 | if (buffer) |
221 | fv[j] = '\0'; /* null terminated */ | 266 | *buffer = '\0'; /* null terminated */ |
222 | if (n) | 267 | if (n) |
223 | *n = fv_len; | 268 | *n = total; |
269 | return 0; | ||
270 | } | ||
271 | |||
272 | static int | ||
273 | rfc822_entry_count (header_t h, size_t *num) | ||
274 | { | ||
275 | rfc822_t rfc; | ||
276 | if (h == NULL || (rfc = (rfc822_t)h->data) == NULL) | ||
277 | return EINVAL; | ||
278 | if (num) | ||
279 | *num = rfc->hdr_count; | ||
280 | return 0; | ||
281 | } | ||
282 | |||
283 | static int | ||
284 | rfc822_entry_name (header_t h, size_t num, char *buf, | ||
285 | size_t buflen, size_t *nwritten) | ||
286 | { | ||
287 | rfc822_t rfc; | ||
288 | size_t len; | ||
289 | if (h == NULL || (rfc = (rfc822_t)h->data) == NULL) | ||
290 | return EINVAL; | ||
291 | if (rfc->hdr_count == 0 || num > rfc->hdr_count) | ||
292 | return ENOENT; | ||
293 | len = rfc->hdr[num].fn_end - rfc->hdr[num].fn; | ||
294 | /* save one for the null */ | ||
295 | --buflen; | ||
296 | if (buf && buflen > 0) | ||
297 | { | ||
298 | buflen = (len > buflen) ? buflen : len; | ||
299 | memcpy (buf, rfc->hdr[num].fn, buflen); | ||
300 | buf[buflen] = '\0'; | ||
301 | } | ||
302 | if (nwritten) | ||
303 | *nwritten = len; | ||
304 | return 0; | ||
305 | } | ||
306 | |||
307 | static int | ||
308 | rfc822_entry_value (header_t h, size_t num, char *buf, | ||
309 | size_t buflen, size_t *nwritten) | ||
310 | { | ||
311 | rfc822_t rfc; | ||
312 | size_t len; | ||
313 | if (h == NULL || (rfc = (rfc822_t)h->data) == NULL) | ||
314 | return EINVAL; | ||
315 | if (rfc->hdr_count == 0 || num > rfc->hdr_count) | ||
316 | return ENOENT; | ||
317 | len = rfc->hdr[num].fv_end - rfc->hdr[num].fv; | ||
318 | /* save one for the null */ | ||
319 | --buflen; | ||
320 | if (buf && buflen > 0) | ||
321 | { | ||
322 | buflen = (len > buflen) ? buflen : len; | ||
323 | memcpy (buf, rfc->hdr[num].fv, buflen); | ||
324 | buf[buflen] = '\0'; | ||
325 | } | ||
326 | if (nwritten) | ||
327 | *nwritten = len; | ||
224 | return 0; | 328 | return 0; |
225 | } | 329 | } |
226 | 330 | ||
227 | ssize_t | 331 | static ssize_t |
228 | rfc822_get_data (header_t h, char *buf, size_t buflen, off_t off, int *err) | 332 | rfc822_get_data (header_t h, char *buf, size_t buflen, off_t off, int *err) |
229 | { | 333 | { |
230 | rfc822_t rfc; | 334 | rfc822_t rfc; | ... | ... |
... | @@ -47,6 +47,7 @@ url_init (url_t * purl, const char *name) | ... | @@ -47,6 +47,7 @@ url_init (url_t * purl, const char *name) |
47 | registrar_t reg = NULL; | 47 | registrar_t reg = NULL; |
48 | size_t name_len; | 48 | size_t name_len; |
49 | int id; | 49 | int id; |
50 | size_t i, entry_count = 0; | ||
50 | 51 | ||
51 | /* Sanity checks */ | 52 | /* Sanity checks */ |
52 | if (name == NULL || *name == '\0') | 53 | if (name == NULL || *name == '\0') |
... | @@ -55,6 +56,22 @@ url_init (url_t * purl, const char *name) | ... | @@ -55,6 +56,22 @@ url_init (url_t * purl, const char *name) |
55 | name_len = strlen (name); | 56 | name_len = strlen (name); |
56 | 57 | ||
57 | /* Search for a known scheme */ | 58 | /* Search for a known scheme */ |
59 | registrar_entry_count (&entry_count); | ||
60 | for (i = 0; i < entry_count; i++) | ||
61 | { | ||
62 | if (registrar_entry (i, &ureg, &mreg, &id) == 0) | ||
63 | { | ||
64 | size_t scheme_len; | ||
65 | if (ureg && ureg->scheme && | ||
66 | name_len > (scheme_len = strlen (ureg->scheme)) && | ||
67 | memcmp (name, ureg->scheme, scheme_len) == 0) | ||
68 | { | ||
69 | status = 0; | ||
70 | break; | ||
71 | } | ||
72 | } | ||
73 | } | ||
74 | /* | ||
58 | while (registrar_list (&ureg, &mreg, &id, ®) == 0) | 75 | while (registrar_list (&ureg, &mreg, &id, ®) == 0) |
59 | { | 76 | { |
60 | size_t scheme_len; | 77 | size_t scheme_len; |
... | @@ -66,6 +83,7 @@ url_init (url_t * purl, const char *name) | ... | @@ -66,6 +83,7 @@ url_init (url_t * purl, const char *name) |
66 | break; | 83 | break; |
67 | } | 84 | } |
68 | } | 85 | } |
86 | */ | ||
69 | 87 | ||
70 | /* Found one initialize it */ | 88 | /* Found one initialize it */ |
71 | if (status == 0) | 89 | if (status == 0) | ... | ... |
-
Please register or sign in to post a comment