summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--build-aux/flatpak/org.gnome.Nautilus.json15
-rw-r--r--build-aux/flatpak/org.gnome.Nautilus.yml10
-rw-r--r--build-aux/flatpak/org.gnome.NautilusMaster.yml10
-rw-r--r--meson.build50
-rw-r--r--src/gnome-desktop/gnome-desktop-thumbnail-script.c892
-rw-r--r--src/gnome-desktop/gnome-desktop-thumbnail-script.h38
-rw-r--r--src/gnome-desktop/gnome-desktop-thumbnail.c1303
-rw-r--r--src/gnome-desktop/gnome-desktop-thumbnail.h102
-rwxr-xr-xsrc/gnome-desktop/gnome-desktop-update.sh45
-rw-r--r--src/meson.build7
-rw-r--r--src/nautilus-properties-window.c2
-rw-r--r--src/nautilus-thumbnails.c2
12 files changed, 39 insertions, 2437 deletions
diff --git a/build-aux/flatpak/org.gnome.Nautilus.json b/build-aux/flatpak/org.gnome.Nautilus.json
index 9285c4e50..ac1ee9c8d 100644
--- a/build-aux/flatpak/org.gnome.Nautilus.json
+++ b/build-aux/flatpak/org.gnome.Nautilus.json
@@ -121,6 +121,21 @@
]
},
{
+ "name": "gnome-desktop",
+ "buildsystem": "meson",
+ "build-options": [
+ "config-opts": [
+ "-Ddebug_tools=false",
+ "-Ddesktop_docs=false",
+ "-Dudev=disabled"
+ ]
+ ],
+ "sources": [
+ "type": "git",
+ "url": "https://gitlab.gnome.org/GNOME/gnome-desktop.git"
+ ]
+ },
+ {
"name": "gnome-autoar",
"sources": [
{
diff --git a/build-aux/flatpak/org.gnome.Nautilus.yml b/build-aux/flatpak/org.gnome.Nautilus.yml
index 186746412..1799e9df3 100644
--- a/build-aux/flatpak/org.gnome.Nautilus.yml
+++ b/build-aux/flatpak/org.gnome.Nautilus.yml
@@ -92,6 +92,16 @@ modules:
- type: git
url: https://gitlab.gnome.org/GNOME/tracker-miners.git
tag: 2.2.1
+- name: gnome-desktop
+ buildsystem: meson
+ build-options:
+ config-opts:
+ - "-Ddebug_tools=false"
+ - "-Ddesktop_docs=false"
+ - "-Dudev=disabled"
+ sources:
+ - type: git
+ url: https://gitlab.gnome.org/GNOME/gnome-desktop.git
- name: gnome-autoar
sources:
- type: git
diff --git a/build-aux/flatpak/org.gnome.NautilusMaster.yml b/build-aux/flatpak/org.gnome.NautilusMaster.yml
index 28c2dfb66..db0a5b2ed 100644
--- a/build-aux/flatpak/org.gnome.NautilusMaster.yml
+++ b/build-aux/flatpak/org.gnome.NautilusMaster.yml
@@ -89,6 +89,16 @@ modules:
sources:
- type: git
url: https://gitlab.gnome.org/GNOME/tracker-miners.git
+- name: gnome-desktop
+ buildsystem: meson
+ build-options:
+ config-opts:
+ - "-Ddebug_tools=false"
+ - "-Ddesktop_docs=false"
+ - "-Dudev=disabled"
+ sources:
+ - type: git
+ url: https://gitlab.gnome.org/GNOME/gnome-desktop.git
- name: gnome-autoar
sources:
- type: git
diff --git a/meson.build b/meson.build
index 70e41043b..9569e22e2 100644
--- a/meson.build
+++ b/meson.build
@@ -73,30 +73,6 @@ add_project_arguments(
language: 'c'
)
-######################
-# Host system checks #
-######################
-
-host_system = host_machine.system()
-host_cpu = host_machine.cpu()
-unsupported_cpus = [
- 'alpha',
- 'ia64',
- 'm68k',
- 'parisc',
- 'parisc64',
- 'sh4',
- 'sparc',
- 'sparc64',
-]
-system_supports_seccomp = host_system == 'linux'
-cpu_supports_seccomp = not unsupported_cpus.contains(host_cpu)
-seccomp_required = system_supports_seccomp and cpu_supports_seccomp
-
-##########################
-# End host system checks #
-##########################
-
##################
# Module imports #
##################
@@ -137,15 +113,8 @@ gio_unix = dependency('gio-unix-2.0', version: glib_ver)
glib = dependency('glib-2.0', version: glib_ver)
gmodule = dependency('gmodule-no-export-2.0', version: glib_ver)
gnome_autoar = dependency('gnome-autoar-0', version: '>= 0.2.1')
-gsettings_desktop_schemas = dependency('gsettings-desktop-schemas')
+gnome_desktop = dependency('gnome-desktop-3.0', version: '>= 3.0.0')
gtk = dependency('gtk+-3.0', version: '>= 3.22.27')
-if seccomp_required
- message('seccomp required on this platform, make sure bubblewrap is available at runtime as well.')
- seccomp = dependency('libseccomp')
-else
- warning('The host does not support seccomp, thumbnailer sandboxing will be disabled. Such setups are not recommended, use at your own risk!')
- seccomp = dependency('', required: false)
-endif
selinux = []
if get_option('selinux')
selinux = dependency('libselinux', version: '>= 2.0')
@@ -154,8 +123,6 @@ tracker_sparql = dependency('tracker-sparql-2.0')
x11 = dependency('x11')
xml = dependency('libxml-2.0', version: '>= 2.7.8')
-fontconfig = dependency('fontconfig', required: false)
-
####################
# End dependencies #
####################
@@ -174,15 +141,8 @@ endif
application_id = 'org.gnome.Nautilus' + profile
-if fontconfig.found()
- fontconfig_cache_path = fontconfig.get_pkgconfig_variable('cachedir')
-else
- fontconfig_cache_path = join_paths(libdir, 'fontconfig/cache')
-endif
-
conf.set_quoted('APPLICATION_ID', application_id)
conf.set_quoted('GETTEXT_PACKAGE', 'nautilus')
-conf.set_quoted('INSTALL_PREFIX', prefix)
conf.set_quoted('LOCALEDIR', join_paths(prefix, localedir))
conf.set_quoted('NAME_SUFFIX', name_suffix)
conf.set_quoted('NAUTILUS_DATADIR', join_paths(datadir, 'nautilus'))
@@ -190,14 +150,6 @@ conf.set_quoted('NAUTILUS_EXTENSIONDIR', join_paths(prefix, extensiondir))
conf.set_quoted('PACKAGE_VERSION', meson.project_version())
conf.set_quoted('PROFILE', profile)
conf.set_quoted('VERSION', '@0@-@VCS_TAG@'.format(meson.project_version()))
-conf.set_quoted('FONTCONFIG_CACHE_PATH', fontconfig_cache_path)
-
-###################################################
-# gnome-desktop macros for thumbnailer sandboxing #
-###################################################
-
-conf.set('ENABLE_SECCOMP', seccomp.found())
-conf.set('HAVE_BWRAP', seccomp.found())
conf.set('ENABLE_PACKAGEKIT', get_option('packagekit'))
conf.set('ENABLE_PROFILING', get_option('profiling'))
diff --git a/src/gnome-desktop/gnome-desktop-thumbnail-script.c b/src/gnome-desktop/gnome-desktop-thumbnail-script.c
deleted file mode 100644
index 0aa26444a..000000000
--- a/src/gnome-desktop/gnome-desktop-thumbnail-script.c
+++ /dev/null
@@ -1,892 +0,0 @@
-/*
- * 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>
-
-#ifdef ENABLE_SECCOMP
-#include <errno.h>
-#include <sys/socket.h>
-#include <sys/ioctl.h>
-#include <sys/utsname.h>
-#include <seccomp.h>
-#endif
-
-#include "gnome-desktop-thumbnail-script.h"
-
-typedef struct {
- gboolean sandbox;
- char *thumbnailer_name;
- GArray *fd_array;
- /* Input/output file paths outside the sandbox */
- char *infile;
- char *infile_tmp; /* the host version of /tmp/gnome-desktop-file-to-thumbnail.* */
- char *outfile;
- char *outdir; /* outdir is outfile's parent dir, if it needs to be deleted */
- /* I/O file paths inside the sandbox */
- char *s_infile;
- char *s_outfile;
-} ScriptExec;
-
-static char *
-expand_thumbnailing_elem (const char *elem,
- const int size,
- const char *infile,
- const char *outfile,
- gboolean *got_input,
- gboolean *got_output)
-{
- GString *str;
- const char *p, *last;
- char *inuri;
-
- 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':
- inuri = g_filename_to_uri (infile, NULL, NULL);
- if (inuri)
- {
- g_string_append (str, inuri);
- *got_input = TRUE;
- g_free (inuri);
- }
- p++;
- break;
- case 'i':
- g_string_append (str, infile);
- *got_input = TRUE;
- 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);
-}
-
-/* From https://github.com/flatpak/flatpak/blob/master/common/flatpak-run.c */
-G_GNUC_NULL_TERMINATED
-static void
-add_args (GPtrArray *argv_array, ...)
-{
- va_list args;
- const gchar *arg;
-
- va_start (args, argv_array);
- while ((arg = va_arg (args, const gchar *)))
- g_ptr_array_add (argv_array, g_strdup (arg));
- va_end (args);
-}
-
-static void
-add_env (GPtrArray *array,
- const char *envvar)
-{
- if (g_getenv (envvar) != NULL)
- add_args (array,
- "--setenv", envvar, g_getenv (envvar),
- NULL);
-}
-
-static char *
-get_extension (const char *path)
-{
- g_autofree char *basename = NULL;
- char *p;
-
- basename = g_path_get_basename (path);
- p = strrchr (basename, '.');
- if (g_file_test (path, G_FILE_TEST_IS_DIR) ||
- !p ||
- p == basename) /* Leading periods on the basename are ignored. */
- return NULL;
- return g_strdup (p + 1);
-}
-
-#ifdef ENABLE_SECCOMP
-static gboolean
-flatpak_fail (GError **error,
- const char *msg,
- ...)
-{
- g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED, msg);
- return FALSE;
-}
-
-/* From https://github.com/flatpak/flatpak/blob/master/common/flatpak-utils.c */
-#if !defined(__i386__) && !defined(__x86_64__) && !defined(__aarch64__) && !defined(__arm__)
-static const char *
-flatpak_get_kernel_arch (void)
-{
- static struct utsname buf;
- static char *arch = NULL;
- char *m;
-
- if (arch != NULL)
- return arch;
-
- if (uname (&buf))
- {
- arch = "unknown";
- return arch;
- }
-
- /* By default, just pass on machine, good enough for most arches */
- arch = buf.machine;
-
- /* Override for some arches */
-
- m = buf.machine;
- /* i?86 */
- if (strlen (m) == 4 && m[0] == 'i' && m[2] == '8' && m[3] == '6')
- {
- arch = "i386";
- }
- else if (g_str_has_prefix (m, "arm"))
- {
- if (g_str_has_suffix (m, "b"))
- arch = "armeb";
- else
- arch = "arm";
- }
- else if (strcmp (m, "mips") == 0)
- {
-#if G_BYTE_ORDER == G_LITTLE_ENDIAN
- arch = "mipsel";
-#endif
- }
- else if (strcmp (m, "mips64") == 0)
- {
-#if G_BYTE_ORDER == G_LITTLE_ENDIAN
- arch = "mips64el";
-#endif
- }
-
- return arch;
-}
-#endif
-
-/* This maps the kernel-reported uname to a single string representing
- * the cpu family, in the sense that all members of this family would
- * be able to understand and link to a binary file with such cpu
- * opcodes. That doesn't necessarily mean that all members of the
- * family can run all opcodes, for instance for modern 32bit intel we
- * report "i386", even though they support instructions that the
- * original i386 cpu cannot run. Still, such an executable would
- * at least try to execute a 386, whereas an arm binary would not.
- */
-static const char *
-flatpak_get_arch (void)
-{
- /* Avoid using uname on multiarch machines, because uname reports the kernels
- * arch, and that may be different from userspace. If e.g. the kernel is 64bit and
- * the userspace is 32bit we want to use 32bit by default. So, we take the current build
- * arch as the default. */
-#if defined(__i386__)
- return "i386";
-#elif defined(__x86_64__)
- return "x86_64";
-#elif defined(__aarch64__)
- return "aarch64";
-#elif defined(__arm__)
-#if G_BYTE_ORDER == G_LITTLE_ENDIAN
- return "arm";
-#else
- return "armeb";
-#endif
-#else
- return flatpak_get_kernel_arch ();
-#endif
-}
-
-/* From https://github.com/flatpak/flatpak/blob/master/common/flatpak-run.c */
-static const uint32_t seccomp_x86_64_extra_arches[] = { SCMP_ARCH_X86, 0, };
-
-#ifdef SCMP_ARCH_AARCH64
-static const uint32_t seccomp_aarch64_extra_arches[] = { SCMP_ARCH_ARM, 0 };
-#endif
-
-static inline void
-cleanup_seccomp (void *p)
-{
- scmp_filter_ctx *pp = (scmp_filter_ctx *) p;
-
- if (*pp)
- seccomp_release (*pp);
-}
-
-static gboolean
-setup_seccomp (GPtrArray *argv_array,
- GArray *fd_array,
- const char *arch,
- gboolean multiarch,
- gboolean devel,
- GError **error)
-{
- __attribute__((cleanup (cleanup_seccomp))) scmp_filter_ctx seccomp = NULL;
-
- /**** BEGIN NOTE ON CODE SHARING
- *
- * There are today a number of different Linux container
- * implementations. That will likely continue for long into the
- * future. But we can still try to share code, and it's important
- * to do so because it affects what library and application writers
- * can do, and we should support code portability between different
- * container tools.
- *
- * This syscall blacklist is copied from linux-user-chroot, which was in turn
- * clearly influenced by the Sandstorm.io blacklist.
- *
- * If you make any changes here, I suggest sending the changes along
- * to other sandbox maintainers. Using the libseccomp list is also
- * an appropriate venue:
- * https://groups.google.com/forum/#!topic/libseccomp
- *
- * A non-exhaustive list of links to container tooling that might
- * want to share this blacklist:
- *
- * https://github.com/sandstorm-io/sandstorm
- * in src/sandstorm/supervisor.c++
- * http://cgit.freedesktop.org/xdg-app/xdg-app/
- * in common/flatpak-run.c
- * https://git.gnome.org/browse/linux-user-chroot
- * in src/setup-seccomp.c
- *
- **** END NOTE ON CODE SHARING
- */
- struct
- {
- int scall;
- struct scmp_arg_cmp *arg;
- } syscall_blacklist[] = {
- /* Block dmesg */
- {SCMP_SYS (syslog)},
- /* Useless old syscall */
- {SCMP_SYS (uselib)},
- /* Don't allow you to switch to bsd emulation or whatnot */
- {SCMP_SYS (personality)},
- /* Don't allow disabling accounting */
- {SCMP_SYS (acct)},
- /* 16-bit code is unnecessary in the sandbox, and modify_ldt is a
- historic source of interesting information leaks. */
- {SCMP_SYS (modify_ldt)},
- /* Don't allow reading current quota use */
- {SCMP_SYS (quotactl)},
-
- /* Don't allow access to the kernel keyring */
- {SCMP_SYS (add_key)},
- {SCMP_SYS (keyctl)},
- {SCMP_SYS (request_key)},
-
- /* Scary VM/NUMA ops */
- {SCMP_SYS (move_pages)},
- {SCMP_SYS (mbind)},
- {SCMP_SYS (get_mempolicy)},
- {SCMP_SYS (set_mempolicy)},
- {SCMP_SYS (migrate_pages)},
-
- /* Don't allow subnamespace setups: */
- {SCMP_SYS (unshare)},
- {SCMP_SYS (mount)},
- {SCMP_SYS (pivot_root)},
- {SCMP_SYS (clone), &SCMP_A0 (SCMP_CMP_MASKED_EQ, CLONE_NEWUSER, CLONE_NEWUSER)},
-
- /* Don't allow faking input to the controlling tty (CVE-2017-5226) */
- {SCMP_SYS (ioctl), &SCMP_A1(SCMP_CMP_MASKED_EQ, 0xFFFFFFFFu, (int)TIOCSTI)},
- };
-
- struct
- {
- int scall;
- struct scmp_arg_cmp *arg;
- } syscall_nondevel_blacklist[] = {
- /* Profiling operations; we expect these to be done by tools from outside
- * the sandbox. In particular perf has been the source of many CVEs.
- */
- {SCMP_SYS (perf_event_open)},
- {SCMP_SYS (ptrace)}
- };
- /* Blacklist all but unix, inet, inet6 and netlink */
- int socket_family_blacklist[] = {
- AF_AX25,
- AF_IPX,
- AF_APPLETALK,
- AF_NETROM,
- AF_BRIDGE,
- AF_ATMPVC,
- AF_X25,
- AF_ROSE,
- AF_DECnet,
- AF_NETBEUI,
- AF_SECURITY,
- AF_KEY,
- AF_NETLINK + 1, /* Last gets CMP_GE, so order is important */
- };
- guint i;
- int r;
- int fd = -1;
- g_autofree char *fd_str = NULL;
- g_autofree char *path = NULL;
-
- seccomp = seccomp_init (SCMP_ACT_ALLOW);
- if (!seccomp)
- return flatpak_fail (error, "Initialize seccomp failed");
-
- if (arch != NULL)
- {
- uint32_t arch_id = 0;
- const uint32_t *extra_arches = NULL;
-
- if (strcmp (arch, "i386") == 0)
- {
- arch_id = SCMP_ARCH_X86;
- }
- else if (strcmp (arch, "x86_64") == 0)
- {
- arch_id = SCMP_ARCH_X86_64;
- extra_arches = seccomp_x86_64_extra_arches;
- }
- else if (strcmp (arch, "arm") == 0)
- {
- arch_id = SCMP_ARCH_ARM;
- }
-#ifdef SCMP_ARCH_AARCH64
- else if (strcmp (arch, "aarch64") == 0)
- {
- arch_id = SCMP_ARCH_AARCH64;
- extra_arches = seccomp_aarch64_extra_arches;
- }
-#endif
-
- /* We only really need to handle arches on multiarch systems.
- * If only one arch is supported the default is fine */
- if (arch_id != 0)
- {
- /* This *adds* the target arch, instead of replacing the
- native one. This is not ideal, because we'd like to only
- allow the target arch, but we can't really disallow the
- native arch at this point, because then bubblewrap
- couldn't continue running. */
- r = seccomp_arch_add (seccomp, arch_id);
- if (r < 0 && r != -EEXIST)
- return flatpak_fail (error, "Failed to add architecture to seccomp filter");
-
- if (multiarch && extra_arches != NULL)
- {
- for (i = 0; extra_arches[i] != 0; i++)
- {
- r = seccomp_arch_add (seccomp, extra_arches[i]);
- if (r < 0 && r != -EEXIST)
- return flatpak_fail (error, "Failed to add multiarch architecture to seccomp filter");
- }
- }
- }
- }
-
- /* TODO: Should we filter the kernel keyring syscalls in some way?
- * We do want them to be used by desktop apps, but they could also perhaps
- * leak system stuff or secrets from other apps.
- */
-
- for (i = 0; i < G_N_ELEMENTS (syscall_blacklist); i++)
- {
- int scall = syscall_blacklist[i].scall;
- if (syscall_blacklist[i].arg)
- r = seccomp_rule_add (seccomp, SCMP_ACT_ERRNO (EPERM), scall, 1, *syscall_blacklist[i].arg);
- else
- r = seccomp_rule_add (seccomp, SCMP_ACT_ERRNO (EPERM), scall, 0);
- if (r < 0 && r == -EFAULT /* unknown syscall */)
- return flatpak_fail (error, "Failed to block syscall %d", scall);
- }
-
- if (!devel)
- {
- for (i = 0; i < G_N_ELEMENTS (syscall_nondevel_blacklist); i++)
- {
- int scall = syscall_nondevel_blacklist[i].scall;
- if (syscall_nondevel_blacklist[i].arg)
- r = seccomp_rule_add (seccomp, SCMP_ACT_ERRNO (EPERM), scall, 1, *syscall_nondevel_blacklist[i].arg);
- else
- r = seccomp_rule_add (seccomp, SCMP_ACT_ERRNO (EPERM), scall, 0);
-
- if (r < 0 && r == -EFAULT /* unknown syscall */)
- return flatpak_fail (error, "Failed to block syscall %d", scall);
- }
- }
-
- /* Socket filtering doesn't work on e.g. i386, so ignore failures here
- * However, we need to user seccomp_rule_add_exact to avoid libseccomp doing
- * something else: https://github.com/seccomp/libseccomp/issues/8 */
- for (i = 0; i < G_N_ELEMENTS (socket_family_blacklist); i++)
- {
- int family = socket_family_blacklist[i];
- if (i == G_N_ELEMENTS (socket_family_blacklist) - 1)
- seccomp_rule_add_exact (seccomp, SCMP_ACT_ERRNO (EAFNOSUPPORT), SCMP_SYS (socket), 1, SCMP_A0 (SCMP_CMP_GE, family));
- else
- seccomp_rule_add_exact (seccomp, SCMP_ACT_ERRNO (EAFNOSUPPORT), SCMP_SYS (socket), 1, SCMP_A0 (SCMP_CMP_EQ, family));
- }
-
- fd = g_file_open_tmp ("flatpak-seccomp-XXXXXX", &path, error);
- if (fd == -1)
- return FALSE;
-
- unlink (path);
-
- if (seccomp_export_bpf (seccomp, fd) != 0)
- {
- close (fd);
- return flatpak_fail (error, "Failed to export bpf");
- }
-
- lseek (fd, 0, SEEK_SET);
-
- fd_str = g_strdup_printf ("%d", fd);
- if (fd_array)
- g_array_append_val (fd_array, fd);
-
- add_args (argv_array,
- "--seccomp", fd_str,
- NULL);
-
- fd = -1; /* Don't close on success */
-
- return TRUE;
-}
-#endif
-
-#ifdef HAVE_BWRAP
-static gboolean
-path_is_usrmerged (const char *dir)
-{
- /* does /dir point to /usr/dir? */
- g_autofree char *target = NULL;
- GStatBuf stat_buf_src, stat_buf_target;
-
- if (g_stat (dir, &stat_buf_src) < 0)
- return FALSE;
-
- target = g_strdup_printf ("/usr/%s", dir);
-
- if (g_stat (target, &stat_buf_target) < 0)
- return FALSE;
-
- return (stat_buf_src.st_dev == stat_buf_target.st_dev) &&
- (stat_buf_src.st_ino == stat_buf_target.st_ino);
-}
-
-static gboolean
-add_bwrap (GPtrArray *array,
- ScriptExec *script)
-{
- const char * const usrmerged_dirs[] = { "bin", "lib64", "lib", "sbin" };
- int i;
-
- g_return_val_if_fail (script->outdir != NULL, FALSE);
- g_return_val_if_fail (script->s_infile != NULL, FALSE);
-
- add_args (array,
- "bwrap",
- "--ro-bind", "/usr", "/usr",
- "--ro-bind", "/etc/ld.so.cache", "/etc/ld.so.cache",
- NULL);
-
- /* These directories might be symlinks into /usr/... */
- for (i = 0; i < G_N_ELEMENTS (usrmerged_dirs); i++)
- {
- g_autofree char *absolute_dir = g_strdup_printf ("/%s", usrmerged_dirs[i]);
-
- if (!g_file_test (absolute_dir, G_FILE_TEST_EXISTS))
- continue;
-
- if (path_is_usrmerged (absolute_dir))
- {
- g_autofree char *symlink_target = g_strdup_printf ("/usr/%s", absolute_dir);
-
- add_args (array,
- "--symlink", symlink_target, absolute_dir,
- NULL);
- }
- else
- {
- add_args (array,
- "--ro-bind", absolute_dir, absolute_dir,
- NULL);
- }
- }
-
- /* fontconfig cache if necessary */
- if (!g_str_has_prefix (FONTCONFIG_CACHE_PATH, "/usr/"))
- add_args (array, "--ro-bind-try", FONTCONFIG_CACHE_PATH, FONTCONFIG_CACHE_PATH, NULL);
-
- add_args (array,
- "--proc", "/proc",
- "--dev", "/dev",
- "--chdir", "/",
- "--setenv", "GIO_USE_VFS", "local",
- "--unshare-all",
- "--die-with-parent",
- NULL);
-
- add_env (array, "G_MESSAGES_DEBUG");
- add_env (array, "G_MESSAGES_PREFIXED");
-
- /* Add gnome-desktop's install prefix if needed */
- if (g_strcmp0 (INSTALL_PREFIX, "") != 0 &&
- g_strcmp0 (INSTALL_PREFIX, "/usr") != 0 &&
- g_strcmp0 (INSTALL_PREFIX, "/usr/") != 0)
- {
- add_args (array,
- "--ro-bind", INSTALL_PREFIX, INSTALL_PREFIX,
- NULL);
- }
-
- g_ptr_array_add (array, g_strdup ("--bind"));
- g_ptr_array_add (array, g_strdup (script->outdir));
- g_ptr_array_add (array, g_strdup ("/tmp"));
-
- /* We make sure to also re-use the original file's original
- * extension in case it's useful for the thumbnailer to
- * identify the file type */
- g_ptr_array_add (array, g_strdup ("--ro-bind"));
- g_ptr_array_add (array, g_strdup (script->infile));
- g_ptr_array_add (array, g_strdup (script->s_infile));
-
- return TRUE;
-}
-#endif /* HAVE_BWRAP */
-
-static char **
-expand_thumbnailing_cmd (const char *cmd,
- ScriptExec *script,
- int size,
- GError **error)
-{
- GPtrArray *array;
- g_auto(GStrv) cmd_elems = NULL;
- guint i;
- gboolean got_in, got_out;
-
- if (!g_shell_parse_argv (cmd, NULL, &cmd_elems, error))
- return NULL;
-
- script->thumbnailer_name = g_strdup (cmd_elems[0]);
-
- array = g_ptr_array_new_with_free_func (g_free);
-
-#ifdef HAVE_BWRAP
- if (script->sandbox)
- {
- if (!add_bwrap (array, script))
- {
- g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
- "Bubblewrap setup failed");
- goto bail;
- }
- }
-#endif
-
-#ifdef ENABLE_SECCOMP
- if (script->sandbox)
- {
- const char *arch;
-
- arch = flatpak_get_arch ();
- g_assert (arch);
- if (!setup_seccomp (array,
- script->fd_array,
- arch,
- FALSE,
- FALSE,
- error))
- {
- goto bail;
- }
- }
-#endif
-
- got_in = got_out = FALSE;
- for (i = 0; cmd_elems[i] != NULL; i++)
- {
- char *expanded;
-
- expanded = expand_thumbnailing_elem (cmd_elems[i],
- size,
- script->s_infile ? script->s_infile : script->infile,
- script->s_outfile ? script->s_outfile : 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
-child_setup (gpointer user_data)
-{
- GArray *fd_array = user_data;
- guint i;
-
- /* If no fd_array was specified, don't care. */
- if (fd_array == NULL)
- return;
-
- /* Otherwise, mark not - close-on-exec all the fds in the array */
- for (i = 0; i < fd_array->len; i++)
- fcntl (g_array_index (fd_array, int, i), F_SETFD, 0);
-}
-
-static void
-script_exec_free (ScriptExec *exec)
-{
- if (exec == NULL)
- return;
-
- g_free (exec->thumbnailer_name);
- g_free (exec->infile);
- if (exec->infile_tmp)
- {
- if (g_file_test (exec->infile_tmp, G_FILE_TEST_IS_DIR))
- g_rmdir (exec->infile_tmp);
- else
- g_unlink (exec->infile_tmp);
- g_free (exec->infile_tmp);
- }
- if (exec->outfile)
- {
- g_unlink (exec->outfile);
- g_free (exec->outfile);
- }
- if (exec->outdir)
- {
- if (g_rmdir (exec->outdir) < 0)
- {
- g_warning ("Could not remove %s, thumbnailer %s left files in directory",
- exec->outdir, exec->thumbnailer_name);
- }
- g_free (exec->outdir);
- }
- g_free (exec->s_infile);
- g_free (exec->s_outfile);
- if (exec->fd_array)
- g_array_free (exec->fd_array, TRUE);
- g_free (exec);
-}
-
-static void
-clear_fd (gpointer data)
-{
- int *fd_p = data;
- if (fd_p != NULL && *fd_p != -1)
- close (*fd_p);
-}
-
-static ScriptExec *
-script_exec_new (const char *uri,
- GError **error)
-{
- ScriptExec *exec;
- g_autoptr(GFile) file = NULL;
-
- exec = g_new0 (ScriptExec, 1);
-#ifdef HAVE_BWRAP
- /* Bubblewrap is not used if the application is already sandboxed in
- * Flatpak as all privileges to create a new namespace are dropped when
- * the initial one is created. */
- if (!g_file_test ("/.flatpak-info", G_FILE_TEST_IS_REGULAR))
- exec->sandbox = TRUE;
-#endif
-
- file = g_file_new_for_uri (uri);
-
- exec->infile = g_file_get_path (file);
- if (!exec->infile)
- {
- g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND,
- "Could not get path for URI '%s'", uri);
- goto bail;
- }
-
-#ifdef HAVE_BWRAP
- if (exec->sandbox)
- {
- char *tmpl;
- g_autofree char *ext = NULL;
- g_autofree char *infile = NULL;
-
- exec->fd_array = g_array_new (FALSE, TRUE, sizeof (int));
- g_array_set_clear_func (exec->fd_array, clear_fd);
-
- tmpl = g_strdup ("/tmp/gnome-desktop-thumbnailer-XXXXXX");
- exec->outdir = g_mkdtemp (tmpl);
- if (!exec->outdir)
- {
- g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
- "Could not create temporary sandbox directory");
- goto bail;
- }
- exec->outfile = g_build_filename (exec->outdir, "gnome-desktop-thumbnailer.png", NULL);
- ext = get_extension (exec->infile);
-
- if (ext)
- infile = g_strdup_printf ("gnome-desktop-file-to-thumbnail.%s", ext);
- else
- infile = g_strdup_printf ("gnome-desktop-file-to-thumbnail");
-
- exec->infile_tmp = g_build_filename (exec->outdir, infile, NULL);
-
- exec->s_infile = g_build_filename ("/tmp/", infile, NULL);
- exec->s_outfile = g_build_filename ("/tmp/", "gnome-desktop-thumbnailer.png", NULL);
- }
- else
-#endif
- {
- int fd;
- g_autofree char *tmpname = NULL;
-
- fd = g_file_open_tmp (".gnome_desktop_thumbnail.XXXXXX", &tmpname, error);
- if (fd == -1)
- goto bail;
- close (fd);
- exec->outfile = g_steal_pointer (&tmpname);
- }
-
- return exec;
-
-bail:
- script_exec_free (exec);
- return NULL;
-}
-
-static void
-print_script_debug (GStrv expanded_script)
-{
- GString *out;
- guint i;
-
- out = g_string_new (NULL);
-
- for (i = 0; expanded_script[i]; i++)
- g_string_append_printf (out, "%s ", expanded_script[i]);
- g_string_append_printf (out, "\n");
-
- g_debug ("About to launch script: %s", out->str);
- g_string_free (out, TRUE);
-}
-
-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, error);
- if (!exec)
- goto out;
- expanded_script = expand_thumbnailing_cmd (cmd, exec, size, error);
- if (expanded_script == NULL)
- goto out;
-
- print_script_debug (expanded_script);
-
- ret = g_spawn_sync (NULL, expanded_script, NULL, G_SPAWN_SEARCH_PATH,
- child_setup, exec->fd_array, 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/src/gnome-desktop/gnome-desktop-thumbnail-script.h b/src/gnome-desktop/gnome-desktop-thumbnail-script.h
deleted file mode 100644
index cbd6bbf67..000000000
--- a/src/gnome-desktop/gnome-desktop-thumbnail-script.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * 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/src/gnome-desktop/gnome-desktop-thumbnail.c b/src/gnome-desktop/gnome-desktop-thumbnail.c
deleted file mode 100644
index 566fbeb84..000000000
--- a/src/gnome-desktop/gnome-desktop-thumbnail.c
+++ /dev/null
@@ -1,1303 +0,0 @@
-/*
- * gnome-thumbnail.c: Utilities for handling thumbnails
- *
- * Copyright (C) 2002 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.
- *
- * Author: Alexander Larsson <alexl@redhat.com>
- */
-
-/**
- * SECTION:gnome-desktop-thumbnail
- * @short_description: Generates and looks up thumbnails of files and
- * directories
- * @stability: Unstable
- * @include: libgnome-desktop/gnome-desktop-thumbnail.h
- *
- * #GnomeDesktopThumbnailFactory allows generation and loading of thumbnails for
- * local and remote files and directories. It uses a collection of programs
- * called <firstterm>thumbnailers</firstterm>, each one generating thumbnails
- * for a specific set of content-types of files. For example,
- * <application>totem-video-thumbnailer</application> generates thumbnails for
- * video files using GStreamer; <application>evince-thumbnailer</application>
- * generates thumbnails for PDFs and other document files. If no specific
- * thumbnailer exists for a file, or if the thumbnailer fails, gdk-pixbuf is
- * used as a fallback.
- *
- * To generate a thumbnail, an appropriate thumbnailer program is selected then
- * executed, passing it the URI of the file to thumbnail, plus a path to write
- * the thumbnail image to. If thumbnailing succeeds, the thumbnailer should have
- * written the image to disk before terminating; but if thumbnailing fails, no
- * image should be written, and the thumbnailer should return a non-zero exit
- * status. #GnomeDesktopThumbnailFactory will then fall back to using gdk-pixbuf
- * to generate a thumbnail, if possible.
- *
- * Thumbnailers are chosen by examining a series of
- * <filename>.thumbnailer</filename> files in
- * <filename><replaceable>$PREFIX</replaceable>/share/thumbnailers</filename>.
- * Each is in a simple key-file format:
- * <informalexample><programlisting>
- * [Thumbnailer Entry]
- * Exec=evince-thumbnailer -s %s %u %o
- * MimeType=application/pdf;application/x-bzpdf;application/x-gzpdf;
- * </programlisting></informalexample>
- *
- * The <filename>.thumbnailer</filename> format supports three keys:
- * <variablelist>
- * <varlistentry><term><code>Exec</code></term><listitem><para>
- * Required. The command to execute the thumbnailer. It supports a few different
- * parameters which are replaced before calling the thumbnailer:
- * <replaceable>%u</replaceable> is the URI of the file being thumbnailed;
- * <replaceable>%i</replaceable> is its path; <replaceable>%o</replaceable>
- * is the path of the image file to be written to;
- * <replaceable>%s</replaceable> is the maximum desired size of the thumbnail
- * image (the maximum width or height, in pixels); and
- * <replaceable>%%</replaceable> is a literal percent character.
- * </para></listitem></varlistentry>
- * <varlistentry><term><code>MimeType</code></term><listitem><para>
- * Required. A semicolon-separated list of MIME types which the thumbnailer
- * supports generating thumbnails for.
- * </para></listitem></varlistentry>
- * </variablelist>
- *
- * So in the example <filename>.thumbnailer</filename> file above, the command
- * passes the requested thumbnail size, then the input file’s URI, then the
- * path for the output image file to
- * <application>evince-thumbnailer</application>.
- *
- * The code to examine and call a thumbnailer is contained in
- * #GnomeDesktopThumbnailFactory, which handles looking up the right thumbnailer
- * script, building and executing the command for it, and loading the resulting
- * thumbnail image into a #GdkPixbuf.
- *
- * Thumbnail caching is also supported by #GnomeDesktopThumbnailFactory. When
- * calling a thumbnailer, the path passed for the output image file is in
- * <filename><envar>$XDG_CACHE_HOME</envar>/thumbnails/
- * <replaceable>$SIZE</replaceable>/</filename>. The cached image file is given
- * a (probably) unique filename, generated by hashing the original file’s URI,
- * so the thumbnail can be looked up in future. #GnomeDesktopThumbnailFactory
- * supports two sizes of thumbnails: %GNOME_DESKTOP_THUMBNAIL_SIZE_NORMAL and
- * %GNOME_DESKTOP_THUMBNAIL_SIZE_LARGE. Normal thumbnails are up to 128×128
- * pixels, whereas large thumbnails are up to 256×256 pixels. Thumbnails which
- * are larger than this are scaled down before being cached, and non-square
- * thumbnails are scaled so their largest dimension is at most 128 or 256
- * pixels.
- *
- * #GnomeDesktopThumbnailFactory also handles failed thumbnails. If a
- * thumbnailer can’t generate a thumbnail for a file (e.g. because the file is
- * corrupt or because the right video codecs aren’t available), it returns a
- * non-zero exit status. The thumbnail factory then writes an entry to
- * <filename><envar>$XDG_CACHE_HOME</envar>/thumbnails/fail/
- * gnome-thumbnail-factory/</filename> which is named after the hash of the
- * input file URI (just like a successful cached thumbnail). For future queries
- * for thumbnails for that file, #GnomeDesktopThumbnailFactory can immediately
- * return an error after looking up the fail entry.
- *
- * If a file changes content, #GnomeDesktopThumbnailFactory will generate a new
- * thumbnail because each cached image has associated metadata (stored as PNG
- * tEXt keys) storing the full URI of the thumbnailed file (to check for hash
- * collisions) and its last modification time at the point of thumbnailing. If
- * the stored modification time doesn’t match the file’s current one, a new
- * thumbnail is generated.
- *
- * Since: 2.2
- */
-
-#include <config.h>
-
-#include <glib.h>
-#include <glib/gstdio.h>
-#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,
- GFile *file,
- GFile *other_file,
- GFileMonitorEvent event_type,
- GnomeDesktopThumbnailFactory *factory);
-
-struct _GnomeDesktopThumbnailFactoryPrivate {
- GnomeDesktopThumbnailSize size;
-
- GMutex lock;
-
- GList *thumbnailers;
- GHashTable *mime_types_map;
- GList *monitors;
-
- GSettings *settings;
- gboolean loaded : 1;
- gboolean disabled : 1;
- gchar **disabled_types;
-};
-
-static const char *appname = "gnome-thumbnail-factory";
-
-G_DEFINE_TYPE (GnomeDesktopThumbnailFactory,
- gnome_desktop_thumbnail_factory,
- G_TYPE_OBJECT)
-#define parent_class gnome_desktop_thumbnail_factory_parent_class
-
-#define GNOME_DESKTOP_THUMBNAIL_FACTORY_GET_PRIVATE(object) \
- (G_TYPE_INSTANCE_GET_PRIVATE ((object), GNOME_DESKTOP_TYPE_THUMBNAIL_FACTORY, GnomeDesktopThumbnailFactoryPrivate))
-
-#define THUMBNAILER_ENTRY_GROUP "Thumbnailer Entry"
-#define THUMBNAILER_EXTENSION ".thumbnailer"
-
-typedef struct {
- volatile gint ref_count;
-
- gchar *path;
-
- gchar *command;
- gchar **mime_types;
-} Thumbnailer;
-
-static Thumbnailer *
-thumbnailer_ref (Thumbnailer *thumb)
-{
- g_return_val_if_fail (thumb != NULL, NULL);
- g_return_val_if_fail (thumb->ref_count > 0, NULL);
-
- g_atomic_int_inc (&thumb->ref_count);
- return thumb;
-}
-
-static void
-thumbnailer_unref (Thumbnailer *thumb)
-{
- g_return_if_fail (thumb != NULL);
- g_return_if_fail (thumb->ref_count > 0);
-
- if (g_atomic_int_dec_and_test (&thumb->ref_count))
- {
- g_free (thumb->path);
- g_free (thumb->command);
- g_strfreev (thumb->mime_types);
-
- g_slice_free (Thumbnailer, thumb);
- }
-}
-
-static Thumbnailer *
-thumbnailer_load (Thumbnailer *thumb)
-{
- GKeyFile *key_file;
- GError *error = NULL;
-
- key_file = g_key_file_new ();
- if (!g_key_file_load_from_file (key_file, thumb->path, 0, &error))
- {
- g_warning ("Failed to load thumbnailer from \"%s\": %s\n", thumb->path, error->message);
- g_error_free (error);
- thumbnailer_unref (thumb);
- g_key_file_free (key_file);
-
- return NULL;
- }
-
- if (!g_key_file_has_group (key_file, THUMBNAILER_ENTRY_GROUP))
- {
- g_warning ("Invalid thumbnailer: missing group \"%s\"\n", THUMBNAILER_ENTRY_GROUP);
- thumbnailer_unref (thumb);
- g_key_file_free (key_file);
-
- return NULL;
- }
-
- thumb->command = g_key_file_get_string (key_file, THUMBNAILER_ENTRY_GROUP, "Exec", NULL);
- if (!thumb->command)
- {
- g_warning ("Invalid thumbnailer: missing Exec key\n");
- thumbnailer_unref (thumb);
- g_key_file_free (key_file);
-
- return NULL;
- }
-
- thumb->mime_types = g_key_file_get_string_list (key_file, THUMBNAILER_ENTRY_GROUP, "MimeType", NULL, NULL);
- if (!thumb->mime_types)
- {
- g_warning ("Invalid thumbnailer: missing MimeType key\n");
- thumbnailer_unref (thumb);
- g_key_file_free (key_file);
-
- return NULL;
- }
-
- g_key_file_free (key_file);
-
- return thumb;
-}
-
-static Thumbnailer *
-thumbnailer_reload (Thumbnailer *thumb)
-{
- g_return_val_if_fail (thumb != NULL, NULL);
-
- g_free (thumb->command);
- thumb->command = NULL;
- g_strfreev (thumb->mime_types);
- thumb->mime_types = NULL;
-
- return thumbnailer_load (thumb);
-}
-
-static Thumbnailer *
-thumbnailer_new (const gchar *path)
-{
- Thumbnailer *thumb;
-
- thumb = g_slice_new0 (Thumbnailer);
- thumb->ref_count = 1;
- thumb->path = g_strdup (path);
-
- return thumbnailer_load (thumb);
-}
-
-static gpointer
-init_thumbnailers_dirs (gpointer data)
-{
- const gchar * const *data_dirs;
- GPtrArray *thumbs_dirs;
- guint i;
-
- data_dirs = g_get_system_data_dirs ();
- thumbs_dirs = g_ptr_array_new ();
-
- g_ptr_array_add (thumbs_dirs, g_build_filename (g_get_user_data_dir (), "thumbnailers", NULL));
- for (i = 0; data_dirs[i] != NULL; i++)
- g_ptr_array_add (thumbs_dirs, g_build_filename (data_dirs[i], "thumbnailers", NULL));
- g_ptr_array_add (thumbs_dirs, NULL);
-
- return g_ptr_array_free (thumbs_dirs, FALSE);
-}
-
-static const gchar * const *
-get_thumbnailers_dirs (void)
-{
- static GOnce once_init = G_ONCE_INIT;
- return g_once (&once_init, init_thumbnailers_dirs, NULL);
-}
-
-/* These should be called with the lock held */
-static void
-gnome_desktop_thumbnail_factory_register_mime_types (GnomeDesktopThumbnailFactory *factory,
- Thumbnailer *thumb)
-{
- GnomeDesktopThumbnailFactoryPrivate *priv = factory->priv;
- gint i;
-
- for (i = 0; thumb->mime_types[i]; i++)
- {
- if (!g_hash_table_lookup (priv->mime_types_map, thumb->mime_types[i]))
- g_hash_table_insert (priv->mime_types_map,
- g_strdup (thumb->mime_types[i]),
- thumbnailer_ref (thumb));
- }
-}
-
-static void
-gnome_desktop_thumbnail_factory_add_thumbnailer (GnomeDesktopThumbnailFactory *factory,
- Thumbnailer *thumb)
-{
- GnomeDesktopThumbnailFactoryPrivate *priv = factory->priv;
-
- gnome_desktop_thumbnail_factory_register_mime_types (factory, thumb);
- priv->thumbnailers = g_list_prepend (priv->thumbnailers, thumb);
-}
-
-static gboolean
-gnome_desktop_thumbnail_factory_is_disabled (GnomeDesktopThumbnailFactory *factory,
- const gchar *mime_type)
-{
- GnomeDesktopThumbnailFactoryPrivate *priv = factory->priv;
- guint i;
-
- if (priv->disabled)
- return TRUE;
-
- if (!priv->disabled_types)
- return FALSE;
-
- for (i = 0; priv->disabled_types[i]; i++)
- {
- if (g_strcmp0 (priv->disabled_types[i], mime_type) == 0)
- return TRUE;
- }
-
- return FALSE;
-}
-
-static gboolean
-remove_thumbnailer_from_mime_type_map (gchar *key,
- Thumbnailer *value,
- gchar *path)
-{
- return (strcmp (value->path, path) == 0);
-}
-
-static void
-update_or_create_thumbnailer (GnomeDesktopThumbnailFactory *factory,
- const gchar *path)
-{
- GnomeDesktopThumbnailFactoryPrivate *priv = factory->priv;
- GList *l;
- Thumbnailer *thumb;
- gboolean found = FALSE;
-
- g_mutex_lock (&priv->lock);
-
- for (l = priv->thumbnailers; l && !found; l = g_list_next (l))
- {
- thumb = (Thumbnailer *)l->data;
-
- if (strcmp (thumb->path, path) == 0)
- {
- found = TRUE;
-
- /* First remove the mime_types associated to this thumbnailer */
- g_hash_table_foreach_remove (priv->mime_types_map,
- (GHRFunc)remove_thumbnailer_from_mime_type_map,
- (gpointer)path);
- if (!thumbnailer_reload (thumb))
- priv->thumbnailers = g_list_delete_link (priv->thumbnailers, l);
- else
- gnome_desktop_thumbnail_factory_register_mime_types (factory, thumb);
- }
- }
-
- if (!found)
- {
- thumb = thumbnailer_new (path);
- if (thumb)
- gnome_desktop_thumbnail_factory_add_thumbnailer (factory, thumb);
- }
-
- g_mutex_unlock (&priv->lock);
-}
-
-static void
-remove_thumbnailer (GnomeDesktopThumbnailFactory *factory,
- const gchar *path)
-{
- GnomeDesktopThumbnailFactoryPrivate *priv = factory->priv;
- GList *l;
- Thumbnailer *thumb;
-
- g_mutex_lock (&priv->lock);
-
- for (l = priv->thumbnailers; l; l = g_list_next (l))
- {
- thumb = (Thumbnailer *)l->data;
-
- if (strcmp (thumb->path, path) == 0)
- {
- priv->thumbnailers = g_list_delete_link (priv->thumbnailers, l);
- g_hash_table_foreach_remove (priv->mime_types_map,
- (GHRFunc)remove_thumbnailer_from_mime_type_map,
- (gpointer)path);
- thumbnailer_unref (thumb);
-
- break;
- }
- }
-
- g_mutex_unlock (&priv->lock);
-}
-
-static void
-remove_thumbnailers_for_dir (GnomeDesktopThumbnailFactory *factory,
- const gchar *thumbnailer_dir,
- GFileMonitor *monitor)
-{
- GnomeDesktopThumbnailFactoryPrivate *priv = factory->priv;
- GList *l;
- Thumbnailer *thumb;
-
- g_mutex_lock (&priv->lock);
-
- /* Remove all the thumbnailers inside this @thumbnailer_dir. */
- for (l = priv->thumbnailers; l; l = g_list_next (l))
- {
- thumb = (Thumbnailer *)l->data;
-
- if (g_str_has_prefix (thumb->path, thumbnailer_dir) == TRUE)
- {
- priv->thumbnailers = g_list_delete_link (priv->thumbnailers, l);
- g_hash_table_foreach_remove (priv->mime_types_map,
- (GHRFunc)remove_thumbnailer_from_mime_type_map,
- (gpointer)thumb->path);
- thumbnailer_unref (thumb);
-
- break;
- }
- }
-
- /* Remove the monitor for @thumbnailer_dir. */
- priv->monitors = g_list_remove (priv->monitors, monitor);
- g_signal_handlers_disconnect_by_func (monitor, thumbnailers_directory_changed, factory);
-
- g_mutex_unlock (&priv->lock);
-}
-
-static void
-gnome_desktop_thumbnail_factory_load_thumbnailers_for_dir (GnomeDesktopThumbnailFactory *factory,
- const gchar *path)
-{
- GnomeDesktopThumbnailFactoryPrivate *priv = factory->priv;
- GDir *dir;
- GFile *dir_file;
- GFileMonitor *monitor;
- const gchar *dirent;
-
- dir = g_dir_open (path, 0, NULL);
- if (!dir)
- return;
-
- /* Monitor dir */
- dir_file = g_file_new_for_path (path);
- monitor = g_file_monitor_directory (dir_file,
- G_FILE_MONITOR_NONE,
- NULL, NULL);
- if (monitor)
- {
- g_signal_connect (monitor, "changed",
- G_CALLBACK (thumbnailers_directory_changed),
- factory);
- priv->monitors = g_list_prepend (priv->monitors, monitor);
- }
- g_object_unref (dir_file);
-
- while ((dirent = g_dir_read_name (dir)))
- {
- Thumbnailer *thumb;
- gchar *filename;
-
- if (!g_str_has_suffix (dirent, THUMBNAILER_EXTENSION))
- continue;
-
- filename = g_build_filename (path, dirent, NULL);
- thumb = thumbnailer_new (filename);
- g_free (filename);
-
- if (thumb)
- gnome_desktop_thumbnail_factory_add_thumbnailer (factory, thumb);
- }
-
- g_dir_close (dir);
-}
-
-static void
-thumbnailers_directory_changed (GFileMonitor *monitor,
- GFile *file,
- GFile *other_file,
- GFileMonitorEvent event_type,
- GnomeDesktopThumbnailFactory *factory)
-{
- gchar *path;
-
- switch (event_type)
- {
- case G_FILE_MONITOR_EVENT_CREATED:
- case G_FILE_MONITOR_EVENT_CHANGED:
- case G_FILE_MONITOR_EVENT_DELETED:
- path = g_file_get_path (file);
- if (!g_str_has_suffix (path, THUMBNAILER_EXTENSION))
- {
- g_free (path);
- return;
- }
-
- if (event_type == G_FILE_MONITOR_EVENT_DELETED)
- remove_thumbnailer (factory, path);
- else
- update_or_create_thumbnailer (factory, path);
-
- g_free (path);
- break;
- case G_FILE_MONITOR_EVENT_UNMOUNTED:
- case G_FILE_MONITOR_EVENT_MOVED:
- path = g_file_get_path (file);
- remove_thumbnailers_for_dir (factory, path, monitor);
-
- if (event_type == G_FILE_MONITOR_EVENT_MOVED)
- gnome_desktop_thumbnail_factory_load_thumbnailers_for_dir (factory, path);
-
- g_free (path);
- break;
- case G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT:
- case G_FILE_MONITOR_EVENT_ATTRIBUTE_CHANGED:
- case G_FILE_MONITOR_EVENT_PRE_UNMOUNT:
- case G_FILE_MONITOR_EVENT_RENAMED:
- case G_FILE_MONITOR_EVENT_MOVED_IN:
- case G_FILE_MONITOR_EVENT_MOVED_OUT:
- default:
- break;
- }
-}
-
-static void
-gnome_desktop_thumbnail_factory_load_thumbnailers (GnomeDesktopThumbnailFactory *factory)
-{
- GnomeDesktopThumbnailFactoryPrivate *priv = factory->priv;
- const gchar * const *dirs;
- guint i;
-
- if (priv->loaded)
- return;
-
- dirs = get_thumbnailers_dirs ();
- for (i = 0; dirs[i]; i++)
- {
- gnome_desktop_thumbnail_factory_load_thumbnailers_for_dir (factory, dirs[i]);
- }
-
- priv->loaded = TRUE;
-}
-
-static void
-external_thumbnailers_disabled_all_changed_cb (GSettings *settings,
- const gchar *key,
- GnomeDesktopThumbnailFactory *factory)
-{
- GnomeDesktopThumbnailFactoryPrivate *priv = factory->priv;
-
- g_mutex_lock (&priv->lock);
-
- priv->disabled = g_settings_get_boolean (priv->settings, "disable-all");
- if (priv->disabled)
- {
- g_strfreev (priv->disabled_types);
- priv->disabled_types = NULL;
- }
- else
- {
- priv->disabled_types = g_settings_get_strv (priv->settings, "disable");
- gnome_desktop_thumbnail_factory_load_thumbnailers (factory);
- }
-
- g_mutex_unlock (&priv->lock);
-}
-
-static void
-external_thumbnailers_disabled_changed_cb (GSettings *settings,
- const gchar *key,
- GnomeDesktopThumbnailFactory *factory)
-{
- GnomeDesktopThumbnailFactoryPrivate *priv = factory->priv;
-
- g_mutex_lock (&priv->lock);
-
- if (!priv->disabled)
- {
- g_strfreev (priv->disabled_types);
- priv->disabled_types = g_settings_get_strv (priv->settings, "disable");
- }
-
- g_mutex_unlock (&priv->lock);
-}
-
-static void
-gnome_desktop_thumbnail_factory_init (GnomeDesktopThumbnailFactory *factory)
-{
- GnomeDesktopThumbnailFactoryPrivate *priv;
-
- factory->priv = GNOME_DESKTOP_THUMBNAIL_FACTORY_GET_PRIVATE (factory);
-
- priv = factory->priv;
-
- priv->size = GNOME_DESKTOP_THUMBNAIL_SIZE_NORMAL;
-
- priv->mime_types_map = g_hash_table_new_full (g_str_hash,
- g_str_equal,
- (GDestroyNotify)g_free,
- (GDestroyNotify)thumbnailer_unref);
-
- g_mutex_init (&priv->lock);
-
- priv->settings = g_settings_new ("org.gnome.desktop.thumbnailers");
- priv->disabled = g_settings_get_boolean (priv->settings, "disable-all");
- if (!priv->disabled)
- priv->disabled_types = g_settings_get_strv (priv->settings, "disable");
- g_signal_connect (priv->settings, "changed::disable-all",
- G_CALLBACK (external_thumbnailers_disabled_all_changed_cb),
- factory);
- g_signal_connect (priv->settings, "changed::disable",
- G_CALLBACK (external_thumbnailers_disabled_changed_cb),
- factory);
-
- if (!priv->disabled)
- gnome_desktop_thumbnail_factory_load_thumbnailers (factory);
-}
-
-static void
-gnome_desktop_thumbnail_factory_finalize (GObject *object)
-{
- GnomeDesktopThumbnailFactory *factory;
- GnomeDesktopThumbnailFactoryPrivate *priv;
-
- factory = GNOME_DESKTOP_THUMBNAIL_FACTORY (object);
-
- priv = factory->priv;
-
- if (priv->thumbnailers)
- {
- g_list_free_full (priv->thumbnailers, (GDestroyNotify)thumbnailer_unref);
- priv->thumbnailers = NULL;
- }
-
- g_clear_pointer (&priv->mime_types_map, g_hash_table_destroy);
-
- if (priv->monitors)
- {
- g_list_free_full (priv->monitors, (GDestroyNotify)g_object_unref);
- priv->monitors = NULL;
- }
-
- g_mutex_clear (&priv->lock);
-
- g_clear_pointer (&priv->disabled_types, g_strfreev);
-
- if (priv->settings)
- {
- g_signal_handlers_disconnect_by_func (priv->settings,
- external_thumbnailers_disabled_all_changed_cb,
- factory);
- g_signal_handlers_disconnect_by_func (priv->settings,
- external_thumbnailers_disabled_changed_cb,
- factory);
- g_clear_object (&priv->settings);
- }
-
- if (G_OBJECT_CLASS (parent_class)->finalize)
- (* G_OBJECT_CLASS (parent_class)->finalize) (object);
-}
-
-static void
-gnome_desktop_thumbnail_factory_class_init (GnomeDesktopThumbnailFactoryClass *class)
-{
- GObjectClass *gobject_class;
-
- gobject_class = G_OBJECT_CLASS (class);
-
- gobject_class->finalize = gnome_desktop_thumbnail_factory_finalize;
-
- g_type_class_add_private (class, sizeof (GnomeDesktopThumbnailFactoryPrivate));
-}
-
-/**
- * gnome_desktop_thumbnail_factory_new:
- * @size: The thumbnail size to use
- *
- * Creates a new #GnomeDesktopThumbnailFactory.
- *
- * This function must be called on the main thread and is non-blocking.
- *
- * Return value: a new #GnomeDesktopThumbnailFactory
- *
- * Since: 2.2
- **/
-GnomeDesktopThumbnailFactory *
-gnome_desktop_thumbnail_factory_new (GnomeDesktopThumbnailSize size)
-{
- GnomeDesktopThumbnailFactory *factory;
-
- factory = g_object_new (GNOME_DESKTOP_TYPE_THUMBNAIL_FACTORY, NULL);
-
- factory->priv->size = size;
-
- return factory;
-}
-
-static char *
-thumbnail_filename (const char *uri)
-{
- GChecksum *checksum;
- guint8 digest[16];
- gsize digest_len = sizeof (digest);
- char *file;
-
- checksum = g_checksum_new (G_CHECKSUM_MD5);
- g_checksum_update (checksum, (const guchar *) uri, strlen (uri));
-
- g_checksum_get_digest (checksum, digest, &digest_len);
- g_assert (digest_len == 16);
-
- file = g_strconcat (g_checksum_get_string (checksum), ".png", NULL);
-
- g_checksum_free (checksum);
-
- return file;
-}
-
-static char *
-thumbnail_path (const char *uri,
- GnomeDesktopThumbnailSize size)
-{
- char *path, *file;
-
- file = thumbnail_filename (uri);
- path = g_build_filename (g_get_user_cache_dir (),
- "thumbnails",
- size == GNOME_DESKTOP_THUMBNAIL_SIZE_LARGE ? "large" : "normal",
- file,
- NULL);
- g_free (file);
- return path;
-}
-
-static char *
-thumbnail_failed_path (const char *uri)
-{
- char *path, *file;
-
- file = thumbnail_filename (uri);
- /* XXX: appname is only used for failed thumbnails. Is this a mistake? */
- path = g_build_filename (g_get_user_cache_dir (),
- "thumbnails",
- "fail",
- appname,
- file,
- NULL);
- g_free (file);
- return path;
-}
-
-static char *
-validate_thumbnail_path (char *path,
- const char *uri,
- time_t mtime,
- GnomeDesktopThumbnailSize size)
-{
- GdkPixbuf *pixbuf;
-
- pixbuf = gdk_pixbuf_new_from_file (path, NULL);
- if (pixbuf == NULL ||
- !gnome_desktop_thumbnail_is_valid (pixbuf, uri, mtime)) {
- g_free (path);
- return NULL;
- }
-
- g_clear_object (&pixbuf);
-
- return path;
-}
-
-static char *
-lookup_thumbnail_path (const char *uri,
- time_t mtime,
- GnomeDesktopThumbnailSize size)
-{
- char *path = thumbnail_path (uri, size);
- return validate_thumbnail_path (path, uri, mtime, size);
-}
-
-static char *
-lookup_failed_thumbnail_path (const char *uri,
- time_t mtime,
- GnomeDesktopThumbnailSize size)
-{
- char *path = thumbnail_failed_path (uri);
- return validate_thumbnail_path (path, uri, mtime, size);
-}
-
-/**
- * gnome_desktop_thumbnail_factory_lookup:
- * @factory: a #GnomeDesktopThumbnailFactory
- * @uri: the uri of a file
- * @mtime: the mtime of the file
- *
- * Tries to locate an existing thumbnail for the file specified.
- *
- * Usage of this function is threadsafe and does blocking I/O.
- *
- * Return value: The absolute path of the thumbnail, or %NULL if none exist.
- *
- * Since: 2.2
- **/
-char *
-gnome_desktop_thumbnail_factory_lookup (GnomeDesktopThumbnailFactory *factory,
- const char *uri,
- time_t mtime)
-{
- GnomeDesktopThumbnailFactoryPrivate *priv = factory->priv;
-
- g_return_val_if_fail (uri != NULL, NULL);
-
- return lookup_thumbnail_path (uri, mtime, priv->size);
-}
-
-/**
- * gnome_desktop_thumbnail_factory_has_valid_failed_thumbnail:
- * @factory: a #GnomeDesktopThumbnailFactory
- * @uri: the uri of a file
- * @mtime: the mtime of the file
- *
- * Tries to locate an failed thumbnail for the file specified. Writing
- * and looking for failed thumbnails is important to avoid to try to
- * thumbnail e.g. broken images several times.
- *
- * Usage of this function is threadsafe and does blocking I/O.
- *
- * Return value: TRUE if there is a failed thumbnail for the file.
- *
- * Since: 2.2
- **/
-gboolean
-gnome_desktop_thumbnail_factory_has_valid_failed_thumbnail (GnomeDesktopThumbnailFactory *factory,
- const char *uri,
- time_t mtime)
-{
- char *path;
-
- g_return_val_if_fail (uri != NULL, FALSE);
-
- path = lookup_failed_thumbnail_path (uri, mtime, factory->priv->size);
- if (path == NULL)
- return FALSE;
-
- g_free (path);
-
- return TRUE;
-}
-
-/**
- * gnome_desktop_thumbnail_factory_can_thumbnail:
- * @factory: a #GnomeDesktopThumbnailFactory
- * @uri: the uri of a file
- * @mime_type: the mime type of the file
- * @mtime: the mtime of the file
- *
- * Returns TRUE if this GnomeDesktopThumbnailFactory can (at least try) to thumbnail
- * this file. Thumbnails or files with failed thumbnails won't be thumbnailed.
- *
- * Usage of this function is threadsafe and does blocking I/O.
- *
- * Return value: TRUE if the file can be thumbnailed.
- *
- * Since: 2.2
- **/
-gboolean
-gnome_desktop_thumbnail_factory_can_thumbnail (GnomeDesktopThumbnailFactory *factory,
- const char *uri,
- const char *mime_type,
- time_t mtime)
-{
- gboolean have_script = FALSE;
-
- /* Don't thumbnail thumbnails */
- if (uri &&
- strncmp (uri, "file:/", 6) == 0 &&
- strstr (uri, "/thumbnails/") != NULL)
- return FALSE;
-
- if (!mime_type)
- return FALSE;
-
- g_mutex_lock (&factory->priv->lock);
- if (!gnome_desktop_thumbnail_factory_is_disabled (factory, mime_type))
- {
- Thumbnailer *thumb;
-
- thumb = g_hash_table_lookup (factory->priv->mime_types_map, mime_type);
- have_script = (thumb != NULL);
- }
- g_mutex_unlock (&factory->priv->lock);
-
- if (have_script)
- {
- return !gnome_desktop_thumbnail_factory_has_valid_failed_thumbnail (factory,
- uri,
- mtime);
- }
-
- return FALSE;
-}
-
-static GdkPixbuf *
-get_preview_thumbnail (const char *uri,
- int size)
-{
- GdkPixbuf *pixbuf;
- GFile *file;
- GFileInfo *file_info;
- GInputStream *input_stream;
- GObject *object;
-
- g_return_val_if_fail (uri != NULL, NULL);
-
- input_stream = NULL;
-
- file = g_file_new_for_uri (uri);
-
- /* First see if we can get an input stream via preview::icon */
- file_info = g_file_query_info (file,
- G_FILE_ATTRIBUTE_PREVIEW_ICON,
- G_FILE_QUERY_INFO_NONE,
- NULL, /* GCancellable */
- NULL); /* return location for GError */
- g_object_unref (file);
-
- if (file_info == NULL)
- return NULL;
-
- object = g_file_info_get_attribute_object (file_info,
- G_FILE_ATTRIBUTE_PREVIEW_ICON);
- if (object)
- g_object_ref (object);
- g_object_unref (file_info);
-
- if (!object)
- return NULL;
- if (!G_IS_LOADABLE_ICON (object)) {
- g_object_unref (object);
- return NULL;
- }
-
- input_stream = g_loadable_icon_load (G_LOADABLE_ICON (object),
- 0, /* size */
- NULL, /* return location for type */
- NULL, /* GCancellable */
- NULL); /* return location for GError */
- g_object_unref (object);
-
- if (!input_stream)
- return NULL;
-
- pixbuf = gdk_pixbuf_new_from_stream_at_scale (input_stream,
- size, size,
- TRUE, NULL, NULL);
- g_object_unref (input_stream);
-
- 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
- * @uri: the uri of a file
- * @mime_type: the mime type of the file
- *
- * Tries to generate a thumbnail for the specified file. If it succeeds
- * it returns a pixbuf that can be used as a thumbnail.
- *
- * Usage of this function is threadsafe and does blocking I/O.
- *
- * Return value: (transfer full): thumbnail pixbuf if thumbnailing succeeded, %NULL otherwise.
- *
- * Since: 2.2
- **/
-GdkPixbuf *
-gnome_desktop_thumbnail_factory_generate_thumbnail (GnomeDesktopThumbnailFactory *factory,
- const char *uri,
- const char *mime_type)
-{
- GdkPixbuf *pixbuf;
- char *script;
- int size;
-
- g_return_val_if_fail (uri != NULL, NULL);
- g_return_val_if_fail (mime_type != NULL, NULL);
-
- /* Doesn't access any volatile fields in factory, so it's threadsafe */
-
- size = 128;
- if (factory->priv->size == GNOME_DESKTOP_THUMBNAIL_SIZE_LARGE)
- size = 256;
-
- pixbuf = get_preview_thumbnail (uri, size);
- if (pixbuf != NULL)
- return pixbuf;
-
- script = NULL;
- g_mutex_lock (&factory->priv->lock);
- if (!gnome_desktop_thumbnail_factory_is_disabled (factory, mime_type))
- {
- Thumbnailer *thumb;
-
- thumb = g_hash_table_lookup (factory->priv->mime_types_map, mime_type);
- if (thumb)
- script = g_strdup (thumb->command);
- }
- g_mutex_unlock (&factory->priv->lock);
-
- if (script)
- {
- GBytes *data;
- GError *error = NULL;
-
- data = gnome_desktop_thumbnail_script_exec (script, size, uri, &error);
- if (data)
- {
- pixbuf = pixbuf_new_from_bytes (data, &error);
- if (!pixbuf)
- {
- g_debug ("Could not load thumbnail pixbuf: %s", error->message);
- g_error_free (error);
- }
- g_bytes_unref (data);
- }
- else
- {
- g_debug ("Thumbnail script ('%s') failed for '%s': %s",
- script, uri, error ? error->message : "no details");
- g_clear_error (&error);
- }
- }
- else
- {
- g_debug ("Could not find thumbnailer for mime-type '%s'",
- mime_type);
- }
-
- g_free (script);
-
- return pixbuf;
-}
-
-static gboolean
-save_thumbnail (GdkPixbuf *pixbuf,
- char *path,
- const char *uri,
- time_t mtime)
-{
- char *dirname;
- char *tmp_path = NULL;
- int tmp_fd;
- char mtime_str[21];
- gboolean ret = FALSE;
- GError *error = NULL;
- const char *width, *height;
-
- if (pixbuf == NULL)
- return FALSE;
-
- dirname = g_path_get_dirname (path);
-
- if (g_mkdir_with_parents (dirname, 0700) != 0)
- goto out;
-
- tmp_path = g_strconcat (path, ".XXXXXX", NULL);
- tmp_fd = g_mkstemp (tmp_path);
-
- if (tmp_fd == -1)
- goto out;
- close (tmp_fd);
-
- g_snprintf (mtime_str, 21, "%" G_GINT64_FORMAT, (gint64) mtime);
- width = gdk_pixbuf_get_option (pixbuf, "tEXt::Thumb::Image::Width");
- height = gdk_pixbuf_get_option (pixbuf, "tEXt::Thumb::Image::Height");
-
- error = NULL;
- if (width != NULL && height != NULL)
- ret = gdk_pixbuf_save (pixbuf,
- tmp_path,
- "png", &error,
- "tEXt::Thumb::Image::Width", width,
- "tEXt::Thumb::Image::Height", height,
- "tEXt::Thumb::URI", uri,
- "tEXt::Thumb::MTime", mtime_str,
- "tEXt::Software", "GNOME::ThumbnailFactory",
- NULL);
- else
- ret = gdk_pixbuf_save (pixbuf,
- tmp_path,
- "png", &error,
- "tEXt::Thumb::URI", uri,
- "tEXt::Thumb::MTime", mtime_str,
- "tEXt::Software", "GNOME::ThumbnailFactory",
- NULL);
-
- if (!ret)
- goto out;
-
- g_chmod (tmp_path, 0600);
- g_rename (tmp_path, path);
-
- out:
- if (error != NULL)
- {
- g_warning ("Failed to create thumbnail %s: %s", tmp_path, error->message);
- g_error_free (error);
- }
- g_unlink (tmp_path);
- g_free (tmp_path);
- g_free (dirname);
- return ret;
-}
-
-static GdkPixbuf *
-make_failed_thumbnail (void)
-{
- GdkPixbuf *pixbuf;
-
- pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8, 1, 1);
- gdk_pixbuf_fill (pixbuf, 0x00000000);
- return pixbuf;
-}
-
-/**
- * gnome_desktop_thumbnail_factory_save_thumbnail:
- * @factory: a #GnomeDesktopThumbnailFactory
- * @thumbnail: the thumbnail as a pixbuf
- * @uri: the uri of a file
- * @original_mtime: the modification time of the original file
- *
- * Saves @thumbnail at the right place. If the save fails a
- * failed thumbnail is written.
- *
- * Usage of this function is threadsafe and does blocking I/O.
- *
- * Since: 2.2
- **/
-void
-gnome_desktop_thumbnail_factory_save_thumbnail (GnomeDesktopThumbnailFactory *factory,
- GdkPixbuf *thumbnail,
- const char *uri,
- time_t original_mtime)
-{
- char *path;
-
- path = thumbnail_path (uri, factory->priv->size);
- if (!save_thumbnail (thumbnail, path, uri, original_mtime))
- {
- thumbnail = make_failed_thumbnail ();
- g_free (path);
- path = thumbnail_failed_path (uri);
- save_thumbnail (thumbnail, path, uri, original_mtime);
- g_object_unref (thumbnail);
- }
- g_free (path);
-}
-
-/**
- * gnome_desktop_thumbnail_factory_create_failed_thumbnail:
- * @factory: a #GnomeDesktopThumbnailFactory
- * @uri: the uri of a file
- * @mtime: the modification time of the file
- *
- * Creates a failed thumbnail for the file so that we don't try
- * to re-thumbnail the file later.
- *
- * Usage of this function is threadsafe and does blocking I/O.
- *
- * Since: 2.2
- **/
-void
-gnome_desktop_thumbnail_factory_create_failed_thumbnail (GnomeDesktopThumbnailFactory *factory,
- const char *uri,
- time_t mtime)
-{
- char *path;
- GdkPixbuf *pixbuf;
-
- path = thumbnail_failed_path (uri);
- pixbuf = make_failed_thumbnail ();
- save_thumbnail (pixbuf, path, uri, mtime);
- g_free (path);
- g_object_unref (pixbuf);
-}
-
-/**
- * gnome_desktop_thumbnail_path_for_uri:
- * @uri: an uri
- * @size: a thumbnail size
- *
- * Returns the filename that a thumbnail of size @size for @uri would have.
- * This function is threadsafe and does no blocking I/O.
- *
- * Return value: an absolute filename
- *
- * Since: 2.2
- **/
-char *
-gnome_desktop_thumbnail_path_for_uri (const char *uri,
- GnomeDesktopThumbnailSize size)
-{
- return thumbnail_path (uri, size);
-}
-
-/**
- * gnome_desktop_thumbnail_is_valid:
- * @pixbuf: an loaded thumbnail #GdkPixbuf
- * @uri: a uri
- * @mtime: the mtime
- *
- * Returns whether the thumbnail has the correct uri and mtime embedded in the
- * png options. This function is threadsafe and does no blocking I/O.
- *
- * Return value: TRUE if the thumbnail has the right @uri and @mtime
- *
- * Since: 2.2
- **/
-gboolean
-gnome_desktop_thumbnail_is_valid (GdkPixbuf *pixbuf,
- const char *uri,
- time_t mtime)
-{
- const char *thumb_uri, *thumb_mtime_str;
- time_t thumb_mtime;
-
- thumb_uri = gdk_pixbuf_get_option (pixbuf, "tEXt::Thumb::URI");
- if (g_strcmp0 (uri, thumb_uri) != 0)
- return FALSE;
-
- thumb_mtime_str = gdk_pixbuf_get_option (pixbuf, "tEXt::Thumb::MTime");
- if (!thumb_mtime_str)
- return FALSE;
- thumb_mtime = atol (thumb_mtime_str);
- if (mtime != thumb_mtime)
- return FALSE;
-
- return TRUE;
-}
diff --git a/src/gnome-desktop/gnome-desktop-thumbnail.h b/src/gnome-desktop/gnome-desktop-thumbnail.h
deleted file mode 100644
index 186534ff3..000000000
--- a/src/gnome-desktop/gnome-desktop-thumbnail.h
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * gnome-thumbnail.h: Utilities for handling thumbnails
- *
- * Copyright (C) 2002 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.
- *
- * Author: Alexander Larsson <alexl@redhat.com>
- */
-
-#ifndef GNOME_DESKTOP_THUMBNAIL_H
-#define GNOME_DESKTOP_THUMBNAIL_H
-
-#ifndef GNOME_DESKTOP_USE_UNSTABLE_API
-#error GnomeDesktopThumbnail is unstable API. You must define GNOME_DESKTOP_USE_UNSTABLE_API before including gnome-desktop-thumbnail.h
-#endif
-
-#include <glib.h>
-#include <glib-object.h>
-#include <time.h>
-#include <gdk-pixbuf/gdk-pixbuf.h>
-
-G_BEGIN_DECLS
-
-typedef enum {
- GNOME_DESKTOP_THUMBNAIL_SIZE_NORMAL,
- GNOME_DESKTOP_THUMBNAIL_SIZE_LARGE
-} GnomeDesktopThumbnailSize;
-
-#define GNOME_DESKTOP_TYPE_THUMBNAIL_FACTORY (gnome_desktop_thumbnail_factory_get_type ())
-#define GNOME_DESKTOP_THUMBNAIL_FACTORY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GNOME_DESKTOP_TYPE_THUMBNAIL_FACTORY, GnomeDesktopThumbnailFactory))
-#define GNOME_DESKTOP_THUMBNAIL_FACTORY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GNOME_DESKTOP_TYPE_THUMBNAIL_FACTORY, GnomeDesktopThumbnailFactoryClass))
-#define GNOME_DESKTOP_IS_THUMBNAIL_FACTORY(obj) (G_TYPE_INSTANCE_CHECK_TYPE ((obj), GNOME_DESKTOP_TYPE_THUMBNAIL_FACTORY))
-#define GNOME_DESKTOP_IS_THUMBNAIL_FACTORY_CLASS(klass) (G_TYPE_CLASS_CHECK_CLASS_TYPE ((klass), GNOME_DESKTOP_TYPE_THUMBNAIL_FACTORY))
-
-typedef struct _GnomeDesktopThumbnailFactory GnomeDesktopThumbnailFactory;
-typedef struct _GnomeDesktopThumbnailFactoryClass GnomeDesktopThumbnailFactoryClass;
-typedef struct _GnomeDesktopThumbnailFactoryPrivate GnomeDesktopThumbnailFactoryPrivate;
-
-struct _GnomeDesktopThumbnailFactory {
- GObject parent;
-
- GnomeDesktopThumbnailFactoryPrivate *priv;
-};
-
-struct _GnomeDesktopThumbnailFactoryClass {
- GObjectClass parent;
-};
-
-G_DEFINE_AUTOPTR_CLEANUP_FUNC(GnomeDesktopThumbnailFactory, g_object_unref)
-
-GType gnome_desktop_thumbnail_factory_get_type (void);
-GnomeDesktopThumbnailFactory *gnome_desktop_thumbnail_factory_new (GnomeDesktopThumbnailSize size);
-
-char * gnome_desktop_thumbnail_factory_lookup (GnomeDesktopThumbnailFactory *factory,
- const char *uri,
- time_t mtime);
-
-gboolean gnome_desktop_thumbnail_factory_has_valid_failed_thumbnail (GnomeDesktopThumbnailFactory *factory,
- const char *uri,
- time_t mtime);
-gboolean gnome_desktop_thumbnail_factory_can_thumbnail (GnomeDesktopThumbnailFactory *factory,
- const char *uri,
- const char *mime_type,
- time_t mtime);
-GdkPixbuf * gnome_desktop_thumbnail_factory_generate_thumbnail (GnomeDesktopThumbnailFactory *factory,
- const char *uri,
- const char *mime_type);
-void gnome_desktop_thumbnail_factory_save_thumbnail (GnomeDesktopThumbnailFactory *factory,
- GdkPixbuf *thumbnail,
- const char *uri,
- time_t original_mtime);
-void gnome_desktop_thumbnail_factory_create_failed_thumbnail (GnomeDesktopThumbnailFactory *factory,
- const char *uri,
- time_t mtime);
-
-
-/* Thumbnailing utils: */
-gboolean gnome_desktop_thumbnail_is_valid (GdkPixbuf *pixbuf,
- const char *uri,
- time_t mtime);
-char * gnome_desktop_thumbnail_path_for_uri (const char *uri,
- GnomeDesktopThumbnailSize size);
-
-G_END_DECLS
-
-#endif /* GNOME_DESKTOP_THUMBNAIL_H */
diff --git a/src/gnome-desktop/gnome-desktop-update.sh b/src/gnome-desktop/gnome-desktop-update.sh
deleted file mode 100755
index f31724ca8..000000000
--- a/src/gnome-desktop/gnome-desktop-update.sh
+++ /dev/null
@@ -1,45 +0,0 @@
-#!/bin/sh
-#
-# gnome-desktop-update.sh
-#
-# Fetch the latest master gnome-desktop-thumbnail source code from the
-# gnome-desktop project https://gitlab.gnome.org/GNOME/gnome-desktop
-#
-# The Nautilus gnome-desktop thumbnail code directly tracks the gnome-desktop
-# repository. There is typically no need to modify the received files.
-#
-# Usage:
-#
-# Execute the script within the nautilus/src/gnome-desktop directory.
-# For example:
-#
-# $ cd src/gnome-desktop
-# $ ./gnome-desktop-update.sh
-#
-
-URL=https://gitlab.gnome.org/GNOME/gnome-desktop/raw/master/libgnome-desktop/
-FILES=(
- "gnome-desktop-thumbnail.c"
- "gnome-desktop-thumbnail.h"
- "gnome-desktop-thumbnail-script.c"
- "gnome-desktop-thumbnail-script.h"
-)
-r=0
-
-for f in ${FILES[@]}; do
- echo "GET: $URL$f"
- if curl -sfO $URL$f; then
- echo " OK: $f"
- else
- echo "ERR: $f download error."
- r=1
- fi;
-done
-
-if [ $r -eq 0 ]; then
- echo "SUCCESS: All updates completed successfully."
-else
- echo "WARNING: One or more updates encountered an error."
-fi;
-
-exit $r \ No newline at end of file
diff --git a/src/meson.build b/src/meson.build
index 91c0a00c8..86d062161 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -53,10 +53,6 @@ libnautilus_sources = [
'animation/ide-box-theatric.h',
'animation/ide-cairo.c',
'animation/ide-cairo.h',
- 'gnome-desktop/gnome-desktop-thumbnail.c',
- 'gnome-desktop/gnome-desktop-thumbnail.h',
- 'gnome-desktop/gnome-desktop-thumbnail-script.c',
- 'gnome-desktop/gnome-desktop-thumbnail-script.h',
'gtk/nautilusgtkplacesview.c',
'gtk/nautilusgtkplacesviewprivate.h',
'gtk/nautilusgtkplacesviewrow.c',
@@ -277,10 +273,9 @@ nautilus_deps = [
gio_unix,
gmodule,
gnome_autoar,
- gsettings_desktop_schemas,
+ gnome_desktop,
libgd_dep,
nautilus_extension,
- seccomp,
selinux,
tracker_sparql,
xml
diff --git a/src/nautilus-properties-window.c b/src/nautilus-properties-window.c
index 464a131ca..9d9bd1c54 100644
--- a/src/nautilus-properties-window.c
+++ b/src/nautilus-properties-window.c
@@ -34,7 +34,7 @@
#include <sys/stat.h>
#define GNOME_DESKTOP_USE_UNSTABLE_API
-#include "gnome-desktop/gnome-desktop-thumbnail.h"
+#include <libgnome-desktop/gnome-desktop-thumbnail.h>
#include "nautilus-enums.h"
#include "nautilus-error-reporting.h"
diff --git a/src/nautilus-thumbnails.c b/src/nautilus-thumbnails.c
index b90dc0daa..991bfb6f6 100644
--- a/src/nautilus-thumbnails.c
+++ b/src/nautilus-thumbnails.c
@@ -40,7 +40,7 @@
#include <sys/wait.h>
#include <unistd.h>
#include <signal.h>
-#include "gnome-desktop/gnome-desktop-thumbnail.h"
+#include <libgnome-desktop/gnome-desktop-thumbnail.h>
#define DEBUG_FLAG NAUTILUS_DEBUG_THUMBNAILS
#include "nautilus-debug.h"