[libgsf] OLE2: fix writing of properties.
- From: Morten Welinder <mortenw src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [libgsf] OLE2: fix writing of properties.
- Date: Sat, 27 Oct 2012 15:31:50 +0000 (UTC)
commit a051e51efe71314e033e7de2f7cd86434ad841d9
Author: Morten Welinder <terra gnome org>
Date: Sat Oct 27 11:30:51 2012 -0400
OLE2: fix writing of properties.
Code was not ready for writing in 2-byte codepages. Big fat TODO
marked the spot.
ChangeLog | 5 +++
NEWS | 1 +
gsf/gsf-msole-utils.c | 85 ++++++++++++++++++++++++++++++++++--------------
3 files changed, 66 insertions(+), 25 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index b41f86a..38a6e11 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,10 @@
2012-10-27 Morten Welinder <terra gnome org>
+ * gsf/gsf-msole-utils.c (msole_metadata_write_string): New
+ function to take codepage into account.
+ (msole_metadata_write_prop, cb_write_dict): Use
+ msole_metadata_write_string.
+
* gsf/gsf-doc-meta-data.c (gsf_doc_meta_data_insert): Initialize
->ref_count.
diff --git a/NEWS b/NEWS
index 11073ad..955a58b 100644
--- a/NEWS
+++ b/NEWS
@@ -5,6 +5,7 @@ jorilx gmail com:
Morten:
* Fix memory management problem with document properties.
+ * Fix writing of OLE2 properties for multi-byte codepages. [#627696]
--------------------------------------------------------------------------
libgsf 1.14.24
diff --git a/gsf/gsf-msole-utils.c b/gsf/gsf-msole-utils.c
index 2c415e2..b14e75a 100644
--- a/gsf/gsf-msole-utils.c
+++ b/gsf/gsf-msole-utils.c
@@ -268,7 +268,7 @@ msole_prop_id_to_gsf (GsfMSOleMetaDataSection *section, guint32 id, gboolean *li
res = g_hash_table_lookup (section->dict, GINT_TO_POINTER (id));
if (res != NULL) {
- d (g_print (res););
+ d (g_print ("%s", res););
return res;
}
}
@@ -278,11 +278,11 @@ msole_prop_id_to_gsf (GsfMSOleMetaDataSection *section, guint32 id, gboolean *li
while (i-- > 0)
if (map[i].id == id &&
(map[i].section == COMMON_PROP || map[i].section == section->type)) {
- d (g_print (map[i].gsf_name););
+ d (g_print ("%s\n", map[i].gsf_name););
return map[i].gsf_name;
}
- d (g_print ("_UNKNOWN_(0x%x %d)", id, id););
+ d (g_print ("_UNKNOWN_(0x%x %d)\n", id, id););
return NULL;
}
@@ -418,6 +418,14 @@ parse_vt_cf (GValue *res, guint8 const **data, guint8 const *data_end, GError **
return TRUE;
}
+static unsigned
+msole_codepage_char_size (int codepage)
+{
+ return (codepage == 1200 || codepage == 1201
+ ? 2
+ : 1);
+}
+
/*
* Return a number no bigger than the number of bytes used for a property
* value of a given type. The returned number might be too small, but
@@ -1013,6 +1021,7 @@ msole_prop_read (GsfInput *in,
len = GSF_LE_GET_GUINT32 (data + 4);
g_return_val_if_fail (len < 0x10000, FALSE);
+ g_return_val_if_fail (len <= size - (data - start), FALSE);
gslen = 0;
name = g_convert_with_iconv (data + 8,
@@ -1028,7 +1037,8 @@ msole_prop_read (GsfInput *in,
/* MS documentation blows goats !
* The docs claim there are padding bytes in the dictionary.
* Their examples show padding bytes.
- * In reality non-unicode strings do not see to have padding.
+ * In reality non-unicode strings do not seem to
+ * have padding.
*/
if (section->char_size != 1 && (data - start) % 4)
data += 4 - ((data - start) % 4);
@@ -1272,8 +1282,7 @@ gsf_doc_meta_data_read_from_msole (GsfDocMetaData *accum, GsfInput *in)
int codepage = g_value_get_int (val);
sections[i].iconv_handle =
gsf_msole_iconv_open_for_import (codepage);
- if (codepage == 1200 || codepage == 1201)
- sections[i].char_size = 2;
+ sections[i].char_size = msole_codepage_char_size (codepage);
}
}
}
@@ -1334,6 +1343,8 @@ typedef struct {
} builtin, user;
unsigned codepage;
+ GIConv iconv_handle;
+ unsigned char_size;
} WritePropState;
static GsfMSOleVariantType
@@ -1388,6 +1399,33 @@ gvalue_to_msole_vt (GValue const *value, GsfMSOleMetaDataPropMap const *map)
return VT_UNKNOWN;
}
+static gboolean
+msole_metadata_write_string (WritePropState *state, const char *txt)
+{
+ guint8 buf[4];
+ guint32 len;
+ gchar *ctxt;
+ gsize bytes_written;
+ gboolean res;
+
+ if (!txt) txt = "";
+ len = strlen (txt);
+ ctxt = g_convert_with_iconv (txt, len, state->iconv_handle,
+ NULL, &bytes_written, NULL);
+
+ GSF_LE_SET_GUINT32 (buf, len + 1);
+ res = gsf_output_write (state->out, 4, buf);
+
+ res = res && gsf_output_write (state->out, bytes_written, ctxt);
+
+ GSF_LE_SET_GUINT32 (buf, 0);
+ res = res && gsf_output_write (state->out, state->char_size, buf);
+
+ g_free (ctxt);
+ return res;
+}
+
+
/* Returns: TRUE on success */
static gboolean
msole_metadata_write_prop (WritePropState *state,
@@ -1395,7 +1433,6 @@ msole_metadata_write_prop (WritePropState *state,
GValue const *value,
gboolean suppress_type)
{
- static guint8 const zero[1] = { '\0' };
GsfMSOleMetaDataPropMap const *map =
(name != NULL) ? msole_gsf_name_to_prop (name) : NULL;
GsfMSOleVariantType type;
@@ -1420,10 +1457,12 @@ msole_metadata_write_prop (WritePropState *state,
GSF_LE_SET_GINT32 (buf, n);
res = gsf_output_write (state->out, 4, buf);
- for (i = 0; i < n; i++)
+ for (i = 0; i < n; i++) {
+ gboolean suppress = type != (VT_VECTOR | VT_VARIANT);
res &= msole_metadata_write_prop (state, NULL,
g_value_array_get_nth (vector, i),
- type != (VT_VECTOR | VT_VARIANT));
+ suppress);
+ }
return res;
}
@@ -1455,15 +1494,8 @@ msole_metadata_write_prop (WritePropState *state,
GSF_LE_SET_DOUBLE (buf, g_value_get_double (value));
return gsf_output_write (state->out, 8, buf);
- case VT_LPSTR : {
-/* FIXME FIXME FIXME TODO : use iconv from codepage */
- char const *txt = g_value_get_string (value);
- unsigned len = (NULL != txt) ? strlen (txt) : 0;
- GSF_LE_SET_GUINT32 (buf, len+1);
- return gsf_output_write (state->out, 4, buf) &&
- gsf_output_write (state->out, len, txt) &&
- gsf_output_write (state->out, 1, zero);
- }
+ case VT_LPSTR:
+ return msole_metadata_write_string (state, g_value_get_string (value));
case VT_FILETIME : {
GsfTimestamp const *ts = g_value_get_boxed (value);
@@ -1491,14 +1523,11 @@ msole_metadata_write_prop (WritePropState *state,
static void
cb_write_dict (char const *name, gpointer id, WritePropState *state)
{
- static guint8 const zero[1] = { '\0' };
- guint8 buf [8];
- unsigned len = strlen (name) + 1;
+ guint8 buf[4];
+
GSF_LE_SET_GUINT32 (buf, GPOINTER_TO_UINT (id));
- GSF_LE_SET_GUINT32 (buf+4, len+1);
- gsf_output_write (state->out, 8, buf);
- gsf_output_write (state->out, len, name);
- gsf_output_write (state->out, 1, zero);
+ gsf_output_write (state->out, 4, buf);
+ msole_metadata_write_string (state, name);
}
static gboolean
@@ -1661,6 +1690,8 @@ gsf_doc_meta_data_write_to_msole (GsfDocMetaData const *meta_data,
WritePropState state;
state.codepage = 1252;
+ state.iconv_handle = (GIConv)-1;
+ state.char_size = 1;
state.out = out;
state.dict = NULL;
state.builtin.count = 1; /* codepage */
@@ -1673,6 +1704,9 @@ gsf_doc_meta_data_write_to_msole (GsfDocMetaData const *meta_data,
d (g_print ("Done\n"
"================================\n"););
+ state.iconv_handle = gsf_msole_iconv_open_codepage_for_export (state.codepage);
+ state.char_size = msole_codepage_char_size (state.codepage);
+
/* Write stream header */
GSF_LE_SET_GUINT32 (buf, (state.dict != NULL) ? 2 : 1);
if (!gsf_output_write (out, sizeof (header), header) ||
@@ -1707,6 +1741,7 @@ gsf_doc_meta_data_write_to_msole (GsfDocMetaData const *meta_data,
success = TRUE;
err :
+ gsf_iconv_close (state.iconv_handle);
g_slist_free (state.builtin.props);
g_slist_free (state.user.props);
if (state.dict != NULL)
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]