From 72d0f45460ff69fe68ec3cb61a6fa776fdbbff7c Mon Sep 17 00:00:00 2001 From: Victor Ma Date: Thu, 10 Apr 2025 17:36:25 -0400 Subject: [PATCH 01/12] Add IPUZ sniffing --- src/puzzle-downloader.c | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/src/puzzle-downloader.c b/src/puzzle-downloader.c index 772f9442..dd3cf718 100644 --- a/src/puzzle-downloader.c +++ b/src/puzzle-downloader.c @@ -664,6 +664,28 @@ file_dialog_copy_ready_cb (GFile *source, } } +static gboolean +file_contains_str (const gchar *uri, const gchar *str) +{ + g_autoptr (GFile) file = NULL; + g_autofree gchar *contents = NULL; + g_autoptr (GError) error = NULL; + + file = g_file_new_for_uri (uri); + if (!g_file_load_contents (file, NULL, &contents, NULL, NULL, &error)) + { + g_warning ("Could not read file: %s\n", error->message); + return FALSE; + } + return strstr (contents, str) != NULL; +} + +static gboolean +file_is_ipuz (const gchar *uri) +{ + return file_contains_str (uri, "http://ipuz.org/v"); +} + static void start_file_import (PuzzleDownloader *downloader) { @@ -686,7 +708,8 @@ start_file_import (PuzzleDownloader *downloader) { g_autofree char *filename = NULL; filename = g_filename_from_uri (downloader->import_target_uri, NULL, NULL); - if (filename != NULL && g_str_has_suffix (filename, ".ipuz")) + if (filename != NULL && (g_str_has_suffix (filename, ".ipuz") + || file_is_ipuz (downloader->import_target_uri))) { g_signal_emit (downloader, obj_signals [FINISHED], 0, downloader->import_target_uri, FALSE); g_clear_pointer (&downloader->import_target_uri, g_free); -- GitLab From 1a1fe5cdd773e43640d8864ae98f3c56723e698b Mon Sep 17 00:00:00 2001 From: Victor Ma Date: Thu, 10 Apr 2025 19:38:04 -0400 Subject: [PATCH 02/12] Add file format detection function --- src/puzzle-downloader.c | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/src/puzzle-downloader.c b/src/puzzle-downloader.c index dd3cf718..80b0d692 100644 --- a/src/puzzle-downloader.c +++ b/src/puzzle-downloader.c @@ -664,8 +664,8 @@ file_dialog_copy_ready_cb (GFile *source, } } -static gboolean -file_contains_str (const gchar *uri, const gchar *str) +static DownloaderFormat +file_format_from_uri (const gchar *uri) { g_autoptr (GFile) file = NULL; g_autofree gchar *contents = NULL; @@ -675,15 +675,18 @@ file_contains_str (const gchar *uri, const gchar *str) if (!g_file_load_contents (file, NULL, &contents, NULL, NULL, &error)) { g_warning ("Could not read file: %s\n", error->message); - return FALSE; + return DOWNLOADER_FORMAT_UNKNOWN; } - return strstr (contents, str) != NULL; -} -static gboolean -file_is_ipuz (const gchar *uri) -{ - return file_contains_str (uri, "http://ipuz.org/v"); + if (strstr (contents, "http://ipuz.org/v") != NULL) + return DOWNLOADER_FORMAT_IPUZ; + else if (strstr (contents, "ACROSS&DOWN") != NULL) + return DOWNLOADER_FORMAT_PUZ; // strlen trick + else if (strstr (contents, "import_target_uri != NULL); + printf("\n\n\n%d\n\n\n", file_format_from_uri(downloader->import_target_uri)); + /* We can short circuit the download/conversion step if the file is * local and it's a .ipuz file. */ /* FIXME(mime): It would be nice to do mime-sniffing here for puz @@ -708,8 +713,7 @@ start_file_import (PuzzleDownloader *downloader) { g_autofree char *filename = NULL; filename = g_filename_from_uri (downloader->import_target_uri, NULL, NULL); - if (filename != NULL && (g_str_has_suffix (filename, ".ipuz") - || file_is_ipuz (downloader->import_target_uri))) + if (filename != NULL && g_str_has_suffix (filename, ".ipuz")) { g_signal_emit (downloader, obj_signals [FINISHED], 0, downloader->import_target_uri, FALSE); g_clear_pointer (&downloader->import_target_uri, g_free); -- GitLab From 726f3fcd291c18342a512efc570d917f6f8ac994 Mon Sep 17 00:00:00 2001 From: Victor Ma Date: Thu, 10 Apr 2025 20:05:30 -0400 Subject: [PATCH 03/12] Sniff instead of checking file extension --- src/puzzle-downloader.c | 34 +++++++++++++--------------------- 1 file changed, 13 insertions(+), 21 deletions(-) diff --git a/src/puzzle-downloader.c b/src/puzzle-downloader.c index 80b0d692..b9ff5a41 100644 --- a/src/puzzle-downloader.c +++ b/src/puzzle-downloader.c @@ -665,9 +665,8 @@ file_dialog_copy_ready_cb (GFile *source, } static DownloaderFormat -file_format_from_uri (const gchar *uri) +file_format_from_file (GFile *file) { - g_autoptr (GFile) file = NULL; g_autofree gchar *contents = NULL; g_autoptr (GError) error = NULL; @@ -680,7 +679,8 @@ file_format_from_uri (const gchar *uri) if (strstr (contents, "http://ipuz.org/v") != NULL) return DOWNLOADER_FORMAT_IPUZ; - else if (strstr (contents, "ACROSS&DOWN") != NULL) + else if ((strstr (contents, "ACROSS&DOWN") != NULL) + && (strlen (contents) == 13)) return DOWNLOADER_FORMAT_PUZ; // strlen trick else if (strstr (contents, "import_target_uri != NULL); - printf("\n\n\n%d\n\n\n", file_format_from_uri(downloader->import_target_uri)); - /* We can short circuit the download/conversion step if the file is * local and it's a .ipuz file. */ - /* FIXME(mime): It would be nice to do mime-sniffing here for puz - * files, at least */ /* FIXME(gio): g_file_query_filesystem_info might be a better * way to find out if it's local */ if (strcmp (g_uri_peek_scheme (downloader->import_target_uri), "file") == 0) { - g_autofree char *filename = NULL; - filename = g_filename_from_uri (downloader->import_target_uri, NULL, NULL); - if (filename != NULL && g_str_has_suffix (filename, ".ipuz")) + downloader->format = file_format_from_uri (downloader->import_target_uri); + if (downloader->format == DOWNLOADER_FORMAT_IPUZ) { g_signal_emit (downloader, obj_signals [FINISHED], 0, downloader->import_target_uri, FALSE); g_clear_pointer (&downloader->import_target_uri, g_free); @@ -731,17 +732,8 @@ start_file_import (PuzzleDownloader *downloader) g_warning ("Unable to create a tmp file: %s", error->message); return; } - /* FIXME(mime): we really need to add sniffing */ - basename = g_file_get_basename (source); - if (g_str_has_suffix (basename, ".puz")) - downloader->format = DOWNLOADER_FORMAT_PUZ; - else if (g_str_has_suffix (basename, ".jpz") || - g_str_has_suffix (basename, ".xml")) - downloader->format = DOWNLOADER_FORMAT_JPZ; - else if (g_str_has_suffix (basename, ".xd")) - downloader->format = DOWNLOADER_FORMAT_XD; - else - downloader->format = DOWNLOADER_FORMAT_IPUZ; + if (downloader->format == NULL) + downloader->format = file_format_from_file (destination); if (downloader->format != DOWNLOADER_FORMAT_IPUZ) downloader->temp_file = g_file_get_path (destination); -- GitLab From b83445cf89f8e93f55bbe73b55824e3c1f08bb1e Mon Sep 17 00:00:00 2001 From: Victor Ma Date: Thu, 10 Apr 2025 20:53:37 -0400 Subject: [PATCH 04/12] Handle remote/non-ipuz case --- src/puzzle-downloader.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/puzzle-downloader.c b/src/puzzle-downloader.c index b9ff5a41..4c23f2c7 100644 --- a/src/puzzle-downloader.c +++ b/src/puzzle-downloader.c @@ -649,6 +649,7 @@ file_dialog_copy_ready_cb (GFile *source, downloader_cancel_timeout_remove (downloader); g_clear_pointer (&downloader->cancel_dialog, adw_dialog_close); + downloader->format = file_format_from_file (source); if (downloader->format == DOWNLOADER_FORMAT_IPUZ) { @@ -732,13 +733,9 @@ start_file_import (PuzzleDownloader *downloader) g_warning ("Unable to create a tmp file: %s", error->message); return; } - if (downloader->format == NULL) - downloader->format = file_format_from_file (destination); - - if (downloader->format != DOWNLOADER_FORMAT_IPUZ) - downloader->temp_file = g_file_get_path (destination); downloader_cancel_timeout_add (downloader, 2000, (GSourceFunc) downloader_cancel_timeout_cb); + downloader->temp_file = g_file_get_path (destination); downloader->wait_cancellable = g_cancellable_new (); flags = G_FILE_COPY_OVERWRITE; -- GitLab From cc4e342eca9ecbd43823a9a5ae1a1cdce9b4023f Mon Sep 17 00:00:00 2001 From: Victor Ma Date: Thu, 10 Apr 2025 21:01:24 -0400 Subject: [PATCH 05/12] Edit sniffing function --- src/puzzle-downloader.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/puzzle-downloader.c b/src/puzzle-downloader.c index 4c23f2c7..7033a4b5 100644 --- a/src/puzzle-downloader.c +++ b/src/puzzle-downloader.c @@ -680,12 +680,13 @@ file_format_from_file (GFile *file) if (strstr (contents, "http://ipuz.org/v") != NULL) return DOWNLOADER_FORMAT_IPUZ; - else if ((strstr (contents, "ACROSS&DOWN") != NULL) - && (strlen (contents) == 13)) - return DOWNLOADER_FORMAT_PUZ; // strlen trick + else if ((strlen (contents) == 13) + && (strstr (contents, "ACROSS&DOWN") != NULL)) + return DOWNLOADER_FORMAT_PUZ; else if (strstr (contents, " Date: Thu, 10 Apr 2025 21:09:09 -0400 Subject: [PATCH 06/12] Add filters and reorder functions --- src/puzzle-downloader.c | 56 +++++++++++++++++++++++------------------ 1 file changed, 31 insertions(+), 25 deletions(-) diff --git a/src/puzzle-downloader.c b/src/puzzle-downloader.c index 7033a4b5..b14a2532 100644 --- a/src/puzzle-downloader.c +++ b/src/puzzle-downloader.c @@ -641,37 +641,12 @@ run_command (PuzzleDownloader *downloader, * Input Dialogs */ -static void -file_dialog_copy_ready_cb (GFile *source, - GAsyncResult *res, - PuzzleDownloader *downloader) -{ - - downloader_cancel_timeout_remove (downloader); - g_clear_pointer (&downloader->cancel_dialog, adw_dialog_close); - downloader->format = file_format_from_file (source); - - if (downloader->format == DOWNLOADER_FORMAT_IPUZ) - { - g_autofree gchar *uri = NULL; - - uri = g_filename_to_uri (downloader->temp_file, NULL, NULL); - g_signal_emit (downloader, obj_signals [FINISHED], 0, uri, TRUE); - g_clear_pointer (&downloader->temp_file, g_free); - } - else - { - convert_puz_to_ipuz (downloader); - } -} - static DownloaderFormat file_format_from_file (GFile *file) { g_autofree gchar *contents = NULL; g_autoptr (GError) error = NULL; - file = g_file_new_for_uri (uri); if (!g_file_load_contents (file, NULL, &contents, NULL, NULL, &error)) { g_warning ("Could not read file: %s\n", error->message); @@ -697,6 +672,30 @@ file_format_from_uri (const gchar *uri) return file_format_from_file (g_file_new_for_uri (uri)); } +static void +file_dialog_copy_ready_cb (GFile *source, + GAsyncResult *res, + PuzzleDownloader *downloader) +{ + + downloader_cancel_timeout_remove (downloader); + g_clear_pointer (&downloader->cancel_dialog, adw_dialog_close); + downloader->format = file_format_from_file (source); + + if (downloader->format == DOWNLOADER_FORMAT_IPUZ) + { + g_autofree gchar *uri = NULL; + + uri = g_filename_to_uri (downloader->temp_file, NULL, NULL); + g_signal_emit (downloader, obj_signals [FINISHED], 0, uri, TRUE); + g_clear_pointer (&downloader->temp_file, g_free); + } + else + { + convert_puz_to_ipuz (downloader); + } +} + static void start_file_import (PuzzleDownloader *downloader) { @@ -814,6 +813,7 @@ run_file_dialog (PuzzleDownloader *downloader) gtk_file_filter_set_name (filter, _("Puzzle Solver Puzzles (.jpuz)")); gtk_file_filter_add_pattern (filter, "*.jpz"); gtk_file_filter_add_pattern (filter, "*.jpuz"); + gtk_file_filter_add_pattern (filter, "*.xml"); g_list_store_append (filters, filter); g_object_unref (filter); @@ -823,6 +823,12 @@ run_file_dialog (PuzzleDownloader *downloader) g_list_store_append (filters, filter); g_object_unref (filter); + filter = gtk_file_filter_new(); + gtk_file_filter_set_name(filter, "All Files"); + gtk_file_filter_add_pattern(filter, "*"); + g_list_store_append (filters, filter); + g_object_unref (filter); + gtk_file_dialog_set_filters (file_dialog, G_LIST_MODEL (filters)); gtk_file_dialog_open (file_dialog, downloader->parent_window, NULL, -- GitLab From d5b30a89c4faf04478d584cee09f9655e13c6e40 Mon Sep 17 00:00:00 2001 From: Victor Ma Date: Thu, 10 Apr 2025 23:13:34 -0400 Subject: [PATCH 07/12] Use autoptr --- src/puzzle-downloader.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/puzzle-downloader.c b/src/puzzle-downloader.c index b14a2532..aa6c5848 100644 --- a/src/puzzle-downloader.c +++ b/src/puzzle-downloader.c @@ -669,7 +669,9 @@ file_format_from_file (GFile *file) static DownloaderFormat file_format_from_uri (const gchar *uri) { - return file_format_from_file (g_file_new_for_uri (uri)); + g_autoptr (GFile) file = NULL; + file = g_file_new_for_uri (uri); + return file_format_from_file (file); } static void @@ -681,6 +683,7 @@ file_dialog_copy_ready_cb (GFile *source, downloader_cancel_timeout_remove (downloader); g_clear_pointer (&downloader->cancel_dialog, adw_dialog_close); downloader->format = file_format_from_file (source); + printf("\n\n\n%s\n\n\n", format_name[downloader->format]); if (downloader->format == DOWNLOADER_FORMAT_IPUZ) { -- GitLab From 59d26e95350a1d861cfb3f5662c786d35f3d6253 Mon Sep 17 00:00:00 2001 From: Victor Ma Date: Sat, 12 Apr 2025 10:47:00 -0400 Subject: [PATCH 08/12] Make small fix --- src/puzzle-downloader.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/puzzle-downloader.c b/src/puzzle-downloader.c index aa6c5848..67a0c38b 100644 --- a/src/puzzle-downloader.c +++ b/src/puzzle-downloader.c @@ -682,8 +682,9 @@ file_dialog_copy_ready_cb (GFile *source, downloader_cancel_timeout_remove (downloader); g_clear_pointer (&downloader->cancel_dialog, adw_dialog_close); - downloader->format = file_format_from_file (source); - printf("\n\n\n%s\n\n\n", format_name[downloader->format]); + + if (downloader->format == NULL) + downloader->format = file_format_from_file (source); if (downloader->format == DOWNLOADER_FORMAT_IPUZ) { @@ -795,6 +796,7 @@ run_file_dialog (PuzzleDownloader *downloader) gtk_file_filter_add_pattern (filter, "*.puz"); gtk_file_filter_add_pattern (filter, "*.xml"); gtk_file_filter_add_pattern (filter, "*.jpz"); + gtk_file_filter_add_pattern (filter, "*.jpuz"); gtk_file_filter_add_pattern (filter, "*.xd"); g_list_store_append (filters, filter); gtk_file_dialog_set_default_filter (file_dialog, filter); @@ -816,7 +818,6 @@ run_file_dialog (PuzzleDownloader *downloader) gtk_file_filter_set_name (filter, _("Puzzle Solver Puzzles (.jpuz)")); gtk_file_filter_add_pattern (filter, "*.jpz"); gtk_file_filter_add_pattern (filter, "*.jpuz"); - gtk_file_filter_add_pattern (filter, "*.xml"); g_list_store_append (filters, filter); g_object_unref (filter); -- GitLab From 5a313c009349addac75f5929d3db339d44804771 Mon Sep 17 00:00:00 2001 From: Victor Ma Date: Sat, 12 Apr 2025 17:13:05 -0400 Subject: [PATCH 09/12] Remove bad NULL check --- src/puzzle-downloader.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/puzzle-downloader.c b/src/puzzle-downloader.c index 67a0c38b..a06ca07f 100644 --- a/src/puzzle-downloader.c +++ b/src/puzzle-downloader.c @@ -683,8 +683,7 @@ file_dialog_copy_ready_cb (GFile *source, downloader_cancel_timeout_remove (downloader); g_clear_pointer (&downloader->cancel_dialog, adw_dialog_close); - if (downloader->format == NULL) - downloader->format = file_format_from_file (source); + downloader->format = file_format_from_file (source); if (downloader->format == DOWNLOADER_FORMAT_IPUZ) { -- GitLab From bcd85ce95b439025b6c2a4d18d089e1719a6493d Mon Sep 17 00:00:00 2001 From: Victor Ma Date: Sun, 13 Apr 2025 13:10:21 -0400 Subject: [PATCH 10/12] Make requested changes --- src/puzzle-downloader.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/puzzle-downloader.c b/src/puzzle-downloader.c index a06ca07f..8a808335 100644 --- a/src/puzzle-downloader.c +++ b/src/puzzle-downloader.c @@ -653,15 +653,15 @@ file_format_from_file (GFile *file) return DOWNLOADER_FORMAT_UNKNOWN; } - if (strstr (contents, "http://ipuz.org/v") != NULL) + if (strstr (contents, "http://ipuz.org/v2") != NULL) return DOWNLOADER_FORMAT_IPUZ; else if ((strlen (contents) == 13) && (strstr (contents, "ACROSS&DOWN") != NULL)) return DOWNLOADER_FORMAT_PUZ; - else if (strstr (contents, " Date: Sun, 13 Apr 2025 20:02:26 -0400 Subject: [PATCH 11/12] Use g_strcmp0 for ACROSS&DOWN --- src/puzzle-downloader.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/puzzle-downloader.c b/src/puzzle-downloader.c index 8a808335..a000b645 100644 --- a/src/puzzle-downloader.c +++ b/src/puzzle-downloader.c @@ -656,7 +656,7 @@ file_format_from_file (GFile *file) if (strstr (contents, "http://ipuz.org/v2") != NULL) return DOWNLOADER_FORMAT_IPUZ; else if ((strlen (contents) == 13) - && (strstr (contents, "ACROSS&DOWN") != NULL)) + && (g_strcmp0 (contents + 2, "ACROSS&DOWN") == 0)) return DOWNLOADER_FORMAT_PUZ; else if (g_ascii_strncasecmp (contents, " Date: Sun, 13 Apr 2025 20:14:14 -0400 Subject: [PATCH 12/12] Add comments explaining sniffing strings --- src/puzzle-downloader.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/puzzle-downloader.c b/src/puzzle-downloader.c index a000b645..e819435a 100644 --- a/src/puzzle-downloader.c +++ b/src/puzzle-downloader.c @@ -653,13 +653,19 @@ file_format_from_file (GFile *file) return DOWNLOADER_FORMAT_UNKNOWN; } + /* IPUZ files specify their IPUZ version with a URL to the spec. */ if (strstr (contents, "http://ipuz.org/v2") != NULL) return DOWNLOADER_FORMAT_IPUZ; + /* PUZ files contain a null-terminated magic string, "ACROSS&DOWN". */ + /* Because it's null-terminated, we can use g_strcmp0. */ else if ((strlen (contents) == 13) && (g_strcmp0 (contents + 2, "ACROSS&DOWN") == 0)) return DOWNLOADER_FORMAT_PUZ; + /* JPZ files begin with an XML header. */ else if (g_ascii_strncasecmp (contents, "