commit-mailutils
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[SCM] GNU Mailutils branch, master, updated. release-2.2-636-gefa5130


From: Sergey Poznyakoff
Subject: [SCM] GNU Mailutils branch, master, updated. release-2.2-636-gefa5130
Date: Thu, 03 Jan 2013 16:29:35 +0000

This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "GNU Mailutils".

http://git.savannah.gnu.org/cgit/mailutils.git/commit/?id=efa513048a74fca2e3ab1b16cc927f8331347f75

The branch, master has been updated
       via  efa513048a74fca2e3ab1b16cc927f8331347f75 (commit)
      from  3a6ea349ae7b1a941acd6ec882e93ad5b3a27ca4 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit efa513048a74fca2e3ab1b16cc927f8331347f75
Author: Sergey Poznyakoff <address@hidden>
Date:   Thu Jan 3 18:04:28 2013 +0200

    Make sure modifications to a message or its parts become visible in the 
message stream.
    
    * include/mailutils/sys/body.h (_mu_body)<rawstream>: New member.
    * include/mailutils/sys/message.h (_mu_message)<rawstream>: New member.
    * libmailutils/mailbox/body.c: Rewrite. Return the specially crafted
    "body-stream" for user I/O operations. Writes to that stream trigger
    creation of a temporary stream (write-through mode) which will be used
    for subsequent I/O.
    * libmailutils/mailbox/msgbody.c (mu_message_get_body): Use msg->rawstream.
    * libmailutils/mailbox/msgheader.c (message_header_fill): Do not
    call mu_message_get_streamref, as that can result in endless recursion.
    Use msg->rawstream instead.
    * libmailutils/mailbox/msgref.c (_mu_message_free): Destroy both
    rawstream and outstream.
    * libmailutils/mailbox/msgstream.c (mu_message_set_stream): Set
    rawstream.
    (mu_message_get_stream): Create outstream as needed.
    (mu_message_get_streamref): If the message has been modified,
    create the outstream and return it to the caller. This way, the
    modifications become visible via the stream interface.
    * libmailutils/tests/Makefile.am: Add new testcases.
    * libmailutils/tests/testsuite.at: Likewise.
    * libmailutils/tests/modmesg.c: New file.
    * libmailutils/tests/modmesg00.at: New file.
    * libmailutils/tests/modmesg01.at: New file.
    * libmailutils/tests/modmesg02.at: New file.
    * libmailutils/tests/modmesg03.at: New file.
    * mh/mhn.c: Fix message reference counting.

-----------------------------------------------------------------------

Summary of changes:
 include/mailutils/sys/body.h                   |    1 +
 include/mailutils/sys/message.h                |    3 +-
 libmailutils/mailbox/body.c                    |  498 ++++++++++++++----------
 libmailutils/mailbox/msgbody.c                 |    7 +-
 libmailutils/mailbox/msgheader.c               |   12 +-
 libmailutils/mailbox/msgref.c                  |   30 +--
 libmailutils/mailbox/msgstream.c               |  104 ++++--
 libmailutils/tests/Makefile.am                 |    7 +-
 libmailutils/tests/modmesg.c                   |  103 +++++
 libmailutils/tests/{strout.at => modmesg00.at} |   21 +-
 libmailutils/tests/{strout.at => modmesg01.at} |   23 +-
 libmailutils/tests/{strerr.at => modmesg02.at} |   31 +-
 libmailutils/tests/{strerr.at => modmesg03.at} |   24 +-
 libmailutils/tests/testsuite.at                |    6 +
 mh/mhn.c                                       |    3 +-
 15 files changed, 542 insertions(+), 331 deletions(-)
 create mode 100644 libmailutils/tests/modmesg.c
 copy libmailutils/tests/{strout.at => modmesg00.at} (85%)
 copy libmailutils/tests/{strout.at => modmesg01.at} (81%)
 copy libmailutils/tests/{strerr.at => modmesg02.at} (78%)
 copy libmailutils/tests/{strerr.at => modmesg03.at} (78%)

