Commit 9388abdf 9388abdf122789ac02258c6ff09534a120f87965 by Alain Magloire

After exchange with Sam Roberts, it should possible to

	set a stream on the message and have the message_t do
	the rfc822 parsing.
	{
	  message_t mesg = NULL;
	  header_t header = NULL;
	  stream_t stream = NULL;
	  char buffer[512];
	  off_t off = 0;
	  size_t n = 0;

	  message_create (mesg, NULL);
	  file_stream_crete (&stream, "/home/user/mh/mesg_1");
	  message_set_stream (mesg, stream, NULL);

	  stream = NULL;
	  message_get_header (mesg, &header);
	  header_get_stream (header, &stream);
	  while (stream_readline (stream, buffer, sizeof buffer, off, &n) == 0
	          && n > 0) {
	    printf ("%s", buffer);
	    off += n;
	  }
	  message_destroy (&mesg, NULL);
	}

	* mailbox/message.c (message_header_fill): New
	function implements a header if there was a stream set on the message.
	(message_body_read): Implements the stream_read of body_t of
	a message if there were a stream set.
	(message_is_modified): Check if an object was set to message_t
	and flag it as modified.
	(message_get_body): If a stream was set on the message create a
	temporary stream for the body.
	(message_set_body): Set the message modified.
	(message_set_header): Set the message modified.
	(message_set_envelope): Set the message modified.
	(message_set_attribute): Set the message modified.

	* mailbox/wicket.c (wicket_destroy): return void.
	* include/mailutils/auth.h: wicket_destroy ()
	should return void.
	* mailbox/body.c (body_is_modified): Implemented.
	(body_clear_modified): Implemented.
	* mailbox/body.c (body_is_modified): Implemented.
	(body_clear_modified): Implemented.
	(_body_get_size0): New function.
	(_body_get_lines0): New function.
	(body_get_lines): Call _body_get_lines0().
	(body_get_size): Call _body_get_size0().
	(body_lines): Fall back on the stream and iterate
	the entire stream to find the  line numbers.
	(body_size):  Fall back on the stream for the size.

	* mailbox/folder_imap.c: Check if memory_stream_create()
	succeed and bailout if not.

	* mailbox/header.c (header_destroy): Free header->mstream.
	(fill_blurb): Remove redundant code, header_free_cache was
	doing the same.  Implement the code in term of a memory
	stream to hold the temporary header blurb.
	(header_write): Implemented.

	* mailbox/memory_stream.c (_memory_read): Cast the offset to size_t
	(_memory_readline): Cast the offset to size_t.
	(_memory_write): Cast the offset to size_t.
