Commit 193c1ef7 193c1ef73dcbc058ee4481e2eed90288ffa5db24 by Alain Magloire

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.
1 parent e3fa2e8c
...@@ -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 }
......
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
22 22
23 #include <url.h> 23 #include <url.h>
24 #include <message.h> 24 #include <message.h>
25 #include <attribute.h>
25 #include <auth.h> 26 #include <auth.h>
26 #include <locker.h> 27 #include <locker.h>
27 28
......
...@@ -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, &registrar[1] }, /* sentinel, head list */ 35 { NULL, NULL, 0, &registrar[1] }, /* sentinel, head list */
36 { &_url_mbox_registrar, &_mailbox_mbox_registrar, 0, &registrar[2] }, 36 { &_url_file_registrar, &_mailbox_mbox_registrar, 0, &registrar[2] },
37 { &_url_unix_registrar, &_mailbox_unix_registrar, 0, &registrar[3] }, 37 { &_url_mbox_registrar, &_mailbox_mbox_registrar, 0, &registrar[3] },
38 { &_url_maildir_registrar, &_mailbox_maildir_registrar, 0, &registrar[4] }, 38 { &_url_unix_registrar, &_mailbox_unix_registrar, 0, &registrar[4] },
39 { &_url_mmdf_registrar, &_mailbox_mmdf_registrar, 0, &registrar[5] }, 39 { &_url_maildir_registrar, &_mailbox_maildir_registrar, 0, &registrar[5] },
40 { &_url_pop_registrar, &_mailbox_pop_registrar, 0, &registrar[6] }, 40 { &_url_mmdf_registrar, &_mailbox_mmdf_registrar, 0, &registrar[6] },
41 { &_url_pop_registrar, &_mailbox_pop_registrar, 0, &registrar[7] },
41 { &_url_imap_registrar, &_mailbox_imap_registrar, 0, &registrar[0] }, 42 { &_url_imap_registrar, &_mailbox_imap_registrar, 0, &registrar[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, &reg) == 0) 75 while (registrar_list (&ureg, &mreg, &id, &reg) == 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)
......