diff --git a/include/mailutils/sys/body.h b/include/mailutils/sys/body.h
index 501bc83..651b614 100644
--- a/include/mailutils/sys/body.h
+++ b/include/mailutils/sys/body.h
@@ -33,6 +33,7 @@ struct _mu_body
 {
   void *owner;
   mu_stream_t stream;
+  mu_stream_t rawstream;
   mu_stream_t fstream;
   int flags;
 
diff --git a/include/mailutils/sys/message.h b/include/mailutils/sys/message.h
index d9d4c4a..df258c2 100644
--- a/include/mailutils/sys/message.h
+++ b/include/mailutils/sys/message.h
@@ -47,7 +47,8 @@ struct _mu_message
   mu_body_t body;
 
   int flags;
-  mu_stream_t stream;
+  mu_stream_t rawstream;
+  mu_stream_t outstream;
   mu_attribute_t attribute;
   mu_monitor_t monitor;
   mu_mime_t mime;
diff --git a/libmailutils/mailbox/body.c b/libmailutils/mailbox/body.c
index 24b9240..5abbc12 100644
--- a/libmailutils/mailbox/body.c
+++ b/libmailutils/mailbox/body.c
@@ -35,139 +35,296 @@
 #include <mailutils/sys/stream.h>
 #include <mailutils/sys/body.h>
 
-#define BODY_MODIFIED 0x10000
-
-static int _body_flush    (mu_stream_t);
-static int _body_read     (mu_stream_t, char *, size_t, size_t *);
-static int _body_truncate (mu_stream_t, mu_off_t);
-static int _body_size     (mu_stream_t, mu_off_t *);
-static int _body_write    (mu_stream_t, const char *, size_t, size_t *);
-static int _body_ioctl    (mu_stream_t, int, int, void *);
-static int _body_seek     (mu_stream_t, mu_off_t, mu_off_t *);
-static const char *_body_error_string (mu_stream_t, int);
-
-/* Our own defaults for the body.  */
-static int _body_get_size   (mu_body_t, size_t *);
-static int _body_get_lines  (mu_body_t, size_t *);
-static int _body_get_size0  (mu_stream_t, size_t *);
-static int _body_get_lines0 (mu_stream_t, size_t *);
+#define BODY_MODIFIED         0x10000
 
-int
-mu_body_create (mu_body_t *pbody, void *owner)
+static int body_get_stream (mu_body_t body, mu_stream_t *pstream, int ref);
+
+
+struct _mu_body_stream
 {
+  struct _mu_stream stream;
   mu_body_t body;
+};
 
-  if (pbody == NULL)
-    return MU_ERR_OUT_PTR_NULL;
-  if (owner == NULL)
-    return EINVAL;
+/* Body stream.  */
+#define BODY_RDONLY 0
+#define BODY_RDWR 1
 
-  body = calloc (1, sizeof (*body));
-  if (body == NULL)
-    return ENOMEM;
+static int
+init_tmp_stream (mu_body_t body)
+{
+  int rc;
+  mu_off_t off;
 
-  body->owner = owner;
-  *pbody = body;
-  return 0;
+  rc = mu_stream_seek (body->rawstream, 0, MU_SEEK_CUR, &off);
+  if (rc)
+    return rc;
+
+  rc = mu_stream_seek (body->rawstream, 0, MU_SEEK_SET, NULL);
+  if (rc)
+    return rc;
+  
+  rc = mu_stream_copy (body->fstream, body->rawstream, 0, NULL);
+  if (rc)
+    return rc;
+  
+  mu_stream_seek (body->rawstream, off, MU_SEEK_SET, NULL);
+
+  return mu_stream_seek (body->fstream, off, MU_SEEK_SET, NULL);
 }
 
-void
-mu_body_destroy (mu_body_t *pbody, void *owner)
+
+static int
+body_stream_transport (mu_stream_t stream, int mode, mu_stream_t *pstr)
 {
-  if (pbody && *pbody)
+  struct _mu_body_stream *str = (struct _mu_body_stream*) stream;
+  mu_body_t body = str->body;
+  
+  if (!body->rawstream && body->_get_stream)
     {
-      mu_body_t body = *pbody;
-      if (body->owner == owner)
+      int status = body->_get_stream (body, &body->rawstream);
+      if (status)
+       return status;
+    }
+  if (mode == BODY_RDWR || !body->rawstream)
+    {
+      /* Create the temporary file.  */
+      if (!body->fstream)
        {
-         if (body->stream)
-           mu_stream_destroy (&body->stream);
-
-         if (body->fstream)
+         int rc;
+         
+         rc = mu_temp_file_stream_create (&body->fstream, NULL, 0);
+         if (rc)
+           return rc;
+         mu_stream_set_buffer (body->fstream, mu_buffer_full, 0);
+         if (body->rawstream)
            {
-             mu_stream_close (body->fstream);
-             mu_stream_destroy (&body->fstream);
+             rc = init_tmp_stream (body);
+             if (rc)
+               {
+                 mu_stream_destroy (&body->fstream);
+                 return rc;
+               }
            }
-
-         free (body);
        }
-      *pbody = NULL;
+      body->flags |= BODY_MODIFIED;
     }
+  *pstr = body->fstream ? body->fstream : body->rawstream;
+  return 0;
+}
+    
+static int
+bstr_close (struct _mu_stream *stream)
+{
+  struct _mu_body_stream *str = (struct _mu_body_stream*) stream;
+  mu_body_t body = str->body;
+  mu_stream_close (body->rawstream);
+  mu_stream_close (body->fstream);
+  return 0;
 }
 
-void *
-mu_body_get_owner (mu_body_t body)
+void
+bstr_done (struct _mu_stream *stream)
 {
-  return (body) ? body->owner : NULL;
+  struct _mu_body_stream *str = (struct _mu_body_stream*) stream;
+  mu_body_t body = str->body;
+  mu_stream_destroy (&body->rawstream);
+  mu_stream_destroy (&body->fstream);  
 }
 
-/* FIXME: not implemented.  */
-int
-mu_body_is_modified (mu_body_t body)
+static int
+bstr_seek (mu_stream_t stream, mu_off_t off, mu_off_t *presult)
 {
-  return (body) ? (body->flags & BODY_MODIFIED) : 0;
+  mu_stream_t transport;
+  int rc;
+  
+  rc = body_stream_transport (stream, BODY_RDONLY, &transport);
+  if (rc)
+    return rc;
+  
+  return mu_stream_seek (transport, off, MU_SEEK_SET, presult);
 }
 
-/* FIXME: not implemented.  */
-int
-mu_body_clear_modified (mu_body_t body)
+static int
+bstr_ioctl (mu_stream_t stream, int code, int opcode, void *ptr)
 {
-  if (body)
-    body->flags &= ~BODY_MODIFIED;
-  return 0;
+  mu_stream_t transport;
+  int rc;
+
+  /* FIXME: always RDONLY, is it? */
+  rc = body_stream_transport (stream, BODY_RDONLY, &transport);
+  if (rc)
+    return rc;
+  return mu_stream_ioctl (transport, code, opcode, ptr);
 }
 
-
-struct _mu_body_stream
+static int
+bstr_read (mu_stream_t stream, char *buf, size_t size, size_t *pret)
 {
-  struct _mu_stream stream;
-  mu_body_t body;
-};
+  mu_stream_t transport;
+  int rc;
+  
+  rc = body_stream_transport (stream, BODY_RDONLY, &transport);
+  if (rc)
+    return rc;
+  return mu_stream_read (transport, buf, size, pret);
+}
 
 static int
