[libgsf] OLE: fix order of entries when writing ole files.
- From: Morten Welinder <mortenw src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [libgsf] OLE: fix order of entries when writing ole files.
- Date: Thu, 8 Dec 2011 18:17:39 +0000 (UTC)
commit e65f8cf481ee517f1bd1edffae3ab7c5de214139
Author: Morten Welinder <terra gnome org>
Date: Thu Dec 8 13:16:04 2011 -0500
OLE: fix order of entries when writing ole files.
The docs are murky and evidently something actually cares about the
ordering. See 665712 for details.
ChangeLog | 12 ++++++++
NEWS | 1 +
gsf/gsf-msole-utils.c | 70 +++++++++++++++++++++++++++++++++++++++++++++++
gsf/gsf-msole-utils.h | 6 ++++
gsf/gsf-outfile-msole.c | 52 +++++++++++++++++++++++-----------
5 files changed, 124 insertions(+), 17 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index ec4ff79..71e1878 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,15 @@
+2011-12-08 Morten Welinder <terra gnome org>
+
+ * gsf/gsf-msole-utils.c (gsf_msole_sorting_key_new)
+ (gsf_msole_sorting_key_free, gsf_msole_sorting_key_cmp): New
+ functions.
+
+ * gsf/gsf-outfile-msole.c (make_sorting_name): New function.
+ (gsf_outfile_msole_constructor): New function.
+ (gsf_outfile_msole_class_init): Hook up constructor.
+ (GsfOutfileMSOle): Add a key member.
+ (ole_name_cmp): Use gsf_msole_sorting_key_cmp. Fixes #665712.
+
2011-12-07 Morten Welinder <terra gnome org>
* gsf/gsf-input-memory.c: Drop HAVE_BROKEN_MMAP -- FreeBSD was
diff --git a/NEWS b/NEWS
index ed00342..2212bed 100644
--- a/NEWS
+++ b/NEWS
@@ -9,6 +9,7 @@ Morten:
* Ensure GsfOutput::name and GsfInput::name notifications.
* Cleanup old code.
* Drop support for gnome-vfs and bonobo.
+ * Fix ole2 entry sorting based on patch from Junping Zhang. [#665712]
Vincent Untz:
* New installation method for thumbnailer. [#651187]
diff --git a/gsf/gsf-msole-utils.c b/gsf/gsf-msole-utils.c
index 0881004..07f1e0c 100644
--- a/gsf/gsf-msole-utils.c
+++ b/gsf/gsf-msole-utils.c
@@ -2434,3 +2434,73 @@ gsf_msole_inflate (GsfInput *input, gsf_off_t offset)
g_byte_array_append (res, buffer, pos % VBA_COMPRESSION_WINDOW);
return res;
}
+
+
+struct GsfMSOleSortingKey_ {
+ gunichar2 *name;
+ size_t len;
+};
+
+GsfMSOleSortingKey *
+gsf_msole_sorting_key_new (const char *name)
+{
+ GsfMSOleSortingKey *res = g_new (GsfMSOleSortingKey, 1);
+ size_t name_len;
+ const char *p;
+
+ if (!name)
+ name = "";
+ name_len = strlen (name);
+
+ res->name = g_new (gunichar2, name_len + 1);
+ res->len = 0;
+
+ /* This code is a bit like g_utf8_to_utf16. */
+
+ for (p = name; *p; p = g_utf8_next_char (p)) {
+ gunichar wc =
+ g_utf8_get_char_validated (p, name_len - (p - name));
+ if (wc & 0x80000000)
+ break; /* Something invalid or incomplete */
+ if (wc < 0x10000) {
+ wc = g_unichar_toupper (wc);
+ /* Let's hope no uppercase char is above 0xffff! */
+ res->name[res->len++] = wc;
+ } else {
+ res->name[res->len++] = (wc - 0x10000) / 0x400 + 0xd800;
+ res->name[res->len++] = (wc - 0x10000) % 0x400 + 0xdc00;
+ }
+ }
+ res->name[res->len] = 0;
+
+ return res;
+}
+
+void
+gsf_msole_sorting_key_free (GsfMSOleSortingKey *sk)
+{
+ if (sk) {
+ g_free (sk->name);
+ g_free (sk);
+ }
+}
+
+int
+gsf_msole_sorting_key_cmp (const GsfMSOleSortingKey *a,
+ const GsfMSOleSortingKey *b)
+{
+ long diff;
+ /* According to the docs length is more important than lexical order */
+ if (a->len != b->len)
+ diff = a->len - b->len;
+ else {
+ const gunichar2 *pa = a->name;
+ const gunichar2 *pb = b->name;
+ while (*pa == *pb && *pa)
+ pa++, pb++;
+ diff = *pa - *pb;
+ }
+
+ /* Note, that diff might not fit "int" */
+ return diff > 0 ? +1 : (diff < 0 ? -1 : 0);
+}
diff --git a/gsf/gsf-msole-utils.h b/gsf/gsf-msole-utils.h
index b3e6940..8a9a8ea 100644
--- a/gsf/gsf-msole-utils.h
+++ b/gsf/gsf-msole-utils.h
@@ -49,6 +49,12 @@ GIConv gsf_msole_iconv_open_codepage_for_export (int codepage_to);
GByteArray *gsf_msole_inflate (GsfInput *input, gsf_off_t offset);
+typedef struct GsfMSOleSortingKey_ GsfMSOleSortingKey;
+GsfMSOleSortingKey *gsf_msole_sorting_key_new (const char *name);
+void gsf_msole_sorting_key_free (GsfMSOleSortingKey *sk);
+int gsf_msole_sorting_key_cmp (const GsfMSOleSortingKey *a,
+ const GsfMSOleSortingKey *b);
+
G_END_DECLS
#endif /* GSF_MSOLE_UTILS_H */
diff --git a/gsf/gsf-outfile-msole.c b/gsf/gsf-outfile-msole.c
index ecd3a00..1681cac 100644
--- a/gsf/gsf-outfile-msole.c
+++ b/gsf/gsf-outfile-msole.c
@@ -24,6 +24,7 @@
#include <gsf/gsf-outfile-msole.h>
#include <gsf/gsf-impl-utils.h>
#include <gsf/gsf-msole-impl.h>
+#include <gsf/gsf-msole-utils.h>
#include <gsf/gsf-utils.h>
#include <string.h>
@@ -48,6 +49,8 @@ struct _GsfOutfileMSOle {
GsfOutput *sink;
GsfOutfileMSOle *root;
+ GsfMSOleSortingKey *key;
+
MSOleOutfileType type;
unsigned first_block;
unsigned blocks;
@@ -80,6 +83,9 @@ gsf_outfile_msole_finalize (GObject *obj)
GsfOutfileMSOle *ole = GSF_OUTFILE_MSOLE (obj);
GsfOutput *output = GSF_OUTPUT (obj);
+ gsf_msole_sorting_key_free (ole->key);
+ ole->key = NULL;
+
if (!gsf_output_is_closed (output))
gsf_output_close (output);
@@ -105,6 +111,7 @@ gsf_outfile_msole_finalize (GObject *obj)
default :
g_warning ("Unknown file type");
}
+
parent_class->finalize (obj);
}
@@ -565,23 +572,17 @@ ole_register_child (GsfOutfileMSOle *root, GsfOutfileMSOle *child)
static gint
ole_name_cmp (GsfOutfileMSOle const *a, GsfOutfileMSOle const *b)
{
- /* According to the docs length is more important than lexical order */
- char const *a_name = gsf_output_name ((GsfOutput const *)a);
- char const *b_name = gsf_output_name ((GsfOutput const *)b);
-
- /* be anal */
- if (a_name == NULL)
- return (b_name == NULL) ? 0 : -1;
- else if (b_name == NULL)
- return 1;
- else {
- unsigned a_len = g_utf8_strlen (a_name, -1);
- unsigned b_len = g_utf8_strlen (b_name, -1);
-
- if (a_len != b_len)
- return a_len - b_len;
- return g_utf8_collate (a_name, b_name);
- }
+ return gsf_msole_sorting_key_cmp (a->key, b->key);
+}
+
+static void
+make_sorting_name (GsfOutfileMSOle *ole,
+ G_GNUC_UNUSED GParamSpec *pspec,
+ G_GNUC_UNUSED gpointer user)
+{
+ const char *name = gsf_output_name (GSF_OUTPUT (ole));
+ gsf_msole_sorting_key_free (ole->key);
+ ole->key = gsf_msole_sorting_key_new (name);
}
static void
@@ -648,6 +649,22 @@ gsf_outfile_msole_init (GObject *obj)
memset (ole->clsid, 0, sizeof (ole->clsid));
}
+static GObject*
+gsf_outfile_msole_constructor (GType type,
+ guint n_construct_properties,
+ GObjectConstructParam *construct_params)
+{
+ GObject *obj = parent_class->constructor (type,
+ n_construct_properties,
+ construct_params);
+ GsfOutfileMSOle *ole = (GsfOutfileMSOle *)obj;
+ g_signal_connect (obj,
+ "notify::name",
+ G_CALLBACK (make_sorting_name), NULL);
+ make_sorting_name (ole, NULL, NULL);
+ return obj;
+}
+
static void
gsf_outfile_msole_class_init (GObjectClass *gobject_class)
{
@@ -655,6 +672,7 @@ gsf_outfile_msole_class_init (GObjectClass *gobject_class)
GsfOutfileClass *outfile_class = GSF_OUTFILE_CLASS (gobject_class);
gobject_class->finalize = gsf_outfile_msole_finalize;
+ gobject_class->constructor = gsf_outfile_msole_constructor;
output_class->Close = gsf_outfile_msole_close;
output_class->Seek = gsf_outfile_msole_seek;
output_class->Write = gsf_outfile_msole_write;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]