Commit ed1175f9 ed1175f91d78846077062af5cf8a969dbaff80a6 by Alain Magloire

* mail/mail.c: Possibility to enable debuging output.

	It should probably be a runtime option via set debug=1 or something
	for now it is disable between if (0) {...}.

	More cleanup in the IMAP code.  A memory stream buffer is
	use to save the string literal sended by the IMAP server.
	The allocation is handle by the memory_stream which simplifies
	the code.

	* folder_imap.c (folder_imap.c): Create a memory stream to
	hold the literal or quoted string send by the IMAP server.
	(folder_imap_list folder_imap_lsub): There is no callback
	field the struct folder_list is in struct _f_imap now.
	(imap_literal_string imap_quoted_string imap_string):  Use the
	memory string stream to save the result.
	(imap_body): Still need to be clean, but creates the cache
	header when doing the scan.
	(imap_parse): Do not use alloca().
1 parent a59f00d4
1 2001-10-13 Jeff Bailey <jbailey@outpost.dnsalias.org> 1 2001-10-13 Alain Malgoire
2
3 * mail/mail.c: Possibility to enable debuging output.
4 It should probably be a runtime option via set debug=1 or something
5 for now it is disable between if (0) {...}.
6
7 More cleanup in the IMAP code. A memory stream buffer is
8 use to save the string literal sended by the IMAP server.
9 The allocation is handle by the memory_stream which simplifies
10 the code.
11
12 * folder_imap.c (folder_imap.c): Create a memory stream to
13 hold the literal or quoted string send by the IMAP server.
14 (folder_imap_list folder_imap_lsub): There is no callback
15 field the struct folder_list is in struct _f_imap now.
16 (imap_literal_string imap_quoted_string imap_string): Use the
17 memory string stream to save the result.
18 (imap_body): Still need to be clean, but creates the cache
19 header when doing the scan.
20 (imap_parse): Do not use alloca().
21
22 2001-10-13 Jeff Bailey
2 23
3 * guimb/Makefile.am: Remove GNU Makeism. 24 * guimb/Makefile.am: Remove GNU Makeism.
4 25
5 * libmu_scm/Makefile.am: Remove GNU Makeism. 26 * libmu_scm/Makefile.am: Remove GNU Makeism.
6 27
7 2001-10-12 Jeff Bailey <jbailey@outpost.dnsalias.org> 28 2001-10-12 Jeff Bailey
8 29
9 * libmu_scm/Makefile.am: Fixes for RO srcdir. 30 * libmu_scm/Makefile.am: Fixes for RO srcdir.
10 31
......
...@@ -345,6 +345,14 @@ main (int argc, char **argv) ...@@ -345,6 +345,14 @@ main (int argc, char **argv)
345 exit (EXIT_FAILURE); 345 exit (EXIT_FAILURE);
346 } 346 }
347 347
348 /* Could we enable this at runtime, via the a set environment? */
349 if (0)
350 {
351 mu_debug_t debug = NULL;
352 mailbox_get_debug (mbox, &debug);
353 mu_debug_set_level (debug, MU_DEBUG_TRACE|MU_DEBUG_PROT);
354 }
355
348 if (mailbox_open (mbox, MU_STREAM_RDWR) != 0) 356 if (mailbox_open (mbox, MU_STREAM_RDWR) != 0)
349 { 357 {
350 util_error ("Can not open mailbox"); 358 util_error ("Can not open mailbox");
......
...@@ -140,10 +140,24 @@ struct _f_imap ...@@ -140,10 +140,24 @@ struct _f_imap
140 size_t seq; /* Sequence number to build a tag. */ 140 size_t seq; /* Sequence number to build a tag. */
141 char *capa; /* Cabilities of the server. */ 141 char *capa; /* Cabilities of the server. */
142 size_t flags; 142 size_t flags;
143 struct literal_string callback; 143
144 /* IO use to hold the literal and quoted strings send by
145 the IMAP server. */
146 struct
147 {
148 stream_t stream;
149 off_t offset;
150 size_t nleft; /* nleft to read in the literal. */
151 msg_imap_t msg_imap;
152 enum imap_state type;
153 } string;
154
155 /* Use for LIST and LSUB. */
156 struct folder_list flist;
144 157
145 int isopen; 158 int isopen;
146 /* Buffer I/O */ 159
160 /* Server channel buffer I/O */
147 size_t buflen; 161 size_t buflen;
148 char *buffer; 162 char *buffer;
149 char *ptr; 163 char *ptr;
...@@ -155,7 +169,6 @@ struct _f_imap ...@@ -155,7 +169,6 @@ struct _f_imap
155 /* Login */ 169 /* Login */
156 char *user; 170 char *user;
157 char *passwd; 171 char *passwd;
158
159 }; 172 };
160 173
161 struct _m_imap 174 struct _m_imap
...@@ -187,6 +200,7 @@ struct _msg_imap ...@@ -187,6 +200,7 @@ struct _msg_imap
187 size_t uid; 200 size_t uid;
188 201
189 header_t fheader; 202 header_t fheader;
203 char *internal_date;
190 204
191 size_t message_size; 205 size_t message_size;
192 size_t message_lines; 206 size_t message_lines;
......
...@@ -174,6 +174,8 @@ free_subparts (msg_imap_t msg_imap) ...@@ -174,6 +174,8 @@ free_subparts (msg_imap_t msg_imap)
174 free (msg_imap->parts); 174 free (msg_imap->parts);
175 if (msg_imap->fheader) 175 if (msg_imap->fheader)
176 header_destroy (&msg_imap->fheader, NULL); 176 header_destroy (&msg_imap->fheader, NULL);
177 if (msg_imap->internal_date)
178 free (msg_imap->internal_date);
177 free(msg_imap); 179 free(msg_imap);
178 } 180 }
179 181
...@@ -672,9 +674,15 @@ imap_expunge (mailbox_t mailbox) ...@@ -672,9 +674,15 @@ imap_expunge (mailbox_t mailbox)
672 { 674 {
673 case IMAP_NO_STATE: 675 case IMAP_NO_STATE:
674 { 676 {
675 char *set; 677 char *set = NULL;
676 status = delete_to_string (m_imap, &set); 678 status = delete_to_string (m_imap, &set);
677 CHECK_ERROR (f_imap, status); 679 CHECK_ERROR (f_imap, status);
680 if (set == NULL || *set == '\0')
681 {
682 if (set)
683 free (set);
684 return 0;
685 }
678 status = imap_writeline (f_imap, 686 status = imap_writeline (f_imap,
679 "g%d STORE %s +FLAGS.SILENT (\\Deleted)\r\n", 687 "g%d STORE %s +FLAGS.SILENT (\\Deleted)\r\n",
680 f_imap->seq++, set); 688 f_imap->seq++, set);
...@@ -1224,6 +1232,9 @@ imap_envelope_date (envelope_t envelope, char *buffer, size_t buflen, ...@@ -1224,6 +1232,9 @@ imap_envelope_date (envelope_t envelope, char *buffer, size_t buflen,
1224 const char** datep = &date; 1232 const char** datep = &date;
1225 /* reserve as much space as we need for internal-date */ 1233 /* reserve as much space as we need for internal-date */
1226 int status; 1234 int status;
1235
1236 if (msg_imap->internal_date == NULL)
1237 {
1227 if (f_imap->state == IMAP_NO_STATE) 1238 if (f_imap->state == IMAP_NO_STATE)
1228 { 1239 {
1229 /* Select first. */ 1240 /* Select first. */
...@@ -1237,9 +1248,17 @@ imap_envelope_date (envelope_t envelope, char *buffer, size_t buflen, ...@@ -1237,9 +1248,17 @@ imap_envelope_date (envelope_t envelope, char *buffer, size_t buflen,
1237 MAILBOX_DEBUG0 (m_imap->mailbox, MU_DEBUG_PROT, f_imap->buffer); 1248 MAILBOX_DEBUG0 (m_imap->mailbox, MU_DEBUG_PROT, f_imap->buffer);
1238 f_imap->state = IMAP_FETCH; 1249 f_imap->state = IMAP_FETCH;
1239 } 1250 }
1240 status = fetch_operation (f_imap, msg_imap, datebuf, sizeof datebuf, NULL); 1251 status = fetch_operation (f_imap, msg_imap, datebuf,
1252 sizeof datebuf, NULL);
1241 if (status != 0) 1253 if (status != 0)
1242 return status; 1254 return status;
1255 msg_imap->internal_date = strdup (datebuf);
1256 }
1257 else
1258 {
1259 date = msg_imap->internal_date;
1260 datep = &date;
1261 }
1243 1262
1244 if (mu_parse_imap_date_time(datep, &tm, &tz) != 0) 1263 if (mu_parse_imap_date_time(datep, &tm, &tz) != 0)
1245 now = (time_t)-1; 1264 now = (time_t)-1;
...@@ -1323,6 +1342,10 @@ imap_attr_set_flags (attribute_t attribute, int flag) ...@@ -1323,6 +1342,10 @@ imap_attr_set_flags (attribute_t attribute, int flag)
1323 f_imap_t f_imap = m_imap->f_imap; 1342 f_imap_t f_imap = m_imap->f_imap;
1324 int status = 0; 1343 int status = 0;
1325 1344
1345 /* If already set don't bother. */
1346 if (msg_imap->flags & flag)
1347 return 0;
1348
1326 /* The delete FLAG is not pass yet but only on the expunge. */ 1349 /* The delete FLAG is not pass yet but only on the expunge. */
1327 if (flag & MU_ATTRIBUTE_DELETED) 1350 if (flag & MU_ATTRIBUTE_DELETED)
1328 { 1351 {
...@@ -1705,13 +1728,11 @@ fetch_operation (f_imap_t f_imap, msg_imap_t msg_imap, char *buffer, ...@@ -1705,13 +1728,11 @@ fetch_operation (f_imap_t f_imap, msg_imap_t msg_imap, char *buffer,
1705 case IMAP_FETCH: 1728 case IMAP_FETCH:
1706 status = imap_send (f_imap); 1729 status = imap_send (f_imap);
1707 CHECK_EAGAIN (f_imap, status); 1730 CHECK_EAGAIN (f_imap, status);
1708 if (f_imap->callback.buffer) 1731 stream_truncate (f_imap->string.stream, 0);
1709 free (f_imap->callback.buffer); 1732 f_imap->string.offset = 0;
1710 f_imap->callback.buffer = NULL; 1733 f_imap->string.nleft = 0;
1711 f_imap->callback.buflen = 0; 1734 f_imap->string.type = IMAP_NO_STATE;
1712 f_imap->callback.total = 0; 1735 f_imap->string.msg_imap = msg_imap;
1713 f_imap->callback.nleft = 0;
1714 f_imap->callback.msg_imap = msg_imap;
1715 f_imap->state = IMAP_FETCH_ACK; 1736 f_imap->state = IMAP_FETCH_ACK;
1716 1737
1717 case IMAP_FETCH_ACK: 1738 case IMAP_FETCH_ACK:
...@@ -1725,25 +1746,21 @@ fetch_operation (f_imap_t f_imap, msg_imap_t msg_imap, char *buffer, ...@@ -1725,25 +1746,21 @@ fetch_operation (f_imap_t f_imap, msg_imap_t msg_imap, char *buffer,
1725 break; 1746 break;
1726 } 1747 }
1727 1748
1728 if (status == 0 && f_imap->isopen == 0 && f_imap->callback.total == 0) 1749 f_imap->state = IMAP_NO_STATE;
1750
1751 /* The server may have timeout any case connection is gone away. */
1752 if (status == 0 && f_imap->isopen == 0 && f_imap->string.offset == 0)
1729 status = EBADF; 1753 status = EBADF;
1730 1754
1731 buflen = min (buflen, f_imap->callback.total);
1732 if (f_imap->callback.buffer)
1733 {
1734 if (buffer) 1755 if (buffer)
1735 memcpy (buffer, f_imap->callback.buffer, buflen); 1756 stream_read (f_imap->string.stream, buffer, buflen, 0, plen);
1736 free (f_imap->callback.buffer); 1757 else if (plen)
1737 } 1758 *plen = 0;
1738 if (plen) 1759 stream_truncate (f_imap->string.stream, 0);
1739 *plen = buflen; 1760 f_imap->string.offset = 0;
1740 f_imap->callback.buffer = NULL; 1761 f_imap->string.nleft = 0;
1741 f_imap->callback.buflen = 0; 1762 f_imap->string.type = IMAP_NO_STATE;
1742 f_imap->callback.total = 0; 1763 f_imap->string.msg_imap = NULL;
1743 f_imap->callback.nleft = 0;
1744 f_imap->callback.type = 0;
1745 f_imap->callback.msg_imap = NULL;
1746 f_imap->state = IMAP_NO_STATE;
1747 return status; 1764 return status;
1748 } 1765 }
1749 1766
......
...@@ -22,15 +22,24 @@ ...@@ -22,15 +22,24 @@
22 #include <errno.h> 22 #include <errno.h>
23 #include <stdlib.h> 23 #include <stdlib.h>
24 #include <string.h> 24 #include <string.h>
25 #include <sys/stat.h>
26 #include <unistd.h>
27 #include <stdio.h>
25 28
26 #include <sys/types.h> 29 #include <sys/types.h>
27 30
28 #include <mailutils/stream.h> 31 #include <mailutils/stream.h>
29 32
33 #undef min
34 #define min(a,b) ((a) < (b) ? (a) : (b))
35
36 #define MU_STREAM_MEMORY_BLOCKSIZE 128
37
30 struct _memory_stream 38 struct _memory_stream
31 { 39 {
32 char *ptr; 40 char *ptr;
33 size_t size; 41 size_t size;
42 size_t capacity;
34 }; 43 };
35 44
36 static void 45 static void
...@@ -71,7 +80,7 @@ _memory_readline (stream_t stream, char *optr, size_t osize, ...@@ -71,7 +80,7 @@ _memory_readline (stream_t stream, char *optr, size_t osize,
71 osize--; 80 osize--;
72 nl = memchr (mfs->ptr + offset, '\n', mfs->size - offset); 81 nl = memchr (mfs->ptr + offset, '\n', mfs->size - offset);
73 n = (nl) ? (size_t)(nl - (mfs->ptr + offset) + 1) : mfs->size - offset; 82 n = (nl) ? (size_t)(nl - (mfs->ptr + offset) + 1) : mfs->size - offset;
74 n = (n > osize) ? osize : n; 83 n = min (n, osize);
75 memcpy (optr, mfs->ptr + offset, n); 84 memcpy (optr, mfs->ptr + offset, n);
76 optr[n] = '\0'; 85 optr[n] = '\0';
77 } 86 }
...@@ -87,13 +96,17 @@ _memory_write (stream_t stream, const char *iptr, size_t isize, ...@@ -87,13 +96,17 @@ _memory_write (stream_t stream, const char *iptr, size_t isize,
87 struct _memory_stream *mfs = stream_get_owner (stream); 96 struct _memory_stream *mfs = stream_get_owner (stream);
88 97
89 /* Bigger we have to realloc. */ 98 /* Bigger we have to realloc. */
90 if (mfs->size < (offset + isize)) 99 if (mfs->capacity < (offset + isize))
91 { 100 {
92 char *tmp = realloc (mfs->ptr, offset + isize); 101 /* Realloc by fixed blocks of 128. */
102 int newsize = MU_STREAM_MEMORY_BLOCKSIZE *
103 (((offset + isize)/MU_STREAM_MEMORY_BLOCKSIZE) + 1);
104 char *tmp = realloc (mfs->ptr, newsize);
93 if (tmp == NULL) 105 if (tmp == NULL)
94 return ENOMEM; 106 return ENOMEM;
95 mfs->ptr = tmp; 107 mfs->ptr = tmp;
96 mfs->size = offset + isize; 108 mfs->size = offset + isize;
109 mfs->capacity = newsize;
97 } 110 }
98 111
99 memcpy (mfs->ptr + offset, iptr, isize); 112 memcpy (mfs->ptr + offset, iptr, isize);
...@@ -109,6 +122,7 @@ _memory_truncate (stream_t stream, off_t len) ...@@ -109,6 +122,7 @@ _memory_truncate (stream_t stream, off_t len)
109 122
110 if (len == 0) 123 if (len == 0)
111 { 124 {
125 if (mfs->ptr)
112 free (mfs->ptr); 126 free (mfs->ptr);
113 mfs->ptr = NULL; 127 mfs->ptr = NULL;
114 } 128 }
...@@ -120,6 +134,7 @@ _memory_truncate (stream_t stream, off_t len) ...@@ -120,6 +134,7 @@ _memory_truncate (stream_t stream, off_t len)
120 mfs->ptr = tmp; 134 mfs->ptr = tmp;
121 } 135 }
122 mfs->size = len; 136 mfs->size = len;
137 mfs->capacity = len;
123 return 0; 138 return 0;
124 } 139 }
125 140
...@@ -137,11 +152,10 @@ _memory_close (stream_t stream) ...@@ -137,11 +152,10 @@ _memory_close (stream_t stream)
137 { 152 {
138 struct _memory_stream *mfs = stream_get_owner (stream); 153 struct _memory_stream *mfs = stream_get_owner (stream);
139 if (mfs->ptr) 154 if (mfs->ptr)
140 {
141 free (mfs->ptr); 155 free (mfs->ptr);
142 mfs->ptr = NULL; 156 mfs->ptr = NULL;
143 mfs->size = 0; 157 mfs->size = 0;
144 } 158 mfs->capacity = 0;
145 return 0; 159 return 0;
146 } 160 }
147 161
...@@ -149,6 +163,7 @@ static int ...@@ -149,6 +163,7 @@ static int
149 _memory_open (stream_t stream, const char *filename, int port, int flags) 163 _memory_open (stream_t stream, const char *filename, int port, int flags)
150 { 164 {
151 struct _memory_stream *mfs = stream_get_owner (stream); 165 struct _memory_stream *mfs = stream_get_owner (stream);
166 int status = 0;
152 167
153 (void)port; /* Ignored. */ 168 (void)port; /* Ignored. */
154 (void)filename; /* Ignored. */ 169 (void)filename; /* Ignored. */
...@@ -156,13 +171,47 @@ _memory_open (stream_t stream, const char *filename, int port, int flags) ...@@ -156,13 +171,47 @@ _memory_open (stream_t stream, const char *filename, int port, int flags)
156 171
157 /* Close any previous file. */ 172 /* Close any previous file. */
158 if (mfs->ptr) 173 if (mfs->ptr)
174 free (mfs->ptr);
175 mfs->ptr = NULL;
176 mfs->size = 0;
177 mfs->capacity = 0;
178 stream_set_flags (stream, flags |MU_STREAM_NO_CHECK);
179 if (filename)
180 {
181 struct stat statbuf;
182 if (stat (filename, &statbuf) == 0)
183 {
184 mfs->ptr = calloc (statbuf.st_size, 1);
185 if (mfs->ptr)
186 {
187 FILE *fp;
188 mfs->capacity = statbuf.st_size;
189 mfs->size = statbuf.st_size;
190 fp = fopen (filename, "r");
191 if (fp)
192 {
193 size_t r = fread (mfs->ptr, mfs->size, 1, fp);
194 if (r != mfs->size)
195 status = EIO;
196 fclose (fp);
197 }
198 else
199 status = errno;
200 if (status != 0)
159 { 201 {
160 free (mfs->ptr); 202 free (mfs->ptr);
161 mfs->ptr = NULL; 203 mfs->ptr = NULL;
204 mfs->capacity = 0;
162 mfs->size = 0; 205 mfs->size = 0;
163 } 206 }
164 stream_set_flags (stream, flags |MU_STREAM_NO_CHECK); 207 }
165 return 0; 208 else
209 status = ENOMEM;
210 }
211 else
212 status = EIO;
213 }
214 return status;
166 } 215 }
167 216
168 int 217 int
......
...@@ -60,8 +60,7 @@ _stream_memory_read (stream_t stream, void *optr, size_t osize, ...@@ -60,8 +60,7 @@ _stream_memory_read (stream_t stream, void *optr, size_t osize,
60 mu_refcount_lock (mem->refcount); 60 mu_refcount_lock (mem->refcount);
61 if (mem->ptr != NULL && (offset < (off_t)mem->size)) 61 if (mem->ptr != NULL && (offset < (off_t)mem->size))
62 { 62 {
63 n = ((offset + osize) > mem->size) ? 63 n = ((offset + osize) > mem->size) ? mem->size - offset : osize;
64 mem->size - offset : osize;
65 memcpy (optr, mem->ptr + offset, n); 64 memcpy (optr, mem->ptr + offset, n);
66 } 65 }
67 mu_refcount_unlock (mem->refcount); 66 mu_refcount_unlock (mem->refcount);
...@@ -130,6 +129,7 @@ _stream_memory_truncate (stream_t stream, off_t len) ...@@ -130,6 +129,7 @@ _stream_memory_truncate (stream_t stream, off_t len)
130 mu_refcount_lock (mem->refcount); 129 mu_refcount_lock (mem->refcount);
131 if (len == 0) 130 if (len == 0)
132 { 131 {
132 if (mem->ptr)
133 free (mem->ptr); 133 free (mem->ptr);
134 mem->ptr = NULL; 134 mem->ptr = NULL;
135 } 135 }
......