Minor change.
Showing
1 changed file
with
243 additions
and
2 deletions
... | @@ -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 | } | ... | ... |
-
Please register or sign in to post a comment