1 parent 1c1e3040
...@@ -61,14 +61,14 @@ extern int authority_set_authenticate __P ((authority_t, int (*_authenticate) __ ...@@ -61,14 +61,14 @@ extern int authority_set_authenticate __P ((authority_t, int (*_authenticate) __
61 struct _wicket; 61 struct _wicket;
62 typedef struct _wicket *wicket_t; 62 typedef struct _wicket *wicket_t;
63 63
64 extern int wicket_create __P ((wicket_t *, const char *)); 64 extern int wicket_create __P ((wicket_t *, const char *));
65 extern int wicket_destroy __P ((wicket_t *)); 65 extern void wicket_destroy __P ((wicket_t *));
66 extern int wicket_set_filename __P ((wicket_t, const char *)); 66 extern int wicket_set_filename __P ((wicket_t, const char *));
67 extern int wicket_get_filename __P ((wicket_t, char *, size_t, size_t *)); 67 extern int wicket_get_filename __P ((wicket_t, char *, size_t, size_t *));
68 extern int wicket_set_ticket __P ((wicket_t, int (*) 68 extern int wicket_set_ticket __P ((wicket_t, int (*)
69 __P ((wicket_t, const char *, 69 __P ((wicket_t, const char *,
70 const char *, ticket_t *)))); 70 const char *, ticket_t *))));
71 extern int wicket_get_ticket __P ((wicket_t, ticket_t *, const char *, const char *)); 71 extern int wicket_get_ticket __P ((wicket_t, ticket_t *, const char *, const char *));
72 72
73 #ifdef __cplusplus 73 #ifdef __cplusplus
74 } 74 }
......
...@@ -31,6 +31,8 @@ ...@@ -31,6 +31,8 @@
31 #include <mailutils/stream.h> 31 #include <mailutils/stream.h>
32 #include <body0.h> 32 #include <body0.h>
33 33
34 #define BODY_MODIFIED 0x10000
35
34 static int lazy_create __P ((body_t)); 36 static int lazy_create __P ((body_t));
35 static int _body_flush __P ((stream_t)); 37 static int _body_flush __P ((stream_t));
36 static int _body_get_fd __P ((stream_t, int *)); 38 static int _body_get_fd __P ((stream_t, int *));
...@@ -39,8 +41,12 @@ static int _body_readline __P ((stream_t, char *, size_t, off_t, size_t *)); ...@@ -39,8 +41,12 @@ static int _body_readline __P ((stream_t, char *, size_t, off_t, size_t *));
39 static int _body_truncate __P ((stream_t, off_t)); 41 static int _body_truncate __P ((stream_t, off_t));
40 static int _body_size __P ((stream_t, off_t *)); 42 static int _body_size __P ((stream_t, off_t *));
41 static int _body_write __P ((stream_t, const char *, size_t, off_t, size_t *)); 43 static int _body_write __P ((stream_t, const char *, size_t, off_t, size_t *));
42 static int _body_get_size __P ((body_t, size_t *)); 44
43 static int _body_get_lines __P ((body_t, size_t *)); 45 /* Our own defaults for the body. */
46 static int _body_get_size __P ((body_t, size_t *));
47 static int _body_get_lines __P ((body_t, size_t *));
48 static int _body_get_size0 __P ((stream_t, size_t *));
49 static int _body_get_lines0 __P ((stream_t, size_t *));
44 50
45 int 51 int
46 body_create (body_t *pbody, void *owner) 52 body_create (body_t *pbody, void *owner)
...@@ -100,14 +106,15 @@ int ...@@ -100,14 +106,15 @@ int
100 body_is_modified (body_t body) 106 body_is_modified (body_t body)
101 { 107 {
102 (void)body; 108 (void)body;
103 return 0; 109 return (body) ? (body->flags & BODY_MODIFIED) : 0;
104 } 110 }
105 111
106 /* FIXME: not implemented. */ 112 /* FIXME: not implemented. */
107 int 113 int
108 body_clear_modified (body_t body) 114 body_clear_modified (body_t body)
109 { 115 {
110 (void)body; 116 if (body)
117 body->flags &= ~BODY_MODIFIED;
111 return 0; 118 return 0;
112 } 119 }
113 120
...@@ -178,11 +185,12 @@ body_set_stream (body_t body, stream_t stream, void *owner) ...@@ -178,11 +185,12 @@ body_set_stream (body_t body, stream_t stream, void *owner)
178 /* make sure we destroy the old one if it is own by the body */ 185 /* make sure we destroy the old one if it is own by the body */
179 stream_destroy (&(body->stream), body); 186 stream_destroy (&(body->stream), body);
180 body->stream = stream; 187 body->stream = stream;
188 body->flags |= BODY_MODIFIED;
181 return 0; 189 return 0;
182 } 190 }
183 191
184 int 192 int
185 body_set_lines (body_t body, int (*_lines)(body_t, size_t *), void *owner) 193 body_set_lines (body_t body, int (*_lines)__P ((body_t, size_t *)), void *owner)
186 { 194 {
187 if (body == NULL) 195 if (body == NULL)
188 return EINVAL; 196 return EINVAL;
...@@ -199,6 +207,9 @@ body_lines (body_t body, size_t *plines) ...@@ -199,6 +207,9 @@ body_lines (body_t body, size_t *plines)
199 return EINVAL; 207 return EINVAL;
200 if (body->_lines) 208 if (body->_lines)
201 return body->_lines (body, plines); 209 return body->_lines (body, plines);
210 /* Fall on the stream. */
211 if (body->stream)
212 return _body_get_lines0 (body->stream, plines);
202 if (plines) 213 if (plines)
203 *plines = 0; 214 *plines = 0;
204 return 0; 215 return 0;
...@@ -211,6 +222,9 @@ body_size (body_t body, size_t *psize) ...@@ -211,6 +222,9 @@ body_size (body_t body, size_t *psize)
211 return EINVAL; 222 return EINVAL;
212 if (body->_size) 223 if (body->_size)
213 return body->_size (body, psize); 224 return body->_size (body, psize);
225 /* Fall on the stream. */
226 if (body->stream)
227 return _body_get_size0 (body->stream, psize);
214 if (psize) 228 if (psize)
215 *psize = 0; 229 *psize = 0;
216 return 0; 230 return 0;
...@@ -227,6 +241,8 @@ body_set_size (body_t body, int (*_size)(body_t, size_t*) , void *owner) ...@@ -227,6 +241,8 @@ body_set_size (body_t body, int (*_size)(body_t, size_t*) , void *owner)
227 return 0; 241 return 0;
228 } 242 }
229 243
244 /* Stub function for the body stream. */
245
230 static int 246 static int
231 _body_get_fd (stream_t stream, int *fd) 247 _body_get_fd (stream_t stream, int *fd)
232 { 248 {
...@@ -276,27 +292,40 @@ _body_flush (stream_t stream) ...@@ -276,27 +292,40 @@ _body_flush (stream_t stream)
276 return stream_flush (body->fstream); 292 return stream_flush (body->fstream);
277 } 293 }
278 294
295 /* Default function for the body. */
279 static int 296 static int
280 _body_get_size (body_t body, size_t *plines) 297 _body_get_lines (body_t body, size_t *plines)
298 {
299 return _body_get_lines0 (body->fstream, plines);
300 }
301
302 static int
303 _body_get_size (body_t body, size_t *psize)
304 {
305 return _body_get_size0 (body->fstream, psize);
306 }
307
308 static int
309 _body_get_size0 (stream_t stream, size_t *psize)
281 { 310 {
282 off_t off = 0; 311 off_t off = 0;
283 int status = _body_size (body->stream, &off); 312 int status = stream_size (stream, &off);
284 if (plines) 313 if (psize)
285 *plines = off; 314 *psize = off;
286 return status; 315 return status;
287 } 316 }
288 317
289 static int 318 static int
290 _body_get_lines (body_t body, size_t *plines) 319 _body_get_lines0 (stream_t stream, size_t *plines)
291 { 320 {
292 int status = stream_flush (body->fstream); 321 int status = stream_flush (stream);
293 size_t lines = 0; 322 size_t lines = 0;
294 if (status == 0) 323 if (status == 0)
295 { 324 {
296 char buf[128]; 325 char buf[128];
297 size_t n = 0; 326 size_t n = 0;
298 off_t off = 0; 327 off_t off = 0;
299 while ((status = stream_readline (body->fstream, buf, sizeof buf, 328 while ((status = stream_readline (stream, buf, sizeof buf,
300 off, &n)) == 0 && n > 0) 329 off, &n)) == 0 && n > 0)
301 { 330 {
302 if (buf[n - 1] == '\n') 331 if (buf[n - 1] == '\n')
......
...@@ -434,7 +434,9 @@ folder_imap_open (folder_t folder, int flags) ...@@ -434,7 +434,9 @@ folder_imap_open (folder_t folder, int flags)
434 { 434 {
435 CHECK_ERROR (f_imap, ENOMEM); 435 CHECK_ERROR (f_imap, ENOMEM);
436 } 436 }
437 memory_stream_create (&f_imap->string.stream); 437 status = memory_stream_create (&f_imap->string.stream);
438 CHECK_ERROR (f_imap, status);
439 stream_open (f_imap->string.stream, NULL, 0, MU_STREAM_RDWR);
438 } 440 }
439 else 441 else
440 { 442 {
......
...@@ -100,6 +100,9 @@ header_destroy (header_t *ph, void *owner) ...@@ -100,6 +100,9 @@ header_destroy (header_t *ph, void *owner)
100 100
101 header_free_cache (header); 101 header_free_cache (header);
102 102
103 if (header->mstream)
104 stream_destroy (&(header->mstream), NULL);
105
103 free (header); 106 free (header);
104 } 107 }
105 *ph = NULL; 108 *ph = NULL;
...@@ -144,7 +147,7 @@ header_parse (header_t header, const char *blurb, int len) ...@@ -144,7 +147,7 @@ header_parse (header_t header, const char *blurb, int len)
144 return 0; 147 return 0;
145 148
146 header->blurb_len = len; 149 header->blurb_len = len;
147 header->blurb = calloc (header->blurb_len + 1, sizeof(char)); 150 header->blurb = calloc (1, header->blurb_len + 1);
148 if (header->blurb == NULL) 151 if (header->blurb == NULL)
149 return ENOMEM; 152 return ENOMEM;
150 memcpy (header->blurb, blurb, header->blurb_len); 153 memcpy (header->blurb, blurb, header->blurb_len);
...@@ -845,27 +848,11 @@ fill_blurb (header_t header) ...@@ -845,27 +848,11 @@ fill_blurb (header_t header)
845 { 848 {
846 int status; 849 int status;
847 char buf[1024]; 850 char buf[1024];
848 char *tbuf; 851 size_t nread;
849 size_t nread = 0;
850 size_t i;
851 852
852 if (header->_fill == NULL) 853 if (header->_fill == NULL)
853 return 0; 854 return 0;
854 855
855 /* Free any fast header, since we will load the entire headers. */
856 for (i = 0; i < header->fhdr_count; i++)
857 {
858 if (header->fhdr[i].fn)
859 free (header->fhdr[i].fn);
860 if (header->fhdr[i].fv)
861 free (header->fhdr[i].fv);
862 }
863 if (header->fhdr)
864 {
865 free (header->fhdr);
866 header->fhdr = NULL;
867 }
868
869 /* The entire header is now ours(part of header_t), clear all the 856 /* The entire header is now ours(part of header_t), clear all the
870 overloading. */ 857 overloading. */
871 header_free_cache (header); 858 header_free_cache (header);
...@@ -875,45 +862,58 @@ fill_blurb (header_t header) ...@@ -875,45 +862,58 @@ fill_blurb (header_t header)
875 header->_size = NULL; 862 header->_size = NULL;
876 header->_lines = NULL; 863 header->_lines = NULL;
877 864
865 if (header->mstream == NULL)
866 {
867 status = memory_stream_create (&(header->mstream));
868 if (status != 0)
869 return status;
870 stream_open (header->mstream, NULL, 0, MU_STREAM_RDWR);
871 header->stream_len = 0;
872 }
873
874 /* Bring in the entire header. */
878 do 875 do
879 { 876 {
880 status = header->_fill (header, buf, sizeof (buf), 877 nread = 0;
881 header->temp_blurb_len, &nread) ; 878 status = header->_fill (header, buf, sizeof buf,
879 header->stream_len, &nread) ;
882 if (status != 0) 880 if (status != 0)
883 { 881 {
884 if (status != EAGAIN && status != EINTR) 882 if (status != EAGAIN && status != EINTR)
885 { 883 {
886 free (header->temp_blurb); 884 stream_destroy (&(header->mstream), NULL);
887 header->temp_blurb = NULL; 885 header->stream_len = 0;
888 header->temp_blurb_len = 0;
889 } 886 }
890 return status; 887 return status;
891 } 888 }
892 if (nread > 0) 889 if (nread > 0)
893 { 890 {
894 tbuf = realloc (header->temp_blurb, header->temp_blurb_len + nread); 891 status = stream_write (header->mstream, buf, nread, header->stream_len, NULL);
895 if (tbuf == NULL) 892 if (status != 0)
896 { 893 {
897 free (header->temp_blurb); 894 stream_destroy (&(header->mstream), NULL);
898 header->temp_blurb = NULL; 895 header->stream_len = 0;
899 header->temp_blurb_len = 0; 896 return status;
900 return ENOMEM;
901 } 897 }
902 header->temp_blurb = tbuf; 898 header->stream_len += nread;
903 memcpy (header->temp_blurb + header->temp_blurb_len, buf, nread);
904 header->temp_blurb_len += nread;
905 } 899 }
906 } 900 }
907 while (nread > 0); 901 while (nread > 0);
908 902
909 /* parse it. */ 903 /* parse it. */
910 status = header_parse (header, header->temp_blurb, header->temp_blurb_len); 904 {
911 if (header->temp_blurb) 905 char *blurb;
912 { 906 size_t len = header->stream_len;
913 free (header->temp_blurb); 907 blurb = calloc (1, len + 1);
914 header->temp_blurb = NULL; 908 if (blurb)
915 } 909 {
916 header->temp_blurb_len = 0; 910 stream_read (header->mstream, blurb, len, 0, &len);
911 status = header_parse (header, blurb, len);
912 }
913 free (blurb);
914 }
915 stream_destroy (&header->mstream, NULL);
916 header->stream_len = 0;
917 return status; 917 return status;
918 } 918 }
919 919
...@@ -922,17 +922,80 @@ header_write (stream_t os, const char *buf, size_t buflen, ...@@ -922,17 +922,80 @@ header_write (stream_t os, const char *buf, size_t buflen,
922 off_t off, size_t *pnwrite) 922 off_t off, size_t *pnwrite)
923 { 923 {
924 header_t header = stream_get_owner (os); 924 header_t header = stream_get_owner (os);
925 if (os == NULL || header == NULL) 925 int status;
926
927 if (header == NULL)
926 return EINVAL; 928 return EINVAL;
927 929
928 (void)buf; (void)off; 930 if ((size_t)off != header->stream_len)
929 if (buflen == 0) 931 return ESPIPE;
930 return 0; 932
933 /* Skip the obvious. */
934 if (buf == NULL || *buf == '\0' || buflen == 0)
935 {
936 if (pnwrite)
937 *pnwrite = 0;
938 return 0;
939 }
940
941 if (header->mstream == NULL)
942 {
943 status = memory_stream_create (&(header->mstream));
944 if (status != 0)
945 return status;
946 stream_open (header->mstream, NULL, 0, MU_STREAM_RDWR);
947 header->stream_len = 0;
948 }
949
950 status = stream_write (header->mstream, buf, buflen, header->stream_len, &buflen);
951 if (status != 0)
952 {
953 stream_destroy (&header->mstream, NULL);
954 header->stream_len = 0;
955 return status;
956 }
957 header->stream_len += buflen;
958
959 /* We detect an empty line .i.e "^\n$" this signal the end of the
960 header. */
961 if (header->stream_len)
962 {
963 int finish = 0;
964 char nlnl[2];
965 nlnl[1] = nlnl[0] = '\0';
966 stream_read (header->mstream, nlnl, 1, 0, NULL);
967 if (nlnl[0] == '\n')
968 {
969 finish = 1;
970 }
971 else
972 {
973 stream_read (header->mstream, nlnl, 2, header->stream_len - 2, NULL);
974 if (nlnl[0] == '\n' && nlnl[1] == '\n')
975 {
976 finish = 1;
977 }
978 }
979 if (finish)
980 {
981 char *blurb;
982 size_t len = header->stream_len;
983 blurb = calloc (1, len + 1);
984 if (blurb)
985 {
986 stream_read (header->mstream, blurb, len, 0, &len);
987 status = header_parse (header, blurb, len);
988 }
989 free (blurb);
990 stream_destroy (&header->mstream, NULL);
991 header->stream_len = 0;
992 }
993 }
931 994
932 if (pnwrite) 995 if (pnwrite)
933 *pnwrite = 0; 996 *pnwrite = buflen;
997 return 0;
934 998
935 return ENOSYS;
936 } 999 }
937 1000
938 static int 1001 static int
......
...@@ -55,8 +55,8 @@ struct _header ...@@ -55,8 +55,8 @@ struct _header
55 void *owner; 55 void *owner;
56 56
57 /* Data. */ 57 /* Data. */
58 char *temp_blurb; 58 stream_t mstream;
59 size_t temp_blurb_len; 59 size_t stream_len;
60 char *blurb; 60 char *blurb;
61 size_t blurb_len; 61 size_t blurb_len;
62 size_t hdr_count; 62 size_t hdr_count;
...@@ -65,7 +65,7 @@ struct _header ...@@ -65,7 +65,7 @@ struct _header
65 struct _hdr *fhdr; 65 struct _hdr *fhdr;
66 int flags; 66 int flags;
67 67
68 /* Streams. */ 68 /* Stream. */
69 stream_t stream; 69 stream_t stream;
70 int (*_get_value) __P ((header_t, const char *, char *, size_t , size_t *)); 70 int (*_get_value) __P ((header_t, const char *, char *, size_t , size_t *));
71 int (*_get_fvalue) __P ((header_t, const char *, char *, size_t , size_t *)); 71 int (*_get_fvalue) __P ((header_t, const char *, char *, size_t , size_t *));
......
...@@ -57,7 +57,7 @@ _memory_read (stream_t stream, char *optr, size_t osize, ...@@ -57,7 +57,7 @@ _memory_read (stream_t stream, char *optr, size_t osize,
57 { 57 {
58 struct _memory_stream *mfs = stream_get_owner (stream); 58 struct _memory_stream *mfs = stream_get_owner (stream);
59 size_t n = 0; 59 size_t n = 0;
60 if (mfs->ptr != NULL && (offset <= (off_t)mfs->size)) 60 if (mfs->ptr != NULL && ((size_t)offset <= mfs->size))
61 { 61 {
62 n = ((offset + osize) > mfs->size) ? mfs->size - offset : osize; 62 n = ((offset + osize) > mfs->size) ? mfs->size - offset : osize;
63 memcpy (optr, mfs->ptr + offset, n); 63 memcpy (optr, mfs->ptr + offset, n);
...@@ -74,7 +74,7 @@ _memory_readline (stream_t stream, char *optr, size_t osize, ...@@ -74,7 +74,7 @@ _memory_readline (stream_t stream, char *optr, size_t osize,
74 struct _memory_stream *mfs = stream_get_owner (stream); 74 struct _memory_stream *mfs = stream_get_owner (stream);
75 char *nl; 75 char *nl;
76 size_t n = 0; 76 size_t n = 0;
77 if (mfs->ptr && (offset < (off_t)mfs->size)) 77 if (mfs->ptr && ((size_t)offset < mfs->size))
78 { 78 {
79 /* Save space for the null byte. */ 79 /* Save space for the null byte. */
80 osize--; 80 osize--;
...@@ -96,7 +96,7 @@ _memory_write (stream_t stream, const char *iptr, size_t isize, ...@@ -96,7 +96,7 @@ _memory_write (stream_t stream, const char *iptr, size_t isize,
96 struct _memory_stream *mfs = stream_get_owner (stream); 96 struct _memory_stream *mfs = stream_get_owner (stream);
97 97
98 /* Bigger we have to realloc. */ 98 /* Bigger we have to realloc. */
99 if (mfs->capacity < (offset + isize)) 99 if (mfs->capacity < ((size_t)offset + isize))
100 { 100 {
101 /* Realloc by fixed blocks of 128. */ 101 /* Realloc by fixed blocks of 128. */
102 int newsize = MU_STREAM_MEMORY_BLOCKSIZE * 102 int newsize = MU_STREAM_MEMORY_BLOCKSIZE *
......
...@@ -35,6 +35,8 @@ ...@@ -35,6 +35,8 @@
35 #include <message0.h> 35 #include <message0.h>
36 #include <mailutils/address.h> 36 #include <mailutils/address.h>
37 37
38 #define MESSAGE_MODIFIED 0x10000;
39
38 static int message_read __P ((stream_t is, char *buf, size_t buflen, 40 static int message_read __P ((stream_t is, char *buf, size_t buflen,
39 off_t off, size_t *pnread )); 41 off_t off, size_t *pnread ));
40 static int message_write __P ((stream_t os, const char *buf, size_t buflen, 42 static int message_write __P ((stream_t os, const char *buf, size_t buflen,
...@@ -45,6 +47,11 @@ static int message_sender __P ((envelope_t envelope, char *buf, size_t len, ...@@ -45,6 +47,11 @@ static int message_sender __P ((envelope_t envelope, char *buf, size_t len,
45 static int message_date __P ((envelope_t envelope, char *buf, size_t len, 47 static int message_date __P ((envelope_t envelope, char *buf, size_t len,
46 size_t *pnwrite)); 48 size_t *pnwrite));
47 static int message_stream_size __P((stream_t stream, off_t *psize)); 49 static int message_stream_size __P((stream_t stream, off_t *psize));
50 static int message_header_fill __P ((header_t header, char *buffer,
51 size_t buflen, off_t off,
52 size_t * pnread));
53 static int message_body_read __P ((stream_t stream, char *buffer,
54 size_t n, off_t off, size_t *pn));
48 55
49 /* Allocate ressources for the message_t. */ 56 /* Allocate ressources for the message_t. */
50 int 57 int
...@@ -168,6 +175,7 @@ message_is_modified (message_t msg) ...@@ -168,6 +175,7 @@ message_is_modified (message_t msg)
168 mod |= header_is_modified (msg->header); 175 mod |= header_is_modified (msg->header);
169 mod |= attribute_is_modified (msg->attribute); 176 mod |= attribute_is_modified (msg->attribute);
170 mod |= body_is_modified (msg->body); 177 mod |= body_is_modified (msg->body);
178 mod |= msg->flags;
171 } 179 }
172 return mod; 180 return mod;
173 } 181 }
...@@ -183,6 +191,7 @@ message_clear_modified (message_t msg) ...@@ -183,6 +191,7 @@ message_clear_modified (message_t msg)
183 attribute_clear_modified (msg->attribute); 191 attribute_clear_modified (msg->attribute);
184 if (msg->body) 192 if (msg->body)
185 body_clear_modified (msg->body); 193 body_clear_modified (msg->body);
194 msg->flags &= ~MESSAGE_MODIFIED;
186 } 195 }
187 return 0; 196 return 0;
188 } 197 }
...@@ -220,6 +229,13 @@ message_get_header (message_t msg, header_t *phdr) ...@@ -220,6 +229,13 @@ message_get_header (message_t msg, header_t *phdr)
220 int status = header_create (&header, NULL, 0, msg); 229 int status = header_create (&header, NULL, 0, msg);
221 if (status != 0) 230 if (status != 0)
222 return status; 231 return status;
232 if (msg->stream)
233 {
234 /* Was it created by us? */
235 message_t mesg = stream_get_owner (msg->stream);
236 if (mesg != msg)
237 header_set_fill (header, message_header_fill, msg);
238 }
223 msg->header = header; 239 msg->header = header;
224 } 240 }
225 *phdr = msg->header; 241 *phdr = msg->header;
...@@ -238,6 +254,7 @@ message_set_header (message_t msg, header_t hdr, void *owner) ...@@ -238,6 +254,7 @@ message_set_header (message_t msg, header_t hdr, void *owner)
238 if (msg->header) 254 if (msg->header)
239 header_destroy (&(msg->header), msg); 255 header_destroy (&(msg->header), msg);
240 msg->header = hdr; 256 msg->header = hdr;
257 msg->flags |= MESSAGE_MODIFIED;
241 return 0; 258 return 0;
242 } 259 }
243 260
...@@ -254,6 +271,26 @@ message_get_body (message_t msg, body_t *pbody) ...@@ -254,6 +271,26 @@ message_get_body (message_t msg, body_t *pbody)
254 int status = body_create (&body, msg); 271 int status = body_create (&body, msg);
255 if (status != 0) 272 if (status != 0)
256 return status; 273 return status;
274 /* If a stream is already set use it to create the body stream. */
275 if (msg->stream)
276 {
277 /* Was it created by us? */
278 message_t mesg = stream_get_owner (msg->stream);
279 if (mesg != msg)
280 {
281 stream_t stream;
282 int flags = 0;
283 stream_get_flags (msg->stream, &flags);
284 if ((status = stream_create (&stream, flags, body)) != 0)
285 {
286 body_destroy (&body, msg);
287 return status;
288 }
289 stream_set_read (stream, message_body_read, body);
290 stream_setbufsiz (stream, 128);
291 body_set_stream (body, stream, msg);
292 }
293 }
257 msg->body = body; 294 msg->body = body;
258 } 295 }
259 *pbody = msg->body; 296 *pbody = msg->body;
...@@ -272,6 +309,7 @@ message_set_body (message_t msg, body_t body, void *owner) ...@@ -272,6 +309,7 @@ message_set_body (message_t msg, body_t body, void *owner)
272 if (msg->body) 309 if (msg->body)
273 body_destroy (&(msg->body), msg); 310 body_destroy (&(msg->body), msg);
274 msg->body = body; 311 msg->body = body;
312 msg->flags |= MESSAGE_MODIFIED;
275 return 0; 313 return 0;
276 } 314 }
277 315
...@@ -287,6 +325,7 @@ message_set_stream (message_t msg, stream_t stream, void *owner) ...@@ -287,6 +325,7 @@ message_set_stream (message_t msg, stream_t stream, void *owner)
287 if (msg->stream) 325 if (msg->stream)
288 stream_destroy (&(msg->stream), msg); 326 stream_destroy (&(msg->stream), msg);
289 msg->stream = stream; 327 msg->stream = stream;
328 msg->flags |= MESSAGE_MODIFIED;
290 return 0; 329 return 0;
291 } 330 }
292 331
...@@ -411,6 +450,7 @@ message_set_envelope (message_t msg, envelope_t envelope, void *owner) ...@@ -411,6 +450,7 @@ message_set_envelope (message_t msg, envelope_t envelope, void *owner)
411 if (msg->envelope) 450 if (msg->envelope)
412 envelope_destroy (&(msg->envelope), msg); 451 envelope_destroy (&(msg->envelope), msg);
413 msg->envelope = envelope; 452 msg->envelope = envelope;
453 msg->flags |= MESSAGE_MODIFIED;
414 return 0; 454 return 0;
415 } 455 }
416 456
...@@ -442,6 +482,7 @@ message_set_attribute (message_t msg, attribute_t attribute, void *owner) ...@@ -442,6 +482,7 @@ message_set_attribute (message_t msg, attribute_t attribute, void *owner)
442 if (msg->attribute) 482 if (msg->attribute)
443 attribute_destroy (&(msg->attribute), owner); 483 attribute_destroy (&(msg->attribute), owner);
444 msg->attribute = attribute; 484 msg->attribute = attribute;
485 msg->flags |= MESSAGE_MODIFIED;
445 return 0; 486 return 0;
446 } 487 }
447 488
...@@ -666,6 +707,7 @@ message_get_observable (message_t msg, observable_t *pobservable) ...@@ -666,6 +707,7 @@ message_get_observable (message_t msg, observable_t *pobservable)
666 return 0; 707 return 0;
667 } 708 }
668 709
710 /* Implements the stream_read () on the message stream. */
669 static int 711 static int
670 message_read (stream_t is, char *buf, size_t buflen, 712 message_read (stream_t is, char *buf, size_t buflen,
671 off_t off, size_t *pnread ) 713 off_t off, size_t *pnread )
...@@ -703,6 +745,7 @@ message_read (stream_t is, char *buf, size_t buflen, ...@@ -703,6 +745,7 @@ message_read (stream_t is, char *buf, size_t buflen,
703 return 0; 745 return 0;
704 } 746 }
705 747
748 /* Implements the stream_write () on the message stream. */
706 static int 749 static int
707 message_write (stream_t os, const char *buf, size_t buflen, 750 message_write (stream_t os, const char *buf, size_t buflen,
708 off_t off, size_t *pnwrite) 751 off_t off, size_t *pnwrite)
...@@ -715,7 +758,7 @@ message_write (stream_t os, const char *buf, size_t buflen, ...@@ -715,7 +758,7 @@ message_write (stream_t os, const char *buf, size_t buflen,
715 return EINVAL; 758 return EINVAL;
716 759
717 /* Skip the obvious. */ 760 /* Skip the obvious. */
718 if (buf == NULL || *buf == '\0' || buflen == 0) 761 if (buf == NULL || buflen == 0)
719 { 762 {
720 if (pnwrite) 763 if (pnwrite)
721 *pnwrite = 0; 764 *pnwrite = 0;
...@@ -726,39 +769,21 @@ message_write (stream_t os, const char *buf, size_t buflen, ...@@ -726,39 +769,21 @@ message_write (stream_t os, const char *buf, size_t buflen,
726 { 769 {
727 size_t len; 770 size_t len;
728 char *nl; 771 char *nl;
729 char *thdr; 772 header_t header = NULL;
773 stream_t hstream = NULL;
774 message_get_header (msg, &header);
775 header_get_stream (header, &hstream);
730 while (!msg->hdr_done && (nl = memchr (buf, '\n', buflen)) != NULL) 776 while (!msg->hdr_done && (nl = memchr (buf, '\n', buflen)) != NULL)
731 { 777 {
732 len = nl - buf + 1; 778 len = nl - buf + 1;
733 /* Allocate more buffer to hold the header. */ 779 status = stream_write (hstream, buf, len, msg->hdr_buflen, NULL);
734 thdr = realloc (msg->hdr_buf, msg->hdr_buflen + len); 780 if (status != 0)
735 if (thdr == NULL) 781 return status;
736 {
737 free (msg->hdr_buf);
738 msg->hdr_buf = NULL;
739 msg->hdr_buflen = 0;
740 return ENOMEM;
741 }
742 else
743 msg->hdr_buf = thdr;
744 memcpy (msg->hdr_buf + msg->hdr_buflen, buf, len);
745 msg->hdr_buflen += len; 782 msg->hdr_buflen += len;
746 /* We detect an empty line .i.e "^\n$" this signal the end of the 783 /* We detect an empty line .i.e "^\n$" this signal the end of the
747 header. */ 784 header. */
748 if (buf == nl) 785 if (buf == nl)
749 { 786 msg->hdr_done = 1;
750 header_destroy (&(msg->header), msg);
751 status = header_create (&(msg->header), msg->hdr_buf,
752 msg->hdr_buflen, msg);
753 free (msg->hdr_buf);
754 msg->hdr_buf = NULL;
755 if (status != 0)
756 {
757 msg->hdr_buflen = 0;
758 return status;
759 }
760 msg->hdr_done = 1;
761 }
762 buf = nl + 1; 787 buf = nl + 1;
763 buflen -= len; 788 buflen -= len;
764 } 789 }
...@@ -767,17 +792,13 @@ message_write (stream_t os, const char *buf, size_t buflen, ...@@ -767,17 +792,13 @@ message_write (stream_t os, const char *buf, size_t buflen,
767 /* Message header is not complete but was not a full line. */ 792 /* Message header is not complete but was not a full line. */
768 if (!msg->hdr_done && buflen > 0) 793 if (!msg->hdr_done && buflen > 0)
769 { 794 {
770 char *thdr = realloc (msg->hdr_buf, msg->hdr_buflen + buflen); 795 header_t header = NULL;
771 if (thdr == NULL) 796 stream_t hstream = NULL;
772 { 797 message_get_header (msg, &header);
773 free (msg->hdr_buf); 798 header_get_stream (header, &hstream);
774 msg->hdr_buf = NULL; 799 status = stream_write (hstream, buf, buflen, msg->hdr_buflen, NULL);
775 msg->hdr_buflen = 0; 800 if (status != 0)
776 return ENOMEM; 801 return status;
777 }
778 else
779 msg->hdr_buf = thdr;
780 memcpy (msg->hdr_buf + msg->hdr_buflen, buf, buflen);
781 msg->hdr_buflen += buflen; 802 msg->hdr_buflen += buflen;
782 buflen = 0; 803 buflen = 0;
783 } 804 }
...@@ -806,6 +827,7 @@ message_write (stream_t os, const char *buf, size_t buflen, ...@@ -806,6 +827,7 @@ message_write (stream_t os, const char *buf, size_t buflen,
806 return status; 827 return status;
807 } 828 }
808 829
830 /* Implements the stream_get_fd () on the message stream. */
809 static int 831 static int
810 message_get_fd (stream_t stream, int *pfd) 832 message_get_fd (stream_t stream, int *pfd)
811 { 833 {
...@@ -831,7 +853,8 @@ message_get_fd (stream_t stream, int *pfd) ...@@ -831,7 +853,8 @@ message_get_fd (stream_t stream, int *pfd)
831 return stream_get_fd (is, pfd); 853 return stream_get_fd (is, pfd);
832 } 854 }
833 855
834 int 856 /* Implements the stream_stream_size () on the message stream. */
857 static int
835 message_stream_size (stream_t stream, off_t *psize) 858 message_stream_size (stream_t stream, off_t *psize)
836 { 859 {
837 message_t msg = stream_get_owner (stream); 860 message_t msg = stream_get_owner (stream);
...@@ -920,3 +943,66 @@ message_sender (envelope_t envelope, char *buf, size_t len, size_t *pnwrite) ...@@ -920,3 +943,66 @@ message_sender (envelope_t envelope, char *buf, size_t len, size_t *pnwrite)
920 *pnwrite = n; 943 *pnwrite = n;
921 return 0; 944 return 0;
922 } 945 }
946
947 static int
948 message_header_fill (header_t header, char *buffer, size_t buflen,
949 off_t off, size_t * pnread)
950 {
951 int status = 0;
952 message_t msg = header_get_owner (header);
953 stream_t stream = NULL;
954 size_t nread = 0;
955
956 /* Noop. */
957 if (buffer == NULL || buflen == 0)
958 {
959 if (pnread)
960 *pnread = nread;
961 return 0;
962 }
963
964 if (!msg->hdr_done)
965 {
966 status = message_get_stream (msg, &stream);
967 if (status == 0)
968 {
969 /* Position the file pointer and the buffer. */
970 status = stream_readline (stream, buffer, buflen, off, &nread);
971 /* Detect the end of the headers. */
972 if (nread && buffer[0] == '\n' && buffer[1] == '\0')
973 {
974 msg->hdr_done = 1;
975 }
976 msg->hdr_buflen += nread;
977 }
978 }
979
980 if (pnread)
981 *pnread = nread;
982
983 return status;
984 }
985
986 static int
987 message_body_read (stream_t stream, char *buffer, size_t n, off_t off,
988 size_t *pn)
989 {
990 body_t body = stream_get_owner (stream);
991 message_t msg = body_get_owner (body);
992 size_t nread = 0;
993 header_t header = NULL;
994 stream_t bstream = NULL;
995 size_t size = 0;
996 int status;
997
998 message_get_header (msg, &header);
999 status = header_size (msg->header, &size);
1000 if (status == 0)
1001 {
1002 message_get_stream (msg, &bstream);
1003 status = stream_read (bstream, buffer, n, size + off, &nread);
1004 }
1005 if (pn)
1006 *pn = nread;
1007 return status;
1008 }
......
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
27 #include <unistd.h> 27 #include <unistd.h>
28 #include <ctype.h> 28 #include <ctype.h>
29 29
30 #include <mailutils/mutil.h>
30 #include <auth0.h> 31 #include <auth0.h>
31 32
32 struct myticket_data 33 struct myticket_data
...@@ -56,7 +57,7 @@ wicket_create (wicket_t *pwicket, const char *filename) ...@@ -56,7 +57,7 @@ wicket_create (wicket_t *pwicket, const char *filename)
56 return 0; 57 return 0;
57 } 58 }
58 59
59 int 60 void
60 wicket_destroy (wicket_t *pwicket) 61 wicket_destroy (wicket_t *pwicket)
61 { 62 {
62 if (pwicket && *pwicket) 63 if (pwicket && *pwicket)
...@@ -96,13 +97,13 @@ wicket_set_filename (wicket_t wicket, const char *filename) ...@@ -96,13 +97,13 @@ wicket_set_filename (wicket_t wicket, const char *filename)
96 } 97 }
97 98
98 int 99 int
99 wicket_set_ticket (wicket_t wicket, int _get_ticket 100 wicket_set_ticket (wicket_t wicket, int get_ticket
100 __P ((wicket_t, const char *, const char *, ticket_t *))) 101 __P ((wicket_t, const char *, const char *, ticket_t *)))
101 { 102 {
102 if (wicket == NULL) 103 if (wicket == NULL)
103 return EINVAL; 104 return EINVAL;
104 105
105 wicket->_get_ticket = _get_ticket; 106 wicket->_get_ticket = get_ticket;
106 return 0; 107 return 0;
107 } 108 }
108 109
......