Commit 6760ea1e 6760ea1ebc3f2f310e2942d61b6c19b367b767f3 by Sergey Poznyakoff

Minor change.

1 parent af7a57cd
...@@ -16,13 +16,26 @@ ...@@ -16,13 +16,26 @@
16 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ 16 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
17 17
18 /* This file implements an MH draftfile stream: a read-only stream used 18 /* This file implements an MH draftfile stream: a read-only stream used
19 to transparently pass MH draftfiles to the mailers. The only difference 19 to transparently pass MH draftfiles to mailers. The only difference
20 between the usual RFC822 and MH draft is that the latter allows to use 20 between the usual RFC822 and MH draft is that the latter allows to use
21 a string of dashes to separate the headers from the body. */ 21 a string of dashes to separate the headers from the body. */
22 22
23 #include <mh.h> 23 #include <mh.h>
24 #include <mailutils/stream.h> 24 #include <mailutils/stream.h>
25 25
26 static int
27 _mh_delim (char *str)
28 {
29 if (str[0] == '-')
30 {
31 for (; *str == '-'; str++)
32 ;
33 for (; *str == ' ' || *str == '\t'; str++)
34 ;
35 }
36 return str[0] == '\n';
37 }
38
26 struct _mhdraft_stream { 39 struct _mhdraft_stream {
27 stream_t stream; /* Actual stream */ 40 stream_t stream; /* Actual stream */
28 size_t mark_offset; /* Offset of the header separator */ 41 size_t mark_offset; /* Offset of the header separator */
...@@ -58,7 +71,7 @@ _mhdraft_readline (stream_t stream, char *optr, size_t osize, ...@@ -58,7 +71,7 @@ _mhdraft_readline (stream_t stream, char *optr, size_t osize,
58 { 71 {
59 int rc; 72 int rc;
60 size_t n; 73 size_t n;
61 size_t rdsize = s->mark_offset - offset; 74 size_t rdsize = s->mark_offset - offset + 1;
62 rc = stream_readline (s->stream, optr, rdsize, offset, &n); 75 rc = stream_readline (s->stream, optr, rdsize, offset, &n);
63 if (rc == 0) 76 if (rc == 0)
64 { 77 {
...@@ -160,3 +173,231 @@ mhdraft_stream_create (stream_t *stream, stream_t src, int flags) ...@@ -160,3 +173,231 @@ mhdraft_stream_create (stream_t *stream, stream_t src, int flags)
160 } 173 }
161 174
162 175
176
177 /* *************************** MH draft message **************************** */
178
179 char *
180 skipws (char *p, size_t off)
181 {
182 int len;
183 for (p += off; *p && isspace (*p); p++)
184 ;
185 len = strlen (p);
186 if (len > 0 && p[len-1] == '\n')
187 p[len-1] = 0;
188 return p;
189 }
190
191 struct _mhdraft_message
192 {
193 char *from;
194 char *date;
195 size_t body_start;
196 size_t body_end;
197 };
198
199 static int
200 restore_envelope (stream_t str, struct _mhdraft_message **pmenv)
201 {
202 size_t offset = 0;
203 char *from = NULL;
204 char *env_from = NULL;
205 char *env_date = NULL;
206 int rc;
207 char buffer[80];
208 size_t len;
209 size_t body_start, body_end;
210
211 while ((rc = stream_readline (str, buffer, sizeof buffer, offset, &len)) == 0
212 && len > 0)
213 {
214 if (buffer[0] == '\n')
215 break;
216 buffer[len] = 0;
217 offset += len;
218 if (strncasecmp (buffer, MU_HEADER_FROM,
219 sizeof (MU_HEADER_FROM) - 1) == 0)
220 from = strdup (skipws (buffer, sizeof (MU_HEADER_FROM)));
221 else if (strncasecmp (buffer, MU_HEADER_ENV_SENDER,
222 sizeof (MU_HEADER_ENV_SENDER) - 1) == 0)
223 env_from = strdup (skipws (buffer, sizeof (MU_HEADER_ENV_SENDER)));
224 else if (strncasecmp (buffer, MU_HEADER_ENV_DATE,
225 sizeof (MU_HEADER_ENV_DATE) - 1) == 0)
226 env_date = strdup (skipws (buffer, sizeof (MU_HEADER_ENV_DATE)));
227 }
228
229 body_start = offset + 1;
230 stream_size (str, &body_end);
231
232 if (!env_from)
233 {
234 if (from)
235 {
236 address_t addr;
237
238 address_create (&addr, from);
239 if (!addr
240 || address_aget_email (addr, 1, &env_from))
241 env_from = strdup ("GNU-MH");
242 address_destroy (&addr);
243 }
244 else
245 env_from = strdup ("GNU-MH");
246 }
247
248 if (!env_date)
249 {
250 struct tm *tm;
251 time_t t;
252 char date[80];
253
254 time(&t);
255 tm = gmtime(&t);
256 strftime (date, sizeof (date), "%a %b %e %H:%M:%S %Y", tm);
257 env_date = strdup (date);
258 }
259
260 *pmenv = xmalloc (sizeof (**pmenv)
261 + strlen (env_from)
262 + strlen (env_date)
263 + 2);
264 (*pmenv)->from = (char*) (*pmenv + 1);
265 (*pmenv)->date = (char*) ((*pmenv)->from + strlen (env_from) + 1);
266
267 strcpy ((*pmenv)->from, env_from);
268 strcpy ((*pmenv)->date, env_date);
269
270 (*pmenv)->body_start = body_start;
271 (*pmenv)->body_end = body_end;
272
273 free (env_from);
274 free (env_date);
275 free (from);
276 return 0;
277 }
278
279 static int
280 _env_msg_date (envelope_t envelope, char *buf, size_t len, size_t *pnwrite)
281 {
282 message_t msg = envelope_get_owner (envelope);
283 struct _mhdraft_message *env = message_get_owner (msg);
284
285 if (!env || !env->date)
286 return EINVAL;
287 strncpy (buf, env->date, len);
288 buf[len-1] = 0;
289 return 0;
290 }
291
292 static int
293 _env_msg_sender (envelope_t envelope, char *buf, size_t len, size_t *pnwrite)
294 {
295 message_t msg = envelope_get_owner (envelope);
296 struct _mhdraft_message *env = message_get_owner (msg);
297
298 if (!env || !env->from)
299 return EINVAL;
300 strncpy (buf, env->from, len);
301 buf[len-1] = 0;
302 return 0;
303 }
304
305 static int
306 _body_size (body_t body, size_t *size)
307 {
308 message_t msg = body_get_owner (body);
309 struct _mhdraft_message *mp = message_get_owner (msg);
310
311 if (size)
312 *size = mp->body_end - mp->body_start;
313 return 0;
314 }
315
316 static int
317 _body_read (stream_t stream, char *optr, size_t osize,
318 off_t offset, size_t *nbytes)
319 {
320 body_t body = stream_get_owner (stream);
321 message_t msg = body_get_owner (body);
322 struct _mhdraft_message *mp = message_get_owner (msg);
323 stream_t str;
324
325 message_get_stream (msg, &str);
326 return stream_read (str, optr, osize, mp->body_start + offset, nbytes);
327 }
328
329 static int
330 _body_readline (stream_t stream, char *optr, size_t osize,
331 off_t offset, size_t *nbytes)
332 {
333 message_t msg = stream_get_owner (stream);
334 struct _mhdraft_message *mp = message_get_owner (msg);
335 stream_t str;
336
337 message_get_stream (msg, &str);
338 return stream_readline (str, optr, osize, mp->body_start + offset, nbytes);
339 }
340
341 static int
342 _body_stream_size (stream_t stream, off_t *psize)
343 {
344 message_t msg = stream_get_owner (stream);
345 struct _mhdraft_message *mp = message_get_owner (msg);
346
347 if (psize)
348 *psize = mp->body_end - mp->body_start;
349 return 0;
350 }
351
352 message_t
353 mh_stream_to_message (stream_t instream)
354 {
355 struct _mhdraft_message *mp;
356 envelope_t env;
357 message_t msg;
358 body_t body;
359 stream_t bstream;
360 stream_t draftstream;
361 int rc;
362
363 if ((rc = mhdraft_stream_create (&draftstream, instream, 0)))
364 {
365 mh_error(_("cannot create draft message stream: %s"),
366 mu_strerror (rc));
367 return NULL;
368 }
369
370 if ((rc = stream_open (draftstream)))
371 {
372 mh_error(_("cannot open draft message stream: %s"),
373 mu_strerror (rc));
374 stream_destroy (&draftstream, stream_get_owner (draftstream));
375 return NULL;
376 }
377
378 restore_envelope (draftstream, &mp);
379
380 if (message_create (&msg, mp))
381 return NULL;
382
383 message_set_stream (msg, draftstream, mp);
384
385 if (envelope_create (&env, msg))
386 return NULL;
387
388 envelope_set_date (env, _env_msg_date, msg);
389 envelope_set_sender (env, _env_msg_sender, msg);
390 message_set_envelope (msg, env, mp);
391
392 body_create (&body, msg);
393 stream_create (&bstream, MU_STREAM_RDWR | MU_STREAM_SEEKABLE, body);
394
395 stream_set_read (bstream, _body_read, body);
396 stream_set_readline (bstream, _body_readline, body);
397 stream_set_size (bstream, _body_stream_size, body);
398 body_set_stream (body, bstream, msg);
399 body_set_size (body, _body_size, msg);
400 message_set_body (msg, body, mp);
401
402 return msg;
403 }
......