[gmime] Added support for getting/setting filename and comment for gzip data



commit ab2ac991c531639bc8f6e8ddf9d3a8708013a19a
Author: Jeffrey Stedfast <jestedfa microsoft com>
Date:   Thu Dec 14 11:05:45 2017 -0500

    Added support for getting/setting filename and comment for gzip data

 docs/reference/gmime-sections.txt     |    4 +
 gmime/gmime-filter-gzip.c             |  141 +++++++++++++++++++++++++++++++--
 gmime/gmime-filter-gzip.h             |    6 ++
 tests/data/filters/lorem-ipsum.txt.gz |  Bin 1197 -> 1232 bytes
 tests/test-filters.c                  |   32 ++++++--
 5 files changed, 170 insertions(+), 13 deletions(-)
---
diff --git a/docs/reference/gmime-sections.txt b/docs/reference/gmime-sections.txt
index acffe1d..5808c62 100644
--- a/docs/reference/gmime-sections.txt
+++ b/docs/reference/gmime-sections.txt
@@ -431,6 +431,10 @@ GMIME_FILTER_FROM_GET_CLASS
 GMimeFilterGZip
 GMimeFilterGZipMode
 g_mime_filter_gzip_new
+g_mime_filter_gzip_get_filename
+g_mime_filter_gzip_set_filename
+g_mime_filter_gzip_get_comment
+g_mime_filter_gzip_set_comment
 
 <SUBSECTION Private>
 g_mime_filter_gzip_get_type
diff --git a/gmime/gmime-filter-gzip.c b/gmime/gmime-filter-gzip.c
index 3b66c62..bc0e98f 100644
--- a/gmime/gmime-filter-gzip.c
+++ b/gmime/gmime-filter-gzip.c
@@ -110,6 +110,7 @@ typedef union {
        } unzip;
        struct {
                guint32 wrote_hdr:1;
+               guint32 flushed:1;
        } zip;
 } gzip_state_t;
 
@@ -119,6 +120,9 @@ struct _GMimeFilterGZipPrivate {
        gzip_state_t state;
        gzip_hdr_t hdr;
        
+       char *filename;
+       char *comment;
+       
        guint32 crc32;
        guint32 isize;
 };
@@ -198,6 +202,8 @@ g_mime_filter_gzip_finalize (GObject *object)
        else
                inflateEnd (priv->stream);
        
+       g_free (priv->filename);
+       g_free (priv->comment);
        g_free (priv->stream);
        g_free (priv);
        
