[gnome-desktop] thumbnail: Split off running the script
- From: Bastien Nocera <hadess src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-desktop] thumbnail: Split off running the script
- Date: Fri, 21 Jul 2017 11:24:53 +0000 (UTC)
commit c1956f35bd1a9170e433d116f36e63d58b6ff826
Author: Bastien Nocera <hadess hadess net>
Date: Thu Jul 20 20:51:09 2017 +0200
thumbnail: Split off running the script
Move most of the script command generation to a separate file, making
the function return a GBytes from a successful thumbnailer run, so as to
avoid having to clean up temporary files from the thumbnailer run.
Note that it changes a few subtle things which shouldn't be a problem in
practice, but, as a corner case, might have been used by applications:
- Thumbnailers must output PNG images. pixbuf_new_from_bytes() could
have been made more complicated to handle all images, and then we would
restrict the thumbnailer output format separately, but it makes no sense
to write complicated code to remove it in the next commit.
- URIs which have no backing path are not supported. This will likely
cause problems for thumbnailing remote shares on OSes which lack
gvfsd-fuse. Support could be re-added in the future.
https://bugzilla.gnome.org/show_bug.cgi?id=774497
libgnome-desktop/Makefile.am | 4 +-
libgnome-desktop/gnome-desktop-thumbnail-script.c | 244 +++++++++++++++++++++
libgnome-desktop/gnome-desktop-thumbnail-script.h | 38 ++++
libgnome-desktop/gnome-desktop-thumbnail.c | 185 +++-------------
4 files changed, 321 insertions(+), 150 deletions(-)
---
diff --git a/libgnome-desktop/Makefile.am b/libgnome-desktop/Makefile.am
index 9c4da15..a60aac8 100644
--- a/libgnome-desktop/Makefile.am
+++ b/libgnome-desktop/Makefile.am
@@ -42,7 +42,9 @@ libgnome_desktop_3_la_SOURCES = \
gnome-datetime-source.c \
gnome-rr-private.h \
default-input-sources.h \
- meta-xrandr-shared.h
+ meta-xrandr-shared.h \
+ gnome-desktop-thumbnail-script.c\
+ gnome-desktop-thumbnail-script.h
dbus_xrandr_built_sources = meta-dbus-xrandr.c meta-dbus-xrandr.h
diff --git a/libgnome-desktop/gnome-desktop-thumbnail-script.c
b/libgnome-desktop/gnome-desktop-thumbnail-script.c
new file mode 100644
index 0000000..87319bc
--- /dev/null
+++ b/libgnome-desktop/gnome-desktop-thumbnail-script.c
@@ -0,0 +1,244 @@
+/*
+ * Copyright (C) 2002, 2017 Red Hat, Inc.
+ * Copyright (C) 2010 Carlos Garcia Campos <carlosgc gnome org>
+ *
+ * This file is part of the Gnome Library.
+ *
+ * The Gnome Library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * The Gnome Library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with the Gnome Library; see the file COPYING.LIB. If not,
+ * write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * Authors: Alexander Larsson <alexl redhat com>
+ * Carlos Garcia Campos <carlosgc gnome org>
+ * Bastien Nocera <hadess hadess net>
+ */
+
+#include "config.h"
+
+#include <gio/gio.h>
+#include <glib/gstdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include "gnome-desktop-thumbnail-script.h"
+
+typedef struct {
+ char *infile;
+ char *outfile;
+} ScriptExec;
+
+static char *
+expand_thumbnailing_elem (const char *elem,
+ const int size,
+ const char *inuri,
+ const char *outfile,
+ gboolean *got_input,
+ gboolean *got_output)
+{
+ GString *str;
+ const char *p, *last;
+ char *localfile;
+
+ str = g_string_new (NULL);
+
+ last = elem;
+ while ((p = strchr (last, '%')) != NULL)
+ {
+ g_string_append_len (str, last, p - last);
+ p++;
+
+ switch (*p) {
+ case 'u':
+ g_string_append (str, inuri);
+ *got_input = TRUE;
+ p++;
+ break;
+ case 'i':
+ localfile = g_filename_from_uri (inuri, NULL, NULL);
+ if (localfile)
+ {
+ g_string_append (str, localfile);
+ *got_input = TRUE;
+ g_free (localfile);
+ }
+ p++;
+ break;
+ case 'o':
+ g_string_append (str, outfile);
+ *got_output = TRUE;
+ p++;
+ break;
+ case 's':
+ g_string_append_printf (str, "%d", size);
+ p++;
+ break;
+ case '%':
+ g_string_append_c (str, '%');
+ p++;
+ break;
+ case 0:
+ default:
+ break;
+ }
+ last = p;
+ }
+ g_string_append (str, last);
+
+ return g_string_free (str, FALSE);
+}
+
+static char **
+expand_thumbnailing_script (const char *cmd,
+ ScriptExec *script,
+ int size,
+ GError **error)
+{
+ GPtrArray *array;
+ g_auto(GStrv) cmd_elems = NULL;
+ guint i;
+ gboolean got_in, got_out;
+ g_autofree char *sandboxed_path = NULL;
+
+ if (!g_shell_parse_argv (cmd, NULL, &cmd_elems, error))
+ return NULL;
+
+ array = g_ptr_array_new_with_free_func (g_free);
+
+ got_in = got_out = FALSE;
+ for (i = 0; cmd_elems[i] != NULL; i++)
+ {
+ char *expanded;
+
+ expanded = expand_thumbnailing_elem (cmd_elems[i],
+ size,
+ script->infile,
+ script->outfile,
+ &got_in,
+ &got_out);
+
+ g_ptr_array_add (array, expanded);
+ }
+
+ if (!got_in)
+ {
+ g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+ "Input file could not be set");
+ goto bail;
+ }
+ else if (!got_out)
+ {
+ g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+ "Output file could not be set");
+ goto bail;
+ }
+
+ g_ptr_array_add (array, NULL);
+
+ return (char **) g_ptr_array_free (array, FALSE);
+
+bail:
+ g_ptr_array_free (array, TRUE);
+ return NULL;
+}
+
+static void
+script_exec_free (ScriptExec *exec)
+{
+ g_free (exec->infile);
+ if (exec->outfile)
+ {
+ g_unlink (exec->outfile);
+ g_free (exec->outfile);
+ }
+ g_free (exec);
+}
+
+static ScriptExec *
+script_exec_new (const char *uri)
+{
+ ScriptExec *exec;
+ g_autoptr(GFile) file = NULL;
+ int fd;
+ g_autofree char *tmpname = NULL;
+
+ exec = g_new0 (ScriptExec, 1);
+ file = g_file_new_for_uri (uri);
+
+ exec->infile = g_file_get_path (file);
+ if (!exec->infile)
+ goto bail;
+
+ fd = g_file_open_tmp (".gnome_desktop_thumbnail.XXXXXX", &tmpname, NULL);
+ if (fd == -1)
+ goto bail;
+ close (fd);
+ exec->outfile = g_steal_pointer (&tmpname);
+
+ return exec;
+
+bail:
+ script_exec_free (exec);
+ return NULL;
+}
+
+GBytes *
+gnome_desktop_thumbnail_script_exec (const char *cmd,
+ int size,
+ const char *uri,
+ GError **error)
+{
+ g_autofree char *error_out = NULL;
+ g_auto(GStrv) expanded_script = NULL;
+ int exit_status;
+ gboolean ret;
+ GBytes *image = NULL;
+ ScriptExec *exec;
+
+ exec = script_exec_new (uri);
+ expanded_script = expand_thumbnailing_script (cmd, exec, size, error);
+ if (expanded_script == NULL)
+ goto out;
+
+#if 0
+ guint i;
+
+ g_print ("About to launch script: ");
+ for (i = 0; expanded_script[i]; i++)
+ g_print ("%s ", expanded_script[i]);
+ g_print ("\n");
+#endif
+
+ ret = g_spawn_sync (NULL, expanded_script, NULL, G_SPAWN_SEARCH_PATH,
+ NULL, NULL, NULL, &error_out,
+ &exit_status, error);
+ if (ret && g_spawn_check_exit_status (exit_status, error))
+ {
+ char *contents;
+ gsize length;
+
+ if (g_file_get_contents (exec->outfile, &contents, &length, error))
+ image = g_bytes_new_take (contents, length);
+ }
+ else
+ {
+ g_debug ("Failed to launch script: %s", !ret ? (*error)->message : error_out);
+ }
+
+out:
+ script_exec_free (exec);
+ return image;
+}
+
diff --git a/libgnome-desktop/gnome-desktop-thumbnail-script.h
b/libgnome-desktop/gnome-desktop-thumbnail-script.h
new file mode 100644
index 0000000..cbd6bbf
--- /dev/null
+++ b/libgnome-desktop/gnome-desktop-thumbnail-script.h
@@ -0,0 +1,38 @@
+/*
+ * gnome-thumbnail.h: Utilities for handling thumbnails
+ *
+ * Copyright (C) 2002, 2017 Red Hat, Inc.
+ *
+ * This file is part of the Gnome Library.
+ *
+ * The Gnome Library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * The Gnome Library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with the Gnome Library; see the file COPYING.LIB. If not,
+ * write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * Authors: Alexander Larsson <alexl redhat com>
+ * Bastien Nocera <hadess hadess net>
+ */
+
+#ifndef GNOME_DESKTOP_THUMBNAIL_SCRIPT_H
+#define GNOME_DESKTOP_THUMBNAIL_SCRIPT_H
+
+#include <glib.h>
+
+GBytes *
+gnome_desktop_thumbnail_script_exec (const char *cmd,
+ int size,
+ const char *uri,
+ GError **error);
+
+#endif /* GNOME_DESKTOP_THUMBNAIL_SCRIPT_H */
diff --git a/libgnome-desktop/gnome-desktop-thumbnail.c b/libgnome-desktop/gnome-desktop-thumbnail.c
index 617160d..73751f6 100644
--- a/libgnome-desktop/gnome-desktop-thumbnail.c
+++ b/libgnome-desktop/gnome-desktop-thumbnail.c
@@ -127,9 +127,12 @@
#include <gdk-pixbuf/gdk-pixbuf.h>
#include <string.h>
#include <stdlib.h>
+#include <sys/stat.h>
+#include <fcntl.h>
#define GNOME_DESKTOP_USE_UNSTABLE_API
#include "gnome-desktop-thumbnail.h"
+#include "gnome-desktop-thumbnail-script.h"
static void
thumbnailers_directory_changed (GFileMonitor *monitor,
@@ -929,120 +932,6 @@ gnome_desktop_thumbnail_factory_can_thumbnail (GnomeDesktopThumbnailFactory *fac
return FALSE;
}
-static char *
-expand_thumbnailing_elem (const char *elem,
- const int size,
- const char *inuri,
- const char *outfile,
- gboolean *got_input,
- gboolean *got_output)
-{
- GString *str;
- const char *p, *last;
- char *localfile;
-
- str = g_string_new (NULL);
-
- last = elem;
- while ((p = strchr (last, '%')) != NULL)
- {
- g_string_append_len (str, last, p - last);
- p++;
-
- switch (*p) {
- case 'u':
- g_string_append (str, inuri);
- *got_input = TRUE;
- p++;
- break;
- case 'i':
- localfile = g_filename_from_uri (inuri, NULL, NULL);
- if (localfile)
- {
- g_string_append (str, localfile);
- *got_input = TRUE;
- g_free (localfile);
- }
- p++;
- break;
- case 'o':
- g_string_append (str, outfile);
- *got_output = TRUE;
- p++;
- break;
- case 's':
- g_string_append_printf (str, "%d", size);
- p++;
- break;
- case '%':
- g_string_append_c (str, '%');
- p++;
- break;
- case 0:
- default:
- break;
- }
- last = p;
- }
- g_string_append (str, last);
-
- return g_string_free (str, FALSE);
-}
-
-static char **
-expand_thumbnailing_script (const char *script,
- const int size,
- const char *inuri,
- const char *outfile,
- GError **error)
-{
- GPtrArray *array;
- char **script_elems;
- guint i;
- gboolean got_in, got_out;
-
- if (!g_shell_parse_argv (script, NULL, &script_elems, error))
- return NULL;
-
- array = g_ptr_array_new_with_free_func (g_free);
-
- got_in = got_out = FALSE;
- for (i = 0; script_elems[i] != NULL; i++)
- {
- char *expanded;
-
- expanded = expand_thumbnailing_elem (script_elems[i],
- size,
- inuri,
- outfile,
- &got_in,
- &got_out);
-
- g_ptr_array_add (array, expanded);
- }
-
- if (!got_in)
- {
- g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
- "Input file could not be set");
- goto bail;
- }
- else if (!got_out)
- {
- g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
- "Output file could not be set");
- goto bail;
- }
-
- g_ptr_array_add (array, NULL);
-
- return (char **) g_ptr_array_free (array, FALSE);
-
-bail:
- g_ptr_array_free (array, TRUE);
- return NULL;
-}
-
static GdkPixbuf *
get_preview_thumbnail (const char *uri,
int size)
@@ -1099,6 +988,30 @@ get_preview_thumbnail (const char *uri,
return pixbuf;
}
+static GdkPixbuf *
+pixbuf_new_from_bytes (GBytes *bytes,
+ GError **error)
+{
+ g_autoptr(GdkPixbufLoader) loader = NULL;
+
+ loader = gdk_pixbuf_loader_new_with_mime_type ("image/png", error);
+ if (!loader)
+ return NULL;
+
+ if (!gdk_pixbuf_loader_write (loader,
+ g_bytes_get_data (bytes, NULL),
+ g_bytes_get_size (bytes),
+ error))
+ {
+ return NULL;
+ }
+
+ if (!gdk_pixbuf_loader_close (loader, error))
+ return NULL;
+
+ return g_object_ref (gdk_pixbuf_loader_get_pixbuf (loader));
+}
+
/**
* gnome_desktop_thumbnail_factory_generate_thumbnail:
* @factory: a #GnomeDesktopThumbnailFactory
@@ -1122,8 +1035,6 @@ gnome_desktop_thumbnail_factory_generate_thumbnail (GnomeDesktopThumbnailFactory
GdkPixbuf *pixbuf;
char *script;
int size;
- int exit_status;
- char *tmpname;
g_return_val_if_fail (uri != NULL, NULL);
g_return_val_if_fail (mime_type != NULL, NULL);
@@ -1154,42 +1065,18 @@ gnome_desktop_thumbnail_factory_generate_thumbnail (GnomeDesktopThumbnailFactory
if (script)
{
- int fd;
-
- fd = g_file_open_tmp (".gnome_desktop_thumbnail.XXXXXX", &tmpname, NULL);
-
- if (fd != -1)
- {
- char **expanded_script;
- GError *error = NULL;
-
- close (fd);
-
- expanded_script = expand_thumbnailing_script (script, size, uri, tmpname, &error);
- if (expanded_script == NULL)
- {
- g_warning ("Failed to expand script '%s': %s", script, error->message);
- g_error_free (error);
- }
- else
- {
- gboolean ret;
+ GBytes *data;
- ret = g_spawn_sync (NULL, expanded_script, NULL, G_SPAWN_SEARCH_PATH,
- NULL, NULL, NULL, NULL, &exit_status, NULL);
- if (ret && exit_status == 0)
- pixbuf = gdk_pixbuf_new_from_file (tmpname, NULL);
-
- g_strfreev (expanded_script);
- }
-
- g_unlink (tmpname);
- g_free (tmpname);
- }
-
- g_free (script);
+ data = gnome_desktop_thumbnail_script_exec (script, size, uri, NULL);
+ if (data)
+ {
+ pixbuf = pixbuf_new_from_bytes (data, NULL);
+ g_bytes_unref (data);
+ }
}
+ g_free (script);
+
return pixbuf;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]