-_body_get_stream (mu_body_t body, mu_stream_t *pstream, int ref)
+bstr_write (mu_stream_t stream, const char *buf, size_t size, size_t *pret)
 {
-  if (body == NULL)
-    return EINVAL;
-  if (pstream == NULL)
-    return MU_ERR_OUT_PTR_NULL;
+  mu_stream_t transport;
+  int rc;
+  
+  rc = body_stream_transport (stream, BODY_RDWR, &transport);
+  if (rc)
+    return rc;
+  return mu_stream_write (transport, buf, size, pret);
+}
 
-  if (body->stream == NULL)
+static int
+bstr_truncate (mu_stream_t stream, mu_off_t n)
+{
+  mu_stream_t transport;
+  int rc;
+  
+  rc = body_stream_transport (stream, BODY_RDWR, &transport);
+  if (rc)
+    return rc;
+  return mu_stream_truncate (transport, n);
+}
+
+static int
+bstr_size (mu_stream_t stream, mu_off_t *size)
+{
+  mu_stream_t transport;
+  int rc;
+  
+  rc = body_stream_transport (stream, BODY_RDONLY, &transport);
+  if (rc)
+    return rc;
+  return mu_stream_size (transport, size);
+}
+
+static int
+bstr_flush (mu_stream_t stream)
+{
+  mu_stream_t transport;
+  int rc;
+  
+  rc = body_stream_transport (stream, BODY_RDONLY, &transport);
+  if (rc)
+    return rc;
+  return mu_stream_flush (transport);
+}
+
+/* Default function for the body.  */
+static int
+bstr_get_lines (mu_body_t body, size_t *plines)
+{
+  mu_stream_t stream, transport;
+  int status;
+  size_t lines = 0;
+  mu_off_t off;
+
+  status = body_get_stream (body, &stream, 0);
+  if (status)
+    return status;
+
+  status = body_stream_transport (body->stream, BODY_RDONLY, &transport);
+  if (status)
+    return status;
+  
+  status = mu_stream_flush (transport);
+  if (status)
+    return status;
+  status = mu_stream_seek (transport, 0, MU_SEEK_CUR, &off);
+  if (status == 0)
     {
-      if (body->_get_stream)
+      char buf[128];
+      size_t n = 0;
+
+      status = mu_stream_seek (transport, 0, MU_SEEK_SET, NULL);
+      if (status)
+       return status;
+      while ((status = mu_stream_readline (transport, buf, sizeof buf,
+                                          &n)) == 0 && n > 0)
        {
-         int status = body->_get_stream (body, &body->stream);
-         if (status)
-           return status;
+         if (buf[n - 1] == '\n')
+           lines++;
        }
-      else
-       {
-         int status;
-         struct _mu_body_stream *str =
-           (struct _mu_body_stream *)
+      mu_stream_seek (transport, off, MU_SEEK_SET, NULL);
+    }
+  if (plines)
+    *plines = lines;
+  return status;
+}
+
+static int
+bstr_get_size0 (mu_stream_t stream, size_t *psize)
+{
+  mu_off_t off = 0;
+  int status = mu_stream_size (stream, &off);
+  if (psize)
+    *psize = off;
+  return status;
+}
+
+static int
+bstr_get_size (mu_body_t body, size_t *psize)
+{
+  mu_stream_t transport;
+  int rc;
+  
+  rc = body_stream_transport (body->stream, BODY_RDONLY, &transport);
+  if (rc)
+    return rc;
+  return bstr_get_size0 (transport, psize);
+}
+
+
+static int
+body_stream_create (mu_body_t body)
+{
+  struct _mu_body_stream *str =
+    (struct _mu_body_stream *)
            _mu_stream_create (sizeof (*str),
                               MU_STREAM_RDWR|MU_STREAM_SEEK|_MU_STR_OPEN);
-         if (!str)
-           return ENOMEM;
+  if (!str)
+    return ENOMEM;
          
-         /* Create the temporary file.  */
+  str->stream.ctl = bstr_ioctl;
+  str->stream.read = bstr_read;
+  str->stream.write = bstr_write;
+  str->stream.truncate = bstr_truncate;
+  str->stream.size = bstr_size;
+  str->stream.seek = bstr_seek;
+  str->stream.flush = bstr_flush;
+  str->stream.close = bstr_close;
+  str->stream.done = bstr_done;
+  str->body = body;
+  body->stream = (mu_stream_t) str;
+  /* Override the defaults.  */
+  body->_lines = bstr_get_lines;
+  body->_size = bstr_get_size;
+
+  body->stream = (mu_stream_t) str;
+  return 0;
+}
 
-         status = mu_temp_file_stream_create (&body->fstream, NULL, 0);
-         if (status != 0)
-           return status;
-         mu_stream_set_buffer (body->fstream, mu_buffer_full, 0);
-         str->stream.ctl = _body_ioctl;
-         str->stream.read = _body_read;
-         str->stream.write = _body_write;
-         str->stream.truncate = _body_truncate;
-         str->stream.size = _body_size;
-         str->stream.seek = _body_seek;
-         str->stream.flush = _body_flush;
-         str->body = body;
-         body->stream = (mu_stream_t) str;
-         /* Override the defaults.  */
-         body->_lines = _body_get_lines;
-         body->_size = _body_get_size;
-       }
+static int
+body_get_stream (mu_body_t body, mu_stream_t *pstream, int ref)
+{
+  if (body == NULL)
+    return EINVAL;
+  if (pstream == NULL)
+    return MU_ERR_OUT_PTR_NULL;
+
+  if (body->stream == NULL)
+    {
+      int status = body_stream_create (body);
+      if (status)
+       return status;
     }
   
   if (!ref)
@@ -182,13 +339,13 @@ int
 mu_body_get_stream (mu_body_t body, mu_stream_t *pstream)
 {
   /* FIXME: Deprecation warning */
-  return _body_get_stream (body, pstream, 0);
+  return body_get_stream (body, pstream, 0);
 }
 
 int
 mu_body_get_streamref (mu_body_t body, mu_stream_t *pstream)
 {
-  return _body_get_stream (body, pstream, 1);
+  return body_get_stream (body, pstream, 1);
 }
 
 int
@@ -200,7 +357,8 @@ mu_body_set_stream (mu_body_t body, mu_stream_t stream, 
void *owner)
     return EACCES;
   /* make sure we destroy the old one if it is owned by the body */
   mu_stream_destroy (&body->stream);
-  body->stream = stream;
+  mu_stream_destroy (&body->rawstream);
+  body->rawstream = stream;
   body->flags |= BODY_MODIFIED;
   return 0;
 }
