Commit c07fc42c c07fc42cdc414e0281b4453d31a0855af07db5a4 by Sergey Poznyakoff

Improve attachment creation API.

* include/mailutils/message.h (mu_attachment_create)
(mu_attachment_copy_from_stream)
(mu_attachment_copy_from_file): New functions.
* libmailutils/mime/attachment.c: Likewise.
(mu_message_create_attachment): Rewrite using the three functions above.
1 parent 7a77cc6f
...@@ -211,10 +211,21 @@ extern int mu_message_set_bodystructure (mu_message_t msg, ...@@ -211,10 +211,21 @@ extern int mu_message_set_bodystructure (mu_message_t msg,
211 void *owner); 211 void *owner);
212 212
213 /* misc functions */ 213 /* misc functions */
214 extern int mu_attachment_create (mu_message_t *newmsg,
215 const char *content_type,
216 const char *encoding,
217 const char *name, const char *filename);
218 extern int mu_attachment_copy_from_stream (mu_message_t att,
219 mu_stream_t stream,
220 char const *encoding);
221 extern int mu_attachment_copy_from_file (mu_message_t att,
222 char const *filename,
223 char const *encoding);
214 extern int mu_message_create_attachment (const char *content_type, 224 extern int mu_message_create_attachment (const char *content_type,
215 const char *encoding, 225 const char *encoding,
216 const char *filename, 226 const char *filename,
217 mu_message_t *newmsg); 227 mu_message_t *newmsg);
228
218 extern int mu_message_save_attachment (mu_message_t msg, 229 extern int mu_message_save_attachment (mu_message_t msg,
219 const char *filename, 230 const char *filename,
220 mu_mime_io_buffer_t buf); 231 mu_mime_io_buffer_t buf);
......
...@@ -55,79 +55,179 @@ struct _mu_mime_io_buffer ...@@ -55,79 +55,179 @@ struct _mu_mime_io_buffer
55 mu_stream_t fstream; /* output file stream for saving attachment */ 55 mu_stream_t fstream; /* output file stream for saving attachment */
56 }; 56 };
57 57
58 int 58 static int
59 mu_message_create_attachment (const char *content_type, const char *encoding, 59 at_hdr (mu_header_t hdr, const char *content_type, const char *encoding,
60 const char *filename, mu_message_t *newmsg) 60 const char *name, const char *filename)
61 { 61 {
62 mu_header_t hdr; 62 int rc;
63 mu_body_t body; 63 char *val, *str;
64 mu_stream_t fstream = NULL, tstream = NULL;
65 char *header = NULL, *name = NULL, *fname = NULL;
66 int ret;
67
68 if (newmsg == NULL)
69 return MU_ERR_OUT_PTR_NULL;
70 if (filename == NULL)
71 return EINVAL;
72 64
73 if ((ret = mu_message_create (newmsg, NULL)) == 0) 65 if (!name)
74 { 66 {
75 if (content_type == NULL) 67 if (filename)
76 content_type = "text/plain";
77 if (encoding == NULL)
78 encoding = "7bit";
79 if ((fname = strdup (filename)) != NULL)
80 { 68 {
81 name = strrchr (fname, '/'); 69 name = strrchr (filename, '/');
82 if (name) 70 if (name)
83 name++; 71 name++;
84 else 72 else
85 name = fname; 73 name = filename;
86 ret = mu_asprintf (&header,
87 "Content-Type: %s; name=%s\n"
88 "Content-Transfer-Encoding: %s\n"
89 "Content-Disposition: attachment; filename=%s\n\n",
90 content_type, name, encoding, name);
91 if (ret == 0)
92 {
93 if ((ret = mu_header_create (&hdr, header,
94 strlen (header))) == 0)
95 {
96 mu_stream_t bstr;
97 mu_message_get_body (*newmsg, &body);
98 mu_body_get_streamref (body, &bstr);
99
100 if ((ret = mu_file_stream_create (&fstream, filename,
101 MU_STREAM_READ)) == 0)
102 {
103 if ((ret = mu_filter_create (&tstream, fstream, encoding,
104 MU_FILTER_ENCODE,
105 MU_STREAM_READ)) == 0)
106 {
107 mu_stream_copy (bstr, tstream, 0, NULL);
108 mu_stream_unref (tstream);
109 mu_message_set_header (*newmsg, hdr, NULL);
110 }
111 }
112 mu_stream_unref (bstr);
113 free (header);
114 }
115 }
116 } 74 }
117 } 75 }
76
77 if (name)
78 {
79 rc = mu_c_str_escape (name, "\\\"", NULL, &str);
80 if (rc)
81 return rc;
82 rc = mu_asprintf (&val, "%s; name=\"%s\"", content_type, str);
83 free (str);
84 if (rc)
85 return rc;
86 rc = mu_header_append (hdr, MU_HEADER_CONTENT_TYPE, val);
87 free (val);
88 }
89 else
90 rc = mu_header_append (hdr, MU_HEADER_CONTENT_TYPE, content_type);
91
92 if (rc)
93 return rc;
94
95 if (filename)
96 {
97 rc = mu_c_str_escape (filename, "\\\"", NULL, &str);
98 if (rc)
99 return rc;
100 rc = mu_asprintf (&val, "%s; filename=\"%s\"", "attachment", str);
101 free (str);
102 if (rc)
103 return rc;
104 rc = mu_header_append (hdr, MU_HEADER_CONTENT_DISPOSITION, val);
105 free (val);
106 }
107 else
108 rc = mu_header_append (hdr, MU_HEADER_CONTENT_DISPOSITION, "attachment");
109 if (rc)
110 return rc;
111 return mu_header_append (hdr, MU_HEADER_CONTENT_TRANSFER_ENCODING, encoding);
112 }
113
114 /* Create in *NEWMSG an empty attachment of given CONTENT_TYPE and ENCODING.
115 NAME, if not NULL, supplies the name of the attachment.
116 FILENAME, if not NULL, gives the file name.
117 */
118 int
119 mu_attachment_create (mu_message_t *newmsg,
120 const char *content_type, const char *encoding,
121 const char *name,
122 const char *filename)
123 {
124 int rc;
125 mu_header_t hdr;
118 126
119 if (ret) 127 if (newmsg == NULL)
128 return MU_ERR_OUT_PTR_NULL;
129
130 rc = mu_message_create (newmsg, NULL);
131 if (rc)
132 return rc;
133
134 rc = mu_header_create (&hdr, NULL, 0);
135 if (rc)
120 { 136 {
121 if (*newmsg) 137 mu_message_destroy (newmsg, NULL);
122 mu_message_destroy (newmsg, NULL); 138 return rc;
123 if (hdr)
124 mu_header_destroy (&hdr);
125 if (fstream)
126 mu_stream_destroy (&fstream);
127 if (fname)
128 free (fname);
129 } 139 }
130 return ret; 140 mu_message_set_header (*newmsg, hdr, NULL);
141
142 rc = at_hdr (hdr, content_type, encoding, name, filename);
143
144 if (rc)
145 mu_message_destroy (newmsg, NULL);
146
147 return rc;
148 }
149
150 /* ATT is an attachment created by a previous call to mu_attachment_create().
151
152 Fills in the attachment body with the data from STREAM using the specified
153 ENCODING.
154 */
155 int
156 mu_attachment_copy_from_stream (mu_message_t att, mu_stream_t stream,
157 char const *encoding)
158 {
159 mu_body_t body;
160 mu_stream_t bstr;
161 mu_stream_t tstream;
162 int rc;
163
164 mu_message_get_body (att, &body);
165 rc = mu_body_get_streamref (body, &bstr);
166 if (rc)
167 return rc;
168
169 rc = mu_filter_create (&tstream, stream, encoding, MU_FILTER_ENCODE,
170 MU_STREAM_READ);
171 if (rc == 0)
172 {
173 rc = mu_stream_copy (bstr, tstream, 0, NULL);
174 mu_stream_unref (tstream);
175 }
176 mu_stream_unref (bstr);
177 return rc;
178 }
179
180 /* ATT is an attachment created by a previous call to mu_attachment_create().
181
182 Fills in the attachment body with the data from FILENAME using the specified
183 ENCODING.
184 */
185 int
186 mu_attachment_copy_from_file (mu_message_t att, char const *filename,
187 char const *encoding)
188 {
189 mu_stream_t stream;
190 int rc;
191
192 rc = mu_file_stream_create (&stream, filename, MU_STREAM_READ);
193 if (rc == 0)
194 {
195 rc = mu_attachment_copy_from_stream (att, stream, encoding);
196 mu_stream_unref (stream);
197 }
198 return rc;
199 }
200
201 int
202 mu_message_create_attachment (const char *content_type, const char *encoding,
203 const char *filename, mu_message_t *newmsg)
204 {
205 int rc;
206 char const *name;
207 mu_message_t att;
208
209 if (content_type == NULL)
210 content_type = "text/plain";
211 if (encoding == NULL)
212 encoding = "7bit";
213
214 name = strrchr (filename, '/');
215 if (name)
216 name++;
217 else
218 name = filename;
219
220 rc = mu_attachment_create (&att, content_type, encoding, name, filename);
221 if (rc == 0)
222 {
223 rc = mu_attachment_copy_from_file (att, filename, encoding);
224 if (rc)
225 mu_message_destroy (&att, NULL);
226 }
227 if (rc == 0)
228 *newmsg = att;
229
230 return rc;
131 } 231 }
132 232
133 int 233 int
......