@@ -221,12 +227,28 @@ gzip_filter (GMimeFilter *filter, char *in, size_t len, size_t prespace,
        struct _GMimeFilterGZipPrivate *priv = gzip->priv;
        int retval;
        
+       if (priv->state.zip.flushed) {
+               *outprespace = prespace;
+               *outlen = 0;
+               *out = in;
+               return;
+       }
+       
        if (!priv->state.zip.wrote_hdr) {
+               size_t filenamelen = gzip->priv->filename ? strlen (gzip->priv->filename) + 1 : 0;
+               size_t commentlen = gzip->priv->comment ? strlen (gzip->priv->comment) + 1 : 0;
+               size_t hdrlen = 10 + filenamelen + commentlen;
+               char *outptr;
+               
                priv->hdr.v.id1 = 31;
                priv->hdr.v.id2 = 139;
                priv->hdr.v.cm = Z_DEFLATED;
                priv->hdr.v.mtime = 0;
                priv->hdr.v.flg = 0;
+               if (gzip->priv->filename)
+                       priv->hdr.v.flg |= GZIP_FLAG_FNAME;
+               if (gzip->priv->comment)
+                       priv->hdr.v.flg |= GZIP_FLAG_FCOMMENT;
                if (gzip->level == Z_BEST_COMPRESSION)
                        priv->hdr.v.xfl = 2;
                else if (gzip->level == Z_BEST_SPEED)
@@ -235,12 +257,23 @@ gzip_filter (GMimeFilter *filter, char *in, size_t len, size_t prespace,
                        priv->hdr.v.xfl = 0;
                priv->hdr.v.os = GZIP_OS_UNKNOWN;
                
-               g_mime_filter_set_size (filter, (len * 2) + 22, FALSE);
+               g_mime_filter_set_size (filter, (len * 2) + hdrlen + 12, FALSE);
                
                memcpy (filter->outbuf, priv->hdr.buf, 10);
+               outptr = filter->outbuf + 10;
+               
+               if (gzip->priv->filename) {
+                       memcpy (outptr, gzip->priv->filename, filenamelen);
+                       outptr += filenamelen;
+               }
                
-               priv->stream->next_out = (unsigned char *) filter->outbuf + 10;
-               priv->stream->avail_out = filter->outsize - 10;
+               if (gzip->priv->comment) {
+                       memcpy (outptr, gzip->priv->comment, commentlen);
+                       outptr += commentlen;
+               }
+               
+               priv->stream->next_out = (unsigned char *) outptr;
+               priv->stream->avail_out = filter->outsize - hdrlen;
                
                priv->state.zip.wrote_hdr = TRUE;
        } else {
@@ -255,8 +288,10 @@ gzip_filter (GMimeFilter *filter, char *in, size_t len, size_t prespace,
        
        do {
                /* FIXME: handle error cases? */
-               if ((retval = deflate (priv->stream, flush)) != Z_OK)
+               if ((retval = deflate (priv->stream, flush)) != Z_OK) {
                        w(fprintf (stderr, "gzip: %d: %s\n", retval, priv->stream->msg));
+                       break;
+               }
                
                if (flush == Z_FULL_FLUSH) {
                        size_t olen;
@@ -279,6 +314,7 @@ gzip_filter (GMimeFilter *filter, char *in, size_t len, size_t prespace,
                                priv->stream->avail_out -= 4;
                                priv->stream->next_out += 4;
                                
+                               priv->state.zip.flushed = TRUE;
                                break;
                        }
                } else {
@@ -374,6 +410,8 @@ gunzip_filter (GMimeFilter *filter, char *in, size_t len, size_t prespace,
                        return;
                }
                
+               g_free (priv->filename);
+               priv->filename = g_strndup (start, inptr - start);
                priv->state.unzip.got_fname = TRUE;
                inptr++;
                
@@ -390,7 +428,9 @@ gunzip_filter (GMimeFilter *filter, char *in, size_t len, size_t prespace,
                        g_mime_filter_backup (filter, start, left);
                        return;
                }
-               
+
+               g_free (priv->comment);
+               priv->comment = g_strndup (start, inptr - start);
                priv->state.unzip.got_fcomment = TRUE;
                inptr++;
                
@@ -491,10 +531,15 @@ filter_reset (GMimeFilter *filter)
        
        memset (&priv->state, 0, sizeof (priv->state));
        
-       if (gzip->mode == GMIME_FILTER_GZIP_MODE_ZIP)
+       if (gzip->mode == GMIME_FILTER_GZIP_MODE_ZIP) {
                deflateReset (priv->stream);
-       else
+       } else {
                inflateReset (priv->stream);
+               g_free (priv->filename);
+               g_free (priv->comment);
+               priv->filename = NULL;
+               priv->comment = NULL;
+       }
        
        priv->crc32 = crc32 (0, Z_NULL, 0);
        priv->isize = 0;
@@ -532,3 +577,85 @@ g_mime_filter_gzip_new (GMimeFilterGZipMode mode, int level)
        
        return (GMimeFilter *) gzip;
 }
+
+
+/**
+ * g_mime_filter_gzip_get_filename:
+ * @gzip: A #GMimeFilterGZip filter
+ *
+ * Gets the filename that was either previously set or retrieved when decoding a gzip stream.
+ *
+ * Returns: a string containing th ename of the file.
+ *
+ * Since: 3.2
+ **/
+const char *
+g_mime_filter_gzip_get_filename (GMimeFilterGZip *gzip)
+{
+       g_return_val_if_fail (GMIME_IS_FILTER_GZIP (gzip), NULL);
+       
+       return gzip->priv->filename;
+}
+
+
+/**
+ * g_mime_filter_gzip_set_filename:
+ * @gzip: A #GMimeFilterGZip filter
+ * @filename: The name of the file
+ *
+ * Sets the filename that should be used when generating the gzip header.
+ *
+ * Since: 3.2
+ **/
+void
+g_mime_filter_gzip_set_filename (GMimeFilterGZip *gzip, const char *filename)
+{
+       char *buf;
+       
+       g_return_if_fail (GMIME_IS_FILTER_GZIP (gzip));
+       
+       buf = g_strdup (filename);
+       g_free (gzip->priv->filename);
+       gzip->priv->filename = buf;
+}
+
+
+/**
+ * g_mime_filter_gzip_get_comment:
+ * @gzip: A #GMimeFilterGZip filter
+ *
+ * Gets the comment that was either previously set or retrieved when decoding a gzip stream.
+ *
+ * Returns: a string containing the comment.
+ *
+ * Since: 3.2
+ **/
+const char *
+g_mime_filter_gzip_get_comment (GMimeFilterGZip *gzip)
+{
+       g_return_val_if_fail (GMIME_IS_FILTER_GZIP (gzip), NULL);
+       
+       return gzip->priv->comment;
+}
+
+
+/**
+ * g_mime_filter_gzip_set_comment:
+ * @gzip: A #GMimeFilterGZip filter
+ * @comment: The comment
+ *
+ * Sets the comment that should be used when generating the gzip header.
+ *
+ * Since: 3.2
+ **/
+void
+g_mime_filter_gzip_set_comment (GMimeFilterGZip *gzip, const char *comment)
+{
+       char *buf;
+       
+       g_return_if_fail (GMIME_IS_FILTER_GZIP (gzip));
+       
+       buf = g_strdup (comment);
+       g_free (gzip->priv->comment);
+       gzip->priv->comment = buf;
+}
diff --git a/gmime/gmime-filter-gzip.h b/gmime/gmime-filter-gzip.h
index 3612cc5..14be89b 100644
--- a/gmime/gmime-filter-gzip.h
+++ b/gmime/gmime-filter-gzip.h
@@ -78,6 +78,12 @@ GType g_mime_filter_gzip_get_type (void);
 
 GMimeFilter *g_mime_filter_gzip_new (GMimeFilterGZipMode mode, int level);
 
+const char *g_mime_filter_gzip_get_filename (GMimeFilterGZip *gzip);
+void g_mime_filter_gzip_set_filename (GMimeFilterGZip *gzip, const char *filename);
+
+const char *g_mime_filter_gzip_get_comment (GMimeFilterGZip *gzip);
+void g_mime_filter_gzip_set_comment (GMimeFilterGZip *gzip, const char *comment);
+
 G_END_DECLS
 
 #endif /* __GMIME_FILTER_GZIP_H__ */
diff --git a/tests/data/filters/lorem-ipsum.txt.gz b/tests/data/filters/lorem-ipsum.txt.gz
index dcd24c3..9c6f004 100644
Binary files a/tests/data/filters/lorem-ipsum.txt.gz and b/tests/data/filters/lorem-ipsum.txt.gz differ
diff --git a/tests/test-filters.c b/tests/test-filters.c
index fbdf161..afd2ce5 100644
--- a/tests/test-filters.c
+++ b/tests/test-filters.c
@@ -119,6 +119,8 @@ test_gzip (const char *datadir, const char *filename)
        g_mime_stream_mem_set_owner ((GMimeStreamMem *) stream, FALSE);
        
        filter = g_mime_filter_gzip_new (GMIME_FILTER_GZIP_MODE_ZIP, 9);
+       g_mime_filter_gzip_set_filename ((GMimeFilterGZip *) filter, filename);
+       g_mime_filter_gzip_set_comment ((GMimeFilterGZip *) filter, "This is a comment.");
        
        pump_data_through_filter (filter, path, stream, TRUE, FALSE);
        g_mime_filter_reset (filter);
@@ -161,6 +163,7 @@ test_gunzip (const char *datadir, const char *filename)
        GByteArray *actual, *expected;
        GMimeStream *stream;
        GMimeFilter *filter;
+       const char *value;
        
        testsuite_check ("%s", what);
        
@@ -171,9 +174,7 @@ test_gunzip (const char *datadir, const char *filename)
        filter = g_mime_filter_gzip_new (GMIME_FILTER_GZIP_MODE_UNZIP, 9);
        
        pump_data_through_filter (filter, path, stream, FALSE, TRUE);
-       g_mime_filter_reset (filter);
        g_object_unref (stream);
-       g_object_unref (filter);
        g_free (path);
        g_free (name);
        
@@ -181,13 +182,32 @@ test_gunzip (const char *datadir, const char *filename)
        expected = read_all_bytes (path, TRUE);
        g_free (path);
        
-       if (actual->len != expected->len || memcmp (actual->data, expected->data, actual->len) != 0)
-               testsuite_check_failed ("%s failed: %s", what, "streams do not match");
-       else
-               testsuite_check_passed ();
+       if (actual->len != expected->len || memcmp (actual->data, expected->data, actual->len) != 0) {
+               testsuite_check_failed ("%s failed: streams do not match", what);
+               goto error;
+       }
+       
+       value = g_mime_filter_gzip_get_filename ((GMimeFilterGZip *) filter);
+       if (!value || strcmp (value, filename) != 0) {
+               testsuite_check_failed ("%s failed: filename does not match: %s", what, value);
+               goto error;
+       }
+       
+       value = g_mime_filter_gzip_get_comment ((GMimeFilterGZip *) filter);
+       if (!value || strcmp (value, "This is a comment.") != 0) {
+               testsuite_check_failed ("%s failed: comment does not match: %s", what, value);
+               goto error;
+       }
+       
+       testsuite_check_passed ();
+       
+error:
        
        g_byte_array_free (expected, TRUE);
        g_byte_array_free (actual, TRUE);
+       
+       g_mime_filter_reset (filter);
+       g_object_unref (filter);
 }
 
 int main (int argc, char **argv)


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