diff --git a/src/extension.c b/src/extension.c index b0ff47a9..fb80a418 100644 --- a/src/extension.c +++ b/src/extension.c @@ -17,6 +17,7 @@ #include "extension.h" #include "file.h" #include "lang.h" +#include "uri.h" typedef struct _I7ExtensionPrivate I7ExtensionPrivate; struct _I7ExtensionPrivate @@ -163,7 +164,9 @@ static void update_recent_extension_file(I7Extension *self, GFile *file, gboolean readonly) { GtkRecentManager *manager = gtk_recent_manager_get_default(); - char *uri = g_file_get_uri(file); + char *raw_uri = g_file_get_uri(file); + char *uri = get_uri_without_apostrophes(raw_uri); + g_free(raw_uri); /* We use the groups "inform7_project", "inform7_extension", and "inform7_builtin" to determine how to open a file from the recent manager */ @@ -198,7 +201,9 @@ static void remove_recent_extension_file(GFile *file) { GtkRecentManager *manager = gtk_recent_manager_get_default(); - char *uri = g_file_get_uri(file); + char *raw_uri = g_file_get_uri(file); + char *uri = get_uri_without_apostrophes(raw_uri); + g_free(raw_uri); gtk_recent_manager_remove_item(manager, uri, NULL); /* ignore error */ g_free(uri); diff --git a/src/meson.build b/src/meson.build index ee4060bf..f80f0d16 100644 --- a/src/meson.build +++ b/src/meson.build @@ -23,7 +23,7 @@ gui = static_library('inform7gui', 'actions.c', 'app.c', 'app-colorscheme.c', 'source-view.c', 'spawn.c', 'story.c', 'story-compile.c', 'story-game.c', 'story-index.c', 'story-results.c', 'story-settings.c', 'story-skein.c', 'story-source.c', 'story-transcript.c', 'transcript-diff.c', - 'transcript-entry.c', 'welcomedialog.c', resources, resources_generated, + 'transcript-entry.c', 'uri.c', 'welcomedialog.c', resources, resources_generated, include_directories: top_include, dependencies: [libm, libxml, glib, gio, gdk, gtk, gtksourceview, gspell, goocanvas, plist, webkit, ratify, libchimara]) diff --git a/src/story.c b/src/story.c index 6c3d5535..db83dcda 100644 --- a/src/story.c +++ b/src/story.c @@ -34,6 +34,7 @@ #include "source-view.h" #include "story.h" #include "transcript-entry.h" +#include "uri.h" enum { PROP_0, @@ -364,7 +365,9 @@ static void update_recent_story_file(I7Story *self, GFile *file) { GtkRecentManager *manager = gtk_recent_manager_get_default(); - char *uri = get_recent_uri_for_story_file(file); + char *raw_uri = get_recent_uri_for_story_file(file); + char *uri = get_uri_without_apostrophes(raw_uri); + g_free(raw_uri); /* We use the groups "inform7_project", "inform7_extension", and "inform7_builtin" to determine how to open a file from the recent manager */ @@ -402,7 +405,9 @@ static void remove_recent_story_file(FileRemoveFromRecent *file) { GtkRecentManager *manager = gtk_recent_manager_get_default(); - char *uri = get_recent_uri_for_story_file(file); + char *raw_uri = get_recent_uri_for_story_file(file); + char *uri = get_uri_without_apostrophes(raw_uri); + g_free(raw_uri); gtk_recent_manager_remove_item(manager, uri, NULL); /* ignore error */ g_free(uri); diff --git a/src/uri.c b/src/uri.c new file mode 100644 index 00000000..aadd2863 --- /dev/null +++ b/src/uri.c @@ -0,0 +1,62 @@ +/* + * SPDX-License-Identifier: GPL-3.0-or-later + * SPDX-FileCopyrightText: 2022 Nathanael Nerode + */ + + +#include "config.h" + +#include +#include + +#include "uri.h" + +/* Given an otherwise-escaped URI containing apostrophes from g_file_get_uri, + * return a URI with the apostrophes replaced with %27 -- which that doesn't do. + * This is g_malloc'ed, just like the return from g_file_get_uri is. + * g_free it when you're done with it. + */ +char * get_uri_without_apostrophes(char * raw_uri) +{ + char * cooked_uri; /* The return value */ + if (raw_uri == NULL) { + /* don't dereference a null pointer -- this is an error state */ + return NULL; + } + + /* First, count the apostrophes and get the raw string length, for malloc */ + size_t apostrophe_count = 0; + size_t char_count = 0; + while (raw_uri[char_count] != '\0') { + if (raw_uri[char_count] == '\'') { + apostrophe_count++; + } + char_count++; + } + size_t cooked_bytes_needed = char_count + apostrophe_count * 2 + 1; + cooked_uri = (char *) g_malloc(cooked_bytes_needed); + if (cooked_uri == NULL) { + /* malloc failed -- this is an error state */ + return NULL; + } + + /* Second, do the copying of the string */ + size_t raw_char_count = 0; + size_t cooked_char_count = 0; + while (raw_uri[raw_char_count] != '\0') { + if (raw_uri[raw_char_count] == '\'') { + cooked_uri[cooked_char_count] = '%'; + cooked_char_count++; + cooked_uri[cooked_char_count] = '2'; + cooked_char_count++; + cooked_uri[cooked_char_count] = '7'; + cooked_char_count++; + } else { + cooked_uri[cooked_char_count] = raw_uri[raw_char_count]; + cooked_char_count++; + } + raw_char_count++; + } + cooked_uri[cooked_char_count] = '\0'; /* Don't forget to terminate the string */ + return cooked_uri; +} diff --git a/src/uri.h b/src/uri.h new file mode 100644 index 00000000..c452ff74 --- /dev/null +++ b/src/uri.h @@ -0,0 +1,15 @@ +/* + * SPDX-License-Identifier: GPL-3.0-or-later + * SPDX-FileCopyrightText: 2022 Nathanael Nerode + */ + +#ifndef URI_H +#define URI_H + +#include "config.h" + +#include + +char * get_uri_without_apostrophes(char * raw_uri); + +#endif /* URI_H */