From c4053506e834660403da44c4f1185076b5b72133 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Aliste?= Date: Sun, 10 Nov 2013 11:10:22 -0200 Subject: [PATCH 1/2] Compress and Escape strings in Named Destinations Named Destinations can be "byte strings", which means that they might include non-printa le characters and embed nul values. We need to escape them because otherwise when copying to glib we looss everything after the first '\0' character. --- glib/poppler-action.cc | 40 ++++++++++++++++++++++++++++++++++++++-- glib/poppler-action.h | 4 +++- glib/poppler-document.cc | 47 +++++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 86 insertions(+), 5 deletions(-) diff --git a/glib/poppler-action.cc b/glib/poppler-action.cc index 384530f..c6d3a44 100644 --- a/glib/poppler-action.cc +++ b/glib/poppler-action.cc @@ -315,6 +315,43 @@ dest_new_goto (PopplerDocument *document, return dest; } +/** + * named dest names can be binary and embed '\0'. Thus, we escape the string + * we may not use g_escape_string because it does not deal with embedded '\0') + */ +static gchar * +escape_string (const gchar *source, + int length) +{ + const guchar *p; + gchar *dest; + gchar *q; + gint i; + + p = (guchar *) source; + /* Each source byte needs maximally 2 destination chars (\\ or \0) */ + q = dest = (gchar *) g_malloc (length * 2 + 1); + + for (i = 0; i < length; ++i) { + switch (*p) { + case '\0': + *q++ = '\\'; + *q++ = '0'; + break; + case '\\': + *q++ = '\\'; + *q++ = '\\'; + break; + default: + *q++ = *p; + break; + } + p++; + } + *q = 0; + return dest; +} + static PopplerDest * dest_new_named (GooString *named_dest) { @@ -326,9 +363,8 @@ dest_new_named (GooString *named_dest) dest->type = POPPLER_DEST_UNKNOWN; return dest; } - dest->type = POPPLER_DEST_NAMED; - dest->named_dest = g_strdup (named_dest->getCString ()); + dest->named_dest = escape_string (named_dest->getCString (), named_dest->getLength ()); return dest; } diff --git a/glib/poppler-action.h b/glib/poppler-action.h index 2a5d7f8..a2a49e4 100644 --- a/glib/poppler-action.h +++ b/glib/poppler-action.h @@ -239,7 +239,9 @@ struct _PopplerActionNamed PopplerActionType type; gchar *title; - gchar *named_dest; + gchar *named_dest; /* FIXME: The proper struct here should be a GString + so it can contain embedded '\0' values + but this would change the API */ }; struct _PopplerActionMovie diff --git a/glib/poppler-document.cc b/glib/poppler-document.cc index 61d92e8..67a2f99 100644 --- a/glib/poppler-document.cc +++ b/glib/poppler-document.cc @@ -672,12 +672,51 @@ poppler_document_get_attachments (PopplerDocument *document) return g_list_reverse (retval); } +static gchar * +compress_string (const gchar *source, int *length) +{ + const gchar *p = source; + gchar *dest; + gchar *q; + int len; + + g_return_val_if_fail (source != NULL, NULL); + + len = strlen (source); + dest = (gchar *) g_malloc (len + 1); + q = dest; + + while (*p) { + if (*p == '\\') { + p++; + len--; + if (*p == '0') + *q++ = '\0'; + else if (*p == '\\') + *q++ = '\\'; + else + g_assert ("Not asserted"); + } else + *q++ = *p; + + p++; + } + *q = 0; + + if (length) + *length = len; + + return dest; +} + /** * poppler_document_find_dest: * @document: A #PopplerDocument * @link_name: a named destination * - * Finds named destination @link_name in @document + * Finds named destination @link_name in @document. Some documents + * may have named destinations which contain embedded '\0' chars. Since @link_name + * is a standard string, you need to escape '\0' and '\\' chars. * * Return value: The #PopplerDest destination or %NULL if * @link_name is not a destination. Returned value must @@ -690,11 +729,15 @@ poppler_document_find_dest (PopplerDocument *document, PopplerDest *dest = NULL; LinkDest *link_dest = NULL; GooString *g_link_name; + int length; + gchar *name_compressed; g_return_val_if_fail (POPPLER_IS_DOCUMENT (document), NULL); g_return_val_if_fail (link_name != NULL, NULL); - g_link_name = new GooString (link_name); + name_compressed = compress_string (link_name, &length); + g_link_name = new GooString (name_compressed, length); + g_free (name_compressed); if (g_link_name) { link_dest = document->doc->findDest (g_link_name); -- 1.8.4.2