@@ -238,11 +396,7 @@ mu_body_lines (mu_body_t body, size_t *plines)
   if (body->_lines)
     return body->_lines (body, plines);
   /* Fall on the stream.  */
-  if (body->stream)
-    return _body_get_lines0 (body->stream, plines);
-  if (plines)
-    *plines = 0;
-  return 0;
+  return bstr_get_lines (body, plines);
 }
 
 int
@@ -254,14 +408,15 @@ mu_body_size (mu_body_t body, size_t *psize)
     return body->_size (body, psize);
   /* Fall on the stream.  */
   if (body->stream)
-    return _body_get_size0 (body->stream, psize);
+    return bstr_get_size0 (body->stream, psize);
   if (psize)
     *psize = 0;
   return 0;
 }
 
 int
-mu_body_set_size (mu_body_t body, int (*_size)(mu_body_t, size_t*) , void 
*owner)
+mu_body_set_size (mu_body_t body, int (*_size)(mu_body_t, size_t*),
+                 void *owner)
 {
   if (body == NULL)
     return EINVAL;
@@ -271,118 +426,61 @@ mu_body_set_size (mu_body_t body, int 
(*_size)(mu_body_t, size_t*) , void *owner
   return 0;
 }
 
-/* Stub function for the body stream.  */
-
-static int
-_body_seek (mu_stream_t stream, mu_off_t off, mu_off_t *presult)
-{
-  struct _mu_body_stream *str = (struct _mu_body_stream*) stream;
-  mu_body_t body = str->body;
-  return mu_stream_seek (body->fstream, off, MU_SEEK_SET, presult);
-}
-
-static const char *
-_body_error_string (mu_stream_t stream, int rc)
-{
-  /* FIXME: How to know if rc was returned by a body->stream? */
-  return NULL;
-}
-
-static int
-_body_ioctl (mu_stream_t stream, int code, int opcode, void *ptr)
-{
-  struct _mu_body_stream *str = (struct _mu_body_stream*) stream;
-  mu_body_t body = str->body;
-  return mu_stream_ioctl (body->fstream, code, opcode, ptr);
-}
-
-static int
-_body_read (mu_stream_t stream, char *buf, size_t size, size_t *pret)
+
+int
+mu_body_create (mu_body_t *pbody, void *owner)
 {
-  struct _mu_body_stream *str = (struct _mu_body_stream*) stream;
-  mu_body_t body = str->body;
-  return mu_stream_read (body->fstream, buf, size, pret);
-}
+  mu_body_t body;
 
-static int
-_body_write (mu_stream_t stream, const char *buf, size_t size, size_t *pret)
-{
-  struct _mu_body_stream *str = (struct _mu_body_stream*) stream;
-  mu_body_t body = str->body;
-  return mu_stream_write (body->fstream, buf, size, pret);
-}
+  if (pbody == NULL)
+    return MU_ERR_OUT_PTR_NULL;
+  if (owner == NULL)
+    return EINVAL;
 
-static int
-_body_truncate (mu_stream_t stream, mu_off_t n)
-{
-  struct _mu_body_stream *str = (struct _mu_body_stream*) stream;
-  mu_body_t body = str->body;
-  return mu_stream_truncate (body->fstream, n);
-}
+  body = calloc (1, sizeof (*body));
+  if (body == NULL)
+    return ENOMEM;
 
-static int
-_body_size (mu_stream_t stream, mu_off_t *size)
-{
-  struct _mu_body_stream *str = (struct _mu_body_stream*) stream;
-  mu_body_t body = str->body;
-  return mu_stream_size (body->fstream, size);
+  body->owner = owner;
+  *pbody = body;
+  return 0;
 }
 
-static int
-_body_flush (mu_stream_t stream)
+void
+mu_body_destroy (mu_body_t *pbody, void *owner)
 {
-  struct _mu_body_stream *str = (struct _mu_body_stream*) stream;
-  mu_body_t body = str->body;
-  return mu_stream_flush (body->fstream);
+  if (pbody && *pbody)
+    {
+      mu_body_t body = *pbody;
+      if (body->owner == owner)
+       {
+         mu_stream_destroy (&body->rawstream);
+         mu_stream_destroy (&body->stream);
+         free (body);
+       }
+      *pbody = NULL;
+    }
 }
 
-/* Default function for the body.  */
-static int
-_body_get_lines (mu_body_t body, size_t *plines)
+void *
+mu_body_get_owner (mu_body_t body)
 {
-  return _body_get_lines0 (body->fstream, plines);
+  return (body) ? body->owner : NULL;
 }
 
-static int
-_body_get_size (mu_body_t body, size_t *psize)
+int
+mu_body_is_modified (mu_body_t body)
 {
-  return _body_get_size0 (body->fstream, psize);
+  return (body) ? (body->flags & BODY_MODIFIED) : 0;
 }
 
-static int
-_body_get_size0 (mu_stream_t stream, size_t *psize)
+int
+mu_body_clear_modified (mu_body_t body)
 {
-  mu_off_t off = 0;
-  int status = mu_stream_size (stream, &off);
-  if (psize)
-    *psize = off;
-  return status;
+  if (body)
+    body->flags &= ~BODY_MODIFIED;
+  return 0;
 }
 
-static int
-_body_get_lines0 (mu_stream_t stream, size_t *plines)
-{
-  int status =  mu_stream_flush (stream);
-  size_t lines = 0;
-  
-  if (status == 0)
-    {
-      char buf[128];
-      size_t n = 0;
-
-      status = mu_stream_seek (stream, 0, MU_SEEK_SET, NULL);
-      if (status)
-       return status;
-      while ((status = mu_stream_readline (stream, buf, sizeof buf,
-                                          &n)) == 0 && n > 0)
-       {
-         if (buf[n - 1] == '\n')
-           lines++;
-       }
-    }
-  if (plines)
-    *plines = lines;
-  return status;
-}
 
 
diff --git a/libmailutils/mailbox/msgbody.c b/libmailutils/mailbox/msgbody.c
index fe843ae..04a2381 100644
--- a/libmailutils/mailbox/msgbody.c
+++ b/libmailutils/mailbox/msgbody.c
@@ -43,8 +43,7 @@ mu_message_get_body (mu_message_t msg, mu_body_t *pbody)
       if (status != 0)
        return status;
       /* If a stream is already set, use it to create the body stream.  */
-      /* FIXME: I'm not sure if the second condition is really needed */
-      if (msg->stream/* && (msg->flags & MESSAGE_INTERNAL_STREAM)*/)
+      if (msg->rawstream)
        {
          mu_stream_t stream;
          int flags = 0;
@@ -52,8 +51,8 @@ mu_message_get_body (mu_message_t msg, mu_body_t *pbody)
          /* FIXME: The actual mu_header_size cannot be used as offset,
             because the headers might have been modified in between. */
          
-         mu_stream_get_flags (msg->stream, &flags);
-         status = mu_streamref_create_abridged (&stream, msg->stream,
+         mu_stream_get_flags (msg->rawstream, &flags);
+         status = mu_streamref_create_abridged (&stream, msg->rawstream,
                                                 msg->orig_header_size, 0);
          if (status)
            {
diff --git a/libmailutils/mailbox/msgheader.c b/libmailutils/mailbox/msgheader.c
index e2a362f..10872b0 100644
--- a/libmailutils/mailbox/msgheader.c
+++ b/libmailutils/mailbox/msgheader.c
@@ -109,17 +109,9 @@ _header_fill (mu_stream_t stream, char **pbuf, size_t 
*plen)
 static int
 message_header_fill (void *data, char **pbuf, size_t *plen)
 {
-  int status = 0;
   mu_message_t msg = data;
-  mu_stream_t stream;
 
-  status = mu_message_get_streamref (msg, &stream);
-  if (status == 0)
-    {
-      status = _header_fill (stream, pbuf, plen);
-      mu_stream_destroy (&stream);
-    }
-  return status;
+  return _header_fill (msg->rawstream, pbuf, plen);
 }
 
 int
@@ -136,7 +128,7 @@ mu_message_get_header (mu_message_t msg, mu_header_t *phdr)
       int status = mu_header_create (&header, NULL, 0);
       if (status != 0)
        return status;
-      if (msg->stream)
+      if (msg->rawstream)
        mu_header_set_fill (header, message_header_fill, msg);
       status = mu_header_size (header, &msg->orig_header_size);
       if (status)
diff --git a/libmailutils/mailbox/msgref.c b/libmailutils/mailbox/msgref.c
index dc99858..e74dfb9 100644
--- a/libmailutils/mailbox/msgref.c
+++ b/libmailutils/mailbox/msgref.c
@@ -54,29 +54,13 @@ _mu_message_free (mu_message_t msg)
       mu_observable_destroy (&msg->observable, msg);
     }
       
-  /* Envelope.  */
-  if (msg->envelope)
-    mu_envelope_destroy (&msg->envelope, msg);
-      
-  /* Header.  */
-  if (msg->header)
-    mu_header_destroy (&msg->header);
-      
-  /* Body.  */
-  if (msg->body)
-    mu_body_destroy (&msg->body, msg);
-      
-  /* Attribute.  */
-  if (msg->attribute)
-    mu_attribute_destroy (&msg->attribute, msg);
-      
-  /* Stream.  */
-  if (msg->stream)
-    mu_stream_destroy (&msg->stream);
-      
-  /*  Mime.  */
-  if (msg->flags & MESSAGE_MIME_OWNER)
-    mu_mime_destroy (&msg->mime);
+  mu_envelope_destroy (&msg->envelope, msg);
+  mu_header_destroy (&msg->header);
+  mu_body_destroy (&msg->body, msg);
+  mu_attribute_destroy (&msg->attribute, msg);
+  mu_stream_destroy (&msg->rawstream);
+  mu_stream_destroy (&msg->outstream);
+  mu_mime_destroy (&msg->mime);
       
   /* Loose the owner.  */
   msg->owner = NULL;
diff --git a/libmailutils/mailbox/msgstream.c b/libmailutils/mailbox/msgstream.c
index f7e6879..2a498d6 100644
--- a/libmailutils/mailbox/msgstream.c
+++ b/libmailutils/mailbox/msgstream.c
@@ -283,16 +283,41 @@ mu_message_set_stream (mu_message_t msg, mu_stream_t 
stream, void *owner)
     return EINVAL;
   if (msg->owner != owner)
     return EACCES;
-  if (msg->stream)
-    mu_stream_destroy (&msg->stream);
-  msg->stream = stream;
+  mu_stream_destroy (&msg->rawstream);
+  mu_stream_destroy (&msg->outstream);
+  msg->rawstream = stream;
   msg->flags |= MESSAGE_MODIFIED;
   msg->flags &= ~MESSAGE_INTERNAL_STREAM;
   return 0;
 }
 
 static int
-_message_get_stream (mu_message_t msg, mu_stream_t *pstream, int ref)
+mkoutstream (mu_message_t msg)
+{
+  int status;
+  mu_header_t hdr;
+  mu_body_t body;
+
+  if (msg->outstream)
+    return 0;
+  /* FIXME: Kind of a kludge: make sure the message has header
+     and body initialized. */
+  status = mu_message_get_header (msg, &hdr);
+  if (status)
+    return status;
+  status = mu_message_get_body (msg, &body);
+  if (status)
+    return status;
+         
+  status = _message_stream_create (&msg->outstream, msg, MU_STREAM_RDWR);
+  if (status == 0)
+    msg->flags |= MESSAGE_INTERNAL_STREAM;
+  return status;
+}
+
+
+int
+mu_message_get_stream (mu_message_t msg, mu_stream_t *pstream)
 {
   int status;
 
@@ -301,54 +326,67 @@ _message_get_stream (mu_message_t msg, mu_stream_t 
*pstream, int ref)
   if (pstream == NULL)
     return MU_ERR_OUT_PTR_NULL;
 
-  if (msg->stream == NULL)
+  /* FIXME: Deprecation warning */
+
+  if (msg->rawstream == NULL)
     {
       if (msg->_get_stream)
        {
-         status = msg->_get_stream (msg, &msg->stream);
+         status = msg->_get_stream (msg, &msg->rawstream);
          if (status)
            return status;
        }
       else
        {
-         mu_header_t hdr;
-         mu_body_t body;
-
-         /* FIXME: Kind of a kludge: make sure the message has header
-            and body initialized. */
-         status = mu_message_get_header (msg, &hdr);
+         status = mkoutstream (msg);
          if (status)
            return status;
-         status = mu_message_get_body (msg, &body);
+         status = mu_streamref_create (&msg->rawstream, msg->outstream);
+       }
+    }
+  *pstream = msg->rawstream;
+  return 0;
+}
+
+int
+mu_message_get_streamref (mu_message_t msg, mu_stream_t *pstream)
+{
+  int status = 0;
+
+  if (msg == NULL)
+    return EINVAL;
+  if (pstream == NULL)
+    return MU_ERR_OUT_PTR_NULL;
+  
+  if (!msg->rawstream)
+    {
+      if (msg->_get_stream)
+       {
+         status = msg->_get_stream (msg, &msg->rawstream);
          if (status)
            return status;
-         
-         status = _message_stream_create (&msg->stream, msg, MU_STREAM_RDWR);
+         status = mu_streamref_create (&msg->outstream, msg->rawstream);
+       }
+      else
+       {
+         status = mkoutstream (msg);
          if (status)
            return status;
-         msg->flags |= MESSAGE_INTERNAL_STREAM;
+         status = mu_streamref_create (&msg->rawstream, msg->outstream);
        }
     }
   
-  if (!ref)
+  if (status)
+    return status;
+
+  if (!msg->outstream ||
+      (!(msg->flags & MESSAGE_INTERNAL_STREAM) &&
+       mu_message_is_modified (msg)))
     {
-      *pstream = msg->stream;
-      return 0;
+      mu_stream_destroy (&msg->outstream);
+      status = mkoutstream (msg);
     }
-  return mu_streamref_create (pstream, msg->stream);
-}
-
-int
-mu_message_get_stream (mu_message_t msg, mu_stream_t *pstream)
-{
-  /* FIXME: Deprecation warning */
-  return _message_get_stream (msg, pstream, 0);
-}
-
-int
-mu_message_get_streamref (mu_message_t msg, mu_stream_t *pstream)
-{
-  return _message_get_stream (msg, pstream, 1);
+  return mu_streamref_create (pstream, msg->outstream);
 }
 
 int
diff --git a/libmailutils/tests/Makefile.am b/libmailutils/tests/Makefile.am
index 3e3a5ba..65574bf 100644
--- a/libmailutils/tests/Makefile.am
+++ b/libmailutils/tests/Makefile.am
@@ -38,7 +38,7 @@ $(srcdir)/package.m4: $(top_srcdir)/configure.ac
 ## Non-installable programs
 ## -------------------------- ##
 
-INCLUDES = @MU_LIB_COMMON_INCLUDES@ 
+AM_CPPFLAGS = @MU_LIB_COMMON_INCLUDES@ 
 noinst_PROGRAMS = \
  addr\
  cidr\
@@ -55,6 +55,7 @@ noinst_PROGRAMS = \
  mimehdr\
  modtofsaf\
  msgset\
+ modmesg\
  prop\
  scantime\
  strftime\
@@ -94,6 +95,10 @@ TESTSUITE_AT = \
  list.at\
  mailcap.at\
  mimehdr.at\
+ modmesg00.at\
+ modmesg01.at\
+ modmesg02.at\
+ modmesg03.at\
  modtofsaf.at\
  msgset.at\
  prop.at\
diff --git a/libmailutils/tests/modmesg.c b/libmailutils/tests/modmesg.c
new file mode 100644
index 0000000..39c3668
--- /dev/null
+++ b/libmailutils/tests/modmesg.c
@@ -0,0 +1,103 @@
+/* GNU Mailutils -- a suite of utilities for electronic mail
+   Copyright (C) 2013 Free Software Foundation, Inc.
+
+   GNU Mailutils is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3, or (at your option)
+   any later version.
+
+   GNU Mailutils is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GNU Mailutils.  If not, see <http://www.gnu.org/licenses/>. */
+
+#include <assert.h>
+#include <mailutils/mailutils.h>
+
+char *text = "From: root\n\
+\n\
+This is a test message.\n\
+oo\n\
+";
+
+int
+main (int argc, char **argv)
+{
+  int i;
+  char *p;
+  mu_message_t msg;
+  mu_stream_t stream = NULL;
+  mu_header_t hdr;
+  mu_body_t body;
+  char *buf = NULL;
+  
+  mu_set_program_name (argv[0]);
+
+  mu_static_memory_stream_create (&stream, text, strlen (text));
+  assert (mu_stream_to_message (stream, &msg) == 0);
+  mu_stream_unref (stream);
+  assert (mu_message_get_header (msg, &hdr) == 0);
+  assert (mu_message_get_body (msg, &body) == 0);
+  assert (mu_body_get_streamref (body, &stream) == 0);
+  assert (mu_stream_seek (stream, 0, MU_SEEK_END, NULL) == 0);
+  
+  for (i = 1; i < argc; i++)
+    {
+      if (strcmp (argv[i], "-h") == 0)
+       {
+         mu_printf ("usage: %s [-a HDR:VAL] [-t TEXT]\n", mu_program_name);
+         return 0;
+       }
+      
+      if (strcmp (argv[i], "-a") == 0)
+       {
+         i++;
+         assert (argv[i] != NULL);
+         p = strchr (argv[i], ':');
+         assert (p != NULL);
+         *p++ = 0;
+         while (*p && mu_isspace (*p))
+           p++;
+         assert (mu_header_set_value (hdr, argv[i], p, 1) == 0);
+       }
+      else if (strcmp (argv[i], "-l") == 0)
+       {
+         mu_off_t off;
+         int whence = MU_SEEK_SET;
+         
+         i++;
+         assert (argv[i] != NULL);
+         off = strtol (argv[i], &p, 10);
+         assert (*p == 0);
+         if (off < 0)
+           whence = MU_SEEK_END;
+         assert (mu_stream_seek (stream, off, whence, NULL) == 0);
+       }
+      else if (strcmp (argv[i], "-t") == 0)
+       {
+         size_t len;
+         i++;
+         assert (argv[i] != NULL);
+         len = strlen (argv[i]);
+         buf = realloc (buf, len + 1);
+         mu_wordsplit_c_unquote_copy (buf, argv[i], len);
+         assert (buf != NULL);
+         assert (mu_stream_write (stream, buf,
+                                  strlen (buf), NULL) == 0);
+       }
+      else
+       mu_error ("ignoring unknown argument %s", argv[i]);
+    }
+  mu_stream_unref (stream);
+
+  assert (mu_message_get_streamref (msg, &stream) == 0);
+  assert (mu_stream_copy (mu_strout, stream, 0, NULL) == 0);
+  mu_stream_unref (stream);
+
+  return 0;
+}
+
+  
diff --git a/libmailutils/tests/strout.at b/libmailutils/tests/modmesg00.at
similarity index 85%
copy from libmailutils/tests/strout.at
copy to libmailutils/tests/modmesg00.at
index b824afb..88fb073 100644
--- a/libmailutils/tests/strout.at
+++ b/libmailutils/tests/modmesg00.at
@@ -14,23 +14,16 @@
 # You should have received a copy of the GNU General Public License
 # along with GNU Mailutils.  If not, see <http://www.gnu.org/licenses/>.
 
-AT_SETUP([strout])
-AT_KEYWORDS([stdstream])
+AT_SETUP([unmodified message])
+AT_KEYWORDS([modmesg00])
 
-AT_CHECK([
-strout now is the time for all good men
-],
+AT_CHECK([modmesg],
 [0],
-[now
-is
-the
-time
-for
-all
-good
-men
+[From: root
+
+This is a test message.
+oo
 ])
 
 AT_CLEANUP
 
-
diff --git a/libmailutils/tests/strout.at b/libmailutils/tests/modmesg01.at
similarity index 81%
copy from libmailutils/tests/strout.at
copy to libmailutils/tests/modmesg01.at
index b824afb..2fd8808 100644
--- a/libmailutils/tests/strout.at
+++ b/libmailutils/tests/modmesg01.at
@@ -14,23 +14,18 @@
 # You should have received a copy of the GNU General Public License
 # along with GNU Mailutils.  If not, see <http://www.gnu.org/licenses/>.
 
-AT_SETUP([strout])
-AT_KEYWORDS([stdstream])
+AT_SETUP([add headers])
+AT_KEYWORDS([modmesg01])
 
-AT_CHECK([
-strout now is the time for all good men
-],
+AT_CHECK([modmesg -a To:address@hidden -a Subject:test],
 [0],
-[now
-is
-the
-time
-for
-all
-good
-men
+[Subject: test
+To: address@hidden
+From: root
+
+This is a test message.
+oo
 ])
 
 AT_CLEANUP
 
-
diff --git a/libmailutils/tests/strerr.at b/libmailutils/tests/modmesg02.at
similarity index 78%
copy from libmailutils/tests/strerr.at
copy to libmailutils/tests/modmesg02.at
index a9dc5dc..6df06d7 100644
--- a/libmailutils/tests/strerr.at
+++ b/libmailutils/tests/modmesg02.at
@@ -14,24 +14,25 @@
 # You should have received a copy of the GNU General Public License
 # along with GNU Mailutils.  If not, see <http://www.gnu.org/licenses/>.
 
-AT_SETUP([strerr])
-AT_KEYWORDS([stdstream])
+AT_SETUP([modify body])
+AT_KEYWORDS([modmesg02])
 
-AT_CHECK([
-strout -err now is the time for all good men
-],
+AT_CHECK([modmesg -t "word\n"],
 [0],
-[],
-[strout: now
-strout: is
-strout: the
-strout: time
-strout: for
-strout: all
-strout: good
-strout: men
+[From: root
+
+This is a test message.
+oo
+word
 ])
 
-AT_CLEANUP
+AT_CHECK([modmesg -l 0 -t "That"],
+[0],
+[From: root
 
+That is a test message.
+oo
+])
+
+AT_CLEANUP
 
diff --git a/libmailutils/tests/strerr.at b/libmailutils/tests/modmesg03.at
similarity index 78%
copy from libmailutils/tests/strerr.at
copy to libmailutils/tests/modmesg03.at
index a9dc5dc..ad0ba83 100644
--- a/libmailutils/tests/strerr.at
+++ b/libmailutils/tests/modmesg03.at
@@ -14,24 +14,18 @@
 # You should have received a copy of the GNU General Public License
 # along with GNU Mailutils.  If not, see <http://www.gnu.org/licenses/>.
 
-AT_SETUP([strerr])
-AT_KEYWORDS([stdstream])
+AT_SETUP([modify headers and body])
+AT_KEYWORDS([modmesg02])
 
-AT_CHECK([
-strout -err now is the time for all good men
-],
+AT_CHECK([modmesg -a To:address@hidden -a Subject:test -l 0 -t "That"],
 [0],
-[],
-[strout: now
-strout: is
-strout: the
-strout: time
-strout: for
-strout: all
-strout: good
-strout: men
+[Subject: test
+To: address@hidden
+From: root
+
+That is a test message.
+oo
 ])
 
 AT_CLEANUP
 
-
diff --git a/libmailutils/tests/testsuite.at b/libmailutils/tests/testsuite.at
index 957e3e5..2b4cf51 100644
--- a/libmailutils/tests/testsuite.at
+++ b/libmailutils/tests/testsuite.at
@@ -92,6 +92,12 @@ m4_include([debugspec.at])
 AT_BANNER([IMAP IO])
 m4_include([imapio.at])
 
+AT_BANNER(Message modification)
+m4_include([modmesg00.at])
+m4_include([modmesg01.at])
+m4_include([modmesg02.at])
+m4_include([modmesg03.at])
+
 m4_include([scantime.at])
 m4_include([strftime.at])
 
diff --git a/mh/mhn.c b/mh/mhn.c
index 3c18824..6baa579 100644
--- a/mh/mhn.c
+++ b/mh/mhn.c
@@ -2159,7 +2159,6 @@ finish_msg (struct compose_env *env, mu_message_t *msg)
       free (p);
     }
   mu_mime_add_part (env->mime, *msg);
-  mu_message_unref (*msg);
   *msg = NULL;
 }
 
@@ -2598,6 +2597,7 @@ mhn_edit (struct compose_env *env, int level)
 
          mu_message_get_body (msg, &body);
          mu_body_get_streamref (body, &output);
+         mu_message_ref (msg);
          line_count = 0;
          ascii_buf = 1; /* Suppose it is ascii */
          env->subpart++;
@@ -2640,6 +2640,7 @@ mhn_edit (struct compose_env *env, int level)
                  /* Close and append the previous part */
                  mu_stream_close (output);
                  mu_stream_destroy (&output);
+                 mu_message_unref (msg);
                  finish_text_msg (env, &msg, ascii_buf);
                }
              


hooks/post-receive
-- 
GNU Mailutils



reply via email to

[Prev in Thread] Current Thread [Next in Thread]