Commit 90af346d 90af346ddc4f730f2dd8b26fda528750af006b76 by Sergey Poznyakoff

attachment.c: redesign/simplify using the new API.

* libmailutils/mime/attachment.c (BUF_SIZE): Remove.
(_mu_mime_io_buffer)<buf, bufsize>: Remove members.
(MSG_HDR): Remove.
(mu_message_create_attachment): Use mu_asprintf instead of
manually crafting the string.
(mu_mime_io_buffer_set_size)
(mu_mime_io_buffer_get_size): Remove.
(mu_message_save_attachment)
(mu_message_encapsulate)
(mu_message_unencapsulate): Use mu_header_sget to avoid
unnecessary memory allocations.
Use mu_stream_copy instead of (ineffective) loops.

* include/mailutils/message.h (mu_mime_io_buffer_set_size)
(mu_mime_io_buffer_get_size): Remove prototypes.
* include/mailutils/header.h (MU_HEADER_RESENT_SENDER)
(MU_HEADER_CONTENT_TRANSFER_ENCODING)
(MU_HEADER_DELIVERY_DATE)
(MU_HEADER_ENVELOPE_TO): Normalize spelling.
1 parent 64b00582
...@@ -35,7 +35,7 @@ extern "C" { ...@@ -35,7 +35,7 @@ extern "C" {
35 #define MU_HEADER_RESENT_FROM "Resent-From" 35 #define MU_HEADER_RESENT_FROM "Resent-From"
36 #define MU_HEADER_SUBJECT "Subject" 36 #define MU_HEADER_SUBJECT "Subject"
37 #define MU_HEADER_SENDER "Sender" 37 #define MU_HEADER_SENDER "Sender"
38 #define MU_HEADER_RESENT_SENDER "Resent-SENDER" 38 #define MU_HEADER_RESENT_SENDER "Resent-Sender"
39 #define MU_HEADER_TO "To" 39 #define MU_HEADER_TO "To"
40 #define MU_HEADER_RESENT_TO "Resent-To" 40 #define MU_HEADER_RESENT_TO "Resent-To"
41 #define MU_HEADER_CC "Cc" 41 #define MU_HEADER_CC "Cc"
...@@ -54,7 +54,7 @@ extern "C" { ...@@ -54,7 +54,7 @@ extern "C" {
54 #define MU_HEADER_STATUS "Status" 54 #define MU_HEADER_STATUS "Status"
55 #define MU_HEADER_CONTENT_LENGTH "Content-Length" 55 #define MU_HEADER_CONTENT_LENGTH "Content-Length"
56 #define MU_HEADER_CONTENT_LANGUAGE "Content-Language" 56 #define MU_HEADER_CONTENT_LANGUAGE "Content-Language"
57 #define MU_HEADER_CONTENT_TRANSFER_ENCODING "Content-transfer-encoding" 57 #define MU_HEADER_CONTENT_TRANSFER_ENCODING "Content-Transfer-Encoding"
58 #define MU_HEADER_CONTENT_ID "Content-ID" 58 #define MU_HEADER_CONTENT_ID "Content-ID"
59 #define MU_HEADER_CONTENT_TYPE "Content-Type" 59 #define MU_HEADER_CONTENT_TYPE "Content-Type"
60 #define MU_HEADER_CONTENT_DESCRIPTION "Content-Description" 60 #define MU_HEADER_CONTENT_DESCRIPTION "Content-Description"
...@@ -68,8 +68,8 @@ extern "C" { ...@@ -68,8 +68,8 @@ extern "C" {
68 #define MU_HEADER_ENV_SENDER "X-Envelope-Sender" 68 #define MU_HEADER_ENV_SENDER "X-Envelope-Sender"
69 #define MU_HEADER_ENV_DATE "X-Envelope-Date" 69 #define MU_HEADER_ENV_DATE "X-Envelope-Date"
70 #define MU_HEADER_FCC "Fcc" 70 #define MU_HEADER_FCC "Fcc"
71 #define MU_HEADER_DELIVERY_DATE "Delivery-date" 71 #define MU_HEADER_DELIVERY_DATE "Delivery-Date"
72 #define MU_HEADER_ENVELOPE_TO "Envelope-to" 72 #define MU_HEADER_ENVELOPE_TO "Envelope-To"
73 #define MU_HEADER_X_EXPIRE_TIMESTAMP "X-Expire-Timestamp" 73 #define MU_HEADER_X_EXPIRE_TIMESTAMP "X-Expire-Timestamp"
74 74
75 #define MU_HEADER_REPLACE 0x01 75 #define MU_HEADER_REPLACE 0x01
......
...@@ -148,9 +148,6 @@ extern int mu_message_unencapsulate (mu_message_t msg, mu_message_t *newmsg, ...@@ -148,9 +148,6 @@ extern int mu_message_unencapsulate (mu_message_t msg, mu_message_t *newmsg,
148 extern int mu_mime_io_buffer_create (mu_mime_io_buffer_t *pinfo); 148 extern int mu_mime_io_buffer_create (mu_mime_io_buffer_t *pinfo);
149 extern void mu_mime_io_buffer_destroy (mu_mime_io_buffer_t *pinfo); 149 extern void mu_mime_io_buffer_destroy (mu_mime_io_buffer_t *pinfo);
150 150
151 extern void mu_mime_io_buffer_set_size (mu_mime_io_buffer_t info, size_t size);
152 extern void mu_mime_io_buffer_get_size (mu_mime_io_buffer_t info,
153 size_t *psize);
154 extern int mu_mime_io_buffer_set_charset (mu_mime_io_buffer_t info, 151 extern int mu_mime_io_buffer_set_charset (mu_mime_io_buffer_t info,
155 const char *charset); 152 const char *charset);
156 extern void mu_mime_io_buffer_sget_charset (mu_mime_io_buffer_t info, 153 extern void mu_mime_io_buffer_sget_charset (mu_mime_io_buffer_t info,
......
...@@ -43,14 +43,11 @@ ...@@ -43,14 +43,11 @@
43 #include <mailutils/stream.h> 43 #include <mailutils/stream.h>
44 #include <mailutils/errno.h> 44 #include <mailutils/errno.h>
45 #include <mailutils/util.h> 45 #include <mailutils/util.h>
46 46 #include <mailutils/io.h>
47 #define BUF_SIZE 2048
48 47
49 struct _mu_mime_io_buffer 48 struct _mu_mime_io_buffer
50 { 49 {
51 unsigned int refcnt; 50 unsigned int refcnt;
52 char *buf;
53 size_t bufsize;
54 char *charset; 51 char *charset;
55 mu_header_t hdr; 52 mu_header_t hdr;
56 mu_message_t msg; 53 mu_message_t msg;
...@@ -58,8 +55,6 @@ struct _mu_mime_io_buffer ...@@ -58,8 +55,6 @@ struct _mu_mime_io_buffer
58 mu_stream_t fstream; /* output file stream for saving attachment */ 55 mu_stream_t fstream; /* output file stream for saving attachment */
59 }; 56 };
60 57
61 #define MSG_HDR "Content-Type: %s; name=%s\nContent-Transfer-Encoding: %s\nContent-Disposition: attachment; filename=%s\n\n"
62
63 int 58 int
64 mu_message_create_attachment (const char *content_type, const char *encoding, 59 mu_message_create_attachment (const char *content_type, const char *encoding,
65 const char *filename, mu_message_t *newmsg) 60 const char *filename, mu_message_t *newmsg)
...@@ -88,23 +83,21 @@ mu_message_create_attachment (const char *content_type, const char *encoding, ...@@ -88,23 +83,21 @@ mu_message_create_attachment (const char *content_type, const char *encoding,
88 name++; 83 name++;
89 else 84 else
90 name = fname; 85 name = fname;
91 if ((header = 86 ret = mu_asprintf (&header,
92 malloc (strlen (MSG_HDR) + strlen (content_type) + 87 "Content-Type: %s; name=%s\n"
93 strlen (name) * 2 + strlen (encoding) + 1)) == NULL) 88 "Content-Transfer-Encoding: %s\n"
94 ret = ENOMEM; 89 "Content-Disposition: attachment; filename=%s\n\n",
95 else 90 content_type, name, encoding, name);
91 if (ret)
96 { 92 {
97 sprintf (header, MSG_HDR, content_type, name, encoding, name); 93 if ((ret = mu_header_create (&hdr, header,
98 if ((ret = mu_header_create (&hdr, header, strlen (header))) 94 strlen (header))) == 0)
99 == 0)
100 { 95 {
101 mu_message_get_body (*newmsg, &body); 96 mu_message_get_body (*newmsg, &body);
102 if ((ret = 97 if ((ret = mu_file_stream_create (&fstream, filename,
103 mu_file_stream_create (&fstream, filename,
104 MU_STREAM_READ)) == 0) 98 MU_STREAM_READ)) == 0)
105 { 99 {
106 if ((ret = 100 if ((ret = mu_filter_create (&tstream, fstream, encoding,
107 mu_filter_create (&tstream, fstream, encoding,
108 MU_FILTER_ENCODE, 101 MU_FILTER_ENCODE,
109 MU_STREAM_READ)) == 0) 102 MU_STREAM_READ)) == 0)
110 { 103 {
...@@ -112,11 +105,12 @@ mu_message_create_attachment (const char *content_type, const char *encoding, ...@@ -112,11 +105,12 @@ mu_message_create_attachment (const char *content_type, const char *encoding,
112 mu_message_set_header (*newmsg, hdr, NULL); 105 mu_message_set_header (*newmsg, hdr, NULL);
113 } 106 }
114 } 107 }
115 }
116 free (header); 108 free (header);
117 } 109 }
118 } 110 }
119 } 111 }
112 }
113
120 if (ret) 114 if (ret)
121 { 115 {
122 if (*newmsg) 116 if (*newmsg)
...@@ -139,23 +133,10 @@ mu_mime_io_buffer_create (mu_mime_io_buffer_t *pinfo) ...@@ -139,23 +133,10 @@ mu_mime_io_buffer_create (mu_mime_io_buffer_t *pinfo)
139 if ((info = calloc (1, sizeof (*info))) == NULL) 133 if ((info = calloc (1, sizeof (*info))) == NULL)
140 return ENOMEM; 134 return ENOMEM;
141 info->refcnt = 1; 135 info->refcnt = 1;
142 info->bufsize = BUF_SIZE;
143 *pinfo = info; 136 *pinfo = info;
144 return 0; 137 return 0;
145 } 138 }
146 139
147 void
148 mu_mime_io_buffer_set_size (mu_mime_io_buffer_t info, size_t size)
149 {
150 info->bufsize = size;
151 }
152
153 void
154 mu_mime_io_buffer_get_size (mu_mime_io_buffer_t info, size_t *psize)
155 {
156 *psize = info->bufsize;
157 }
158
159 int 140 int
160 mu_mime_io_buffer_set_charset (mu_mime_io_buffer_t info, const char *charset) 141 mu_mime_io_buffer_set_charset (mu_mime_io_buffer_t info, const char *charset)
161 { 142 {
...@@ -189,7 +170,6 @@ mu_mime_io_buffer_destroy (mu_mime_io_buffer_t *pinfo) ...@@ -189,7 +170,6 @@ mu_mime_io_buffer_destroy (mu_mime_io_buffer_t *pinfo)
189 { 170 {
190 mu_mime_io_buffer_t info = *pinfo; 171 mu_mime_io_buffer_t info = *pinfo;
191 free (info->charset); 172 free (info->charset);
192 free (info->buf);
193 free (info); 173 free (info);
194 *pinfo = NULL; 174 *pinfo = NULL;
195 } 175 }
...@@ -212,7 +192,6 @@ _attachment_free (struct _mu_mime_io_buffer *info, int free_message) ...@@ -212,7 +192,6 @@ _attachment_free (struct _mu_mime_io_buffer *info, int free_message)
212 if (--info->refcnt == 0) 192 if (--info->refcnt == 0)
213 { 193 {
214 free (info->charset); 194 free (info->charset);
215 free (info->buf);
216 free (info); 195 free (info);
217 } 196 }
218 } 197 }
...@@ -245,11 +224,6 @@ _attachment_setup (mu_mime_io_buffer_t *pinfo, mu_message_t msg, ...@@ -245,11 +224,6 @@ _attachment_setup (mu_mime_io_buffer_t *pinfo, mu_message_t msg,
245 return ret; 224 return ret;
246 } 225 }
247 226
248 if (!info->buf && ((info->buf = malloc (info->bufsize)) == NULL))
249 {
250 _attachment_free (info, 0);
251 return ENOMEM;
252 }
253 info->msg = msg; 227 info->msg = msg;
254 *pinfo = info; 228 *pinfo = info;
255 return 0; 229 return 0;
...@@ -261,8 +235,6 @@ mu_message_save_attachment (mu_message_t msg, const char *filename, ...@@ -261,8 +235,6 @@ mu_message_save_attachment (mu_message_t msg, const char *filename,
261 { 235 {
262 mu_stream_t istream; 236 mu_stream_t istream;
263 int ret; 237 int ret;
264 size_t size;
265 size_t nbytes;
266 mu_header_t hdr; 238 mu_header_t hdr;
267 const char *fname = NULL; 239 const char *fname = NULL;
268 char *partname = NULL; 240 char *partname = NULL;
...@@ -285,44 +257,22 @@ mu_message_save_attachment (mu_message_t msg, const char *filename, ...@@ -285,44 +257,22 @@ mu_message_save_attachment (mu_message_t msg, const char *filename,
285 else 257 else
286 fname = filename; 258 fname = filename;
287 if (fname 259 if (fname
288 && (ret = 260 && (ret = mu_file_stream_create (&info->fstream, fname,
289 mu_file_stream_create (&info->fstream, fname,
290 MU_STREAM_WRITE | MU_STREAM_CREAT)) == 0) 261 MU_STREAM_WRITE | MU_STREAM_CREAT)) == 0)
291 { 262 {
292 char *content_encoding; 263 const char *content_encoding;
293 char *content_encoding_mem = NULL;
294 264
295 mu_header_get_value (hdr, "Content-Transfer-Encoding", NULL, 0, 265 if (mu_header_sget_value (hdr, MU_HEADER_CONTENT_TRANSFER_ENCODING,
296 &size); 266 &content_encoding))
297 if (size)
298 {
299 content_encoding_mem = malloc (size + 1);
300 if (content_encoding_mem == NULL)
301 ret = ENOMEM;
302 content_encoding = content_encoding_mem;
303 mu_header_get_value (hdr, "Content-Transfer-Encoding",
304 content_encoding, size + 1, 0);
305 }
306 else
307 content_encoding = "7bit"; 267 content_encoding = "7bit";
308 ret = 268 ret = mu_filter_create (&info->stream, istream, content_encoding,
309 mu_filter_create (&info->stream, istream, content_encoding,
310 MU_FILTER_DECODE, 269 MU_FILTER_DECODE,
311 MU_STREAM_READ); 270 MU_STREAM_READ);
312 free (content_encoding_mem);
313 } 271 }
314 } 272 }
315 if (info->stream && istream) 273 if (info->stream && istream)
316 { 274 ret = mu_stream_copy (info->fstream, info->stream, 0, NULL);
317 while (((ret = 275
318 mu_stream_read (info->stream, info->buf, BUF_SIZE,
319 &nbytes)) == 0 && nbytes))
320 {
321 if ((ret =
322 mu_stream_write (info->fstream, info->buf, nbytes, NULL)) != 0)
323 break;
324 }
325 }
326 if (ret != EAGAIN && info) 276 if (ret != EAGAIN && info)
327 { 277 {
328 mu_stream_close (info->fstream); 278 mu_stream_close (info->fstream);
...@@ -345,9 +295,7 @@ mu_message_encapsulate (mu_message_t msg, mu_message_t *newmsg, ...@@ -345,9 +295,7 @@ mu_message_encapsulate (mu_message_t msg, mu_message_t *newmsg,
345 mu_mime_io_buffer_t info) 295 mu_mime_io_buffer_t info)
346 { 296 {
347 mu_stream_t istream, ostream; 297 mu_stream_t istream, ostream;
348 const char *header;
349 int ret = 0; 298 int ret = 0;
350 size_t nbytes;
351 mu_message_t tmsg = NULL; 299 mu_message_t tmsg = NULL;
352 300
353 if (newmsg == NULL) 301 if (newmsg == NULL)
...@@ -361,11 +309,13 @@ mu_message_encapsulate (mu_message_t msg, mu_message_t *newmsg, ...@@ -361,11 +309,13 @@ mu_message_encapsulate (mu_message_t msg, mu_message_t *newmsg,
361 if (ret) 309 if (ret)
362 return ret; 310 return ret;
363 msg = tmsg; 311 msg = tmsg;
364 header = 312 #define MSG822_HEADER "Content-Type: message/rfc822\n" \
365 "Content-Type: message/rfc822\nContent-Transfer-Encoding: 7bit\n\n"; 313 "Content-Transfer-Encoding: 7bit\n\n"
366 if ((ret = 314 if ((ret = mu_header_create (&hdr,
367 mu_header_create (&hdr, header, strlen (header))) == 0) 315 MSG822_HEADER,
316 sizeof (MSG822_HEADER) - 1)) == 0)
368 ret = mu_message_set_header (msg, hdr, NULL); 317 ret = mu_message_set_header (msg, hdr, NULL);
318 #undef MSG822_HEADER
369 if (ret) 319 if (ret)
370 { 320 {
371 mu_message_destroy (&msg, NULL); 321 mu_message_destroy (&msg, NULL);
...@@ -382,13 +332,7 @@ mu_message_encapsulate (mu_message_t msg, mu_message_t *newmsg, ...@@ -382,13 +332,7 @@ mu_message_encapsulate (mu_message_t msg, mu_message_t *newmsg,
382 if (ret == 0 && (ret = mu_message_get_streamref (msg, &istream)) == 0) 332 if (ret == 0 && (ret = mu_message_get_streamref (msg, &istream)) == 0)
383 { 333 {
384 mu_stream_seek (istream, 0, MU_SEEK_SET, NULL); 334 mu_stream_seek (istream, 0, MU_SEEK_SET, NULL);
385 while (((ret = mu_stream_read (istream, info->buf, BUF_SIZE, 335 ret = mu_stream_copy (ostream, istream, 0, NULL);
386 &nbytes)) == 0 && nbytes))
387 {
388 if ((ret =
389 mu_stream_write (ostream, info->buf, nbytes, NULL)) != 0)
390 break;
391 }
392 mu_stream_destroy (&istream); 336 mu_stream_destroy (&istream);
393 } 337 }
394 if (ret == 0) 338 if (ret == 0)
...@@ -404,7 +348,6 @@ int ...@@ -404,7 +348,6 @@ int
404 mu_message_unencapsulate (mu_message_t msg, mu_message_t *newmsg, 348 mu_message_unencapsulate (mu_message_t msg, mu_message_t *newmsg,
405 mu_mime_io_buffer_t info) 349 mu_mime_io_buffer_t info)
406 { 350 {
407 size_t size, nbytes;
408 int ret = 0; 351 int ret = 0;
409 mu_header_t hdr; 352 mu_header_t hdr;
410 mu_stream_t istream, ostream; 353 mu_stream_t istream, ostream;
...@@ -417,21 +360,10 @@ mu_message_unencapsulate (mu_message_t msg, mu_message_t *newmsg, ...@@ -417,21 +360,10 @@ mu_message_unencapsulate (mu_message_t msg, mu_message_t *newmsg,
417 if (info == NULL /* FIXME: not needed? */ 360 if (info == NULL /* FIXME: not needed? */
418 && (ret = mu_message_get_header (msg, &hdr)) == 0) 361 && (ret = mu_message_get_header (msg, &hdr)) == 0)
419 { 362 {
420 mu_header_get_value (hdr, "Content-Type", NULL, 0, &size); 363 const char *s;
421 if (size) 364 if (!(mu_header_sget_value (hdr, MU_HEADER_CONTENT_TYPE, &s) == 0 &&
422 { 365 mu_c_strncasecmp (s, MESSAGE_RFC822_STR,
423 char *content_type; 366 sizeof (MESSAGE_RFC822_STR) - 1) == 0))
424 if ((content_type = malloc (size + 1)) == NULL)
425 return ENOMEM;
426 mu_header_get_value (hdr, "Content-Type", content_type, size + 1,
427 0);
428 ret = mu_c_strncasecmp (content_type, MESSAGE_RFC822_STR,
429 sizeof (MESSAGE_RFC822_STR) - 1);
430 free (content_type);
431 if (ret != 0)
432 return EINVAL;
433 }
434 else
435 return EINVAL; 367 return EINVAL;
436 } 368 }
437 if ((ret = _attachment_setup (&info, msg, &istream)) != 0) 369 if ((ret = _attachment_setup (&info, msg, &istream)) != 0)
...@@ -442,14 +374,7 @@ mu_message_unencapsulate (mu_message_t msg, mu_message_t *newmsg, ...@@ -442,14 +374,7 @@ mu_message_unencapsulate (mu_message_t msg, mu_message_t *newmsg,
442 { 374 {
443 mu_message_get_streamref (info->msg, &ostream); 375 mu_message_get_streamref (info->msg, &ostream);
444 mu_stream_seek (ostream, 0, MU_SEEK_SET, NULL); 376 mu_stream_seek (ostream, 0, MU_SEEK_SET, NULL);
445 while (((ret = 377 ret = mu_stream_copy (ostream, istream, 0, NULL);
446 mu_stream_read (istream, info->buf, BUF_SIZE,
447 &nbytes)) == 0 && nbytes))
448 {
449 if ((ret =
450 mu_stream_write (ostream, info->buf, nbytes, NULL)) != 0)
451 break;
452 }
453 mu_stream_destroy (&ostream); 378 mu_stream_destroy (&ostream);
454 } 379 }
455 if (ret == 0) 380 if (ret == 0)
......