[libgsf] zip: Fix zip directory record problem. [#614968]



commit 0a2e93f6b302e1836c727f1b13ec62cc0ae7efa2
Author: Morten Welinder <terra gnome org>
Date:   Tue Apr 6 14:10:55 2010 -0400

    zip: Fix zip directory record problem.  [#614968]

 ChangeLog             |    9 +++++++++
 NEWS                  |    3 +++
 gsf/gsf-infile-zip.c  |    4 +++-
 gsf/gsf-outfile-zip.c |   17 ++++++++++++-----
 gsf/gsf-zip-impl.h    |    1 +
 5 files changed, 28 insertions(+), 6 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index 5c7d471..ac555ae 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+2010-04-06  Morten Welinder  <terra gnome org>
+
+	* gsf/gsf-outfile-zip.c (zip_header_write, zip_dirent_write): Use
+	dirent->flags for consistency.  Fixes #614968.
+	(zip_dirent_update_flags): New function.
+	(zip_dirent_new_out): Deduce dirent->flags.
+
+	* gsf/gsf-infile-zip.c (zip_dirent_new_in): Read dirent->flags.
+
 2010-04-05  Morten Welinder  <terra gnome org>
 
 	* gsf/gsf-libxml.c (gsf_xml_out_add_cstr): Fix win32 warning about
diff --git a/NEWS b/NEWS
index f0f0138..5b08b49 100644
--- a/NEWS
+++ b/NEWS
@@ -1,5 +1,8 @@
 libgsf 1.14.18
 
+Morten:
+	* Fix zip directory record problem.  [#614968]
+
 --------------------------------------------------------------------------
 libgsf 1.14.17
 
diff --git a/gsf/gsf-infile-zip.c b/gsf/gsf-infile-zip.c
index e11a152..cba7247 100644
--- a/gsf/gsf-infile-zip.c
+++ b/gsf/gsf-infile-zip.c
@@ -191,7 +191,7 @@ zip_dirent_new_in (GsfInfileZip *zip, gsf_off_t *offset)
 		{ 'P', 'K', 0x01, 0x02 };
 	GsfZipDirent *dirent;
 	guint8 const *data;
-	guint16 name_len, extras_len, comment_len, compr_method;
+	guint16 name_len, extras_len, comment_len, compr_method, flags;
 	guint32 crc32, csize, usize, off;
 	gchar *name;
 
@@ -206,6 +206,7 @@ zip_dirent_new_in (GsfInfileZip *zip, gsf_off_t *offset)
 	extras_len =    GSF_LE_GET_GUINT16 (data + ZIP_DIRENT_EXTRAS_SIZE);
 	comment_len =   GSF_LE_GET_GUINT16 (data + ZIP_DIRENT_COMMENT_SIZE);
 
+	flags =         GSF_LE_GET_GUINT32 (data + ZIP_DIRENT_FLAGS);
 	compr_method =  GSF_LE_GET_GUINT16 (data + ZIP_DIRENT_COMPR_METHOD);
 	crc32 =         GSF_LE_GET_GUINT32 (data + ZIP_DIRENT_CRC32);
 	csize =         GSF_LE_GET_GUINT32 (data + ZIP_DIRENT_CSIZE);
@@ -222,6 +223,7 @@ zip_dirent_new_in (GsfInfileZip *zip, gsf_off_t *offset)
 	dirent = gsf_zip_dirent_new ();
 	dirent->name = name;
 
+	dirent->flags = flags;
 	dirent->compr_method =  compr_method;
 	dirent->crc32 =         crc32;
 	dirent->csize =         csize;
diff --git a/gsf/gsf-outfile-zip.c b/gsf/gsf-outfile-zip.c
index c7e1767..f94e262 100644
--- a/gsf/gsf-outfile-zip.c
+++ b/gsf/gsf-outfile-zip.c
@@ -157,7 +157,7 @@ zip_dirent_write (GsfOutput *sink, GsfZipDirent *dirent)
 	memcpy (buf, dirent_signature, sizeof dirent_signature);
 	GSF_LE_SET_GUINT16 (buf + ZIP_DIRENT_ENCODER, 0x317); /* Unix */
 	GSF_LE_SET_GUINT16 (buf + ZIP_DIRENT_EXTRACT, 0x14);
-	GSF_LE_SET_GUINT16 (buf + ZIP_DIRENT_FLAGS, 0x08);
+	GSF_LE_SET_GUINT16 (buf + ZIP_DIRENT_FLAGS, dirent->flags);
 	GSF_LE_SET_GUINT16 (buf + ZIP_DIRENT_COMPR_METHOD,
 			    dirent->compr_method);
 	GSF_LE_SET_GUINT32 (buf + ZIP_DIRENT_DOSTIME, dirent->dostime);
@@ -275,6 +275,15 @@ zip_time_make (time_t t)
 	return ztime;
 }
 
+static void
+zip_dirent_update_flags (GsfZipDirent *dirent)
+{
+	if (dirent->compr_method == GSF_ZIP_STORED)
+		dirent->flags &= ~8;
+	else
+		dirent->flags |= 8;
+}
+
 static GsfZipDirent*
 zip_dirent_new_out (GsfOutfileZip *zip)
 {
@@ -282,6 +291,7 @@ zip_dirent_new_out (GsfOutfileZip *zip)
 	dirent->name = stream_name_build (zip);
 	dirent->compr_method = zip->compression_method;
 	dirent->dostime = zip_time_make (time (NULL));
+	zip_dirent_update_flags (dirent);
 	return dirent;
 }
 
@@ -292,7 +302,6 @@ zip_header_write (GsfOutfileZip *zip)
 		{ 'P', 'K', 0x03, 0x04 };
 	guint8 hbuf[ZIP_HEADER_SIZE];
 	GsfZipDirent *dirent = zip->vdir->dirent;
-	guint16 flags = 0;
 	char *name = dirent->name;
 	int   nlen = strlen (name);
 	gboolean ret;
@@ -300,9 +309,7 @@ zip_header_write (GsfOutfileZip *zip)
 	memset (hbuf, 0, sizeof hbuf);
 	memcpy (hbuf, header_signature, sizeof header_signature);
 	GSF_LE_SET_GUINT16 (hbuf + ZIP_HEADER_VERSION, 0x14);
-	if (dirent->compr_method == GSF_ZIP_DEFLATED)
-		flags = 0x08;
-	GSF_LE_SET_GUINT16 (hbuf + ZIP_HEADER_FLAGS, flags);
+	GSF_LE_SET_GUINT16 (hbuf + ZIP_HEADER_FLAGS, dirent->flags);
 	GSF_LE_SET_GUINT16 (hbuf + ZIP_HEADER_COMP_METHOD,
 			    dirent->compr_method);
 	GSF_LE_SET_GUINT32 (hbuf + ZIP_HEADER_TIME, dirent->dostime);
diff --git a/gsf/gsf-zip-impl.h b/gsf/gsf-zip-impl.h
index 5e89f47..d36daa8 100644
--- a/gsf/gsf-zip-impl.h
+++ b/gsf/gsf-zip-impl.h
@@ -88,6 +88,7 @@ G_BEGIN_DECLS
 
 typedef struct {	
 	char                    *name;
+	guint16                  flags;
 	GsfZipCompressionMethod  compr_method;
 	guint32                  crc32;
 	size_t                   csize;



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